Index: src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java (revision 605226) +++ src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java (working copy) @@ -42,6 +42,7 @@ * collector if they are thus rendered weakly reachable. * * + * This implementation of ItemStateCache is thread-safe. */ public class ItemStateReferenceCache implements ItemStateCache, Dumpable { @@ -86,7 +87,7 @@ /** * {@inheritDoc} */ - public boolean isCached(ItemId id) { + public synchronized boolean isCached(ItemId id) { // check primary cache return refs.contains(id); } @@ -94,7 +95,7 @@ /** * {@inheritDoc} */ - public ItemState retrieve(ItemId id) { + public synchronized ItemState retrieve(ItemId id) { // fake call to update stats of secondary cache cache.retrieve(id); @@ -105,7 +106,7 @@ /** * {@inheritDoc} */ - public void cache(ItemState state) { + public synchronized void cache(ItemState state) { ItemId id = state.getId(); if (refs.contains(id)) { log.warn("overwriting cached entry " + id); @@ -120,7 +121,7 @@ /** * {@inheritDoc} */ - public void evict(ItemId id) { + public synchronized void evict(ItemId id) { // fake call to update stats of secondary cache cache.evict(id); // remove from primary cache @@ -130,14 +131,14 @@ /** * {@inheritDoc} */ - public void dispose() { + public synchronized void dispose() { cache.dispose(); } /** * {@inheritDoc} */ - public void evictAll() { + public synchronized void evictAll() { // fake call to update stats of secondary cache cache.evictAll(); // remove all weak references from primary cache @@ -147,7 +148,7 @@ /** * {@inheritDoc} */ - public void update(ItemId id) { + public synchronized void update(ItemId id) { // delegate cache.update(id); } @@ -155,7 +156,7 @@ /** * {@inheritDoc} */ - public boolean isEmpty() { + public synchronized boolean isEmpty() { // check primary cache return refs.isEmpty(); } @@ -163,23 +164,49 @@ /** * {@inheritDoc} */ - public int size() { + public synchronized int size() { // size of primary cache return refs.size(); } /** * {@inheritDoc} + *
+ * The returned Set is not synchronized. The caller must ensure that + * it manually synchronizes access to the Set. Example: + *
+ * ItemStateCache cache = new ItemStateReferenceCache(...);
+ * synchronized (cache) {
+ * Set keys = cache.keySet();
+ * for (Iterator it = keys.iterator(); it.hasNext(); ) {
+ * Object item = it.next();
+ * // do something with item
+ * }
+ * }
+ *
*/
- public Set keySet() {
+ public synchronized Set keySet() {
// keys of primary cache
return Collections.unmodifiableSet(refs.keySet());
}
/**
* {@inheritDoc}
+ *
+ * The returned collection is not synchronized. The caller must ensure that
+ * it manually synchronizes access to the collection. Example:
+ *
+ * ItemStateCache cache = new ItemStateReferenceCache(...);
+ * synchronized (cache) {
+ * Collection values = cache.values();
+ * for (Iterator it = values.iterator(); it.hasNext(); ) {
+ * Object item = it.next();
+ * // do something with item
+ * }
+ * }
+ *
*/
- public Collection values() {
+ public synchronized Collection values() {
// values of primary cache
return Collections.unmodifiableCollection(refs.values());
}
@@ -188,7 +215,7 @@
/**
* {@inheritDoc}
*/
- public void dump(PrintStream ps) {
+ public synchronized void dump(PrintStream ps) {
ps.println("ItemStateReferenceCache (" + this + ")");
ps.println();
ps.print("[refs] ");
Index: src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (revision 605226)
+++ src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (working copy)
@@ -35,7 +35,7 @@
* cache of weak references to ItemState objects issued by this
* ItemStateManager
*/
- private final ItemStateReferenceCache cache;
+ private final ItemStateCache cache;
/**
* Shared item state manager
@@ -140,7 +140,7 @@
}
// check cache. synchronized to ensure an entry is not created twice.
- synchronized (cache) {
+ synchronized (this) {
state = cache.retrieve(id);
if (state == null) {
// regular behaviour
@@ -336,8 +336,11 @@
// JCR-798: copy cached item states to array
// to avoid ConcurrentModificationException
- ItemState[] isa = (ItemState[]) cache.values().toArray(
- new ItemState[cache.size()]);
+ ItemState[] isa;
+ synchronized (cache) {
+ isa = (ItemState[]) cache.values().toArray(
+ new ItemState[cache.size()]);
+ }
for (int i = 0; i < isa.length; i++) {
ItemState state = isa[i];
if (state != null) {