Index: src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (revision 602118)
+++ 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
@@ -69,7 +69,8 @@
*/
public LocalItemStateManager(SharedItemStateManager sharedStateMgr,
EventStateCollectionFactory factory, ItemStateCacheFactory cacheFactory) {
- cache = new ItemStateReferenceCache(cacheFactory);
+ cache = new SynchronizedItemStateCache(
+ new ItemStateReferenceCache(cacheFactory));
this.sharedStateMgr = sharedStateMgr;
this.factory = factory;
@@ -336,8 +337,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) {
Index: src/main/java/org/apache/jackrabbit/core/state/SynchronizedItemStateCache.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/SynchronizedItemStateCache.java (revision 0)
+++ src/main/java/org/apache/jackrabbit/core/state/SynchronizedItemStateCache.java (revision 0)
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.ItemId;
+
+import java.util.Set;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * SynchronizedItemStateCache implements a wrapper for a {@link
+ * ItemStateCache} and turns it into a synchronized item state cache.
+ */
+class SynchronizedItemStateCache implements ItemStateCache {
+
+ /**
+ * The underlying item state cache (not thread-safe).
+ */
+ private final ItemStateCache cache;
+
+ /**
+ * The mutex on which to synchronize access.
+ */
+ private final Object mutex;
+
+ /**
+ * Wraps the item state cache and provides synchronized access
+ * to it. Access to the cache is synchronized on this object.
+ *
+ * @param cache the item state cache.
+ */
+ SynchronizedItemStateCache(ItemStateCache cache) {
+ this.cache = cache;
+ this.mutex = this;
+ }
+
+ /**
+ * Wraps the item state cache and provides synchronized access
+ * to it. Access to the cache is synchronized on
+ * mutex.
+ *
+ * @param cache the item state cache.
+ * @param mutex the object on which to synchronize access.
+ */
+ SynchronizedItemStateCache(ItemStateCache cache, Object mutex) {
+ this.cache = cache;
+ this.mutex = mutex;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isCached(ItemId id) {
+ synchronized (mutex) {
+ return cache.isCached(id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ItemState retrieve(ItemId id) {
+ synchronized (mutex) {
+ return cache.retrieve(id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void cache(ItemState state) {
+ synchronized (mutex) {
+ cache.cache(state);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void evict(ItemId id) {
+ synchronized (mutex) {
+ cache.evict(id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void evictAll() {
+ synchronized (mutex) {
+ cache.evictAll();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty() {
+ synchronized (mutex) {
+ return cache.isEmpty();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int size() {
+ synchronized (mutex) {
+ return cache.size();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * ItemStateCache cache = new SynchronizedItemStateCache(...);
+ * synchronized (cache) {
+ * Set keys = cache.keySet();
+ * for (Iterator it = keys.iterator(); it.hasNext(); ) {
+ * Object item = it.next();
+ * // do something with item
+ * }
+ * }
+ *
+ */
+ public Set keySet() {
+ synchronized (mutex) {
+ return cache.keySet();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * The returned collection is not synchronized. The caller must ensure that
+ * it manually synchronizes access to the collection. Example:
+ *
+ * ItemStateCache cache = new SynchronizedItemStateCache(...);
+ * synchronized (cache) {
+ * Collection values = cache.values();
+ * for (Iterator it = values.iterator(); it.hasNext(); ) {
+ * Object item = it.next();
+ * // do something with item
+ * }
+ * }
+ *
+ */
+ public Collection values() {
+ synchronized (mutex) {
+ return cache.values();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void update(ItemId id) {
+ synchronized (mutex) {
+ cache.update(id);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dispose() {
+ synchronized (mutex) {
+ cache.dispose();
+ }
+ }
+}
Property changes on: src\main\java\org\apache\jackrabbit\core\state\SynchronizedItemStateCache.java
___________________________________________________________________
Name: svn:eol-style
+ native