boolean hardDelete() throws StoreException {
    if (index.getCurrentEndOffset().compareTo(index.getStartOffset()) > 0) {
      final Timer.Context context = metrics.hardDeleteTime.time();
      try {
        FindInfo info =
            index.findDeletedEntriesSince(startToken, scanSizeInBytes, time.seconds() - messageRetentionSeconds);
        endToken = info.getFindToken();
        logger.trace("New range for hard deletes : startToken {}, endToken {} for {}", startToken, info.getFindToken(),
            dataDir);
        if (!endToken.equals(startToken)) {
          if (!info.getMessageEntries().isEmpty()) {
            if (injectedBeforeHardDeleteSupplier != null) {
              injectedBeforeHardDeleteSupplier.get();
            }
            performHardDeletes(info.getMessageEntries());
          }
          startToken = endToken;
          return true;
        }
      } catch (StoreException e) {
        if (e.getErrorCode() != StoreErrorCodes.StoreShuttingDown) {
          metrics.hardDeleteExceptionsCount.inc();
        }
        throw e;
      } finally {
        context.stop();
      }
    }
    return false;
  }
Finds deleted entries from the index, persists tokens and calls performHardDelete to delete the corresponding put
records in the log.
Note: At this time, expired blobs are not hard deleted.

Sp is the token till which log is persisted and is therefore safe to be used as the start point during recovery.
(S, E] represents the range of elements being hard deleted at any given time.

The algorithm is as follows:
1. Start at the current token S.
2. {E, entries} = findDeletedEntriesSince(S).
3. Persist {Sp, E} and at least all the entries in the range (Sp, E] to help with recovery if we crash.
4. perform hard deletes of entries in this range.
5. set S = E
6. Index Persistor runs in the background and
   a) saves Sf = S
   b) flushes log (so everything up to Sf is surely flushed in the log)
   c) sets Sp = Sf

The guarantee provided is that for any persisted token pair (Sp, E):
   - all the hard deletes till point Sp have been flushed in the log; and
   - all ongoing hard deletes and unflushed hard deletes are somewhere between Sp and E, so during recovery this
   is the range to be recovered.

@return true if the token moved forward, false otherwise.
ambry-store/src/main/java/com/github/ambry/store/HardDeleter.java