You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/10/21 15:42:18 UTC
svn commit: r1025995 - in /jackrabbit/branches/2.1: ./
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core...
Author: jukka
Date: Thu Oct 21 13:42:18 2010
New Revision: 1025995
URL: http://svn.apache.org/viewvc?rev=1025995&view=rev
Log:
2.1: Merged revisions 1004184, 1004223 and 1004223 (JCR-2699)
Modified:
jackrabbit/branches/2.1/ (props changed)
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Propchange: jackrabbit/branches/2.1/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 21 13:42:18 2010
@@ -2,4 +2,4 @@
/jackrabbit/sandbox/JCR-1456:774917-886178
/jackrabbit/sandbox/JCR-2170:812417-816332
/jackrabbit/sandbox/tripod-JCR-2209:795441-795863
-/jackrabbit/trunk:931121,931479,931483-931484,931504,931609,931613,931838,931919,932318-932319,933144,933197,933203,933213,933216,933554,933646,933694,934405,934412,934849,935557,936668,938099,945528,950440,950680,955222,955229,955307,955852,961487,961626,964362,965539,986682,986686,986715,991144,996810,1001707,1002065-1002066,1002084,1002101-1002102,1002168,1002170,1002589,1002608,1002657,1002729,1003423,1003470,1003542,1003773,1004182
+/jackrabbit/trunk:931121,931479,931483-931484,931504,931609,931613,931838,931919,932318-932319,933144,933197,933203,933213,933216,933554,933646,933694,934405,934412,934849,935557,936668,938099,945528,950440,950680,955222,955229,955307,955852,961487,961626,964362,965539,986682,986686,986715,991144,996810,1001707,1002065-1002066,1002084,1002101-1002102,1002168,1002170,1002589,1002608,1002657,1002729,1003423,1003470,1003542,1003773,1004182,1004184,1004223-1004224
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java Thu Oct 21 13:42:18 2010
@@ -22,9 +22,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
/**
* Concurrent cache implementation that uses cache segments to minimize
* the chance of lock contention. The LRU algorithm is used to evict excess
@@ -34,9 +31,6 @@ import org.slf4j.LoggerFactory;
*/
public class ConcurrentCache<K, V> extends AbstractCache {
- /** Logger instance */
- private static Logger log = LoggerFactory.getLogger(ConcurrentCache.class);
-
private static class E<V> {
private final V value;
@@ -150,16 +144,18 @@ public class ConcurrentCache<K, V> exten
* @param key entry key
* @param value entry value
* @param size entry size
+ * @return the previous value, or <code>null</code>
*/
- public void put(K key, V value, long size) {
+ public V put(K key, V value, long size) {
Map<K, E<V>> segment = getSegment(key);
synchronized (segment) {
recordSizeChange(size);
E<V> previous = segment.put(key, new E<V>(value, size));
if (previous != null) {
- log.warn("Overwriting cached entry {} from {} to {}",
- new Object[] { key, previous.value, value });
recordSizeChange(-previous.size);
+ return previous.value;
+ } else {
+ return null;
}
}
}
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -319,17 +319,6 @@ public abstract class AbstractBundlePers
throws ItemStateException;
/**
- * Checks if a bundle exists in the underlying system.
- *
- * @param id the node id of the bundle
- * @return <code>true</code> if the bundle exists;
- * <code>false</code> otherwise.
- * @throws ItemStateException if an error while checking occurs.
- */
- protected abstract boolean existsBundle(NodeId id)
- throws ItemStateException;
-
- /**
* Stores a bundle to the underlying system.
*
* @param bundle the bundle to store
@@ -632,7 +621,9 @@ public abstract class AbstractBundlePers
}
/**
- * Gets the bundle for the given node id.
+ * Gets the bundle for the given node id. Read/write synchronization
+ * happens higher up at the SISM level, so we don't need to worry about
+ * conflicts here.
*
* @param id the id of the bundle to retrieve.
* @return the bundle or <code>null</code> if the bundle does not exist
@@ -644,14 +635,12 @@ public abstract class AbstractBundlePers
if (bundle == MISSING) {
return null;
} else if (bundle == null) {
- synchronized (this) {
- bundle = loadBundle(id);
- if (bundle != null) {
- bundle.markOld();
- bundles.put(id, bundle, bundle.getSize());
- } else {
- bundles.put(id, MISSING, 16);
- }
+ bundle = loadBundle(id);
+ if (bundle != null) {
+ bundle.markOld();
+ bundles.put(id, bundle, bundle.getSize());
+ } else {
+ bundles.put(id, MISSING, 16);
}
}
return bundle;
@@ -666,7 +655,6 @@ public abstract class AbstractBundlePers
private void deleteBundle(NodePropBundle bundle) throws ItemStateException {
destroyBundle(bundle);
bundle.removeAllProperties();
- bundles.remove(bundle.getId());
bundles.put(bundle.getId(), MISSING, 16);
}
@@ -684,7 +672,6 @@ public abstract class AbstractBundlePers
// only put to cache if already exists. this is to ensure proper overwrite
// and not creating big contention during bulk loads
if (bundles.containsKey(bundle.getId())) {
- bundles.remove(bundle.getId());
bundles.put(bundle.getId(), bundle, bundle.getSize());
}
}
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -779,7 +779,7 @@ public class BundleDbPersistenceManager
try {
// skip root nodes (that point to itself)
if (parentId != null && !id.toString().endsWith("babecafebabe")) {
- if (!existsBundle(parentId)) {
+ if (loadBundle(parentId) == null) {
log.error("NodeState '" + id + "' references inexistent parent uuid '" + parentId + "'");
}
}
@@ -1176,25 +1176,6 @@ public class BundleDbPersistenceManager
/**
* {@inheritDoc}
*/
- protected synchronized boolean existsBundle(NodeId id) throws ItemStateException {
- ResultSet rs = null;
- try {
- Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id));
- rs = stmt.getResultSet();
- // a bundle exists, if the result has at least one entry
- return rs.next();
- } catch (Exception e) {
- String msg = "failed to check existence of bundle: " + id;
- log.error(msg, e);
- throw new ItemStateException(msg, e);
- } finally {
- closeResultSet(rs);
- }
- }
-
- /**
- * {@inheritDoc}
- */
protected synchronized void storeBundle(NodePropBundle bundle) throws ItemStateException {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -232,8 +232,7 @@ public class BundleFsPersistenceManager
/**
* {@inheritDoc}
*/
- protected synchronized NodePropBundle loadBundle(NodeId id)
- throws ItemStateException {
+ protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
DataInputStream din = null;
try {
String path = buildNodeFilePath(null, id).toString();
@@ -256,20 +255,6 @@ public class BundleFsPersistenceManager
}
/**
- * {@inheritDoc}
- */
- protected synchronized boolean existsBundle(NodeId id) throws ItemStateException {
- try {
- StringBuffer buf = buildNodeFilePath(null, id);
- return itemFs.exists(buf.toString());
- } catch (Exception e) {
- String msg = "failed to check existence of bundle: " + id;
- BundleFsPersistenceManager.log.error(msg, e);
- throw new ItemStateException(msg, e);
- }
- }
-
- /**
* Creates the file path for the given node id that is
* suitable for storing node states in a filesystem.
*
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -319,17 +319,6 @@ public abstract class AbstractBundlePers
throws ItemStateException;
/**
- * Checks if a bundle exists in the underlying system.
- *
- * @param id the node id of the bundle
- * @return <code>true</code> if the bundle exists;
- * <code>false</code> otherwise.
- * @throws ItemStateException if an error while checking occurs.
- */
- protected abstract boolean existsBundle(NodeId id)
- throws ItemStateException;
-
- /**
* Stores a bundle to the underlying system.
*
* @param bundle the bundle to store
@@ -630,7 +619,9 @@ public abstract class AbstractBundlePers
}
/**
- * Gets the bundle for the given node id.
+ * Gets the bundle for the given node id. Read/write synchronization
+ * happens higher up at the SISM level, so we don't need to worry about
+ * conflicts here.
*
* @param id the id of the bundle to retrieve.
* @return the bundle or <code>null</code> if the bundle does not exist
@@ -642,14 +633,12 @@ public abstract class AbstractBundlePers
if (bundle == MISSING) {
return null;
} else if (bundle == null) {
- synchronized (this) {
- bundle = loadBundle(id);
- if (bundle != null) {
- bundle.markOld();
- bundles.put(id, bundle, bundle.getSize());
- } else {
- bundles.put(id, MISSING, 16);
- }
+ bundle = loadBundle(id);
+ if (bundle != null) {
+ bundle.markOld();
+ bundles.put(id, bundle, bundle.getSize());
+ } else {
+ bundles.put(id, MISSING, 16);
}
}
return bundle;
@@ -664,7 +653,6 @@ public abstract class AbstractBundlePers
private void deleteBundle(NodePropBundle bundle) throws ItemStateException {
destroyBundle(bundle);
bundle.removeAllProperties();
- bundles.remove(bundle.getId());
bundles.put(bundle.getId(), MISSING, 16);
}
@@ -682,7 +670,6 @@ public abstract class AbstractBundlePers
// only put to cache if already exists. this is to ensure proper
// overwrite and not creating big contention during bulk loads
if (bundles.containsKey(bundle.getId())) {
- bundles.remove(bundle.getId());
bundles.put(bundle.getId(), bundle, bundle.getSize());
}
}
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -744,7 +744,7 @@ public class BundleDbPersistenceManager
try {
// skip root nodes (that point to itself)
if (parentId != null && !id.toString().endsWith("babecafebabe")) {
- if (!existsBundle(parentId)) {
+ if (loadBundle(parentId) == null) {
log.error("NodeState '" + id + "' references inexistent parent uuid '" + parentId + "'");
}
}
@@ -1024,8 +1024,7 @@ public class BundleDbPersistenceManager
/**
* {@inheritDoc}
*/
- protected synchronized NodePropBundle loadBundle(NodeId id)
- throws ItemStateException {
+ protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
return loadBundle(id, false);
}
@@ -1064,7 +1063,7 @@ public class BundleDbPersistenceManager
* exist.
* @throws ItemStateException if an error while loading occurs.
*/
- protected synchronized NodePropBundle loadBundle(NodeId id, boolean checkBeforeLoading)
+ protected NodePropBundle loadBundle(NodeId id, boolean checkBeforeLoading)
throws ItemStateException {
ResultSet rs = null;
@@ -1102,24 +1101,6 @@ public class BundleDbPersistenceManager
/**
* {@inheritDoc}
*/
- protected synchronized boolean existsBundle(NodeId id) throws ItemStateException {
- ResultSet rs = null;
- try {
- rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
- // a bundle exists, if the result has at least one entry
- return rs.next();
- } catch (Exception e) {
- String msg = "failed to check existence of bundle: " + id;
- log.error(msg, e);
- throw new ItemStateException(msg, e);
- } finally {
- DbUtility.close(rs);
- }
- }
-
- /**
- * {@inheritDoc}
- */
protected synchronized void storeBundle(NodePropBundle bundle) throws ItemStateException {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -231,8 +231,7 @@ public class BundleFsPersistenceManager
/**
* {@inheritDoc}
*/
- protected synchronized NodePropBundle loadBundle(NodeId id)
- throws ItemStateException {
+ protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
DataInputStream din = null;
try {
String path = buildNodeFilePath(null, id).toString();
@@ -255,20 +254,6 @@ public class BundleFsPersistenceManager
}
/**
- * {@inheritDoc}
- */
- protected synchronized boolean existsBundle(NodeId id) throws ItemStateException {
- try {
- StringBuffer buf = buildNodeFilePath(null, id);
- return itemFs.exists(buf.toString());
- } catch (Exception e) {
- String msg = "failed to check existence of bundle: " + id;
- BundleFsPersistenceManager.log.error(msg, e);
- throw new ItemStateException(msg, e);
- }
- }
-
- /**
* Creates the file path for the given node id that is
* suitable for storing node states in a filesystem.
*
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java Thu Oct 21 13:42:18 2010
@@ -92,10 +92,9 @@ public class PostgreSQLPersistenceManage
*
* {@inheritDoc}
*/
- protected synchronized NodePropBundle loadBundle(NodeId id)
- throws ItemStateException {
+ protected NodePropBundle loadBundle(NodeId id) throws ItemStateException {
ResultSet rs = null;
- try {
+ try {
rs = conHelper.exec(bundleSelectSQL, getKey(id), false, 0);
if (rs.next()) {
InputStream input = rs.getBinaryStream(1);
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java Thu Oct 21 13:42:18 2010
@@ -18,11 +18,11 @@ package org.apache.jackrabbit.core.state
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.core.id.ItemId;
-import org.apache.jackrabbit.core.util.Dumpable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
/**
@@ -43,36 +43,27 @@ import java.util.Map;
* </ul>
* This implementation of ItemStateCache is thread-safe.
*/
-public class ItemStateReferenceCache implements ItemStateCache, Dumpable {
+public class ItemStateReferenceCache implements ItemStateCache {
/** Logger instance */
private static Logger log = LoggerFactory.getLogger(ItemStateReferenceCache.class);
/**
- * primary cache storing weak references to <code>ItemState</code>
- * instances.
+ * Cache that automatically flushes entries based on some eviction policy;
+ * entries flushed from the secondary cache will be indirectly flushed
+ * from the reference map by the garbage collector if they thus are
+ * rendered weakly reachable.
*/
- @SuppressWarnings("unchecked")
- private final Map<ItemId, ItemState> refs =
- // I tried using soft instead of weak references here, but that
- // seems to have some unexpected performance consequences (notable
- // increase in the JCR TCK run time). So even though soft references
- // are generally recommended over weak references for caching
- // purposes, it seems that using weak references is safer here.
- new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+ private final ItemStateCache cache;
/**
- * secondary cache that automatically flushes entries based on some
- * eviction policy; entries flushed from the secondary cache will be
- * indirectly flushed from the primary (reference) cache by the garbage
- * collector if they thus are rendered weakly reachable.
+ * Segments of the weak reference map used to keep track of item states.
*/
- private final ItemStateCache cache;
+ private final Map<ItemId, ItemState>[] segments;
/**
* Creates a new <code>ItemStateReferenceCache</code> that uses a
- * <code>MLRUItemStateCache</code> instance as internal secondary
- * cache.
+ * <code>MLRUItemStateCache</code> instance as internal cache.
*/
public ItemStateReferenceCache(ItemStateCacheFactory cacheFactory) {
this(cacheFactory.newItemStateCache());
@@ -85,95 +76,143 @@ public class ItemStateReferenceCache imp
*
* @param cache secondary cache implementing a custom eviction policy
*/
+ @SuppressWarnings("unchecked")
public ItemStateReferenceCache(ItemStateCache cache) {
this.cache = cache;
+ this.segments = new Map[Runtime.getRuntime().availableProcessors()];
+ for (int i = 0; i < segments.length; i++) {
+ // I tried using soft instead of weak references here, but that
+ // seems to have some unexpected performance consequences (notable
+ // increase in the JCR TCK run time). So even though soft references
+ // are generally recommended over weak references for caching
+ // purposes, it seems that using weak references is safer here.
+ segments[i] =
+ new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+ }
+ }
+
+ /**
+ * Returns the reference map segment for the given entry key. The segment
+ * is selected based on the hash code of the key, after a transformation
+ * to prevent interfering with the optimal performance of the segment
+ * hash map.
+ *
+ * @param id item identifer
+ * @return reference map segment
+ */
+ private Map<ItemId, ItemState> getSegment(ItemId id) {
+ // Unsigned shift right to prevent negative indexes and to
+ // prevent too similar keys to all get stored in the same segment
+ return segments[(id.hashCode() >>> 1) % segments.length];
}
//-------------------------------------------------------< ItemStateCache >
/**
* {@inheritDoc}
*/
- public synchronized boolean isCached(ItemId id) {
- // check primary cache
- return refs.containsKey(id);
+ public boolean isCached(ItemId id) {
+ Map<ItemId, ItemState> segment = getSegment(id);
+ synchronized (segment) {
+ return segment.containsKey(id);
+ }
}
/**
* {@inheritDoc}
*/
- public synchronized ItemState retrieve(ItemId id) {
- // fake call to update stats of secondary cache
- cache.retrieve(id);
+ public ItemState retrieve(ItemId id) {
+ // Update the access statistics in the cache
+ ItemState state = cache.retrieve(id);
+ if (state != null) {
+ // Return fast to avoid the second lookup below
+ return state;
+ }
- // retrieve from primary cache
- return refs.get(id);
+ Map<ItemId, ItemState> segment = getSegment(id);
+ synchronized (segment) {
+ return segment.get(id);
+ }
}
/**
* {@inheritDoc}
*/
- public synchronized ItemState[] retrieveAll() {
- // values of primary cache
- return (ItemState[]) refs.values().toArray(new ItemState[refs.size()]);
+ public ItemState[] retrieveAll() {
+ List<ItemState> states = new ArrayList<ItemState>();
+ for (int i = 0; i < segments.length; i++) {
+ synchronized (segments[i]) {
+ states.addAll(segments[i].values());
+ }
+ }
+ return states.toArray(new ItemState[states.size()]);
}
/**
* {@inheritDoc}
*/
- public synchronized void cache(ItemState state) {
- ItemId id = state.getId();
- if (refs.containsKey(id)) {
- log.warn("overwriting cached entry " + id);
- }
- // fake call to update stats of secondary cache
+ public void cache(ItemState state) {
+ // Update the cache
cache.cache(state);
- // store weak reference in primary cache
- refs.put(id, state);
+ // Store a weak reference in the reference map
+ ItemId id = state.getId();
+ Map<ItemId, ItemState> segment = getSegment(id);
+ synchronized (segment) {
+ if (segment.containsKey(id)) {
+ log.warn("overwriting cached entry " + id);
+ }
+ segment.put(id, state);
+ }
}
/**
* {@inheritDoc}
*/
- public synchronized void evict(ItemId id) {
- // fake call to update stats of secondary cache
+ public void evict(ItemId id) {
+ // Update the cache
cache.evict(id);
- // remove from primary cache
- refs.remove(id);
+ // Remove from reference map
+ // TODO: Allow the weak reference to be cleared automatically?
+ Map<ItemId, ItemState> segment = getSegment(id);
+ synchronized (segment) {
+ segment.remove(id);
+ }
}
/**
* {@inheritDoc}
*/
- public synchronized void dispose() {
+ public void dispose() {
cache.dispose();
}
/**
* {@inheritDoc}
*/
- public synchronized void evictAll() {
- // fake call to update stats of secondary cache
+ public void evictAll() {
+ // Update the cache
cache.evictAll();
- // remove all weak references from primary cache
- refs.clear();
+ // remove all weak references from reference map
+ // TODO: Allow the weak reference to be cleared automatically?
+ for (int i = 0; i < segments.length; i++) {
+ synchronized (segments[i]) {
+ segments[i].clear();
+ }
+ }
}
/**
* {@inheritDoc}
*/
- public synchronized boolean isEmpty() {
- // check primary cache
- return refs.isEmpty();
+ public boolean isEmpty() {
+ for (int i = 0; i < segments.length; i++) {
+ synchronized (segments[i]) {
+ if (!segments[i].isEmpty()) {
+ return false;
+ }
+ }
+ }
+ return true;
}
- //-------------------------------------------------------------< Dumpable >
- /**
- * {@inheritDoc}
- */
- public synchronized void dump(PrintStream ps) {
- ps.println("ItemStateReferenceCache (" + this + ")");
- ps.println(" refs: " + refs.keySet());
- ps.println();
- }
}
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java Thu Oct 21 13:42:18 2010
@@ -163,19 +163,17 @@ public class LocalItemStateManager
return state;
}
- // check cache. synchronized to ensure an entry is not created twice.
- synchronized (this) {
- state = cache.retrieve(id);
- if (state == null) {
- // regular behaviour
- if (id.denotesNode()) {
- state = getNodeState((NodeId) id);
- } else {
- state = getPropertyState((PropertyId) id);
- }
+ // check cache
+ state = cache.retrieve(id);
+ if (state == null) {
+ // regular behaviour
+ if (id.denotesNode()) {
+ state = getNodeState((NodeId) id);
+ } else {
+ state = getPropertyState((PropertyId) id);
}
- return state;
}
+ return state;
}
/**
Modified: jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=1025995&r1=1025994&r2=1025995&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Thu Oct 21 13:42:18 2010
@@ -1708,21 +1708,8 @@ public class SharedItemStateManager
// not found in cache, load from persistent storage
state = loadItemState(id);
state.setStatus(ItemState.STATUS_EXISTING);
- synchronized (this) {
- // Use a double check to ensure that the cache entry is
- // not created twice. We don't synchronize the entire
- // method to allow the first cache retrieval to proceed
- // even when another thread is loading a new item state.
- ItemState cachedState = cache.retrieve(id);
- if (cachedState == null) {
- // put it in cache
- cache.cache(state);
- // set parent container
- state.setContainer(this);
- } else {
- state = cachedState;
- }
- }
+ state.setContainer(this);
+ cache.cache(state);
}
return state;
}