You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2008/02/07 15:01:21 UTC
svn commit: r619416 - in
/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi:
ItemCache.java ItemCacheImpl.java ItemManager.java ItemManagerImpl.java
SessionImpl.java
Author: angela
Date: Thu Feb 7 06:01:18 2008
New Revision: 619416
URL: http://svn.apache.org/viewvc?rev=619416&view=rev
Log:
JCR-1011: JCR2SPI: add configurable cache for Item instances (ItemManager)
Added:
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java (with props)
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java
jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java?rev=619416&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java Thu Feb 7 06:01:18 2008
@@ -0,0 +1,43 @@
+/*
+ * 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.jcr2spi;
+
+import org.apache.jackrabbit.jcr2spi.state.ItemState;
+
+import javax.jcr.Item;
+
+/**
+ * <code>ItemCache</code>...
+ */
+public interface ItemCache extends ItemLifeCycleListener {
+
+ /**
+ * Returns the cached <code>Item</code> that belongs to the given
+ * <code>ItemState</code> or <code>null</code> if the cache does not
+ * contain that <code>Item</code>.
+ *
+ * @param state State of the item that should be retrieved.
+ * @return The item reference stored in the corresponding cache entry
+ * or <code>null</code> if there's no corresponding cache entry.
+ */
+ Item getItem(ItemState state);
+
+ /**
+ * Clear all entries in the ItemCache and free resources.
+ */
+ void clear();
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCache.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java?rev=619416&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java Thu Feb 7 06:01:18 2008
@@ -0,0 +1,166 @@
+/*
+ * 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.jcr2spi;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.jcr2spi.state.ItemState;
+import org.apache.jackrabbit.jcr2spi.util.Dumpable;
+import org.apache.commons.collections.map.LRUMap;
+
+import javax.jcr.Item;
+import javax.jcr.RepositoryException;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.PrintStream;
+
+/**
+ * <code>ItemCacheImpl</code>...
+ */
+public class ItemCacheImpl implements ItemCache, Dumpable {
+
+ private static Logger log = LoggerFactory.getLogger(ItemCacheImpl.class);
+
+ private final Map cache;
+
+ ItemCacheImpl(int maxSize) {
+ cache = new LRUMap(maxSize);
+ }
+
+ //----------------------------------------------------------< ItemCache >---
+ /**
+ * @see ItemCache#getItem(ItemState)
+ */
+ public Item getItem(ItemState state) {
+ return (Item) cache.get(state);
+ }
+
+ /**
+ * @see ItemCache#clear()
+ */
+ public void clear() {
+ cache.clear();
+ }
+
+ //----------------------------------------------< ItemLifeCycleListener >---
+ /**
+ * @see ItemLifeCycleListener#itemCreated(Item)
+ */
+ public void itemCreated(Item item) {
+ if (!(item instanceof ItemImpl)) {
+ String msg = "Incompatible Item object: " + ItemImpl.class.getName() + " expected.";
+ throw new IllegalArgumentException(msg);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("created item " + item);
+ }
+ // add instance to cache
+ cacheItem(((ItemImpl)item).getItemState(), item);
+ }
+
+ /**
+ * @see ItemLifeCycleListener#itemInvalidated(Item)
+ */
+ public void itemInvalidated(Item item) {
+ if (!(item instanceof ItemImpl)) {
+ String msg = "Incompatible Item object: " + ItemImpl.class.getName() + " expected.";
+ throw new IllegalArgumentException(msg);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("invalidated item " + item);
+ }
+ // remove instance from cache
+ evictItem(((ItemImpl)item).getItemState());
+ }
+
+ /**
+ * @see ItemLifeCycleListener#itemDestroyed(Item)
+ */
+ public void itemDestroyed(Item item) {
+ if (!(item instanceof ItemImpl)) {
+ String msg = "Incompatible Item object: " + ItemImpl.class.getName() + " expected.";
+ throw new IllegalArgumentException(msg);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("destroyed item " + item);
+ }
+ // we're no longer interested in this item
+ ((ItemImpl)item).removeLifeCycleListener(this);
+ // remove instance from cache
+ evictItem(((ItemImpl)item).getItemState());
+ }
+
+ //-------------------------------------------------< item cache methods >---
+ /**
+ * Puts the reference of an item in the cache with
+ * the item's path as the key.
+ *
+ * @param item the item to cache
+ */
+ private synchronized void cacheItem(ItemState state, Item item) {
+ if (cache.containsKey(state)) {
+ log.warn("overwriting cached item " + state);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("caching item " + state);
+ }
+ cache.put(state, item);
+ }
+
+ /**
+ * Removes a cache entry for a specific item.
+ *
+ * @param itemState state of the item to remove from the cache
+ */
+ private synchronized void evictItem(ItemState itemState) {
+ if (log.isDebugEnabled()) {
+ log.debug("removing item " + itemState + " from cache");
+ }
+ cache.remove(itemState);
+ }
+
+ //-----------------------------------------------------------< Dumpable >---
+ /**
+ * @see Dumpable#dump(PrintStream)
+ */
+ public void dump(PrintStream ps) {
+ Iterator iter = cache.keySet().iterator();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ Item item = (Item) cache.get(state);
+ if (item.isNode()) {
+ ps.print("Node: ");
+ } else {
+ ps.print("Property: ");
+ }
+ if (item.isNew()) {
+ ps.print("new ");
+ } else if (item.isModified()) {
+ ps.print("modified ");
+ } else {
+ ps.print("- ");
+ }
+ String path;
+ try {
+ path = item.getPath();
+ } catch (RepositoryException e) {
+ path = "-";
+ }
+ ps.println(state + "\t" + path + " (" + item + ")");
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java?rev=619416&r1=619415&r2=619416&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManager.java Thu Feb 7 06:01:18 2008
@@ -50,7 +50,7 @@
* If the parent <code>Session</code> is an <code>XASession</code>, there is
* one <code>ItemManager</code> instance per started global transaction.
*/
-public interface ItemManager extends ItemLifeCycleListener {
+public interface ItemManager {
/**
* Disposes this <code>ItemManager</code> and frees resources.
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java?rev=619416&r1=619415&r2=619416&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemManagerImpl.java Thu Feb 7 06:01:18 2008
@@ -23,6 +23,7 @@
import org.apache.jackrabbit.jcr2spi.state.ItemState;
import org.apache.jackrabbit.jcr2spi.state.NodeState;
import org.apache.jackrabbit.jcr2spi.state.PropertyState;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateCreationListener;
import org.apache.jackrabbit.jcr2spi.util.Dumpable;
import org.apache.jackrabbit.jcr2spi.util.LogUtil;
import org.apache.jackrabbit.jcr2spi.version.VersionHistoryImpl;
@@ -30,7 +31,6 @@
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.commons.collections.map.ReferenceMap;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -41,14 +41,14 @@
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Item;
+import javax.jcr.Workspace;
import java.io.PrintStream;
import java.util.Iterator;
-import java.util.Map;
/**
* <code>ItemManagerImpl</code> implements the <code>ItemManager</code> interface.
*/
-public class ItemManagerImpl implements Dumpable, ItemManager {
+public class ItemManagerImpl implements Dumpable, ItemManager, ItemStateCreationListener {
private static Logger log = LoggerFactory.getLogger(ItemManagerImpl.class);
@@ -63,19 +63,26 @@
* o.a.j.core the item state are copied to transient space for reading and
* will therefor not change upon transient modifications.
*/
- private Map itemCache;
+ private final ItemCache itemCache;
/**
* Creates a new per-session instance <code>ItemManagerImpl</code> instance.
*
* @param hierMgr HierarchyManager associated with the new instance
* @param session the session associated with the new instance
+ * @param cache the ItemCache to be used.
*/
- ItemManagerImpl(HierarchyManager hierMgr, SessionImpl session) {
+ ItemManagerImpl(HierarchyManager hierMgr, SessionImpl session, ItemCache cache) {
this.hierMgr = hierMgr;
this.session = session;
- /* Setup item cache with weak keys (ItemState) and weak values (Item).*/
- itemCache = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
+ itemCache = cache;
+
+ // start listening to creation of ItemStates upon batch-reading in the
+ // workspace item state factory.
+ Workspace wsp = session.getWorkspace();
+ if (wsp instanceof WorkspaceImpl) {
+ ((WorkspaceImpl) wsp).getItemStateFactory().addCreationListener(this);
+ }
}
//--------------------------------------------------------< ItemManager >---
@@ -83,6 +90,12 @@
* @see ItemManager#dispose()
*/
public void dispose() {
+ // stop listening
+ Workspace wsp = session.getWorkspace();
+ if (wsp instanceof WorkspaceImpl) {
+ ((WorkspaceImpl) wsp).getItemStateFactory().removeCreationListener(this);
+ }
+ // aftwards clear the cache.
itemCache.clear();
}
@@ -173,7 +186,7 @@
}
// first try to access item from cache
- Item item = retrieveItem(itemState);
+ Item item = itemCache.getItem(itemState);
// not yet in cache, need to create instance
if (item == null) {
// create instance of item
@@ -256,54 +269,6 @@
return new LazyItemIterator(this, propEntries);
}
- //----------------------------------------------< ItemLifeCycleListener >---
- /**
- * @see ItemLifeCycleListener#itemCreated(Item)
- */
- public void itemCreated(Item item) {
- if (!(item instanceof ItemImpl)) {
- String msg = "Incompatible Item object: " + ItemImpl.class.getName() + " expected.";
- throw new IllegalArgumentException(msg);
- }
- if (log.isDebugEnabled()) {
- log.debug("created item " + item);
- }
- // add instance to cache
- cacheItem(((ItemImpl)item).getItemState(), item);
- }
-
- /**
- * @see ItemLifeCycleListener#itemInvalidated(Item)
- */
- public void itemInvalidated(Item item) {
- if (!(item instanceof ItemImpl)) {
- String msg = "Incompatible Item object: " + ItemImpl.class.getName() + " expected.";
- throw new IllegalArgumentException(msg);
- }
- if (log.isDebugEnabled()) {
- log.debug("invalidated item " + item);
- }
- // remove instance from cache
- evictItem(((ItemImpl)item).getItemState());
- }
-
- /**
- * @see ItemLifeCycleListener#itemDestroyed(Item)
- */
- public void itemDestroyed(Item item) {
- if (!(item instanceof ItemImpl)) {
- String msg = "Incompatible Item object: " + ItemImpl.class.getName() + " expected.";
- throw new IllegalArgumentException(msg);
- }
- if (log.isDebugEnabled()) {
- log.debug("destroyed item " + item);
- }
- // we're no longer interested in this item
- ((ItemImpl)item).removeLifeCycleListener(this);
- // remove instance from cache
- evictItem(((ItemImpl)item).getItemState());
- }
-
//-----------------------------------------------------------< Dumpable >---
/**
* @see Dumpable#dump(PrintStream)
@@ -313,23 +278,10 @@
ps.println();
ps.println("Items in cache:");
ps.println();
- Iterator iter = itemCache.keySet().iterator();
- while (iter.hasNext()) {
- ItemState state = (ItemState) iter.next();
- Item item = (Item) itemCache.get(state);
- if (item.isNode()) {
- ps.print("Node: ");
- } else {
- ps.print("Property: ");
- }
- if (item.isNew()) {
- ps.print("new ");
- } else if (item.isModified()) {
- ps.print("modified ");
- } else {
- ps.print("- ");
- }
- ps.println(state + "\t" + LogUtil.safeGetJCRPath(state, session.getPathResolver()) + " (" + item + ")");
+ if (itemCache instanceof Dumpable) {
+ ((Dumpable) itemCache).dump(ps);
+ } else {
+ ps.println("ItemCache (" + itemCache.toString() + ")");
}
}
@@ -342,7 +294,7 @@
private NodeImpl createNodeInstance(NodeState state) throws RepositoryException {
// we want to be informed on life cycle changes of the new node object
// in order to maintain item cache consistency
- ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{this};
+ ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{itemCache};
// check special nodes
Name ntName = state.getNodeTypeName();
@@ -365,49 +317,32 @@
private PropertyImpl createPropertyInstance(PropertyState state) {
// we want to be informed on life cycle changes of the new property object
// in order to maintain item cache consistency
- ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{this};
+ ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{itemCache};
// create property object
PropertyImpl prop = new PropertyImpl(this, session, state, listeners);
return prop;
}
- //-------------------------------------------------< item cache methods >---
+ //------------------------------------------< ItemStateCreationListener >---
/**
- * Puts the reference of an item in the cache with
- * the item's path as the key.
*
- * @param item the item to cache
+ * @param state
*/
- private void cacheItem(ItemState state, Item item) {
- if (itemCache.containsKey(state)) {
- log.warn("overwriting cached item " + state);
- }
- if (log.isDebugEnabled()) {
- log.debug("caching item " + state);
+ public void created(ItemState state) {
+ if (state.isNode()) {
+ try {
+ createNodeInstance((NodeState) state);
+ } catch (RepositoryException e) {
+ // log warning and ignore
+ log.warn("Unable to create Node instance: " + e.getMessage());
+ }
+ } else {
+ createPropertyInstance((PropertyState) state);
}
- itemCache.put(state, item);
- }
-
- /**
- * Returns an item reference from the cache.
- *
- * @param state State of the item that should be retrieved.
- * @return the item reference stored in the corresponding cache entry
- * or <code>null</code> if there's no corresponding cache entry.
- */
- private Item retrieveItem(ItemState state) {
- return (Item) itemCache.get(state);
}
- /**
- * Removes a cache entry for a specific item.
- *
- * @param itemState state of the item to remove from the cache
- */
- private void evictItem(ItemState itemState) {
- if (log.isDebugEnabled()) {
- log.debug("removing item " + itemState + " from cache");
- }
- itemCache.remove(itemState);
+ public void statusChanged(ItemState state, int previousStatus) {
+ // nothing to do -> Item is listening to status changes and forces
+ // cleanup of cache entries through it's own status changes.
}
}
Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java?rev=619416&r1=619415&r2=619416&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/SessionImpl.java Thu Feb 7 06:01:18 2008
@@ -641,7 +641,9 @@
}
protected ItemManager createItemManager(HierarchyManager hierarchyManager) {
- return new ItemManagerImpl(hierarchyManager, this);
+ ItemCache cache = new ItemCacheImpl(1000); // TODO: make configurable
+ ItemManagerImpl imgr = new ItemManagerImpl(hierarchyManager, this, cache);
+ return imgr;
}
//---------------------------------------------------< ManagerProvider > ---