mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Fix a bug in HashSegmentIteration.forEachTierWhile()
This commit is contained in:
@@ -655,4 +655,28 @@ public abstract class SegmentStages implements SegmentLock, LocksInterface {
|
||||
nextPosToSearchFrom = 0L;
|
||||
nextPosToSearchFrom(nextPosToSearchFrom);
|
||||
}
|
||||
|
||||
public void verifyTierCountersAreaData() {
|
||||
goToFirstTier();
|
||||
while (true) {
|
||||
int tierSegmentIndex = TierCountersArea.segmentIndex(tierCountersAreaAddr());
|
||||
if (tierSegmentIndex != segmentIndex) {
|
||||
throw new AssertionError("segmentIndex: " + segmentIndex +
|
||||
", tier: " + tier + ", tierIndex: " + tierIndex + ", tierBaseAddr: " +
|
||||
tierBaseAddr + " reports it belongs to segmentIndex " + tierSegmentIndex);
|
||||
}
|
||||
if (hasNextTier()) {
|
||||
long currentTierIndex = this.tierIndex;
|
||||
nextTier();
|
||||
if (prevTierIndex() != currentTierIndex) {
|
||||
throw new AssertionError("segmentIndex: " + segmentIndex +
|
||||
", tier: " + tier + ", tierIndex: " + tierIndex + ", tierBaseAddr: " +
|
||||
tierBaseAddr + " reports the previous tierIndex is " + prevTierIndex() +
|
||||
" while actually it is " + currentTierIndex);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,12 +103,14 @@ public abstract class HashSegmentIteration<K, E extends HashEntry<K>>
|
||||
}
|
||||
hlp.initHashLookupPos(startPos);
|
||||
long currentHashLookupPos;
|
||||
int steps = 0;
|
||||
do {
|
||||
// Step from hlp.hashLookupPos, not currentHashLookupPos (with additional initialization
|
||||
// of this local variable to startPos outside the loop), because if e.remove() is
|
||||
// called in the `action`, hlp.hashLookupPos is stepped back in doRemove(), and
|
||||
// currentHashLookupPos become invalid
|
||||
currentHashLookupPos = hashLookup.step(hlp.hashLookupPos);
|
||||
steps++;
|
||||
hlp.setHashLookupPos(currentHashLookupPos);
|
||||
long entry = hashLookup.readEntry(currentTierBaseAddr, currentHashLookupPos);
|
||||
initHashLookupEntry(entry);
|
||||
@@ -135,12 +137,17 @@ public abstract class HashSegmentIteration<K, E extends HashEntry<K>>
|
||||
// slot in _current_ tier's hash lookup is shift deleted, see
|
||||
// relocation()
|
||||
currentHashLookupPos = hashLookup.stepBack(currentHashLookupPos);
|
||||
steps--;
|
||||
hlp.initHashLookupPos(currentHashLookupPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (currentHashLookupPos != startPos);
|
||||
// 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 currentHashLookupPos
|
||||
// becomes equal to start pos without making the whole loop, but only visiting a single
|
||||
// entry
|
||||
} while (currentHashLookupPos != startPos || steps == 0);
|
||||
return interrupted ? ~size : size;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
@@ -464,4 +466,16 @@ public class VanillaChronicleMap<K, V, R>
|
||||
return q.defaultReturnValue().returnValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void verifyTierCountersAreaData() {
|
||||
for (int i = 0; i < actualSegments; i++) {
|
||||
try (MapSegmentContext<K, V, ?> c = segmentContext(i)) {
|
||||
Method verifyTierCountersAreaData =
|
||||
c.getClass().getMethod("verifyTierCountersAreaData");
|
||||
verifyTierCountersAreaData.invoke(c);
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user