public FlushResult tryFlushIfNeeded(final @NotNull IndexConfiguration indexes,
                                          final @NotNull /*InOut*/ IntRef contentionQuota,
                                          final long flushingPeriodMs) {
        if (System.currentTimeMillis() - lastFlushedMs < flushingPeriodMs) {
          //no need for another flush yet:
          return FlushResult.NOTHING_TO_FLUSH_NOW;
        }
        final UpdatableIndex<?, ?, FileContent, ?> index = indexes.getIndex(indexId);
        if (index == null) {
          //did nothing -> spent no quota:
          return FlushResult.NOTHING_TO_FLUSH_NOW;
        }

        int unspentContentionQuota = contentionQuota.get();
        final ReadWriteLock indexProtectingLock = index.getLock();
        final Lock indexReadLock = indexProtectingLock.readLock();

        final boolean lockSucceeded = indexReadLock.tryLock();
        if (lockSucceeded) {
          try {
            try {
              index.flush();
              lastFlushedMs = System.currentTimeMillis();
            }
            catch (Throwable e) {
              requestRebuild(indexId, e);
            }

            unspentContentionQuota -= threadsCompetingForLock(indexProtectingLock);
            contentionQuota.set(unspentContentionQuota);

            return FlushResult.FLUSHED_ALL;
          }
          finally {
            indexReadLock.unlock();
          }
        }

        //+1 because of the thread currently holding lock (causing .tryLock to fail)
        final int competingThreads = threadsCompetingForLock(indexProtectingLock) + 1;
        unspentContentionQuota -= competingThreads;

        contentionQuota.set(unspentContentionQuota);
        return FlushResult.HAS_MORE_TO_FLUSH;
      }
public FlushResult tryFlushIfNeeded(final @NotNull IndexConfiguration indexes,
                                          final @NotNull /*InOut*/ IntRef contentionQuota,
                                          final long flushingPeriodMs)