private void setupState() throws IOException, StoreException {
    if (remoteTokenTracker != null) {
      // Fresh ignoredOfflinePeers set
      ignoredOfflinePeers.clear();
      for (Map.Entry<String, Pair<Long, FindToken>> entry : remoteTokenTracker.getPeerReplicaAndToken().entrySet()) {
        Pair<Long, FindToken> pair = entry.getValue();
        // Ignore this peer if the last active replication's timestamp of this peer is longer than the pre-configured days.
        if (config.storeCompactionIgnorePeersUnavailableForDays != 0
            && pair.getFirst() + TimeUnit.DAYS.toMillis(config.storeCompactionIgnorePeersUnavailableForDays)
            < time.milliseconds()) {
          ignoredOfflinePeers.add(entry.getKey());
          logger.info("Store {}: peer {}'s last active time is {}, ignore this peer from checking delete tombstones",
              dataDir, entry.getKey(), pair.getFirst());
        }
      }
    }
    CompactionDetails details = compactionLog.getCompactionDetails();
    long highestGeneration = 0;
    for (LogSegmentName segmentName : details.getLogSegmentsUnderCompaction()) {
      highestGeneration = Math.max(highestGeneration, segmentName.getGeneration());
    }
    logger.debug("Generation of target segments will be {} for {} in {}", highestGeneration + 1, details, storeId);
    List<Pair<LogSegmentName, String>> targetSegmentNamesAndFilenames = new ArrayList<>();
    List<LogSegment> existingTargetLogSegments = new ArrayList<>();
    for (LogSegmentName segmentName : details.getLogSegmentsUnderCompaction()) {
      long pos = segmentName.getPosition();
      LogSegmentName targetSegmentName = LogSegmentName.fromPositionAndGeneration(pos, highestGeneration + 1);
      String targetSegmentFileName = targetSegmentName.toFilename() + TEMP_LOG_SEGMENT_NAME_SUFFIX;
      File targetSegmentFile = new File(dataDir, targetSegmentFileName);
      if (targetSegmentFile.exists()) {
        existingTargetLogSegments.add(new LogSegment(targetSegmentName, targetSegmentFile, config, tgtMetrics));
      } else {
        targetSegmentNamesAndFilenames.add(new Pair<>(targetSegmentName, targetSegmentFileName));
      }
    }
    // TODO: available swap space count should be obtained from DiskManager. For now, assumed to be 1.
    long targetLogTotalCapacity = srcLog.getSegmentCapacity();
    logger.debug("Target log capacity is {} for {}. Existing log segments are {}. Future names and files are {}",
        targetLogTotalCapacity, storeId, existingTargetLogSegments, targetSegmentNamesAndFilenames);
    tgtLog = new Log(dataDir.getAbsolutePath(), targetLogTotalCapacity, diskSpaceAllocator, config, tgtMetrics, true,
        existingTargetLogSegments, targetSegmentNamesAndFilenames.iterator(), diskMetrics);
    Journal journal = new Journal(dataDir.getAbsolutePath(), 2 * config.storeIndexMaxNumberOfInmemElements,
        config.storeMaxNumberOfEntriesToReturnFromJournal);
    tgtIndex =
        new PersistentIndex(dataDir.getAbsolutePath(), storeId, null, tgtLog, config, storeKeyFactory, null, null,
            diskIOScheduler, tgtMetrics, journal, time, sessionId, incarnationId,
            TARGET_INDEX_CLEAN_SHUTDOWN_FILE_NAME);
    if (srcIndex.hardDeleter != null && !srcIndex.hardDeleter.isPaused()) {
      logger.debug("Pausing hard delete for {}", storeId);
      srcIndex.hardDeleter.pause();
    }
  }
Sets up the state required for copying data by populating all the data structures, creating a log and index that
wraps the swap spaces and pausing hard delete in the application log.
@throws IOException if logs and indexes could not be set up.
@throws StoreException if there were exceptions reading to writing to store components.
ambry-store/src/main/java/com/github/ambry/store/BlobStoreCompactor.java