예제 #1
0
  @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);
  }
예제 #2
0
  @Test
  public void testNestedLockingSupported() {
    log.info("testing if nested locking 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();

    final List<Long> holder = new ArrayList<Long>(1);
    // first thread acquires the two locks and waits and continues holding the lock for some time.
    PLock p1 = pessimisticLockManager.findOrPersistPLock("blabla");
    assertNotNull(p1);
    PLock p3 = pessimisticLockManager.findOrPersistPLock("blibli");
    assertNotNull(p3);

    new Thread(
            new Runnable() {
              public void run() {
                PLock p2 = pessimisticLockManager.findOrPersistPLock("blibli");
                assertNotNull(p2);
                long p2Acquired = System.nanoTime();
                holder.add(new Long(p2Acquired));
                dbInstance.closeSession();
              }
            })
        .start();
    sleep(500);
    boolean acOk = holder.size() == 0;
    // the commit will drop the lock on blibli d
    dbInstance.closeSession();
    sleep(500);
    boolean acNowOk = holder.size() == 1;

    // if row locking is not supported, then the timestamp when p2 has been acquired will be shortly
    // -after- p1 has been released
    assertTrue("since holding the blabla lock, no other may acquire it", acOk);
    assertTrue(
        "after having released the blabla lock, a next waiting thread must have acquired it after some time",
        acNowOk);
  }
예제 #3
0
  @Test
  public void testSingleRowLockingSupported() {
    log.info(
        "testing if one lock only locks the given row and not the complete table (test whether the database supports rowlocking)");
    // make sure both 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");
    Assert.assertNotNull(pc1);
    PLock pc2 = pessimisticLockManager.findOrPersistPLock("blublu");
    Assert.assertNotNull(pc2);
    dbInstance.closeSession();

    final List<Long> holder = new ArrayList<Long>(1);
    // first thread acquires the lock and waits and continues holding the lock for some time.
    PLock p1 = pessimisticLockManager.findOrPersistPLock("blabla");
    Assert.assertNotNull(p1);

    new Thread(
            new Runnable() {
              public void run() {
                PLock p2 = pessimisticLockManager.findOrPersistPLock("blublu");
                assertNotNull(p2);
                long p2Acquired = System.nanoTime();
                holder.add(new Long(p2Acquired));
                dbInstance.closeSession();
              }
            })
        .start();

    sleep(500);
    long p1AboutToRelease = System.nanoTime();
    dbInstance.closeSession();

    // if row locking is not supported, then the timestamp when p2 has been acquired will be shortly
    // -after- p1 has been released
    boolean singleRowLockingOk = holder.size() > 0 && holder.get(0).longValue() < p1AboutToRelease;
    assertTrue(
        "the database does not seem to support row locking when executing 'select for update', critical for performance!, ",
        singleRowLockingOk);
  }
예제 #4
0
  /** 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);
  }
예제 #5
0
  @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);
  }
예제 #6
0
  @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());
  }