[jbosscache-commits] JBoss Cache SVN: r8238 - in core/branches/1.4.X: src/org/jboss/cache/interceptors and 2 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Thu Sep 24 07:32:14 EDT 2009


Author: galder.zamarreno at jboss.com
Date: 2009-09-24 07:32:13 -0400 (Thu, 24 Sep 2009)
New Revision: 8238

Added:
   core/branches/1.4.X/etc/META-INF/optimistic-replicated-eviction.xml
   core/branches/1.4.X/tests/functional/org/jboss/cache/eviction/OptimisticReplicatedEvictionTest.java
Modified:
   core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
   core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/NodeInterceptorRemoveNodeTest.java
Log:
[JBCACHE-1545] OL queues removal modifications even if the node was not present locally.

Added: core/branches/1.4.X/etc/META-INF/optimistic-replicated-eviction.xml
===================================================================
--- core/branches/1.4.X/etc/META-INF/optimistic-replicated-eviction.xml	                        (rev 0)
+++ core/branches/1.4.X/etc/META-INF/optimistic-replicated-eviction.xml	2009-09-24 11:32:13 UTC (rev 8238)
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Sample TreeCache Service Configuration                               -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<server>
+
+    <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+    <!-- ==================================================================== -->
+    <!-- Defines TreeCache configuration                                      -->
+    <!-- ==================================================================== -->
+
+    <mbean code="org.jboss.cache.TreeCache"
+        name="jboss.cache:service=TreeCache">
+
+        <depends>jboss:service=Naming</depends>
+        <depends>jboss:service=TransactionManager</depends>
+
+        <!--
+            Configure the TransactionManager
+        -->
+        <attribute name="TransactionManagerLookupClass">org.jboss.cache.DummyTransactionManagerLookup</attribute>
+
+        <attribute name="FetchInMemoryState">false</attribute>
+        <attribute name="FetchPersistentState">false</attribute>
+        <!--  Whether each interceptor should have an mbean
+              registered to capture and display its statistics.  -->
+        <attribute name="UseInterceptorMbeans">true</attribute>
+
+        <!--
+            Node locking scheme:
+                OPTIMISTIC
+                PESSIMISTIC (default)
+        -->
+        <attribute name="NodeLockingScheme">Optimistic</attribute>
+
+        <!--
+            Node locking level : SERIALIZABLE
+                                 REPEATABLE_READ (default)
+                                 READ_COMMITTED
+                                 READ_UNCOMMITTED
+                                 NONE
+        -->
+        <attribute name="IsolationLevel">READ_COMMITTED</attribute>
+
+
+        <!--
+             Valid modes are LOCAL
+                             REPL_ASYNC
+                             REPL_SYNC
+        -->
+        <attribute name="CacheMode">REPL_SYNC</attribute>
+
+        <!-- Name of cluster. Needs to be the same for all clusters, in order
+             to find each other
+        -->
+        <attribute name="ClusterName">Infa-Cache-Cluster</attribute>
+        
+        <attribute name="ClusterConfig">
+            <config>
+                <!-- UDP: if you have a multihomed machine,
+                set the bind_addr attribute to the appropriate NIC IP address, e.g bind_addr="192.168.0.2"
+                -->
+                <!-- UDP: On Windows machines, because of the media sense feature
+                 being broken with multicast (even after disabling media sense)
+                 set the loopback attribute to true -->
+                <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+                    ip_ttl="64" ip_mcast="true" 
+                    mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+                    ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+                    loopback="false"/>
+                <PING timeout="2000" num_initial_members="3"
+                    up_thread="false" down_thread="false"/>
+                <MERGE2 min_interval="10000" max_interval="20000"/>
+                <!--        <FD shun="true" up_thread="true" down_thread="true" />-->
+                <FD_SOCK/>
+                <VERIFY_SUSPECT timeout="1500"
+                    up_thread="false" down_thread="false"/>
+                <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+                    max_xmit_size="8192" up_thread="false" down_thread="false"/>
+                <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"
+                    down_thread="false"/>
+                <pbcast.STABLE desired_avg_gossip="20000"
+                    up_thread="false" down_thread="false"/>
+                <FRAG frag_size="8192"
+                    down_thread="false" up_thread="false"/>
+                <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+                    shun="true" print_local_addr="true"/>
+                <pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>
+            </config>
+        </attribute>        
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <attribute name="LockAcquisitionTimeout">1000</attribute>
+
+        <!-- Name of the eviction policy class.-->
+        <attribute name="EvictionPolicyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+        <attribute name="EvictionPolicyConfig">
+            <config>
+                <attribute name="wakeUpIntervalSeconds">1</attribute>
+                <region name="/_default_">
+                    <attribute name="maxNodes">10</attribute>
+                    <attribute name="timeToLiveSeconds">0</attribute>
+                    <attribute name="maxAgeSeconds">0</attribute>
+                </region>
+                <region name="/testingRegion">
+                    <attribute name="maxNodes">10</attribute>
+                    <attribute name="timeToLiveSeconds">0</attribute>
+                    <attribute name="maxAgeSeconds">0</attribute>
+                </region>
+                <region name="/timeBased">
+                    <attribute name="maxNodes">10</attribute>
+                    <attribute name="timeToLiveSeconds">1</attribute>
+                    <attribute name="maxAgeSeconds">1</attribute>
+                </region>
+                <region name="/timeToLiveBased">
+                    <attribute name="maxNodes">10</attribute>
+                    <attribute name="timeToLiveSeconds">5</attribute>
+                    <attribute name="maxAgeSeconds">0</attribute>
+                </region>
+            </config>
+        </attribute>
+
+    </mbean>
+</server>

Modified: core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java	2009-09-24 10:28:05 UTC (rev 8237)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/OptimisticNodeInterceptor.java	2009-09-24 11:32:13 UTC (rev 8238)
@@ -101,6 +101,14 @@
             else
             {
                log.trace("Workspace node is null.  Perhaps it has been deleted?");
+               // However, if a removal was requested to a node we don't have, we should still propagate it!!
+               Option opt = ctx.getOptionOverrides();
+               if ((opt == null || !opt.isCacheModeLocal()) && m.getMethodId() == MethodDeclarations.removeNodeMethodLocal_id)
+               {
+                  txTable.addModification(gtx, m);
+                  if (log.isDebugEnabled()) log.debug("Adding Method " + m + " to modification list");
+               }
+               if (cache.getCacheLoaderManager() != null) txTable.addCacheLoaderModification(gtx, m);
                return null;
             }
          }

Added: core/branches/1.4.X/tests/functional/org/jboss/cache/eviction/OptimisticReplicatedEvictionTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/eviction/OptimisticReplicatedEvictionTest.java	                        (rev 0)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/eviction/OptimisticReplicatedEvictionTest.java	2009-09-24 11:32:13 UTC (rev 8238)
@@ -0,0 +1,182 @@
+package org.jboss.cache.eviction;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.AbstractTreeCacheListener;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.ExtendedTreeCacheListener;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.PropertyConfigurator;
+import org.jboss.cache.TreeCache;
+
+import EDU.oswego.cs.dl.util.concurrent.BoundedLinkedQueue;
+import EDU.oswego.cs.dl.util.concurrent.Callable;
+import EDU.oswego.cs.dl.util.concurrent.Executor;
+import EDU.oswego.cs.dl.util.concurrent.FutureResult;
+import EDU.oswego.cs.dl.util.concurrent.ThreadedExecutor;
+
+public class OptimisticReplicatedEvictionTest extends TestCase
+{
+   private static final Log log = LogFactory.getLog(OptimisticReplicatedEvictionTest.class);
+
+    private TreeCache cache1;
+    private TreeCache cache2;
+    
+    private BoundedLinkedQueue queue = new BoundedLinkedQueue();
+    private static final Fqn SHUTDOWN_FQN = new Fqn("time-to-shutdown");
+    
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        
+        cache1 = new TreeCache();
+        PropertyConfigurator config1 = new PropertyConfigurator();
+        config1.configure(cache1, "META-INF/optimistic-replicated-eviction.xml");
+        cache1.startService();
+                
+        cache2 = new TreeCache();
+        PropertyConfigurator config2 = new PropertyConfigurator();
+        config2.configure(cache2, "META-INF/optimistic-replicated-eviction.xml");
+        RemovalThread removalThread = new RemovalThread(cache2);
+        log.trace("Starting the removal thread...");
+        removalThread.start();
+        EvictionListener listener = new EvictionListener();
+        log.trace("Listening for evictions...");
+        cache2.addTreeCacheListener(listener);
+        cache2.startService();
+    }
+
+    protected void tearDown() throws Exception
+    {
+        if (cache1 != null)
+        {
+            cache1.stopService();
+            cache1 = null;
+        }
+        super.tearDown();
+    }
+    
+    public void testClusteredEvictionToClearVersionInfo() throws Exception 
+    {
+       cache1.put( "/timeToLiveBased/test000", "k-allele", "v1-allele" ); // this could be from any node 
+       cache1.put( "/timeToLiveBased/test000", "k-allele", "v2-allele" ); // v2
+
+       Callable c = new Callable() {
+         public Object call() throws Exception {
+            Thread.sleep(8 * 1000);
+            Object ret = cache2.put("/timeToLiveBased/test000", "k-allele", "v3-allele" ); // will always fail during replication to A:
+            if (ret instanceof Exception) throw (Exception) ret;
+            return null;
+         }
+      };
+      
+      Executor executor = new ThreadedExecutor();
+      FutureResult f = new FutureResult();
+      Runnable command = f.setter(c);
+      executor.execute(command);
+       
+      for (;;) 
+      {
+         if (f.isReady()) 
+         {
+            f.get();
+            break;
+         }
+         else 
+         {
+            Thread.sleep(2 * 1000);
+         }
+         cache1.get("/timeToLiveBased/test000", "k-allele"); // refresh the eviction timer so the node will never be evicted on A
+      }
+       
+       assertEquals(cache1.get("/timeToLiveBased/test000", "k-allele"), "v3-allele");
+       assertEquals(cache2.get("/timeToLiveBased/test000", "k-allele"), "v3-allele");
+    }
+    
+    // Jimmy's cluster wide removal workaround
+    /**
+     * An inner class that serves as a listener for cache eviction events.
+     */
+    private class EvictionListener extends AbstractTreeCacheListener implements ExtendedTreeCacheListener
+    {
+        public void nodeEvict(Fqn fqn, boolean pre)
+        {
+            // make sure we act *after* eviction takes place
+            if (!pre)
+            {
+                if (log.isTraceEnabled())
+                {
+                    StringBuilder builder = new StringBuilder("Adding ");
+                    builder.append(fqn);
+                    builder.append(" for removal...");                    
+                    log.trace(builder);                        
+                }
+                try {
+                  queue.put(fqn);
+               } catch (InterruptedException e) {
+                  Thread.currentThread().interrupt();
+               }
+            }
+        }
+    }
+
+    /**
+     * An inner class that serves as the thread that calls the cluster-wide
+     * remove operation as cache listener event message threads are cache
+     * blocking.
+     */
+    private class RemovalThread extends Thread
+    {
+       private final TreeCache cache;
+       
+        public RemovalThread(TreeCache cache)
+        {
+            setName("Cache Eviction Remover");
+            this.cache = cache;
+        }
+        
+        public void run()
+        {
+            log.trace("The cache eviction remover thread is starting...");
+            
+            while (! isInterrupted())
+            {
+                Fqn fqn = null;
+                
+                try
+                {
+                    fqn = (Fqn) queue.take();
+                    
+                    // if we're shutting down, do nothing...
+                    if (fqn != SHUTDOWN_FQN)
+                    {                    
+                        if (log.isTraceEnabled())
+                        {
+                            log.trace("Removing " + fqn);
+                        }
+                    
+                        cache.remove(fqn);
+                    }
+                }
+                catch (CacheException ce)
+                {
+                    // if this happens, data will remain in remote caches so
+                    // indicate it as WARN or even ERROR
+                    StringBuilder builder = new StringBuilder("Failed to remove ");
+                    builder.append(fqn);
+                    builder.append(" from remote caches:");                    
+                    log.warn(builder, ce);
+                }
+                catch (InterruptedException ie)
+                {
+                    Thread.currentThread().interrupt();
+                    // we were interrupted in queue.take() so stop
+                    break;
+                }             
+            }
+            log.trace("The cache eviction remover thread is stopping...");
+        }
+    }    
+}

Modified: core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/NodeInterceptorRemoveNodeTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/NodeInterceptorRemoveNodeTest.java	2009-09-24 10:28:05 UTC (rev 8237)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/optimistic/NodeInterceptorRemoveNodeTest.java	2009-09-24 11:32:13 UTC (rev 8238)
@@ -77,7 +77,8 @@
         assertEquals(0, workspace.getNodes().size());
 
         assertTrue(entry.getLocks().isEmpty());
-        assertEquals(0, entry.getModifications().size());
+        // JBCACHE-1545 modifications are still queued even though removed node does not exist
+        assertEquals(1, entry.getModifications().size());
         assertTrue(!cache.exists("/one/two"));
         assertEquals(null, dummy.getCalled());
 



More information about the jbosscache-commits mailing list