KAFKA-15271: Historicalterator can exposes elements that are too new (#14125)

A HistoricalIterator at epoch N is supposed to only reveal elements at epoch N or earlier. However,
due to a bug, we sometimes will reveal elements which are at a newer epoch than N. The bug does
not affect elements that are in the latest epoch (aka topTier). It only affects elements that are
newer than N, but which do not persist until the latest epoch.  This PR fixes the bug and adds a
unit test for this case.

Reviewers: David Arthur <mumrah@gmail.com>
This commit is contained in:
Colin Patrick McCabe 2023-08-08 16:36:59 -07:00 committed by GitHub
parent e0727063f7
commit 9bc4a2d4d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 2 deletions

View File

@ -261,8 +261,10 @@ class SnapshottableHashTable<T extends SnapshottableHashTable.ElementWithStartEp
int tierSlot = slot >>> shift;
BaseHashTable.unpackSlot(temp, deltaTable.baseElements(), tierSlot);
for (T object : temp) {
if (BaseHashTable.findSlot(object, topTier.length) == slot) {
ready.add(object);
if (object.startEpoch() <= snapshot.epoch()) {
if (BaseHashTable.findSlot(object, topTier.length) == slot) {
ready.add(object);
}
}
}
temp.clear();

View File

@ -275,6 +275,21 @@ public class SnapshottableHashTableTest {
assertIteratorYields(table.snapshottableIterator(Long.MAX_VALUE));
}
@Test
public void testIteratorAtOlderEpoch() {
SnapshotRegistry registry = new SnapshotRegistry(new LogContext());
SnapshottableHashTable<TestElement> table =
new SnapshottableHashTable<>(registry, 4);
assertNull(table.snapshottableAddOrReplace(E_3B));
registry.getOrCreateSnapshot(0);
assertNull(table.snapshottableAddOrReplace(E_1A));
registry.getOrCreateSnapshot(1);
assertEquals(E_1A, table.snapshottableAddOrReplace(E_1B));
registry.getOrCreateSnapshot(2);
assertEquals(E_1B, table.snapshottableRemove(E_1B));
assertIteratorYields(table.snapshottableIterator(1), E_3B, E_1A);
}
/**
* Assert that the given iterator contains the given elements, in any order.
* We compare using reference equality here, rather than object equality.