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();