use of org.hibernate.engine.spi.SharedSessionContractImplementor in project hibernate-orm by hibernate.
the class VersionedTest method testStaleRead.
protected ByRef<Object> testStaleRead(BiConsumer<Session, Item> consumer) throws Exception {
AtomicReference<Exception> synchronizationException = new AtomicReference<>();
CountDownLatch syncLatch = new CountDownLatch(1);
CountDownLatch commitLatch = new CountDownLatch(1);
Future<Boolean> action = executor.submit(() -> withTxSessionApply(s -> {
try {
((SharedSessionContractImplementor) s).getTransactionCoordinator().getLocalSynchronizations().registerSynchronization(new Synchronization() {
@Override
public void beforeCompletion() {
}
@Override
public void afterCompletion(int i) {
syncLatch.countDown();
try {
awaitOrThrow(commitLatch);
} catch (Exception e) {
synchronizationException.set(e);
}
}
});
Item item = s.load(Item.class, itemId);
consumer.accept(s, item);
s.flush();
} catch (StaleStateException e) {
log.info("Exception thrown: ", e);
markRollbackOnly(s);
return false;
} catch (PessimisticLockException e) {
log.info("Exception thrown: ", e);
markRollbackOnly(s);
return false;
}
return true;
}));
awaitOrThrow(syncLatch);
ByRef<Object> entryRef = new ByRef<>(null);
try {
withTxSession(s -> {
Item item = s.load(Item.class, itemId);
assertEquals("Original item", item.getDescription());
entryRef.set(assertSingleCacheEntry());
});
} finally {
commitLatch.countDown();
}
assertTrue(action.get(WAIT_TIMEOUT, TimeUnit.SECONDS));
assertNull(synchronizationException.get());
return entryRef;
}
use of org.hibernate.engine.spi.SharedSessionContractImplementor in project hibernate-orm by hibernate.
the class EntityRegionAccessStrategyTest method testContestedPutFromLoad.
/**
* This test fails in CI too often because it depends on very short timeout. The behaviour is basically
* non-testable as we want to make sure that the "Putter" is always progressing; however, it is sometimes
* progressing in different thread (on different node), and sometimes even in system, sending a message
* over network. Therefore even checking that some OOB/remote thread is in RUNNABLE/RUNNING state is prone
* to spurious failure (and we can't grab the state of all threads atomically).
*/
@Ignore
@Test
public void testContestedPutFromLoad() throws Exception {
if (accessType == AccessType.READ_ONLY) {
return;
}
final Object KEY = TestingKeyFactory.generateEntityCacheKey(KEY_BASE + testCount++);
SharedSessionContractImplementor s1 = mockedSession();
localAccessStrategy.putFromLoad(s1, KEY, VALUE1, s1.getTimestamp(), 1);
final CountDownLatch pferLatch = new CountDownLatch(1);
final CountDownLatch pferCompletionLatch = new CountDownLatch(1);
final CountDownLatch commitLatch = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(1);
Thread blocker = new Thread("Blocker") {
@Override
public void run() {
try {
SharedSessionContractImplementor session = mockedSession();
withTx(localEnvironment, session, () -> {
assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(session, KEY, session.getTimestamp()));
doUpdate(localAccessStrategy, session, KEY, VALUE2, 2);
pferLatch.countDown();
commitLatch.await();
return null;
});
} catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
} catch (AssertionFailedError e) {
node1Failure = e;
} finally {
completionLatch.countDown();
}
}
};
Thread putter = new Thread("Putter") {
@Override
public void run() {
try {
SharedSessionContractImplementor session = mockedSession();
withTx(localEnvironment, session, () -> {
localAccessStrategy.putFromLoad(session, KEY, VALUE1, session.getTimestamp(), 1);
return null;
});
} catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
} catch (AssertionFailedError e) {
node1Failure = e;
} finally {
pferCompletionLatch.countDown();
}
}
};
blocker.start();
assertTrue("Active tx has done an update", pferLatch.await(1, TimeUnit.SECONDS));
putter.start();
assertTrue("putFromLoad returns promptly", pferCompletionLatch.await(10, TimeUnit.MILLISECONDS));
commitLatch.countDown();
assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
assertThreadsRanCleanly();
SharedSessionContractImplementor session = mockedSession();
assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(session, KEY, session.getTimestamp()));
}
use of org.hibernate.engine.spi.SharedSessionContractImplementor in project hibernate-orm by hibernate.
the class EntityRegionAccessStrategyTest method putFromLoadTestReadOnly.
protected void putFromLoadTestReadOnly(boolean minimal) throws Exception {
final Object KEY = TestingKeyFactory.generateEntityCacheKey(KEY_BASE + testCount++);
CountDownLatch remotePutFromLoadLatch = expectPutFromLoad();
SharedSessionContractImplementor session = mockedSession();
withTx(localEnvironment, session, () -> {
assertNull(localAccessStrategy.get(session, KEY, session.getTimestamp()));
if (minimal)
localAccessStrategy.putFromLoad(session, KEY, VALUE1, session.getTimestamp(), 1, true);
else
localAccessStrategy.putFromLoad(session, KEY, VALUE1, session.getTimestamp(), 1);
return null;
});
SharedSessionContractImplementor s2 = mockedSession();
assertEquals(VALUE1, localAccessStrategy.get(s2, KEY, s2.getTimestamp()));
SharedSessionContractImplementor s3 = mockedSession();
Object expected;
if (isUsingInvalidation()) {
expected = null;
} else {
if (accessType != AccessType.NONSTRICT_READ_WRITE) {
assertTrue(remotePutFromLoadLatch.await(2, TimeUnit.SECONDS));
}
expected = VALUE1;
}
assertEquals(expected, remoteAccessStrategy.get(s3, KEY, s3.getTimestamp()));
}
use of org.hibernate.engine.spi.SharedSessionContractImplementor in project hibernate-orm by hibernate.
the class EntityRegionAccessStrategyTest method testUpdate.
@Test
public void testUpdate() throws Exception {
if (accessType == AccessType.READ_ONLY) {
return;
}
final Object KEY = generateNextKey();
// Set up initial state
SharedSessionContractImplementor s1 = mockedSession();
localAccessStrategy.putFromLoad(s1, KEY, VALUE1, s1.getTimestamp(), 1);
SharedSessionContractImplementor s2 = mockedSession();
remoteAccessStrategy.putFromLoad(s2, KEY, VALUE1, s2.getTimestamp(), 1);
// both nodes are updated, we don't have to wait for any async replication of putFromLoad
CountDownLatch asyncUpdateLatch = expectAfterUpdate();
final CountDownLatch readLatch = new CountDownLatch(1);
final CountDownLatch commitLatch = new CountDownLatch(1);
final CountDownLatch completionLatch = new CountDownLatch(2);
Thread updater = new Thread(() -> {
try {
SharedSessionContractImplementor session = mockedSession();
withTx(localEnvironment, session, () -> {
log.debug("Transaction began, get initial value");
assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(session, KEY, session.getTimestamp()));
log.debug("Now update value");
doUpdate(localAccessStrategy, session, KEY, VALUE2, 2);
log.debug("Notify the read latch");
readLatch.countDown();
log.debug("Await commit");
commitLatch.await();
return null;
});
} catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
} catch (AssertionFailedError e) {
node1Failure = e;
} finally {
if (readLatch.getCount() > 0) {
readLatch.countDown();
}
log.debug("Completion latch countdown");
completionLatch.countDown();
}
}, "testUpdate-updater");
Thread reader = new Thread(() -> {
try {
SharedSessionContractImplementor session = mockedSession();
withTx(localEnvironment, session, () -> {
log.debug("Transaction began, await read latch");
readLatch.await();
log.debug("Read latch acquired, verify local access strategy");
// This won't block w/ mvc and will read the old value (if transactional as the transaction
// is not being committed yet, or if non-strict as we do the actual update only after transaction)
// or null if non-transactional
Object expected = isTransactional() || accessType == AccessType.NONSTRICT_READ_WRITE ? VALUE1 : null;
assertEquals("Correct value", expected, localAccessStrategy.get(session, KEY, session.getTimestamp()));
return null;
});
} catch (Exception e) {
log.error("node1 caught exception", e);
node1Exception = e;
} catch (AssertionFailedError e) {
node1Failure = e;
} finally {
commitLatch.countDown();
log.debug("Completion latch countdown");
completionLatch.countDown();
}
}, "testUpdate-reader");
updater.setDaemon(true);
reader.setDaemon(true);
updater.start();
reader.start();
assertTrue(completionLatch.await(2, TimeUnit.SECONDS));
assertThreadsRanCleanly();
SharedSessionContractImplementor s3 = mockedSession();
assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(s3, KEY, s3.getTimestamp()));
assertTrue(asyncUpdateLatch.await(10, TimeUnit.SECONDS));
Object expected = isUsingInvalidation() ? null : VALUE2;
SharedSessionContractImplementor s4 = mockedSession();
assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(s4, KEY, s4.getTimestamp()));
}
use of org.hibernate.engine.spi.SharedSessionContractImplementor in project hibernate-orm by hibernate.
the class AbstractGeneralDataRegionTest method testEvictAll.
/**
* Test method for {@link QueryResultsRegion#evictAll()}.
* <p/>
* FIXME add testing of the "immediately without regard for transaction isolation" bit in the
* CollectionRegionAccessStrategy API.
*/
public void testEvictAll() throws Exception {
withSessionFactoriesAndRegions(2, (sessionFactories, regions) -> {
GeneralDataRegion localRegion = regions.get(0);
GeneralDataRegion remoteRegion = regions.get(1);
AdvancedCache localCache = ((BaseGeneralDataRegion) localRegion).getCache();
AdvancedCache remoteCache = ((BaseGeneralDataRegion) remoteRegion).getCache();
SharedSessionContractImplementor localSession = (SharedSessionContractImplementor) sessionFactories.get(0).openSession();
SharedSessionContractImplementor remoteSession = (SharedSessionContractImplementor) sessionFactories.get(1).openSession();
try {
Set localKeys = localCache.keySet();
assertEquals("No valid children in " + localKeys, 0, localKeys.size());
Set remoteKeys = remoteCache.keySet();
assertEquals("No valid children in " + remoteKeys, 0, remoteKeys.size());
assertNull("local is clean", localRegion.get(null, KEY));
assertNull("remote is clean", remoteRegion.get(null, KEY));
localRegion.put(localSession, KEY, VALUE1);
assertEquals(VALUE1, localRegion.get(null, KEY));
remoteRegion.put(remoteSession, KEY, VALUE1);
assertEquals(VALUE1, remoteRegion.get(null, KEY));
localRegion.evictAll();
// This should re-establish the region root node in the optimistic case
assertNull(localRegion.get(null, KEY));
localKeys = localCache.keySet();
assertEquals("No valid children in " + localKeys, 0, localKeys.size());
// Re-establishing the region root on the local node doesn't
// propagate it to other nodes. Do a get on the remote node to re-establish
// This only adds a node in the case of optimistic locking
assertEquals(null, remoteRegion.get(null, KEY));
remoteKeys = remoteCache.keySet();
assertEquals("No valid children in " + remoteKeys, 0, remoteKeys.size());
assertEquals("local is clean", null, localRegion.get(null, KEY));
assertEquals("remote is clean", null, remoteRegion.get(null, KEY));
} finally {
localSession.close();
remoteSession.close();
}
});
}
Aggregations