public static void main(String args[]) throws Exception {
    final AtomicInteger exitCode = new AtomicInteger(0);
    VerifiableProperties verifiableProperties = ToolUtils.getVerifiableProperties(args);
    DumpIndexToolConfig config = new DumpIndexToolConfig(verifiableProperties);
    ClusterMapConfig clusterMapConfig = new ClusterMapConfig(verifiableProperties);
    try (ClusterMap clusterMap = ((ClusterAgentsFactory) Utils.getObj(clusterMapConfig.clusterMapClusterAgentsFactory,
        clusterMapConfig, config.hardwareLayoutFilePath, config.partitionLayoutFilePath)).getClusterMap()) {
      StoreConfig storeConfig = new StoreConfig(verifiableProperties);
      // this tool supports only blob IDs. It can become generic if StoreKeyFactory provides a deserFromString method.
      BlobIdFactory blobIdFactory = new BlobIdFactory(clusterMap);
      StoreToolsMetrics metrics = new StoreToolsMetrics(clusterMap.getMetricRegistry());
      StoreMetrics storeMetrics = new StoreMetrics("DumpIndexTool", clusterMap.getMetricRegistry());
      ServerConfig serverConfig = new ServerConfig(verifiableProperties);
      Time time = SystemTime.getInstance();
      Throttler throttler = new Throttler(config.indexEntriesToProcessPerSec, 1000, true, time);
      StoreKeyConverterFactory storeKeyConverterFactory =
          Utils.getObj(serverConfig.serverStoreKeyConverterFactory, verifiableProperties,
              clusterMap.getMetricRegistry());
      DumpIndexTool dumpIndexTool =
          new DumpIndexTool(blobIdFactory, storeConfig, time, metrics, storeMetrics, throttler,
              storeKeyConverterFactory.getStoreKeyConverter());
      Set<StoreKey> filterKeySet = new HashSet<>();
      for (String key : config.filterSet) {
        filterKeySet.add(new BlobId(key, clusterMap));
      }
      switch (config.typeOfOperation) {
        case DumpIndex:
          dumpIndex(dumpIndexTool, config.pathOfInput, filterKeySet);
          break;
        case DumpIndexSegment:
          dumpIndexSegment(dumpIndexTool, config.pathOfInput, filterKeySet);
          break;
        case VerifyIndex:
          IndexProcessingResults results =
              dumpIndexTool.processIndex(config.pathOfInput, filterKeySet, time.milliseconds(),
                  config.detectDuplicatesAcrossKeys);
          exitCode.set(reportVerificationResults(config.pathOfInput, results, config.failIfCraftedIdsPresent));
          break;
        case VerifyDataNode:
          DataNodeId dataNodeId = clusterMap.getDataNodeId(config.hostname, config.port);
          if (dataNodeId == null) {
            logger.error("No data node corresponding to {}:{}", config.hostname, config.port);
          } else {
            Set<File> replicaDirs = clusterMap.getReplicaIds(dataNodeId)
                .stream()
                .map(replicaId -> new File(replicaId.getMountPath()))
                .collect(Collectors.toSet());
            Map<File, IndexProcessingResults> resultsByReplica =
                dumpIndexTool.processIndex(replicaDirs, filterKeySet, config.parallelism,
                    config.detectDuplicatesAcrossKeys);
            replicaDirs.removeAll(resultsByReplica.keySet());
            if (replicaDirs.size() != 0) {
              logger.error("Results obtained missing {}", replicaDirs);
              exitCode.set(5);
            } else {
              resultsByReplica.forEach((replicaDir, result) -> exitCode.set(Math.max(exitCode.get(),
                  reportVerificationResults(replicaDir, result, config.failIfCraftedIdsPresent))));
            }
          }
          break;
        default:
          throw new IllegalArgumentException("Unrecognized operation: " + config.typeOfOperation);
      }
    }
    System.exit(exitCode.get());
  }
Constructs the configs associated with the tool.
@param verifiableProperties the props to use to load the config.
ambry-tools/src/main/java/com/github/ambry/store/DumpIndexTool.java