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(); }