final AtomicBoolean locked = new AtomicBoolean(false);
final AtomicBoolean error = new AtomicBoolean(false);
final CountDownLatch latch1 = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
Connection conn1 = connectionManager.connect().get();
Connection conn2 = connectionManager.connect().get();
logger.debug("Obtained connection managers");
// Get lock on locks table
conn1.beginTransaction();
TestUtils.selectForUpdate(conn1, new DbListener<ResultSet>() {
public void onCompletion(DbFuture<ResultSet> future) throws Exception {
logger.debug("In first callback");
locked.set(true);
invoked[0] = true;
latch1.countDown();
}
}).get();
logger.debug("Obtained lock on locks table");
// Try to get lock with second connection
conn2.beginTransaction();
DbFuture<ResultSet> future = TestUtils.selectForUpdate(conn2, new DbListener<ResultSet>() {
public void onCompletion(DbFuture<ResultSet> future) throws Exception {
logger.debug("In second callback");
invoked[1] = true;
if (!locked.get()) {
error.set(true);
}
latch2.countDown();
}
});
logger.debug("Select for update called with second connection, should be blocking");
assertTrue(latch1.await(1, TimeUnit.SECONDS));
assertTrue(invoked[0], "First SELECT FOR UPDATE callback should have been invoked");
assertTrue(locked.get(), "locked should be set");
assertFalse(invoked[1], "Second SELCT FOR UPDATE callback should not have been invoked yet");
assertFalse(error.get());
conn1.rollback().get();
logger.debug("Released first lock");
future.get();
logger.debug("Second SELECT FOR UPDATE completed");
assertTrue(latch2.await(1, TimeUnit.SECONDS));
assertTrue(invoked[1]);
assertFalse(error.get(), "An error occurred during SELECT FOR UPDATE");
conn2.rollback().get();
logger.debug("Released second lock");
// Close connections
logger.debug("Closing connections");
conn1.close(true).get();
logger.debug("Closed connection 1");
conn2.close(true).get();
logger.debug("Closed connection 2");
}