use of org.neo4j.test.OtherThreadExecutor in project neo4j by neo4j.
the class NestedTransactionLocksIT method nestedTransactionCanAcquireLocksFromTransactionObject.
@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());
}
}
}
use of org.neo4j.test.OtherThreadExecutor in project neo4j by neo4j.
the class ManyPropertyKeysIT method concurrently_creating_same_property_key_in_different_transactions_should_end_up_with_same_key_id.
@Test
public void concurrently_creating_same_property_key_in_different_transactions_should_end_up_with_same_key_id() throws Exception {
// GIVEN
GraphDatabaseAPI db = (GraphDatabaseAPI) new TestGraphDatabaseFactory().newImpermanentDatabase();
OtherThreadExecutor<WorkerState> worker1 = new OtherThreadExecutor<>("w1", new WorkerState(db));
OtherThreadExecutor<WorkerState> worker2 = new OtherThreadExecutor<>("w2", new WorkerState(db));
worker1.execute(new BeginTx());
worker2.execute(new BeginTx());
// WHEN
String key = "mykey";
worker1.execute(new CreateNodeAndSetProperty(key));
worker2.execute(new CreateNodeAndSetProperty(key));
worker1.execute(new FinishTx());
worker2.execute(new FinishTx());
worker1.close();
worker2.close();
// THEN
assertEquals(1, propertyKeyCount(db));
db.shutdown();
}
use of org.neo4j.test.OtherThreadExecutor in project neo4j by neo4j.
the class TransactionConstraintsIT method deadlockDetectionBetween.
private void deadlockDetectionBetween(HighlyAvailableGraphDatabase slave1, final HighlyAvailableGraphDatabase slave2) throws Exception {
// GIVEN
// -- two members acquiring a read lock on the same entity
final Node commonNode;
try (Transaction tx = slave1.beginTx()) {
commonNode = slave1.createNode();
tx.success();
}
OtherThreadExecutor<HighlyAvailableGraphDatabase> thread2 = new OtherThreadExecutor<>("T2", slave2);
Transaction tx1 = slave1.beginTx();
Transaction tx2 = thread2.execute(new BeginTx());
tx1.acquireReadLock(commonNode);
thread2.execute(state -> tx2.acquireReadLock(commonNode));
// -- and one of them wanting (and awaiting) to upgrade its read lock to a write lock
Future<Lock> writeLockFuture = thread2.executeDontWait(state -> {
try (Transaction ignored = tx2) {
return tx2.acquireWriteLock(commonNode);
}
});
for (int i = 0; i < 10; i++) {
thread2.waitUntilThreadState(Thread.State.TIMED_WAITING, Thread.State.WAITING);
Thread.sleep(2);
}
try (// Close transaction no matter what happens
Transaction ignored = tx1) {
// WHEN
tx1.acquireWriteLock(commonNode);
// -- Deadlock detection is non-deterministic, so either the slave or the master will detect it
writeLockFuture.get();
fail("Deadlock exception should have been thrown");
} catch (DeadlockDetectedException e) {
// THEN -- deadlock should be avoided with this exception
} catch (ExecutionException e) {
// OR -- the tx2 thread fails with executionexception, caused by deadlock on its end
assertThat(e.getCause(), instanceOf(DeadlockDetectedException.class));
}
thread2.close();
}
use of org.neo4j.test.OtherThreadExecutor in project neo4j by neo4j.
the class IndexOperationsIT method put_if_absent_works_across_instances.
@Test
public void put_if_absent_works_across_instances() throws Exception {
// GIVEN
// -- two instances, each begin a transaction
String key = "key2", value = "value2";
HighlyAvailableGraphDatabase db1 = cluster.getMaster(), db2 = cluster.getAnySlave();
long node = createNode(db1, key, value, false);
cluster.sync();
OtherThreadExecutor<HighlyAvailableGraphDatabase> w1 = new OtherThreadExecutor<>("w1", db1);
OtherThreadExecutor<HighlyAvailableGraphDatabase> w2 = new OtherThreadExecutor<>("w2", db2);
Transaction tx1 = w1.execute(new BeginTx());
Transaction tx2 = w2.execute(new BeginTx());
// WHEN
// -- second instance does putIfAbsent --> null
assertNull(w2.execute(new PutIfAbsent(node, key, value)));
// -- get a future to first instance putIfAbsent. Wait for it to go and await the lock
Future<Node> w1Future = w1.executeDontWait(new PutIfAbsent(node, key, value));
w1.waitUntilWaiting();
// -- second instance completes tx
w2.execute(new FinishTx(tx2, true));
tx2.success();
tx2.close();
// THEN
// -- first instance can complete the future with a non-null result
assertNotNull(w1Future.get());
w1.execute(new FinishTx(tx1, true));
// -- assert the index has got one entry and both instances have the same data
assertNodeAndIndexingExists(db1, node, key, value);
assertNodeAndIndexingExists(db2, node, key, value);
cluster.sync();
assertNodeAndIndexingExists(cluster.getAnySlave(db1, db2), node, key, value);
w2.close();
w1.close();
}
use of org.neo4j.test.OtherThreadExecutor in project neo4j by neo4j.
the class DynamicTaskExecutorTest method shouldLetShutdownCompleteInEventOfPanic.
@Test
public void shouldLetShutdownCompleteInEventOfPanic() throws Exception {
// GIVEN
final TaskExecutor<Void> executor = new DynamicTaskExecutor<>(2, 0, 10, PARK, getClass().getSimpleName());
IOException exception = new IOException("Failure");
// WHEN
FailingTask failingTask = new FailingTask(exception);
executor.submit(failingTask);
failingTask.latch.await();
// WHEN
try (OtherThreadExecutor<Void> closer = new OtherThreadExecutor<>("closer", null)) {
Future<Void> shutdown = closer.executeDontWait(new WorkerCommand<Void, Void>() {
@Override
public Void doWork(Void state) throws Exception {
executor.close();
return null;
}
});
while (!closer.waitUntilWaiting().isAt(DynamicTaskExecutor.class, "close")) {
Thread.sleep(10);
}
// Here we've got a shutdown call stuck awaiting queue to be empty (since true was passed in)
// at the same time we've got a FailingTask ready to throw its exception and another task
// sitting in the queue after it. Now make the task throw that exception.
failingTask.latch.release();
// Some time after throwing this, the shutdown request should have been completed.
shutdown.get();
}
}
Aggregations