use of org.neo4j.kernel.impl.locking.Lock in project neo4j by neo4j.
the class NeoStoreIndexStoreViewTest method before.
@Before
public void before() throws KernelException {
graphDb = dbRule.getGraphDatabaseAPI();
createAlistairAndStefanNodes();
getOrCreateIds();
neoStores = graphDb.getDependencyResolver().resolveDependency(RecordStorageEngine.class).testAccessNeoStores();
locks = mock(LockService.class, (Answer) invocation -> {
Long nodeId = (Long) invocation.getArguments()[0];
Lock lock = lockMocks.get(nodeId);
if (lock == null) {
lockMocks.put(nodeId, lock = mock(Lock.class));
}
return lock;
});
storeView = new NeoStoreIndexStoreView(locks, neoStores);
}
use of org.neo4j.kernel.impl.locking.Lock in project neo4j by neo4j.
the class TxStateTransactionDataSnapshot method takeSnapshot.
private void takeSnapshot() {
try {
for (long nodeId : state.addedAndRemovedNodes().getRemoved()) {
try (Cursor<NodeItem> node = storeStatement.acquireSingleNodeCursor(nodeId)) {
if (node.next()) {
Lock lock = node.get().lock();
try (Cursor<PropertyItem> properties = storeStatement.acquirePropertyCursor(node.get().nextPropertyId(), lock)) {
while (properties.next()) {
removedNodeProperties.add(new NodePropertyEntryView(nodeId, store.propertyKeyGetName(properties.get().propertyKeyId()), null, properties.get().value()));
}
}
node.get().labels().visitKeys(labelId -> {
removedLabels.add(new LabelEntryView(nodeId, store.labelGetName(labelId)));
return false;
});
}
}
}
for (long relId : state.addedAndRemovedRelationships().getRemoved()) {
Relationship relationshipProxy = relationship(relId);
try (Cursor<RelationshipItem> relationship = storeStatement.acquireSingleRelationshipCursor(relId)) {
if (relationship.next()) {
Lock lock = relationship.get().lock();
try (Cursor<PropertyItem> properties = storeStatement.acquirePropertyCursor(relationship.get().nextPropertyId(), lock)) {
while (properties.next()) {
removedRelationshipProperties.add(new RelationshipPropertyEntryView(relationshipProxy, store.propertyKeyGetName(properties.get().propertyKeyId()), null, properties.get().value()));
}
}
}
}
}
for (NodeState nodeState : state.modifiedNodes()) {
Iterator<StorageProperty> added = nodeState.addedAndChangedProperties();
while (added.hasNext()) {
DefinedProperty property = (DefinedProperty) added.next();
assignedNodeProperties.add(new NodePropertyEntryView(nodeState.getId(), store.propertyKeyGetName(property.propertyKeyId()), property.value(), committedValue(nodeState, property.propertyKeyId())));
}
Iterator<Integer> removed = nodeState.removedProperties();
while (removed.hasNext()) {
Integer property = removed.next();
removedNodeProperties.add(new NodePropertyEntryView(nodeState.getId(), store.propertyKeyGetName(property), null, committedValue(nodeState, property)));
}
ReadableDiffSets<Integer> labels = nodeState.labelDiffSets();
for (Integer label : labels.getAdded()) {
assignedLabels.add(new LabelEntryView(nodeState.getId(), store.labelGetName(label)));
}
for (Integer label : labels.getRemoved()) {
removedLabels.add(new LabelEntryView(nodeState.getId(), store.labelGetName(label)));
}
}
for (RelationshipState relState : state.modifiedRelationships()) {
Relationship relationship = relationship(relState.getId());
Iterator<StorageProperty> added = relState.addedAndChangedProperties();
while (added.hasNext()) {
DefinedProperty property = (DefinedProperty) added.next();
assignedRelationshipProperties.add(new RelationshipPropertyEntryView(relationship, store.propertyKeyGetName(property.propertyKeyId()), property.value(), committedValue(relState, property.propertyKeyId())));
}
Iterator<Integer> removed = relState.removedProperties();
while (removed.hasNext()) {
Integer property = removed.next();
removedRelationshipProperties.add(new RelationshipPropertyEntryView(relationship, store.propertyKeyGetName(property), null, committedValue(relState, property)));
}
}
} catch (PropertyKeyIdNotFoundKernelException | LabelNotFoundKernelException e) {
throw new IllegalStateException("An entity that does not exist was modified.", e);
}
}
use of org.neo4j.kernel.impl.locking.Lock in project neo4j by neo4j.
the class PropertyExistenceEnforcer method properties.
private Cursor<PropertyItem> properties(NodeItem node) {
Lock lock = node.lock();
Cursor<PropertyItem> cursor = storeStatement().acquirePropertyCursor(node.nextPropertyId(), lock);
return txState.augmentPropertyCursor(cursor, txState.getNodeState(node.id()));
}
use of org.neo4j.kernel.impl.locking.Lock in project neo4j by neo4j.
the class PropertyExistenceEnforcer method properties.
private Cursor<PropertyItem> properties(RelationshipItem relationship) {
Lock lock = relationship.lock();
Cursor<PropertyItem> cursor = storeStatement().acquirePropertyCursor(relationship.nextPropertyId(), lock);
return txState.augmentPropertyCursor(cursor, txState.getRelationshipState(relationship.id()));
}
use of org.neo4j.kernel.impl.locking.Lock in project neo4j by neo4j.
the class UniqueConstraintCompatibility method applyChangesToPopulatingUpdater.
/**
* NOTE the tests using this will currently succeed for the wrong reasons,
* because the data-changing transaction does not actually release the
* schema read lock early enough for the PopulatingUpdater to come into
* play.
*/
private Future<?> applyChangesToPopulatingUpdater(long blockDataChangeTransactionOnLockOnId, long blockPopulatorOnLockOnId, final Action... actions) throws InterruptedException, ExecutionException {
// We want to issue an update to an index populator for a constraint.
// However, creating a constraint takes a schema write lock, while
// creating nodes and setting their properties takes a schema read
// lock. We need to sneak past these locks.
final CountDownLatch createNodeReadyLatch = new CountDownLatch(1);
final CountDownLatch createNodeCommitLatch = new CountDownLatch(1);
Future<?> updatingTransaction = executor.submit(new Runnable() {
@Override
public void run() {
try (Transaction tx = db.beginTx()) {
for (Action action : actions) {
action.accept(tx);
}
tx.success();
createNodeReadyLatch.countDown();
awaitUninterruptibly(createNodeCommitLatch);
}
}
});
createNodeReadyLatch.await();
// The above transaction now contain the changes we want to expose to
// the IndexUpdater as updates. This will happen when we commit the
// transaction. The transaction now also holds the schema read lock,
// so we can't begin creating our constraint just yet.
// We first have to unlock the schema, and then block just before we
// send off our updates. We can do that by making another thread take a
// read lock on the node we just created, and then initiate our commit.
Lock lockBlockingDataChangeTransaction = getLockService().acquireNodeLock(blockDataChangeTransactionOnLockOnId, LockType.WRITE_LOCK);
// Before we begin creating the constraint, we take a write lock on an
// "earlier" node, to hold up the populator for the constraint index.
Lock lockBlockingIndexPopulator = getLockService().acquireNodeLock(blockPopulatorOnLockOnId, LockType.WRITE_LOCK);
// This thread tries to create a constraint. It should block, waiting for it's
// population job to finish, and it's population job should in turn be blocked
// on the lockBlockingIndexPopulator above:
final CountDownLatch createConstraintTransactionStarted = new CountDownLatch(1);
Future<?> createConstraintTransaction = executor.submit(new Runnable() {
@Override
public void run() {
createUniqueConstraint(createConstraintTransactionStarted);
}
});
createConstraintTransactionStarted.await();
// Now we can initiate the data-changing commit. It should then
// release the schema read lock, and block on the
// lockBlockingDataChangeTransaction.
createNodeCommitLatch.countDown();
// Now we can issue updates to the populator in the still ongoing population job.
// We do that by releasing the lock that is currently preventing our
// data-changing transaction from committing.
lockBlockingDataChangeTransaction.release();
// And we observe that our updating transaction has completed as well:
updatingTransaction.get();
// Now we can release the lock blocking the populator, allowing it to finish:
lockBlockingIndexPopulator.release();
// And return the future for examination:
return createConstraintTransaction;
}
Aggregations