use of org.neo4j.util.concurrent.ArrayQueueOutOfOrderSequence in project neo4j by neo4j.
the class GBPTreeGenericCountsStoreTest method shouldCheckpointAndRecoverConsistentlyUnderStressfulLoad.
@Test
void shouldCheckpointAndRecoverConsistentlyUnderStressfulLoad() throws Throwable {
// given
// it's good if it's way more than number of cores so that it creates some scheduling issues
int threads = 50;
int numberOfRounds = 5;
int roundTimeMillis = 300;
ConcurrentMap<CountsKey, AtomicLong> expected = new ConcurrentHashMap<>();
AtomicLong nextTxId = new AtomicLong(BASE_TX_ID);
AtomicLong lastCheckPointedTxId = new AtomicLong(nextTxId.longValue());
long lastRoundClosedAt = BASE_TX_ID;
// Start at some number > 0 so that we can do negative deltas now and then
long baseCount = 10_000;
try (CountUpdater initialApplier = countsStore.updater(nextTxId.incrementAndGet(), NULL)) {
for (int s = -1; s < HIGH_TOKEN_ID; s++) {
initialApplier.increment(nodeKey(s), baseCount);
for (int t = -1; t < HIGH_TOKEN_ID; t++) {
for (int e = -1; e < HIGH_TOKEN_ID; e++) {
initialApplier.increment(relationshipKey(s, t, e), baseCount);
}
}
}
}
OutOfOrderSequence lastClosedTxId = new ArrayQueueOutOfOrderSequence(nextTxId.get(), 200, EMPTY_LONG_ARRAY);
// when
for (int r = 0; r < numberOfRounds; r++) {
// Let loose updaters and a check-pointer
Race race = new Race().withMaxDuration(roundTimeMillis, TimeUnit.MILLISECONDS);
race.addContestants(threads, throwing(() -> {
long txId = nextTxId.incrementAndGet();
// Sleep a random time after getting the txId, this creates bigger temporary gaps in the txId sequence
Thread.sleep(ThreadLocalRandom.current().nextInt(5));
generateAndApplyTransaction(expected, txId);
lastClosedTxId.offer(txId, EMPTY_LONG_ARRAY);
}));
race.addContestant(throwing(() -> {
long checkpointTxId = lastClosedTxId.getHighestGapFreeNumber();
countsStore.checkpoint(NULL);
lastCheckPointedTxId.set(checkpointTxId);
Thread.sleep(ThreadLocalRandom.current().nextInt(roundTimeMillis / 5));
}));
race.go();
// Crash here, well not really crash but close the counts store knowing that there's any number of transactions since the last checkpoint
// and we know the last committed tx id as well as the (pessimistic) last check-pointed tx id.
crashAndRestartCountsStore();
recover(lastCheckPointedTxId.get(), nextTxId.get());
assertThat(nextTxId.get()).isGreaterThan(lastRoundClosedAt);
lastRoundClosedAt = nextTxId.get();
// then
assertCountsMatchesExpected(expected, baseCount);
}
}
use of org.neo4j.util.concurrent.ArrayQueueOutOfOrderSequence in project neo4j by neo4j.
the class DefaultReconciledTransactionTracker method enable.
@Override
public void enable(long reconciledTransactionId) {
requireNonNegative(reconciledTransactionId);
initializationLock.writeLock().lock();
try {
if (sequence == null) {
log.info("Enabling with transaction ID %s", reconciledTransactionId);
} else {
// This isn't expected to be used, but we leave the code path for robustness.
log.warn("Enabling when not disabled with %s to transaction ID %s", sequence, reconciledTransactionId);
}
sequence = new ArrayQueueOutOfOrderSequence(reconciledTransactionId, INITIAL_ARRAY_SIZE, NO_METADATA);
startingNumber = reconciledTransactionId;
for (long txId : outstanding) {
if (txId > reconciledTransactionId) {
sequence.offer(txId, NO_METADATA);
}
}
outstanding.clear();
} finally {
initializationLock.writeLock().unlock();
}
}
Aggregations