private void recoverTierEntriesCounter(long entries) {
   if (s.tierEntries() != entries) {
     lh.LOG.error(
         "Wrong number of entries counter for tier with index {}, " + "stored: {}, should be: {}",
         s.tierIndex,
         s.tierEntries(),
         entries);
     s.tierEntries(entries);
   }
 }
 private void recoverLowestPossibleFreeChunkTiered() {
   long lowestFreeChunk = s.freeList.nextClearBit(0);
   if (lowestFreeChunk == -1) lowestFreeChunk = mh.m().actualChunksPerSegmentTier;
   if (s.lowestPossiblyFreeChunk() != lowestFreeChunk) {
     lh.LOG.error(
         "wrong lowest free chunk for tier with index {}, " + "stored: {}, should be: {}",
         s.tierIndex,
         s.lowestPossiblyFreeChunk(),
         lowestFreeChunk);
     s.lowestPossiblyFreeChunk(lowestFreeChunk);
   }
 }
  public void removeDuplicatesInSegment() {
    long startHlPos = 0L;
    VanillaChronicleMap<?, ?, ?> m = mh.m();
    CompactOffHeapLinearHashTable hashLookup = m.hashLookup;
    long currentTierBaseAddr = s.tierBaseAddr;
    while (!hashLookup.empty(hashLookup.readEntry(currentTierBaseAddr, startHlPos))) {
      startHlPos = hashLookup.step(startHlPos);
    }
    long hlPos = startHlPos;
    int steps = 0;
    long entries = 0;
    tierIteration:
    do {
      hlPos = hashLookup.step(hlPos);
      steps++;
      long entry = hashLookup.readEntry(currentTierBaseAddr, hlPos);
      if (!hashLookup.empty(entry)) {
        e.readExistingEntry(hashLookup.value(entry));
        Data key = (Data) e.key();
        try (ExternalMapQueryContext<?, ?, ?> c = m.queryContext(key)) {
          MapEntry<?, ?> entry2 = c.entry();
          Data<?> key2 = ((MapEntry) c).key();
          if (key2.bytes().address(key2.offset()) != key.bytes().address(key.offset())) {
            lh.LOG.error(
                "entries with duplicate key {} in segment {}: "
                    + "with values {} and {}, removing the latter",
                key,
                c.segmentIndex(),
                entry2 != null ? ((MapEntry) c).value() : "<deleted>",
                !e.entryDeleted() ? e.value() : "<deleted>");
            if (hashLookup.remove(currentTierBaseAddr, hlPos) != hlPos) {
              hlPos = hashLookup.stepBack(hlPos);
              steps--;
            }
            continue tierIteration;
          }
        }
        entries++;
      }
      // the `steps == 0` condition and this variable updates in the loop fix the bug, when
      // shift deletion occurs on the first entry of the tier, and the hlPos
      // becomes equal to start pos without making the whole loop, but only visiting a single
      // entry
    } while (hlPos != startHlPos || steps == 0);

    recoverTierEntriesCounter(entries);
    recoverLowestPossibleFreeChunkTiered();
  }