private CostBenefitInfo getMiddleRangeToCompact(NavigableMap<LogSegmentName, Long> validDataPerLogSegments,
      long segmentCapacity, long segmentHeaderSize, long maxBlobSize, BlobStoreStats blobStoreStats) {
    Map.Entry<LogSegmentName, Long> firstEntry = validDataPerLogSegments.firstEntry();
    Map.Entry<LogSegmentName, Long> lastEntry = validDataPerLogSegments.lastEntry();

    String storeId = blobStoreStats.getStoreId();
    // when boots up, give it a chance to try the "middle range compaction"
    if (!blobToLastMiddleRangeCompaction.containsKey(storeId)) {
      // stagger the initial run cross 24 hours
      long staggerTime =
          random.nextInt(24 * 60 * 60 * 1000) % storeConfig.storeStatsBasedMiddleRangeCompactionIntervalInMs;
      blobToLastMiddleRangeCompaction.put(storeId,
          time.milliseconds() - storeConfig.storeStatsBasedMiddleRangeCompactionIntervalInMs + staggerTime);
    }

    if (time.milliseconds() - blobToLastMiddleRangeCompaction.get(storeId)
        >= storeConfig.storeStatsBasedMiddleRangeCompactionIntervalInMs) {
      // find the first log segment has valid data percentage <= the percentage threshold
      while (firstEntry != null) {
        if (firstEntry.getValue() / (segmentCapacity * 1.0)
            <= storeConfig.storeMaxLogSegmentValidDataPercentageToQualifyCompaction) {
          break;
        }
        firstEntry = validDataPerLogSegments.higherEntry(firstEntry.getKey());
      }
      if (firstEntry != null) {
        // find the last log segment has valid data percentage <= the percentage threshold
        while (lastEntry != null && firstEntry.getKey().compareTo(lastEntry.getKey()) < 0) {
          if (lastEntry.getValue() / (segmentCapacity * 1.0)
              <= storeConfig.storeMaxLogSegmentValidDataPercentageToQualifyCompaction) {
            break;
          }
          lastEntry = validDataPerLogSegments.lowerEntry(lastEntry.getKey());
        }
        if (lastEntry != null && firstEntry.getKey().compareTo(lastEntry.getKey()) < 0) {
          CostBenefitInfo costBenefitInfo =
              getCostBenefitInfo(firstEntry.getKey(), lastEntry.getKey(), validDataPerLogSegments, segmentCapacity,
                  segmentHeaderSize, maxBlobSize, true);
          if (costBenefitInfo.getBenefit() > 1) {
            logger.info("[CAPACITY] Merging middle log segments which are qualified for compaction {} ",
                costBenefitInfo);
            blobToLastMiddleRangeCompaction.put(storeId, time.milliseconds());
            return costBenefitInfo;
          }
        }
      }
      logger.info("[CAPACITY] Merging middle log segments, no qualified middle range. ");
    }

    return null;
  }
Finds middle range to compact.
The first log segment and the last segment have to have less valid data than the configured threshold.
@param validDataPerLogSegments the valid data size for each log segment in the form of a {@link NavigableMap}
@param segmentCapacity Segment capacity of one {@link LogSegment}
@param segmentHeaderSize Segment header size of a {@link LogSegment}
@param maxBlobSize The max blob size
@param blobStoreStats the {@link BlobStoreStats}
@return the {@link CostBenefitInfo} for the best candidate to compact. {@code null} if there isn't any.
ambry-store/src/main/java/com/github/ambry/store/StatsBasedCompactionPolicy.java