You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tv...@apache.org on 2016/02/07 18:56:53 UTC
svn commit: r1728995 - in /commons/proper/jcs/trunk:
commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/
commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/
commons-jcs-core/src/main/java/org/apache/commons/jcs/eng...
Author: tv
Date: Sun Feb 7 17:56:52 2016
New Revision: 1728995
URL: http://svn.apache.org/viewvc?rev=1728995&view=rev
Log:
JCS-54 Add soft reference memory cache
Added:
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java (with props)
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/package.html (with props)
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/SoftReferenceElementDescriptor.java (with props)
commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/
commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java (with props)
commons/proper/jcs/trunk/commons-jcs-core/src/test/test-conf/TestSoftReferenceCache.ccf
Modified:
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/MemoryElementDescriptor.java
commons/proper/jcs/trunk/src/changes/changes.xml
Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java?rev=1728995&r1=1728994&r2=1728995&view=diff
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java (original)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java Sun Feb 7 17:56:52 2016
@@ -26,7 +26,7 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.jcs.engine.CacheConstants;
import org.apache.commons.jcs.engine.behavior.ICacheElement;
@@ -58,13 +58,13 @@ public abstract class AbstractDoubleLink
protected DoubleLinkedList<MemoryElementDescriptor<K, V>> list; // TODO privatise
/** number of hits */
- private AtomicInteger hitCnt;
+ private AtomicLong hitCnt;
/** number of misses */
- private AtomicInteger missCnt;
+ private AtomicLong missCnt;
/** number of puts */
- private AtomicInteger putCnt;
+ private AtomicLong putCnt;
/**
* For post reflection creation initialization.
@@ -79,9 +79,9 @@ public abstract class AbstractDoubleLink
try
{
super.initialize(hub);
- hitCnt = new AtomicInteger(0);
- missCnt = new AtomicInteger(0);
- putCnt = new AtomicInteger(0);
+ hitCnt = new AtomicLong(0);
+ missCnt = new AtomicLong(0);
+ putCnt = new AtomicLong(0);
list = new DoubleLinkedList<MemoryElementDescriptor<K, V>>();
log.info("initialized MemoryCache for " + getCacheName());
}
@@ -92,6 +92,21 @@ public abstract class AbstractDoubleLink
}
/**
+ * Reset statistics
+ *
+ * @see org.apache.commons.jcs.engine.memory.AbstractMemoryCache#dispose()
+ */
+ @Override
+ public void dispose() throws IOException
+ {
+ super.dispose();
+ removeAll();
+ hitCnt.set(0);
+ missCnt.set(0);
+ putCnt.set(0);
+ }
+
+ /**
* This is called by super initialize.
*
* NOTE: should return a thread safe map
@@ -127,10 +142,11 @@ public abstract class AbstractDoubleLink
MemoryElementDescriptor<K, V> newNode = adjustListForUpdate(ce);
// this should be synchronized if we were not using a ConcurrentHashMap
- MemoryElementDescriptor<K, V> oldNode = map.put(newNode.ce.getKey(), newNode);
+ final K key = newNode.getCacheElement().getKey();
+ MemoryElementDescriptor<K, V> oldNode = map.put(key, newNode);
// If the node was the same as an existing node, remove it.
- if (oldNode != null && newNode.ce.getKey().equals(oldNode.ce.getKey()))
+ if (oldNode != null && key.equals(oldNode.getCacheElement().getKey()))
{
list.remove(oldNode);
}
@@ -246,7 +262,7 @@ public abstract class AbstractDoubleLink
lock.lock();
try
{
- ce = me.ce;
+ ce = me.getCacheElement();
// ABSTRACT
adjustListForGet(me);
}
@@ -337,7 +353,7 @@ public abstract class AbstractDoubleLink
final MemoryElementDescriptor<K, V> last = list.getLast();
if (last != null)
{
- toSpool = last.ce;
+ toSpool = last.getCacheElement();
if (toSpool != null)
{
getCompositeCache().spoolToDisk(toSpool);
@@ -542,7 +558,7 @@ public abstract class AbstractDoubleLink
log.debug("dumpingCacheEntries");
for (MemoryElementDescriptor<K, V> me = list.getFirst(); me != null; me = (MemoryElementDescriptor<K, V>) me.next)
{
- log.debug("dumpCacheEntries> key=" + me.ce.getKey() + ", val=" + me.ce.getVal());
+ log.debug("dumpCacheEntries> key=" + me.getCacheElement().getKey() + ", val=" + me.getCacheElement().getVal());
}
}
@@ -560,11 +576,10 @@ public abstract class AbstractDoubleLink
log.debug("verifycache: checking linked list by key ");
for (MemoryElementDescriptor<K, V> li = list.getFirst(); li != null; li = (MemoryElementDescriptor<K, V>) li.next)
{
- Object key = li.ce.getKey();
+ K key = li.getCacheElement().getKey();
if (!map.containsKey(key))
{
- log.error("verifycache[" + getCacheName() + "]: map does not contain key : " + li.ce.getKey());
- log.error("li.hashcode=" + li.ce.getKey().hashCode());
+ log.error("verifycache[" + getCacheName() + "]: map does not contain key : " + key);
log.error("key class=" + key.getClass());
log.error("key hashcode=" + key.hashCode());
log.error("key toString=" + key.toString());
@@ -578,9 +593,9 @@ public abstract class AbstractDoubleLink
}
dumpMap();
}
- else if (map.get(li.ce.getKey()) == null)
+ else if (map.get(key) == null)
{
- log.error("verifycache[" + getCacheName() + "]: linked list retrieval returned null for key: " + li.ce.getKey());
+ log.error("verifycache[" + getCacheName() + "]: linked list retrieval returned null for key: " + key);
}
}
@@ -601,7 +616,7 @@ public abstract class AbstractDoubleLink
for (MemoryElementDescriptor<K, V> li2 = list.getFirst(); li2 != null; li2 = (MemoryElementDescriptor<K, V>) li2.next)
{
- if (val.equals(li2.ce.getKey()))
+ if (val.equals(li2.getCacheElement().getKey()))
{
found = true;
break;
@@ -638,7 +653,7 @@ public abstract class AbstractDoubleLink
// go through the linked list looking for the key
for (MemoryElementDescriptor<K, V> li = list.getFirst(); li != null; li = (MemoryElementDescriptor<K, V>) li.next)
{
- if (li.ce.getKey() == key)
+ if (li.getCacheElement().getKey() == key)
{
found = true;
log.debug("verifycache(key) key match: " + key);
@@ -682,9 +697,9 @@ public abstract class AbstractDoubleLink
{
elems.add(new StatElement<Integer>("List Size", Integer.valueOf(list.size())));
elems.add(new StatElement<Integer>("Map Size", Integer.valueOf(map.size())));
- elems.add(new StatElement<AtomicInteger>("Put Count", putCnt));
- elems.add(new StatElement<AtomicInteger>("Hit Count", hitCnt));
- elems.add(new StatElement<AtomicInteger>("Miss Count", missCnt));
+ elems.add(new StatElement<AtomicLong>("Put Count", putCnt));
+ elems.add(new StatElement<AtomicLong>("Hit Count", hitCnt));
+ elems.add(new StatElement<AtomicLong>("Miss Count", missCnt));
}
finally
{
Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java?rev=1728995&r1=1728994&r2=1728995&view=diff
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java (original)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java Sun Feb 7 17:56:52 2016
@@ -176,7 +176,7 @@ public abstract class AbstractMemoryCach
log.debug( cacheName + ": MemoryCache quiet hit for " + key );
}
- ce = me.ce;
+ ce = me.getCacheElement();
}
else if ( log.isDebugEnabled() )
{
@@ -269,7 +269,9 @@ public abstract class AbstractMemoryCach
{
String attributeCacheName = this.cacheAttributes.getCacheName();
if(attributeCacheName != null)
+ {
return attributeCacheName;
+ }
return cacheName;
}
@@ -296,7 +298,7 @@ public abstract class AbstractMemoryCach
for (Map.Entry<K, MemoryElementDescriptor<K, V>> e : map.entrySet())
{
MemoryElementDescriptor<K, V> me = e.getValue();
- log.debug( "dumpMap> key=" + e.getKey() + ", val=" + me.ce.getVal() );
+ log.debug( "dumpMap> key=" + e.getKey() + ", val=" + me.getCacheElement().getVal() );
}
}
Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java?rev=1728995&r1=1728994&r2=1728995&view=diff
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java (original)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java Sun Feb 7 17:56:52 2016
@@ -20,14 +20,13 @@ package org.apache.commons.jcs.engine.me
*/
import java.io.IOException;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.jcs.engine.CacheConstants;
import org.apache.commons.jcs.engine.behavior.ICacheElement;
@@ -45,20 +44,20 @@ import org.apache.commons.logging.LogFac
/**
* This is a test memory manager using the jdk1.4 LinkedHashMap.
*/
-public class LHMLRUMemoryCache<K extends Serializable, V extends Serializable>
+public class LHMLRUMemoryCache<K, V>
extends AbstractMemoryCache<K, V>
{
/** The Logger. */
private static final Log log = LogFactory.getLog( LRUMemoryCache.class );
/** number of hits */
- private AtomicInteger hitCnt;
+ private AtomicLong hitCnt;
/** number of misses */
- private AtomicInteger missCnt;
+ private AtomicLong missCnt;
/** number of puts */
- private AtomicInteger putCnt;
+ private AtomicLong putCnt;
/**
* For post reflection creation initialization
@@ -66,12 +65,12 @@ public class LHMLRUMemoryCache<K extends
* @param hub
*/
@Override
- public synchronized void initialize( CompositeCache<K, V> hub )
+ public void initialize( CompositeCache<K, V> hub )
{
super.initialize( hub );
- hitCnt = new AtomicInteger(0);
- missCnt = new AtomicInteger(0);
- putCnt = new AtomicInteger(0);
+ hitCnt = new AtomicLong(0);
+ missCnt = new AtomicLong(0);
+ putCnt = new AtomicLong(0);
log.info( "initialized LHMLRUMemoryCache for " + getCacheName() );
}
@@ -112,7 +111,14 @@ public class LHMLRUMemoryCache<K extends
public ICacheElement<K, V> getQuiet( K key )
throws IOException
{
- return map.get( key ).ce;
+ MemoryElementDescriptor<K, V> me = map.get( key );
+
+ if (me != null)
+ {
+ return me.getCacheElement();
+ }
+
+ return null;
}
/**
@@ -126,14 +132,12 @@ public class LHMLRUMemoryCache<K extends
public synchronized ICacheElement<K, V> get( K key )
throws IOException
{
- MemoryElementDescriptor<K, V> me = null;
-
if ( log.isDebugEnabled() )
{
log.debug( "getting item from cache " + getCacheName() + " for key " + key );
}
- me = map.get( key );
+ MemoryElementDescriptor<K, V> me = map.get( key );
if ( me != null )
{
@@ -142,7 +146,7 @@ public class LHMLRUMemoryCache<K extends
{
log.debug( getCacheName() + ": LHMLRUMemoryCache hit for " + key );
}
- return me.ce;
+ return me.getCacheElement();
}
else
{
@@ -258,9 +262,9 @@ public class LHMLRUMemoryCache<K extends
ArrayList<IStatElement<?>> elems = new ArrayList<IStatElement<?>>();
elems.add(new StatElement<Integer>( "Map Size", Integer.valueOf(map.size()) ) );
- elems.add(new StatElement<AtomicInteger>("Put Count", putCnt));
- elems.add(new StatElement<AtomicInteger>("Hit Count", hitCnt));
- elems.add(new StatElement<AtomicInteger>("Miss Count", missCnt));
+ elems.add(new StatElement<AtomicLong>("Put Count", putCnt));
+ elems.add(new StatElement<AtomicLong>("Hit Count", hitCnt));
+ elems.add(new StatElement<AtomicLong>("Miss Count", missCnt));
stats.setStatElements( elems );
@@ -325,7 +329,7 @@ public class LHMLRUMemoryCache<K extends
@Override
protected boolean removeEldestEntry( Map.Entry<K, MemoryElementDescriptor<K, V>> eldest )
{
- ICacheElement<K, V> element = eldest.getValue().ce;
+ ICacheElement<K, V> element = eldest.getValue().getCacheElement();
if ( size() <= getCacheAttributes().getMaxObjects() )
{
Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java?rev=1728995&view=auto
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java (added)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java Sun Feb 7 17:56:52 2016
@@ -0,0 +1,388 @@
+package org.apache.commons.jcs.engine.memory.soft;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.commons.jcs.engine.CacheConstants;
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
+import org.apache.commons.jcs.engine.control.CompositeCache;
+import org.apache.commons.jcs.engine.control.group.GroupAttrName;
+import org.apache.commons.jcs.engine.memory.AbstractMemoryCache;
+import org.apache.commons.jcs.engine.memory.util.MemoryElementDescriptor;
+import org.apache.commons.jcs.engine.memory.util.SoftReferenceElementDescriptor;
+import org.apache.commons.jcs.engine.stats.StatElement;
+import org.apache.commons.jcs.engine.stats.Stats;
+import org.apache.commons.jcs.engine.stats.behavior.IStatElement;
+import org.apache.commons.jcs.engine.stats.behavior.IStats;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A JCS {@link MemoryCache} that has {@link SoftReference} too all its values.
+ * This cache does not respect {@link ICompositeCacheAttributes#getMaxObjects()}
+ * as overflowing is handled by java gc.
+ * <p>
+ * The cache also has strong references to a maximum number of objects given by
+ * the maxObjects parameter
+ *
+ * @author halset
+ */
+public class SoftReferenceMemoryCache<K, V> extends AbstractMemoryCache<K, V>
+{
+ /** The logger. */
+ private static final Log log = LogFactory.getLog(SoftReferenceMemoryCache.class);
+
+ /**
+ * Strong references to the maxObjects number of newest objects.
+ * <p>
+ * Trimming is done by {@link #trimStrongReferences()} instead of by
+ * overriding removeEldestEntry to be able to control waterfalling as easy
+ * as possible
+ */
+ private LinkedBlockingQueue<ICacheElement<K, V>> strongReferences;
+
+ /** number of hits */
+ private AtomicLong hitCnt;
+
+ /** number of misses */
+ private AtomicLong missCnt;
+
+ /** number of puts */
+ private AtomicLong putCnt;
+
+ /**
+ * For post reflection creation initialization
+ * <p>
+ * @param hub
+ */
+ @Override
+ public synchronized void initialize( CompositeCache<K, V> hub )
+ {
+ super.initialize( hub );
+ strongReferences = new LinkedBlockingQueue<ICacheElement<K, V>>();
+ hitCnt = new AtomicLong(0);
+ missCnt = new AtomicLong(0);
+ putCnt = new AtomicLong(0);
+ log.info( "initialized Soft Reference Memory Cache for " + getCacheName() );
+ }
+
+ /**
+ * @see org.apache.commons.jcs.engine.memory.AbstractMemoryCache#createMap()
+ */
+ @Override
+ public Map<K, MemoryElementDescriptor<K, V>> createMap()
+ {
+ return new ConcurrentHashMap<K, MemoryElementDescriptor<K, V>>();
+ }
+
+ /**
+ * @see org.apache.commons.jcs.engine.memory.behavior.IMemoryCache#getKeySet()
+ */
+ @Override
+ public Set<K> getKeySet()
+ {
+ Set<K> keys = new HashSet<K>();
+ for (Map.Entry<K, MemoryElementDescriptor<K, V>> e : map.entrySet())
+ {
+ SoftReferenceElementDescriptor<K, V> sred = (SoftReferenceElementDescriptor<K, V>) e.getValue();
+ if (sred.getCacheElement() != null)
+ {
+ keys.add(e.getKey());
+ }
+ }
+
+ return keys;
+ }
+
+ /**
+ * Returns the current cache size.
+ * <p>
+ * @return The size value
+ */
+ @Override
+ public int getSize()
+ {
+ int size = 0;
+ for (MemoryElementDescriptor<K, V> me : map.values())
+ {
+ SoftReferenceElementDescriptor<K, V> sred = (SoftReferenceElementDescriptor<K, V>) me;
+ if (sred.getCacheElement() != null)
+ {
+ size++;
+ }
+ }
+ return size;
+ }
+
+ /**
+ * @return statistics about the cache
+ */
+ @Override
+ public IStats getStatistics()
+ {
+ ArrayList<IStatElement<?>> elems = new ArrayList<IStatElement<?>>();
+
+ int size = getSize();
+ int emptyrefs = map.size() - size;
+
+ elems.add(new StatElement<Integer>("Size", Integer.valueOf(size)));
+ elems.add(new StatElement<Integer>("Empty References", Integer.valueOf(emptyrefs)));
+ elems.add(new StatElement<Integer>("Strong References", Integer.valueOf(strongReferences.size())));
+ elems.add(new StatElement<AtomicLong>("Put Count", putCnt));
+ elems.add(new StatElement<AtomicLong>("Hit Count", hitCnt));
+ elems.add(new StatElement<AtomicLong>("Miss Count", missCnt));
+
+ IStats stats = new Stats();
+ stats.setTypeName("Soft Reference Memory Cache");
+ stats.setStatElements(elems);
+
+ return stats;
+ }
+
+ /**
+ * Removes an item from the cache. This method handles hierarchical removal. If the key is a
+ * String and ends with the CacheConstants.NAME_COMPONENT_DELIMITER, then all items with keys
+ * starting with the argument String will be removed.
+ * <p>
+ *
+ * @param key
+ * @return true if the removal was successful
+ * @throws IOException
+ */
+ @Override
+ public boolean remove(K key) throws IOException
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("removing item for key: " + key);
+ }
+
+ boolean removed = false;
+
+ // handle partial removal
+ if (key instanceof String && ((String) key).endsWith(CacheConstants.NAME_COMPONENT_DELIMITER))
+ {
+ // remove all keys of the same name hierarchy.
+ for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator();
+ itr.hasNext();)
+ {
+ Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
+ K k = entry.getKey();
+
+ if (k instanceof String && ((String) k).startsWith(key.toString()))
+ {
+ lock.lock();
+ try
+ {
+ strongReferences.remove(entry.getValue().getCacheElement());
+ itr.remove();
+ removed = true;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+ }
+ }
+ else if (key instanceof GroupAttrName && ((GroupAttrName<?>) key).attrName == null)
+ {
+ // remove all keys of the same name hierarchy.
+ for (Iterator<Map.Entry<K, MemoryElementDescriptor<K, V>>> itr = map.entrySet().iterator();
+ itr.hasNext();)
+ {
+ Map.Entry<K, MemoryElementDescriptor<K, V>> entry = itr.next();
+ K k = entry.getKey();
+
+ if (k instanceof GroupAttrName && ((GroupAttrName<?>) k).groupId.equals(((GroupAttrName<?>) key).groupId))
+ {
+ lock.lock();
+ try
+ {
+ strongReferences.remove(entry.getValue().getCacheElement());
+ itr.remove();
+ removed = true;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+ }
+ }
+ else
+ {
+ // remove single item.
+ lock.lock();
+ try
+ {
+ MemoryElementDescriptor<K, V> me = map.remove(key);
+ if (me != null)
+ {
+ strongReferences.remove(me.getCacheElement());
+ removed = true;
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ return removed;
+ }
+
+ /**
+ * Removes all cached items from the cache.
+ * <p>
+ * @throws IOException
+ */
+ @Override
+ public void removeAll() throws IOException
+ {
+ super.removeAll();
+ strongReferences.clear();
+ }
+
+ /**
+ * Puts an item to the cache.
+ * <p>
+ * @param ce Description of the Parameter
+ * @throws IOException Description of the Exception
+ */
+ @Override
+ public void update(ICacheElement<K, V> ce) throws IOException
+ {
+ putCnt.incrementAndGet();
+ ce.getElementAttributes().setLastAccessTimeNow();
+
+ lock.lock();
+
+ try
+ {
+ map.put(ce.getKey(), new SoftReferenceElementDescriptor<K, V>(ce));
+ strongReferences.add(ce);
+ trimStrongReferences();
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Trim the number of strong references to equal or below the number given
+ * by the maxObjects parameter.
+ *
+ * @throws IOException
+ */
+ private void trimStrongReferences() throws IOException
+ {
+ int max = getCacheAttributes().getMaxObjects();
+ int startsize = strongReferences.size();
+
+ for (int cursize = startsize; cursize > max; cursize--)
+ {
+ ICacheElement<K, V> ce = strongReferences.poll();
+ waterfal(ce);
+ }
+ }
+
+ /**
+ * Get an item from the cache
+ * <p>
+ * @param key Description of the Parameter
+ * @return Description of the Return Value
+ * @throws IOException Description of the Exception
+ */
+ @Override
+ public ICacheElement<K, V> get(K key) throws IOException
+ {
+ ICacheElement<K, V> val = null;
+ lock.lock();
+
+ try
+ {
+ val = getQuiet(key);
+ if (val != null)
+ {
+ val.getElementAttributes().setLastAccessTimeNow();
+
+ // update the ordering of the strong references
+ strongReferences.add(val);
+ trimStrongReferences();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+
+ if (val == null)
+ {
+ missCnt.incrementAndGet();
+ }
+ else
+ {
+ hitCnt.incrementAndGet();
+ }
+
+ return val;
+ }
+
+ /**
+ * Prepares for shutdown.
+ * <p>
+ * @throws IOException
+ */
+ @Override
+ public void dispose() throws IOException
+ {
+ super.dispose();
+ removeAll();
+ hitCnt.set(0);
+ missCnt.set(0);
+ putCnt.set(0);
+ }
+
+ /**
+ * This can't be implemented.
+ * <p>
+ * @param numberToFree
+ * @return 0
+ * @throws IOException
+ */
+ @Override
+ public int freeElements(int numberToFree) throws IOException
+ {
+ return 0;
+ }
+}
Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/package.html
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/package.html?rev=1728995&view=auto
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/package.html (added)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/package.html Sun Feb 7 17:56:52 2016
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+<html>
+ <head>
+ </head>
+ <body>
+ A memory plugin implemented using soft references.
+ </body>
+</html>
Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/package.html
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/MemoryElementDescriptor.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/MemoryElementDescriptor.java?rev=1728995&r1=1728994&r2=1728995&view=diff
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/MemoryElementDescriptor.java (original)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/MemoryElementDescriptor.java Sun Feb 7 17:56:52 2016
@@ -32,7 +32,7 @@ public class MemoryElementDescriptor<K,
private static final long serialVersionUID = -1905161209035522460L;
/** The CacheElement wrapped by this descriptor */
- public final ICacheElement<K, V> ce; // TODO privatise
+ private final ICacheElement<K, V> ce;
/**
* Constructs a usable MemoryElementDescriptor.
@@ -44,4 +44,12 @@ public class MemoryElementDescriptor<K,
super( ce );
this.ce = ce;
}
+
+ /**
+ * @return the ce
+ */
+ public ICacheElement<K, V> getCacheElement()
+ {
+ return ce;
+ }
}
Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/SoftReferenceElementDescriptor.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/SoftReferenceElementDescriptor.java?rev=1728995&view=auto
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/SoftReferenceElementDescriptor.java (added)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/SoftReferenceElementDescriptor.java Sun Feb 7 17:56:52 2016
@@ -0,0 +1,62 @@
+package org.apache.commons.jcs.engine.memory.util;
+
+/*
+ * 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.
+ */
+
+import java.lang.ref.SoftReference;
+
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+
+/**
+ * This wrapper is needed for double linked lists.
+ */
+public class SoftReferenceElementDescriptor<K, V>
+ extends MemoryElementDescriptor<K, V>
+{
+ /** Don't change */
+ private static final long serialVersionUID = -1905161209035522460L;
+
+ /** The CacheElement wrapped by this descriptor */
+ private final SoftReference<ICacheElement<K, V>> srce;
+
+ /**
+ * Constructs a usable MemoryElementDescriptor.
+ * <p>
+ * @param ce
+ */
+ public SoftReferenceElementDescriptor( ICacheElement<K, V> ce )
+ {
+ super( ce );
+ this.srce = new SoftReference<ICacheElement<K, V>>(ce);
+ }
+
+ /**
+ * @return the ce
+ */
+ @Override
+ public ICacheElement<K, V> getCacheElement()
+ {
+ if (srce != null)
+ {
+ return srce.get();
+ }
+
+ return null;
+ }
+}
Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/util/SoftReferenceElementDescriptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java?rev=1728995&view=auto
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java (added)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java Sun Feb 7 17:56:52 2016
@@ -0,0 +1,247 @@
+package org.apache.commons.jcs.engine.memory.soft;
+
+/*
+ * 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.
+ */
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.jcs.JCS;
+import org.apache.commons.jcs.access.CacheAccess;
+import org.apache.commons.jcs.access.exception.CacheException;
+import org.apache.commons.jcs.engine.CacheElement;
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.control.CompositeCache;
+import org.apache.commons.jcs.engine.control.CompositeCacheManager;
+
+/**
+ * Tests for the test Soft reference implementation.
+ * <p>
+ * @author Aaron Smuts
+ */
+public class SoftReferenceMemoryCacheUnitTest
+ extends TestCase
+{
+ /** Test setup */
+ @Override
+ public void setUp()
+ {
+ JCS.setConfigFilename( "/TestSoftReferenceCache.ccf" );
+ }
+
+ /**
+ * @see junit.framework.TestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception
+ {
+ CompositeCacheManager.getInstance().shutDown();
+ }
+
+ /**
+ * Verify that the cache gets used by a non-defined region when it is set as the default in the
+ * default region.
+ * <p>
+ * @throws CacheException
+ */
+ public void testLoadFromCCF()
+ throws CacheException
+ {
+ CacheAccess<String, String> cache = JCS.getInstance( "testPutGet" );
+ String memoryCacheName = cache.getCacheAttributes().getMemoryCacheName();
+ assertTrue( "Cache name should have SoftReference in it.",
+ memoryCacheName.indexOf( "SoftReferenceMemoryCache" ) != -1 );
+ }
+
+ /**
+ * put twice as many as the max. verify that all are in the cache.
+ * <p>
+ * @throws CacheException
+ */
+ public void testPutGetThroughHub()
+ throws CacheException
+ {
+ CacheAccess<String, String> cache = JCS.getInstance( "testPutGetThroughHub" );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max * 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ cache.put( i + ":key", "myregion" + " data " + i );
+ }
+
+ // Test that all items are in cache
+ for ( int i = 0; i < items; i++ )
+ {
+ String value = cache.get( i + ":key" );
+ assertEquals( "myregion" + " data " + i, value );
+ }
+
+ // Test that getMultiple returns all the items remaining in cache and none of the missing ones
+ Set<String> keys = new HashSet<String>();
+ for ( int i = 0; i < items; i++ )
+ {
+ keys.add( i + ":key" );
+ }
+
+ Map<String, ICacheElement<String, String>> elements = cache.getCacheElements( keys );
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement<String, String> element = elements.get( i + ":key" );
+ assertNotNull( "element " + i + ":key is missing", element );
+ assertEquals( "value " + i + ":key", "myregion" + " data " + i, element.getVal() );
+ }
+
+ // System.out.println(cache.getStats());
+ }
+
+ /**
+ * put the max and remove each. verify that they are all null.
+ * <p>
+ * @throws CacheException
+ */
+ public void testPutRemoveThroughHub()
+ throws CacheException
+ {
+ CacheAccess<String, String> cache = JCS.getInstance( "testPutGetThroughHub" );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max * 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ cache.put( i + ":key", "myregion" + " data " + i );
+ }
+
+ for ( int i = 0; i < items; i++ )
+ {
+ cache.remove( i + ":key" );
+ }
+
+ // Test that first items are not in the cache
+ for ( int i = max; i >= 0; i-- )
+ {
+ String value = cache.get( i + ":key" );
+ assertNull( "Should not have value for key [" + i + ":key" + "] in the cache.", value );
+ }
+ }
+
+ /**
+ * put the max and clear. verify that no elements remain.
+ * <p>
+ * @throws CacheException
+ */
+ public void testClearThroughHub()
+ throws CacheException
+ {
+ CacheAccess<String, String> cache = JCS.getInstance( "testPutGetThroughHub" );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max * 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ cache.put( i + ":key", "myregion" + " data " + i );
+ }
+
+ cache.clear();
+
+ // Test that first items are not in the cache
+ for ( int i = max; i >= 0; i-- )
+ {
+ String value = cache.get( i + ":key" );
+ assertNull( "Should not have value for key [" + i + ":key" + "] in the cache.", value );
+ }
+ }
+
+ /**
+ * Put half the max and clear. get the key array and verify that it has the correct number of
+ * items.
+ * <p>
+ * @throws Exception
+ */
+ public void testGetKeyArray()
+ throws Exception
+ {
+ CompositeCacheManager cacheMgr = CompositeCacheManager.getUnconfiguredInstance();
+ cacheMgr.configure( "/TestSoftReferenceCache.ccf" );
+ CompositeCache<String, String> cache = cacheMgr.getCache( "testGetKeyArray" );
+
+ SoftReferenceMemoryCache<String, String> srmc = new SoftReferenceMemoryCache<String, String>();
+ srmc.initialize( cache );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max / 2;
+
+ for ( int i = 0; i < items; i++ )
+ {
+ ICacheElement<String, String> ice = new CacheElement<String, String>( cache.getCacheName(), i + ":key", cache.getCacheName() + " data " + i );
+ ice.setElementAttributes( cache.getElementAttributes() );
+ srmc.update( ice );
+ }
+
+ Set<String> keys = srmc.getKeySet();
+
+ assertEquals( "Wrong number of keys.", items, keys.size() );
+ }
+
+ /**
+ * Add a few keys with the delimiter. Remove them.
+ * <p>
+ * @throws CacheException
+ */
+ public void testRemovePartialThroughHub()
+ throws CacheException
+ {
+ CacheAccess<String, String> cache = JCS.getInstance( "testGetStatsThroughHub" );
+
+ int max = cache.getCacheAttributes().getMaxObjects();
+ int items = max / 2;
+
+ cache.put( "test", "data" );
+
+ String root = "myroot";
+
+ for ( int i = 0; i < items; i++ )
+ {
+ cache.put( root + ":" + i + ":key", "myregion" + " data " + i );
+ }
+
+ // Test that last items are in cache
+ for ( int i = 0; i < items; i++ )
+ {
+ String value = cache.get( root + ":" + i + ":key" );
+ assertEquals( "myregion" + " data " + i, value );
+ }
+
+ // remove partial
+ cache.remove( root + ":" );
+
+ for ( int i = 0; i < items; i++ )
+ {
+ assertNull( "Should have been removed by partial loop.", cache.get( root + ":" + i + ":key" ) );
+ }
+
+ assertNotNull( "Other item should be in the cache.", cache.get( "test" ) );
+ }
+}
Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: commons/proper/jcs/trunk/commons-jcs-core/src/test/test-conf/TestSoftReferenceCache.ccf
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/test/test-conf/TestSoftReferenceCache.ccf?rev=1728995&view=auto
==============================================================================
--- commons/proper/jcs/trunk/commons-jcs-core/src/test/test-conf/TestSoftReferenceCache.ccf (added)
+++ commons/proper/jcs/trunk/commons-jcs-core/src/test/test-conf/TestSoftReferenceCache.ccf Sun Feb 7 17:56:52 2016
@@ -0,0 +1,37 @@
+# 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.
+# JCS Config for unit testing
+
+jcs.default=
+jcs.default.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes
+jcs.default.cacheattributes.MaxObjects=100
+jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.soft.SoftReferenceMemoryCache
+jcs.default.cacheattributes.UseMemoryShrinker=false
+jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=3600
+jcs.default.elementattributes=org.apache.commons.jcs.engine.ElementAttributes
+jcs.default.elementattributes.IsEternal=false
+jcs.default.elementattributes.MaxLife=600
+jcs.default.elementattributes.IdleTime=1800
+jcs.default.elementattributes.IsSpool=true
+jcs.default.elementattributes.IsRemote=true
+jcs.default.elementattributes.IsLateral=true
+
+# Region defined that uses the Soft Reference
+jcs.region.srDefined=
+jcs.region.srDefined.cacheattributes=org.apache.commons.jcs.engine.CompositeCacheAttributes
+jcs.region.srDefined.cacheattributes.MaxObjects=100000
+jcs.region.srDefined.cacheattributes.MemoryCacheName=org.apache.commons.jcs.engine.memory.soft.SoftReferenceMemoryCache
Modified: commons/proper/jcs/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/changes/changes.xml?rev=1728995&r1=1728994&r2=1728995&view=diff
==============================================================================
--- commons/proper/jcs/trunk/src/changes/changes.xml (original)
+++ commons/proper/jcs/trunk/src/changes/changes.xml Sun Feb 7 17:56:52 2016
@@ -20,6 +20,9 @@
</properties>
<body>
<release version="2.0" date="unreleased" description="JDK 1.6 based major release">
+ <action issue="JCS-54" dev="tv" type="add" due-to="Tore Halset">
+ Add soft reference memory cache
+ </action>
<action issue="JCS-78" dev="tv" type="fix" due-to="Marko Stipanov">
Fix: RemoteCacheStartupServlet can't start with config outside classpath
</action>