Search in sources :

Example 1 with Lock

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);
}
Also used : Answer(org.mockito.stubbing.Answer) LockService(org.neo4j.kernel.impl.locking.LockService) Lock(org.neo4j.kernel.impl.locking.Lock) Before(org.junit.Before)

Example 2 with Lock

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);
    }
}
Also used : DefinedProperty(org.neo4j.kernel.api.properties.DefinedProperty) NodeState(org.neo4j.storageengine.api.txstate.NodeState) LabelNotFoundKernelException(org.neo4j.kernel.api.exceptions.LabelNotFoundKernelException) RelationshipState(org.neo4j.storageengine.api.txstate.RelationshipState) Lock(org.neo4j.kernel.impl.locking.Lock) PropertyKeyIdNotFoundKernelException(org.neo4j.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException) NodeItem(org.neo4j.storageengine.api.NodeItem) PropertyItem(org.neo4j.storageengine.api.PropertyItem) Relationship(org.neo4j.graphdb.Relationship) StorageProperty(org.neo4j.storageengine.api.StorageProperty) RelationshipItem(org.neo4j.storageengine.api.RelationshipItem)

Example 3 with Lock

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()));
}
Also used : PropertyItem(org.neo4j.storageengine.api.PropertyItem) Lock(org.neo4j.kernel.impl.locking.Lock)

Example 4 with Lock

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()));
}
Also used : PropertyItem(org.neo4j.storageengine.api.PropertyItem) Lock(org.neo4j.kernel.impl.locking.Lock)

Example 5 with Lock

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;
}
Also used : Transaction(org.neo4j.graphdb.Transaction) KernelTransaction(org.neo4j.kernel.api.KernelTransaction) CountDownLatch(java.util.concurrent.CountDownLatch) Lock(org.neo4j.kernel.impl.locking.Lock)

Aggregations

Lock (org.neo4j.kernel.impl.locking.Lock)7 PropertyItem (org.neo4j.storageengine.api.PropertyItem)4 Test (org.junit.Test)2 NodeItem (org.neo4j.storageengine.api.NodeItem)2 CountDownLatch (java.util.concurrent.CountDownLatch)1 Before (org.junit.Before)1 InOrder (org.mockito.InOrder)1 Answer (org.mockito.stubbing.Answer)1 Relationship (org.neo4j.graphdb.Relationship)1 Transaction (org.neo4j.graphdb.Transaction)1 KernelTransaction (org.neo4j.kernel.api.KernelTransaction)1 EntityNotFoundException (org.neo4j.kernel.api.exceptions.EntityNotFoundException)1 KernelException (org.neo4j.kernel.api.exceptions.KernelException)1 LabelNotFoundKernelException (org.neo4j.kernel.api.exceptions.LabelNotFoundKernelException)1 PropertyKeyIdNotFoundKernelException (org.neo4j.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException)1 NodeUpdates (org.neo4j.kernel.api.index.NodeUpdates)1 DefinedProperty (org.neo4j.kernel.api.properties.DefinedProperty)1 LockService (org.neo4j.kernel.impl.locking.LockService)1 RelationshipItem (org.neo4j.storageengine.api.RelationshipItem)1 StorageProperty (org.neo4j.storageengine.api.StorageProperty)1