Search in sources :

Example 1 with PLock

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());
}
Also used : PLock(org.olat.core.commons.services.lock.pessimistic.PLock) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 2 with PLock

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);
}
Also used : PLock(org.olat.core.commons.services.lock.pessimistic.PLock) Test(org.junit.Test)

Example 3 with PLock

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);
}
Also used : PLock(org.olat.core.commons.services.lock.pessimistic.PLock) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 4 with PLock

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);
}
Also used : PLock(org.olat.core.commons.services.lock.pessimistic.PLock) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 5 with PLock

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);
}
Also used : PLock(org.olat.core.commons.services.lock.pessimistic.PLock) ArrayList(java.util.ArrayList) Identity(org.olat.core.id.Identity) SecurityGroup(org.olat.basesecurity.SecurityGroup) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)14 PLock (org.olat.core.commons.services.lock.pessimistic.PLock)14 CountDownLatch (java.util.concurrent.CountDownLatch)8 ArrayList (java.util.ArrayList)6 SecurityGroup (org.olat.basesecurity.SecurityGroup)2 Identity (org.olat.core.id.Identity)2