HHH-6843 Updating LockTest to be less aggressive and more inline with actual isolation requirements
The actual changes are in the refactoring of LockTest#testContendedPessimisticLock which got split up into several methods and has the asserts changed The formatting changes fix some generics warning and indentation. Used to be two separate commits, but after some git screw-up became one now
This commit is contained in:
parent
c520a81990
commit
ab111b6018
|
@ -23,14 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.ejb.test.lock;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.LockTimeoutException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.QueryTimeoutException;
|
||||
|
||||
import java.lang.RuntimeException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -38,8 +30,15 @@ import java.util.concurrent.Callable;
|
|||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.LockTimeoutException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.QueryTimeoutException;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.dialect.HSQLDialect;
|
||||
import org.hibernate.dialect.Oracle10gDialect;
|
||||
|
@ -48,8 +47,6 @@ import org.hibernate.ejb.AvailableSettings;
|
|||
import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -179,7 +176,9 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
// em.lock(lock,LockModeType.PESSIMISTIC_READ);
|
||||
em.lock( lock, LockModeType.READ );
|
||||
fail( "expected OptimisticLockException exception" );
|
||||
} catch(OptimisticLockException expected) {}
|
||||
}
|
||||
catch ( OptimisticLockException expected ) {
|
||||
}
|
||||
em.getTransaction().rollback();
|
||||
|
||||
// the previous code block can be rewritten as follows (to get the previous behavior)
|
||||
|
@ -264,7 +263,11 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock = em2.find( Lock.class, lock.getId(), LockModeType.OPTIMISTIC );
|
||||
assertEquals( "lock mode should be OPTIMISTIC ", LockModeType.OPTIMISTIC, em2.getLockMode( lock ) );
|
||||
em2.lock( lock, LockModeType.OPTIMISTIC_FORCE_INCREMENT );
|
||||
assertEquals( "lock mode should be OPTIMISTIC_FORCE_INCREMENT ", LockModeType.OPTIMISTIC_FORCE_INCREMENT, em2.getLockMode(lock) );
|
||||
assertEquals(
|
||||
"lock mode should be OPTIMISTIC_FORCE_INCREMENT ",
|
||||
LockModeType.OPTIMISTIC_FORCE_INCREMENT,
|
||||
em2.getLockMode( lock )
|
||||
);
|
||||
em2.getTransaction().commit();
|
||||
em2.getTransaction().begin();
|
||||
em2.remove( lock );
|
||||
|
@ -275,71 +278,115 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
@Test
|
||||
@SkipForDialect(value = { HSQLDialect.class, SybaseASE15Dialect.class }, jiraKey = "HHH-6820")
|
||||
public void testContendedPessimisticLock() throws Exception {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
final EntityManager em2 = createIsolatedEntityManager();
|
||||
final EntityManager em = getOrCreateEntityManager();
|
||||
Lock lock = createAndPersistLockInstance( em );
|
||||
|
||||
Lock lock = new Lock();
|
||||
Thread t = null;
|
||||
try {
|
||||
lock.setName( "testContendedPessimisticLock" );
|
||||
inFirstTransactionReloadAndModifyLockInstance( em, lock );
|
||||
|
||||
em.getTransaction().begin();
|
||||
em.persist( lock );
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
em.getTransaction().begin();
|
||||
lock = em.getReference( Lock.class, lock.getId() );
|
||||
em.lock( lock, LockModeType.PESSIMISTIC_WRITE );
|
||||
final Integer id = lock.getId();
|
||||
lock.getName(); // force entity to be read
|
||||
log.info("testContendedPessimisticLock: got write lock");
|
||||
final CountDownLatch latch = new CountDownLatch( 1 );
|
||||
FutureTask<Boolean> future = inBackgroundThreadStartSecondTransactionAndReadLockInstance( latch );
|
||||
|
||||
t = new Thread( new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
em2.getTransaction().begin();
|
||||
log.info("testContendedPessimisticLock: (BG) about to issue (PESSIMISTIC_READ) query against write-locked entity");
|
||||
// we should block on the following read
|
||||
Query query = em2.createQuery(
|
||||
"select L from Lock_ L where L.id < 10000 ");
|
||||
query.setLockMode(LockModeType.PESSIMISTIC_READ);
|
||||
List<Lock> resultList = query.getResultList();
|
||||
resultList.get(0).getName(); // force entity to be read
|
||||
}
|
||||
finally {
|
||||
em2.getTransaction().commit();
|
||||
latch.countDown(); // signal that we got the read lock
|
||||
}
|
||||
}
|
||||
} );
|
||||
// wait with timeout on the background thread
|
||||
log.debug( "testContendedPessimisticLock: wait on BG thread" );
|
||||
boolean backGroundThreadCompleted = latch.await( 3, TimeUnit.SECONDS );
|
||||
|
||||
t.setDaemon( true );
|
||||
t.setName("LockTest read lock");
|
||||
t.start();
|
||||
log.info("testContendedPessimisticLock: wait on BG thread");
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS );
|
||||
// latchSet should be false (timeout) because the background thread
|
||||
// shouldn't be able to get a read lock on write locked entity.
|
||||
log.info("testContendedPessimisticLock: BG thread completed transaction");
|
||||
assertFalse( "shouldn't be able to get read lock while another transaction has write lock",latchSet );
|
||||
if ( backGroundThreadCompleted ) {
|
||||
// the background thread read a value. At the very least we need to assert that he did not see the
|
||||
// changed value
|
||||
boolean backgroundThreadHasReadNewValue = future.get();
|
||||
assertFalse(
|
||||
"The background thread is not allowed to see the updated value while the first transaction has not committed yet",
|
||||
backgroundThreadHasReadNewValue
|
||||
);
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
else {
|
||||
log.debug( "The background thread was blocked" );
|
||||
// commit first transaction so that background thread can continue
|
||||
em.getTransaction().commit();
|
||||
boolean backgroundThreadHasReadNewValue = future.get();
|
||||
assertTrue(
|
||||
"Background thread should read the new value after being unblocked",
|
||||
backgroundThreadHasReadNewValue
|
||||
);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
cleanup( em, lock );
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanup(EntityManager em, Lock lock) throws InterruptedException {
|
||||
if ( em.getTransaction().isActive() ) {
|
||||
em.getTransaction().rollback();
|
||||
}
|
||||
if ( t != null) { // wait for background thread to finish before deleting entity
|
||||
t.join();
|
||||
}
|
||||
em.getTransaction().begin();
|
||||
lock = em.getReference( Lock.class, lock.getId() );
|
||||
em.remove( lock );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
em2.close();
|
||||
}
|
||||
|
||||
private FutureTask<Boolean> inBackgroundThreadStartSecondTransactionAndReadLockInstance(final CountDownLatch latch) {
|
||||
final EntityManager isolatedEntityManager = createIsolatedEntityManager();
|
||||
|
||||
FutureTask<Boolean> bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
isolatedEntityManager.getTransaction().begin();
|
||||
log.debug(
|
||||
"testContendedPessimisticLock: (BG) about to issue (PESSIMISTIC_READ) query against write-locked entity"
|
||||
);
|
||||
// we should block on the following read
|
||||
Query query = isolatedEntityManager.createQuery(
|
||||
"select L from Lock_ L where L.id < 10000 "
|
||||
);
|
||||
query.setLockMode( LockModeType.PESSIMISTIC_READ );
|
||||
List<Lock> resultList = query.getResultList();
|
||||
Lock lock = resultList.get( 0 );
|
||||
return lock.getName().equals( "foo" );
|
||||
}
|
||||
catch ( RuntimeException e ) {
|
||||
fail( "An error occurred waiting while attempting to read the entity: " + e.getMessage() );
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
isolatedEntityManager.getTransaction().commit();
|
||||
isolatedEntityManager.close();
|
||||
latch.countDown(); // signal that we got the read lock
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Thread thread = new Thread( bgTask );
|
||||
thread.setDaemon( true );
|
||||
thread.setName( "LockTest read lock" );
|
||||
thread.start();
|
||||
|
||||
return bgTask;
|
||||
}
|
||||
|
||||
private void inFirstTransactionReloadAndModifyLockInstance(EntityManager em, Lock lock) {
|
||||
em.getTransaction().begin();
|
||||
lock = em.getReference( Lock.class, lock.getId() );
|
||||
em.lock( lock, LockModeType.PESSIMISTIC_WRITE );
|
||||
// modify and flush, but don't commit the transaction
|
||||
lock.setName( "foo" );
|
||||
em.flush();
|
||||
log.debug( "testContendedPessimisticLock: got write lock" );
|
||||
}
|
||||
|
||||
private Lock createAndPersistLockInstance(EntityManager em) {
|
||||
Lock lock = new Lock();
|
||||
lock.setName( "testContendedPessimisticLock" );
|
||||
em.getTransaction().begin();
|
||||
em.persist( lock );
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
return lock;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -370,48 +417,56 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock.getName(); // force entity to be read
|
||||
log.info( "testContendedPessimisticReadLockTimeout: got write lock" );
|
||||
|
||||
bgTask = new FutureTask<Boolean>( new Callable() {
|
||||
bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
boolean timedOut = false; // true (success) if LockTimeoutException occurred
|
||||
em2.getTransaction().begin();
|
||||
log.info("testContendedPessimisticReadLockTimeout: (BG) about to read write-locked entity");
|
||||
log.info(
|
||||
"testContendedPessimisticReadLockTimeout: (BG) about to read write-locked entity"
|
||||
);
|
||||
// we should block on the following read
|
||||
Lock lock2 = em2.getReference( Lock.class, id );
|
||||
lock2.getName(); // force entity to be read
|
||||
log.info( "testContendedPessimisticReadLockTimeout: (BG) read write-locked entity" );
|
||||
Map<String, Object> props = new HashMap<String, Object>();
|
||||
// timeout is in milliseconds
|
||||
props.put("javax.persistence.lock.timeout", new Integer(1000));
|
||||
props.put( "javax.persistence.lock.timeout", 1000 );
|
||||
try {
|
||||
em2.lock( lock2, LockModeType.PESSIMISTIC_READ, props );
|
||||
}
|
||||
catch ( LockTimeoutException e ) {
|
||||
// success
|
||||
log.info("testContendedPessimisticReadLockTimeout: (BG) got expected timeout exception");
|
||||
log.info(
|
||||
"testContendedPessimisticReadLockTimeout: (BG) got expected timeout exception"
|
||||
);
|
||||
timedOut = true;
|
||||
em2.getTransaction().rollback();
|
||||
return new Boolean(timedOut);
|
||||
return timedOut;
|
||||
}
|
||||
catch ( Throwable e ) {
|
||||
log.info( "Expected LockTimeoutException but got unexpected exception", e );
|
||||
throw new RuntimeException("Expected LockTimeoutException but got unexpected exception",e);
|
||||
throw new RuntimeException(
|
||||
"Expected LockTimeoutException but got unexpected exception", e
|
||||
);
|
||||
}
|
||||
em2.getTransaction().commit();
|
||||
return new Boolean(timedOut);
|
||||
return timedOut;
|
||||
}
|
||||
finally {
|
||||
latch.countDown(); // signal that we finished
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
t = new Thread( bgTask );
|
||||
t.setDaemon( true );
|
||||
t.setName( "Lock timeout Test (bg)" );
|
||||
t.start();
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
|
||||
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get().booleanValue() );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
@ -442,7 +497,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
Lock lock = new Lock();
|
||||
Thread t = null;
|
||||
FutureTask<Boolean> bgTask = null;
|
||||
FutureTask<Boolean> bgTask;
|
||||
final CountDownLatch latch = new CountDownLatch( 1 );
|
||||
try {
|
||||
lock.setName( "testContendedPessimisticWriteLockTimeout" );
|
||||
|
@ -459,45 +514,51 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock.getName(); // force entity to be read
|
||||
log.info( "testContendedPessimisticWriteLockTimeout: got write lock" );
|
||||
|
||||
bgTask = new FutureTask<Boolean>( new Callable() {
|
||||
bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
boolean timedOut = false; // true (success) if LockTimeoutException occurred
|
||||
em2.getTransaction().begin();
|
||||
log.info("testContendedPessimisticWriteLockTimeout: (BG) about to read write-locked entity");
|
||||
log.info(
|
||||
"testContendedPessimisticWriteLockTimeout: (BG) about to read write-locked entity"
|
||||
);
|
||||
// we should block on the following read
|
||||
Lock lock2 = em2.getReference( Lock.class, id );
|
||||
lock2.getName(); // force entity to be read
|
||||
log.info( "testContendedPessimisticWriteLockTimeout: (BG) read write-locked entity" );
|
||||
Map<String, Object> props = new HashMap<String, Object>();
|
||||
// timeout is in milliseconds
|
||||
props.put("javax.persistence.lock.timeout", new Integer(1000));
|
||||
props.put( "javax.persistence.lock.timeout", 1000 );
|
||||
try {
|
||||
em2.lock( lock2, LockModeType.PESSIMISTIC_WRITE, props );
|
||||
}
|
||||
catch ( LockTimeoutException e ) {
|
||||
// success
|
||||
log.info("testContendedPessimisticWriteLockTimeout: (BG) got expected timeout exception");
|
||||
log.info(
|
||||
"testContendedPessimisticWriteLockTimeout: (BG) got expected timeout exception"
|
||||
);
|
||||
timedOut = true;
|
||||
}
|
||||
catch ( Throwable e ) {
|
||||
log.info( "Expected LockTimeoutException but got unexpected exception", e );
|
||||
}
|
||||
em2.getTransaction().commit();
|
||||
return new Boolean(timedOut);
|
||||
return timedOut;
|
||||
}
|
||||
finally {
|
||||
latch.countDown(); // signal that we finished
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
t = new Thread( bgTask );
|
||||
t.setDaemon( true );
|
||||
t.setName( "Lock timeout Test (bg)" );
|
||||
t.start();
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
|
||||
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get().booleanValue() );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
@ -528,7 +589,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
Lock lock = new Lock();
|
||||
Thread t = null;
|
||||
FutureTask<Boolean> bgTask = null;
|
||||
FutureTask<Boolean> bgTask;
|
||||
final CountDownLatch latch = new CountDownLatch( 1 );
|
||||
try {
|
||||
lock.setName( "testContendedPessimisticWriteLockNoWait" );
|
||||
|
@ -545,45 +606,51 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock.getName(); // force entity to be read
|
||||
log.info( "testContendedPessimisticWriteLockNoWait: got write lock" );
|
||||
|
||||
bgTask = new FutureTask<Boolean>( new Callable() {
|
||||
bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
boolean timedOut = false; // true (success) if LockTimeoutException occurred
|
||||
em2.getTransaction().begin();
|
||||
log.info("testContendedPessimisticWriteLockNoWait: (BG) about to read write-locked entity");
|
||||
log.info(
|
||||
"testContendedPessimisticWriteLockNoWait: (BG) about to read write-locked entity"
|
||||
);
|
||||
// we should block on the following read
|
||||
Lock lock2 = em2.getReference( Lock.class, id );
|
||||
lock2.getName(); // force entity to be read
|
||||
log.info( "testContendedPessimisticWriteLockNoWait: (BG) read write-locked entity" );
|
||||
Map<String, Object> props = new HashMap<String, Object>();
|
||||
// timeout of zero means no wait (for lock)
|
||||
props.put("javax.persistence.lock.timeout", new Integer(0));
|
||||
props.put( "javax.persistence.lock.timeout", 0 );
|
||||
try {
|
||||
em2.lock( lock2, LockModeType.PESSIMISTIC_WRITE, props );
|
||||
}
|
||||
catch ( LockTimeoutException e ) {
|
||||
// success
|
||||
log.info("testContendedPessimisticWriteLockNoWait: (BG) got expected timeout exception");
|
||||
log.info(
|
||||
"testContendedPessimisticWriteLockNoWait: (BG) got expected timeout exception"
|
||||
);
|
||||
timedOut = true;
|
||||
}
|
||||
catch ( Throwable e ) {
|
||||
log.info( "Expected LockTimeoutException but got unexpected exception", e );
|
||||
}
|
||||
em2.getTransaction().commit();
|
||||
return new Boolean(timedOut);
|
||||
return timedOut;
|
||||
}
|
||||
finally {
|
||||
latch.countDown(); // signal that we finished
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
t = new Thread( bgTask );
|
||||
t.setDaemon( true );
|
||||
t.setName( "Lock timeout Test (bg)" );
|
||||
t.start();
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
|
||||
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get().booleanValue() );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
@ -614,7 +681,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
Lock lock = new Lock();
|
||||
Thread t = null;
|
||||
FutureTask<Boolean> bgTask = null;
|
||||
FutureTask<Boolean> bgTask;
|
||||
final CountDownLatch latch = new CountDownLatch( 1 );
|
||||
try {
|
||||
lock.setName( "testQueryTimeout" );
|
||||
|
@ -631,7 +698,8 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock.getName(); // force entity to be read
|
||||
log.info( "testQueryTimeout: got write lock" );
|
||||
|
||||
bgTask = new FutureTask<Boolean>( new Callable() {
|
||||
bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
boolean timedOut = false; // true (success) if LockTimeoutException occurred
|
||||
|
@ -644,9 +712,10 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
try {
|
||||
// we should block on the following read
|
||||
Query query = em2.createQuery(
|
||||
"select L from Lock_ L where L.id < 10000 ");
|
||||
"select L from Lock_ L where L.id < 10000 "
|
||||
);
|
||||
query.setLockMode( LockModeType.PESSIMISTIC_READ );
|
||||
query.setHint( "javax.persistence.query.timeout", new Integer(500) ); // 1 sec timeout
|
||||
query.setHint( "javax.persistence.query.timeout", 500 ); // 1 sec timeout
|
||||
List<Lock> resultList = query.getResultList();
|
||||
String name = resultList.get( 0 ).getName(); // force entity to be read
|
||||
log.info( "testQueryTimeout: name read =" + name );
|
||||
|
@ -657,23 +726,27 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
timedOut = true;
|
||||
}
|
||||
catch ( Throwable e ) {
|
||||
log.info("testQueryTimeout: Expected LockTimeoutException but got unexpected exception", e);
|
||||
log.info(
|
||||
"testQueryTimeout: Expected LockTimeoutException but got unexpected exception",
|
||||
e
|
||||
);
|
||||
}
|
||||
em2.getTransaction().commit();
|
||||
return new Boolean( timedOut );
|
||||
return timedOut;
|
||||
}
|
||||
finally {
|
||||
latch.countDown(); // signal that we finished
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
t = new Thread( bgTask );
|
||||
t.setDaemon( true );
|
||||
t.setName( "testQueryTimeout (bg)" );
|
||||
t.start();
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
|
||||
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get().booleanValue() );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
@ -700,12 +773,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
return;
|
||||
}
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
Map queryTimeoutProps = new HashMap();
|
||||
queryTimeoutProps.put("javax.persistence.query.timeout", new Integer(500) ); // 1 sec timeout (should round up)
|
||||
Map<String, Object> queryTimeoutProps = new HashMap<String, Object>();
|
||||
queryTimeoutProps.put( "javax.persistence.query.timeout", 500 ); // 1 sec timeout (should round up)
|
||||
final EntityManager em2 = createIsolatedEntityManager( queryTimeoutProps );
|
||||
Lock lock = new Lock();
|
||||
Thread t = null;
|
||||
FutureTask<Boolean> bgTask = null;
|
||||
FutureTask<Boolean> bgTask;
|
||||
final CountDownLatch latch = new CountDownLatch( 1 );
|
||||
try {
|
||||
lock.setName( "testQueryTimeout" );
|
||||
|
@ -722,7 +795,8 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock.getName(); // force entity to be read
|
||||
log.info( "testQueryTimeout: got write lock" );
|
||||
|
||||
bgTask = new FutureTask<Boolean>( new Callable() {
|
||||
bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
boolean timedOut = false; // true (success) if LockTimeoutException occurred
|
||||
|
@ -735,7 +809,8 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
try {
|
||||
// we should block on the following read
|
||||
Query query = em2.createQuery(
|
||||
"select L from Lock_ L where L.id < 10000 ");
|
||||
"select L from Lock_ L where L.id < 10000 "
|
||||
);
|
||||
query.setLockMode( LockModeType.PESSIMISTIC_READ );
|
||||
List<Lock> resultList = query.getResultList();
|
||||
String name = resultList.get( 0 ).getName(); // force entity to be read
|
||||
|
@ -747,23 +822,27 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
timedOut = true;
|
||||
}
|
||||
catch ( Throwable e ) {
|
||||
log.info("testQueryTimeout: Expected LockTimeoutException but got unexpected exception", e);
|
||||
log.info(
|
||||
"testQueryTimeout: Expected LockTimeoutException but got unexpected exception",
|
||||
e
|
||||
);
|
||||
}
|
||||
em2.getTransaction().commit();
|
||||
return new Boolean( timedOut );
|
||||
return timedOut;
|
||||
}
|
||||
finally {
|
||||
latch.countDown(); // signal that we finished
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
t = new Thread( bgTask );
|
||||
t.setDaemon( true );
|
||||
t.setName( "testQueryTimeout (bg)" );
|
||||
t.start();
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
|
||||
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get().booleanValue() );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
@ -782,13 +861,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLockTimeoutEMProps() throws Exception {
|
||||
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
Map TimeoutProps = new HashMap();
|
||||
TimeoutProps.put("javax.persistence.lock.timeout", new Integer(1000) ); // 1 second timeout
|
||||
Map<String, Object> TimeoutProps = new HashMap<String, Object>();
|
||||
TimeoutProps.put( "javax.persistence.lock.timeout", 1000 ); // 1 second timeout
|
||||
final EntityManager em2 = createIsolatedEntityManager( TimeoutProps );
|
||||
// TODO: replace dialect instanceof test with a Dialect.hasCapability (e.g. supportsPessimisticLockTimeout)
|
||||
if ( !( getDialect() instanceof Oracle10gDialect ) ) {
|
||||
|
@ -797,7 +875,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
}
|
||||
Lock lock = new Lock();
|
||||
Thread t = null;
|
||||
FutureTask<Boolean> bgTask = null;
|
||||
FutureTask<Boolean> bgTask;
|
||||
final CountDownLatch latch = new CountDownLatch( 1 );
|
||||
try {
|
||||
lock.setName( "testLockTimeoutEMProps" );
|
||||
|
@ -814,7 +892,8 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
lock.getName(); // force entity to be read
|
||||
log.info( "testLockTimeoutEMProps: got write lock" );
|
||||
|
||||
bgTask = new FutureTask<Boolean>( new Callable() {
|
||||
bgTask = new FutureTask<Boolean>(
|
||||
new Callable<Boolean>() {
|
||||
public Boolean call() {
|
||||
try {
|
||||
boolean timedOut = false; // true (success) if LockTimeoutException occurred
|
||||
|
@ -837,20 +916,21 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
|
|||
log.info( "Expected LockTimeoutException but got unexpected exception", e );
|
||||
}
|
||||
em2.getTransaction().commit();
|
||||
return new Boolean(timedOut);
|
||||
return timedOut;
|
||||
}
|
||||
finally {
|
||||
latch.countDown(); // signal that we finished
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
t = new Thread( bgTask );
|
||||
t.setDaemon( true );
|
||||
t.setName( "Lock timeout Test (bg)" );
|
||||
t.start();
|
||||
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
|
||||
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get().booleanValue() );
|
||||
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
|
Loading…
Reference in New Issue