use of org.neo4j.kernel.impl.api.BatchTransactionApplier in project neo4j by neo4j.
the class TransactionRecordStateTest method shouldLockUpdatedNodes.
@Test
public void shouldLockUpdatedNodes() throws Exception {
// given
LockService locks = mock(LockService.class, new Answer<Object>() {
@Override
public synchronized Object answer(final InvocationOnMock invocation) throws Throwable {
// This is necessary because finalize() will also be called
String name = invocation.getMethod().getName();
if (name.equals("acquireNodeLock") || name.equals("acquireRelationshipLock")) {
return mock(Lock.class, (Answer) invocationOnMock -> null);
}
return null;
}
});
NeoStores neoStores = neoStoresRule.open();
NodeStore nodeStore = neoStores.getNodeStore();
long[] nodes = { // allocate ids
nodeStore.nextId(), nodeStore.nextId(), nodeStore.nextId(), nodeStore.nextId(), nodeStore.nextId(), nodeStore.nextId(), nodeStore.nextId() };
{
// create the node records that we will modify in our main tx.
TransactionRecordState tx = newTransactionRecordState(neoStores);
for (int i = 1; i < nodes.length - 1; i++) {
tx.nodeCreate(nodes[i]);
}
tx.nodeAddProperty(nodes[3], 0, "old");
tx.nodeAddProperty(nodes[4], 0, "old");
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), locks);
apply(applier, transaction(tx));
}
reset(locks);
// These are the changes we want to assert locking on
TransactionRecordState tx = newTransactionRecordState(neoStores);
tx.nodeCreate(nodes[0]);
tx.addLabelToNode(0, nodes[1]);
tx.nodeAddProperty(nodes[2], 0, "value");
tx.nodeChangeProperty(nodes[3], 0, "value");
tx.nodeRemoveProperty(nodes[4], 0);
tx.nodeDelete(nodes[5]);
tx.nodeCreate(nodes[6]);
tx.addLabelToNode(0, nodes[6]);
tx.nodeAddProperty(nodes[6], 0, "value");
//commit( tx );
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), locks);
apply(applier, transaction(tx));
// then
// create node, NodeCommand == 1 update
verify(locks, times(1)).acquireNodeLock(nodes[0], LockService.LockType.WRITE_LOCK);
// add label, NodeCommand == 1 update
verify(locks, times(1)).acquireNodeLock(nodes[1], LockService.LockType.WRITE_LOCK);
// add property, NodeCommand and PropertyCommand == 2 updates
verify(locks, times(2)).acquireNodeLock(nodes[2], LockService.LockType.WRITE_LOCK);
// update property, in place, PropertyCommand == 1 update
verify(locks, times(1)).acquireNodeLock(nodes[3], LockService.LockType.WRITE_LOCK);
// remove property, updates the Node and the Property == 2 updates
verify(locks, times(2)).acquireNodeLock(nodes[4], LockService.LockType.WRITE_LOCK);
// delete node, single NodeCommand == 1 update
verify(locks, times(1)).acquireNodeLock(nodes[5], LockService.LockType.WRITE_LOCK);
// create and add-label goes into the NodeCommand, add property is a PropertyCommand == 2 updates
verify(locks, times(2)).acquireNodeLock(nodes[6], LockService.LockType.WRITE_LOCK);
}
use of org.neo4j.kernel.impl.api.BatchTransactionApplier in project neo4j by neo4j.
the class TransactionRecordStateTest method shouldExtractUpdateCommandsInCorrectOrder.
@Test
public void shouldExtractUpdateCommandsInCorrectOrder() throws Throwable {
// GIVEN
NeoStores neoStores = neoStoresRule.open(GraphDatabaseSettings.dense_node_threshold.name(), "1");
TransactionRecordState recordState = newTransactionRecordState(neoStores);
long nodeId = 0, relId1 = 1, relId2 = 2, relId3 = 3;
recordState.nodeCreate(nodeId);
recordState.relCreate(relId1, 0, nodeId, nodeId);
recordState.relCreate(relId2, 0, nodeId, nodeId);
recordState.nodeAddProperty(nodeId, 0, 101);
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), LockService.NO_LOCK_SERVICE);
apply(applier, transaction(recordState));
recordState = newTransactionRecordState(neoStores);
recordState.nodeChangeProperty(nodeId, 0, 102);
recordState.relCreate(relId3, 0, nodeId, nodeId);
recordState.relAddProperty(relId1, 0, 123);
// WHEN
Collection<StorageCommand> commands = new ArrayList<>();
recordState.extractCommands(commands);
// THEN
Iterator<StorageCommand> commandIterator = commands.iterator();
// added rel property
assertCommand(commandIterator.next(), PropertyCommand.class);
// created relationship relId3
assertCommand(commandIterator.next(), RelationshipCommand.class);
// rest is updates...
assertCommand(commandIterator.next(), PropertyCommand.class);
assertCommand(commandIterator.next(), RelationshipCommand.class);
assertCommand(commandIterator.next(), RelationshipCommand.class);
assertCommand(commandIterator.next(), Command.RelationshipGroupCommand.class);
assertCommand(commandIterator.next(), NodeCommand.class);
assertFalse(commandIterator.hasNext());
}
use of org.neo4j.kernel.impl.api.BatchTransactionApplier in project neo4j by neo4j.
the class TransactionRecordStateTest method movingBilaterallyOfTheDenseNodeThresholdIsConsistent.
@Test
public void movingBilaterallyOfTheDenseNodeThresholdIsConsistent() throws Exception {
// GIVEN
NeoStores neoStores = neoStoresRule.open(GraphDatabaseSettings.dense_node_threshold.name(), "10");
TransactionRecordState tx = newTransactionRecordState(neoStores);
long nodeId = neoStores.getNodeStore().nextId();
tx.nodeCreate(nodeId);
int typeA = (int) neoStores.getRelationshipTypeTokenStore().nextId();
tx.createRelationshipTypeToken("A", typeA);
createRelationships(neoStores, tx, nodeId, typeA, INCOMING, 20);
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), LockService.NO_LOCK_SERVICE);
apply(applier, transaction(tx));
tx = newTransactionRecordState(neoStores);
int typeB = 1;
tx.createRelationshipTypeToken("B", typeB);
// WHEN
// i remove enough relationships to become dense and remove enough to become not dense
long[] relationshipsOfTypeB = createRelationships(neoStores, tx, nodeId, typeB, OUTGOING, 5);
for (long relationshipToDelete : relationshipsOfTypeB) {
tx.relDelete(relationshipToDelete);
}
PhysicalTransactionRepresentation ptx = transactionRepresentationOf(tx);
apply(applier, ptx);
// THEN
// The dynamic label record in before should be the same id as in after, and should be in use
final AtomicBoolean foundRelationshipGroupInUse = new AtomicBoolean();
ptx.accept(command -> ((Command) command).handle(new CommandVisitor.Adapter() {
@Override
public boolean visitRelationshipGroupCommand(Command.RelationshipGroupCommand command) throws IOException {
if (command.getAfter().inUse()) {
if (!foundRelationshipGroupInUse.get()) {
foundRelationshipGroupInUse.set(true);
} else {
fail();
}
}
return false;
}
}));
assertTrue("Did not create relationship group command", foundRelationshipGroupInUse.get());
}
use of org.neo4j.kernel.impl.api.BatchTransactionApplier in project neo4j by neo4j.
the class TransactionRecordStateTest method shouldDeleteDynamicLabelsForDeletedNode.
@Test
public void shouldDeleteDynamicLabelsForDeletedNode() throws Throwable {
// GIVEN a store that has got a node with a dynamic label record
NeoStores store = neoStoresRule.open();
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(store, mock(CacheAccessBackDoor.class), LockService.NO_LOCK_SERVICE);
AtomicLong nodeId = new AtomicLong();
AtomicLong dynamicLabelRecordId = new AtomicLong();
apply(applier, transaction(nodeWithDynamicLabelRecord(store, nodeId, dynamicLabelRecordId)));
assertDynamicLabelRecordInUse(store, dynamicLabelRecordId.get(), true);
// WHEN applying a transaction where the node is deleted
apply(applier, transaction(deleteNode(store, nodeId.get())));
// THEN the dynamic label record should also be deleted
assertDynamicLabelRecordInUse(store, dynamicLabelRecordId.get(), false);
}
use of org.neo4j.kernel.impl.api.BatchTransactionApplier in project neo4j by neo4j.
the class TransactionRecordStateTest method shouldExtractDeleteCommandsInCorrectOrder.
@Test
public void shouldExtractDeleteCommandsInCorrectOrder() throws Exception {
// GIVEN
NeoStores neoStores = neoStoresRule.open(GraphDatabaseSettings.dense_node_threshold.name(), "1");
TransactionRecordState recordState = newTransactionRecordState(neoStores);
long nodeId1 = 0, nodeId2 = 1, relId1 = 1, relId2 = 2, relId4 = 10;
recordState.nodeCreate(nodeId1);
recordState.nodeCreate(nodeId2);
recordState.relCreate(relId1, 0, nodeId1, nodeId1);
recordState.relCreate(relId2, 0, nodeId1, nodeId1);
recordState.relCreate(relId4, 1, nodeId1, nodeId1);
recordState.nodeAddProperty(nodeId1, 0, 101);
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), LockService.NO_LOCK_SERVICE);
apply(applier, transaction(recordState));
recordState = newTransactionRecordState(neoStores);
recordState.relDelete(relId4);
recordState.nodeDelete(nodeId2);
recordState.nodeRemoveProperty(nodeId1, 0);
// WHEN
Collection<StorageCommand> commands = new ArrayList<>();
recordState.extractCommands(commands);
// THEN
Iterator<StorageCommand> commandIterator = commands.iterator();
// updated rel group to not point to the deleted one below
assertCommand(commandIterator.next(), Command.RelationshipGroupCommand.class);
// updated node to point to the group after the deleted one
assertCommand(commandIterator.next(), NodeCommand.class);
// rest is deletions below...
assertCommand(commandIterator.next(), PropertyCommand.class);
assertCommand(commandIterator.next(), RelationshipCommand.class);
assertCommand(commandIterator.next(), Command.RelationshipGroupCommand.class);
assertCommand(commandIterator.next(), NodeCommand.class);
assertFalse(commandIterator.hasNext());
}
Aggregations