Merge changes from 2.1 release branch back into trunk
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/jcs/trunk@1782354 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/README.md b/README.md
index 78ebaca..49374d7 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jcs</artifactId>
- <version>2.1</version>
+ <version>2.0</version>
</dependency>
```
diff --git a/commons-jcs-core/pom.xml b/commons-jcs-core/pom.xml
index ea02976..1b35a29 100644
--- a/commons-jcs-core/pom.xml
+++ b/commons-jcs-core/pom.xml
@@ -33,9 +33,9 @@
<name>Apache Commons JCS :: Core</name>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-core</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-core</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-core</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-core</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-core</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core</url>
</scm>
<properties>
@@ -154,9 +154,6 @@
<exclude>**/UDPDiscoveryUnitTest.java</exclude>
<!-- Causes hang in Continuum -->
<exclude>**/UDPDiscoverySenderUnitTest.java</exclude>
- <!-- The ones that fail may be different for you. -->
- <!-- <exclude>**/JDBCDiskCacheRemovalUnitTest.java</exclude> -->
- <!-- <exclude>**/JDBCDiskCacheUnitTest.java</exclude> -->
</excludes>
</configuration>
</plugin>
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java
index 304df37..a51da23 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/JCS.java
@@ -130,6 +130,22 @@
}
/**
+ * Shut down the cache manager and set the instance to null
+ */
+ public static void shutdown()
+ {
+ synchronized ( JCS.class )
+ {
+ if ( cacheMgr != null && cacheMgr.isInitialized())
+ {
+ cacheMgr.shutDown();
+ }
+
+ cacheMgr = null;
+ }
+ }
+
+ /**
* Helper method which checks to make sure the cacheMgr class field is set, and if not requests
* an instance from CacheManagerFactory.
*
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
index 653220d..0b3d656 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/remote/AbstractRemoteAuxiliaryCache.java
@@ -26,8 +26,8 @@
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
-import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -77,7 +77,7 @@
private IRemoteCacheAttributes remoteCacheAttributes;
/** A thread pool for gets if configured. */
- private ThreadPoolExecutor pool = null;
+ private ExecutorService pool = null;
/** Should we get asynchronously using a pool. */
private boolean usePoolForGet = false;
@@ -113,15 +113,12 @@
if ( getRemoteCacheAttributes().getGetTimeoutMillis() > 0 )
{
- pool = ThreadPoolManager.getInstance().getPool( getRemoteCacheAttributes().getThreadPoolName() );
+ pool = ThreadPoolManager.getInstance().getExecutorService( getRemoteCacheAttributes().getThreadPoolName() );
if ( log.isDebugEnabled() )
{
log.debug( "Thread Pool = " + pool );
}
- if ( pool != null )
- {
- usePoolForGet = true;
- }
+ usePoolForGet = true;
}
}
@@ -145,7 +142,7 @@
getRemoteCacheListener().dispose();
}
}
- catch ( Exception ex )
+ catch ( IOException ex )
{
log.error( "Couldn't dispose", ex );
handleException( ex, "Failed to dispose [" + cacheName + "]", ICacheEventLogger.DISPOSE_EVENT );
@@ -573,8 +570,7 @@
if ( pool != null )
{
- elems.add(new StatElement<Integer>( "Pool Size", Integer.valueOf(pool.getPoolSize()) ) );
- elems.add(new StatElement<Integer>( "Maximum Pool Size", Integer.valueOf(pool.getMaximumPoolSize()) ) );
+ elems.add(new StatElement<ExecutorService>( "Pool", pool ) );
}
if ( getRemoteCacheService() instanceof ZombieCacheServiceNonLocal )
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java
index 216a94d..9f37b0c 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/AbstractCacheEventQueue.java
@@ -64,9 +64,6 @@
/** in milliseconds */
private int waitBeforeRetry;
- /** this is true if there is any worker thread. */
- private final AtomicBoolean alive = new AtomicBoolean(false);
-
/**
* This means that the queue is functional. If we reached the max number of failures, the queue
* is marked as non functional and will never work again.
@@ -108,21 +105,27 @@
* If they queue has an active thread it is considered alive.
* <p>
* @return The alive value
+ *
+ * @deprecated The alive-logic is not used
*/
- @Override
+ @Deprecated
+ @Override
public boolean isAlive()
{
- return alive.get();
+ return true;
}
/**
* Sets whether the queue is actively processing -- if there are working threads.
* <p>
* @param aState
+ *
+ * @deprecated The alive-logic is not used
*/
- public void setAlive( boolean aState )
+ @Deprecated
+ public void setAlive( boolean aState )
{
- alive.set(aState);
+ // do nothing
}
/**
@@ -179,17 +182,9 @@
* @throws IOException
*/
@Override
- public synchronized void addPutEvent( ICacheElement<K, V> ce )
- throws IOException
+ public void addPutEvent( ICacheElement<K, V> ce )
{
- if ( isWorking() )
- {
- put( new PutEvent( ce ) );
- }
- else if ( log.isWarnEnabled() )
- {
- log.warn( "Not enqueuing Put Event for [" + this + "] because it's non-functional." );
- }
+ put( new PutEvent( ce ) );
}
/**
@@ -200,54 +195,28 @@
* @throws IOException
*/
@Override
- public synchronized void addRemoveEvent( K key )
- throws IOException
+ public void addRemoveEvent( K key )
{
- if ( isWorking() )
- {
- put( new RemoveEvent( key ) );
- }
- else if ( log.isWarnEnabled() )
- {
- log.warn( "Not enqueuing Remove Event for [" + this + "] because it's non-functional." );
- }
+ put( new RemoveEvent( key ) );
}
/**
* This adds a remove all event to the queue. When it is processed, all elements will be removed
* from the cache.
- * <p>
- * @throws IOException
*/
@Override
- public synchronized void addRemoveAllEvent()
- throws IOException
+ public void addRemoveAllEvent()
{
- if ( isWorking() )
- {
- put( new RemoveAllEvent() );
- }
- else if ( log.isWarnEnabled() )
- {
- log.warn( "Not enqueuing RemoveAll Event for [" + this + "] because it's non-functional." );
- }
+ put( new RemoveAllEvent() );
}
/**
- * @throws IOException
+ * This adds a dispose event to the queue. When it is processed, the cache is shut down
*/
@Override
- public synchronized void addDisposeEvent()
- throws IOException
+ public void addDisposeEvent()
{
- if ( isWorking() )
- {
- put( new DisposeEvent() );
- }
- else if ( log.isWarnEnabled() )
- {
- log.warn( "Not enqueuing Dispose Event for [" + this + "] because it's non-functional." );
- }
+ put( new DisposeEvent() );
}
/**
@@ -293,8 +262,7 @@
log.warn( "Error while running event from Queue: " + this
+ ". Dropping Event and marking Event Queue as non-functional." );
}
- setWorking( false );
- setAlive( false );
+ destroy();
return;
}
if ( log.isInfoEnabled() )
@@ -312,10 +280,7 @@
{
log.warn( "Interrupted while sleeping for retry on event " + this + "." );
}
- // TODO consider if this is best. maybe we should just
- // destroy
- setWorking( false );
- setAlive( false );
+ destroy();
}
}
}
@@ -342,10 +307,8 @@
* Constructor for the PutEvent object.
* <p>
* @param ice
- * @throws IOException
*/
PutEvent( ICacheElement<K, V> ice )
- throws IOException
{
this.ice = ice;
}
@@ -391,10 +354,8 @@
* Constructor for the RemoveEvent object
* <p>
* @param key
- * @throws IOException
*/
RemoveEvent( K key )
- throws IOException
{
this.key = key;
}
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java
index 58fc27b..bf2758f 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/CacheEventQueue.java
@@ -1,9 +1,5 @@
package org.apache.commons.jcs.engine;
-import java.util.ArrayList;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -24,35 +20,19 @@
*/
import org.apache.commons.jcs.engine.behavior.ICacheListener;
-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;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
/**
* An event queue is used to propagate ordered cache events to one and only one target listener.
- * <p>
- * This is a modified version of the experimental version. It should lazy initialize the processor
- * thread, and kill the thread if the queue goes empty for a specified period, now set to 1 minute.
- * If something comes in after that a new processor thread should be created.
*/
public class CacheEventQueue<K, V>
- extends AbstractCacheEventQueue<K, V>
+ extends PooledCacheEventQueue<K, V>
{
- /** The logger. */
- private static final Log log = LogFactory.getLog( CacheEventQueue.class );
-
/** The type of queue -- there are pooled and single */
private static final QueueType queueType = QueueType.SINGLE;
- /** the thread that works the queue. */
- private Thread processorThread;
-
- /** Queue implementation */
- private LinkedBlockingQueue<AbstractCacheEvent> queue = new LinkedBlockingQueue<AbstractCacheEvent>();
-
/**
* Constructs with the specified listener and the cache name.
* <p>
@@ -77,7 +57,29 @@
public CacheEventQueue( ICacheListener<K, V> listener, long listenerId, String cacheName, int maxFailure,
int waitBeforeRetry )
{
- initialize( listener, listenerId, cacheName, maxFailure, waitBeforeRetry );
+ super( listener, listenerId, cacheName, maxFailure, waitBeforeRetry, null );
+ }
+
+ /**
+ * Initializes the queue.
+ * <p>
+ * @param listener
+ * @param listenerId
+ * @param cacheName
+ * @param maxFailure
+ * @param waitBeforeRetry
+ * @param threadPoolName
+ */
+ @Override
+ protected void initialize( ICacheListener<K, V> listener, long listenerId, String cacheName, int maxFailure,
+ int waitBeforeRetry, String threadPoolName )
+ {
+ super.initialize(listener, listenerId, cacheName, maxFailure, waitBeforeRetry);
+
+ // create a default pool with one worker thread to mimic the SINGLE queue behavior
+ pool = ThreadPoolManager.getInstance().createPool(
+ new PoolConfiguration(false, 0, 1, 0, getWaitToDieMillis(), WhenBlockedPolicy.RUN, 0),
+ "CacheEventQueue.QProcessor-" + getCacheName());
}
/**
@@ -90,192 +92,4 @@
{
return queueType;
}
-
- /**
- * Kill the processor thread and indicate that the queue is destroyed and no longer alive, but it
- * can still be working.
- */
- protected void stopProcessing()
- {
- setAlive(false);
- processorThread = null;
- }
-
- /**
- * Event Q is empty.
- * <p>
- * Calling destroy interrupts the processor thread.
- */
- @Override
- public void destroy()
- {
- if ( isAlive() )
- {
- setAlive(false);
-
- if ( log.isInfoEnabled() )
- {
- log.info( "Destroying queue, stats = " + getStatistics() );
- }
-
- if ( processorThread != null )
- {
- processorThread.interrupt();
- processorThread = null;
- }
-
- if ( log.isInfoEnabled() )
- {
- log.info( "Cache event queue destroyed: " + this );
- }
- }
- else
- {
- if ( log.isInfoEnabled() )
- {
- log.info( "Destroy was called after queue was destroyed. Doing nothing. Stats = " + getStatistics() );
- }
- }
- }
-
- /**
- * Adds an event to the queue.
- * <p>
- * @param event
- */
- @Override
- protected void put( AbstractCacheEvent event )
- {
- if ( log.isDebugEnabled() )
- {
- log.debug( "Event entering Queue for " + getCacheName() + ": " + event );
- }
-
- queue.offer(event);
-
- if ( isWorking() )
- {
- if ( !isAlive() )
- {
- setAlive(true);
- processorThread = new QProcessor();
- processorThread.start();
- if ( log.isInfoEnabled() )
- {
- log.info( "Cache event queue created: " + this );
- }
- }
- }
- }
-
- // /////////////////////////// Inner classes /////////////////////////////
-
- /**
- * This is the thread that works the queue.
- * <p>
- * @author asmuts
- * @created January 15, 2002
- */
- protected class QProcessor
- extends Thread
- {
- /**
- * Constructor for the QProcessor object
- * <p>
- * @param aQueue the event queue to take items from.
- */
- QProcessor()
- {
- super( "CacheEventQueue.QProcessor-" + getCacheName() );
- setDaemon( true );
- }
-
- /**
- * Main processing method for the QProcessor object.
- * <p>
- * Waits for a specified time (waitToDieMillis) for something to come in and if no new
- * events come in during that period the run method can exit and the thread is dereferenced.
- */
- @Override
- public void run()
- {
-
- while ( CacheEventQueue.this.isAlive() )
- {
- AbstractCacheEvent event = null;
-
- try
- {
- event = queue.poll(getWaitToDieMillis(), TimeUnit.MILLISECONDS);
- }
- catch (InterruptedException e)
- {
- // is ok
- }
-
- if ( log.isDebugEnabled() )
- {
- log.debug( "Event from queue = " + event );
- }
-
- if ( event == null )
- {
- stopProcessing();
- }
-
- if ( event != null && isWorking() && CacheEventQueue.this.isAlive() )
- {
- event.run();
- }
- }
- if ( log.isDebugEnabled() )
- {
- log.debug( "QProcessor exiting for " + getCacheName() );
- }
- }
- }
-
- /**
- * This method returns semi-structured data on this queue.
- * <p>
- * @see org.apache.commons.jcs.engine.behavior.ICacheEventQueue#getStatistics()
- * @return information on the status and history of the queue
- */
- @Override
- public IStats getStatistics()
- {
- IStats stats = new Stats();
- stats.setTypeName( "Cache Event Queue" );
-
- ArrayList<IStatElement<?>> elems = new ArrayList<IStatElement<?>>();
-
- elems.add(new StatElement<Boolean>( "Working", Boolean.valueOf(this.isWorking()) ) );
- elems.add(new StatElement<Boolean>( "Alive", Boolean.valueOf(this.isAlive()) ) );
- elems.add(new StatElement<Boolean>( "Empty", Boolean.valueOf(this.isEmpty()) ) );
- elems.add(new StatElement<Integer>( "Size", Integer.valueOf(this.size()) ) );
-
- stats.setStatElements( elems );
-
- return stats;
- }
-
- /**
- * @return whether there are any items in the queue.
- */
- @Override
- public boolean isEmpty()
- {
- return queue.isEmpty();
- }
-
- /**
- * Returns the number of elements in the queue.
- * <p>
- * @return number of items in the queue.
- */
- @Override
- public int size()
- {
- return queue.size();
- }
}
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java
index 81dfe23..e4b1089 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/PooledCacheEventQueue.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
/*
@@ -52,7 +53,10 @@
private static final QueueType queueType = QueueType.POOLED;
/** The Thread Pool to execute events with. */
- private ThreadPoolExecutor pool = null;
+ protected ExecutorService pool = null;
+
+ /** The Thread Pool queue */
+ protected BlockingQueue<Runnable> queue = null;
/**
* Constructor for the CacheEventQueue object
@@ -86,8 +90,13 @@
super.initialize(listener, listenerId, cacheName, maxFailure, waitBeforeRetry);
// this will share the same pool with other event queues by default.
- pool = ThreadPoolManager.getInstance().getPool(
+ pool = ThreadPoolManager.getInstance().getExecutorService(
(threadPoolName == null) ? "cache_event_queue" : threadPoolName );
+
+ if (pool instanceof ThreadPoolExecutor)
+ {
+ queue = ((ThreadPoolExecutor) pool).getQueue();
+ }
}
/**
@@ -105,9 +114,9 @@
@Override
public synchronized void destroy()
{
- if ( isAlive() )
+ if ( isWorking() )
{
- setAlive(false);
+ setWorking(false);
pool.shutdownNow();
if ( log.isInfoEnabled() )
{
@@ -138,20 +147,15 @@
ArrayList<IStatElement<?>> elems = new ArrayList<IStatElement<?>>();
- elems.add(new StatElement<Boolean>( "Working", Boolean.valueOf(super.isWorking()) ) );
- elems.add(new StatElement<Boolean>( "Alive", Boolean.valueOf(this.isAlive()) ) );
+ elems.add(new StatElement<Boolean>( "Working", Boolean.valueOf(isWorking()) ) );
elems.add(new StatElement<Boolean>( "Empty", Boolean.valueOf(this.isEmpty()) ) );
- if ( pool.getQueue() != null )
+ if ( queue != null )
{
- BlockingQueue<Runnable> bb = pool.getQueue();
- elems.add(new StatElement<Integer>( "Queue Size", Integer.valueOf(bb.size()) ) );
- elems.add(new StatElement<Integer>( "Queue Capacity", Integer.valueOf(bb.remainingCapacity()) ) );
+ elems.add(new StatElement<Integer>( "Queue Size", Integer.valueOf(queue.size()) ) );
+ elems.add(new StatElement<Integer>( "Queue Capacity", Integer.valueOf(queue.remainingCapacity()) ) );
}
- elems.add(new StatElement<Integer>( "Pool Size", Integer.valueOf(pool.getPoolSize()) ) );
- elems.add(new StatElement<Integer>( "Maximum Pool Size", Integer.valueOf(pool.getMaximumPoolSize()) ) );
-
stats.setStatElements( elems );
return stats;
@@ -166,32 +170,25 @@
@Override
public boolean isEmpty()
{
- if ( pool.getQueue() == null )
- {
- return true;
- }
- else
- {
- return pool.getQueue().size() == 0;
- }
+ return size() == 0;
}
/**
* Returns the number of elements in the queue. If the queue cannot determine the size
- * accurately it will return 1.
+ * accurately it will return 0.
* <p>
* @return number of items in the queue.
*/
@Override
public int size()
{
- if ( pool.getQueue() == null )
+ if ( queue == null )
{
return 0;
}
else
{
- return pool.getQueue().size();
+ return queue.size();
}
}
}
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java
index 1a6e9bd..44ab573 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/control/event/ElementEventQueue.java
@@ -20,14 +20,14 @@
*/
import java.io.IOException;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutorService;
import org.apache.commons.jcs.engine.control.event.behavior.IElementEvent;
import org.apache.commons.jcs.engine.control.event.behavior.IElementEventHandler;
import org.apache.commons.jcs.engine.control.event.behavior.IElementEventQueue;
-import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -45,20 +45,16 @@
/** shutdown or not */
private boolean destroyed = false;
- /** The event queue */
- private LinkedBlockingQueue<Runnable> queue;
-
/** The worker thread pool. */
- private ThreadPoolExecutor queueProcessor;
+ private ExecutorService queueProcessor;
/**
* Constructor for the ElementEventQueue object
*/
public ElementEventQueue()
{
- queue = new LinkedBlockingQueue<Runnable>();
- queueProcessor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
- queue, new DaemonThreadFactory(THREAD_PREFIX));
+ queueProcessor = ThreadPoolManager.getInstance().createPool(
+ new PoolConfiguration(false, 0, 1, 1, 0, WhenBlockedPolicy.RUN, 1), THREAD_PREFIX);
if ( log.isDebugEnabled() )
{
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
index b5523d7..5f85104 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractDoubleLinkedListMemoryCache.java
@@ -20,15 +20,10 @@
*/
import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import org.apache.commons.jcs.engine.CacheConstants;
import org.apache.commons.jcs.engine.behavior.ICacheElement;
import org.apache.commons.jcs.engine.control.CompositeCache;
import org.apache.commons.jcs.engine.control.group.GroupAttrName;
@@ -199,74 +194,6 @@
}
/**
- * Get an item from the cache If the item is found, it is removed from the list and added first.
- * <p>
- *
- * @param key
- * Identifies item to find
- * @return ICacheElement<K, V> if found, else null
- * @throws IOException
- */
- @Override
- public final ICacheElement<K, V> get(K key) throws IOException
- {
- ICacheElement<K, V> ce = null;
-
- if (log.isDebugEnabled())
- {
- log.debug(getCacheName() + ": getting item for key " + key);
- }
-
- MemoryElementDescriptor<K, V> me = map.get(key);
-
- if (me != null)
- {
- hitCnt.incrementAndGet();
-
- lock.lock();
- try
- {
- ce = me.getCacheElement();
- // ABSTRACT
- adjustListForGet(me);
- }
- finally
- {
- lock.unlock();
- }
-
- if (log.isDebugEnabled())
- {
- log.debug(getCacheName() + ": LRUMemoryCache hit for " + key);
- }
- }
- else
- {
- missCnt.incrementAndGet();
-
- if (log.isDebugEnabled())
- {
- log.debug(getCacheName() + ": LRUMemoryCache miss for " + key);
- }
- }
-
- if (log.isDebugEnabled())
- {
- verifyCache();
- }
-
- return ce;
- }
-
- /**
- * Adjust the list as needed for a get. This allows children to control the algorithm
- * <p>
- *
- * @param me
- */
- protected abstract void adjustListForGet(MemoryElementDescriptor<K, V> me);
-
- /**
* This instructs the memory cache to remove the <i>numberToFree</i> according to its eviction
* policy. For example, the LRUMemoryCache will remove the <i>numberToFree</i> least recently
* used items. These will be spooled to disk if a disk auxiliary is available.
@@ -343,116 +270,61 @@
}
/**
- * 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
+ * @see org.apache.commons.jcs.engine.memory.AbstractMemoryCache#get(java.lang.Object)
*/
@Override
- public boolean remove(K key) throws IOException
+ public ICacheElement<K, V> get(K key) throws IOException
{
+ ICacheElement<K, V> ce = super.get(key);
+
if (log.isDebugEnabled())
{
- log.debug("removing item for key: " + key);
+ verifyCache();
}
- 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
- {
- list.remove(entry.getValue());
- 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
- {
- list.remove(entry.getValue());
- itr.remove();
- removed = true;
- }
- finally
- {
- lock.unlock();
- }
- }
- }
- }
- else
- {
- // remove single item.
- lock.lock();
- try
- {
- MemoryElementDescriptor<K, V> me = map.remove(key);
- if (me != null)
- {
- list.remove(me);
- removed = true;
- }
- }
- finally
- {
- lock.unlock();
- }
- }
-
- return removed;
+ return ce;
}
/**
- * Remove all of the elements from both the Map and the linked list implementation. Overrides
- * base class.
+ * Adjust the list as needed for a get. This allows children to control the algorithm
* <p>
*
- * @throws IOException
+ * @param me
+ */
+ protected abstract void adjustListForGet(MemoryElementDescriptor<K, V> me);
+
+ /**
+ * Update control structures after get
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
*/
@Override
- public void removeAll() throws IOException
+ protected void lockedGetElement(MemoryElementDescriptor<K, V> me)
{
- lock.lock();
- try
- {
- list.removeAll();
- map.clear();
- }
- finally
- {
- lock.unlock();
- }
+ adjustListForGet(me);
+ }
+
+ /**
+ * Remove element from control structure
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
+ */
+ @Override
+ protected void lockedRemoveElement(MemoryElementDescriptor<K, V> me)
+ {
+ list.remove(me);
+ }
+
+ /**
+ * Removes all cached items from the cache control structures.
+ * (guarded by the lock)
+ */
+ @Override
+ protected void lockedRemoveAll()
+ {
+ list.removeAll();
}
// --------------------------- internal methods (linked list implementation)
@@ -631,17 +503,6 @@
}
/**
- * Get an Array of the keys for all elements in the memory cache
- *
- * @return An Object[]
- */
- @Override
- public Set<K> getKeySet()
- {
- return new LinkedHashSet<K>(map.keySet());
- }
-
- /**
* This returns semi-structured information on the memory cache, such as the size, put count,
* hit count, and miss count.
* <p>
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
index 87929fa..dc4bf5c 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/AbstractMemoryCache.java
@@ -22,16 +22,19 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import org.apache.commons.jcs.engine.CacheStatus;
+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.behavior.IMemoryCache;
import org.apache.commons.jcs.engine.memory.util.MemoryElementDescriptor;
import org.apache.commons.jcs.engine.stats.StatElement;
@@ -43,9 +46,6 @@
/**
* This base includes some common code for memory caches.
- * <p>
- * This keeps a static reference to a memory shrinker clock daemon. If this region is configured to
- * use the shrinker, the clock daemon will be setup to run the shrinker on this region.
*/
public abstract class AbstractMemoryCache<K, V>
implements IMemoryCache<K, V>
@@ -59,9 +59,6 @@
/** The cache region this store is associated with */
private CompositeCache<K, V> cache;
- /** status */
- private CacheStatus status;
-
/** How many to spool at a time. */
protected int chunkSize;
@@ -96,8 +93,6 @@
this.cache = hub;
this.map = createMap();
-
- this.status = CacheStatus.ALIVE;
}
/**
@@ -109,28 +104,6 @@
public abstract Map<K, MemoryElementDescriptor<K, V>> createMap();
/**
- * Removes an item from the cache
- * <p>
- * @param key Identifies item to be removed
- * @return Description of the Return Value
- * @throws IOException Description of the Exception
- */
- @Override
- public abstract boolean remove( K key )
- throws IOException;
-
- /**
- * 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 abstract ICacheElement<K, V> get( K key )
- throws IOException;
-
- /**
* Gets multiple items from the cache based on the given set of keys.
* <p>
* @param keys
@@ -203,26 +176,32 @@
throws IOException;
/**
- * Get a set of the keys for all elements in the memory cache
- * <p>
- * @return A set of the key type
- */
- @Override
- public abstract Set<K> getKeySet();
-
- /**
* Removes all cached items from the cache.
* <p>
* @throws IOException
*/
@Override
- public void removeAll()
- throws IOException
+ public void removeAll() throws IOException
{
- map.clear();
+ lock.lock();
+ try
+ {
+ lockedRemoveAll();
+ map.clear();
+ }
+ finally
+ {
+ lock.unlock();
+ }
}
/**
+ * Removes all cached items from the cache control structures.
+ * (guarded by the lock)
+ */
+ protected abstract void lockedRemoveAll();
+
+ /**
* Prepares for shutdown. Reset statistics
* <p>
* @throws IOException
@@ -270,16 +249,6 @@
}
/**
- * Returns the cache status.
- * <p>
- * @return The status value
- */
- public CacheStatus getStatus()
- {
- return this.status;
- }
-
- /**
* Returns the cache (aka "region") name.
* <p>
* @return The cacheName value
@@ -351,4 +320,204 @@
{
return this.cache;
}
+
+ /**
+ * Remove all keys of the same group hierarchy.
+ * @param key the key
+ * @return true if something has been removed
+ */
+ protected boolean removeByGroup(K key)
+ {
+ boolean removed = false;
+
+ // remove all keys of the same group 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
+ {
+ itr.remove();
+ lockedRemoveElement(entry.getValue());
+ removed = true;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+ }
+
+ return removed;
+ }
+
+ /**
+ * Remove all keys of the same name hierarchy.
+ *
+ * @param key the key
+ * @return true if something has been removed
+ */
+ protected boolean removeByHierarchy(K key)
+ {
+ boolean removed = false;
+
+ // 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
+ {
+ itr.remove();
+ lockedRemoveElement(entry.getValue());
+ removed = true;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+ }
+
+ return removed;
+ }
+
+ /**
+ * Remove element from control structure
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
+ */
+ protected abstract void lockedRemoveElement(MemoryElementDescriptor<K, V> me);
+
+ /**
+ * 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))
+ {
+ removed = removeByHierarchy(key);
+ }
+ else if (key instanceof GroupAttrName && ((GroupAttrName<?>) key).attrName == null)
+ {
+ removed = removeByGroup(key);
+ }
+ else
+ {
+ // remove single item.
+ lock.lock();
+ try
+ {
+ MemoryElementDescriptor<K, V> me = map.remove(key);
+ if (me != null)
+ {
+ lockedRemoveElement(me);
+ removed = true;
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ return removed;
+ }
+
+ /**
+ * Get an Array of the keys for all elements in the memory cache
+ *
+ * @return An Object[]
+ */
+ @Override
+ public Set<K> getKeySet()
+ {
+ return new LinkedHashSet<K>(map.keySet());
+ }
+
+ /**
+ * Get an item from the cache.
+ * <p>
+ *
+ * @param key Identifies item to find
+ * @return ICacheElement<K, V> if found, else null
+ * @throws IOException
+ */
+ @Override
+ public ICacheElement<K, V> get(K key) throws IOException
+ {
+ ICacheElement<K, V> ce = null;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug(getCacheName() + ": getting item for key " + key);
+ }
+
+ MemoryElementDescriptor<K, V> me = map.get(key);
+
+ if (me != null)
+ {
+ hitCnt.incrementAndGet();
+ ce = me.getCacheElement();
+
+ lock.lock();
+ try
+ {
+ lockedGetElement(me);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug(getCacheName() + ": MemoryCache hit for " + key);
+ }
+ }
+ else
+ {
+ missCnt.incrementAndGet();
+
+ if (log.isDebugEnabled())
+ {
+ log.debug(getCacheName() + ": MemoryCache miss for " + key);
+ }
+ }
+
+ return ce;
+ }
+
+ /**
+ * Update control structures after get
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
+ */
+ protected abstract void lockedGetElement(MemoryElementDescriptor<K, V> me);
}
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
index b6ff779..2679fb7 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/lru/LHMLRUMemoryCache.java
@@ -21,15 +21,10 @@
import java.io.IOException;
import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.Map;
-import java.util.Set;
-import org.apache.commons.jcs.engine.CacheConstants;
import org.apache.commons.jcs.engine.behavior.ICacheElement;
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.stats.behavior.IStats;
@@ -83,124 +78,37 @@
}
/**
- * Get an item from the cache
- * <p>
- * @param key Identifies item to find
- * @return ICacheElement<K, V> if found, else null
- * @throws IOException
+ * Update control structures after get
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
*/
@Override
- public ICacheElement<K, V> get( K key )
- throws IOException
+ protected void lockedGetElement(MemoryElementDescriptor<K, V> me)
{
- if ( log.isDebugEnabled() )
- {
- log.debug( "getting item from cache " + getCacheName() + " for key " + key );
- }
-
- MemoryElementDescriptor<K, V> me = map.get( key );
-
- if ( me != null )
- {
- hitCnt.incrementAndGet();
- if ( log.isDebugEnabled() )
- {
- log.debug( getCacheName() + ": LHMLRUMemoryCache hit for " + key );
- }
- return me.getCacheElement();
- }
- else
- {
- missCnt.incrementAndGet();
- if ( log.isDebugEnabled() )
- {
- log.debug( getCacheName() + ": LHMLRUMemoryCache miss for " + key );
- }
- }
-
- return null;
+ // empty
}
/**
- * 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 removed
- * @throws IOException
+ * Remove element from control structure
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
*/
@Override
- public boolean remove( K key )
- throws IOException
+ protected void lockedRemoveElement(MemoryElementDescriptor<K, V> me)
{
- 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.
- synchronized ( map )
- {
- 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() ) )
- {
- itr.remove();
- removed = true;
- }
- }
- }
- }
- else if ( key instanceof GroupAttrName && ((GroupAttrName<?>)key).attrName == null )
- {
- // remove all keys of the same name hierarchy.
- synchronized ( map )
- {
- 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) )
- {
- itr.remove();
- removed = true;
- }
- }
- }
- }
- else
- {
- // remove single item.
- MemoryElementDescriptor<K, V> me = map.remove( key );
- if ( me != null )
- {
- removed = true;
- }
- }
-
- return removed;
+ // empty
}
/**
- * Get an Array of the keys for all elements in the memory cache
- * <p>
- * @return An Object[]
+ * Removes all cached items from the cache control structures.
+ * (guarded by the lock)
*/
@Override
- public Set<K> getKeySet()
+ protected void lockedRemoveAll()
{
- return new LinkedHashSet<K>(map.keySet());
+ // empty
}
/**
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
index 5108c66..b5c703b 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/engine/memory/soft/SoftReferenceMemoryCache.java
@@ -22,7 +22,6 @@
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -30,11 +29,9 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.LinkedBlockingQueue;
-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;
@@ -147,107 +144,41 @@
}
/**
- * 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>
+ * Update control structures after get
+ * (guarded by the lock)
*
- * @param key
- * @return true if the removal was successful
- * @throws IOException
+ * @param me the memory element descriptor
*/
@Override
- public boolean remove(K key) throws IOException
+ protected void lockedGetElement(MemoryElementDescriptor<K, V> me)
{
- if (log.isDebugEnabled())
- {
- log.debug("removing item for key: " + key);
- }
+ ICacheElement<K, V> val = me.getCacheElement();
+ val.getElementAttributes().setLastAccessTimeNow();
- 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;
+ // update the ordering of the strong references
+ strongReferences.add(val);
+ trimStrongReferences();
}
/**
- * Removes all cached items from the cache.
- * <p>
- * @throws IOException
+ * Remove element from control structure
+ * (guarded by the lock)
+ *
+ * @param me the memory element descriptor
*/
@Override
- public void removeAll() throws IOException
+ protected void lockedRemoveElement(MemoryElementDescriptor<K, V> me)
{
- super.removeAll();
+ strongReferences.remove(me.getCacheElement());
+ }
+
+ /**
+ * Removes all cached items from the cache control structures.
+ * (guarded by the lock)
+ */
+ @Override
+ protected void lockedRemoveAll()
+ {
strongReferences.clear();
}
@@ -294,48 +225,6 @@
}
/**
- * 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;
- }
-
- /**
* This can't be implemented.
* <p>
* @param numberToFree
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
index e8f9cba..07a6687 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/discovery/UDPDiscoveryReceiver.java
@@ -25,14 +25,15 @@
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.ExecutorService;
import org.apache.commons.jcs.engine.CacheInfo;
import org.apache.commons.jcs.engine.behavior.IShutdownObserver;
import org.apache.commons.jcs.io.ObjectInputStreamClassLoaderAware;
import org.apache.commons.jcs.utils.discovery.UDPDiscoveryMessage.BroadcastType;
-import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration;
+import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.threadpool.ThreadPoolManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -56,7 +57,7 @@
private static final int maxPoolSize = 2;
/** The processor */
- private ThreadPoolExecutor pooledExecutor = null;
+ private ExecutorService pooledExecutor = null;
/** number of messages received. For debugging and testing. */
private int cnt = 0;
@@ -91,10 +92,9 @@
this.multicastPort = multicastPort;
// create a small thread pool to handle a barrage
- pooledExecutor = (ThreadPoolExecutor)Executors.newFixedThreadPool(maxPoolSize,
- new DaemonThreadFactory("JCS-UDPDiscoveryReceiver-", Thread.MIN_PRIORITY));
- pooledExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
- //pooledExecutor.setMinimumPoolSize(1);
+ pooledExecutor = ThreadPoolManager.getInstance().createPool(
+ new PoolConfiguration(false, 0, maxPoolSize, maxPoolSize, 0, WhenBlockedPolicy.DISCARDOLDEST, maxPoolSize),
+ "JCS-UDPDiscoveryReceiver-", Thread.MIN_PRIORITY);
if ( log.isInfoEnabled() )
{
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java
index c747f4c..9effd97 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/AbstractLRUMap.java
@@ -64,22 +64,20 @@
private final DoubleLinkedList<LRUElementDescriptor<K, V>> list;
/** Map where items are stored by key. */
- private Map<K, LRUElementDescriptor<K, V>> map;
+ private final Map<K, LRUElementDescriptor<K, V>> map;
- /** stats */
- int hitCnt = 0;
-
- /** stats */
- int missCnt = 0;
-
- /** stats */
- int putCnt = 0;
-
- /** make configurable */
- private int chunkSize = 1;
-
+ /** lock to keep map and list synchronous */
private final Lock lock = new ReentrantLock();
+ /** stats */
+ private long hitCnt = 0;
+
+ /** stats */
+ private long missCnt = 0;
+
+ /** stats */
+ private long putCnt = 0;
+
/**
* This creates an unbounded version. Setting the max objects will result in spooling on
* subsequent puts.
@@ -196,7 +194,7 @@
@Override
public V get( Object key )
{
- V retVal = null;
+ V retVal;
if ( log.isDebugEnabled() )
{
@@ -205,22 +203,28 @@
LRUElementDescriptor<K, V> me = map.get( key );
- if ( me != null )
+ if ( me == null )
{
- hitCnt++;
- if ( log.isDebugEnabled() )
- {
- log.debug( "LRUMap hit for " + key );
- }
-
- retVal = me.getPayload();
-
- list.makeFirst( me );
+ missCnt++;
+ retVal = null;
}
else
{
- missCnt++;
- log.debug( "LRUMap miss for " + key );
+ hitCnt++;
+ retVal = me.getPayload();
+ list.makeFirst( me );
+ }
+
+ if ( log.isDebugEnabled() )
+ {
+ if ( me == null )
+ {
+ log.debug( "LRUMap miss for " + key );
+ }
+ else
+ {
+ log.debug( "LRUMap hit for " + key );
+ }
}
// verifyCache();
@@ -238,20 +242,23 @@
public V getQuiet( Object key )
{
V ce = null;
-
LRUElementDescriptor<K, V> me = map.get( key );
+
if ( me != null )
{
- if ( log.isDebugEnabled() )
+ ce = me.getPayload();
+ }
+
+ if ( log.isDebugEnabled() )
+ {
+ if ( me == null )
+ {
+ log.debug( "LRUMap quiet miss for " + key );
+ }
+ else
{
log.debug( "LRUMap quiet hit for " + key );
}
-
- ce = me.getPayload();
- }
- else if ( log.isDebugEnabled() )
- {
- log.debug( "LRUMap quiet miss for " + key );
}
return ce;
@@ -300,17 +307,16 @@
putCnt++;
LRUElementDescriptor<K, V> old = null;
+ LRUElementDescriptor<K, V> me = new LRUElementDescriptor<K, V>(key, value);
+
lock.lock();
try
{
- // TODO address double synchronization of addFirst, use write lock
- addFirst( key, value );
- // this must be synchronized
- LRUElementDescriptor<K, V> first = list.getFirst();
- old = map.put(first.getKey(), first);
+ list.addFirst( me );
+ old = map.put(key, me);
// If the node was the same as an existing node, remove it.
- if ( old != null && first.getKey().equals(old.getKey()))
+ if ( old != null && key.equals(old.getKey()))
{
list.remove( old );
}
@@ -321,7 +327,6 @@
}
// If the element limit is reached, we need to spool
-
if (shouldRemove())
{
if (log.isDebugEnabled())
@@ -332,7 +337,6 @@
// The spool will put them in a disk event queue, so there is no
// need to pre-queue the queuing. This would be a bit wasteful
// and wouldn't save much time in this synchronous call.
-
while ( shouldRemove() )
{
lock.lock();
@@ -366,10 +370,10 @@
{
log.debug( "update: After spool map size: " + map.size() );
}
- if ( map.size() != dumpCacheSize() )
+ if ( map.size() != list.size() )
{
- log.error("update: After spool, size mismatch: map.size() = " + map.size() + ", linked list size = "
- + dumpCacheSize());
+ log.error("update: After spool, size mismatch: map.size() = " + map.size() +
+ ", linked list size = " + list.size());
}
}
@@ -382,37 +386,6 @@
protected abstract boolean shouldRemove();
-
- /**
- * Adds a new node to the start of the link list.
- * <p>
- * @param key
- * @param val The feature to be added to the First
- */
- private void addFirst(K key, V val)
- {
- lock.lock();
- try
- {
- LRUElementDescriptor<K, V> me = new LRUElementDescriptor<K, V>(key, val);
- list.addFirst( me );
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Returns the size of the list.
- * <p>
- * @return int
- */
- private int dumpCacheSize()
- {
- return list.size();
- }
-
/**
* Dump the cache entries from first to list for debugging.
*/
@@ -458,8 +431,8 @@
}
boolean found = false;
- log.debug( "verifycache: mapContains " + map.size() + " elements, linked list contains " + dumpCacheSize()
- + " elements" );
+ log.debug( "verifycache: mapContains " + map.size() +
+ " elements, linked list contains " + list.size() + " elements" );
log.debug( "verifycache: checking linked list by key " );
for (LRUElementDescriptor<K, V> li = list.getFirst(); li != null; li = (LRUElementDescriptor<K, V>) li.next )
{
@@ -537,37 +510,6 @@
}
/**
- * Logs an error is an element that should be in the cache is not.
- * <p>
- * @param key
- */
- @SuppressWarnings("unchecked") // No generics for public fields
- protected void verifyCache( Object key )
- {
- if ( !log.isDebugEnabled() )
- {
- return;
- }
-
- boolean found = false;
-
- // go through the linked list looking for the key
- for (LRUElementDescriptor<K, V> li = list.getFirst(); li != null; li = (LRUElementDescriptor<K, V>) li.next )
- {
- if ( li.getKey() == key )
- {
- found = true;
- log.debug( "verifycache(key) key match: " + key );
- break;
- }
- }
- if ( !found )
- {
- log.error( "verifycache(key), couldn't find key! : " + key );
- }
- }
-
- /**
* This is called when an item is removed from the LRU. We just log some information.
* <p>
* Children can implement this method for special behavior.
@@ -584,24 +526,6 @@
}
/**
- * The chunk size is the number of items to remove when the max is reached. By default it is 1.
- * <p>
- * @param chunkSize The chunkSize to set.
- */
- public void setChunkSize( int chunkSize )
- {
- this.chunkSize = chunkSize;
- }
-
- /**
- * @return Returns the chunkSize.
- */
- public int getChunkSize()
- {
- return chunkSize;
- }
-
- /**
* @return IStats
*/
public IStats getStatistics()
@@ -613,9 +537,9 @@
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<Integer>( "Put Count", Integer.valueOf(putCnt) ) );
- elems.add(new StatElement<Integer>( "Hit Count", Integer.valueOf(hitCnt) ) );
- elems.add(new StatElement<Integer>( "Miss Count", Integer.valueOf(missCnt) ) );
+ elems.add(new StatElement<Long>( "Put Count", Long.valueOf(putCnt) ) );
+ elems.add(new StatElement<Long>( "Hit Count", Long.valueOf(hitCnt) ) );
+ elems.add(new StatElement<Long>( "Miss Count", Long.valueOf(missCnt) ) );
stats.setStatElements( elems );
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java
index fa100b2..84ff231 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/struct/LRUMap.java
@@ -19,8 +19,6 @@
* under the License.
*/
-import java.util.concurrent.atomic.AtomicInteger;
-
/**
*
* @author Wiktor Niesiobędzki
@@ -32,10 +30,8 @@
*/
public class LRUMap<K, V> extends AbstractLRUMap<K, V>
{
-
/** if the max is less than 0, there is no limit! */
- int maxObjects = -1;
- AtomicInteger counter = new AtomicInteger(0);
+ private int maxObjects = -1;
public LRUMap()
{
@@ -49,7 +45,7 @@
*/
public LRUMap(int maxObjects)
{
- super();
+ this();
this.maxObjects = maxObjects;
}
@@ -58,9 +54,4 @@
{
return maxObjects > 0 && this.size() > maxObjects;
}
-
- public Object getMaxCounter()
- {
- return maxObjects;
- }
}
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java
index 05f17e7..f4e886d 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/PoolConfiguration.java
@@ -27,23 +27,46 @@
public final class PoolConfiguration
implements Cloneable
{
+ /**
+ * DEFAULT SETTINGS
+ */
+ private static final boolean DEFAULT_USE_BOUNDARY = true;
+
+ /** Default queue size limit */
+ private static final int DEFAULT_BOUNDARY_SIZE = 2000;
+
+ /** Default max size */
+ private static final int DEFAULT_MAXIMUM_POOL_SIZE = 150;
+
+ /** Default min */
+ private static final int DEFAULT_MINIMUM_POOL_SIZE = Runtime.getRuntime().availableProcessors();
+
+ /** Default keep alive */
+ private static final int DEFAULT_KEEPALIVE_TIME = 1000 * 60 * 5;
+
+ /** Default when blocked */
+ private static final WhenBlockedPolicy DEFAULT_WHEN_BLOCKED_POLICY = WhenBlockedPolicy.RUN;
+
+ /** Default startup size */
+ private static final int DEFAULT_STARTUP_SIZE = DEFAULT_MINIMUM_POOL_SIZE;
+
/** Should we bound the queue */
- private boolean useBoundary = true;
+ private boolean useBoundary = DEFAULT_USE_BOUNDARY;
/** If the queue is bounded, how big can it get */
- private int boundarySize = 2000;
+ private int boundarySize = DEFAULT_BOUNDARY_SIZE;
/** only has meaning if a boundary is used */
- private int maximumPoolSize = 150;
+ private int maximumPoolSize = DEFAULT_MAXIMUM_POOL_SIZE;
/**
* the exact number that will be used in a boundless queue. If the queue has a boundary, more
* will be created if the queue fills.
*/
- private int minimumPoolSize = 4;
+ private int minimumPoolSize = DEFAULT_MINIMUM_POOL_SIZE;
/** How long idle threads above the minimum should be kept alive. */
- private int keepAliveTime = 1000 * 60 * 5;
+ private int keepAliveTime = DEFAULT_KEEPALIVE_TIME;
public enum WhenBlockedPolicy {
/** abort when queue is full and max threads is reached. */
@@ -63,10 +86,10 @@
}
/** should be ABORT, BLOCK, RUN, WAIT, DISCARDOLDEST, */
- private WhenBlockedPolicy whenBlockedPolicy = WhenBlockedPolicy.RUN;
+ private WhenBlockedPolicy whenBlockedPolicy = DEFAULT_WHEN_BLOCKED_POLICY;
/** The number of threads to create on startup */
- private int startUpSize = 4;
+ private int startUpSize = DEFAULT_MINIMUM_POOL_SIZE;
/**
* @param useBoundary The useBoundary to set.
@@ -89,7 +112,9 @@
*/
public PoolConfiguration()
{
- // nop
+ this( DEFAULT_USE_BOUNDARY, DEFAULT_BOUNDARY_SIZE, DEFAULT_MAXIMUM_POOL_SIZE,
+ DEFAULT_MINIMUM_POOL_SIZE, DEFAULT_KEEPALIVE_TIME,
+ DEFAULT_WHEN_BLOCKED_POLICY, DEFAULT_STARTUP_SIZE );
}
/**
diff --git a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java
index 0c9346c..93ca842 100644
--- a/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java
+++ b/commons-jcs-core/src/main/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManager.java
@@ -23,11 +23,14 @@
import java.util.Properties;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import org.apache.commons.jcs.utils.threadpool.PoolConfiguration.WhenBlockedPolicy;
+import org.apache.commons.jcs.utils.config.PropertySetter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -39,30 +42,12 @@
* This manager forces you to use a bounded queue. By default it uses the current thread for
* execution when the buffer is full and no free threads can be created.
* <p>
- * You can specify the props file to use or pass in a properties object prior to configuration. By
- * default it looks for configuration information in thread_pool.properties.
+ * You can specify the props file to use or pass in a properties object prior to configuration.
* <p>
* If set, the Properties object will take precedence.
* <p>
- * If a value is not set for a particular pool, the hard coded defaults will be used.
- *
- * <pre>
- * int boundarySize_DEFAULT = 2000;
- *
- * int maximumPoolSize_DEFAULT = 150;
- *
- * int minimumPoolSize_DEFAULT = 4;
- *
- * int keepAliveTime_DEFAULT = 1000 * 60 * 5;
- *
- * boolean abortWhenBlocked = false;
- *
- * String whenBlockedPolicy_DEFAULT = IPoolConfiguration.POLICY_RUN;
- *
- * int startUpSize_DEFAULT = 4;
- * </pre>
- *
- * You can configure default settings by specifying a default pool in the properties, ie "cache.ccf"
+ * If a value is not set for a particular pool, the hard coded defaults in <code>PoolConfiguration</code> will be used.
+ * You can configure default settings by specifying <code>thread_pool.default</code> in the properties, ie "cache.ccf"
* <p>
* @author Aaron Smuts
*/
@@ -71,31 +56,8 @@
/** The logger */
private static final Log log = LogFactory.getLog( ThreadPoolManager.class );
- /**
- * DEFAULT SETTINGS, these are not final since they can be set via the properties file or object
- */
- private static boolean useBoundary_DEFAULT = true;
-
- /** Default queue size limit */
- private static int boundarySize_DEFAULT = 2000;
-
- /** Default max size */
- private static int maximumPoolSize_DEFAULT = 150;
-
- /** Default min */
- private static int minimumPoolSize_DEFAULT = 4;
-
- /** Default keep alive */
- private static int keepAliveTime_DEFAULT = 1000 * 60 * 5;
-
- /** Default when blocked */
- private static WhenBlockedPolicy whenBlockedPolicy_DEFAULT = WhenBlockedPolicy.RUN;
-
- /** Default startup size */
- private static int startUpSize_DEFAULT = 4;
-
/** The default config, created using property defaults if present, else those above. */
- private static PoolConfiguration defaultConfig;
+ private PoolConfiguration defaultConfig;
/** the root property name */
private static final String PROP_NAME_ROOT = "thread_pool";
@@ -103,7 +65,13 @@
/** default property file name */
private static final String DEFAULT_PROP_NAME_ROOT = "thread_pool.default";
- /**
+ /** the scheduler root property name */
+ private static final String PROP_NAME_SCHEDULER_ROOT = "scheduler_pool";
+
+ /** default scheduler property file name */
+ private static final String DEFAULT_PROP_NAME_SCHEDULER_ROOT = "scheduler_pool.default";
+
+ /**
* You can specify the properties to be used to configure the thread pool. Setting this post
* initialization will have no effect.
*/
@@ -113,24 +81,42 @@
private static ThreadPoolManager INSTANCE = null;
/** Map of names to pools. */
- private ConcurrentHashMap<String, ThreadPoolExecutor> pools;
+ private ConcurrentHashMap<String, ExecutorService> pools;
+
+ /** Map of names to scheduler pools. */
+ private ConcurrentHashMap<String, ScheduledExecutorService> schedulerPools;
/**
* No instances please. This is a singleton.
*/
private ThreadPoolManager()
{
- this.pools = new ConcurrentHashMap<String, ThreadPoolExecutor>();
+ this.pools = new ConcurrentHashMap<String, ExecutorService>();
+ this.schedulerPools = new ConcurrentHashMap<String, ScheduledExecutorService>();
configure();
}
/**
* Creates a pool based on the configuration info.
* <p>
- * @param config
- * @return A ThreadPoll wrapper
+ * @param config the pool configuration
+ * @param threadNamePrefix prefix for the thread names of the pool
+ * @return A ThreadPool wrapper
*/
- private ThreadPoolExecutor createPool( PoolConfiguration config )
+ public ExecutorService createPool( PoolConfiguration config, String threadNamePrefix)
+ {
+ return createPool(config, threadNamePrefix, Thread.NORM_PRIORITY);
+ }
+
+ /**
+ * Creates a pool based on the configuration info.
+ * <p>
+ * @param config the pool configuration
+ * @param threadNamePrefix prefix for the thread names of the pool
+ * @param threadPriority the priority of the created threads
+ * @return A ThreadPool wrapper
+ */
+ public ExecutorService createPool( PoolConfiguration config, String threadNamePrefix, int threadPriority )
{
BlockingQueue<Runnable> queue = null;
if ( config.isUseBoundary() )
@@ -157,7 +143,7 @@
config.getKeepAliveTime(),
TimeUnit.MILLISECONDS,
queue,
- new DaemonThreadFactory("JCS-ThreadPoolManager-"));
+ new DaemonThreadFactory(threadNamePrefix, threadPriority));
// when blocked policy
switch (config.getWhenBlockedPolicy())
@@ -187,6 +173,23 @@
}
/**
+ * Creates a scheduler pool based on the configuration info.
+ * <p>
+ * @param config the pool configuration
+ * @param threadNamePrefix prefix for the thread names of the pool
+ * @param threadPriority the priority of the created threads
+ * @return A ScheduledExecutorService
+ */
+ public ScheduledExecutorService createSchedulerPool( PoolConfiguration config, String threadNamePrefix, int threadPriority )
+ {
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(
+ config.getMaximumPoolSize(),
+ new DaemonThreadFactory(threadNamePrefix, threadPriority));
+
+ return scheduler;
+ }
+
+ /**
* Returns a configured instance of the ThreadPoolManger To specify a configuration file or
* Properties object to use call the appropriate setter prior to calling getInstance.
* <p>
@@ -208,34 +211,46 @@
{
if ( INSTANCE != null )
{
- for ( String poolName : INSTANCE.getPoolNames())
+ for ( ExecutorService pool : INSTANCE.pools.values() )
{
try
{
- INSTANCE.getPool(poolName).shutdownNow();
+ pool.shutdownNow();
}
catch (Throwable t)
{
- log.warn("Failed to close pool " + poolName, t);
+ log.warn("Failed to close pool " + pool, t);
}
}
-
+
+ for ( ScheduledExecutorService pool : INSTANCE.schedulerPools.values() )
+ {
+ try
+ {
+ pool.shutdownNow();
+ }
+ catch (Throwable t)
+ {
+ log.warn("Failed to close pool " + pool, t);
+ }
+ }
+
INSTANCE = null;
}
}
/**
- * Returns a pool by name. If a pool by this name does not exist in the configuration file or
+ * Returns an executor service by name. If a service by this name does not exist in the configuration file or
* properties, one will be created using the default values.
* <p>
- * Pools are lazily created.
+ * Services are lazily created.
* <p>
* @param name
- * @return The thread pool configured for the name.
+ * @return The executor service configured for the name.
*/
- public ThreadPoolExecutor getPool( String name )
+ public ExecutorService getExecutorService( String name )
{
- ThreadPoolExecutor pool = pools.get( name );
+ ExecutorService pool = pools.get( name );
if ( pool == null )
{
@@ -245,12 +260,17 @@
}
PoolConfiguration config = loadConfig( PROP_NAME_ROOT + "." + name );
- pool = createPool( config );
- ThreadPoolExecutor _pool = pools.putIfAbsent( name, pool );
- if (_pool != null)
+ ExecutorService _pool = createPool( config, "JCS-ThreadPoolManager-" + name + "-" );
+ pool = pools.putIfAbsent( name, _pool );
+ if (pool == null)
{
pool = _pool;
}
+ else
+ {
+ // already created in another thread
+ _pool.shutdownNow();
+ }
if ( log.isDebugEnabled() )
{
@@ -260,6 +280,61 @@
return pool;
}
+
+ /**
+ * Returns a pool by name. If a pool by this name does not exist in the configuration file or
+ * properties, one will be created using the default values.
+ * <p>
+ * Pools are lazily created.
+ * <p>
+ * @param name
+ * @return The thread pool configured for the name.
+ *
+ * @deprecated Use getExecutorService() instead
+ */
+ @Deprecated
+ public ThreadPoolExecutor getPool( String name )
+ {
+ return (ThreadPoolExecutor) getExecutorService(name);
+ }
+
+ /**
+ * Returns a scheduler pool by name. If a pool by this name does not exist in the configuration file or
+ * properties, one will be created using the default values.
+ * <p>
+ * Pools are lazily created.
+ * <p>
+ * @param name
+ * @return The scheduler pool configured for the name.
+ */
+ public ScheduledExecutorService getSchedulerPool( String name )
+ {
+ ScheduledExecutorService pool = schedulerPools.get( name );
+
+ if ( pool == null )
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "Creating scheduler pool for name [" + name + "]" );
+ }
+
+ PoolConfiguration defaultSchedulerConfig = loadConfig( DEFAULT_PROP_NAME_SCHEDULER_ROOT );
+ PoolConfiguration config = loadConfig( PROP_NAME_SCHEDULER_ROOT + "." + name, defaultSchedulerConfig );
+ ScheduledExecutorService _pool = createSchedulerPool( config, "JCS-ThreadPoolManager-" + name + "-", Thread.NORM_PRIORITY );
+ pool = schedulerPools.putIfAbsent( name, _pool );
+ if (pool == null)
+ {
+ pool = _pool;
+ }
+ else
+ {
+ // already created in another thread
+ _pool.shutdownNow();
+ }
+ }
+
+ return pool;
+ }
/**
* Returns the names of all configured pools.
@@ -285,7 +360,7 @@
/**
* Initialize the ThreadPoolManager and create all the pools defined in the configuration.
*/
- private static void configure()
+ private void configure()
{
if ( log.isDebugEnabled() )
{
@@ -300,88 +375,36 @@
// set intial default and then override if new
// settings are available
- defaultConfig = new PoolConfiguration( useBoundary_DEFAULT, boundarySize_DEFAULT, maximumPoolSize_DEFAULT,
- minimumPoolSize_DEFAULT, keepAliveTime_DEFAULT,
- whenBlockedPolicy_DEFAULT, startUpSize_DEFAULT );
-
+ defaultConfig = new PoolConfiguration();
defaultConfig = loadConfig( DEFAULT_PROP_NAME_ROOT );
}
/**
- * Configures the default PoolConfiguration settings.
+ * Configures the PoolConfiguration settings.
* <p>
- * @param root
+ * @param root the configuration key prefix
* @return PoolConfiguration
*/
- private static PoolConfiguration loadConfig( String root )
+ private PoolConfiguration loadConfig( String root )
{
- PoolConfiguration config = defaultConfig.clone();
+ return loadConfig(root, defaultConfig);
+ }
+
+ /**
+ * Configures the PoolConfiguration settings.
+ * <p>
+ * @param root the configuration key prefix
+ * @param defaultPoolConfiguration the default configuration
+ * @return PoolConfiguration
+ */
+ private PoolConfiguration loadConfig( String root, PoolConfiguration defaultPoolConfiguration )
+ {
+ PoolConfiguration config = defaultPoolConfiguration.clone();
+ PropertySetter.setProperties( config, props, root + "." );
- try
+ if ( log.isDebugEnabled() )
{
- config.setUseBoundary( Boolean.parseBoolean( props.getProperty( root + ".useBoundary", "false" ) ) );
- }
- catch ( NumberFormatException nfe )
- {
- log.error( "useBoundary not a boolean.", nfe );
- }
-
- // load default if they exist
- try
- {
- config.setBoundarySize( Integer.parseInt( props.getProperty( root + ".boundarySize", "2000" ) ) );
- }
- catch ( NumberFormatException nfe )
- {
- log.error( "boundarySize not a number.", nfe );
- }
-
- // maximum pool size
- try
- {
- config.setMaximumPoolSize( Integer.parseInt( props.getProperty( root + ".maximumPoolSize", "150" ) ) );
- }
- catch ( NumberFormatException nfe )
- {
- log.error( "maximumPoolSize not a number.", nfe );
- }
-
- // minimum pool size
- try
- {
- config.setMinimumPoolSize( Integer.parseInt( props.getProperty( root + ".minimumPoolSize", "4" ) ) );
- }
- catch ( NumberFormatException nfe )
- {
- log.error( "minimumPoolSize not a number.", nfe );
- }
-
- // keep alive
- try
- {
- config.setKeepAliveTime( Integer.parseInt( props.getProperty( root + ".keepAliveTime", "300000" ) ) );
- }
- catch ( NumberFormatException nfe )
- {
- log.error( "keepAliveTime not a number.", nfe );
- }
-
- // when blocked
- config.setWhenBlockedPolicy( props.getProperty( root + ".whenBlockedPolicy", "RUN" ) );
-
- // startupsize
- try
- {
- config.setStartUpSize( Integer.parseInt( props.getProperty( root + ".startUpSize", "4" ) ) );
- }
- catch ( NumberFormatException nfe )
- {
- log.error( "startUpSize not a number.", nfe );
- }
-
- if ( log.isInfoEnabled() )
- {
- log.info( root + " PoolConfiguration = " + config );
+ log.debug( root + " PoolConfiguration = " + config );
}
return config;
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java
index 77df909..8317505 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/indexed/IndexedDiskCacheOptimizationUnitTest.java
@@ -65,8 +65,8 @@
Thread.sleep( 1000 );
long sizeBeforeRemove = disk.getDataFileSize();
- System.out.println( "file sizeBeforeRemove " + sizeBeforeRemove );
- System.out.println( "totalSize inserted " + DiskTestObjectUtil.totalSize( elements, numberToInsert ) );
+ // System.out.println( "file sizeBeforeRemove " + sizeBeforeRemove );
+ // System.out.println( "totalSize inserted " + DiskTestObjectUtil.totalSize( elements, numberToInsert ) );
// DO WORK
for ( int i = 0; i < removeCount; i++ )
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java
index fe671ae..231841a 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/remote/RemoteCacheNoWaitUnitTest.java
@@ -1,5 +1,16 @@
package org.apache.commons.jcs.auxiliary.remote;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.jcs.engine.CacheElement;
+import org.apache.commons.jcs.engine.CacheStatus;
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
+import org.apache.commons.jcs.utils.timing.SleepUtil;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -20,16 +31,6 @@
*/
import junit.framework.TestCase;
-import org.apache.commons.jcs.engine.CacheElement;
-import org.apache.commons.jcs.engine.CacheStatus;
-import org.apache.commons.jcs.engine.behavior.ICacheElement;
-import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
-import org.apache.commons.jcs.utils.timing.SleepUtil;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
/**
* Unit tests for the remote cache no wait. The no wait manages a queue on top of the client.
@@ -198,7 +199,7 @@
// DO WORK
noWait.update( element );
SleepUtil.sleepAtLeast( 10 );
- ICacheEventQueue<String, String> originalQueue = noWait.getCacheEventQueue();
+ // ICacheEventQueue<String, String> originalQueue = noWait.getCacheEventQueue();
noWait.fixCache( service );
@@ -208,7 +209,7 @@
// VERIFY
assertEquals( "Wrong status", service, client.fixed );
- assertFalse( "Original queue should not alive", originalQueue.isAlive() );
+ // assertFalse( "Original queue should not alive", originalQueue.isAlive() );
assertTrue( "New queue should be alive." + newQueue, newQueue.isAlive() );
}
}
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java
index 3925b63..60b72f3 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/CacheEventQueueFactoryUnitTest.java
@@ -1,5 +1,10 @@
package org.apache.commons.jcs.engine;
+import org.apache.commons.jcs.auxiliary.remote.MockRemoteCacheListener;
+import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
+import org.apache.commons.jcs.engine.behavior.ICacheEventQueue.QueueType;
+import org.apache.commons.jcs.engine.behavior.ICacheListener;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -20,10 +25,6 @@
*/
import junit.framework.TestCase;
-import org.apache.commons.jcs.auxiliary.remote.MockRemoteCacheListener;
-import org.apache.commons.jcs.engine.behavior.ICacheEventQueue;
-import org.apache.commons.jcs.engine.behavior.ICacheEventQueue.QueueType;
-import org.apache.commons.jcs.engine.behavior.ICacheListener;
/** Unit tests for the CacheEventQueueFactory */
public class CacheEventQueueFactoryUnitTest
@@ -44,7 +45,7 @@
// VERIFY
assertNotNull( "Should have a result", result );
- assertTrue( "Wrong type", result instanceof CacheEventQueue );
+ assertTrue( "Wrong type", result.getQueueType() == QueueType.SINGLE );
}
/** Test create */
@@ -62,6 +63,6 @@
// VERIFY
assertNotNull( "Should have a result", result );
- assertTrue( "Wrong type", result instanceof PooledCacheEventQueue );
+ assertTrue( "Wrong type", result.getQueueType() == QueueType.POOLED );
}
}
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java
index 8aa4bb8..799ebf4 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/engine/EventQueueConcurrentLoadTest.java
@@ -21,13 +21,13 @@
import java.io.IOException;
+import org.apache.commons.jcs.engine.behavior.ICacheElement;
+import org.apache.commons.jcs.engine.behavior.ICacheListener;
+
import junit.extensions.ActiveTestSuite;
import junit.framework.Test;
import junit.framework.TestCase;
-import org.apache.commons.jcs.engine.behavior.ICacheElement;
-import org.apache.commons.jcs.engine.behavior.ICacheListener;
-
/**
* This test case is designed to makes sure there are no deadlocks in the event queue. The time to
* live should be set to a very short interval to make a deadlock more likely.
@@ -109,16 +109,6 @@
}
} );
- suite.addTest( new EventQueueConcurrentLoadTest( "testStopProcessing1" )
- {
- @Override
- public void runTest()
- throws Exception
- {
- this.runStopProcessingTest();
- }
- } );
-
suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutTest4" )
{
@Override
@@ -139,16 +129,6 @@
}
} );
- suite.addTest( new EventQueueConcurrentLoadTest( "testStopProcessing2" )
- {
- @Override
- public void runTest()
- throws Exception
- {
- this.runStopProcessingTest();
- }
- } );
-
suite.addTest( new EventQueueConcurrentLoadTest( "testRunPutDelayTest" )
{
@Override
@@ -222,16 +202,6 @@
}
/**
- * Add remove events to the event queue.
- * @throws Exception
- */
- public void runStopProcessingTest()
- throws Exception
- {
- queue.stopProcessing();
- }
-
- /**
* Test putting and a delay. Waits until queue is empty to start.
* @param end
* @param expectedPutCount
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java
index 09b6005..6ce5625 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapConcurrentUnitTest.java
@@ -1,5 +1,7 @@
package org.apache.commons.jcs.utils.struct;
+import java.util.Iterator;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -23,8 +25,6 @@
import junit.framework.TestCase;
import junit.framework.TestSuite;
-import java.util.Iterator;
-
/**
* Tests the LRUMap
*
@@ -150,7 +150,6 @@
{
int total = 10;
LRUMap<String, String> map = new LRUMap<String, String>( total );
- map.setChunkSize( 1 );
// put the max in
for ( int i = 0; i < total; i++ )
@@ -189,7 +188,6 @@
{
int total = 10000;
LRUMap<String, String> map = new LRUMap<String, String>( total );
- map.setChunkSize( 1 );
// put the max in
for ( int i = 0; i < total * 2; i++ )
@@ -201,7 +199,6 @@
for ( int i = total - 1; i >= 0; i-- )
{
assertNull( map.get( i + ":key" ) );
-
}
// get the total to total *2 items out, these should be found.
@@ -212,7 +209,6 @@
}
// System.out.println( map.getStatistics() );
-
}
/**
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java
index bbf851f..e11d7ab 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/struct/LRUMapPerformanceTest.java
@@ -1,5 +1,9 @@
package org.apache.commons.jcs.utils.struct;
+import java.util.Map;
+
+import org.apache.commons.jcs.JCSvsHashtablePerformanceTest;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -22,9 +26,6 @@
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
-import org.apache.commons.jcs.JCSvsHashtablePerformanceTest;
-
-import java.util.Map;
/**
* This ensures that the jcs version of the LRU map is as fast as the commons
@@ -106,7 +107,7 @@
try
{
- Map<String, String> cache = new LRUMap<String, String>( tries );
+ LRUMap<String, String> cache = new LRUMap<String, String>( tries );
for ( int j = 0; j < loops; j++ )
{
@@ -134,9 +135,12 @@
System.out.println( name + " get time for " + tries + " = " + time + "; millis per = " + tPer );
///////////////////////////////////////////////////////////////
- cache2Name = "LRUMapJCS (commons)";
+ cache2Name = "LRUMap (commons)";
//or LRUMapJCS
Map<String, String> cache2 = new org.apache.commons.collections4.map.LRUMap<String, String>( tries );
+// Map<String, String> cache2 = new ConcurrentLinkedHashMap.Builder<String, String>()
+// .maximumWeightedCapacity( tries )
+// .build();
//cache2Name = "Hashtable";
//Hashtable cache2 = new Hashtable();
start = System.currentTimeMillis();
diff --git a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java
index e2210a1..1c89cc5 100644
--- a/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java
+++ b/commons-jcs-core/src/test/java/org/apache/commons/jcs/utils/threadpool/ThreadPoolManagerUnitTest.java
@@ -21,12 +21,14 @@
import java.util.ArrayList;
import java.util.Properties;
+import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
-
-import junit.framework.TestCase;
+import java.util.concurrent.TimeUnit;
import org.apache.commons.jcs.utils.props.PropertyLoader;
+import junit.framework.TestCase;
+
/**
* Verify that the manager can create pools as intended by the default and
* specified file names.
@@ -63,6 +65,39 @@
}
/**
+ * Make sure it can load a certain configuration
+ */
+ public void testSpecialConfig()
+ {
+ Properties props = PropertyLoader.loadProperties( "thread_pool.properties" );
+ ThreadPoolManager.setProps( props );
+ ThreadPoolManager mgr = ThreadPoolManager.getInstance();
+ assertNotNull( mgr );
+
+ ThreadPoolExecutor pool = mgr.getPool( "aborttest" );
+ assertNotNull( pool );
+
+ int poolSize = pool.getCorePoolSize();
+ int expectedPoolSize = Integer.parseInt( props.getProperty( "thread_pool.aborttest.startUpSize" ) );
+ assertEquals( expectedPoolSize, poolSize);
+
+ int minPoolSize = pool.getPoolSize();
+ int expectedMinPoolSize = Integer.parseInt( props.getProperty( "thread_pool.aborttest.minimumPoolSize" ) );
+ assertEquals( expectedMinPoolSize, minPoolSize );
+
+ int maxPoolSize = pool.getMaximumPoolSize();
+ int expectedMaxPoolSize = Integer.parseInt( props.getProperty( "thread_pool.aborttest.maximumPoolSize" ) );
+ assertEquals( expectedMaxPoolSize, maxPoolSize );
+
+ long keepAliveTime = pool.getKeepAliveTime(TimeUnit.MILLISECONDS);
+ long expectedKeepAliveTime = Long.parseLong( props.getProperty( "thread_pool.aborttest.keepAliveTime" ) );
+ assertEquals( expectedKeepAliveTime, keepAliveTime );
+
+ RejectedExecutionHandler whenBlockedPolicy = pool.getRejectedExecutionHandler();
+ assertTrue( whenBlockedPolicy instanceof ThreadPoolExecutor.AbortPolicy );
+ }
+
+ /**
* Try to get an undefined pool from an existing default file.
*/
public void testDefaultConfigUndefinedPool()
@@ -91,10 +126,10 @@
assertNotNull( mgr );
String poolName1 = "testGetPoolNames1";
- mgr.getPool( poolName1 );
+ mgr.getExecutorService( poolName1 );
String poolName2 = "testGetPoolNames2";
- mgr.getPool( poolName2 );
+ mgr.getExecutorService( poolName2 );
ArrayList<String> names = mgr.getPoolNames();
assertTrue( "Should have name in list.", names.contains( poolName1 ) );
diff --git a/commons-jcs-core/src/test/test-conf/thread_pool.properties b/commons-jcs-core/src/test/test-conf/thread_pool.properties
index cbf5284..b6a3326 100644
--- a/commons-jcs-core/src/test/test-conf/thread_pool.properties
+++ b/commons-jcs-core/src/test/test-conf/thread_pool.properties
@@ -44,13 +44,13 @@
thread_pool.maxtest.whenBlockedPolicy=RUN
thread_pool.maxtest.startUpSize=5
-# wait test thread pool config
-thread_pool.waittest.boundarySize=1
-thread_pool.waittest.maximumPoolSize=11
-thread_pool.waittest.minimumPoolSize=1
-thread_pool.waittest.keepAliveTime=1
-thread_pool.waittest.whenBlockedPolicy=WAIT
-thread_pool.waittest.startUpSize=1
+# abort test thread pool config
+thread_pool.aborttest.boundarySize=1
+thread_pool.aborttest.maximumPoolSize=11
+thread_pool.aborttest.minimumPoolSize=1
+thread_pool.aborttest.keepAliveTime=1
+thread_pool.aborttest.whenBlockedPolicy=ABORT
+thread_pool.aborttest.startUpSize=1
# with boundary test thread pool config
thread_pool.withbound.useBoundary=true
@@ -58,7 +58,7 @@
thread_pool.withbound.maximumPoolSize=11
thread_pool.withbound.minimumPoolSize=1
thread_pool.withbound.keepAliveTime=1
-thread_pool.withbound.whenBlockedPolicy=WAIT
+thread_pool.withbound.whenBlockedPolicy=ABORT
thread_pool.withbound.startUpSize=1
@@ -68,5 +68,5 @@
thread_pool.nobound.maximumPoolSize=11
thread_pool.nobound.minimumPoolSize=1
thread_pool.nobound.keepAliveTime=1
-thread_pool.nobound.whenBlockedPolicy=WAIT
+thread_pool.nobound.whenBlockedPolicy=ABORT
thread_pool.nobound.startUpSize=1
diff --git a/commons-jcs-dist/pom.xml b/commons-jcs-dist/pom.xml
index 0991542..559b600 100644
--- a/commons-jcs-dist/pom.xml
+++ b/commons-jcs-dist/pom.xml
@@ -32,9 +32,9 @@
<description>Creates the Apache Commons JCS multimodule distribution.</description>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-dist</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-dist</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-dist</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-dist</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-dist</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-dist</url>
</scm>
<!-- NOTE: These dependency declarations are only required to sort this project to the
diff --git a/commons-jcs-jcache-extras/pom.xml b/commons-jcs-jcache-extras/pom.xml
index 741923f..091cbea 100644
--- a/commons-jcs-jcache-extras/pom.xml
+++ b/commons-jcs-jcache-extras/pom.xml
@@ -30,9 +30,9 @@
<name>Apache Commons JCS :: JCache Extras</name>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-extras</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-extras</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-extras</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-extras</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-extras</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-jcache-extras</url>
</scm>
<dependencies>
diff --git a/commons-jcs-jcache-openjpa/pom.xml b/commons-jcs-jcache-openjpa/pom.xml
index b7efa57..a83133b 100644
--- a/commons-jcs-jcache-openjpa/pom.xml
+++ b/commons-jcs-jcache-openjpa/pom.xml
@@ -30,9 +30,9 @@
<name>Apache Commons JCS :: JCache OpenJPA</name>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-openjpa</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-openjpa</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache-openjpa</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-openjpa</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache-openjpa</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-jcache-openjpa</url>
</scm>
<dependencies>
diff --git a/commons-jcs-jcache/pom.xml b/commons-jcs-jcache/pom.xml
index b6fb71e..15d2c8d 100644
--- a/commons-jcs-jcache/pom.xml
+++ b/commons-jcs-jcache/pom.xml
@@ -32,9 +32,9 @@
<name>Apache Commons JCS :: JCache</name>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-jcache</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-jcache</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-jcache</url>
</scm>
<dependencies>
diff --git a/commons-jcs-tck-tests/pom.xml b/commons-jcs-tck-tests/pom.xml
index 4e61e0b..7ecb150 100644
--- a/commons-jcs-tck-tests/pom.xml
+++ b/commons-jcs-tck-tests/pom.xml
@@ -39,9 +39,9 @@
<name>Apache Commons JCS :: JCache TCK</name>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-tck-tests</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-tck-tests</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC/commons-jcs-tck-tests</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-tck-tests</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk/commons-jcs-tck-tests</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-tck-tests</url>
</scm>
<properties>
diff --git a/pom.xml b/pom.xml
index 094c6b2..c51c573 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,9 +51,9 @@
</issueManagement>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/branches/commons-jcs-2.1-RC</developerConnection>
- <url>http://svn.apache.org/viewvc/commons/proper/jcs/branches/commons-jcs-2.1-RC</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/jcs/trunk</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/jcs/trunk</developerConnection>
+ <url>http://svn.apache.org/viewvc/commons/proper/jcs/trunk</url>
</scm>
<mailingLists>
@@ -519,8 +519,8 @@
<maven.compiler.target>1.6</maven.compiler.target>
<commons.componentid>jcs</commons.componentid>
- <commons.release.version>2.1</commons.release.version>
- <commons.release.name>commons-jcs-dist-2.1</commons.release.name>
+ <commons.release.version>2.0</commons.release.version>
+ <commons.release.name>commons-jcs-dist-2.0</commons.release.name>
<commons.release.desc>(Java 6.0+)</commons.release.desc>
<!-- The RC version used in the staging repository URL. -->
<commons.rc.version>RC1</commons.rc.version>