Author: tv
Date: Fri Nov 9 20:48:18 2012
New Revision: 1407624
URL: http://svn.apache.org/viewvc?rev=1407624&view=rev
Log:
Fix JCS-73: Concurrent cache access causes values loss - added missing
synchronization
Modified:
commons/proper/jcs/trunk/src/changes/changes.xml
commons/proper/jcs/trunk/src/java/org/apache/jcs/access/GroupCacheAccess.java
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/control/CompositeCache.java
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
Modified: commons/proper/jcs/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/changes/changes.xml?rev=1407624&r1=1407623&r2=1407624&view=diff
==============================================================================
--- commons/proper/jcs/trunk/src/changes/changes.xml (original)
+++ commons/proper/jcs/trunk/src/changes/changes.xml Fri Nov 9 20:48:18 2012
@@ -20,6 +20,9 @@
</properties>
<body>
<release version="2.0" date="unreleased" description="JDK 1.5
based major release">
+ <action dev="tv" type="fix" issue="JCS-73" due-to="Alexander
Kleymenov">
+ Concurrent cache access causes values loss.
+ </action>
<action dev="tv" type="fix" issue="JCS-77" due-to="Matt Morrisson">
NullPointerException thrown by IndexedDiskCache if IndexedDisk
calls fail to
initialize.
Modified:
commons/proper/jcs/trunk/src/java/org/apache/jcs/access/GroupCacheAccess.java
URL:
http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/java/org/apache/jcs/access/GroupCacheAccess.java?rev=1407624&r1=1407623&r2=1407624&view=diff
==============================================================================
---
commons/proper/jcs/trunk/src/java/org/apache/jcs/access/GroupCacheAccess.java
(original)
+++
commons/proper/jcs/trunk/src/java/org/apache/jcs/access/GroupCacheAccess.java
Fri Nov 9 20:48:18 2012
@@ -162,9 +162,6 @@ public class GroupCacheAccess<K extends
throw new InvalidArgumentException( "Value must not be null" );
}
- // unbind object first if any.
- remove( name, groupName );
-
// Create the element and update. This may throw an IOException which
// should be wrapped by cache access.
try
Modified:
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/control/CompositeCache.java
URL:
http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/control/CompositeCache.java?rev=1407624&r1=1407623&r2=1407624&view=diff
==============================================================================
---
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/control/CompositeCache.java
(original)
+++
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/control/CompositeCache.java
Fri Nov 9 20:48:18 2012
@@ -211,7 +211,7 @@ public class CompositeCache<K extends Se
if ( log.isDebugEnabled() )
{
- log.debug( "Updating memory cache" );
+ log.debug( "Updating memory cache " + cacheElement.getKey() );
}
synchronized ( this )
@@ -466,121 +466,124 @@ public class CompositeCache<K extends Se
log.debug( "get: key = " + key + ", localOnly = " + localOnly );
}
- try
+ synchronized (this)
{
- // First look in memory cache
- element = memCache.get( key );
-
- if ( element != null )
+ try
{
- // Found in memory cache
- if ( isExpired( element ) )
+ // First look in memory cache
+ element = memCache.get( key );
+
+ if ( element != null )
{
- if ( log.isDebugEnabled() )
+ // Found in memory cache
+ if ( isExpired( element ) )
{
- log.debug( cacheName + " - Memory cache hit, but
element expired" );
- }
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( cacheName + " - Memory cache hit, but
element expired" );
+ }
- missCountExpired++;
+ missCountExpired++;
- remove( key );
+ remove( key );
- element = null;
- }
- else
- {
- if ( log.isDebugEnabled() )
+ element = null;
+ }
+ else
{
- log.debug( cacheName + " - Memory cache hit" );
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( cacheName + " - Memory cache hit" );
+ }
+
+ // Update counters
+ hitCountRam++;
}
- // Update counters
- hitCountRam++;
+ found = true;
}
-
- found = true;
- }
- else
- {
- // Item not found in memory. If local invocation look in aux
- // caches, even if not local look in disk auxiliaries
-
- for ( int i = 0; i < auxCaches.length; i++ )
+ else
{
- AuxiliaryCache<K, V> aux = auxCaches[i];
+ // Item not found in memory. If local invocation look in
aux
+ // caches, even if not local look in disk auxiliaries
- if ( aux != null )
+ for ( int i = 0; i < auxCaches.length; i++ )
{
- CacheType cacheType = aux.getCacheType();
+ AuxiliaryCache<K, V> aux = auxCaches[i];
- if ( !localOnly || cacheType == CacheType.DISK_CACHE )
+ if ( aux != null )
{
- if ( log.isDebugEnabled() )
- {
- log.debug( "Attempting to get from aux [" +
aux.getCacheName() + "] which is of type: "
- + cacheType );
- }
+ CacheType cacheType = aux.getCacheType();
- try
- {
- element = aux.get( key );
- }
- catch ( IOException e )
- {
- log.error( "Error getting from aux", e );
- }
- }
-
- if ( log.isDebugEnabled() )
- {
- log.debug( "Got CacheElement: " + element );
- }
-
- // Item found in one of the auxiliary caches.
- if ( element != null )
- {
- if ( isExpired( element ) )
+ if ( !localOnly || cacheType ==
CacheType.DISK_CACHE )
{
if ( log.isDebugEnabled() )
{
- log.debug( cacheName + " - Aux cache[" + i
+ "] hit, but element expired." );
+ log.debug( "Attempting to get from aux ["
+ aux.getCacheName() + "] which is of type: "
+ + cacheType );
}
- missCountExpired++;
-
- // This will tell the remotes to remove the
item
- // based on the element's expiration policy.
The elements attributes
- // associated with the item when it created
govern its behavior
- // everywhere.
- remove( key );
+ try
+ {
+ element = aux.get( key );
+ }
+ catch ( IOException e )
+ {
+ log.error( "Error getting from aux", e );
+ }
+ }
- element = null;
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( "Got CacheElement: " + element );
}
- else
+
+ // Item found in one of the auxiliary caches.
+ if ( element != null )
{
- if ( log.isDebugEnabled() )
+ if ( isExpired( element ) )
{
- log.debug( cacheName + " - Aux cache[" + i
+ "] hit" );
- }
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( cacheName + " - Aux cache["
+ i + "] hit, but element expired." );
+ }
+
+ missCountExpired++;
+
+ // This will tell the remotes to remove
the item
+ // based on the element's expiration
policy. The elements attributes
+ // associated with the item when it
created govern its behavior
+ // everywhere.
+ remove( key );
- // Update counters
- hitCountAux++;
- auxHitCountByIndex[i]++;
+ element = null;
+ }
+ else
+ {
+ if ( log.isDebugEnabled() )
+ {
+ log.debug( cacheName + " - Aux cache["
+ i + "] hit" );
+ }
+
+ // Update counters
+ hitCountAux++;
+ auxHitCountByIndex[i]++;
- copyAuxiliaryRetrievedItemToMemory( element );
- }
+ copyAuxiliaryRetrievedItemToMemory(
element );
+ }
- found = true;
+ found = true;
- break;
+ break;
+ }
}
}
}
}
- }
- catch ( Exception e )
- {
- log.error( "Problem encountered getting element.", e );
+ catch ( Exception e )
+ {
+ log.error( "Problem encountered getting element.", e );
+ }
}
if ( !found )
Modified:
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
URL:
http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java?rev=1407624&r1=1407623&r2=1407624&view=diff
==============================================================================
---
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
(original)
+++
commons/proper/jcs/trunk/src/java/org/apache/jcs/engine/memory/lru/LRUMemoryCache.java
Fri Nov 9 20:48:18 2012
@@ -29,7 +29,7 @@ import org.apache.jcs.engine.memory.util
/**
* A fast reference management system. The least recently used items move to
the end of the list and
* get spooled to disk if the cache hub is configured to use a disk cache.
Most of the cache
- * bottelnecks are in IO. There are no io bottlenecks here, it's all about
processing power.
+ * bottlenecks are in IO. There are no io bottlenecks here, it's all about
processing power.
* <p>
* Even though there are only a few adjustments necessary to maintain the
double linked list, we
* might want to find a more efficient memory manager for large cache regions.