use of org.neo4j.internal.id.IdGenerator.Marker in project neo4j by neo4j.
the class BufferingIdGeneratorFactoryTest method shouldDelayFreeingOfDeletedIds.
@Test
void shouldDelayFreeingOfDeletedIds() {
// WHEN
try (Marker marker = idGenerator.marker(NULL)) {
marker.markDeleted(7);
}
verify(actual.markers[STRING_BLOCK.ordinal()]).markDeleted(7);
verify(actual.markers[STRING_BLOCK.ordinal()]).close();
verifyNoMoreInteractions(actual.markers[STRING_BLOCK.ordinal()]);
// after some maintenance and transaction still not closed
bufferingIdGeneratorFactory.maintenance(NULL);
verifyNoMoreInteractions(actual.markers[STRING_BLOCK.ordinal()]);
// although after transactions have all closed
boundaries.setMostRecentlyReturnedSnapshotToAllClosed();
bufferingIdGeneratorFactory.maintenance(NULL);
// THEN
verify(actual.markers[STRING_BLOCK.ordinal()]).markFree(7);
}
use of org.neo4j.internal.id.IdGenerator.Marker in project neo4j by neo4j.
the class BufferingIdGeneratorFactoryTest method shouldDelayFreeingOfDeletedIdsUntilCheckpoint.
@Test
void shouldDelayFreeingOfDeletedIdsUntilCheckpoint() {
// WHEN
try (Marker marker = idGenerator.marker(NULL)) {
marker.markDeleted(7);
}
verify(actual.markers[STRING_BLOCK.ordinal()]).markDeleted(7);
verify(actual.markers[STRING_BLOCK.ordinal()]).close();
verifyNoMoreInteractions(actual.markers[STRING_BLOCK.ordinal()]);
// after some maintenance and transaction still not closed
idGenerator.checkpoint(NULL);
verifyNoMoreInteractions(actual.markers[STRING_BLOCK.ordinal()]);
// although after transactions have all closed
boundaries.setMostRecentlyReturnedSnapshotToAllClosed();
idGenerator.checkpoint(NULL);
// THEN
verify(actual.markers[STRING_BLOCK.ordinal()]).markFree(7);
}
use of org.neo4j.internal.id.IdGenerator.Marker in project neo4j by neo4j.
the class IndexedIdGeneratorTest method shouldMarkDroppedIdsAsDeletedAndFree.
@Test
void shouldMarkDroppedIdsAsDeletedAndFree() throws IOException {
// given
idGenerator.start(NO_FREE_IDS, NULL);
long id = idGenerator.nextId(NULL);
long droppedId = idGenerator.nextId(NULL);
long id2 = idGenerator.nextId(NULL);
// when
try (Marker commitMarker = idGenerator.marker(NULL)) {
commitMarker.markUsed(id);
commitMarker.markUsed(id2);
}
restart();
// then
assertEquals(droppedId, idGenerator.nextId(NULL));
}
use of org.neo4j.internal.id.IdGenerator.Marker in project neo4j by neo4j.
the class IndexedIdGeneratorTest method shouldAwaitConcurrentOngoingMaintenanceIfToldTo.
@Test
void shouldAwaitConcurrentOngoingMaintenanceIfToldTo() throws Exception {
// given
idGenerator.close();
Barrier.Control barrier = new Barrier.Control();
IndexedIdGenerator.Monitor monitor = new IndexedIdGenerator.Monitor.Adapter() {
private boolean first = true;
@Override
public void cached(long cachedId) {
if (first) {
barrier.reached();
first = false;
}
super.cached(cachedId);
}
};
idGenerator = new IndexedIdGenerator(pageCache, file, immediate(), IdType.LABEL_TOKEN, false, () -> 0, MAX_ID, writable(), Config.defaults(), NULL, monitor, DEFAULT_DATABASE_NAME, Sets.immutable.empty());
idGenerator.start(NO_FREE_IDS, NULL);
try (Marker marker = idGenerator.marker(NULL)) {
for (int i = 0; i < 5; i++) {
marker.markDeleted(i);
marker.markFree(i);
}
}
// when
try (OtherThreadExecutor t2 = new OtherThreadExecutor("T2");
OtherThreadExecutor t3 = new OtherThreadExecutor("T3")) {
Future<Object> t2Future = t2.executeDontWait(() -> {
idGenerator.nextId(NULL);
return null;
});
barrier.await();
// check that a maintenance call blocks
Future<Object> t3Future = t3.executeDontWait(() -> {
idGenerator.maintenance(NULL);
return null;
});
t3.waitUntilWaiting(details -> details.isAt(FreeIdScanner.class, "tryLoadFreeIdsIntoCache"));
barrier.release();
t2Future.get();
t3Future.get();
}
}
use of org.neo4j.internal.id.IdGenerator.Marker in project neo4j by neo4j.
the class IndexedIdGeneratorTest method shouldPrioritizeFreelistOnConcurrentAllocation.
@Test
void shouldPrioritizeFreelistOnConcurrentAllocation() throws Exception {
// given
idGenerator.close();
Barrier.Control barrier = new Barrier.Control();
AtomicInteger numReserved = new AtomicInteger();
AtomicInteger numCached = new AtomicInteger();
AtomicBoolean enabled = new AtomicBoolean(true);
IndexedIdGenerator.Monitor monitor = new IndexedIdGenerator.Monitor.Adapter() {
@Override
public void markedAsReserved(long markedId) {
numReserved.incrementAndGet();
}
@Override
public void cached(long cachedId) {
int cached = numCached.incrementAndGet();
if (cached == numReserved.get() && enabled.get()) {
enabled.set(false);
barrier.reached();
}
}
@Override
public void allocatedFromHigh(long allocatedId) {
fail("Should not allocate from high ID");
}
};
idGenerator = new IndexedIdGenerator(pageCache, file, immediate(), IdType.LABEL_TOKEN, false, () -> 0, MAX_ID, writable(), Config.defaults(), NULL, monitor, "db", Sets.immutable.empty());
idGenerator.start(NO_FREE_IDS, NULL);
// delete and free more than cache-size IDs
try (Marker marker = idGenerator.marker(NULL)) {
for (int i = 0; i < IndexedIdGenerator.SMALL_CACHE_CAPACITY + 10; i++) {
marker.markDeleted(i);
marker.markFree(i);
}
}
// let one thread call nextId() and block when it has filled the cache (the above monitor will see to that it happens)
try (OtherThreadExecutor t2 = new OtherThreadExecutor("T2")) {
Future<Void> nextIdFuture = t2.executeDontWait(() -> {
long id = idGenerator.nextId(NULL);
assertEquals(IndexedIdGenerator.SMALL_CACHE_CAPACITY, id);
return null;
});
// and let another thread allocate all those IDs before the T2 thread had a chance to get one of them
barrier.await();
for (int i = 0; i < numCached.get(); i++) {
idGenerator.nextId(NULL);
}
// then let first thread continue and it should not allocate off of high id
barrier.release();
nextIdFuture.get();
}
}
Aggregations