Author: bstansberry(a)jboss.com
Date: 2007-12-23 09:59:07 -0500 (Sun, 23 Dec 2007)
New Revision: 14263
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
Log:
Update handling of deletion of the region root node
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -40,11 +40,16 @@
import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.jboss.cache.notifications.annotation.NodeCreated;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
import org.jboss.cache.notifications.event.NodeCreatedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
import org.jboss.cache.optimistic.DataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.builder.JndiMultiplexingCacheInstanceManager;
import org.hibernate.cache.jbc2.util.CacheHelper;
import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
@@ -56,16 +61,20 @@
*/
@CacheListener
public abstract class BasicRegionAdapter implements Region {
+
+
public static final String ITEM = CacheHelper.ITEM;
protected final Cache jbcCache;
protected final String regionName;
protected final Fqn regionFqn;
+ protected Node regionRoot;
protected final boolean optimistic;
-
protected final TransactionManager transactionManager;
+ protected final Logger log;
+ protected final Object regionRootMutex = new Object();
- protected SetResidentListener listener;
+ protected RegionRootListener listener;
public BasicRegionAdapter(Cache jbcCache, String regionName, String regionPrefix) {
this.jbcCache = jbcCache;
@@ -73,6 +82,7 @@
this.regionName = regionName;
this.regionFqn = createRegionFqn(regionName, regionPrefix);
optimistic = jbcCache.getConfiguration().getNodeLockingScheme() ==
NodeLockingScheme.OPTIMISTIC;
+ log = LoggerFactory.getLogger(getClass());
activateLocalClusterNode();
}
@@ -97,33 +107,50 @@
// and then need to re-add it. In that case, the fact
// that it is resident will not replicate, so use a listener
// to set it as resident
- if (CacheHelper.isClusteredReplication(cfg.getCacheMode())) {
- listener = new SetResidentListener();
+ if (CacheHelper.isClusteredReplication(cfg.getCacheMode())
+ || CacheHelper.isClusteredInvalidation(cfg.getCacheMode())) {
+ listener = new RegionRootListener();
jbcCache.addCacheListener(listener);
}
- // Make sure the root node for the region exists and
- // has a DataVersion that never complains
- Node regionRoot = jbcCache.getRoot().getChild( regionFqn );
- if (regionRoot == null) {
- // Establish the region root node with a non-locking data version
- DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE :
null;
- regionRoot = CacheHelper.addNode(jbcCache, regionFqn, true, true,
version);
- }
- else if (optimistic && regionRoot instanceof NodeSPI) {
- // FIXME Hacky workaround to JBCACHE-1202
- if ( !( ( ( NodeSPI ) regionRoot ).getVersion() instanceof
NonLockingDataVersion ) ) {
- ((NodeSPI) regionRoot).setVersion(NonLockingDataVersion.INSTANCE);
- }
- }
- // Never evict this node
- regionRoot.setResident(true);
+ establishRegionRootNode();
}
catch (Exception e) {
throw new CacheException(e.getMessage(), e);
}
}
+ private void establishRegionRootNode()
+ {
+ synchronized (regionRootMutex) {
+ if (regionRoot != null && regionRoot.isValid())
+ return;
+ // Don't hold a transactional lock for this
+ Transaction tx = suspend();
+ try {
+ // Make sure the root node for the region exists and
+ // has a DataVersion that never complains
+ regionRoot = jbcCache.getRoot().getChild( regionFqn );
+ if (regionRoot == null) {
+ // Establish the region root node with a non-locking data version
+ DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE :
null;
+ regionRoot = CacheHelper.addNode(jbcCache, regionFqn, true, true,
version);
+ }
+ else if (optimistic && regionRoot instanceof NodeSPI) {
+ // FIXME Hacky workaround to JBCACHE-1202
+ if ( !( ( ( NodeSPI ) regionRoot ).getVersion() instanceof
NonLockingDataVersion ) ) {
+ ((NodeSPI)
regionRoot).setVersion(NonLockingDataVersion.INSTANCE);
+ }
+ }
+ // Never evict this node
+ regionRoot.setResident(true);
+ }
+ finally {
+ resume(tx);
+ }
+ }
+ }
+
public String getName() {
return regionName;
}
@@ -135,12 +162,29 @@
public Fqn getRegionFqn() {
return regionFqn;
}
+
+ /**
+ * If the cache is configured for optimistic locking, checks for the
+ * validity of the root cache node for this region,
+ * creating a new one if it does not exist or is invalid. Suspends any
+ * transaction while doing this to ensure no transactional locks are held
+ * on the region root.
+ *
+ * This is only needed for optimistic locking, as with optimistic the
+ * region root node has a special version that must be established.
+ *
+ * TODO remove this once JBCACHE-1250 is resolved.
+ */
+ public void ensureRegionRootExists() {
+ if (optimistic && (regionRoot == null || !regionRoot.isValid()))
+ establishRegionRootNode();
+ }
public void destroy() throws CacheException {
try {
// NOTE : this is being used from the process of shutting down a
// SessionFactory. Specific things to consider:
- // (1) this clearing of the region should not propogate to
+ // (1) this clearing of the region should not propagate to
// other nodes on the cluster (if any); this is the
// cache-mode-local option bit...
// (2) really just trying a best effort to cleanup after
@@ -321,11 +365,12 @@
}
@CacheListener
- public class SetResidentListener {
+ 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);
}
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -27,11 +27,11 @@
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;
import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
-import org.jboss.cache.Cache;
-import org.jboss.cache.Fqn;
import org.jboss.cache.config.Option;
import org.jboss.cache.optimistic.DataVersion;
@@ -51,9 +51,9 @@
protected final CacheDataDescription dataDescription;
- public OptimisticTransactionalAccessDelegate(Cache cache, Fqn regionFqn,
CacheDataDescription dataDescription) {
- super(cache, regionFqn);
- this.dataDescription = dataDescription;
+ public OptimisticTransactionalAccessDelegate(TransactionalDataRegionAdapter region)
{
+ super(region);
+ this.dataDescription = region.getCacheDataDescription();
}
/**
@@ -63,6 +63,8 @@
*/
@Override
public void evict(Object key) throws CacheException {
+
+ region.ensureRegionRootExists();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.remove(cache, regionFqn, key, opt);
@@ -76,6 +78,18 @@
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
+ {
+ region.ensureRegionRootExists();
+ return super.get(key, txTimestamp);
}
/**
@@ -85,6 +99,8 @@
*/
@Override
public boolean insert(Object key, Object value, Object version) throws CacheException
{
+
+ region.ensureRegionRootExists();
Option opt = getDataVersionOption(version, null);
CacheHelper.put(cache, regionFqn, key, value, opt);
@@ -94,6 +110,8 @@
@Override
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object
version, boolean minimalPutOverride)
throws CacheException {
+
+ region.ensureRegionRootExists();
// We ignore minimalPutOverride. JBossCache putForExternalRead is
// already about as minimal as we can get; it will promptly return
@@ -104,6 +122,8 @@
@Override
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object
version) throws CacheException {
+
+ region.ensureRegionRootExists();
Option opt = getDataVersionOption(version, version);
return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
@@ -111,6 +131,8 @@
@Override
public void remove(Object key) throws CacheException {
+
+ region.ensureRegionRootExists();
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.remove(cache, regionFqn, key, opt);
@@ -125,6 +147,8 @@
@Override
public boolean update(Object key, Object value, Object currentVersion, Object
previousVersion)
throws CacheException {
+
+ region.ensureRegionRootExists();
Option opt = getDataVersionOption(currentVersion, previousVersion);
CacheHelper.put(cache, regionFqn, key, value, opt);
@@ -132,6 +156,7 @@
}
private Option getDataVersionOption(Object currentVersion, Object previousVersion) {
+
DataVersion dv = (dataDescription != null &&
dataDescription.isVersioned()) ? new DataVersionAdapter(
currentVersion, previousVersion, dataDescription.getVersionComparator(),
dataDescription.toString())
: NonLockingDataVersion.INSTANCE;
@@ -141,6 +166,7 @@
}
private void evictOrRemoveAll() {
+
Option opt = NonLockingDataVersion.getInvocationOption();
CacheHelper.removeAll(cache, regionFqn, opt);
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -27,6 +27,7 @@
import org.hibernate.cache.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
import org.hibernate.cache.jbc2.util.CacheHelper;
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
@@ -46,10 +47,12 @@
protected final Cache cache;
protected final Fqn regionFqn;
+ protected final BasicRegionAdapter region;
- public TransactionalAccessDelegate(Cache cache, Fqn regionFqn) {
- this.cache = cache;
- this.regionFqn = regionFqn;
+ public TransactionalAccessDelegate(BasicRegionAdapter adapter) {
+ this.region = adapter;
+ this.cache = adapter.getCacheInstance();
+ this.regionFqn = adapter.getRegionFqn();
}
public Object get(Object key, long txTimestamp) throws CacheException {
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -42,8 +42,7 @@
public OptimisticTransactionalAccess(CollectionRegionImpl region) {
// We use a different delegate than the non-optimistic superclass default
- super(region, new
OptimisticTransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn(),
- region.getCacheDataDescription()));
+ super(region, new OptimisticTransactionalAccessDelegate(region));
}
}
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -52,7 +52,7 @@
* @param region the region to which this provides access
*/
public TransactionalAccess(CollectionRegionImpl region) {
- this(region, new TransactionalAccessDelegate(region.getCacheInstance(),
region.getRegionFqn()));
+ this(region, new TransactionalAccessDelegate(region));
}
/**
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -41,7 +41,6 @@
* @param region The region\ to which this is providing access
*/
public OptimisticTransactionalAccess(EntityRegionImpl region) {
- super(region, new
OptimisticTransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn(),
- region.getCacheDataDescription()));
+ super(region, new OptimisticTransactionalAccessDelegate(region));
}
}
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -46,7 +46,7 @@
private final TransactionalAccessDelegate delegate;
public TransactionalAccess(EntityRegionImpl region) {
- this(region, new TransactionalAccessDelegate(region.getCacheInstance(),
region.getRegionFqn()));
+ this(region, new TransactionalAccessDelegate(region));
}
protected TransactionalAccess(EntityRegionImpl region, TransactionalAccessDelegate
delegate) {
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -75,6 +75,9 @@
}
public void evict(Object key) throws CacheException {
+
+ ensureRegionRootExists();
+
Option opt = getNonLockingDataVersionOption(false);
if (localOnly)
opt.setCacheModeLocal(true);
@@ -91,6 +94,8 @@
}
public Object get(Object key) throws CacheException {
+
+ ensureRegionRootExists();
// Don't hold the JBC node lock throughout the tx, as that
// prevents updates
@@ -102,6 +107,8 @@
}
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
@@ -110,9 +117,9 @@
// 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
+ // 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 for concurrent reads.
+ // 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
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
===================================================================
---
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java 2007-12-23
14:55:36 UTC (rev 14262)
+++
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java 2007-12-23
14:59:07 UTC (rev 14263)
@@ -85,6 +85,9 @@
}
public void evict(Object key) throws CacheException {
+
+ ensureRegionRootExists();
+
// TODO Is this a valid operation on a timestamps cache?
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.removeNode(getCacheInstance(), getRegionFqn(), key, opt);
@@ -102,6 +105,9 @@
Object value = localCache.get(key);
if (value == null) {
+
+ ensureRegionRootExists();
+
value = suspendAndGet(key, null, false);
if (value != null)
localCache.put(key, value);
@@ -110,6 +116,8 @@
}
public void put(Object key, Object value) throws CacheException {
+
+ ensureRegionRootExists();
// Don't hold the JBC node lock throughout the tx, as that
// prevents reads and other updates