use of org.neo4j.internal.counts.GBPTreeGenericCountsStore.Rebuilder in project neo4j by neo4j.
the class GBPTreeGenericCountsStoreTest method shouldDeleteAndMarkForRebuildOnCorruptStore.
@Test
void shouldDeleteAndMarkForRebuildOnCorruptStore() throws Exception {
// given
try (CountUpdater updater = countsStore.updater(BASE_TX_ID + 1, NULL)) {
updater.increment(nodeKey(LABEL_ID_1), 9);
}
closeCountsStore();
try (StoreChannel channel = fs.open(countsStoreFile(), Set.of(StandardOpenOption.WRITE))) {
ByteBuffer buffer = ByteBuffer.wrap(new byte[8192]);
for (int i = 0; buffer.hasRemaining(); i++) {
buffer.put((byte) i);
}
buffer.flip();
channel.writeAll(buffer, 0);
}
// when
Rebuilder countsBuilder = mock(Rebuilder.class);
when(countsBuilder.lastCommittedTxId()).thenReturn(BASE_TX_ID);
doAnswer(invocationOnMock -> {
CountUpdater updater = invocationOnMock.getArgument(0, CountUpdater.class);
updater.increment(nodeKey(LABEL_ID_1), 3);
return null;
}).when(countsBuilder).rebuild(any(), any(), any());
openCountsStore(countsBuilder);
// then rebuild store instead of throwing exception
verify(countsBuilder).rebuild(any(), any(), any());
assertEquals(3, countsStore.read(nodeKey(LABEL_ID_1), NULL));
}
use of org.neo4j.internal.counts.GBPTreeGenericCountsStore.Rebuilder in project neo4j by neo4j.
the class GBPTreeGenericCountsStoreTest method shouldRebuildOnMismatchingLastCommittedTxId.
@Test
void shouldRebuildOnMismatchingLastCommittedTxId() throws IOException {
// given some pre-state
long countsStoreTxId = BASE_TX_ID + 1;
try (CountUpdater updater = countsStore.updater(countsStoreTxId, NULL)) {
updater.increment(nodeKey(1), 1);
}
// when
countsStore.checkpoint(NULL);
closeCountsStore();
MutableBoolean rebuildTriggered = new MutableBoolean();
openCountsStore(new Rebuilder() {
@Override
public long lastCommittedTxId() {
return countsStoreTxId + 1;
}
@Override
public void rebuild(CountUpdater updater, CursorContext cursorContext, MemoryTracker memoryTracker) {
rebuildTriggered.setTrue();
}
});
// then
assertThat(rebuildTriggered.booleanValue()).isTrue();
}
use of org.neo4j.internal.counts.GBPTreeGenericCountsStore.Rebuilder in project neo4j by neo4j.
the class GBPTreeGenericCountsStoreTest method shouldNotRebuildOnMismatchingLastCommittedTxIdButMatchingAfterRecovery.
@Test
void shouldNotRebuildOnMismatchingLastCommittedTxIdButMatchingAfterRecovery() throws IOException {
// given some pre-state
long countsStoreTxId = BASE_TX_ID + 1;
CountsKey key = nodeKey(1);
try (CountUpdater updater = countsStore.updater(countsStoreTxId, NULL)) {
updater.increment(key, 1);
}
// leaving a gap intentionally
try (CountUpdater updater = countsStore.updater(countsStoreTxId + 2, NULL)) {
updater.increment(key, 3);
}
countsStore.checkpoint(NULL);
// when
closeCountsStore();
MutableBoolean rebuildTriggered = new MutableBoolean();
instantiateCountsStore(new Rebuilder() {
@Override
public long lastCommittedTxId() {
return countsStoreTxId + 2;
}
@Override
public void rebuild(CountUpdater updater, CursorContext cursorContext, MemoryTracker memoryTracker) {
rebuildTriggered.setTrue();
}
}, writable(), NO_MONITOR);
// and do recovery
try (CountUpdater updater = countsStore.updater(countsStoreTxId + 1, NULL)) {
updater.increment(key, 7);
}
// already applied
assertThat(countsStore.updater(countsStoreTxId + 2, NULL)).isNull();
countsStore.start(NULL, INSTANCE);
// then
assertThat(rebuildTriggered.booleanValue()).isFalse();
assertThat(countsStore.read(key, NULL)).isEqualTo(11);
}
use of org.neo4j.internal.counts.GBPTreeGenericCountsStore.Rebuilder in project neo4j by neo4j.
the class GBPTreeGenericCountsStoreTest method shouldNotApplyTransactionOnCreatedCountsStoreDuringRecovery.
@Test
void shouldNotApplyTransactionOnCreatedCountsStoreDuringRecovery() throws IOException {
// given
int labelId = 123;
incrementNodeCount(BASE_TX_ID + 1, labelId, 4);
countsStore.checkpoint(NULL);
incrementNodeCount(BASE_TX_ID + 2, labelId, -2);
closeCountsStore();
deleteCountsStore();
GBPTreeCountsStore.Monitor monitor = mock(GBPTreeCountsStore.Monitor.class);
// instantiate, but don't start
instantiateCountsStore(new Rebuilder() {
@Override
public void rebuild(CountUpdater updater, CursorContext cursorContext, MemoryTracker memoryTracker) {
updater.increment(nodeKey(labelId), 2);
}
@Override
public long lastCommittedTxId() {
return BASE_TX_ID + 2;
}
}, writable(), monitor);
// when doing recovery of the last transaction (since this is on an empty counts store then making the count negative, i.e. 0 - 2)
// applying this negative delta would have failed in the updater.
incrementNodeCount(BASE_TX_ID + 2, labelId, -2);
verify(monitor).ignoredTransaction(BASE_TX_ID + 2);
countsStore.start(NULL, INSTANCE);
// then
assertEquals(2, countsStore.read(nodeKey(labelId), NULL));
}
Aggregations