Search in sources :

Example 1 with Lock

use of org.neo4j.lock.Lock in project neo4j by neo4j.

the class FullScanStoreViewTest method shouldLockNodesWhileReadingThem.

@Test
void shouldLockNodesWhileReadingThem() {
    // given
    StoreScan storeScan = storeView.visitNodes(new int[] { labelId }, id -> id == propertyKeyId, new TestPropertyScanConsumer(), null, false, true, NULL, INSTANCE);
    // when
    storeScan.run(NO_EXTERNAL_UPDATES);
    // then
    assertThat(lockMocks.size()).as("allocated locks: " + lockMocks.keySet()).isGreaterThanOrEqualTo(2);
    Lock lock0 = lockMocks.get(0L);
    Lock lock1 = lockMocks.get(1L);
    assertNotNull(lock0, "Lock[node=0] never acquired");
    assertNotNull(lock1, "Lock[node=1] never acquired");
    InOrder order = inOrder(locks, lock0, lock1);
    order.verify(locks).acquireNodeLock(0, SHARED);
    order.verify(lock0).release();
    order.verify(locks).acquireNodeLock(1, SHARED);
    order.verify(lock1).release();
}
Also used : InOrder(org.mockito.InOrder) StoreScan(org.neo4j.kernel.impl.api.index.StoreScan) Lock(org.neo4j.lock.Lock) Test(org.junit.jupiter.api.Test)

Example 2 with Lock

use of org.neo4j.lock.Lock in project neo4j by neo4j.

the class FullScanStoreViewTest method shouldLockRelationshipsWhileReadingThem.

@Test
void shouldLockRelationshipsWhileReadingThem() throws Exception {
    // given
    StoreScan storeScan = storeView.visitRelationships(new int[] { relTypeId }, id -> id == relPropertyKeyId, new TestPropertyScanConsumer(), null, true, true, NULL, INSTANCE);
    // when
    storeScan.run(NO_EXTERNAL_UPDATES);
    // then
    assertThat(lockMocks.size()).as("allocated locks: " + lockMocks.keySet()).isGreaterThanOrEqualTo(2);
    Lock lock0 = lockMocks.get(0L);
    Lock lock1 = lockMocks.get(1L);
    assertNotNull(lock0, "Lock[relationship=0] never acquired");
    assertNotNull(lock1, "Lock[relationship=1] never acquired");
    InOrder order = inOrder(locks, lock0, lock1);
    order.verify(locks).acquireRelationshipLock(0, SHARED);
    order.verify(lock0).release();
    order.verify(locks).acquireRelationshipLock(1, SHARED);
    order.verify(lock1).release();
}
Also used : InOrder(org.mockito.InOrder) StoreScan(org.neo4j.kernel.impl.api.index.StoreScan) Lock(org.neo4j.lock.Lock) Test(org.junit.jupiter.api.Test)

Example 3 with Lock

use of org.neo4j.lock.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(() -> {
        try (Transaction tx = db.beginTx()) {
            for (Action action : actions) {
                action.accept(tx);
            }
            tx.commit();
            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.EXCLUSIVE);
    // 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.EXCLUSIVE);
    // 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(() -> 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) CountDownLatch(java.util.concurrent.CountDownLatch) Lock(org.neo4j.lock.Lock)

Example 4 with Lock

use of org.neo4j.lock.Lock in project neo4j by neo4j.

the class GenerateIndexUpdatesStep method process.

@Override
protected void process(long[] entityIds, BatchSender sender, CursorContext cursorContext) throws Exception {
    GeneratedIndexUpdates updates = new GeneratedIndexUpdates(gatherPropertyUpdates, gatherTokenUpdates);
    try (CURSOR nodeCursor = entityCursorBehaviour.allocateEntityScanCursor(cursorContext);
        StoragePropertyCursor propertyCursor = reader.allocatePropertyCursor(cursorContext, memoryTracker)) {
        for (long entityId : entityIds) {
            try (Lock ignored = lockFunction.apply(entityId)) {
                nodeCursor.single(entityId);
                if (nodeCursor.next()) {
                    generateUpdates(updates, nodeCursor, propertyCursor);
                    if (updates.propertiesByteSize > maxBatchSizeBytes) {
                        batchDone(updates, sender);
                        updates = new GeneratedIndexUpdates(gatherPropertyUpdates, gatherTokenUpdates);
                    }
                }
            }
        }
    }
    batchDone(updates, sender);
}
Also used : StoragePropertyCursor(org.neo4j.storageengine.api.StoragePropertyCursor) Lock(org.neo4j.lock.Lock)

Example 5 with Lock

use of org.neo4j.lock.Lock in project neo4j by neo4j.

the class LockGroupTest method shouldReleaseAllLocksWhenExitingTheLockGroupRegion.

@Test
void shouldReleaseAllLocksWhenExitingTheLockGroupRegion() {
    // given
    Lock lock1 = mock(Lock.class);
    Lock lock2 = mock(Lock.class);
    Lock lock3 = mock(Lock.class);
    // when
    try (LockGroup locks = new LockGroup()) {
        locks.add(lock1);
        locks.add(lock2);
        locks.add(lock3);
    }
    // then
    verify(lock1).release();
    verify(lock2).release();
    verify(lock3).release();
}
Also used : LockGroup(org.neo4j.lock.LockGroup) Lock(org.neo4j.lock.Lock) Test(org.junit.jupiter.api.Test)

Aggregations

Lock (org.neo4j.lock.Lock)6 Test (org.junit.jupiter.api.Test)4 InOrder (org.mockito.InOrder)3 StoreScan (org.neo4j.kernel.impl.api.index.StoreScan)2 IOException (java.io.IOException)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 Transaction (org.neo4j.graphdb.Transaction)1 NodeRecord (org.neo4j.kernel.impl.store.record.NodeRecord)1 LockGroup (org.neo4j.lock.LockGroup)1 LockService (org.neo4j.lock.LockService)1 CommandsToApply (org.neo4j.storageengine.api.CommandsToApply)1 StorageCommand (org.neo4j.storageengine.api.StorageCommand)1 StoragePropertyCursor (org.neo4j.storageengine.api.StoragePropertyCursor)1