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.


Reply via email to