You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by rm...@apache.org on 2018/05/22 14:49:09 UTC

svn commit: r1832033 - in /commons/proper/jcs/branches/commons-jcs-2.2.x: commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/ commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ commons-jcs-jcache/src/test/java/org/apache/...

Author: rmannibucau
Date: Tue May 22 14:49:09 2018
New Revision: 1832033

URL: http://svn.apache.org/viewvc?rev=1832033&view=rev
Log:
JCS-190 [JCACHE] listener onExpired callback not always called

Added:
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java
      - copied, changed from r1832029, commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java
Modified:
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java
    commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java

Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java?rev=1832033&r1=1832032&r2=1832033&view=diff
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java (original)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCache.java Tue May 22 14:49:09 2018
@@ -526,8 +526,7 @@ public class CompositeCache<K, V>
                             log.debug( cacheAttr.getCacheName() + " - Memory cache hit, but element expired" );
                         }
 
-                        missCountExpired.incrementAndGet();
-                        remove( key );
+                        doExpires(element);
                         element = null;
                     }
                     else
@@ -586,13 +585,11 @@ public class CompositeCache<K, V>
                                         log.debug( cacheAttr.getCacheName() + " - Aux cache[" + aux.getCacheName() + "] hit, but element expired." );
                                     }
 
-                                    missCountExpired.incrementAndGet();
-
                                     // This will tell the remotes to remove the item
                                     // based on the element's expiration policy. The elements attributes
                                     // associated with the item when it created govern its behavior
                                     // everywhere.
-                                    remove( key );
+                                    doExpires(element);
                                     element = null;
                                 }
                                 else
@@ -639,6 +636,11 @@ public class CompositeCache<K, V>
         return element;
     }
 
+    protected void doExpires(ICacheElement<K, V> element) {
+        missCountExpired.incrementAndGet();
+        remove( element.getKey() );
+    }
+
     /**
      * Gets multiple items from the cache based on the given set of keys.
      * <p>
@@ -745,8 +747,7 @@ public class CompositeCache<K, V>
                         log.debug( cacheAttr.getCacheName() + " - Memory cache hit, but element expired" );
                     }
 
-                    missCountExpired.incrementAndGet();
-                    remove( element.getKey() );
+                    doExpires(element);
                     elementsFromMemory.remove( element.getKey() );
                 }
                 else
@@ -1000,13 +1001,11 @@ public class CompositeCache<K, V>
                         log.debug( cacheAttr.getCacheName() + " - Aux cache[" + aux.getCacheName() + "] hit, but element expired." );
                     }
 
-                    missCountExpired.incrementAndGet();
-
                     // This will tell the remote caches to remove the item
                     // based on the element's expiration policy. The elements attributes
                     // associated with the item when it created govern its behavior
                     // everywhere.
-                    remove( element.getKey() );
+                    doExpires(element);
                     elementsFromAuxiliary.remove( element.getKey() );
                 }
                 else

Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java?rev=1832033&r1=1832032&r2=1832033&view=diff
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java (original)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheConfigurator.java Tue May 22 14:49:09 2018
@@ -202,10 +202,10 @@ public class CompositeCacheConfigurator
         IElementAttributes ea = parseElementAttributes( props, regName,
                 ccm.getDefaultElementAttributes(), regionPrefix );
 
-        CompositeCache<K, V> cache = ( cca == null )
-            ? new CompositeCache<K, V>( parseCompositeCacheAttributes( props, regName,
-                    ccm.getDefaultCacheAttributes(), regionPrefix ), ea )
-            : new CompositeCache<K, V>( cca, ea );
+        ICompositeCacheAttributes instantiationCca = cca == null
+                ? parseCompositeCacheAttributes(props, regName, ccm.getDefaultCacheAttributes(), regionPrefix)
+                : cca;
+        CompositeCache<K, V> cache = newCache(instantiationCca, ea);
 
         // Inject cache manager
         cache.setCompositeCacheManager(ccm);
@@ -282,6 +282,12 @@ public class CompositeCacheConfigurator
         return cache;
     }
 
+    protected <K, V> CompositeCache<K, V> newCache(
+            ICompositeCacheAttributes cca, IElementAttributes ea)
+    {
+        return new CompositeCache<K, V>( cca, ea );
+    }
+
     /**
      * Get an ICompositeCacheAttributes for the listed region.
      *<p>

Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java?rev=1832033&r1=1832032&r2=1832033&view=diff
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java (original)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/CompositeCacheManager.java Tue May 22 14:49:09 2018
@@ -460,7 +460,7 @@ public class CompositeCacheManager
         }
 
         // configure the cache
-        CompositeCacheConfigurator configurator = new CompositeCacheConfigurator();
+        CompositeCacheConfigurator configurator = newConfigurator();
 
         long start = System.currentTimeMillis();
 
@@ -604,7 +604,7 @@ public class CompositeCacheManager
 
                 if ( cache == null )
                 {
-                    CompositeCacheConfigurator configurator = new CompositeCacheConfigurator();
+                    CompositeCacheConfigurator configurator = newConfigurator();
 
                     cache = configurator.parseRegion( this.getConfigurationProperties(), this, cattr.getCacheName(),
                                                       this.defaultAuxValues, cattr );
@@ -621,6 +621,10 @@ public class CompositeCacheManager
         return cache;
     }
 
+    protected CompositeCacheConfigurator newConfigurator() {
+        return new CompositeCacheConfigurator();
+    }
+
     /**
      * @param name
      */

Added: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java?rev=1832033&view=auto
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java (added)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/ExpiryAwareCache.java Tue May 22 14:49:09 2018
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.commons.jcs.jcache;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import javax.cache.Cache;
+import javax.cache.configuration.CacheEntryListenerConfiguration;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.EventType;
+
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
+import org.apache.commons.jcs.engine.behavior.IElementAttributes;
+import org.apache.commons.jcs.engine.control.CompositeCache;
+
+// allows us to plug some lifecycle callbacks on the core cache without impacting too much the core
+public class ExpiryAwareCache<A, B> extends CompositeCache<A, B>
+{
+    private Map<CacheEntryListenerConfiguration<A, B>, JCSListener<A, B>> listeners;
+    private Cache<A, B> cacheRef;
+
+    ExpiryAwareCache(final ICompositeCacheAttributes cattr, final IElementAttributes attr)
+    {
+        super(cattr, attr);
+    }
+
+    @Override
+    protected void doExpires(final ICacheElement<A, B> element)
+    {
+        super.doExpires(element);
+        for (final JCSListener<A, B> listener : listeners.values())
+        {
+            listener.onExpired(Arrays.<CacheEntryEvent<? extends A, ? extends B>> asList(new JCSCacheEntryEvent<A, B>(
+                    cacheRef, EventType.REMOVED, null, element.getKey(), element.getVal())));
+        }
+    }
+
+    void init(final Cache<A, B> cache, final Map<CacheEntryListenerConfiguration<A, B>, JCSListener<A, B>> listeners)
+    {
+        this.cacheRef = cache;
+        this.listeners = listeners;
+    }
+}

Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java?rev=1832033&r1=1832032&r2=1832033&view=diff
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java (original)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCache.java Tue May 22 14:49:09 2018
@@ -23,7 +23,6 @@ import org.apache.commons.jcs.engine.Ele
 import org.apache.commons.jcs.engine.behavior.ICacheElement;
 import org.apache.commons.jcs.engine.behavior.IElementAttributes;
 import org.apache.commons.jcs.engine.behavior.IElementSerializer;
-import org.apache.commons.jcs.engine.control.CompositeCache;
 import org.apache.commons.jcs.jcache.jmx.JCSCacheMXBean;
 import org.apache.commons.jcs.jcache.jmx.JCSCacheStatisticsMXBean;
 import org.apache.commons.jcs.jcache.jmx.JMXs;
@@ -71,7 +70,7 @@ import static org.apache.commons.jcs.jca
 // TODO: configure serializer
 public class JCSCache<K, V> implements Cache<K, V>
 {
-    private final CompositeCache<K, V> delegate;
+    private final ExpiryAwareCache<K, V> delegate;
     private final JCSCachingManager manager;
     private final JCSConfiguration<K, V> config;
     private final CacheLoader<K, V> loader;
@@ -89,7 +88,7 @@ public class JCSCache<K, V> implements C
 
     public JCSCache(final ClassLoader classLoader, final JCSCachingManager mgr,
                     final String cacheName, final JCSConfiguration<K, V> configuration,
-                    final Properties properties, final CompositeCache<K, V> cache)
+                    final Properties properties, final ExpiryAwareCache<K, V> cache)
     {
         manager = mgr;
 
@@ -153,6 +152,7 @@ public class JCSCache<K, V> implements C
         {
             listeners.put(listener, new JCSListener<K, V>(listener));
         }
+        delegate.init(this, listeners);
 
         statistics.setActive(config.isStatisticsEnabled());
 
@@ -307,7 +307,7 @@ public class JCSCache<K, V> implements C
                 }
                 else
                 {
-                    expires(key);
+                    forceExpires(key);
                 }
             }
         }
@@ -401,7 +401,7 @@ public class JCSCache<K, V> implements C
         {
             if (!created)
             {
-                expires(key);
+                forceExpires(key);
             }
         }
     }
@@ -411,7 +411,7 @@ public class JCSCache<K, V> implements C
         return duration == null || !duration.isZero();
     }
 
-    private void expires(final K cacheKey)
+    private void forceExpires(final K cacheKey)
     {
         final ICacheElement<K, V> elt = delegate.get(cacheKey);
         delegate.remove(cacheKey);
@@ -549,7 +549,7 @@ public class JCSCache<K, V> implements C
             final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
             if (!isNotZero(expiryForAccess))
             {
-                expires(key);
+                forceExpires(key);
             }
             else if (expiryForAccess != null && (!elt.getElementAttributes().getIsEternal() || !expiryForAccess.isEternal()))
             {

Modified: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java?rev=1832033&r1=1832032&r2=1832033&view=diff
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java (original)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/main/java/org/apache/commons/jcs/jcache/JCSCachingManager.java Tue May 22 14:49:09 2018
@@ -18,6 +18,10 @@
  */
 package org.apache.commons.jcs.jcache;
 
+import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
+import org.apache.commons.jcs.engine.behavior.IElementAttributes;
+import org.apache.commons.jcs.engine.control.CompositeCache;
+import org.apache.commons.jcs.engine.control.CompositeCacheConfigurator;
 import org.apache.commons.jcs.engine.control.CompositeCacheManager;
 import org.apache.commons.jcs.jcache.lang.Subsitutor;
 import org.apache.commons.jcs.jcache.proxy.ClassLoaderAwareCache;
@@ -65,6 +69,19 @@ public class JCSCachingManager implement
             return new InternalManager();
         }
 
+        protected CompositeCacheConfigurator newConfigurator()
+        {
+            return new CompositeCacheConfigurator()
+            {
+                @Override
+                protected <K, V> CompositeCache<K, V> newCache(
+                        final ICompositeCacheAttributes cca, final IElementAttributes ea)
+                {
+                    return new ExpiryAwareCache<K, V>( cca, ea );
+                }
+            };
+        }
+
         @Override // needed to call it from JCSCachingManager
         protected void initialize() {
             super.initialize();
@@ -197,7 +214,7 @@ public class JCSCachingManager implement
                             loader, this, cacheName,
                             new JCSConfiguration/*<K, V>*/(configuration, keyType, valueType),
                             properties,
-                            delegate.getCache(cacheName)));
+                            ExpiryAwareCache.class.cast(delegate.getCache(cacheName))));
             caches.putIfAbsent(cacheName, cache);
         }
         else

Copied: commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java (from r1832029, commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java)
URL: http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java?p2=commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java&p1=commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java&r1=1832029&r2=1832033&rev=1832033&view=diff
==============================================================================
--- commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ImmediateExpiryTest.java (original)
+++ commons/proper/jcs/branches/commons-jcs-2.2.x/commons-jcs-jcache/src/test/java/org/apache/commons/jcs/jcache/ExpiryListenerTest.java Tue May 22 14:49:09 2018
@@ -1,53 +1,81 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
+ * regarding copyright ownership. The ASF licenses this file
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
+ * with the License. You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
+ * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
 
 package org.apache.commons.jcs.jcache;
 
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
 
 import javax.cache.Cache;
 import javax.cache.CacheManager;
 import javax.cache.Caching;
 import javax.cache.configuration.FactoryBuilder;
+import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
 import javax.cache.configuration.MutableConfiguration;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryExpiredListener;
+import javax.cache.event.CacheEntryListenerException;
 import javax.cache.expiry.CreatedExpiryPolicy;
 import javax.cache.expiry.Duration;
 import javax.cache.expiry.ExpiryPolicy;
 import javax.cache.spi.CachingProvider;
 
-import static org.junit.Assert.assertFalse;
+import org.junit.Test;
+
+public class ExpiryListenerTest {
 
-public class ImmediateExpiryTest
-{
     @Test
-    public void immediate()
-    {
+    public void listener() throws InterruptedException {
         final CachingProvider cachingProvider = Caching.getCachingProvider();
         final CacheManager cacheManager = cachingProvider.getCacheManager();
-        cacheManager.createCache("default",
-                new MutableConfiguration<Object, Object>()
-                        .setExpiryPolicyFactory(
-                                new FactoryBuilder.SingletonFactory<ExpiryPolicy>(new CreatedExpiryPolicy(Duration.ZERO))));
+        final CacheEntryExpiredListenerImpl listener = new CacheEntryExpiredListenerImpl();
+        cacheManager.createCache("default", new MutableConfiguration<String, String>()
+                .setExpiryPolicyFactory(new FactoryBuilder.SingletonFactory<ExpiryPolicy>(
+                        new CreatedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, 1))))
+                .addCacheEntryListenerConfiguration(new MutableCacheEntryListenerConfiguration<String, String>(
+                        FactoryBuilder.factoryOf(listener),
+                        null, false, false
+                )));
         final Cache<String, String> cache = cacheManager.getCache("default");
         assertFalse(cache.containsKey("foo"));
         cache.put("foo", "bar");
+        Thread.sleep(10);
         assertFalse(cache.containsKey("foo"));
         cachingProvider.close();
+        assertEquals(1, listener.events.size());
+    }
+
+    private static class CacheEntryExpiredListenerImpl implements CacheEntryExpiredListener<String, String>, Serializable {
+        private final Collection<CacheEntryEvent<? extends String, ? extends String>> events =
+                new ArrayList<CacheEntryEvent<? extends String, ? extends String>>();
+
+        @Override
+        public void onExpired(final Iterable<CacheEntryEvent<? extends String, ? extends String>> cacheEntryEvents)
+                throws CacheEntryListenerException {
+            for (final CacheEntryEvent<? extends String, ? extends String> cacheEntryEvent : cacheEntryEvents) {
+                events.add(cacheEntryEvent);
+            }
+        }
     }
 }