use of org.apache.commons.lang3.mutable.MutableLong in project neo4j by neo4j.
the class TreeNodeTest method shouldInsertAndRemoveRandomKeysAndValues.
@Test
public void shouldInsertAndRemoveRandomKeysAndValues() throws Exception {
// This test doesn't care about sorting, that's an aspect that lies outside of TreeNode, really
// GIVEN
node.initializeLeaf(cursor, STABLE_GENERATION, UNSTABLE_GENERATION);
int maxKeyCount = node.leafMaxKeyCount();
// add +1 to these to simplify some array logic in the test itself
long[] expectedKeys = new long[maxKeyCount + 1];
long[] expectedValues = new long[maxKeyCount + 1];
int expectedKeyCount = 0;
MutableLong key = layout.newKey();
MutableLong value = layout.newValue();
// WHEN/THEN
for (int i = 0; i < 1000; i++) {
if (random.nextFloat() < 0.7) {
// 70% insert
if (expectedKeyCount < maxKeyCount) {
// there's room
int position = expectedKeyCount == 0 ? 0 : random.nextInt(expectedKeyCount);
// ensure unique
do {
key.setValue(random.nextLong());
} while (contains(expectedKeys, 0, expectedKeyCount, key.longValue()));
node.insertKeyAt(cursor, key, position, expectedKeyCount);
insert(expectedKeys, expectedKeyCount, key.longValue(), position);
value.setValue(random.nextLong());
node.insertValueAt(cursor, value, position, expectedKeyCount);
insert(expectedValues, expectedKeyCount, value.longValue(), position);
node.setKeyCount(cursor, ++expectedKeyCount);
}
} else {
// 30% remove
if (expectedKeyCount > 0) {
// there are things to remove
int position = random.nextInt(expectedKeyCount);
node.keyAt(cursor, key, position);
node.removeKeyAt(cursor, position, expectedKeyCount);
long expectedKey = remove(expectedKeys, expectedKeyCount, position);
assertEquals(expectedKey, key.longValue());
node.valueAt(cursor, value, position);
node.removeValueAt(cursor, position, expectedKeyCount);
long expectedValue = remove(expectedValues, expectedKeyCount, position);
assertEquals(expectedValue, value.longValue());
node.setKeyCount(cursor, --expectedKeyCount);
}
}
}
// THEN
assertEquals(expectedKeyCount, node.keyCount(cursor));
for (int i = 0; i < expectedKeyCount; i++) {
long expectedKey = expectedKeys[i];
node.keyAt(cursor, key, i);
assertEquals(expectedKey, key.longValue());
long expectedValue = expectedValues[i];
node.valueAt(cursor, value, i);
assertEquals("For key " + key.longValue(), expectedValue, value.longValue());
}
}
use of org.apache.commons.lang3.mutable.MutableLong in project neo4j by neo4j.
the class ParallelBatchImporterTest method relationships.
private InputIterable<InputRelationship> relationships(final long randomSeed, final long count, final InputIdGenerator idGenerator, final IdGroupDistribution groups) {
return new InputIterable<InputRelationship>() {
private int calls;
@Override
public InputIterator<InputRelationship> iterator() {
calls++;
assertTrue("Unexpected use of input iterator " + multiPassIterators + ", " + calls, multiPassIterators || (!multiPassIterators && calls == 1));
// since we use it to compare the imported data against after the import has been completed.
return new SimpleInputIterator<InputRelationship>("test relationships") {
private final Random random = new Random(randomSeed);
private final Randoms randoms = new Randoms(random, Randoms.DEFAULT);
private int cursor;
private final MutableLong nodeIndex = new MutableLong(-1);
@Override
protected InputRelationship fetchNextOrNull() {
if (cursor < count) {
Object[] properties = randomProperties(randoms, "Name " + cursor);
try {
Object startNode = idGenerator.randomExisting(random, nodeIndex);
Group startNodeGroup = groups.groupOf(nodeIndex.longValue());
Object endNode = idGenerator.randomExisting(random, nodeIndex);
Group endNodeGroup = groups.groupOf(nodeIndex.longValue());
// miss some
startNode = idGenerator.miss(random, startNode, 0.001f);
endNode = idGenerator.miss(random, endNode, 0.001f);
String type = idGenerator.randomType(random);
if (random.nextFloat() < 0.00005) {
// Let there be a small chance of introducing a one-off relationship
// with a type that no, or at least very few, other relationships have.
type += "_odd";
}
return new InputRelationship(sourceDescription, itemNumber, itemNumber, properties, null, startNodeGroup, startNode, endNodeGroup, endNode, type, null);
} finally {
cursor++;
}
}
return null;
}
};
}
@Override
public boolean supportsMultiplePasses() {
return multiPassIterators;
}
};
}
use of org.apache.commons.lang3.mutable.MutableLong in project neo4j by neo4j.
the class FormatCompatibilityTest method shouldDetectFormatChange.
@Test
public void shouldDetectFormatChange() throws Throwable {
// GIVEN stored tree
File storeFile = directory.file(STORE);
try {
unzipTo(storeFile);
} catch (FileNotFoundException e) {
// First time this test is run, eh?
createAndZipTree(storeFile);
tellDeveloperToCommitThisFormatVersion();
}
assertTrue(CURRENT_FORMAT_ZIP + " seems to be missing from resources directory", fsRule.get().fileExists(storeFile));
// WHEN reading from the tree
// THEN everything should work, otherwise there has likely been a format change
PageCache pageCache = pageCacheRule.getPageCache(fsRule.get());
try (GBPTree<MutableLong, MutableLong> tree = new GBPTree<>(pageCache, storeFile, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER)) {
try {
tree.consistencyCheck();
try (RawCursor<Hit<MutableLong, MutableLong>, IOException> cursor = tree.seek(new MutableLong(0), new MutableLong(KEY_COUNT))) {
for (long expectedKey = 0; cursor.next(); expectedKey++) {
Hit<MutableLong, MutableLong> hit = cursor.get();
assertEquals(expectedKey, hit.key().longValue());
assertEquals(value(expectedKey), hit.value().longValue());
}
assertFalse(cursor.next());
}
} catch (Throwable t) {
throw new AssertionError(format("If this is the single failing test for %s this failure is a strong indication that format " + "has changed without also incrementing %s.FORMAT_VERSION. " + "Please go ahead and increment the format version", TREE_CLASS_NAME, TREE_CLASS_NAME), t);
}
} catch (MetadataMismatchException e) {
// Good actually, or?
assertThat(e.getMessage(), containsString("format version"));
fsRule.get().deleteFile(storeFile);
createAndZipTree(storeFile);
tellDeveloperToCommitThisFormatVersion();
}
}
use of org.apache.commons.lang3.mutable.MutableLong in project neo4j by neo4j.
the class FormatCompatibilityTest method createAndZipTree.
private void createAndZipTree(File storeFile) throws IOException {
PageCache pageCache = pageCacheRule.getPageCache(fsRule.get());
try (GBPTree<MutableLong, MutableLong> tree = new GBPTree<>(pageCache, storeFile, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER)) {
MutableLong insertKey = new MutableLong();
MutableLong insertValue = new MutableLong();
int batchSize = KEY_COUNT / 10;
for (int i = 0, key = 0; i < 10; i++) {
try (Writer<MutableLong, MutableLong> writer = tree.writer()) {
for (int j = 0; j < batchSize; j++, key++) {
insertKey.setValue(key);
insertValue.setValue(value(key));
writer.put(insertKey, insertValue);
}
}
tree.checkpoint(IOLimiter.unlimited());
}
}
zip(storeFile);
}
use of org.apache.commons.lang3.mutable.MutableLong in project neo4j by neo4j.
the class GBPTreeRecoveryTest method doShouldRecoverFromAnything.
private void doShouldRecoverFromAnything(boolean replayRecoveryExactlyFromCheckpoint) throws Exception {
assertInitialized();
// GIVEN
// a tree which has had random updates and checkpoints in it, load generated with specific seed
File file = directory.file("index");
List<Action> load = generateLoad();
int lastCheckPointIndex = indexOfLastCheckpoint(load);
{
// _,_,_,_,_,_,_,c,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,c,_,_,_,_,_,_,_,_,_,_,_
// ^ ^
// | |------------ crash flush index
// |-------------------------- last checkpoint index
//
PageCache pageCache = createPageCache();
GBPTree<MutableLong, MutableLong> index = createIndex(pageCache, file);
// Execute all actions up to and including last checkpoint ...
execute(load.subList(0, lastCheckPointIndex + 1), index);
// ... a random amount of the remaining "unsafe" actions ...
int numberOfRemainingActions = load.size() - lastCheckPointIndex - 1;
int crashFlushIndex = lastCheckPointIndex + random.nextInt(numberOfRemainingActions) + 1;
execute(load.subList(lastCheckPointIndex + 1, crashFlushIndex), index);
// ... flush ...
pageCache.flushAndForce();
// ... execute the remaining actions
execute(load.subList(crashFlushIndex, load.size()), index);
// ... and finally crash
fs.snapshot(throwing(() -> {
index.close();
pageCache.close();
}));
}
// WHEN doing recovery
List<Action> recoveryActions;
if (replayRecoveryExactlyFromCheckpoint) {
recoveryActions = recoveryActions(load, lastCheckPointIndex + 1);
} else {
recoveryActions = recoveryActions(load, random.nextInt(lastCheckPointIndex + 1));
}
// first crashing during recovery
int numberOfCrashesDuringRecovery = random.intBetween(0, 3);
for (int i = 0; i < numberOfCrashesDuringRecovery; i++) {
PageCache pageCache = createPageCache();
GBPTree<MutableLong, MutableLong> index = createIndex(pageCache, file);
int numberOfActionsToRecoverBeforeCrashing = random.intBetween(1, recoveryActions.size());
recover(recoveryActions.subList(0, numberOfActionsToRecoverBeforeCrashing), index);
pageCache.flushAndForce();
fs.snapshot(throwing(() -> {
index.close();
pageCache.close();
}));
}
// to finally apply all actions after last checkpoint and verify tree
try (PageCache pageCache = createPageCache();
GBPTree<MutableLong, MutableLong> index = createIndex(pageCache, file)) {
recover(recoveryActions, index);
index.finishRecovery();
// THEN
// we should end up with a consistent index containing all the stuff load says
index.consistencyCheck();
long[] /*key,value,key,value...*/
aggregate = expectedSortedAggregatedDataFromGeneratedLoad(load);
try (RawCursor<Hit<MutableLong, MutableLong>, IOException> cursor = index.seek(new MutableLong(Long.MIN_VALUE), new MutableLong(Long.MAX_VALUE))) {
for (int i = 0; i < aggregate.length; ) {
assertTrue(cursor.next());
Hit<MutableLong, MutableLong> hit = cursor.get();
assertEquals(aggregate[i++], hit.key().longValue());
assertEquals(aggregate[i++], hit.value().longValue());
}
assertFalse(cursor.next());
}
}
}
Aggregations