use of org.olat.core.commons.services.lock.pessimistic.PLock in project OpenOLAT by OpenOLAT.
the class PLockTest method testLockWaitTimout.
@Test
public void testLockWaitTimout() {
// Ignore Test if DB is PostgreSQL. PostgreSQL has not lock timeout
assumeTrue(!isPostgresqlConfigured() && !isOracleConfigured());
final String asset = "testLockWaitTimout";
log.info("testing if holding a lock timeouts");
// make sure all three row entries for the locks are created, otherwise the system-wide locking
// applied on lock-row-creation cannot support row-level-locking by definition.
PLock pc3 = pessimisticLockManager.findOrPersistPLock("blibli");
assertNotNull(pc3);
dbInstance.closeSession();
/**
* t1 t2
* .. bli
* .. ..
* .. ..
* .. ..
* bli ..
* ..
* ..
* .... hold for longer than 30 secs
*/
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
final CountDownLatch finishCount = new CountDownLatch(2);
// t1
new Thread(new Runnable() {
public void run() {
try {
sleep(500);
PLock p3 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(p3);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
finishCount.countDown();
try {
dbInstance.closeSession();
} catch (Exception e) {
// ignore
}
}
}
}).start();
// t2
new Thread(new Runnable() {
public void run() {
try {
PLock p2 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(p2);
sleep(55000);
// holding the lock for more than the transaction timeout
// (normally 30secs, configured where? hib) should cause a lock timeout
// if the db is configured so (innodb_lock_wait_timeout).
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
finishCount.countDown();
try {
dbInstance.closeSession();
} catch (Exception e) {
// ignore
}
}
}
}).start();
// sleep until t1 and t2 should have terminated/excepted
try {
log.info("Sleep 55s");
finishCount.await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail("");
}
Assert.assertEquals("expected a lock wait timeout exceeded exception", 1, exceptionHolder.size());
}
use of org.olat.core.commons.services.lock.pessimistic.PLock in project OpenOLAT by OpenOLAT.
the class PLockTest method testReentrantLock.
@Test
public void testReentrantLock() {
long start = System.currentTimeMillis();
String asset = "p1";
// make sure the lock is created first
PLock pc = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(pc);
dbInstance.closeSession();
// test double acquisition within same transaction
PLock pc1 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(pc1);
PLock pc2 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(pc2);
dbInstance.closeSession();
// and without explicit transaction boundary.
PLock p1 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(p1);
PLock p2 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(p2);
long stop = System.currentTimeMillis();
long diff = stop - start;
assertTrue("5 select's took longer than 10 seconds -> deadlock / lock timeout ? dur in ms was:" + diff, diff < 10000);
}
use of org.olat.core.commons.services.lock.pessimistic.PLock in project OpenOLAT by OpenOLAT.
the class PLockTest method testReentrantLock2Threads.
/**
* T1 T2
*/
@Test
public void testReentrantLock2Threads() {
final String asset = "p1-2";
// make sure the lock is created first
PLock pc = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(pc);
dbInstance.closeSession();
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
final CountDownLatch finishCount = new CountDownLatch(2);
// thread 1
new Thread(new Runnable() {
public void run() {
try {
PLock pc1 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(pc1);
log.info("Thread-1: got PLock pc1=" + pc1);
log.info("Thread-1: sleep 1sec");
sleep(1000);
PLock pc2 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(pc2);
log.info("Thread-1: got PLock pc2=" + pc2);
log.info("Thread-1: finished");
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
finishCount.countDown();
try {
dbInstance.commitAndCloseSession();
} catch (Exception e) {
// ignore
}
}
}
}).start();
// thread 2
new Thread(new Runnable() {
public void run() {
try {
log.info("Thread-2: sleep 0.5sec");
sleep(500);
log.info("Thread-2: try to get PLock...");
PLock p1 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(p1);
log.info("Thread-2: got PLock p1=" + p1);
log.info("Thread-2: sleep 1sec");
sleep(1000);
PLock p2 = pessimisticLockManager.findOrPersistPLock(asset);
assertNotNull(p2);
log.info("Thread-1: got PLock p2=" + p2);
log.info("Thread-1: finished");
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
finishCount.countDown();
try {
dbInstance.commitAndCloseSession();
} catch (Exception e) {
// ignore
}
}
}
}).start();
// sleep until t1 and t2 should have terminated/excepted
try {
finishCount.await(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail("Test takes too long (more than 60s)");
}
// if not -> they are in deadlock and the db did not detect it
for (Exception exception : exceptionHolder) {
log.info("exception: " + exception.getMessage());
exception.printStackTrace();
}
assertTrue("exception in test => see sysout", exceptionHolder.size() == 0);
}
use of org.olat.core.commons.services.lock.pessimistic.PLock in project OpenOLAT by OpenOLAT.
the class PLockTest method testDeadLockTimeout.
@Test
public void testDeadLockTimeout() {
log.info("testing if deadlock detection and handling is supported");
// make sure all three row entries for the locks are created, otherwise the system-wide locking
// applied on lock-row-creation cannot support row-level-locking by definition.
PLock pc1 = pessimisticLockManager.findOrPersistPLock("blabla");
assertNotNull(pc1);
PLock pc2 = pessimisticLockManager.findOrPersistPLock("blublu");
assertNotNull(pc2);
PLock pc3 = pessimisticLockManager.findOrPersistPLock("blibli");
assertNotNull(pc3);
dbInstance.closeSession();
/**
* t1 t2
* bla bli
* .. ..
* .. ..
* .. ..
* bli ..
* ..
* ..
* bla
* -> deadlock! t2 waits on bla (already acquired by t1, but t1 waits on bli, already acquired by t2)
*/
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>(1));
final CountDownLatch finishCount = new CountDownLatch(2);
// t1
new Thread(new Runnable() {
public void run() {
try {
PLock p1 = pessimisticLockManager.findOrPersistPLock("blabla");
assertNotNull(p1);
sleep(250);
// now try to acquire blibli but that fails, since blibli is already locked by thread 2.
// but thread 2 cannot continue either, since it is waiting for lock blabla, which is already hold by thread 1
// -> deadlock
PLock p3 = pessimisticLockManager.findOrPersistPLock("blibli");
assertNotNull(p3);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
dbInstance.closeSession();
} catch (Exception e) {
// ignore
}
finishCount.countDown();
}
}
}).start();
// t2
new Thread(new Runnable() {
public void run() {
try {
PLock p2 = pessimisticLockManager.findOrPersistPLock("blibli");
assertNotNull(p2);
sleep(500);
PLock p3 = pessimisticLockManager.findOrPersistPLock("blabla");
assertNotNull(p3);
} catch (Exception e) {
exceptionHolder.add(e);
} finally {
try {
dbInstance.closeSession();
} catch (Exception e) {
// ignore
}
finishCount.countDown();
}
}
}).start();
// sleep until t1 and t2 should have terminated/excepted
try {
finishCount.await(8, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Assert.fail("Takes too long (more than 8sec)");
}
// if not -> they are in deadlock and the db did not detect it
for (Exception exception : exceptionHolder) {
log.error("exception: ", exception);
}
assertTrue("expected a deadlock exception, but got none", exceptionHolder.size() > 0);
}
use of org.olat.core.commons.services.lock.pessimistic.PLock in project OpenOLAT by OpenOLAT.
the class PLockTest method testSync.
@Test
public void testSync() {
log.info("testing enrollment");
// ------------------ now check with lock -------------------
// create a group
// create users
final List<Identity> identities = new ArrayList<Identity>();
for (int i = 0; i < MAX_COUNT + MAX_USERS_MORE; i++) {
Identity id = JunitTestHelper.createAndPersistIdentityAsUser("u-" + i + "-" + UUID.randomUUID().toString());
identities.add(id);
log.info("testSync: Identity=" + id.getName() + " created");
}
dbInstance.closeSession();
final SecurityGroup group2 = BaseSecurityManager.getInstance().createAndPersistSecurityGroup();
// make sure the lock has been written to the disk (tests for createOrFind see other methods)
dbInstance.closeSession();
// prepare threads
int numOfThreads = MAX_COUNT + MAX_USERS_MORE;
final CountDownLatch finishCount = new CountDownLatch(numOfThreads);
// try to enrol all in the same group
for (int i = 0; i < numOfThreads; i++) {
final int j = i;
new Thread(new Runnable() {
public void run() {
try {
log.info("testSync: thread started j=" + j);
Identity id = identities.get(j);
//
PLock p2 = pessimisticLockManager.findOrPersistPLock("befinsert");
assertNotNull(p2);
doNoLockingEnrol(id, group2);
dbInstance.commit();
dbInstance.closeSession();
} catch (Exception e) {
e.printStackTrace();
} finally {
finishCount.countDown();
}
}
}).start();
}
try {
finishCount.await(120, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("", e);
}
// now count
dbInstance.closeSession();
int cnt2 = BaseSecurityManager.getInstance().countIdentitiesOfSecurityGroup(group2);
assertTrue("cnt should be smaller or eq than allowed since synced with select for update. cnt:" + cnt2 + ", max " + MAX_COUNT, cnt2 <= MAX_COUNT);
assertTrue("cnt should be eq to allowed since synced with select for update. cnt:" + cnt2 + ", max " + MAX_COUNT, cnt2 == MAX_COUNT);
log.info("cnt lock " + cnt2);
}
Aggregations