From ab4c6841df3c3762d35ed1e1af69155757c3b7a3 Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Thu, 30 Jul 2015 17:28:52 +0200 Subject: [PATCH] HHH-10005 Query in context needs precedence over query in cache --- .../query/QueryResultsRegionImpl.java | 18 ++--- .../query/QueryRegionImplTestCase.java | 72 ++++++++++++++++++- 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java index ff0219358c..9e1ec82053 100644 --- a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java +++ b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java @@ -123,17 +123,17 @@ public class QueryResultsRegionImpl extends BaseTransactionalDataRegion implemen // to avoid holding locks that would prevent updates. // Add a zero (or low) timeout option so we don't block // waiting for tx's that did a put to commit - Object result; - if ( skipCacheStore ) { - result = getCache.withFlags( Flag.SKIP_CACHE_STORE ).get( key ); - } - else { - result = getCache.get( key ); + Object result = null; + Map map = transactionContext.get(session); + if (map != null) { + result = map.get(key); } if (result == null) { - Map map = transactionContext.get(session); - if (map != null) { - result = map.get(key); + if ( skipCacheStore ) { + result = getCache.withFlags( Flag.SKIP_CACHE_STORE ).get( key ); + } + else { + result = getCache.get( key ); } } return result; diff --git a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java index 2659a4b128..9101437f34 100644 --- a/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java +++ b/hibernate-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java @@ -11,6 +11,7 @@ import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import org.hibernate.Session; @@ -102,7 +103,7 @@ public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase { @Override public void run() { try { - assertNotEquals(VALUE2, callWithSession(sessionFactory, session-> region.get(session, KEY))); + assertNotEquals(VALUE2, callWithSession(sessionFactory, session -> region.get(session, KEY))); } catch (AssertionFailedError e) { holder.addAssertionFailure(e); } catch (Exception e) { @@ -118,7 +119,7 @@ public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase { public void run() { try { withSession(sessionFactory, session -> { - region.put((SessionImplementor) session, KEY, VALUE2); + region.put(session, KEY, VALUE2); writerLatch.await(); }); } catch (Exception e) { @@ -143,7 +144,7 @@ public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase { assertTrue("Reader finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS)); - assertEquals(VALUE2, region.get(null, KEY)); + assertEquals(VALUE2, callWithSession(sessionFactory, session -> region.get(session, KEY))); }); } @@ -313,6 +314,71 @@ public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase { }); } + @Test + public void testQueryUpdate() throws Exception { + withQueryRegion((sessionFactory, region) -> { + ExceptionHolder holder = new ExceptionHolder(); + CyclicBarrier barrier = new CyclicBarrier(2); + withSession(sessionFactory, session -> region.put(session, KEY, VALUE1)); + + Thread updater = new Thread() { + @Override + public void run() { + try { + withSession(sessionFactory, (session) -> { + assertEquals(VALUE1, region.get(session, KEY)); + region.put(session, KEY, VALUE2); + assertEquals(VALUE2, region.get(session, KEY)); + barrier.await(5, TimeUnit.SECONDS); + barrier.await(5, TimeUnit.SECONDS); + region.put(session, KEY, VALUE3); + assertEquals(VALUE3, region.get(session, KEY)); + barrier.await(5, TimeUnit.SECONDS); + barrier.await(5, TimeUnit.SECONDS); + }); + } catch (AssertionFailedError e) { + holder.addAssertionFailure(e); + barrier.reset(); + } catch (Exception e) { + holder.addException(e); + barrier.reset(); + } + } + }; + + Thread reader = new Thread() { + @Override + public void run() { + try { + withSession(sessionFactory, (session) -> { + assertEquals(VALUE1, region.get(session, KEY)); + barrier.await(5, TimeUnit.SECONDS); + assertEquals(VALUE1, region.get(session, KEY)); + barrier.await(5, TimeUnit.SECONDS); + barrier.await(5, TimeUnit.SECONDS); + assertEquals(VALUE1, region.get(session, KEY)); + barrier.await(5, TimeUnit.SECONDS); + }); + } catch (AssertionFailedError e) { + holder.addAssertionFailure(e); + barrier.reset(); + } catch (Exception e) { + holder.addException(e); + barrier.reset(); + } + } + }; + + updater.start(); + reader.start(); + updater.join(); + reader.join(); + holder.checkExceptions(); + + assertEquals(VALUE3, callWithSession(sessionFactory, session -> region.get(session, KEY))); + }); + } + @Listener public class GetBlocker { private final CountDownLatch latch;