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 17:13:34 UTC
svn commit: r1026025 - in /jackrabbit/branches/2.0: ./
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 15:13:34 2010
New Revision: 1026025
URL: http://svn.apache.org/viewvc?rev=1026025&view=rev
Log:
2.0: Merged revisions 1025990 and 1025995 (JCR-2699)
Added:
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java
- copied unchanged from r1025990, jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/AbstractCache.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
- copied, changed from r1025990, jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java
jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/
- copied from r1025990, jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/
jackrabbit/branches/2.0/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java
- copied unchanged from r1025990, jackrabbit/branches/2.1/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/cache/ConcurrentCacheTest.java
Removed:
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleCache.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/LRUNodeIdCache.java
Modified:
jackrabbit/branches/2.0/ (props changed)
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateCache.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ManagedMLRUItemStateCacheFactory.java
jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Propchange: jackrabbit/branches/2.0/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Oct 21 15:13:34 2010
@@ -1,6 +1,6 @@
/jackrabbit/branches/1.5:794012,794100,794102
-/jackrabbit/branches/2.1:955309,955314,982266,982277,982505,998310,1025933,1025957,1025962,1025964,1025981,1025985
+/jackrabbit/branches/2.1:955309,955314,982266,982277,982505,998310,1025933,1025957,1025962,1025964,1025981,1025985,1025990,1025995
/jackrabbit/sandbox/JCR-1456:774917-886178
/jackrabbit/sandbox/JCR-2170:812417-816332
/jackrabbit/sandbox/tripod-JCR-2209:795441-795863
-/jackrabbit/trunk:891595,891629,892253,892263,894150-894151,896408,896513,896532,896857,896870,896876,896908,896940,896942-896943,896969,896977,897071,897836,897842,897858,897935,897983,897992-897993,897996,898002,898042,898267,898325,898540,898677,898699,898701,898715,898872,899102,899181,899391,899393-899394,899583,899594,899643,900305,900310,900314,900453,900702,900736,900762-900763,900767,900782,901095,901122,901139,901144,901170,901176,901191,901193,901196,901216,901228,901285,902058,902062,926324,928888,936668,955222,955229,955307,955852,965539,996810,1001707,1002065-1002066,1002084,1002101-1002102,1002168,1002170,1002589,1002608,1002657,1002729,1003423,1003470
+/jackrabbit/trunk:891595,891629,892253,892263,894150-894151,896408,896513,896532,896857,896870,896876,896908,896940,896942-896943,896969,896977,897071,897836,897842,897858,897935,897983,897992-897993,897996,898002,898042,898267,898325,898540,898677,898699,898701,898715,898872,899102,899181,899391,899393-899394,899583,899594,899643,900305,900310,900314,900453,900702,900736,900762-900763,900767,900782,901095,901122,901139,901144,901170,901176,901191,901193,901196,901216,901228,901285,902058,902062,926324,928888,936668,955222,955229,955307,955852,965539,996810,1001707,1002065-1002066,1002084,1002101-1002102,1002168,1002170,1002589,1002608,1002657,1002729,1003423,1003470,1003542,1003773,1004182,1004184,1004223-1004224
Copied: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java (from r1025990, 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java?p2=jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java&p1=jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java&r1=1025990&r2=1026025&rev=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.1/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cache/ConcurrentCache.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java Thu Oct 21 15:13:34 2010
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.core.persi
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.cache.ConcurrentCache;
import org.apache.jackrabbit.core.fs.FileSystemResource;
import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.state.ItemState;
@@ -37,9 +38,7 @@ import org.apache.jackrabbit.core.persis
import org.apache.jackrabbit.core.persistence.PersistenceManager;
import org.apache.jackrabbit.core.persistence.util.BundleBinding;
import org.apache.jackrabbit.core.util.StringIndex;
-import org.apache.jackrabbit.core.persistence.util.BundleCache;
import org.apache.jackrabbit.core.persistence.util.HashMapIndex;
-import org.apache.jackrabbit.core.persistence.util.LRUNodeIdCache;
import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
@@ -68,7 +67,7 @@ import javax.jcr.PropertyType;
* included in the bundle but generated when required.
* <p/>
* In order to increase performance, there are 2 caches maintained. One is the
- * {@link BundleCache} that caches already loaded bundles. The other is the
+ * bundle cache that caches already loaded bundles. The other is the
* {@link LRUNodeIdCache} that caches non-existent bundles. This is useful
* because a lot of {@link #exists(NodeId)} calls are issued that would result
* in a useless SQL execution if the desired bundle does not exist.
@@ -96,6 +95,10 @@ public abstract class AbstractBundlePers
/** the name of the namespace-index resource */
protected static final String RES_NS_INDEX = "/namespaces.properties";
+ /** Sentinel instance used to mark a non-existent bundle in the cache */
+ private static final NodePropBundle MISSING =
+ new NodePropBundle(null, new NodeId());
+
/** the index for namespaces */
private StringIndex nsIndex;
@@ -103,10 +106,7 @@ public abstract class AbstractBundlePers
private StringIndex nameIndex;
/** the cache of loaded bundles */
- private BundleCache bundles;
-
- /** the cache of non-existent bundles */
- private LRUNodeIdCache missing;
+ private ConcurrentCache<NodeId, NodePropBundle> bundles;
/** the persistence manager context */
protected PMContext context;
@@ -286,25 +286,22 @@ public abstract class AbstractBundlePers
*/
public synchronized void onExternalUpdate(ChangeLog changes) {
for (ItemState state : changes.modifiedStates()) {
- if (state.isNode()) {
- bundles.remove((NodeId) state.getId());
- } else {
- bundles.remove(state.getParentId());
- }
+ bundles.remove(getBundleId(state));
}
for (ItemState state : changes.deletedStates()) {
- if (state.isNode()) {
- bundles.remove((NodeId) state.getId());
- } else {
- bundles.remove(state.getParentId());
- }
+ bundles.remove(getBundleId(state));
}
for (ItemState state : changes.addedStates()) {
- if (state.isNode()) {
- missing.remove((NodeId) state.getId());
- } else {
- missing.remove(state.getParentId());
- }
+ // There may have been a cache miss entry
+ bundles.remove(getBundleId(state));
+ }
+ }
+
+ private NodeId getBundleId(ItemState state) {
+ if (state.isNode()) {
+ return (NodeId) state.getId();
+ } else {
+ return state.getParentId();
}
}
@@ -322,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
@@ -385,8 +371,8 @@ public abstract class AbstractBundlePers
public void init(PMContext context) throws Exception {
this.context = context;
// init bundle cache
- bundles = new BundleCache(bundleCacheSize);
- missing = new LRUNodeIdCache();
+ bundles = new ConcurrentCache<NodeId, NodePropBundle>();
+ bundles.setMaxMemorySize(bundleCacheSize);
}
/**
@@ -397,7 +383,6 @@ public abstract class AbstractBundlePers
public void close() throws Exception {
// clear caches
bundles.clear();
- missing.clear();
}
/**
@@ -504,7 +489,6 @@ public abstract class AbstractBundlePers
} finally {
if (!success) {
bundles.clear();
- missing.clear();
}
}
}
@@ -637,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
@@ -645,19 +631,16 @@ public abstract class AbstractBundlePers
* @throws ItemStateException if an error occurs.
*/
private NodePropBundle getBundle(NodeId id) throws ItemStateException {
- if (missing.contains(id)) {
- return null;
- }
NodePropBundle bundle = bundles.get(id);
- if (bundle == null) {
- synchronized (this) {
- bundle = loadBundle(id);
- if (bundle != null) {
- bundle.markOld();
- bundles.put(bundle);
- } else {
- missing.put(id);
- }
+ if (bundle == MISSING) {
+ return null;
+ } else if (bundle == null) {
+ bundle = loadBundle(id);
+ if (bundle != null) {
+ bundle.markOld();
+ bundles.put(id, bundle, bundle.getSize());
+ } else {
+ bundles.put(id, MISSING, 16);
}
}
return bundle;
@@ -672,8 +655,7 @@ public abstract class AbstractBundlePers
private void deleteBundle(NodePropBundle bundle) throws ItemStateException {
destroyBundle(bundle);
bundle.removeAllProperties();
- bundles.remove(bundle.getId());
- missing.put(bundle.getId());
+ bundles.put(bundle.getId(), MISSING, 16);
}
/**
@@ -687,11 +669,10 @@ public abstract class AbstractBundlePers
bundle.markOld();
log.debug("stored bundle {}", bundle.getId());
- missing.remove(bundle.getId());
// only put to cache if already exists. this is to ensure proper overwrite
// and not creating big contention during bulk loads
- if (bundles.contains(bundle.getId())) {
- bundles.put(bundle);
+ if (bundles.containsKey(bundle.getId())) {
+ bundles.put(bundle.getId(), bundle, bundle.getSize());
}
}
Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleFsPersistenceManager.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/AbstractBundlePersistenceManager.java Thu Oct 21 15:13:34 2010
@@ -24,6 +24,7 @@ import javax.jcr.PropertyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.core.cache.ConcurrentCache;
import org.apache.jackrabbit.core.fs.FileSystemResource;
import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.id.ItemId;
@@ -34,9 +35,7 @@ import org.apache.jackrabbit.core.persis
import org.apache.jackrabbit.core.persistence.PMContext;
import org.apache.jackrabbit.core.persistence.PersistenceManager;
import org.apache.jackrabbit.core.persistence.util.BundleBinding;
-import org.apache.jackrabbit.core.persistence.util.BundleCache;
import org.apache.jackrabbit.core.persistence.util.HashMapIndex;
-import org.apache.jackrabbit.core.persistence.util.LRUNodeIdCache;
import org.apache.jackrabbit.core.persistence.util.NodePropBundle;
import org.apache.jackrabbit.core.state.ItemState;
import org.apache.jackrabbit.core.state.ChangeLog;
@@ -68,7 +67,7 @@ import org.apache.jackrabbit.spi.commons
* included in the bundle but generated when required.
* <p/>
* In order to increase performance, there are 2 caches maintained. One is the
- * {@link BundleCache} that caches already loaded bundles. The other is the
+ * bundle cache that caches already loaded bundles. The other is the
* {@link LRUNodeIdCache} that caches non-existent bundles. This is useful
* because a lot of {@link #exists(NodeId)} calls are issued that would result
* in a useless SQL execution if the desired bundle does not exist.
@@ -96,6 +95,10 @@ public abstract class AbstractBundlePers
/** the name of the namespace-index resource */
protected static final String RES_NS_INDEX = "/namespaces.properties";
+ /** Sentinel instance used to mark a non-existent bundle in the cache */
+ private static final NodePropBundle MISSING =
+ new NodePropBundle(null, new NodeId());
+
/** the index for namespaces */
private StringIndex nsIndex;
@@ -103,10 +106,7 @@ public abstract class AbstractBundlePers
private StringIndex nameIndex;
/** the cache of loaded bundles */
- private BundleCache bundles;
-
- /** the cache of non-existent bundles */
- private LRUNodeIdCache missing;
+ private ConcurrentCache<NodeId, NodePropBundle> bundles;
/** the persistence manager context */
protected PMContext context;
@@ -286,25 +286,22 @@ public abstract class AbstractBundlePers
*/
public synchronized void onExternalUpdate(ChangeLog changes) {
for (ItemState state : changes.modifiedStates()) {
- if (state.isNode()) {
- bundles.remove((NodeId) state.getId());
- } else {
- bundles.remove(state.getParentId());
- }
+ bundles.remove(getBundleId(state));
}
for (ItemState state : changes.deletedStates()) {
- if (state.isNode()) {
- bundles.remove((NodeId) state.getId());
- } else {
- bundles.remove(state.getParentId());
- }
+ bundles.remove(getBundleId(state));
}
for (ItemState state : changes.addedStates()) {
- if (state.isNode()) {
- missing.remove((NodeId) state.getId());
- } else {
- missing.remove(state.getParentId());
- }
+ // There may have been a cache miss entry
+ bundles.remove(getBundleId(state));
+ }
+ }
+
+ private NodeId getBundleId(ItemState state) {
+ if (state.isNode()) {
+ return (NodeId) state.getId();
+ } else {
+ return state.getParentId();
}
}
@@ -322,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
@@ -385,19 +371,18 @@ public abstract class AbstractBundlePers
public void init(PMContext context) throws Exception {
this.context = context;
// init bundle cache
- bundles = new BundleCache(bundleCacheSize);
- missing = new LRUNodeIdCache();
+ bundles = new ConcurrentCache<NodeId, NodePropBundle>();
+ bundles.setMaxMemorySize(bundleCacheSize);
}
/**
* {@inheritDoc}
*
- * Closes the persistence manager, release acquired resourecs.
+ * Closes the persistence manager, release acquired resources.
*/
public void close() throws Exception {
// clear caches
bundles.clear();
- missing.clear();
}
/**
@@ -502,7 +487,6 @@ public abstract class AbstractBundlePers
} finally {
if (!success) {
bundles.clear();
- missing.clear();
}
}
}
@@ -635,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
@@ -643,19 +629,16 @@ public abstract class AbstractBundlePers
* @throws ItemStateException if an error occurs.
*/
private NodePropBundle getBundle(NodeId id) throws ItemStateException {
- if (missing.contains(id)) {
- return null;
- }
NodePropBundle bundle = bundles.get(id);
- if (bundle == null) {
- synchronized (this) {
- bundle = loadBundle(id);
- if (bundle != null) {
- bundle.markOld();
- bundles.put(bundle);
- } else {
- missing.put(id);
- }
+ if (bundle == MISSING) {
+ return null;
+ } else if (bundle == null) {
+ bundle = loadBundle(id);
+ if (bundle != null) {
+ bundle.markOld();
+ bundles.put(id, bundle, bundle.getSize());
+ } else {
+ bundles.put(id, MISSING, 16);
}
}
return bundle;
@@ -670,8 +653,7 @@ public abstract class AbstractBundlePers
private void deleteBundle(NodePropBundle bundle) throws ItemStateException {
destroyBundle(bundle);
bundle.removeAllProperties();
- bundles.remove(bundle.getId());
- missing.put(bundle.getId());
+ bundles.put(bundle.getId(), MISSING, 16);
}
/**
@@ -685,11 +667,10 @@ public abstract class AbstractBundlePers
bundle.markOld();
log.debug("stored bundle {}", bundle.getId());
- missing.remove(bundle.getId());
- // only put to cache if already exists. this is to ensure proper overwrite
- // and not creating big contention during bulk loads
- if (bundles.contains(bundle.getId())) {
- bundles.put(bundle);
+ // 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.put(bundle.getId(), bundle, bundle.getSize());
}
}
Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleDbPersistenceManager.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/BundleFsPersistenceManager.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/pool/PostgreSQLPersistenceManager.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateCache.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateCache.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateCache.java Thu Oct 21 15:13:34 2010
@@ -83,14 +83,6 @@ public interface ItemStateCache {
boolean isEmpty();
/**
- * Informs the cache that the item was modified and the cache might need to
- * recalculate the items caching weight.
- *
- * @param id the id of the item that was modified.
- */
- void update(ItemId id);
-
- /**
* Informs the cache that it is no longer in use.
*/
void dispose();
Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java Thu Oct 21 15:13:34 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,103 +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();
- }
-
- /**
- * {@inheritDoc}
- */
- public synchronized void update(ItemId id) {
- // delegate
- cache.update(id);
+ // 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java Thu Oct 21 15:13:34 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.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/MLRUItemStateCache.java Thu Oct 21 15:13:34 2010
@@ -16,14 +16,9 @@
*/
package org.apache.jackrabbit.core.state;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
import org.apache.commons.collections.map.LinkedMap;
-import org.apache.jackrabbit.core.cache.Cache;
-import org.apache.jackrabbit.core.cache.CacheAccessListener;
+import org.apache.jackrabbit.core.cache.CacheManager;
+import org.apache.jackrabbit.core.cache.ConcurrentCache;
import org.apache.jackrabbit.core.id.ItemId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,139 +33,59 @@ import org.slf4j.LoggerFactory;
* TODO rename class to something more appropriate, e.g. FIFOItemSateCache since
* it doesn't use a LRU eviction policy anymore.
*/
-public class MLRUItemStateCache implements ItemStateCache, Cache {
+public class MLRUItemStateCache implements ItemStateCache {
+
/** Logger instance */
private static Logger log = LoggerFactory.getLogger(MLRUItemStateCache.class);
/** default maximum memory to use */
public static final int DEFAULT_MAX_MEM = 4 * 1024 * 1024;
- /** the amount of memory the entries use */
- private volatile long totalMem;
-
- /** the maximum of memory the cache may use */
- private volatile long maxMem;
-
/** the number of writes */
- private volatile long numWrites;
-
- /** the access count */
- private volatile long accessCount;
+ private volatile long numWrites = 0;
- /** the cache access listeners */
- private CacheAccessListener accessListener;
-
- /**
- * A cache for <code>ItemState</code> instances
- */
- private final Map<ItemId, Entry> cache;
-
- /**
- * Constructs a new, empty <code>ItemStateCache</code> with a maximum amount
- * of memory of {@link #DEFAULT_MAX_MEM}.
- */
- public MLRUItemStateCache() {
- this(DEFAULT_MAX_MEM);
- }
+ private final ConcurrentCache<ItemId, ItemState> cache =
+ new ConcurrentCache<ItemId, ItemState>();
- /**
- * Constructs a new, empty <code>ItemStateCache</code> with the specified
- * maximum memory.
- *
- * @param maxMem the maximum amount of memory this cache may use.
- */
- @SuppressWarnings("serial")
- private MLRUItemStateCache(int maxMem) {
- this.maxMem = maxMem;
- this.cache = new LinkedHashMap<ItemId, MLRUItemStateCache.Entry>(
- maxMem / 1024, 0.75f, true /* access-ordered */) {
- @Override
- protected boolean removeEldestEntry(Map.Entry<ItemId, Entry> e) {
- long maxMem = MLRUItemStateCache.this.maxMem;
- if (totalMem <= maxMem) {
- return false;
- } else if (totalMem - e.getValue().size <= maxMem) {
- totalMem -= e.getValue().size;
- return true;
- } else {
- shrink();
- return false;
- }
- }
- };
+ public MLRUItemStateCache(CacheManager cacheMgr) {
+ cache.setMaxMemorySize(DEFAULT_MAX_MEM);
+ cache.setAccessListener(cacheMgr);
+ cacheMgr.add(cache);
}
//-------------------------------------------------------< ItemStateCache >
+
/**
* {@inheritDoc}
*/
public boolean isCached(ItemId id) {
- synchronized (cache) {
- return cache.containsKey(id);
- }
+ return cache.containsKey(id);
}
/**
* {@inheritDoc}
*/
public ItemState retrieve(ItemId id) {
- touch();
- synchronized (cache) {
- Entry entry = cache.get(id);
- if (entry != null) {
- return entry.state;
- } else {
- return null;
- }
- }
+ return cache.get(id);
}
/**
* {@inheritDoc}
*/
public ItemState[] retrieveAll() {
- synchronized (cache) {
- ItemState[] states = new ItemState[cache.size()];
- int i = 0;
- for (Entry entry : cache.values()) {
- states[i++] = entry.state;
- }
- return states;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void update(ItemId id) {
- touch();
- synchronized (cache) {
- Entry entry = cache.get(id);
- if (entry != null) {
- totalMem -= entry.size;
- entry.recalc();
- totalMem += entry.size;
- }
- }
+ return cache.values();
}
/**
* {@inheritDoc}
*/
public void cache(ItemState state) {
- touch();
- synchronized (cache) {
- ItemId id = state.getId();
- if (cache.containsKey(id)) {
- log.warn("overwriting cached entry " + id);
- evict(id);
- }
- Entry entry = new Entry(state);
- totalMem += entry.size;
- cache.put(id, entry);
- if (numWrites++ % 10000 == 0 && log.isDebugEnabled()) {
- log.debug(this + " size=" + cache.size() + ", " + totalMem + "/" + maxMem);
- }
+ cache.put(state.getId(), state, state.calculateMemoryFootprint());
+
+ if (numWrites++ % 10000 == 0 && log.isDebugEnabled()) {
+ log.debug("Item state cache size: {}% of {} bytes",
+ cache.getMemoryUsed() * 100 / cache.getMaxMemorySize(),
+ cache.getMaxMemorySize());
}
}
@@ -178,135 +93,28 @@ public class MLRUItemStateCache implemen
* {@inheritDoc}
*/
public void evict(ItemId id) {
- touch();
- synchronized (cache) {
- Entry entry = cache.remove(id);
- if (entry != null) {
- totalMem -= entry.size;
- }
- }
+ cache.remove(id);
}
/**
* {@inheritDoc}
*/
public void evictAll() {
- synchronized (cache) {
- cache.clear();
- totalMem = 0;
- }
+ cache.clear();
}
/**
* {@inheritDoc}
*/
public boolean isEmpty() {
- synchronized (cache) {
- return cache.isEmpty();
- }
- }
-
- private void touch() {
- accessCount++;
- if ((accessCount % CacheAccessListener.ACCESS_INTERVAL) == 0) {
- if (accessListener != null) {
- accessListener.cacheAccessed();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public long getAccessCount() {
- return accessCount;
- }
-
- /**
- * {@inheritDoc}
- */
- public long getMaxMemorySize() {
- return maxMem;
- }
-
- /**
- * {@inheritDoc}
- */
- public long getMemoryUsed() {
- return totalMem;
- }
-
- /**
- * {@inheritDoc}
- */
- public void resetAccessCount() {
- synchronized (cache) {
- accessCount = 0;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void setMaxMemorySize(long size) {
- synchronized (cache) {
- this.maxMem = size;
-
- // remove items, if too many
- if (totalMem > maxMem) {
- shrink();
- }
- }
- }
-
- private void shrink() {
- List<Map.Entry<ItemId, Entry>> list =
- new ArrayList<Map.Entry<ItemId, Entry>>(cache.entrySet());
- for (int i = list.size() - 1; totalMem > maxMem && i >= 0; i--) {
- Map.Entry<ItemId, Entry> last = list.get(i);
- totalMem -= last.getValue().size;
- cache.remove(last.getKey());
- }
- }
-
- /**
- * Set the cache access listener. Only one listener per cache is supported.
- *
- * @param listener the new listener
- */
- public void setAccessListener(CacheAccessListener listener) {
- this.accessListener = listener;
+ return cache.isEmpty();
}
/**
* {@inheritDoc}
*/
public void dispose() {
- synchronized (cache) {
- if (accessListener != null) {
- accessListener.disposeCache(this);
- }
- }
- }
-
-
- /**
- * Internal cache entry.
- */
- private static class Entry {
-
- private final ItemState state;
-
- private long size;
-
- public Entry(ItemState state) {
- this.state = state;
- this.size = 64 + state.calculateMemoryFootprint();
- }
-
- public void recalc() {
- size = 64 + state.calculateMemoryFootprint();
- }
+ cache.dispose();
}
}
Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ManagedMLRUItemStateCacheFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ManagedMLRUItemStateCacheFactory.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ManagedMLRUItemStateCacheFactory.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/ManagedMLRUItemStateCacheFactory.java Thu Oct 21 15:13:34 2010
@@ -41,10 +41,7 @@ public class ManagedMLRUItemStateCacheFa
* Create a new cache instance and link it to the cache manager.
*/
public ItemStateCache newItemStateCache() {
- MLRUItemStateCache cache = new MLRUItemStateCache();
- cacheMgr.add(cache);
- cache.setAccessListener(cacheMgr);
- return cache;
+ return new MLRUItemStateCache(cacheMgr);
}
}
Modified: jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=1026025&r1=1026024&r2=1026025&view=diff
==============================================================================
--- jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/branches/2.0/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Thu Oct 21 15:13:34 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;
}