public Map<File, IndexProcessingResults> processIndex(Set<File> replicaDirs, Set<StoreKey> filterSet, int parallelism,
      boolean detectDuplicatesAcrossKeys) {
    if (detectDuplicatesAcrossKeys && parallelism != 1) {
      throw new IllegalArgumentException("Parallelism cannot be > 1 because StoreKeyConverter is not thread safe");
    }
    if (replicaDirs == null || replicaDirs.size() == 0) {
      return Collections.emptyMap();
    }
    long currentTimeMs = time.milliseconds();
    ConcurrentMap<File, IndexProcessingResults> resultsByReplica = new ConcurrentHashMap<>();
    ExecutorService executorService = Executors.newFixedThreadPool(Math.min(parallelism, replicaDirs.size()));
    List<Future<?>> taskFutures = new ArrayList<>(replicaDirs.size());
    for (File replicaDir : replicaDirs) {
      Future<?> taskFuture = executorService.submit(() -> {
        logger.info("Processing segment files for replica {} ", replicaDir);
        IndexProcessingResults results = null;
        try {
          results = processIndex(replicaDir, filterSet, currentTimeMs, detectDuplicatesAcrossKeys);
        } catch (Throwable e) {
          results = new IndexProcessingResults(e);
        } finally {
          resultsByReplica.put(replicaDir, results);
        }
      });
      taskFutures.add(taskFuture);
    }
    for (Future<?> taskFuture : taskFutures) {
      try {
        taskFuture.get();
      } catch (Exception e) {
        throw new IllegalStateException("Future encountered error while waiting", e);
      }
    }
    return resultsByReplica;
  }
Returns {@link IndexProcessingResults} for each replicaDir in {@code replicaDirs}
@param replicaDirs the directories to examine
@param filterSet the filter set of keys to examine. Can be {@code null}
@param parallelism the desired parallelism. The minimum of this and the size of {@code replicaDirs} is the actual
                   chosen parallelism.
@param detectDuplicatesAcrossKeys if {@code true}, uses the {@link StoreKeyConverter} to detect duplicates across
                                  keys. If set to {@code true}, parallelism has to be 1.
@return @link IndexProcessingResults} for each replicaDir in {@code replicaDirs}
ambry-tools/src/main/java/com/github/ambry/store/DumpIndexTool.java