[jboss-cvs] JBossAS SVN: r60250 - branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Feb 4 00:08:32 EST 2007


Author: bstansberry at jboss.com
Date: 2007-02-04 00:08:32 -0500 (Sun, 04 Feb 2007)
New Revision: 60250

Added:
   branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java
Modified:
   branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java
Log:
Port EJBTHREE-798 fix to Branch_4_2

Copied: branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java (from rev 60074, branches/Branch_4_0/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java)
===================================================================
--- branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java	                        (rev 0)
+++ branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java	2007-02-04 05:08:32 UTC (rev 60250)
@@ -0,0 +1,331 @@
+//$Id: TreeCache.java 9965 2006-05-30 18:00:28Z steve.ebersole at jboss.com $
+package org.jboss.ejb3.entity;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.StandardQueryCache;
+import org.hibernate.cache.UpdateTimestampsCache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+
+/**
+ * Subclass of the standard <code>org.hibernate.cache.TreeCache</code> used as
+ * a workaround until issues related to JBCLUSTER-150 are resolved in Hibernate.
+ *
+ * @author Gavin King
+ * @author Brian Stansberry
+ */
+public class JBCCache implements Cache {
+	
+	private static final Log log = LogFactory.getLog(JBCCache.class);
+
+	private static final String ITEM = "item";
+
+	private org.jboss.cache.TreeCache cache;
+	private final String regionName;
+	private final Fqn regionFqn;
+	private final TransactionManager transactionManager;
+    private boolean localWritesOnly;
+
+	public JBCCache(org.jboss.cache.TreeCache cache, String regionName, TransactionManager transactionManager) 
+	throws CacheException {
+		this.cache = cache;
+		this.regionName = regionName;
+		this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
+		this.transactionManager = transactionManager;
+        if (cache.getUseRegionBasedMarshalling())
+        {           
+           localWritesOnly = StandardQueryCache.class.getName().equals(regionName);
+           
+           boolean fetchState = cache.getFetchInMemoryState();
+           try
+           {
+              // We don't want a state transfer for the StandardQueryCache,
+              // as it can include classes from multiple scoped classloaders
+              if (localWritesOnly)
+                 cache.setFetchInMemoryState(false);
+              
+              // We always activate
+              activateCacheRegion(regionFqn.toString());
+           }
+           finally
+           {
+              // Restore the normal state transfer setting
+              if (localWritesOnly)
+                 cache.setFetchInMemoryState(fetchState);              
+           }
+        }
+        else
+        {
+           log.debug("TreeCache is not configured for region based marshalling");
+        }
+	}
+
+	public Object get(Object key) throws CacheException {
+		Transaction tx = suspend();
+		try {
+			return read(key);
+		}
+		finally {
+			resume( tx );
+		}
+	}
+	
+	public Object read(Object key) throws CacheException {
+		try {
+			return cache.get( new Fqn( regionFqn, key ), ITEM );
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void update(Object key, Object value) throws CacheException {
+		try {
+            if (localWritesOnly) {
+               Option option = new Option();
+               option.setCacheModeLocal(true);
+               cache.put( new Fqn( regionFqn, key ), ITEM, value, option );
+            }
+            else {               
+                cache.put( new Fqn( regionFqn, key ), ITEM, value );
+            }
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void put(Object key, Object value) throws CacheException {
+		Transaction tx = suspend();
+		try {
+           if (localWritesOnly) {
+              Option option = new Option();
+              option.setCacheModeLocal(true);
+              // Overloaded method isn't available, so have to use InvocationContext
+              cache.getInvocationContext().setOptionOverrides(option);
+              try {
+                  // do the failfast put outside the scope of the JTA txn
+                  cache.putFailFast( new Fqn( regionFqn, key ), ITEM, value, 0 );
+              }
+              finally {
+                 cache.getInvocationContext().setOptionOverrides(null);
+              }
+           }
+           else {               
+               //do the failfast put outside the scope of the JTA txn
+			   cache.putFailFast( new Fqn( regionFqn, key ), ITEM, value, 0 );
+           }
+		}
+		catch (TimeoutException te) {
+			//ignore!
+			log.debug("ignoring write lock acquisition failure");
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+		finally {
+			resume( tx );
+		}
+	}
+
+	private void resume(Transaction tx) {
+		try {
+			if (tx!=null) transactionManager.resume(tx);
+		}
+		catch (Exception e) {
+			throw new CacheException("Could not resume transaction", e);
+		}
+	}
+
+	private Transaction suspend() {
+		Transaction tx = null;
+		try {
+			if ( transactionManager!=null ) {
+				tx = transactionManager.suspend();
+			}
+		}
+		catch (SystemException se) {
+			throw new CacheException("Could not suspend transaction", se);
+		}
+		return tx;
+	}
+
+	public void remove(Object key) throws CacheException {
+		try {
+           if (localWritesOnly) {
+              Option option = new Option();
+              option.setCacheModeLocal(true);
+              cache.remove( new Fqn( regionFqn, key ), option );
+           }
+           else {               
+               cache.remove( new Fqn( regionFqn, key ) );
+           }
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void clear() throws CacheException {
+		try {
+			cache.remove( regionFqn );
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public void destroy() throws CacheException {
+		try {
+			// NOTE : evict() operates locally only (i.e., does not propogate
+			// to any other nodes in the potential cluster).  This is
+			// exactly what is needed when we destroy() here; destroy() is used
+			// as part of the process of shutting down a SessionFactory; thus
+			// these removals should not be propogated
+			cache.evict( regionFqn );
+            
+            if (cache.getUseRegionBasedMarshalling() && !isSharedClassLoaderRegion(regionName))
+            {
+               inactivateCacheRegion();
+            }
+		}
+        catch (CacheException e)
+        {
+           throw e;
+        }
+		catch( Exception e ) {
+			throw new CacheException( e );
+		}
+	}
+
+	public void lock(Object key) throws CacheException {
+		throw new UnsupportedOperationException( "TreeCache is a fully transactional cache" + regionName );
+	}
+
+	public void unlock(Object key) throws CacheException {
+		throw new UnsupportedOperationException( "TreeCache is a fully transactional cache: " + regionName );
+	}
+
+	public long nextTimestamp() {
+		return System.currentTimeMillis() / 100;
+	}
+
+	public int getTimeout() {
+		return 600; //60 seconds
+	}
+
+	public String getRegionName() {
+		return regionName;
+	}
+
+	public long getSizeInMemory() {
+		return -1;
+	}
+
+	public long getElementCountInMemory() {
+		try {
+			Set children = cache.getChildrenNames( regionFqn );
+			return children == null ? 0 : children.size();
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+
+	public long getElementCountOnDisk() {
+		return 0;
+	}
+	
+	public Map toMap() {
+		try {
+			Map result = new HashMap();
+			Set childrenNames = cache.getChildrenNames( regionFqn );
+			if (childrenNames != null) {
+				Iterator iter = childrenNames.iterator();
+				while ( iter.hasNext() ) {
+					Object key = iter.next();
+					result.put( 
+							key, 
+							cache.get( new Fqn( regionFqn, key ), ITEM )
+						);
+				}
+			}
+			return result;
+		}
+		catch (Exception e) {
+			throw new CacheException(e);
+		}
+	}
+	
+	public String toString() {
+		return "TreeCache(" + regionName + ')';
+	}
+       
+    private boolean isSharedClassLoaderRegion(String regionName)
+    {
+       return (StandardQueryCache.class.getName().equals(regionName) 
+                || UpdateTimestampsCache.class.getName().equals(regionName));
+    }
+    
+    private void activateCacheRegion(String regionName) throws CacheException
+    {
+       String fqnString = regionFqn.toString();
+       // FIXME -- find a way that doesn't involve this API
+       if (cache.getMarshaller().isInactive(fqnString))
+       {
+          try
+          {
+             // Only register the classloader if it's not a shared region.  
+             // If it's shared, no single classloader is valid
+             if (!isSharedClassLoaderRegion(regionName))
+             {
+                cache.registerClassLoader(fqnString, Thread.currentThread().getContextClassLoader());
+             }
+             cache.activateRegion(fqnString);
+          }
+          catch (Exception e)
+          {
+             throw new CacheException("Problem activating region " + regionName, e);
+          }
+       }
+       else
+       {
+          log.debug("activateCacheRegion(): Region " + fqnString + " is already active");
+       }
+    }
+    
+    private void inactivateCacheRegion() throws CacheException
+    {
+       String fqnString = regionFqn.toString();
+       // FIXME -- find a way that doesn't involve this API
+       if (!cache.getMarshaller().isInactive(fqnString))
+       {
+          try
+          {
+             cache.inactivateRegion(fqnString);
+             cache.unregisterClassLoader(fqnString);
+          }
+          catch (Exception e)
+          {
+             throw new CacheException("Problem activating region " + fqnString, e);
+          }
+       }     
+       else
+       {
+          log.debug("inactivateCacheRegion(): Region " + fqnString + " is already inactive");
+       }
+    }	
+}

Modified: branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java
===================================================================
--- branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2007-02-04 05:07:36 UTC (rev 60249)
+++ branches/Branch_4_2/ejb3/src/main/org/jboss/ejb3/entity/TreeCacheProviderHook.java	2007-02-04 05:08:32 UTC (rev 60250)
@@ -23,9 +23,15 @@
 
 import java.util.Properties;
 
+import javax.management.ObjectName;
+
 import org.hibernate.cache.Cache;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.CacheProvider;
+import org.jboss.cache.TreeCacheMBean;
+import org.jboss.ejb3.tx.TxUtil;
+import org.jboss.mx.util.MBeanProxyExt;
+import org.jboss.mx.util.MBeanServerLocator;
 
 /**
  * Support for a standalone JBossCache (TreeCache) instance.  The JBossCache is configured
@@ -36,8 +42,9 @@
  */
 public class TreeCacheProviderHook implements CacheProvider
 {
-   private TransactionalCacheFactory cacheFactory;
 
+   private org.jboss.cache.TreeCache cache;
+
    /**
     * Construct and configure the Cache representation of a named cache region.
     *
@@ -49,8 +56,7 @@
     */
    public Cache buildCache(String regionName, Properties properties) throws CacheException
    {
-//      return new TreeCache(cache, regionName, TxUtil.getTransactionManager());
-      return cacheFactory.buildCache(regionName, properties);
+      return new JBCCache(cache, regionName, TxUtil.getTransactionManager());
    }
 
    public boolean isMinimalPutsEnabledByDefault()
@@ -72,17 +78,16 @@
     */
    public void start(Properties properties)
    {
-      cacheFactory = TransactionalCacheFactory.getFactory(properties);
-//      try
-//      {
-//         ObjectName mbeanObjectName = new ObjectName((String) properties.get("hibernate.treecache.mbean.object_name"));
-//         TreeCacheMBean mbean = (TreeCacheMBean) MBeanProxyExt.create(TreeCacheMBean.class, mbeanObjectName, MBeanServerLocator.locateJBoss());
-//         cache = mbean.getInstance();
-//      }
-//      catch (Exception e)
-//      {
-//         throw new CacheException(e);
-//      }
+      try
+      {
+         ObjectName mbeanObjectName = new ObjectName((String) properties.get("hibernate.treecache.mbean.object_name"));
+         TreeCacheMBean mbean = (TreeCacheMBean) MBeanProxyExt.create(TreeCacheMBean.class, mbeanObjectName, MBeanServerLocator.locateJBoss());
+         cache = mbean.getInstance();
+      }
+      catch (Exception e)
+      {
+         throw new CacheException(e);
+      }
    }
 
    public void stop()




More information about the jboss-cvs-commits mailing list