[hibernate-commits] Hibernate SVN: r17811 - in core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src: main/java/org/hibernate/cache/jbc2/access and 9 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed Oct 21 00:03:22 EDT 2009


Author: stliu
Date: 2009-10-21 00:03:22 -0400 (Wed, 21 Oct 2009)
New Revision: 17811

Modified:
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractGeneralDataRegionTestCase.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java
   core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/PessimisticBulkOperationsTest.java
Log:
JBPAPP-2957 HHH-3818  Hibernate/JBC integration doesn't property handle Entity/CollectionRegionAccessStrategy evict

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -23,9 +23,13 @@
  */
 package org.hibernate.cache.jbc2;
 
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.transaction.SystemException;
 import javax.transaction.Transaction;
@@ -42,7 +46,12 @@
 import org.jboss.cache.config.Configuration;
 import org.jboss.cache.config.Option;
 import org.jboss.cache.config.Configuration.NodeLockingScheme;
-import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeInvalidated;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.ViewChanged;
+import org.jboss.cache.notifications.event.NodeInvalidatedEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.ViewChangedEvent;
 import org.jboss.cache.optimistic.DataVersion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -53,30 +62,52 @@
  * 
  * @author Steve Ebersole
  */
- at CacheListener
 public abstract class BasicRegionAdapter implements Region {
    
+    private enum InvalidateState { INVALID, CLEARING, VALID };
     
     public static final String ITEM = CacheHelper.ITEM;
 
     protected final Cache jbcCache;
     protected final String regionName;
     protected final Fqn regionFqn;
+    protected final Fqn internalFqn;
     protected Node regionRoot;
     protected final boolean optimistic;
     protected final TransactionManager transactionManager;
     protected final Logger log;
     protected final Object regionRootMutex = new Object();
+    protected final Object memberId;
+    protected final boolean replication;
+    protected final Object invalidationMutex = new Object();
+    protected final AtomicReference<InvalidateState> invalidateState = 
+       new AtomicReference<InvalidateState>(InvalidateState.VALID);
+    protected final Set<Object> currentView = new HashSet<Object>();
 
 //    protected RegionRootListener listener;
     
     public BasicRegionAdapter(Cache jbcCache, String regionName, String regionPrefix) {
+
+        this.log = LoggerFactory.getLogger(getClass());
+        
         this.jbcCache = jbcCache;
         this.transactionManager = jbcCache.getConfiguration().getRuntimeConfig().getTransactionManager();
         this.regionName = regionName;
         this.regionFqn = createRegionFqn(regionName, regionPrefix);
-        optimistic = jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC;
-        log = LoggerFactory.getLogger(getClass());
+        this.internalFqn = CacheHelper.getInternalFqn(regionFqn);
+        this.optimistic = jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC;
+        this.memberId = jbcCache.getLocalAddress();
+        this.replication = CacheHelper.isClusteredReplication(jbcCache);
+        
+        this.jbcCache.addCacheListener(this);
+        
+        synchronized (currentView) {
+           List view = jbcCache.getMembers();
+           if (view != null) {
+              currentView.addAll(view);
+           }
+        }
+        
         activateLocalClusterNode();
         
         log.debug("Created Region for " + regionName + " -- regionPrefix is " + regionPrefix);
@@ -129,13 +160,13 @@
             if (!regionRoot.isResident()) {
                regionRoot.setResident(true);
             }
+            establishInternalNodes();
         }
         catch (Exception e) {
             throw new CacheException(e.getMessage(), e);
         }
         finally {
-            if (tx != null)
-               resume(tx);
+            resume(tx);
         }
         
     }
@@ -154,6 +185,7 @@
             // For pessimistic locking, we just want to toss out our ref
             // to any old invalid root node and get the latest (may be null)            
             if (!optimistic) {
+               establishInternalNodes();
                regionRoot = jbcCache.getRoot().getChild( regionFqn );
                return;
             }
@@ -181,6 +213,7 @@
                  }
                  // Never evict this node
                  newRoot.setResident(true);
+                 establishInternalNodes();
             }
             finally {
                 resume(tx);
@@ -189,6 +222,24 @@
         }
     }
 
+    private void establishInternalNodes()
+    {
+       synchronized (currentView) {
+          Transaction tx = suspend();
+          try {
+             for (Object member : currentView) {
+                DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE : null;
+                Fqn f = Fqn.fromRelativeElements(internalFqn, member);
+                CacheHelper.addNode(jbcCache, f, true, false, version);
+             }
+          }
+          finally {
+             resume(tx);
+          }
+       }
+       
+    }
+
     public String getName() {
         return regionName;
     }
@@ -201,6 +252,11 @@
         return regionFqn;
     }
     
+    public Object getMemberId()
+    {
+       return this.memberId;
+    }
+    
     /**
      * Checks for the validity of the root cache node for this region,
      * creating a new one if it does not exist or is invalid, and also
@@ -219,6 +275,37 @@
        if (regionRoot != null && regionRoot.isValid() && !regionRoot.isResident())
           regionRoot.setResident(true);
     }
+    
+    public boolean checkValid()
+    {
+       boolean valid = invalidateState.get() == InvalidateState.VALID;
+       
+       if (!valid) {
+          synchronized (invalidationMutex) {
+             if (invalidateState.compareAndSet(InvalidateState.INVALID, InvalidateState.CLEARING)) {
+                Transaction tx = suspend();
+                try {
+                   Option opt = new Option();
+                   opt.setLockAcquisitionTimeout(1);
+                   opt.setCacheModeLocal(true);
+                   CacheHelper.removeAll(jbcCache, regionFqn, opt);
+                   invalidateState.compareAndSet(InvalidateState.CLEARING, InvalidateState.VALID);
+                }
+                catch (Exception e) {
+                   if (log.isTraceEnabled()) {
+                      log.trace("Could not invalidate region: " + e.getLocalizedMessage());
+                   }
+                }
+                finally {
+                   resume(tx);
+                }
+             }
+          }
+          valid = invalidateState.get() == InvalidateState.VALID;
+       }
+       
+       return valid;   
+    }
 
     public void destroy() throws CacheException {
         try {
@@ -242,10 +329,9 @@
         } catch (Exception e) {
             throw new CacheException(e);
         }
-//        finally {
-//            if (listener != null)
-//                jbcCache.removeCacheListener(listener);
-//        }
+        finally {
+            jbcCache.removeCacheListener(this);
+        }
     }
 
     protected void deactivateLocalNode() {
@@ -256,18 +342,50 @@
         }
     }
 
+	public boolean contains(Object key) {
+		if ( !checkValid() ) {
+			return false;
+		}
+
+		try {
+			Option opt = new Option();
+            opt.setLockAcquisitionTimeout(100);
+            CacheHelper.setInvocationOption( jbcCache, opt );
+			return CacheHelper.getAllowingTimeout( jbcCache, regionFqn, key ) != null;
+		}
+		catch ( CacheException ce ) {
+			throw ce;
+		}
+		catch ( Throwable t ) {
+			throw new CacheException( t );
+		}
+	}
+
     public long getSizeInMemory() {
         // not supported
         return -1;
     }
 
     public long getElementCountInMemory() {
-        try {
-            Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
-            return childrenNames.size();
-        } catch (Exception e) {
-            throw new CacheException(e);
+        if (checkValid()) {
+           try {
+               Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
+               int size = childrenNames.size();
+               if (childrenNames.contains(CacheHelper.Internal.NODE)) {
+                  size--;
+               }
+               return size;
+           }
+		   catch ( CacheException ce ) {
+			   throw ce;
+		   }
+		   catch (Exception e) {
+               throw new CacheException(e);
+           }
         }
+        else {
+           return 0;
+        }           
     }
 
     public long getElementCountOnDisk() {
@@ -275,18 +393,25 @@
     }
 
     public Map toMap() {
-        try {
-            Map result = new HashMap();
-            Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
-            for (Object childName : childrenNames) {
-                result.put(childName, CacheHelper.get(jbcCache,regionFqn, childName));
-            }
-            return result;
-        } catch (CacheException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new CacheException(e);
+        if (checkValid()) {
+           try {
+               Map result = new HashMap();
+               Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
+               for (Object childName : childrenNames) {
+                   if (CacheHelper.Internal.NODE != childName) {
+                      result.put(childName, CacheHelper.get(jbcCache,regionFqn, childName));
+                   }
+               }
+               return result;
+           } catch (CacheException e) {
+               throw e;
+           } catch (Exception e) {
+               throw new CacheException(e);
+           }
         }
+        else {
+           return Collections.emptyMap();
+        }
     }
 
     public long nextTimestamp() {
@@ -327,7 +452,7 @@
      * @return the transaction that was suspended, or <code>null</code> if
      *         there wasn't one
      */
-    protected Transaction suspend() {
+    public Transaction suspend() {
         Transaction tx = null;
         try {
             if (transactionManager != null) {
@@ -345,7 +470,7 @@
      * @param tx
      *            the transaction to suspend. May be <code>null</code>.
      */
-    protected void resume(Transaction tx) {
+    public void resume(Transaction tx) {
         try {
             if (tx != null)
                 transactionManager.resume(tx);
@@ -404,17 +529,52 @@
         return escaped;
     }
     
-//    @CacheListener
-//    public class RegionRootListener {
-//        
-//        @NodeCreated
-//        public void nodeCreated(NodeCreatedEvent event) {
-//            if (!event.isPre() && event.getFqn().equals(getRegionFqn())) {
-//                log.debug("Node created for " + getRegionFqn());
-//                Node regionRoot = jbcCache.getRoot().getChild(getRegionFqn());
-//                regionRoot.setResident(true);
-//            }
-//        }
-//        
-//    }
+    @NodeModified
+    public void nodeModified(NodeModifiedEvent event)
+    {
+       handleEvictAllModification(event);
+    }
+    
+    protected boolean handleEvictAllModification(NodeModifiedEvent event) {
+       
+       if (!event.isPre() && (replication || event.isOriginLocal()) && event.getData().containsKey(ITEM))
+       {
+          if (event.getFqn().isChildOf(internalFqn))
+          {
+             invalidateState.set(InvalidateState.INVALID);
+             return true;
+          }
+       }
+       return false;       
+    }
+    
+    @NodeInvalidated
+    public void nodeInvalidated(NodeInvalidatedEvent event)
+    {
+       handleEvictAllInvalidation(event);
+    }
+    
+    protected boolean handleEvictAllInvalidation(NodeInvalidatedEvent event)
+    {
+       if (!event.isPre() && event.getFqn().isChildOf(internalFqn))
+       {
+          invalidateState.set(InvalidateState.INVALID);
+          return true;
+       }      
+       return false;
+    }
+    
+    @ViewChanged
+    public void viewChanged(ViewChangedEvent event) {
+       
+       synchronized (currentView) {
+          List view = event.getNewView().getMembers();
+          if (view != null) {
+             currentView.addAll(view);
+             establishInternalNodes();
+          }
+       }
+       
+    }
+   
 }

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -23,11 +23,12 @@
  */
 package org.hibernate.cache.jbc2.access;
 
+import javax.transaction.Transaction;
+
 import org.hibernate.cache.CacheDataDescription;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cache.access.EntityRegionAccessStrategy;
-import org.hibernate.cache.jbc2.BasicRegionAdapter;
 import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
 import org.hibernate.cache.jbc2.util.CacheHelper;
 import org.hibernate.cache.jbc2.util.DataVersionAdapter;
@@ -75,22 +76,17 @@
      * by adding a {@link NonLockingDataVersion} to the invocation.
      */
     @Override
-    public void evictAll() throws CacheException {
-
-        evictOrRemoveAll();
-    }    
-    
-    /**
-     * Overrides the {@link TransactionalAccessDelegate#get(Object, long) superclass}
-     * by {@link BasicRegionAdapter#ensureRegionRootExists() ensuring the root
-     * node for the region exists} before making the call.
-     */
-    @Override
-    public Object get(Object key, long txTimestamp) throws CacheException
+    public void evictAll() throws CacheException
     {
-        region.ensureRegionRootExists();
-        
-        return CacheHelper.get(cache, regionFqn, key);
+       Transaction tx = region.suspend();
+       try {        
+          region.ensureRegionRootExists();
+          Option opt = NonLockingDataVersion.getInvocationOption();
+          CacheHelper.sendEvictAllNotification(cache, regionFqn, region.getMemberId(), opt);
+       }
+       finally {
+          region.resume(tx);
+       }
     }
 
     /**
@@ -100,6 +96,9 @@
      */
     @Override
     public boolean insert(Object key, Object value, Object version) throws CacheException {
+       
+        if (!region.checkValid())
+            return false;
         
         region.ensureRegionRootExists();
 
@@ -111,6 +110,9 @@
     @Override
     public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
             throws CacheException {
+       
+        if (!region.checkValid())
+            return false;
         
         region.ensureRegionRootExists();
 
@@ -123,6 +125,9 @@
 
     @Override
     public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+       
+        if (!region.checkValid())
+            return false;
         
         region.ensureRegionRootExists();
 
@@ -132,6 +137,10 @@
 
     @Override
     public void remove(Object key) throws CacheException {
+       
+        // We remove whether or not the region is valid. Other nodes
+        // may have already restored the region so they need to
+        // be informed of the change.
         
         region.ensureRegionRootExists();
 
@@ -141,14 +150,18 @@
 
     @Override
     public void removeAll() throws CacheException {
-
-        evictOrRemoveAll();  
+       Option opt = NonLockingDataVersion.getInvocationOption();
+       CacheHelper.removeAll(cache, regionFqn, opt);
     }
 
     @Override
     public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
             throws CacheException {
         
+        // We update whether or not the region is valid. Other nodes
+        // may have already restored the region so they need to
+        // be informed of the change.
+        
         region.ensureRegionRootExists();
 
         Option opt = getDataVersionOption(currentVersion, previousVersion);
@@ -166,10 +179,4 @@
         return opt;
     }
 
-    private void evictOrRemoveAll() {
-       
-        Option opt = NonLockingDataVersion.getInvocationOption();
-        CacheHelper.removeAll(cache, regionFqn, opt);
-    }
-
 }

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -23,6 +23,8 @@
  */
 package org.hibernate.cache.jbc2.access;
 
+import javax.transaction.Transaction;
+
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cache.access.EntityRegionAccessStrategy;
@@ -56,14 +58,20 @@
     }
 
     public Object get(Object key, long txTimestamp) throws CacheException {
-       
+        
+        if (!region.checkValid())
+           return null;
+        
         region.ensureRegionRootExists();
         
         return CacheHelper.get(cache, regionFqn, key);
     }
 
-    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+   public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
        
+        if (!region.checkValid())
+            return false;
+       
         region.ensureRegionRootExists();
 
         return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
@@ -72,6 +80,9 @@
     public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
             throws CacheException {
        
+        if (!region.checkValid())
+            return false;
+       
         region.ensureRegionRootExists();
 
         // We ignore minimalPutOverride. JBossCache putForExternalRead is
@@ -96,6 +107,9 @@
 
     public boolean insert(Object key, Object value, Object version) throws CacheException {
        
+        if (!region.checkValid())
+            return false;
+       
         region.ensureRegionRootExists();
 
         CacheHelper.put(cache, regionFqn, key, value);
@@ -109,6 +123,10 @@
     public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
             throws CacheException {
        
+        // We update whether or not the region is valid. Other nodes
+        // may have already restored the region so they need to
+        // be informed of the change.
+       
         region.ensureRegionRootExists();
 
         CacheHelper.put(cache, regionFqn, key, value);
@@ -122,13 +140,17 @@
 
     public void remove(Object key) throws CacheException {
        
+        // We remove whether or not the region is valid. Other nodes
+        // may have already restored the region so they need to
+        // be informed of the change.
+       
         region.ensureRegionRootExists();
 
         CacheHelper.remove(cache, regionFqn, key);
     }
 
     public void removeAll() throws CacheException {
-        evictOrRemoveAll();
+       CacheHelper.removeAll(cache, regionFqn); 
     }
 
     public void evict(Object key) throws CacheException {
@@ -139,10 +161,15 @@
     }
 
     public void evictAll() throws CacheException {
-        evictOrRemoveAll();
+       Transaction tx = region.suspend();
+       try {        
+          region.ensureRegionRootExists();
+          
+          CacheHelper.sendEvictAllNotification(cache, regionFqn, region.getMemberId(), null);
+       }
+       finally {
+          region.resume(tx);
+       }        
     }
     
-    private void evictOrRemoveAll() throws CacheException {
-        CacheHelper.removeAll(cache, regionFqn);        
-    }
 }

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -26,6 +26,7 @@
 import org.jboss.cache.Cache;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.notifications.annotation.CacheListener;
 
 import org.hibernate.cache.CacheDataDescription;
 import org.hibernate.cache.CacheException;
@@ -39,6 +40,7 @@
  * 
  * @author Steve Ebersole
  */
+ at CacheListener
 public class CollectionRegionImpl extends TransactionalDataRegionAdapter implements CollectionRegion {
 
     public static final String TYPE = "COLL";

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -26,6 +26,7 @@
 import org.jboss.cache.Cache;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.notifications.annotation.CacheListener;
 
 import org.hibernate.cache.CacheDataDescription;
 import org.hibernate.cache.CacheException;
@@ -39,6 +40,7 @@
  * 
  * @author Steve Ebersole
  */
+ at CacheListener
 public class EntityRegionImpl extends TransactionalDataRegionAdapter implements EntityRegion {
 
     public static final String TYPE = "ENTITY";

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -25,6 +25,8 @@
 
 import java.util.Properties;
 
+import javax.transaction.Transaction;
+
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.QueryResultsRegion;
 import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
@@ -33,6 +35,7 @@
 import org.jboss.cache.Cache;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.config.Option;
+import org.jboss.cache.notifications.annotation.CacheListener;
 
 /**
  * Defines the behavior of the query cache regions for JBossCache 2.x.
@@ -40,6 +43,7 @@
  * @author Brian Stansberry
  * @version $Revision$
  */
+ at CacheListener
 public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter implements QueryResultsRegion {
 
     public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.region.jbc2.query.localonly";
@@ -85,14 +89,22 @@
     }
 
     public void evictAll() throws CacheException {
-        Option opt = getNonLockingDataVersionOption(false);
-        if (localOnly)
-            opt.setCacheModeLocal(true);
-        CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+          Transaction tx = suspend();
+          try {        
+             ensureRegionRootExists();
+             Option opt = getNonLockingDataVersionOption(true);
+             CacheHelper.sendEvictAllNotification(jbcCache, regionFqn, getMemberId(), opt);
+          }
+          finally {
+             resume(tx);
+          }        
     }
 
     public Object get(Object key) throws CacheException {
        
+        if (!checkValid())
+           return null;
+       
         ensureRegionRootExists();
 
         // Don't hold the JBC node lock throughout the tx, as that
@@ -106,28 +118,30 @@
 
     public void put(Object key, Object value) throws CacheException {
        
-        ensureRegionRootExists();
-
-        // Here we don't want to suspend the tx. If we do:
-        // 1) We might be caching query results that reflect uncommitted
-        // changes. No tx == no WL on cache node, so other threads
-        // can prematurely see those query results
-        // 2) No tx == immediate replication. More overhead, plus we
-        // spread issue #1 above around the cluster
-
-        // Add a zero (or quite low) timeout option so we don't block.
-        // Ignore any TimeoutException. Basically we forego caching the
-        // query result in order to avoid blocking.
-        // Reads are done with suspended tx, so they should not hold the
-        // lock for long.  Not caching the query result is OK, since
-        // any subsequent read will just see the old result with its
-        // out-of-date timestamp; that result will be discarded and the
-        // db query performed again.
-        Option opt = getNonLockingDataVersionOption(false);
-        opt.setLockAcquisitionTimeout(2);
-        if (localOnly)
-            opt.setCacheModeLocal(true);
-        CacheHelper.putAllowingTimeout(getCacheInstance(), getRegionFqn(), key, value, opt);
+        if (checkValid()) {
+           ensureRegionRootExists();
+   
+           // Here we don't want to suspend the tx. If we do:
+           // 1) We might be caching query results that reflect uncommitted
+           // changes. No tx == no WL on cache node, so other threads
+           // can prematurely see those query results
+           // 2) No tx == immediate replication. More overhead, plus we
+           // spread issue #1 above around the cluster
+   
+           // Add a zero (or quite low) timeout option so we don't block.
+           // Ignore any TimeoutException. Basically we forego caching the
+           // query result in order to avoid blocking.
+           // Reads are done with suspended tx, so they should not hold the
+           // lock for long.  Not caching the query result is OK, since
+           // any subsequent read will just see the old result with its
+           // out-of-date timestamp; that result will be discarded and the
+           // db query performed again.
+           Option opt = getNonLockingDataVersionOption(false);
+           opt.setLockAcquisitionTimeout(2);
+           if (localOnly)
+               opt.setCacheModeLocal(true);
+           CacheHelper.putAllowingTimeout(getCacheInstance(), getRegionFqn(), key, value, opt);
+        }
     }
 
     @Override

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -41,6 +41,7 @@
 import org.jboss.cache.notifications.annotation.CacheListener;
 import org.jboss.cache.notifications.annotation.NodeModified;
 import org.jboss.cache.notifications.annotation.NodeRemoved;
+import org.jboss.cache.notifications.event.NodeInvalidatedEvent;
 import org.jboss.cache.notifications.event.NodeModifiedEvent;
 import org.jboss.cache.notifications.event.NodeRemovedEvent;
 
@@ -95,14 +96,21 @@
 
     public void evictAll() throws CacheException {
         // TODO Is this a valid operation on a timestamps cache?
-        Option opt = getNonLockingDataVersionOption(true);
-        CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+        Transaction tx = suspend();
+        try {        
+           ensureRegionRootExists();
+           Option opt = getNonLockingDataVersionOption(true);
+           CacheHelper.sendEvictAllNotification(jbcCache, regionFqn, getMemberId(), opt);
+        }
+        finally {
+           resume(tx);
+        }        
     }
 
     public Object get(Object key) throws CacheException {
 
         Object value = localCache.get(key);
-        if (value == null) {
+        if (value == null && checkValid()) {
            
             ensureRegionRootExists();
             
@@ -147,14 +155,15 @@
      */
     @NodeModified
     public void nodeModified(NodeModifiedEvent event) {
-        if (event.isPre())
-            return;
-
-        Fqn fqn = event.getFqn();
-        Fqn regFqn = getRegionFqn();
-        if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
-            Object key = fqn.get(regFqn.size());
-            localCache.put(key, event.getData().get(ITEM));
+       
+        if (!handleEvictAllModification(event) && !event.isPre()) {
+   
+           Fqn fqn = event.getFqn();
+           Fqn regFqn = getRegionFqn();
+           if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
+               Object key = fqn.get(regFqn.size());
+               localCache.put(key, event.getData().get(ITEM));
+           }
         }
     }
 
@@ -178,8 +187,30 @@
             localCache.clear();
         }
     }
+    
+    
 
-    /**
+   @Override
+   protected boolean handleEvictAllInvalidation(NodeInvalidatedEvent event)
+   {
+      boolean result = super.handleEvictAllInvalidation(event);
+      if (result) {
+         localCache.clear();
+      }
+      return result;
+   }
+
+   @Override
+   protected boolean handleEvictAllModification(NodeModifiedEvent event)
+   {
+      boolean result = super.handleEvictAllModification(event);
+      if (result) {
+         localCache.clear();
+      }
+      return result;
+   }
+
+   /**
      * Brings all data from the distributed cache into our local cache.
      */
     private void populateLocalCache() {

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -46,6 +46,8 @@
  */
 public class CacheHelper {
 
+    public static enum Internal { NODE, LOCAL };
+    
     /** Key under which items are cached */
     public static final String ITEM = "item";
     /** Key and value used in a hack to create region root nodes */
@@ -467,4 +469,23 @@
         option.setDataVersion(version);
         setInvocationOption(cache, option);
     }
+    
+    public static Fqn getInternalFqn(Fqn region)
+    {
+       return Fqn.fromRelativeElements(region, Internal.NODE);
+    }
+    
+    public static void sendEvictNotification(Cache cache, Fqn region, Object member, Object key, Option option)
+    {
+       setInvocationOption(cache, option);
+       Fqn f = Fqn.fromRelativeElements(region, Internal.NODE, member  == null ? Internal.LOCAL : member, key);
+       cache.put(f, ITEM, DUMMY);
+    }
+    
+    public static void sendEvictAllNotification(Cache cache, Fqn region, Object member, Option option)
+    {
+       setInvocationOption(cache, option);
+       Fqn f = Fqn.fromRelativeElements(region, Internal.NODE, member  == null ? Internal.LOCAL : member);
+       cache.put(f, ITEM, DUMMY);
+    }
 }

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractGeneralDataRegionTestCase.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractGeneralDataRegionTestCase.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractGeneralDataRegionTestCase.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -24,9 +24,7 @@
 package org.hibernate.test.cache.jbc2;
 
 import java.util.Iterator;
-import java.util.Set;
 
-import org.hibernate.cache.CacheException;
 import org.hibernate.cache.GeneralDataRegion;
 import org.hibernate.cache.QueryResultsRegion;
 import org.hibernate.cache.Region;
@@ -171,8 +169,7 @@
         
         Node regionRoot = localCache.getRoot().getChild(regionFqn);
         assertFalse(regionRoot == null);
-        Set children = regionRoot.getChildrenNames();
-        assertEquals("No children in " + children, 0, children.size());
+        assertEquals("No children in " + regionRoot, 0, getValidChildrenCount(regionRoot));
         assertTrue(regionRoot.isResident());
         
         if (optimistic) {
@@ -181,7 +178,7 @@
     
         regionRoot = remoteCache.getRoot().getChild(regionFqn);
         assertFalse(regionRoot == null);
-        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertEquals(0, getValidChildrenCount(regionRoot));
         assertTrue(regionRoot.isResident());
         
         if (optimistic) {
@@ -212,35 +209,24 @@
         
         localRegion.evictAll();
         
-        // This should re-establish the region root node in the optimistic case
+        // This should re-establish the region root node
         assertNull(localRegion.get(KEY));
         
         regionRoot = localCache.getRoot().getChild(regionFqn);
-        if (optimistic) {
-           assertFalse(regionRoot == null);
-           assertEquals(0, regionRoot.getChildrenNames().size());
-           assertTrue(regionRoot.isValid());
-           assertTrue(regionRoot.isResident());
-        }
-        else {
-            assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
-        }
+        assertFalse(regionRoot == null);
+        assertEquals(0, getValidChildrenCount(regionRoot));
+        assertTrue(regionRoot.isValid());
+        assertTrue(regionRoot.isResident());
 
         // 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(KEY));
         
         regionRoot = remoteCache.getRoot().getChild(regionFqn);
-        if (optimistic) {
-            assertFalse(regionRoot == null);
-            assertEquals(0, regionRoot.getChildrenNames().size());
-            assertTrue(regionRoot.isValid());
-            assertTrue(regionRoot.isResident());
-        }
-        else {
-            assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
-        }
+        assertFalse(regionRoot == null);
+        assertEquals(0, getValidChildrenCount(regionRoot));
+        assertTrue(regionRoot.isValid());
+        assertTrue(regionRoot.isResident());
         
         assertEquals("local is clean", null, localRegion.get(KEY));
         assertEquals("remote is clean", null, remoteRegion.get(KEY));

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -25,10 +25,14 @@
 
 
 
+import java.util.Set;
+
 import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.util.CacheHelper;
 import org.hibernate.junit.UnitTestCase;
 import org.hibernate.test.util.CacheTestSupport;
 import org.jboss.cache.Cache;
+import org.jboss.cache.Node;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -96,4 +100,15 @@
     protected void avoidConcurrentFlush() {
         testSupport.avoidConcurrentFlush();
     }
+
+    protected int getValidChildrenCount(Node node) {
+        int result = 0;
+        Set<Node> children = node.getChildren();
+        for (Node child : children) {
+           if (node.isValid() && CacheHelper.Internal.NODE.equals(child.getFqn().getLastElement()) == false) {
+              result++;
+           }
+        }
+        return result;
+    }
 }
\ No newline at end of file

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -471,38 +471,27 @@
             localAccessStrategy.evictAll();
         else
             localAccessStrategy.removeAll();
-        
-        // This should re-establish the region root node in the optimistic case
+
+        // This should re-establish the region root node
         assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
         
         regionRoot = localCache.getRoot().getChild(regionFqn);
-        if (isUsingOptimisticLocking()) {
-            assertFalse(regionRoot == null);
-            assertEquals(0, getValidChildrenCount(regionRoot));
-            assertTrue(regionRoot.isValid());
-            assertTrue(regionRoot.isResident());
-        }
-        else {
-            assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
-        }
+         assertFalse(regionRoot == null);
+         assertEquals(0, getValidChildrenCount(regionRoot));
+         assertTrue(regionRoot.isValid());
+         assertTrue(regionRoot.isResident());
 
         // 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, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
 
         regionRoot = remoteCache.getRoot().getChild(regionFqn);
-        if (isUsingOptimisticLocking()) {
-           assertFalse(regionRoot == null);
-           assertTrue(regionRoot.isValid());
-           assertTrue(regionRoot.isResident());
-           // Not invalidation, so we didn't insert a child above
-           assertEquals(0, getValidChildrenCount(regionRoot));
-        }        
-        else {
-            assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
-        }
-        
+        assertFalse(regionRoot == null);
+        assertTrue(regionRoot.isValid());
+        assertTrue(regionRoot.isResident());
+        // Not invalidation, so we didn't insert a child above
+        assertEquals(0, getValidChildrenCount(regionRoot));
+
         // Test whether the get above messes up the optimistic version
         remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
         assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
@@ -521,17 +510,7 @@
         assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis()));
         assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
     }
-    
-    private int getValidChildrenCount(Node node) {
-        int result = 0;
-        for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
-           if (((Node) it.next()).isValid()) {
-              result++;
-           }
-        }
-        return result;        
-    }
-    
+
     private void rollback() {
         try {
             BatchModeTransactionManager.getInstance().rollback();

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -682,36 +682,26 @@
         else
             localAccessStrategy.removeAll();
         
-        // This should re-establish the region root node in the optimistic case
+        // This should re-establish the region root node
         assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
         
         regionRoot = localCache.getRoot().getChild(regionFqn);
-        if (isUsingOptimisticLocking()) {
-            assertFalse(regionRoot == null);
-            assertEquals(0, getValidChildrenCount(regionRoot));
-            assertTrue(regionRoot.isValid());
-            assertTrue(regionRoot.isResident());
-        }
-        else {
-            assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
-        }
+        assertFalse(regionRoot == null);
+        assertEquals(0, getValidChildrenCount(regionRoot));
+        assertTrue(regionRoot.isValid());
+        assertTrue(regionRoot.isResident());
 
         // 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
         assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
 
         regionRoot = remoteCache.getRoot().getChild(regionFqn);
-        if (isUsingOptimisticLocking()) {
-           assertFalse(regionRoot == null);
-           assertTrue(regionRoot.isValid());
-           assertTrue(regionRoot.isResident());
-           // Not invalidation, so we didn't insert a child above
-           assertEquals(0, getValidChildrenCount(regionRoot));
-       }        
-       else {
-          assertTrue("region root is removed", regionRoot == null || !regionRoot.isValid());
-       }
-        
+        assertFalse(regionRoot == null);
+        assertTrue(regionRoot.isValid());
+        assertTrue(regionRoot.isResident());
+        // Not invalidation, so we didn't insert a child above
+        assertEquals(0, getValidChildrenCount(regionRoot));
+
         // Test whether the get above messes up the optimistic version
         remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
         assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
@@ -730,17 +720,7 @@
         assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System.currentTimeMillis()));
         assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
     }
-    
-    private int getValidChildrenCount(Node node) {
-        int result = 0;
-        for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
-           if (((Node) it.next()).isValid()) {
-              result++;
-           }
-        }
-        return result;        
-    }
-    
+
     protected void rollback() {
         try {
             BatchModeTransactionManager.getInstance().rollback();

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -63,7 +63,7 @@
         final CountDownLatch commitLatch = new CountDownLatch(1);
         final CountDownLatch completionLatch = new CountDownLatch(1);
         
-        Thread blocker = new Thread() {          
+        Thread blocker = new Thread("Blocker") {          
             
             public void run() {
                 
@@ -95,7 +95,7 @@
             }
         };
         
-        Thread putter = new Thread() {          
+        Thread putter = new Thread("Putter") {          
             
             public void run() {
                 

Modified: core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/PessimisticBulkOperationsTest.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/PessimisticBulkOperationsTest.java	2009-10-21 03:19:20 UTC (rev 17810)
+++ core/branches/Branch_3_3_2_GA_CP/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/bulk/PessimisticBulkOperationsTest.java	2009-10-21 04:03:22 UTC (rev 17811)
@@ -26,11 +26,11 @@
 import java.util.Set;
 
 import org.hibernate.FlushMode;
-import org.hibernate.cache.RegionFactory;
 import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
 import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
 import org.hibernate.cfg.Configuration;
 import org.hibernate.classic.Session;
+import org.hibernate.stat.SecondLevelCacheStatistics;
 import org.hibernate.test.cache.jbc2.functional.CacheTestCaseBase;
 import org.hibernate.test.cache.jbc2.functional.Contact;
 import org.hibernate.test.cache.jbc2.functional.Customer;
@@ -90,7 +90,12 @@
          assertNotNull("Red Hat contacts exist", rhContacts);
          assertEquals("Created expected number of Red Hat contacts", 10, rhContacts.size());
          
+         SecondLevelCacheStatistics contactSlcs = getEnvironment().getSessionFactory().getStatistics().getSecondLevelCacheStatistics(
+               getPrefixedRegionName(Contact.class.getName()));
+         assertEquals(contactSlcs.getElementCountInMemory(), 20);
+         
          assertEquals("Deleted all Red Hat contacts", 10, deleteContacts());
+         assertEquals(0, contactSlcs.getElementCountInMemory());
          
          List<Integer> jbContacts = getContactsByCustomer("JBoss");
          assertNotNull("JBoss contacts exist", jbContacts);
@@ -108,6 +113,7 @@
          }
          
          updateContacts("Kabir", "Updated");
+         assertEquals(contactSlcs.getElementCountInMemory(), 0);
          for (Integer id : jbContacts)
          {
             Contact contact = getContact(id);
@@ -120,6 +126,21 @@
          List<Integer> updated = getContactsByTLF("Updated");
          assertNotNull("Got updated contacts", updated);
          assertEquals("Updated contacts", 5, updated.size());
+         
+         updateContactsWithOneManual("Kabir", "UpdatedAgain");
+         assertEquals(contactSlcs.getElementCountInMemory(), 0);
+         for (Integer id : jbContacts)
+         {
+            Contact contact = getContact(id);
+            assertNotNull("JBoss contact " + id + " exists", contact);
+            String expected = ("Kabir".equals(contact.getName())) ? "UpdatedAgain" : "2222";
+            assertEquals("JBoss contact " + id + " has correct TLF",
+                         expected, contact.getTlf());
+         }
+         
+         updated = getContactsByTLF("UpdatedAgain");
+         assertNotNull("Got updated contacts", updated);
+         assertEquals("Updated contacts", 5, updated.size());
       }
       finally
       {
@@ -231,6 +252,34 @@
           throw e;         
       }     
    }
+
+   public int updateContactsWithOneManual(String name, String newTLF) throws Exception
+   {
+      String queryHQL = "from Contact c where c.name = :cName";
+      String updateHQL = "update Contact set tlf = :cNewTLF where name = :cName";
+
+      SimpleJtaTransactionManagerImpl.getInstance().begin();
+      try {
+          
+          Session session = getSessions().getCurrentSession();
+          
+          @SuppressWarnings("unchecked")
+          List<Contact> list = session.createQuery(queryHQL).setParameter("cName", name).list();
+          list.get(0).setTlf(newTLF);
+          
+          int rowsAffected = session.createQuery(updateHQL)
+                                .setFlushMode(FlushMode.AUTO)
+                                .setParameter("cNewTLF", newTLF)
+                                .setParameter("cName", name)
+                                .executeUpdate();
+          SimpleJtaTransactionManagerImpl.getInstance().commit();
+          return rowsAffected;       
+      }
+      catch (Exception e) {
+          SimpleJtaTransactionManagerImpl.getInstance().rollback();
+          throw e;         
+      }     
+   }
    
    public Contact getContact(Integer id) throws Exception
    {



More information about the hibernate-commits mailing list