jtaylor 02/04/12 21:01:33
Modified: . build.xml project.xml
src/java/org/apache/jcs/engine/control Cache.java
src/java/org/apache/jcs/engine/memory/lru
LRUMemoryCache.java
src/test/org/apache/jcs TestDiskCache.java
Added: src/test/org/apache/jcs TestDiskCacheConcurrent.java
Log:
Added another unit test that pounds the SAME region with 3 different threads,
rather than different regions.
This quickly showed a couple of synchronization problems in memory cache. I
changed some synchronization around and tried to to make the list remove cope
with the case where another thread has already removed the element. Before it
was just treating it like the only element, and quietly dropping the list (but
not the map -- yikes!)
Also, moved synchronization of spool to disk from Cache to LRUMemoryCache to
avoid a deadlock which occurred occasionally. Makes much more sense since that
method doesn't affect any of the volatile state in Cache.
Revision Changes Path
1.4 +1 -1 jakarta-turbine-jcs/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-turbine-jcs/build.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- build.xml 8 Apr 2002 18:38:57 -0000 1.3
+++ build.xml 13 Apr 2002 04:01:33 -0000 1.4
@@ -46,7 +46,7 @@
</target>
<target
- name="maven:jar" depends="jcs:test-prepare">
+ name="maven:jar">
<ant antfile="${maven.home}/build-maven.xml" target="jar"/>
</target>
1.4 +2 -1 jakarta-turbine-jcs/project.xml
Index: project.xml
===================================================================
RCS file: /home/cvs/jakarta-turbine-jcs/project.xml,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- project.xml 12 Apr 2002 01:39:57 -0000 1.3
+++ project.xml 13 Apr 2002 04:01:33 -0000 1.4
@@ -137,8 +137,9 @@
<aspectSourceDirectories></aspectSourceDirectories>
<unitTestPatterns>
<unitTestPattern>include = **/TestJCS.java</unitTestPattern>
- <unitTestPattern>include = **/TestDiskCache.java</unitTestPattern>
<unitTestPattern>include = **/TestSimpleLoad.java</unitTestPattern>
+ <unitTestPattern>include = **/TestDiskCache.java</unitTestPattern>
+ <unitTestPattern>include = **/TestDiskCacheConcurrent.java</unitTestPattern>
</unitTestPatterns>
<jarResources></jarResources>
<jars></jars>
1.7 +3 -3
jakarta-turbine-jcs/src/java/org/apache/jcs/engine/control/Cache.java
Index: Cache.java
===================================================================
RCS file:
/home/cvs/jakarta-turbine-jcs/src/java/org/apache/jcs/engine/control/Cache.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Cache.java 12 Apr 2002 13:03:12 -0000 1.6
+++ Cache.java 13 Apr 2002 04:01:33 -0000 1.7
@@ -83,7 +83,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Aaron Smuts</a>
* @author <a href="mailto:[EMAIL PROTECTED]">James Taylor</a>
- * @version $Id: Cache.java,v 1.6 2002/04/12 13:03:12 jtaylor Exp $
+ * @version $Id: Cache.java,v 1.7 2002/04/13 04:01:33 jtaylor Exp $
*/
public class Cache
implements ICache, ICompositeCache, Serializable
@@ -426,7 +426,7 @@
*
* @param ce The CacheElement
*/
- public synchronized void spoolToDisk( ICacheElement ce )
+ public void spoolToDisk( ICacheElement ce )
{
// SPOOL TO DISK.
@@ -452,7 +452,7 @@
}
if ( log.isDebugEnabled() )
{
- log.debug( "moveToMemory -- request to put " + ce.getKey() + "
on disk cache[" + i + "]" );
+ log.debug( "spoolToDisk done for: " + ce.getKey() + " on disk
cache[" + i + "]" );
}
}
}
1.5 +24 -11
jakarta-turbine-jcs/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
Index: LRUMemoryCache.java
===================================================================
RCS file:
/home/cvs/jakarta-turbine-jcs/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- LRUMemoryCache.java 9 Apr 2002 00:32:45 -0000 1.4
+++ LRUMemoryCache.java 13 Apr 2002 04:01:33 -0000 1.5
@@ -32,7 +32,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Aaron Smuts</a>
* @author <a href="mailto:[EMAIL PROTECTED]">James Taylor</a>
- * @version $Id: LRUMemoryCache.java,v 1.4 2002/04/09 00:32:45 jtaylor Exp $
+ * @version $Id: LRUMemoryCache.java,v 1.5 2002/04/13 04:01:33 jtaylor Exp $
*/
public class LRUMemoryCache implements MemoryCache, Serializable
{
@@ -158,17 +158,23 @@
// need to pre-queue the queuing. This would be a bit wasteful
// and wouldn't save much time in this synchronous call.
+ MemoryElementDescriptor node;
+
for ( int i = 0; i < chunkSizeCorrected; i++ )
{
- cache.spoolToDisk( last.ce );
- map.remove( last.ce.getKey() );
- removeNode( last );
+ synchronized ( this )
+ {
+ cache.spoolToDisk( last.ce );
+
+ map.remove( last.ce.getKey() );
+
+ removeNode( last );
+ }
}
if ( log.isDebugEnabled() )
{
- log.debug( "After spool, put " + last.ce.getKey()
- + " on disk cache, map size: " + size );
+ log.debug( "After spool map size: " + size );
}
}
}
@@ -376,7 +382,7 @@
/**
* Removes the specified node from the link list.
*/
- private void removeNode( MemoryElementDescriptor me )
+ private synchronized void removeNode( MemoryElementDescriptor me )
{
if ( log.isDebugEnabled() )
{
@@ -387,8 +393,15 @@
{
if ( me.prev == null )
{
- // the only node.
- first = last = null;
+ // Make sure it really is the only node before setting head and
+ // tail to null. It is possible that we will be passed a node
+ // which has already been removed from the list, in which case
+ // we should ignore it
+
+ if ( me == first && me == last )
+ {
+ first = last = null;
+ }
}
else
{
@@ -438,7 +451,7 @@
/**
* Adds a new node to the start of the link list.
*/
- private void addFirst( ICacheElement ce )
+ private synchronized void addFirst( ICacheElement ce )
{
MemoryElementDescriptor me = new MemoryElementDescriptor( ce );
@@ -460,7 +473,7 @@
/**
* Moves an existing node to the start of the link list.
*/
- public synchronized void makeFirst( ICacheElement ce )
+ public void makeFirst( ICacheElement ce )
{
makeFirst( new MemoryElementDescriptor( ce ) );
}
1.2 +29 -32 jakarta-turbine-jcs/src/test/org/apache/jcs/TestDiskCache.java
Index: TestDiskCache.java
===================================================================
RCS file: /home/cvs/jakarta-turbine-jcs/src/test/org/apache/jcs/TestDiskCache.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TestDiskCache.java 7 Apr 2002 16:55:32 -0000 1.1
+++ TestDiskCache.java 13 Apr 2002 04:01:33 -0000 1.2
@@ -55,24 +55,21 @@
* <http://www.apache.org/>.
*/
+import junit.extensions.ActiveTestSuite;
import junit.framework.Test;
import junit.framework.TestCase;
-import junit.framework.TestSuite;
-import junit.extensions.ActiveTestSuite;
-
-import org.apache.jcs.JCS;
-import org.apache.jcs.engine.behavior.ICompositeCacheAttributes;
/**
- * Test which excercises the disk caches (Indexed, JISP, and HSQL).
+ * Test which exercises the indexed disk cache. This one uses three different
+ * regions for thre threads.
*
* @author <a href="mailto:[EMAIL PROTECTED]">James Taylor</a>
- * @version $Id: TestDiskCache.java,v 1.1 2002/04/07 16:55:32 jvanzyl Exp $
+ * @version $Id: TestDiskCache.java,v 1.2 2002/04/13 04:01:33 jtaylor Exp $
*/
public class TestDiskCache extends TestCase
{
- /**
- * Number of items to cache, twice the configured maxObjects for the
+ /**
+ * Number of items to cache, twice the configured maxObjects for the
* memory cache regions.
*/
private static int items = 200;
@@ -102,30 +99,30 @@
public static Test suite()
{
ActiveTestSuite suite = new ActiveTestSuite();
-
+
suite.addTest( new TestDiskCache( "testIndexedDiskCache1" )
+ {
+ public void runTest() throws Exception
{
- public void runTest() throws Exception
- {
- runTestForRegion( "indexedRegion1" );
- }
- });
+ runTestForRegion( "indexedRegion1" );
+ }
+ } );
suite.addTest( new TestDiskCache( "testIndexedDiskCache2" )
+ {
+ public void runTest() throws Exception
{
- public void runTest() throws Exception
- {
- runTestForRegion( "indexedRegion2" );
- }
- });
+ runTestForRegion( "indexedRegion2" );
+ }
+ } );
suite.addTest( new TestDiskCache( "testIndexedDiskCache3" )
+ {
+ public void runTest() throws Exception
{
- public void runTest() throws Exception
- {
- runTestForRegion( "indexedRegion3" );
- }
- });
+ runTestForRegion( "indexedRegion3" );
+ }
+ } );
return suite;
}
@@ -161,8 +158,8 @@
* than the size of the memory cache, so items should spool to disk.
*
* @param region Name of the region to access
- *
- * @exception Exception If an error occurs
+ *
+ * @exception Exception If an error occurs
*/
public void runTestForRegion( String region )
throws Exception
@@ -170,19 +167,19 @@
JCS jcs = JCS.getInstance( region );
// Add items to cache
-
+
for ( int i = 0; i <= items; i++ )
{
jcs.put( i + ":key", region + " data " + i );
}
-
+
// Test that all items are in cache
for ( int i = 0; i <= items; i++ )
{
String value = ( String ) jcs.get( i + ":key" );
- this.assertEquals( region + " data " + i , value );
+ this.assertEquals( region + " data " + i, value );
}
// Remove all the items
@@ -191,9 +188,9 @@
{
jcs.destroy( i + ":key" );
}
-
+
// Verify removal
-
+
for ( int i = 0; i <= items; i++ )
{
assertNull( jcs.get( i + ":key" ) );
1.1
jakarta-turbine-jcs/src/test/org/apache/jcs/TestDiskCacheConcurrent.java
Index: TestDiskCacheConcurrent.java
===================================================================
package org.apache.jcs;
/*
* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Turbine" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Turbine", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import junit.extensions.ActiveTestSuite;
import junit.framework.Test;
import junit.framework.TestCase;
/**
* Test which exercises the indexed disk cache. Runs three threads against the
* same region.
*
* @author <a href="mailto:[EMAIL PROTECTED]">James Taylor</a>
* @version $Id: TestDiskCacheConcurrent.java,v 1.1 2002/04/13 04:01:33 jtaylor Exp $
*/
public class TestDiskCacheConcurrent extends TestCase
{
/**
* Constructor for the TestDiskCache object.
*/
public TestDiskCacheConcurrent( String testName )
{
super( testName );
}
/**
* Main method passes this test to the text test runner.
*/
public static void main( String args[] )
{
String[] testCaseName = {TestDiskCacheConcurrent.class.getName()};
junit.textui.TestRunner.main( testCaseName );
}
/**
* A unit test suite for JUnit
*
* @return The test suite
*/
public static Test suite()
{
ActiveTestSuite suite = new ActiveTestSuite();
suite.addTest( new TestDiskCacheConcurrent( "testIndexedDiskCache1" )
{
public void runTest() throws Exception
{
runTestForRegion( "indexedRegion1", 0, 200 );
}
} );
suite.addTest( new TestDiskCacheConcurrent( "testIndexedDiskCache2" )
{
public void runTest() throws Exception
{
runTestForRegion( "indexedRegion1", 1000, 1200 );
}
} );
suite.addTest( new TestDiskCacheConcurrent( "testIndexedDiskCache3" )
{
public void runTest() throws Exception
{
runTestForRegion( "indexedRegion1", 2000, 2200 );
}
});
return suite;
}
/**
* Test setup
*/
public void setUp()
{
JCS.setConfigFilename( "/TestDiskCache.ccf" );
}
// /**
// * Tests the region which uses the indexed disk cache
// */
// public void testIndexedDiskCache()
// throws Exception
// {
// runTestForRegion( "indexedRegion" );
// }
//
// /**
// * Tests the region which uses the indexed disk cache
// */
// public void testIndexedDiskCache2()
// throws Exception
// {
// runTestForRegion( "indexedRegion2" );
// }
/**
* Adds items to cache, gets them, and removes them. The item count is more
* than the size of the memory cache, so items should spool to disk.
*
* @param region Name of the region to access
*
* @exception Exception If an error occurs
*/
public void runTestForRegion( String region, int start, int end )
throws Exception
{
JCS jcs = JCS.getInstance( region );
// Add items to cache
for ( int i = start; i <= end; i++ )
{
jcs.put( i + ":key", region + " data " + i );
}
// Test that all items are in cache
for ( int i = start; i <= end; i++ )
{
String value = ( String ) jcs.get( i + ":key" );
this.assertEquals( region + " data " + i, value );
}
// Remove all the items
for ( int i = start; i <= end; i++ )
{
jcs.destroy( i + ":key" );
}
// Verify removal
for ( int i = start; i <= end; i++ )
{
assertNull( "Removed key should be null: " + i + ":key",
jcs.get( i + ":key" ) );
}
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>