@NotNull
  IntSet getSuitableKeyHashes(@NotNull IdFilter idFilter) throws StorageException {
    try {
      doForce();

      Int2ObjectMap<IntSet> hash2inputIds = new Int2ObjectOpenHashMap<>(1000);
      AtomicInteger uselessRecords = new AtomicInteger();

      withLock(() -> {
        ProgressManager.checkCanceled();

        myKeyHashToVirtualFileMapping.processAll((offset, key) -> {
          ProgressManager.checkCanceled();
          int inputId = key[1];
          int absInputId = Math.abs(inputId);
          if (!idFilter.containsFileId(absInputId)) return true;
          int keyHash = key[0];
          if (inputId > 0) {
            if (!hash2inputIds.computeIfAbsent(keyHash, __ -> new IntOpenHashSet()).add(inputId)) {
              uselessRecords.incrementAndGet();
            }
          }
          else {
            IntSet inputIds = hash2inputIds.get(keyHash);
            if (inputIds != null) {
              inputIds.remove(absInputId);
              if (inputIds.isEmpty()) {
                hash2inputIds.remove(keyHash);
              }
            }
            uselessRecords.incrementAndGet();
          }
          return true;
        });
      }, true);

      if (uselessRecords.get() >= hash2inputIds.size()) {
        setRequiresCompaction();
      }

      return hash2inputIds.keySet();
    }
    catch (IOException e) {
      throw new StorageException(e);
    }
  }
@NotNull
  IntSet getSuitableKeyHashes(@NotNull IdFilter idFilter)