use of org.neo4j.kernel.impl.store.DynamicNodeLabels in project neo4j by neo4j.
the class NodeInUseWithCorrectLabelsCheck method checkReference.
@Override
public void checkReference(RECORD record, NodeRecord nodeRecord, CheckerEngine<RECORD, REPORT> engine, RecordAccess records) {
if (nodeRecord.inUse()) {
NodeLabels nodeLabels = NodeLabelsField.parseLabelsField(nodeRecord);
if (nodeLabels instanceof DynamicNodeLabels) {
DynamicNodeLabels dynamicNodeLabels = (DynamicNodeLabels) nodeLabels;
long firstRecordId = dynamicNodeLabels.getFirstDynamicRecordId();
RecordReference<DynamicRecord> firstRecordReference = records.nodeLabels(firstRecordId);
ExpectedNodeLabelsChecker expectedNodeLabelsChecker = new ExpectedNodeLabelsChecker(nodeRecord);
LabelChainWalker<RECORD, REPORT> checker = new LabelChainWalker<>(expectedNodeLabelsChecker);
engine.comparativeCheck(firstRecordReference, checker);
// I think this is empty in production
nodeRecord.getDynamicLabelRecords();
} else {
long[] storeLabels = nodeLabels.get(null);
REPORT report = engine.report();
validateLabelIds(nodeRecord, storeLabels, report);
}
} else {
engine.report().nodeNotInUse(nodeRecord);
}
}
use of org.neo4j.kernel.impl.store.DynamicNodeLabels in project neo4j by neo4j.
the class NodeLabelReader method getListOfLabels.
public static <RECORD extends AbstractBaseRecord, REPORT extends ConsistencyReport> Set<Long> getListOfLabels(NodeRecord nodeRecord, RecordAccess records, CheckerEngine<RECORD, REPORT> engine) {
final Set<Long> labels = new HashSet<>();
NodeLabels nodeLabels = NodeLabelsField.parseLabelsField(nodeRecord);
if (nodeLabels instanceof DynamicNodeLabels) {
DynamicNodeLabels dynamicNodeLabels = (DynamicNodeLabels) nodeLabels;
long firstRecordId = dynamicNodeLabels.getFirstDynamicRecordId();
RecordReference<DynamicRecord> firstRecordReference = records.nodeLabels(firstRecordId);
engine.comparativeCheck(firstRecordReference, new LabelChainWalker<>(new LabelChainWalker.Validator<RECORD, REPORT>() {
@Override
public void onRecordNotInUse(DynamicRecord dynamicRecord, CheckerEngine<RECORD, REPORT> engine) {
}
@Override
public void onRecordChainCycle(DynamicRecord record, CheckerEngine<RECORD, REPORT> engine) {
}
@Override
public void onWellFormedChain(long[] labelIds, CheckerEngine<RECORD, REPORT> engine, RecordAccess records) {
copyToSet(labelIds, labels);
}
}));
} else {
copyToSet(nodeLabels.get(null), labels);
}
return labels;
}
use of org.neo4j.kernel.impl.store.DynamicNodeLabels in project neo4j by neo4j.
the class NodeLabelsFieldTest method shouldHandleRandomAddsAndRemoves.
/*
* There was this issue that DynamicNodeLabels#add would consider even unused dynamic records when
* reading existing label ids before making the change. Previously this would create a duplicate
* last label id (the one formerly being in the second record).
*
* This randomized test found this issue every time when it existed and it will potentially find other
* unforeseen issues as well.
*/
@Test
public void shouldHandleRandomAddsAndRemoves() throws Exception {
// GIVEN
Set<Integer> key = new HashSet<>();
NodeRecord node = new NodeRecord(0);
node.setInUse(true);
// WHEN
for (int i = 0; i < 100_000; i++) {
NodeLabels labels = NodeLabelsField.parseLabelsField(node);
int labelId = random.nextInt(200);
if (random.nextBoolean()) {
if (!key.contains(labelId)) {
labels.add(labelId, nodeStore, nodeStore.getDynamicLabelStore());
key.add(labelId);
}
} else {
if (key.remove(labelId)) {
labels.remove(labelId, nodeStore);
}
}
}
// THEN
NodeLabels labels = NodeLabelsField.parseLabelsField(node);
long[] readLabelIds = labels.get(nodeStore);
for (long labelId : readLabelIds) {
assertTrue("Found an unexpected label " + labelId, key.remove((int) labelId));
}
assertTrue(key.isEmpty());
}
use of org.neo4j.kernel.impl.store.DynamicNodeLabels in project neo4j by neo4j.
the class NodeLabelsFieldTest method shouldHandleRandomAddsAndRemoves.
/*
* There was this issue that DynamicNodeLabels#add would consider even unused dynamic records when
* reading existing label ids before making the change. Previously this would create a duplicate
* last label id (the one formerly being in the second record).
*
* This randomized test found this issue every time when it existed and it will potentially find other
* unforeseen issues as well.
*/
@Test
void shouldHandleRandomAddsAndRemoves() {
// GIVEN
Set<Integer> key = new HashSet<>();
NodeRecord node = new NodeRecord(0);
node.setInUse(true);
// WHEN
for (int i = 0; i < 100_000; i++) {
NodeLabels labels = NodeLabelsField.parseLabelsField(node);
int labelId = random.nextInt(200);
if (random.nextBoolean()) {
if (!key.contains(labelId)) {
labels.add(labelId, nodeStore, nodeStore.getDynamicLabelStore(), NULL, INSTANCE);
key.add(labelId);
}
} else {
if (key.remove(labelId)) {
labels.remove(labelId, nodeStore, NULL, INSTANCE);
}
}
}
// THEN
NodeLabels labels = NodeLabelsField.parseLabelsField(node);
long[] readLabelIds = labels.get(nodeStore, NULL);
for (long labelId : readLabelIds) {
assertTrue(key.remove((int) labelId), "Found an unexpected label " + labelId);
}
assertTrue(key.isEmpty());
}
Aggregations