This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git


The following commit(s) were added to refs/heads/master by this push:
     new fb3f101b Fix inconsistent locking
fb3f101b is described below

commit fb3f101b87709b713468e8d827b8612e6e65f29b
Author: Thomas Vandahl <[email protected]>
AuthorDate: Tue Sep 1 15:04:39 2026 +0200

    Fix inconsistent locking
---
 .../AbstractDoubleLinkedListMemoryCache.java       | 71 +++++++++++++---------
 .../jcs4/engine/memory/AbstractMemoryCache.java    | 13 ++--
 .../jcs4/engine/memory/fifo/FIFOMemoryCache.java   |  3 +-
 .../jcs4/engine/memory/lru/LHMLRUMemoryCache.java  |  2 +-
 .../jcs4/engine/memory/lru/LRUMemoryCache.java     |  3 +-
 .../jcs4/engine/memory/mru/MRUMemoryCache.java     |  3 +-
 .../memory/soft/SoftReferenceMemoryCache.java      |  5 +-
 7 files changed, 58 insertions(+), 42 deletions(-)

diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
index 900e124e..031ece0c 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
@@ -45,7 +45,8 @@ public abstract class AbstractDoubleLinkedListMemoryCache<K, 
V> extends Abstract
     private static final Log log = 
Log.getLog(AbstractDoubleLinkedListMemoryCache.class);
 
     /** Thread-safe double linked list for lru */
-    protected DoubleLinkedList<MemoryElementDescriptor<K, V>> list; // TODO 
privatise
+    private DoubleLinkedList<MemoryElementDescriptor<K, V>> list;
+
     /**
      * Adds a new node to the start of the link list.
      * <p>
@@ -102,17 +103,19 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
 
     /**
      * Adjust the list as needed for a get. This allows children to control 
the algorithm
+     * (guarded by the lock)
      * <p>
      *
-     * @param me
+     * @param list the node list
+     * @param me the current cache element
      */
-    protected abstract void adjustListForGet(MemoryElementDescriptor<K, V> me);
+    protected abstract void 
adjustListForGet(DoubleLinkedList<MemoryElementDescriptor<K, V>> list, 
MemoryElementDescriptor<K, V> me);
 
     /**
      * Children implement this to control the cache expiration algorithm
      * <p>
      *
-     * @param ce
+     * @param ce the current cache element
      * @return MemoryElementDescriptor the new node
      * @throws IOException
      */
@@ -188,14 +191,23 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
     @Override
     public ICacheElement<K, V> get(final K key) throws IOException
     {
-        final ICacheElement<K, V> ce = super.get(key);
+        lock.lock();
 
-        if (log.isTraceEnabled())
+        try
         {
-            verifyCache();
-        }
+            final ICacheElement<K, V> ce = super.get(key);
 
-        return ce;
+            if (log.isTraceEnabled())
+            {
+                verifyCache();
+            }
+
+            return ce;
+        }
+        finally
+        {
+            lock.unlock();
+        }
     }
 
     /**
@@ -238,7 +250,7 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
     @Override
     protected void lockedGetElement(final MemoryElementDescriptor<K, V> me)
     {
-        adjustListForGet(me);
+        adjustListForGet(list, me);
     }
 
     /**
@@ -271,24 +283,6 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
      */
     private void spoolIfNeeded() throws Error
     {
-        final int size = map.size();
-        // If the element limit is reached, we need to spool
-
-        if (size <= getCacheAttributes().MaxObjects())
-        {
-            return;
-        }
-
-        log.debug("In memory limit reached, spooling");
-
-        // Write the last 'chunkSize' items to disk.
-        final int chunkSizeCorrected = Math.min(size, chunkSize);
-
-        log.debug("About to spool to disk cache, map size: {0}, max objects: 
{1}, "
-                + "maximum items to spool: {2}", () -> size,
-                getCacheAttributes()::MaxObjects,
-                () -> chunkSizeCorrected);
-
         // 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.
@@ -296,6 +290,24 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
 
         try
         {
+            final int size = map.size();
+            // If the element limit is reached, we need to spool
+
+            if (size <= getCacheAttributes().MaxObjects())
+            {
+                return;
+            }
+
+            log.debug("In memory limit reached, spooling");
+
+            // Write the last 'chunkSize' items to disk.
+            final int chunkSizeCorrected = Math.min(size, chunkSize);
+
+            log.debug("About to spool to disk cache, map size: {0}, max 
objects: {1}, "
+                    + "maximum items to spool: {2}", () -> size,
+                    getCacheAttributes()::MaxObjects,
+                    () -> chunkSizeCorrected);
+
             freeElements(chunkSizeCorrected);
 
             // If this is out of the sync block it can detect a mismatch
@@ -365,11 +377,10 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
     @Override
     public final void update(final ICacheElement<K, V> ce) throws IOException
     {
-        putCnt.incrementAndGet();
-
         lock.lock();
         try
         {
+            super.update(ce);
             final MemoryElementDescriptor<K, V> newNode = 
adjustListForUpdate(ce);
 
             // this should be synchronized if we were not using a 
ConcurrentHashMap
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
index 56aafa53..346f164b 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
@@ -66,13 +66,13 @@ public abstract class AbstractMemoryCache<K, V>
     protected Map<K, MemoryElementDescriptor<K, V>> map; // TODO privatise
 
     /** Number of hits */
-    protected AtomicLong hitCnt;
+    private AtomicLong hitCnt;
 
     /** Number of misses */
-    protected AtomicLong missCnt;
+    private AtomicLong missCnt;
 
     /** Number of puts */
-    protected AtomicLong putCnt;
+    private AtomicLong putCnt;
 
     /**
      * Children must implement this method. A FIFO implementation may use a 
tree map. An LRU might
@@ -487,8 +487,11 @@ public abstract class AbstractMemoryCache<K, V>
      * @throws IOException Description of the Exception
      */
     @Override
-    public abstract void update( ICacheElement<K, V> ce )
-        throws IOException;
+    public void update( ICacheElement<K, V> ce )
+        throws IOException
+    {
+        putCnt.incrementAndGet();
+    }
 
     /**
      * Puts an item to the cache.
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCache.java
index 70cfe775..0d188461 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCache.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import org.apache.commons.jcs4.engine.behavior.ICacheElement;
 import 
org.apache.commons.jcs4.engine.memory.AbstractDoubleLinkedListMemoryCache;
 import org.apache.commons.jcs4.engine.memory.util.MemoryElementDescriptor;
+import org.apache.commons.jcs4.utils.struct.DoubleLinkedList;
 
 /**
  * The items are spooled in the order they are added. No adjustments to the 
list are made on get.
@@ -37,7 +38,7 @@ public class FIFOMemoryCache<K, V>
      * @param me
      */
     @Override
-    protected void adjustListForGet( final MemoryElementDescriptor<K, V> me )
+    protected void adjustListForGet(final 
DoubleLinkedList<MemoryElementDescriptor<K, V>> list, final 
MemoryElementDescriptor<K, V> me )
     {
         // DO NOTHING
     }
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
index 24bc3e3c..68f6aa8e 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
@@ -188,7 +188,7 @@ public class LHMLRUMemoryCache<K, V>
     public void update( final ICacheElement<K, V> ce )
         throws IOException
     {
-        putCnt.incrementAndGet();
+        super.update(ce);
         map.put( ce.key(), new MemoryElementDescriptor<>(ce) );
     }
 }
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LRUMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LRUMemoryCache.java
index 1acf1a76..2c00917f 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LRUMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LRUMemoryCache.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import org.apache.commons.jcs4.engine.behavior.ICacheElement;
 import 
org.apache.commons.jcs4.engine.memory.AbstractDoubleLinkedListMemoryCache;
 import org.apache.commons.jcs4.engine.memory.util.MemoryElementDescriptor;
+import org.apache.commons.jcs4.utils.struct.DoubleLinkedList;
 
 /**
  * A fast reference management system. The least recently used items move to 
the end of the list and
@@ -45,7 +46,7 @@ public class LRUMemoryCache<K, V>
      * @param me
      */
     @Override
-    protected void adjustListForGet( final MemoryElementDescriptor<K, V> me )
+    protected void adjustListForGet(final 
DoubleLinkedList<MemoryElementDescriptor<K, V>> list, final 
MemoryElementDescriptor<K, V> me )
     {
         list.makeFirst( me );
     }
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCache.java
index b2faabf8..e0a252bd 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCache.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import org.apache.commons.jcs4.engine.behavior.ICacheElement;
 import 
org.apache.commons.jcs4.engine.memory.AbstractDoubleLinkedListMemoryCache;
 import org.apache.commons.jcs4.engine.memory.util.MemoryElementDescriptor;
+import org.apache.commons.jcs4.utils.struct.DoubleLinkedList;
 
 /**
  * The most recently used items move to the front of the list and get spooled 
to disk if the cache
@@ -38,7 +39,7 @@ public class MRUMemoryCache<K, V>
      * @param me
      */
     @Override
-    protected void adjustListForGet( final MemoryElementDescriptor<K, V> me )
+    protected void adjustListForGet(final 
DoubleLinkedList<MemoryElementDescriptor<K, V>> list, final 
MemoryElementDescriptor<K, V> me )
     {
         list.makeLast( me );
     }
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
index 00ee7f63..f2828723 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
@@ -215,13 +215,12 @@ public class SoftReferenceMemoryCache<K, V> extends 
AbstractMemoryCache<K, V>
     @Override
     public void update(final ICacheElement<K, V> ce) throws IOException
     {
-        putCnt.incrementAndGet();
-        ce.elementAttributes().setLastAccessTimeNow();
-
         lock.lock();
 
         try
         {
+            super.update(ce);
+            ce.elementAttributes().setLastAccessTimeNow();
             map.put(ce.key(), new SoftReferenceElementDescriptor<>(ce));
             strongReferences.add(ce);
             trimStrongReferences();

Reply via email to