private List<IndexEntry> getValidIndexEntries(IndexSegment indexSegment, List<IndexEntry> allIndexEntries)
        throws StoreException {
      // Assumed preference order from IndexSegment (current impl)
      // (Legend: entry/entries in segment -> output from IndexSegment#getIndexEntriesSince())
      // PUT entry only -> PUT entry
      // TTL update entry only -> TTL update entry
      // DELETE entry only -> DELETE entry
      // PUT + DELETE -> DELETE
      // TTL update + DELETE -> DELETE
      // PUT + TTL update -> PUT (the one relevant to this comment)
      // PUT + TTL update + DELETE -> DELETE
      long deleteReferenceTime = compactionLog.getCompactionDetails().getReferenceTimeMs();
      List<IndexEntry> validEntries = new ArrayList<>();
      for (IndexEntry indexEntry : allIndexEntries) {
        IndexValue value = indexEntry.getValue();
        if (value.isDelete()) {
          IndexValue putValue = getPutValueFromSrc(indexEntry.getKey(), value, indexSegment);
          if (putValue != null) {
            // In PersistentIndex.markAsDeleted(), the expiry time of the put/ttl update value is copied into the
            // delete value. So it is safe to check for isExpired() on the delete value.
            if (value.getOperationTimeInMs() < deleteReferenceTime || srcIndex.isExpired(value)) {
              // still have to evaluate whether the TTL update has to be copied
              NavigableSet<IndexValue> values = indexSegment.find(indexEntry.getKey());
              IndexValue secondVal = values.lower(values.last());
              if (secondVal != null && secondVal.isFlagSet(IndexValue.Flags.Ttl_Update_Index) && isTtlUpdateEntryValid(
                  indexEntry.getKey(), indexSegment.getStartOffset())) {
                validEntries.add(new IndexEntry(indexEntry.getKey(), secondVal));
              }
              // DELETE entry. Always valid.
              validEntries.add(indexEntry);
            } else {
              // if this delete cannot be counted and there is a corresponding unexpired PUT/TTL update entry in the same
              // index segment, we will need to add it.
              addAllEntriesForKeyInSegment(validEntries, indexSegment, indexEntry);
            }
          } else {
            // DELETE entry without corresponding PUT (may be left by previous compaction). Check if this delete
            // tombstone is removable.
            if (config.storeCompactionPurgeDeleteTombstone && isDeleteTombstoneRemovable(indexEntry, indexSegment)) {
              logger.debug(
                  "Delete tombstone of {} (with expiration time {} ms) is removable and won't be copied to target log segment",
                  indexEntry.getKey(), value.getExpiresAtMs());
            } else {
              validEntries.add(indexEntry);
            }
          }
        } else if (value.isTtlUpdate()) {
          // if IndexSegment::getIndexEntriesSince() returns a TTL update entry, it is because it is the ONLY entry i.e.
          // no PUT or DELETE in the same index segment.
          if (isTtlUpdateEntryValid(indexEntry.getKey(), indexSegment.getStartOffset())) {
            validEntries.add(indexEntry);
          }
        } else {
          IndexValue valueFromIdx = srcIndex.findKey(indexEntry.getKey());
          // Doesn't matter whether we get the PUT or DELETE entry for the expiry test
          if (!srcIndex.isExpired(valueFromIdx)) {
            // unexpired PUT entry.
            if (!hasDeleteEntryOutOfRetention(indexEntry.getKey(), indexSegment.getStartOffset(),
                deleteReferenceTime)) {
              // PUT entry that has not expired and is not considered deleted.
              // Add all values in this index segment (to account for the presence of TTL updates)
              addAllEntriesForKeyInSegment(validEntries, indexSegment, indexEntry);
            } else {
              logger.trace("{} in index segment with start offset {} in {} is not valid because it is a deleted PUT",
                  indexEntry, indexSegment.getStartOffset(), storeId);
            }
          } else {
            logger.trace("{} in index segment with start offset {} in {} is not valid because it is an expired PUT",
                indexEntry, indexSegment.getStartOffset(), storeId);
          }
        }
      }
      return validEntries;
    }
Gets all the valid index entries in the given list of index entries.
@param indexSegment the {@link IndexSegment} that {@code allIndexEntries} are from.
@param allIndexEntries the list of {@link IndexEntry} instances from which the valid entries have to be chosen.
                       There should be only one entry per key where a DELETE is preferred over all other entries
                       and PUT is preferred over a TTL update entry
@return the list of valid entries generated from {@code allIndexEntries}. May contain entries not in
{@code allIndexEntries}.
@throws StoreException if {@link BlobReadOptions} could not be obtained from the store for deleted blobs.
ambry-store/src/main/java/com/github/ambry/store/BlobStoreCompactor.java