private WorkerCommand<Void, Lock> acquireWriteLock( final Node resource ) { return state -> { try ( Transaction tx = db.beginTx() ) { return tx.acquireWriteLock( resource ); } }; }
@Test public void canAcquireWriteLock() { // when placeboTx.acquireWriteLock( resource ); // then verify( locks ).acquireExclusiveNodeLock( resource.getId() ); }
tx.acquireWriteLock( database.getNodeById( nodeId ) ); tx.success();
tx.acquireWriteLock( commonNode ); Index<Node> index = graphDb.index().forNodes( "uuids" ); final Node existing = index.get( "uuid", uuid ).getSingle();
@Test public void nestedTransactionCanAcquireLocksFromTransactionObject() throws Exception { // given Node resource = createNode(); try ( Transaction outerTx = db.beginTx(); Transaction nestedTx = db.beginTx() ) { assertNotSame( outerTx, nestedTx ); try ( OtherThreadExecutor<Void> otherThread = new OtherThreadExecutor<>( "other thread", null ) ) { // when Lock lock = nestedTx.acquireWriteLock( resource ); Future<Lock> future = tryToAcquireSameLockOnAnotherThread( resource, otherThread ); // then acquireOnOtherThreadTimesOut( future ); // and when lock.release(); //then assertNotNull( future.get() ); } } }
@Test public void canOnlyReleaseOnce() { Node node = getGraphDb().createNode(); tx.success(); Transaction current = tx.begin(); Lock nodeLock = current.acquireWriteLock( node ); nodeLock.release(); try { nodeLock.release(); fail( "Shouldn't be able to release more than once" ); } catch ( IllegalStateException e ) { // Good } }
@Test public void releaseReleaseManually() throws Exception { String key = "name"; Node node = getGraphDb().createNode(); tx.success(); Transaction current = tx.begin(); Lock nodeLock = current.acquireWriteLock( node ); worker.beginTx(); try { worker.setProperty( node, key, "ksjd" ); fail( "Shouldn't be able to grab it" ); } catch ( Exception ignored ) { } nodeLock.release(); worker.setProperty( node, key, "yo" ); try { worker.finishTx(); } catch ( ExecutionException e ) { // Ok, interrupting the thread while it's waiting for a lock will lead to tx failure. } }
@Test public void transactionShouldReleaseLocksWhenGraphDbIsBeingShutdown() { // GIVEN final Locks locks = db.getDependencyResolver().resolveDependency( Locks.class ); assertEquals( 0, lockCount( locks ) ); Exception exceptionThrownByTxClose = null; // WHEN try ( Transaction tx = db.beginTx() ) { Node node = db.createNode(); tx.acquireWriteLock( node ); assertThat( lockCount( locks ), greaterThanOrEqualTo( 1 ) ); db.shutdown(); db.createNode(); tx.success(); } catch ( Exception e ) { exceptionThrownByTxClose = e; } // THEN assertThat( exceptionThrownByTxClose, instanceOf( DatabaseShutdownException.class ) ); assertFalse( db.isAvailable( 1 ) ); assertEquals( 0, lockCount( locks ) ); }
@Test public void makeSureNodeStaysLockedEvenAfterManualRelease() throws Exception { String key = "name"; Node node = getGraphDb().createNode(); tx.success(); Transaction current = tx.begin(); Lock nodeLock = current.acquireWriteLock( node ); node.setProperty( key, "value" ); nodeLock.release(); worker.beginTx(); try { worker.setProperty( node, key, "ksjd" ); fail( "Shouldn't be able to grab it" ); } catch ( Exception ignored ) { } tx.success(); try { worker.finishTx(); } catch ( ExecutionException e ) { // Ok, interrupting the thread while it's waiting for a lock will lead to tx failure. } }
private void retry(ExecutionContext executionContext, Function<ExecutionContext, Object> work, Long times){ TransactionTemplate template = new TransactionTemplate().retries(times.intValue()).backoff(10, TimeUnit.MILLISECONDS); template.with(db).execute(tx -> { Lock lock = tx.acquireWriteLock(executionContext.propertyContainer); work.apply(executionContext); lock.release(); }); }
@Procedure(mode = Mode.WRITE) @Description("apoc.lock.nodes([nodes]) acquires a write lock on the given nodes") public void nodes(@Name("nodes") List<Node> nodes) { try (Transaction tx = db.beginTx()) { for (Node node : nodes) { tx.acquireWriteLock(node); } tx.success(); } }
@Procedure(mode = Mode.WRITE) @Description("apoc.lock.rels([relationships]) acquires a write lock on the given relationship") public void rels(@Name("rels") List<Relationship> rels) { try (Transaction tx = db.beginTx()) { for (Relationship rel : rels) { tx.acquireWriteLock(rel); } tx.success(); } }
@Procedure(mode = Mode.WRITE) @Description("apoc.lock.all([nodes],[relationships]) acquires a write lock on the given nodes and relationships") public void all(@Name("nodes") List<Node> nodes, @Name("rels") List<Relationship> rels) { try (Transaction tx = db.beginTx()) { for (Node node : nodes) { tx.acquireWriteLock(node); } for (Relationship rel : rels) { tx.acquireReadLock(rel); } tx.success(); } } @Procedure(mode = Mode.WRITE)
Transaction tx = graphDb.beginTx(); try { tx.acquireWriteLock( lockNode ); // do something tx.success(); } finally { tx.finish(); }
private Node getInstant(TimeInstant timeInstant, ChildNotFoundPolicy childNotFoundPolicy) { Node instant = null; try (Transaction tx = database.beginTx()) { DateTime dateTime = new DateTime(timeInstant.getTime(), timeInstant.getTimezone()); Node timeRoot = getTimeRoot(false); if (timeRoot != null) { tx.acquireWriteLock(timeRoot); instant = getInstant(timeRoot, dateTime, timeInstant.getResolution(), childNotFoundPolicy); } tx.success(); } return instant; }
/** * {@inheritDoc} */ @Override public Node getOrCreateInstant(TimeInstant timeInstant) { Node instant; DateTime dateTime = new DateTime(timeInstant.getTime(), timeInstant.getTimezone()); try (Transaction tx = database.beginTx()) { Node timeRoot = getTimeRoot(true); tx.acquireWriteLock(timeRoot); instant = getOrCreateInstant(timeRoot, dateTime, timeInstant.getResolution()); tx.success(); } return instant; }
tx.acquireWriteLock(root); //We should not have to do this, temp workaround for https://github.com/neo4j/neo4j/issues/2677 Relationship nextRel = root.getSingleRelationship(Relationships._GA_CHANGEFEED_NEXT_CHANGE, Direction.OUTGOING);
/** * Record (persist) a set of changes. * * @param changeSet to record. */ protected void recordChanges(ChangeSet changeSet) { try (Transaction tx = database.beginTx()) { tx.acquireWriteLock(getRoot()); Node changeNode = database.createNode(_GA_ChangeSet); changeNode.setProperty(UUID, changeSet.getUuid()); changeNode.setProperty(TIMESTAMP, changeSet.getTimestamp()); changeNode.setProperty(CHANGES, changeSet.getChangesAsArray()); Relationship firstChangeRel = getRoot().getSingleRelationship(Relationships._GA_CHANGEFEED_NEXT_CHANGE, Direction.OUTGOING); if (firstChangeRel == null) { //First changeSet recorded, create an _GA_CHANGEFEED_OLDEST_CHANGE relation from the root to it getRoot().createRelationshipTo(changeNode, Relationships._GA_CHANGEFEED_OLDEST_CHANGE); } else { Node firstChange = firstChangeRel.getEndNode(); tx.acquireWriteLock(firstChange); changeNode.createRelationshipTo(firstChange, Relationships._GA_CHANGEFEED_NEXT_CHANGE); firstChangeRel.delete(); } getRoot().createRelationshipTo(changeNode, Relationships._GA_CHANGEFEED_NEXT_CHANGE); tx.success(); } }
lock = tx.acquireWriteLock( sequence ); long nextValue = updateSequenceValue( request.getKey(), sequence, request.getIncrement() ); tx.success();
public Node getOrCreateUserPessimistically( String username, GraphDatabaseService graphDb, Node lockNode ) { // START SNIPPET: pessimisticLocking try ( Transaction tx = graphDb.beginTx() ) { Index<Node> usersIndex = graphDb.index().forNodes( "users" ); Node userNode = usersIndex.get( "name", username ).getSingle(); if ( userNode != null ) { return userNode; } tx.acquireWriteLock( lockNode ); userNode = usersIndex.get( "name", username ).getSingle(); if ( userNode == null ) { userNode = graphDb.createNode( Label.label( "User" ) ); usersIndex.add( userNode, "name", username ); userNode.setProperty( "name", username ); } tx.success(); return userNode; } // END SNIPPET: pessimisticLocking }