Skip to content

Commit

Permalink
implementing read locks (#601)
Browse files Browse the repository at this point in the history
* implementing read locks

* fixing failing test
  • Loading branch information
sarmbruster committed Sep 19, 2017
1 parent 341d1ea commit 61692cb
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/main/java/apoc/lock/Lock.java
Expand Up @@ -40,6 +40,19 @@ public void nodes(@Name("nodes") List<Node> nodes) {
tx.success();
}
}

@Procedure(mode = Mode.READ, name = "apoc.lock.read.nodes")
@Description("apoc.lock.read.nodes([nodes]) acquires a read lock on the given nodes")
public void readLockOnNodes(@Name("nodes") List<Node> nodes) {
try (Transaction tx = db.beginTx()) {
for (Node node : nodes) {
tx.acquireReadLock(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) {
Expand All @@ -50,4 +63,15 @@ public void rels(@Name("rels") List<Relationship> rels) {
tx.success();
}
}

@Procedure(mode = Mode.READ, name = "apoc.lock.read.rels")
@Description("apoc.lock.read.rels([relationships]) acquires a read lock on the given relationship")
public void readLocksOnRels(@Name("rels") List<Relationship> rels) {
try (Transaction tx = db.beginTx()) {
for (Relationship rel : rels) {
tx.acquireReadLock(rel);
}
tx.success();
}
}
}
62 changes: 62 additions & 0 deletions src/test/java/apoc/lock/LockTest.java
@@ -0,0 +1,62 @@
package apoc.lock;

import apoc.util.TestUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.helpers.collection.Iterators;
import org.neo4j.test.TestGraphDatabaseFactory;

import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertEquals;

public class LockTest {

private static GraphDatabaseService db;

@BeforeClass
public static void setUp() throws Exception {
db = new TestGraphDatabaseFactory().newImpermanentDatabase();
TestUtil.registerProcedure(db, Lock.class);
}

@AfterClass
public static void tearDown() {
db.shutdown();
}

@Test
public void shouldReadLockBlockAWrite() throws Exception {

Node node;
try (Transaction tx = db.beginTx()) {
node = db.createNode();
tx.success();
}

try (Transaction tx = db.beginTx()) {
final Object n = Iterators.single(db.execute("match (n) CALL apoc.lock.read.nodes([n]) return n").columnAs("n"));
assertEquals(n, node);

final Thread thread = new Thread(() -> {
db.execute("match (n) delete n");

});
thread.start();
thread.join(TimeUnit.SECONDS.toMillis(1));

// the blocked thread didn't do any work, so we still have nodes
long count = Iterators.count(db.execute("match (n) return n").columnAs("n"));
assertEquals(1, count);

tx.success();
}



}
}
4 changes: 4 additions & 0 deletions src/test/java/apoc/schema/SchemasTest.java
Expand Up @@ -295,6 +295,10 @@ public void testIndexNotExists() {
public void testIndexOnMultipleProperties() {
ignoreException(() -> {
db.execute("CREATE INDEX ON :Foo(bar, foo)").close();
try (Transaction tx = db.beginTx()) {
db.schema().awaitIndexesOnline(1, TimeUnit.SECONDS);
tx.success();
}
testResult(db, "CALL apoc.schema.nodes()", (result) -> {
// Get the index info
Map<String, Object> r = result.next();
Expand Down

0 comments on commit 61692cb

Please sign in to comment.