Author: jason.greene(a)jboss.com
Date: 2008-01-16 17:13:38 -0500 (Wed, 16 Jan 2008)
New Revision: 5149
Added:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCacheThreadContext.java
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheThreadContextImpl.java
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/PojoCacheThreadContextTest.java
Modified:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCache.java
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/BuddyReplicationTest.java
Log:
Implement PCACHE-59
Modified: pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCache.java
===================================================================
--- pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCache.java 2008-01-16
20:52:01 UTC (rev 5148)
+++ pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCache.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -241,6 +241,13 @@
* @param listener the listener to remove
*/
void removeListener(Object listener);
+
+ /**
+ * Get's the thread context for all POJO Cache operations.
+ *
+ * @return the current thread's context
+ */
+ PojoCacheThreadContext getThreadContext();
/**
* Obtain the underlying generic cache system. Use this for non-POJO cache operation,
e.g.
Added: pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCacheThreadContext.java
===================================================================
--- pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCacheThreadContext.java
(rev 0)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/PojoCacheThreadContext.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -0,0 +1,49 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+*/
+
+package org.jboss.cache.pojo;
+
+
+/**
+ * Represents the thread specific context for POJO Cache operations against a particular
cache instance. This is
+ * primarily used to change thread specific options. Once set, they remain for the entire
lifetime of the thread.
+ *
+ * Instances of this class can only be obtained by {@link PojoCache#getThreadContext}
+ *
+ * @author Jason T. Greene
+ */
+public interface PojoCacheThreadContext
+{
+ /**
+ * Returns whether or not this thread should trigger gravitation when a cache-miss
occurs. The default is false.
+ *
+ * @return true if gravitation should be triggered on cache-miss, false if gravitation
should not be triggered
+ */
+ public boolean isGravitationEnabled();
+
+ /**
+ * Enables or disables gravitation on cache-miss
+ *
+ * @param gravitate true if gravitation should be triggered on cache-miss, false if
gravitation should not be triggered
+ */
+ public void setGravitationEnabled(boolean gravitate);
+}
\ No newline at end of file
Modified: pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java
===================================================================
---
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java 2008-01-16
20:52:01 UTC (rev 5148)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -13,6 +13,7 @@
import org.jboss.cache.Cache;
import org.jboss.cache.CacheException;
import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCache;
import org.jboss.cache.pojo.PojoCacheException;
import org.jboss.cache.pojo.util.ObjectUtil;
@@ -26,11 +27,13 @@
{
private static Log log = LogFactory.getLog(InternalHelper.class.getName());
- private Cache cache;
+ private Cache<Object, Object> cache;
+ private PojoCache pcache;
- InternalHelper(Cache cache)
+ InternalHelper(PojoCache pcache)
{
- this.cache = cache;
+ this.cache = pcache.getCache();
+ this.pcache = pcache;
}
PojoInstance getPojoInstance(Fqn fqn) throws CacheException
@@ -86,7 +89,8 @@
private Object get(Fqn fqn, Object key, boolean gravitate) throws CacheException
{
- if (gravitate)
+ // Only gravitate when we have to and only when the user has enabled it
+ if (gravitate && pcache.getThreadContext().isGravitationEnabled())
{
cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
Object obj = cache.get(fqn, key);
Modified:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java
===================================================================
---
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java 2008-01-16
20:52:01 UTC (rev 5148)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -58,7 +58,7 @@
{
pojoCache = cache;
this.cache = pojoCache.getCache();
- internal_ = new InternalHelper(this.cache);
+ internal_ = new InternalHelper(cache);
graphHandler_ = new ObjectGraphHandler(pojoCache, internal_);
collectionHandler_ = new CollectionClassHandler(pojoCache, internal_);
serializableHandler_ = new SerializableObjectHandler(pojoCache, internal_);
Modified: pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
===================================================================
---
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java 2008-01-16
20:52:01 UTC (rev 5148)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -24,6 +24,7 @@
import org.jboss.cache.factories.XmlConfigurationParser;
import org.jboss.cache.pojo.PojoCache;
import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.PojoCacheThreadContext;
import org.jboss.cache.pojo.annotation.Attach;
import org.jboss.cache.pojo.annotation.Detach;
import org.jboss.cache.pojo.annotation.Find;
@@ -44,6 +45,7 @@
private Map cachedTypes_ = new WeakHashMap();
private boolean hasCreate_ = false;
private CacheListenerAdaptor listenerAdaptor = new CacheListenerAdaptor(this);
+ private PojoCacheThreadContext threadContext = new PojoCacheThreadContextImpl();
public PojoCacheImpl(String configStr, boolean toStart)
{
@@ -317,6 +319,11 @@
cache.removeCacheListener(listenerAdaptor);
}
}
+
+ public PojoCacheThreadContext getThreadContext()
+ {
+ return threadContext;
+ }
public Cache<Object,Object> getCache()
{
Added:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheThreadContextImpl.java
===================================================================
---
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheThreadContextImpl.java
(rev 0)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheThreadContextImpl.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -0,0 +1,46 @@
+package org.jboss.cache.pojo.impl;
+
+import org.jboss.cache.pojo.PojoCacheThreadContext;
+
+public class PojoCacheThreadContextImpl implements PojoCacheThreadContext
+{
+ private static final int GRAVITATE = 0;
+ private static final Boolean GRAVITATE_DEFAULT = false;
+
+ // Every cache instance gets it's own configuration
+ // An array is used to conserve memory usage since reclamation is slow with TLs, and
prevent CL leaks
+ // In the future, if we get multiple booleans, use bitwise operations on an integer
+ // as the first entry
+ private final ThreadLocal<Object[]> state = new ThreadLocal<Object[]>()
+ {
+ @Override
+ protected Object[] initialValue()
+ {
+ return new Object[] {GRAVITATE_DEFAULT};
+ }
+ };
+
+ PojoCacheThreadContextImpl()
+ {
+ }
+
+ /**
+ * Returns whether or not this thread should trigger gravitation when a cache-miss
occurs. The default is false.
+ *
+ * @return true if gravitation should be triggered on cache-miss, false if gravitation
should not be triggered
+ */
+ public boolean isGravitationEnabled()
+ {
+ return (Boolean) state.get()[GRAVITATE];
+ }
+
+ /**
+ * Enables or disables gravitation on cache-miss
+ *
+ * @param gravitate true if gravitation should be triggered on cache-miss, false if
gravitation should not be triggered
+ */
+ public void setGravitationEnabled(boolean gravitate)
+ {
+ state.get()[GRAVITATE] = gravitate;
+ }
+}
Modified: pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/BuddyReplicationTest.java
===================================================================
---
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/BuddyReplicationTest.java 2008-01-16
20:52:01 UTC (rev 5148)
+++
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/BuddyReplicationTest.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -65,6 +65,10 @@
addBuddyReplication(cfg2);
cache1 = PojoCacheFactory.createCache(cfg2, toStart);
cache1.start();
+
+ // Enable gravitation
+ cache.getThreadContext().setGravitationEnabled(true);
+ cache1.getThreadContext().setGravitationEnabled(true);
}
@AfterMethod(alwaysRun = true)
Added:
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/PojoCacheThreadContextTest.java
===================================================================
--- pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/PojoCacheThreadContextTest.java
(rev 0)
+++
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/PojoCacheThreadContextTest.java 2008-01-16
22:13:38 UTC (rev 5149)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.jboss.cache.pojo;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNull;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.buddyreplication.NextMemberBuddyLocatorConfig;
+import org.jboss.cache.config.BuddyReplicationConfig;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
+import org.jboss.cache.pojo.test.Person;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * A BuddyReplicatedTest.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian
Stansberry</a>
+ * @version $Revision: 4717 $
+ */
+@Test(groups = {"functional"})
+public class PojoCacheThreadContextTest
+{
+ Log log = LogFactory.getLog(ReplicatedTest.class);
+ volatile PojoCache cache, cache1;
+
+ @BeforeMethod(alwaysRun = true)
+ protected void setUp() throws Exception
+ {
+ log.info("setUp() ....");
+ boolean toStart = false;
+ Configuration cfg1 =
UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.LOCAL);
+ cache = PojoCacheFactory.createCache(cfg1, toStart);
+ cache.start();
+ Configuration cfg2 =
UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.LOCAL);
+ cache1 = PojoCacheFactory.createCache(cfg2, toStart);
+ cache1.start();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ protected void tearDown() throws Exception
+ {
+ cache.stop();
+ cache1.stop();
+ }
+
+ public void testDefault()
+ {
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), false);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), false);
+ }
+
+ private class TestThread extends Thread
+ {
+ public volatile Throwable t;
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ cache1.getThreadContext().setGravitationEnabled(true);
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), false);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), true);
+
+ cache.getThreadContext().setGravitationEnabled(true);
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), true);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), true);
+ }
+ catch (Throwable t)
+ {
+ this.t = t;
+ }
+ }
+ };
+
+ public void testThreadIsolation() throws Throwable
+ {
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), false);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), false);
+
+
+ TestThread t1 = new TestThread();
+ t1.start();
+ t1.join();
+ if (t1.t != null)
+ throw t1.t;
+
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), false);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), false);
+
+ cache1.getThreadContext().setGravitationEnabled(true);
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), false);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), true);
+ t1 = new TestThread();
+ t1.start();
+ t1.join();
+ if (t1.t != null)
+ throw t1.t;
+
+ assertEquals(cache.getThreadContext().isGravitationEnabled(), false);
+ assertEquals(cache1.getThreadContext().isGravitationEnabled(), true);
+ }
+}