You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2005/08/02 18:56:16 UTC
svn commit: r227042 - in
/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core: ./
state/ virtual/
Author: stefan
Date: Tue Aug 2 09:56:07 2005
New Revision: 227042
URL: http://svn.apache.org/viewcvs?rev=227042&view=rev
Log:
core.state:
replaced abstract ItemStateCache with interface of same name and added ItemStateMap, ItemStateReferenceMap, ItemStateReferenceCache & LRUItemStateCache which provide cleaner semantics and improved memory usage behaviour
Added:
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateMap.java (with props)
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java (with props)
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceMap.java (with props)
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LRUItemStateCache.java (with props)
Modified:
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/WorkspaceImpl.java Tue Aug 2 09:56:07 2005
@@ -62,7 +62,6 @@
import javax.jcr.version.VersionHistory;
import java.io.IOException;
import java.io.InputStream;
-import java.io.PrintStream;
import java.util.HashMap;
import java.util.Iterator;
@@ -155,19 +154,6 @@
*/
public TransactionalItemStateManager getItemStateManager() {
return stateMgr;
- }
-
- /**
- * Dumps the state of this <code>WorkspaceImpl</code> instance
- * (used for diagnostic purposes).
- *
- * @param ps
- * @throws RepositoryException
- */
- public void dump(PrintStream ps) throws RepositoryException {
- ps.println("Workspace: " + wspConfig.getName() + " (" + this + ")");
- ps.println();
- stateMgr.dump(ps);
}
/**
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateCache.java Tue Aug 2 09:56:07 2005
@@ -16,205 +16,88 @@
*/
package org.apache.jackrabbit.core.state;
-import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.core.ItemId;
-import org.apache.log4j.Logger;
-import java.io.PrintStream;
-import java.util.ArrayList;
+import java.util.Set;
import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
/**
* An <code>ItemStateCache</code> maintains a cache of <code>ItemState</code>
* instances.
*/
-public abstract class ItemStateCache {
- private static Logger log = Logger.getLogger(ItemStateCache.class);
+public interface ItemStateCache {
+ /**
+ * Returns <code>true</code> if this cache contains an <code>ItemState</code>
+ * object with the specified <code>id</code>.
+ *
+ * @param id id of <code>ItemState</code> object whose presence should be
+ * tested.
+ * @return <code>true</code> if there's a corresponding cache entry,
+ * otherwise <code>false</code>.
+ */
+ boolean isCached(ItemId id);
/**
- * A cache for <code>ItemState</code> instances
+ * Returns the <code>ItemState</code> object with the specified
+ * <code>id</code> if it is present or <code>null</code> if no entry exists
+ * with that <code>id</code>.
+ *
+ * @param id the id of the <code>ItemState</code> object to be returned.
+ * @return the <code>ItemState</code> object with the specified
+ * <code>id</code> or or <code>null</code> if no entry exists
+ * with that <code>id</code>
*/
- private final Map cache;
+ ItemState retrieve(ItemId id);
/**
- * Monitor for cache object. Derived classes should synchronize on
- * this monitor when the identity of cached objects is critical, i.e.
- * when object should not be cached more than once.
+ * Stores the specified <code>ItemState</code> object in the map
+ * using its <code>ItemId</code> as the key.
+ *
+ * @param state the <code>ItemState</code> object to cache
*/
- protected final Object cacheMonitor = new Object();
+ void cache(ItemState state);
/**
- * Creates a new <code>ItemStateCache</code> that will use instance
- * hard references to keys and soft references to values.
+ * Removes the <code>ItemState</code> object with the specified id from
+ * this cache if it is present.
+ *
+ * @param id the id of the <code>ItemState</code> object which should be
+ * removed from this cache.
*/
- protected ItemStateCache() {
- // setup cache with soft references to ItemState instances
- this(ReferenceMap.HARD, ReferenceMap.SOFT);
- }
+ void evict(ItemId id);
/**
- * Creates a new <code>ItemStateCache</code> instance that will use the
- * specified types of references.
+ * Clears all entries from this cache.
+ */
+ void evictAll();
+
+ /**
+ * Returns <code>true</code> if this cache contains no entries.
*
- * @param keyType the type of reference to use for keys (i.e. the item paths)
- * @param valueType the type of reference to use for values (i.e. the item-datas)
- * @see ReferenceMap#HARD
- * @see ReferenceMap#SOFT
- * @see ReferenceMap#WEAK
+ * @return <code>true</code> if this cache contains no entries.
*/
- protected ItemStateCache(int keyType, int valueType) {
- cache = new ReferenceMap(keyType, valueType);
- }
+ boolean isEmpty();
/**
- * Checks if there's already a corresponding cache entry for
- * <code>id</code>.
+ * Returns the number of entries in this cache.
*
- * @param id id of a <code>ItemState</code> object
- * @return true if there's a corresponding cache entry, otherwise false.
+ * @return number of entries in this cache.
*/
- protected boolean isCached(ItemId id) {
- return cache.containsKey(id);
- }
+ int size();
/**
- * Returns an item-state reference from the cache.
+ * Returns an unmodifiable set view of the keys (i.e. <code>ItemId</code>
+ * objects) of the cached entries.
*
- * @param id the id of the <code>ItemState</code> object whose
- * reference should be retrieved from the cache.
- * @return the <code>ItemState</code> reference stored in the corresponding
- * cache entry or <code>null</code> if there's no corresponding
- * cache entry.
+ * @return a set view of the keys of the cached entries.
*/
- protected ItemState retrieve(ItemId id) {
- return (ItemState) cache.get(id);
- }
+ Set keySet();
/**
- * Puts the reference to an <code>ItemState</code> object in the cache using its path as the key.
+ * Returns an unmodifiable collection view of the values (i.e.
+ * <code>ItemState</code> objects) contained in this cache.
*
- * @param state the <code>ItemState</code> object to cache
+ * @return a collection view of the values contained in this cache.
*/
- protected void cache(ItemState state) {
- ItemId id = state.getId();
- if (cache.containsKey(id)) {
- log.warn("overwriting cached entry " + id);
- }
- if (log.isDebugEnabled()) {
- log.debug("caching " + id);
- }
- cache.put(id, state);
- }
-
- /**
- * Removes a cache entry for a specific id.
- *
- * @param id the id of the <code>ItemState</code> object whose
- * reference should be removed from the cache.
- */
- protected void evict(ItemId id) {
- if (log.isDebugEnabled()) {
- log.debug("removing entry " + id + " from cache");
- }
- cache.remove(id);
- }
-
- /**
- * Clears all entries from the cache.
- */
- protected void evictAll() {
- if (log.isDebugEnabled()) {
- log.debug("removing all entries from cache");
- }
- cache.clear();
- }
-
- /**
- * Returns <code>true</code> if the cache contains no entries.
- *
- * @return <code>true</code> if the cache contains no entries.
- */
- protected boolean isEmpty() {
- return cache.isEmpty();
- }
-
- /**
- * Returns the number of entries in the cache.
- *
- * @return number of entries in the cache.
- */
- protected int size() {
- return cache.size();
- }
-
- /**
- * Returns an iterator of the keys (i.e. <code>ItemId</code> objects)
- * of the cached entries.
- *
- * @return an iterator of the keys of the cached entries.
- */
- protected Iterator keys() {
- // use temp collection to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(cache.keySet());
- return tmp.iterator();
- }
-
- /**
- * Returns an iterator of the entries (i.e. <code>ItemState</code> objects)
- * in the cache.
- *
- * @return an iterator of the entries in the cache.
- */
- protected Iterator entries() {
- // use temp collection to avoid ConcurrentModificationException
- Collection tmp = new ArrayList(cache.values());
- return tmp.iterator();
- }
-
- /**
- * Dumps the state of this <code>ItemStateCache</code> instance
- * (used for diagnostic purposes).
- *
- * @param ps
- */
- void dump(PrintStream ps) {
- ps.println("entries in cache:");
- ps.println();
- Iterator iter = keys();
- while (iter.hasNext()) {
- ItemId id = (ItemId) iter.next();
- ItemState state = retrieve(id);
- dumpItemState(id, state, ps);
- }
- }
-
- private void dumpItemState(ItemId id, ItemState state, PrintStream ps) {
- ps.print(state.isNode() ? "Node: " : "Prop: ");
- switch (state.getStatus()) {
- case ItemState.STATUS_EXISTING:
- ps.print("[existing] ");
- break;
- case ItemState.STATUS_EXISTING_MODIFIED:
- ps.print("[existing, modified] ");
- break;
- case ItemState.STATUS_EXISTING_REMOVED:
- ps.print("[existing, removed] ");
- break;
- case ItemState.STATUS_NEW:
- ps.print("[new] ");
- break;
- case ItemState.STATUS_STALE_DESTROYED:
- ps.print("[stale, destroyed] ");
- break;
- case ItemState.STATUS_STALE_MODIFIED:
- ps.print("[stale, modified] ");
- break;
- case ItemState.STATUS_UNDEFINED:
- ps.print("[undefined] ");
- break;
- }
- ps.println(id + " (" + state + ")");
- }
+ Collection values();
}
Added: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateMap.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateMap.java?rev=227042&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateMap.java (added)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateMap.java Tue Aug 2 09:56:07 2005
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.log4j.Logger;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * An <code>ItemStateMap</code> stores <code>ItemState</code> instances using
+ * their <code>ItemId</code>s as key.
+ */
+public class ItemStateMap {
+ private static Logger log = Logger.getLogger(ItemStateMap.class);
+
+ /**
+ * the map backing this <code>ItemStateMap</code> instance
+ */
+ protected final Map map;
+
+ /**
+ * Creates a new HashMap-backed <code>ItemStateMap</code> instance.
+ */
+ public ItemStateMap() {
+ this(new HashMap());
+ }
+
+ /**
+ * Protected constructor for specialized subclasses
+ *
+ * @param map <code>Map</code> implementation to be used as backing store.
+ */
+ protected ItemStateMap(Map map) {
+ this.map = map;
+ }
+
+ //-------------------------------------------------------< public methods >
+ /**
+ * Returns <code>true</code> if this map contains an <code>ItemState</code>
+ * object with the specified <code>id</code>.
+ *
+ * @param id id of <code>ItemState</code> object whose presence should be
+ * tested.
+ * @return <code>true</code> if there's a corresponding map entry,
+ * otherwise <code>false</code>.
+ */
+ public boolean contains(ItemId id) {
+ return map.containsKey(id);
+ }
+
+ /**
+ * Returns the <code>ItemState</code> object with the specified
+ * <code>id</code> if it is present or <code>null</code> if no entry exists
+ * with that <code>id</code>.
+ *
+ * @param id the id of the <code>ItemState</code> object to be returned.
+ * @return the <code>ItemState</code> object with the specified
+ * <code>id</code> or or <code>null</code> if no entry exists
+ * with that <code>id</code>
+ */
+ public ItemState get(ItemId id) {
+ return (ItemState) map.get(id);
+ }
+
+ /**
+ * Stores the specified <code>ItemState</code> object in the map
+ * using its <code>ItemId</code> as the key.
+ *
+ * @param state the <code>ItemState</code> object to store
+ */
+ public void put(ItemState state) {
+ ItemId id = state.getId();
+ if (map.containsKey(id)) {
+ log.warn("overwriting map entry " + id);
+ }
+ map.put(id, state);
+ }
+
+ /**
+ * Removes the <code>ItemState</code> object with the specified id from
+ * this map if it is present.
+ *
+ * @param id the id of the <code>ItemState</code> object which should be
+ * removed from this map.
+ */
+ public void remove(ItemId id) {
+ map.remove(id);
+ }
+
+ /**
+ * Removes all entries from this map.
+ */
+ public void clear() {
+ map.clear();
+ }
+
+ /**
+ * Returns <code>true</code> if the map contains no entries.
+ *
+ * @return <code>true</code> if the map contains no entries.
+ */
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /**
+ * Returns the number of entries in the map.
+ *
+ * @return number of entries in the map.
+ */
+ public int size() {
+ return map.size();
+ }
+
+ /**
+ * Returns an unmodifiable set view of the keys (i.e. <code>ItemId</code>
+ * objects) contained in this map.
+ *
+ * @return a set view of the keys contained in this map.
+ */
+ public Set keySet() {
+ return Collections.unmodifiableSet(map.keySet());
+ }
+
+ /**
+ * Returns an unmodifiable collection view of the values (i.e.
+ * <code>ItemState</code> objects) contained in this map.
+ *
+ * @return a collection view of the values contained in this map.
+ */
+ public Collection values() {
+ return Collections.unmodifiableCollection(map.values());
+ }
+
+ //-------------------------------------------------------< implementation >
+ /**
+ * Dumps the state of this <code>ItemStateMap</code> instance
+ * (used for diagnostic purposes).
+ *
+ * @param ps
+ */
+ protected void dump(PrintStream ps) {
+ ps.println("map entries:");
+ ps.println();
+ Iterator iter = keySet().iterator();
+ while (iter.hasNext()) {
+ ItemId id = (ItemId) iter.next();
+ ItemState state = get(id);
+ dumpItemState(id, state, ps);
+ }
+ }
+
+ private void dumpItemState(ItemId id, ItemState state, PrintStream ps) {
+ ps.print(state.isNode() ? "Node: " : "Prop: ");
+ switch (state.getStatus()) {
+ case ItemState.STATUS_EXISTING:
+ ps.print("[existing] ");
+ break;
+ case ItemState.STATUS_EXISTING_MODIFIED:
+ ps.print("[existing, modified] ");
+ break;
+ case ItemState.STATUS_EXISTING_REMOVED:
+ ps.print("[existing, removed] ");
+ break;
+ case ItemState.STATUS_NEW:
+ ps.print("[new] ");
+ break;
+ case ItemState.STATUS_STALE_DESTROYED:
+ ps.print("[stale, destroyed] ");
+ break;
+ case ItemState.STATUS_STALE_MODIFIED:
+ ps.print("[stale, modified] ");
+ break;
+ case ItemState.STATUS_UNDEFINED:
+ ps.print("[undefined] ");
+ break;
+ }
+ ps.println(id + " (" + state + ")");
+ }
+}
Propchange: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java?rev=227042&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java (added)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java Tue Aug 2 09:56:07 2005
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.log4j.Logger;
+
+import java.util.Set;
+import java.util.Collections;
+import java.util.Collection;
+
+/**
+ * <code>ItemStateReferenceCache</code> internally consists of 2 components:
+ * <ul>
+ * <li>an <code>ItemStateReferenceMap<code> serving as the primary (or main)
+ * cache; it holds weak references to <code>ItemState</code> instances. This
+ * <code>ItemStateCache</code> implementation directly represents the
+ * contents of the primary cache, i.e. {@link #isCached(ItemId)},
+ * {@link #retrieve(ItemId)}}, {@link #size()} etc. only refer to the contents
+ * of the primary cache.</li>
+ * <li>an <code>ItemStateCache</code> implementing a custom eviction policy and
+ * serving as the secondary (or auxiliary) cache; entries that are automatically
+ * flusehd from this secondary cache through its eviction policy (LRU, etc.)
+ * will be indirectly flushed from the primary (reference) cache by the garbage
+ * collector if they are thus rendered weakly reachable.
+ * </li>
+ * </ul>
+ */
+public class ItemStateReferenceCache implements ItemStateCache {
+
+ /** Logger instance */
+ private static Logger log = Logger.getLogger(LRUItemStateCache.class);
+
+ /**
+ * primary cache storing weak references to <code>ItemState</code>
+ * instances.
+ */
+ private final ItemStateReferenceMap refs;
+ /**
+ * 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.
+ */
+ private final ItemStateCache cache;
+
+ /**
+ * Creates a new <code>ItemStateReferenceCache</code> that uses a
+ * <code>LRUItemStateCache</code> instance as internal secondary
+ * cache.
+ */
+ public ItemStateReferenceCache() {
+ this(new LRUItemStateCache());
+ }
+
+ /**
+ * Creates a new <code>ItemStateReferenceCache</code> that uses the
+ * specified <code>ItemStateCache</code> instance as internal secondary
+ * cache.
+ *
+ * @param cache secondary cache implementing a custom eviction policy
+ */
+ public ItemStateReferenceCache(ItemStateCache cache) {
+ this.cache = cache;
+ refs = new ItemStateReferenceMap();
+ }
+
+ //-------------------------------------------------------< ItemStateCache >
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isCached(ItemId id) {
+ // check primary cache
+ return refs.contains(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ItemState retrieve(ItemId id) {
+ // fake call to update stats of secondary cache
+ cache.retrieve(id);
+
+ // retrieve from primary cache
+ return (ItemState) refs.get(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void cache(ItemState state) {
+ ItemId id = state.getId();
+ if (refs.contains(id)) {
+ log.warn("overwriting cached entry " + id);
+ }
+ // fake call to update stats of secondary cache
+ cache.cache(state);
+ // store weak reference in primary cache
+ refs.put(state);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void evict(ItemId id) {
+ // fake call to update stats of secondary cache
+ cache.evict(id);
+ // remove from primary cache
+ refs.remove(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void evictAll() {
+ // fake call to update stats of secondary cache
+ cache.evictAll();
+ // remove all weak references from primary cache
+ refs.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty() {
+ // check primary cache
+ return refs.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int size() {
+ // size of primary cache
+ return refs.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set keySet() {
+ return Collections.unmodifiableSet(refs.keySet());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection values() {
+ return Collections.unmodifiableCollection(refs.values());
+ }
+}
Propchange: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceMap.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceMap.java?rev=227042&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceMap.java (added)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceMap.java Tue Aug 2 09:56:07 2005
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.commons.collections.map.ReferenceMap;
+
+/**
+ * <code>ItemStateReferenceMap</code> is a specialized <code>ItemStateMap</code>
+ * that stores <code>WEAK</code> references to <code>ItemState</code> objects.
+ */
+public class ItemStateReferenceMap extends ItemStateMap {
+
+ /**
+ * Creates a new ReferenceMap-backed <code>ItemStateReferenceMap</code>
+ * instance that stores <code>WEAK</code> references to
+ * <code>ItemState</code> objects. An entry in this map is automatically
+ * removed when the garbage collector determines that its value
+ * (i.e. an <code>ItemState</code> object) is only weakly reachable.
+ */
+ public ItemStateReferenceMap() {
+ super(new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK));
+ }
+}
Propchange: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/ItemStateReferenceMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LRUItemStateCache.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LRUItemStateCache.java?rev=227042&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LRUItemStateCache.java (added)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LRUItemStateCache.java Tue Aug 2 09:56:07 2005
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.log4j.Logger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * An <code>ItemStateCache</code> implementation that internally uses a
+ * {@link LRUMap} to maintain a cache of <code>ItemState</code> objects.
+ */
+public class LRUItemStateCache implements ItemStateCache {
+ /** Logger instance */
+ private static Logger log = Logger.getLogger(LRUItemStateCache.class);
+
+ /** default maximum size of this cache */
+ public static final int DEFAULT_MAX_SIZE = 5000;
+
+ /**
+ * A cache for <code>ItemState</code> instances
+ */
+ private final LRUMap cache;
+
+ /**
+ * Constructs a new, empty <code>ItemStateCache</code> with a maximum size
+ * of 1000 and a load factor of 0.8.
+ */
+ public LRUItemStateCache() {
+ this(DEFAULT_MAX_SIZE);
+ }
+
+ /**
+ * Constructs a new, empty <code>ItemStateCache</code> with the specified
+ * maximum size.
+ *
+ * @param maxSize the maximum size of the cache, -1 for no limit,
+ */
+ public LRUItemStateCache(int maxSize) {
+ // setup cache
+ cache = new LRUMap(maxSize, true);
+ }
+
+ //-------------------------------------------------------< ItemStateCache >
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isCached(ItemId id) {
+ return cache.containsKey(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ItemState retrieve(ItemId id) {
+ return (ItemState) cache.get(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void cache(ItemState state) {
+ ItemId id = state.getId();
+ if (cache.containsKey(id)) {
+ log.warn("overwriting cached entry " + id);
+ }
+ cache.put(id, state);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void evict(ItemId id) {
+ cache.remove(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void evictAll() {
+ cache.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isEmpty() {
+ return cache.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int size() {
+ return cache.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set keySet() {
+ return Collections.unmodifiableSet(cache.keySet());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection values() {
+ return Collections.unmodifiableCollection(cache.values());
+ }
+}
Propchange: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LRUItemStateCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java Tue Aug 2 09:56:07 2005
@@ -25,13 +25,12 @@
import org.apache.log4j.Logger;
import javax.jcr.RepositoryException;
-import java.io.PrintStream;
/**
* Local <code>ItemStateManager</code> that isolates changes to
* persistent states from other clients.
*/
-public class LocalItemStateManager extends ItemStateCache
+public class LocalItemStateManager
implements UpdatableItemStateManager, ItemStateListener {
/**
@@ -40,6 +39,12 @@
private static Logger log = Logger.getLogger(LocalItemStateManager.class);
/**
+ * cache of weak references to ItemState objects issued by this
+ * ItemStateManager
+ */
+ private final ItemStateReferenceCache cache;
+
+ /**
* Shared item state manager
*/
protected final SharedItemStateManager sharedStateMgr;
@@ -70,7 +75,9 @@
* manager. Version item states are not associated with a specific workspace
* instance.
*/
- public LocalItemStateManager(SharedItemStateManager sharedStateMgr, WorkspaceImpl wspImpl) {
+ public LocalItemStateManager(SharedItemStateManager sharedStateMgr,
+ WorkspaceImpl wspImpl) {
+ cache = new ItemStateReferenceCache();
this.sharedStateMgr = sharedStateMgr;
this.wspImpl = wspImpl;
}
@@ -80,7 +87,7 @@
*/
public void dispose() {
// clear cache
- evictAll();
+ cache.evictAll();
}
/**
@@ -101,7 +108,7 @@
state = new NodeState(state, state.getStatus(), false);
// put it in cache
- cache(state);
+ cache.cache(state);
// register as listener
state.addListener(this);
@@ -126,25 +133,13 @@
state = new PropertyState(state, state.getStatus(), false);
// put it in cache
- cache(state);
+ cache.cache(state);
// register as listener
state.addListener(this);
return state;
}
- /**
- * Dumps the state of this <code>LocalItemStateManager</code> instance
- * (used for diagnostic purposes).
- *
- * @param ps
- */
- public void dump(PrintStream ps) {
- ps.println("LocalItemStateManager (" + this + ")");
- ps.println();
- super.dump(ps);
- }
-
//-----------------------------------------------------< ItemStateManager >
/**
* {@inheritDoc}
@@ -159,8 +154,8 @@
}
// check cache. synchronized to ensure an entry is not created twice.
- synchronized (cacheMonitor) {
- state = retrieve(id);
+ synchronized (cache) {
+ state = cache.retrieve(id);
if (state == null) {
// regular behaviour
if (id.denotesNode()) {
@@ -189,7 +184,7 @@
}
// check cache
- if (isCached(id)) {
+ if (cache.isCached(id)) {
return true;
}
@@ -375,7 +370,7 @@
public void stateDestroyed(ItemState destroyed) {
destroyed.removeListener(this);
- evict(destroyed.getId());
+ cache.evict(destroyed.getId());
}
/**
@@ -384,6 +379,6 @@
public void stateDiscarded(ItemState discarded) {
discarded.removeListener(this);
- evict(discarded.getId());
+ cache.evict(discarded.getId());
}
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java Tue Aug 2 09:56:07 2005
@@ -93,11 +93,6 @@
public void dump(PrintStream ps) {
ps.println("SessionItemStateManager (" + this + ")");
ps.println();
- // FIXME hack!
- if (persistentStateMgr instanceof ItemStateCache) {
- ((ItemStateCache) persistentStateMgr).dump(ps);
- ps.println();
- }
transientStateMgr.dump(ps);
ps.println();
}
@@ -292,7 +287,7 @@
* @return
*/
public boolean hasAnyTransientItemStates() {
- return !transientStateMgr.isEmpty();
+ return transientStateMgr.hasAnyItemStates();
}
/**
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Tue Aug 2 09:56:07 2005
@@ -34,7 +34,6 @@
import javax.jcr.PropertyType;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
-import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
@@ -46,7 +45,7 @@
* <code>PersistenceManager</code>. Objects returned by this item state
* manager are shared among all sessions.
*/
-public class SharedItemStateManager extends ItemStateCache
+public class SharedItemStateManager
implements ItemStateManager, ItemStateListener {
/**
@@ -55,9 +54,15 @@
private static Logger log = Logger.getLogger(SharedItemStateManager.class);
/**
- * Persistence Manager to use for loading and storing items
+ * cache of weak references to ItemState objects issued by this
+ * ItemStateManager
*/
- protected final PersistenceManager persistMgr;
+ private final ItemStateReferenceCache cache;
+
+ /**
+ * Persistence Manager used for loading and storing items
+ */
+ private final PersistenceManager persistMgr;
/**
* Keep a hard reference to the root node state
@@ -67,12 +72,14 @@
/**
* Virtual item state providers
*/
- private VirtualItemStateProvider[] virtualProviders = new VirtualItemStateProvider[0];
+ private VirtualItemStateProvider[] virtualProviders = new
+ VirtualItemStateProvider[0];
/**
* Read-/Write-Lock to synchronize access on this item state manager.
*/
- private final ReadWriteLock rwLock = new ReentrantWriterPreferenceReadWriteLock();
+ private final ReadWriteLock rwLock =
+ new ReentrantWriterPreferenceReadWriteLock();
/**
* Creates a new <code>SharedItemStateManager</code> instance.
@@ -85,149 +92,17 @@
String rootNodeUUID,
NodeTypeRegistry ntReg)
throws ItemStateException {
-
+ cache = new ItemStateReferenceCache();
this.persistMgr = persistMgr;
try {
- root = getNodeState(new NodeId(rootNodeUUID));
+ root = (NodeState) getNonVirtualItemState(new NodeId(rootNodeUUID));
} catch (NoSuchItemStateException e) {
// create root node
root = createRootNodeState(rootNodeUUID, ntReg);
}
}
- /**
- * Disposes this <code>SharedItemStateManager</code> and frees resources.
- */
- public void dispose() {
- // clear cache
- evictAll();
- }
-
- /**
- * Adds a new virtual item state provider.<p/>
- * NOTE: This method is not synchronized, because it is called right after
- * creation only by the same thread and therefore concurrency issues
- * do not occur. Should this ever change, the synchronization status
- * has to be re-examined.
- * @param prov
- */
- public void addVirtualItemStateProvider(VirtualItemStateProvider prov) {
- VirtualItemStateProvider[] provs = new VirtualItemStateProvider[virtualProviders.length + 1];
- System.arraycopy(virtualProviders, 0, provs, 0, virtualProviders.length);
- provs[virtualProviders.length] = prov;
- virtualProviders = provs;
- }
-
- /**
- * Create root node state
- * @param rootNodeUUID root node UUID
- * @param ntReg node type registry
- * @return root node state
- * @throws ItemStateException if an error occurs
- */
- private NodeState createRootNodeState(String rootNodeUUID,
- NodeTypeRegistry ntReg)
- throws ItemStateException {
-
- NodeState rootState = createInstance(rootNodeUUID, Constants.REP_ROOT, null);
-
- // FIXME need to manually setup root node by creating mandatory jcr:primaryType property
- // @todo delegate setup of root node to NodeTypeInstanceHandler
-
- // id of the root node's definition
- NodeDefId nodeDefId;
- // definition of jcr:primaryType property
- PropDef propDef;
- try {
- nodeDefId = ntReg.getRootNodeDef().getId();
- EffectiveNodeType ent = ntReg.getEffectiveNodeType(Constants.REP_ROOT);
- propDef = ent.getApplicablePropertyDef(Constants.JCR_PRIMARYTYPE,
- PropertyType.NAME, false);
- } catch (NoSuchNodeTypeException nsnte) {
- String msg = "internal error: failed to create root node";
- log.error(msg, nsnte);
- throw new ItemStateException(msg, nsnte);
- } catch (ConstraintViolationException cve) {
- String msg = "internal error: failed to create root node";
- log.error(msg, cve);
- throw new ItemStateException(msg, cve);
- }
- rootState.setDefinitionId(nodeDefId);
-
- // create jcr:primaryType property
- rootState.addPropertyName(propDef.getName());
-
- PropertyState prop = createInstance(propDef.getName(), rootNodeUUID);
- prop.setValues(new InternalValue[]{InternalValue.create(Constants.REP_ROOT)});
- prop.setType(propDef.getRequiredType());
- prop.setMultiValued(propDef.isMultiple());
- prop.setDefinitionId(propDef.getId());
-
- ChangeLog changeLog = new ChangeLog();
- changeLog.added(rootState);
- changeLog.added(prop);
-
- persistMgr.store(changeLog);
- changeLog.persisted();
-
- return rootState;
- }
-
- /**
- * Dumps the state of this <code>SharedItemStateManager</code> instance
- * (used for diagnostic purposes).
- *
- * @param ps
- */
- public void dump(PrintStream ps) {
- ps.println("SharedItemStateManager (" + this + ")");
- ps.println();
- super.dump(ps);
- }
-
- /**
- * @param id
- * @return
- * @throws NoSuchItemStateException
- * @throws ItemStateException
- */
- private NodeState getNodeState(NodeId id)
- throws NoSuchItemStateException, ItemStateException {
-
- // load from persisted state
- NodeState state = persistMgr.load(id);
- state.setStatus(ItemState.STATUS_EXISTING);
-
- // put it in cache
- cache(state);
-
- // register as listener
- state.addListener(this);
- return state;
- }
-
- /**
- * @param id
- * @return
- * @throws NoSuchItemStateException
- * @throws ItemStateException
- */
- private PropertyState getPropertyState(PropertyId id)
- throws NoSuchItemStateException, ItemStateException {
-
- // load from persisted state
- PropertyState state = persistMgr.load(id);
- state.setStatus(ItemState.STATUS_EXISTING);
-
- // put it in cache
- cache(state);
-
- // register as listener
- state.addListener(this);
- return state;
- }
-
//-----------------------------------------------------< ItemStateManager >
/**
* {@inheritDoc}
@@ -261,28 +136,6 @@
}
/**
- * returns the item state for the given id without considering virtual
- * item state providers.
- */
- private ItemState getNonVirtualItemState(ItemId id)
- throws NoSuchItemStateException, ItemStateException {
-
- // check cache. synchronized to ensure an entry is not created twice.
- synchronized (cacheMonitor) {
- ItemState state = retrieve(id);
- if (state == null) {
- // regular behaviour
- if (id.denotesNode()) {
- state = getNodeState((NodeId) id);
- } else {
- state = getPropertyState((PropertyId) id);
- }
- }
- return state;
- }
- }
-
- /**
* {@inheritDoc}
*/
public boolean hasItemState(ItemId id) {
@@ -294,7 +147,7 @@
}
try {
- if (isCached(id)) {
+ if (cache.isCached(id)) {
return true;
}
@@ -321,26 +174,6 @@
}
/**
- * Checks if this item state manager has the given item state without
- * considering the virtual item state managers.
- */
- private boolean hasNonVirtualItemState(ItemId id) {
- if (isCached(id)) {
- return true;
- }
-
- try {
- if (id.denotesNode()) {
- return persistMgr.exists((NodeId) id);
- } else {
- return persistMgr.exists((PropertyId) id);
- }
- } catch (ItemStateException ise) {
- return false;
- }
- }
-
- /**
* {@inheritDoc}
*/
public NodeReferences getNodeReferences(NodeReferencesId id)
@@ -403,100 +236,60 @@
return false;
}
- //-------------------------------------------------------- other operations
-
+ //----------------------------------------------------< ItemStateListener >
/**
- * Create a new node state instance
- *
- * @param uuid uuid
- * @param nodeTypeName node type name
- * @param parentUUID parent UUID
- * @return new node state instance
+ * {@inheritDoc}
*/
- private NodeState createInstance(String uuid, QName nodeTypeName,
- String parentUUID) {
-
- NodeState state = persistMgr.createNew(new NodeId(uuid));
- state.setNodeTypeName(nodeTypeName);
- state.setParentUUID(parentUUID);
- state.setStatus(ItemState.STATUS_NEW);
- state.addListener(this);
-
- return state;
+ public void stateCreated(ItemState created) {
+ cache.cache(created);
}
/**
- * Create a new node state instance
- *
- * @param other other state associated with new instance
- * @return new node state instance
+ * {@inheritDoc}
*/
- private ItemState createInstance(ItemState other) {
- if (other.isNode()) {
- NodeState ns = (NodeState) other;
- return createInstance(ns.getUUID(), ns.getNodeTypeName(), ns.getParentUUID());
- } else {
- PropertyState ps = (PropertyState) other;
- return createInstance(ps.getName(), ps.getParentUUID());
- }
+ public void stateModified(ItemState modified) {
+ // not interested
}
/**
- * Create a new property state instance
- *
- * @param propName property name
- * @param parentUUID parent UUID
- * @return new property state instance
+ * {@inheritDoc}
*/
- PropertyState createInstance(QName propName, String parentUUID) {
- PropertyState state = persistMgr.createNew(new PropertyId(parentUUID, propName));
- state.setStatus(ItemState.STATUS_NEW);
- state.addListener(this);
-
- return state;
+ public void stateDestroyed(ItemState destroyed) {
+ destroyed.removeListener(this);
+ cache.evict(destroyed.getId());
}
/**
- * Load item state from persistent storage.
- * @param id item id
- * @return item state
+ * {@inheritDoc}
*/
- private ItemState loadItemState(ItemId id)
- throws NoSuchItemStateException, ItemStateException {
-
- if (id.denotesNode()) {
- return persistMgr.load((NodeId) id);
- } else {
- return persistMgr.load((PropertyId) id);
- }
+ public void stateDiscarded(ItemState discarded) {
+ discarded.removeListener(this);
+ cache.evict(discarded.getId());
}
+ //-------------------------------------------------< misc. public methods >
/**
- * Check targets of modified node references exist.
- * @param log change log
- * @throws ItemStateException if some target was not found
+ * Disposes this <code>SharedItemStateManager</code> and frees resources.
*/
- protected void checkTargetsExist(ChangeLog log) throws ItemStateException {
- Iterator iter = log.modifiedRefs();
- while (iter.hasNext()) {
- NodeReferences refs = (NodeReferences) iter.next();
- NodeId id = new NodeId(refs.getUUID());
+ public void dispose() {
+ // clear cache
+ cache.evictAll();
+ }
- for (int i = 0; i < virtualProviders.length; i++) {
- VirtualItemStateProvider provider = virtualProviders[i];
- if (provider.hasItemState(id)) {
- refs = null;
- break;
- }
- }
- if (refs != null && refs.hasReferences()) {
- if (!log.has(id) && !hasItemState(id)) {
- String msg = "Target node " + id
- + " of REFERENCE property does not exist";
- throw new ItemStateException(msg);
- }
- }
- }
+ /**
+ * Adds a new virtual item state provider.<p/>
+ * NOTE: This method is not synchronized, because it is called right after
+ * creation only by the same thread and therefore concurrency issues
+ * do not occur. Should this ever change, the synchronization status
+ * has to be re-examined.
+ * @param prov
+ */
+ public void addVirtualItemStateProvider(VirtualItemStateProvider prov) {
+ VirtualItemStateProvider[] provs =
+ new VirtualItemStateProvider[virtualProviders.length + 1];
+ System.arraycopy(virtualProviders, 0, provs, 0, virtualProviders.length);
+ provs[virtualProviders.length] = prov;
+ virtualProviders = provs;
}
/**
@@ -664,58 +457,220 @@
}
}
+ //-------------------------------------------------------< implementation >
/**
- * Acquires the read lock on this item state manager.
- * @throws ItemStateException if the read lock cannot be acquired.
+ * Create a new node state instance
+ *
+ * @param uuid uuid
+ * @param nodeTypeName node type name
+ * @param parentUUID parent UUID
+ * @return new node state instance
*/
- private void acquireReadLock() throws ItemStateException {
+ private NodeState createInstance(String uuid, QName nodeTypeName,
+ String parentUUID) {
+
+ NodeState state = persistMgr.createNew(new NodeId(uuid));
+ state.setNodeTypeName(nodeTypeName);
+ state.setParentUUID(parentUUID);
+ state.setStatus(ItemState.STATUS_NEW);
+ state.addListener(this);
+
+ return state;
+ }
+
+ /**
+ * Create root node state
+ * @param rootNodeUUID root node UUID
+ * @param ntReg node type registry
+ * @return root node state
+ * @throws ItemStateException if an error occurs
+ */
+ private NodeState createRootNodeState(String rootNodeUUID,
+ NodeTypeRegistry ntReg)
+ throws ItemStateException {
+
+ NodeState rootState = createInstance(rootNodeUUID, Constants.REP_ROOT, null);
+
+ // FIXME need to manually setup root node by creating mandatory jcr:primaryType property
+ // @todo delegate setup of root node to NodeTypeInstanceHandler
+
+ // id of the root node's definition
+ NodeDefId nodeDefId;
+ // definition of jcr:primaryType property
+ PropDef propDef;
try {
- rwLock.readLock().acquire();
- } catch (InterruptedException e) {
- throw new ItemStateException("Interrupted while acquiring read lock");
+ nodeDefId = ntReg.getRootNodeDef().getId();
+ EffectiveNodeType ent = ntReg.getEffectiveNodeType(Constants.REP_ROOT);
+ propDef = ent.getApplicablePropertyDef(Constants.JCR_PRIMARYTYPE,
+ PropertyType.NAME, false);
+ } catch (NoSuchNodeTypeException nsnte) {
+ String msg = "internal error: failed to create root node";
+ log.error(msg, nsnte);
+ throw new ItemStateException(msg, nsnte);
+ } catch (ConstraintViolationException cve) {
+ String msg = "internal error: failed to create root node";
+ log.error(msg, cve);
+ throw new ItemStateException(msg, cve);
}
+ rootState.setDefinitionId(nodeDefId);
+
+ // create jcr:primaryType property
+ rootState.addPropertyName(propDef.getName());
+
+ PropertyState prop = createInstance(propDef.getName(), rootNodeUUID);
+ prop.setValues(new InternalValue[]{InternalValue.create(Constants.REP_ROOT)});
+ prop.setType(propDef.getRequiredType());
+ prop.setMultiValued(propDef.isMultiple());
+ prop.setDefinitionId(propDef.getId());
+
+ ChangeLog changeLog = new ChangeLog();
+ changeLog.added(rootState);
+ changeLog.added(prop);
+
+ persistMgr.store(changeLog);
+ changeLog.persisted();
+
+ return rootState;
}
/**
- * Acquires the write lock on this item state manager.
- * @throws ItemStateException if the write lock cannot be acquired.
+ * Returns the item state for the given id without considering virtual
+ * item state providers.
*/
- private void acquireWriteLock() throws ItemStateException {
+ private ItemState getNonVirtualItemState(ItemId id)
+ throws NoSuchItemStateException, ItemStateException {
+
+ // check cache; synchronized to ensure an entry is not created twice.
+ synchronized (cache) {
+ ItemState state = cache.retrieve(id);
+ if (state == null) {
+ // not found in cache, load from persistent storage
+ state = loadItemState(id);
+ state.setStatus(ItemState.STATUS_EXISTING);
+ // put it in cache
+ cache.cache(state);
+ // register as listener
+ state.addListener(this);
+ }
+ return state;
+ }
+ }
+
+ /**
+ * Checks if this item state manager has the given item state without
+ * considering the virtual item state managers.
+ */
+ private boolean hasNonVirtualItemState(ItemId id) {
+ if (cache.isCached(id)) {
+ return true;
+ }
+
try {
- rwLock.writeLock().acquire();
- } catch (InterruptedException e) {
- throw new ItemStateException("Interrupted while acquiring write lock");
+ if (id.denotesNode()) {
+ return persistMgr.exists((NodeId) id);
+ } else {
+ return persistMgr.exists((PropertyId) id);
+ }
+ } catch (ItemStateException ise) {
+ return false;
}
}
- //----------------------------------------------------< ItemStateListener >
/**
- * {@inheritDoc}
+ * Create a new node state instance
+ *
+ * @param other other state associated with new instance
+ * @return new node state instance
*/
- public void stateCreated(ItemState created) {
- cache(created);
+ private ItemState createInstance(ItemState other) {
+ if (other.isNode()) {
+ NodeState ns = (NodeState) other;
+ return createInstance(ns.getUUID(), ns.getNodeTypeName(), ns.getParentUUID());
+ } else {
+ PropertyState ps = (PropertyState) other;
+ return createInstance(ps.getName(), ps.getParentUUID());
+ }
}
/**
- * {@inheritDoc}
+ * Create a new property state instance
+ *
+ * @param propName property name
+ * @param parentUUID parent UUID
+ * @return new property state instance
*/
- public void stateModified(ItemState modified) {
- // not interested
+ private PropertyState createInstance(QName propName, String parentUUID) {
+ PropertyState state = persistMgr.createNew(new PropertyId(parentUUID, propName));
+ state.setStatus(ItemState.STATUS_NEW);
+ state.addListener(this);
+
+ return state;
}
/**
- * {@inheritDoc}
+ * Load item state from persistent storage.
+ * @param id item id
+ * @return item state
*/
- public void stateDestroyed(ItemState destroyed) {
- destroyed.removeListener(this);
- evict(destroyed.getId());
+ private ItemState loadItemState(ItemId id)
+ throws NoSuchItemStateException, ItemStateException {
+
+ if (id.denotesNode()) {
+ return persistMgr.load((NodeId) id);
+ } else {
+ return persistMgr.load((PropertyId) id);
+ }
}
/**
- * {@inheritDoc}
+ * Check targets of modified node references exist.
+ * @param log change log
+ * @throws ItemStateException if some target was not found
*/
- public void stateDiscarded(ItemState discarded) {
- discarded.removeListener(this);
- evict(discarded.getId());
+ void checkTargetsExist(ChangeLog log) throws ItemStateException {
+ Iterator iter = log.modifiedRefs();
+ while (iter.hasNext()) {
+ NodeReferences refs = (NodeReferences) iter.next();
+ NodeId id = new NodeId(refs.getUUID());
+
+ for (int i = 0; i < virtualProviders.length; i++) {
+ VirtualItemStateProvider provider = virtualProviders[i];
+ if (provider.hasItemState(id)) {
+ refs = null;
+ break;
+ }
+ }
+ if (refs != null && refs.hasReferences()) {
+ if (!log.has(id) && !hasItemState(id)) {
+ String msg = "Target node " + id
+ + " of REFERENCE property does not exist";
+ throw new ItemStateException(msg);
+ }
+ }
+ }
+ }
+
+ /**
+ * Acquires the read lock on this item state manager.
+ * @throws ItemStateException if the read lock cannot be acquired.
+ */
+ private void acquireReadLock() throws ItemStateException {
+ try {
+ rwLock.readLock().acquire();
+ } catch (InterruptedException e) {
+ throw new ItemStateException("Interrupted while acquiring read lock");
+ }
+ }
+
+ /**
+ * Acquires the write lock on this item state manager.
+ * @throws ItemStateException if the write lock cannot be acquired.
+ */
+ private void acquireWriteLock() throws ItemStateException {
+ try {
+ rwLock.writeLock().acquire();
+ } catch (InterruptedException e) {
+ throw new ItemStateException("Interrupted while acquiring write lock");
+ }
}
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/TransientItemStateManager.java Tue Aug 2 09:56:07 2005
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.core.state;
-import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.PropertyId;
@@ -24,24 +23,39 @@
import org.apache.log4j.Logger;
import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
/**
* <code>TransientItemStateManager</code> ...
*/
-class TransientItemStateManager extends ItemStateCache implements ItemStateManager {
+class TransientItemStateManager implements ItemStateManager {
private static Logger log = Logger.getLogger(TransientItemStateManager.class);
- private final Attic attic;
+ /**
+ * map of those states that have been removed transiently
+ */
+ private final ItemStateMap atticMap;
+
+ /**
+ * map of new or modified transient states
+ */
+ private final ItemStateMap transientMap;
+
+ /**
+ * ItemStateManager view of the states in the attic; lazily instantiated
+ * in {@link #getAttic()}
+ */
+ private AtticItemStateManager attic;
/**
* Creates a new <code>TransientItemStateManager</code> instance.
*/
TransientItemStateManager() {
- // we're keeping hard references in the cache
- super(ReferenceMap.HARD, ReferenceMap.HARD);
- attic = new Attic();
+ transientMap = new ItemStateMap();
+ atticMap = new ItemStateMap();
}
/**
@@ -54,10 +68,10 @@
ps.println("TransientItemStateManager (" + this + ")");
ps.println();
ps.print("[transient] ");
- super.dump(ps);
+ transientMap.dump(ps);
ps.println();
ps.print("[attic] ");
- attic.dump(ps);
+ atticMap.dump(ps);
}
//----------------------------------------------------< ItemStateProvider >
@@ -67,7 +81,7 @@
public ItemState getItemState(ItemId id)
throws NoSuchItemStateException, ItemStateException {
- ItemState state = retrieve(id);
+ ItemState state = transientMap.get(id);
if (state != null) {
return state;
} else {
@@ -79,7 +93,7 @@
* {@inheritDoc}
*/
public boolean hasItemState(ItemId id) {
- return isCached(id);
+ return transientMap.contains(id);
}
/**
@@ -104,42 +118,42 @@
* @return
*/
boolean hasAnyItemStates() {
- return !isEmpty();
+ return !transientMap.isEmpty();
}
/**
* @return
*/
boolean hasAnyItemStatesInAttic() {
- return !attic.isEmpty();
+ return !atticMap.isEmpty();
}
/**
* @return
*/
int getEntriesCount() {
- return size();
+ return transientMap.size();
}
/**
* @return
*/
int getEntriesInAtticCount() {
- return attic.size();
+ return atticMap.size();
}
/**
* @return
*/
Iterator getEntries() {
- return entries();
+ return transientMap.values().iterator();
}
/**
* @return
*/
Iterator getEntriesInAttic() {
- return attic.entries();
+ return atticMap.values().iterator();
}
//----------------< methods for creating & discarding ItemState instances >
@@ -157,9 +171,9 @@
NodeId id = new NodeId(uuid);
- // check cache. synchronized to ensure an entry is not created twice.
- synchronized (cacheMonitor) {
- if (isCached(id)) {
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientMap) {
+ if (transientMap.contains(id)) {
String msg = "there's already a node state instance with id " + id;
log.debug(msg);
throw new ItemStateException(msg);
@@ -167,8 +181,8 @@
NodeState state = new NodeState(uuid, nodeTypeName, parentUUID,
initialStatus, true);
- // put it in cache
- cache(state);
+ // put transient state in the map
+ transientMap.put(state);
return state;
}
}
@@ -184,17 +198,17 @@
ItemId id = overlayedState.getId();
- // check cache. synchronized to ensure an entry is not created twice.
- synchronized (cacheMonitor) {
- if (isCached(id)) {
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientMap) {
+ if (transientMap.contains(id)) {
String msg = "there's already a node state instance with id " + id;
log.debug(msg);
throw new ItemStateException(msg);
}
NodeState state = new NodeState(overlayedState, initialStatus, true);
- // put it in cache
- cache(state);
+ // put transient state in the map
+ transientMap.put(state);
return state;
}
}
@@ -211,17 +225,17 @@
PropertyId id = new PropertyId(parentUUID, propName);
- // check cache. synchronized to ensure an entry is not created twice.
- synchronized (cacheMonitor) {
- if (isCached(id)) {
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientMap) {
+ if (transientMap.contains(id)) {
String msg = "there's already a property state instance with id " + id;
log.debug(msg);
throw new ItemStateException(msg);
}
PropertyState state = new PropertyState(propName, parentUUID, initialStatus, true);
- // put it in cache
- cache(state);
+ // put transient state in the map
+ transientMap.put(state);
return state;
}
}
@@ -238,23 +252,24 @@
PropertyId id = new PropertyId(overlayedState.getParentUUID(),
overlayedState.getName());
- // check cache. synchronized to ensure an entry is not created twice.
- synchronized (cacheMonitor) {
- if (isCached(id)) {
+ // check map; synchronized to ensure an entry is not created twice.
+ synchronized (transientMap) {
+ if (transientMap.contains(id)) {
String msg = "there's already a property state instance with id " + id;
log.debug(msg);
throw new ItemStateException(msg);
}
PropertyState state = new PropertyState(overlayedState, initialStatus, true);
- // put it in cache
- cache(state);
+ // put transient state in the map
+ transientMap.put(state);
return state;
}
}
/**
- * Disposes the specified instance, i.e. discards it and clears it from cache.
+ * Disposes the specified instance, i.e. discards it and removes it from
+ * the map.
*
* @param state the <code>ItemState</code> instance that should be disposed
* @see ItemState#discard()
@@ -263,23 +278,23 @@
// discard item state, this will invalidate the wrapping Item
// instance of the transient state
state.discard();
- // remove from cache
- evict(state.getId());
+ // remove from map
+ transientMap.remove(state.getId());
// give the instance a chance to prepare to get gc'ed
state.onDisposed();
}
/**
- * Transfers the specified instance from the 'active' cache to the attic.
+ * Transfers the specified instance from the 'active' map to the attic.
*
* @param state the <code>ItemState</code> instance that should be moved to
* the attic
*/
void moveItemStateToAttic(ItemState state) {
- // remove from cache
- evict(state.getId());
+ // remove from map
+ transientMap.remove(state.getId());
// add to attic
- attic.cache(state);
+ atticMap.put(state);
}
/**
@@ -294,7 +309,7 @@
// instance of the transient state
state.discard();
// remove from attic
- attic.evict(state.getId());
+ atticMap.remove(state.getId());
// give the instance a chance to prepare to get gc'ed
state.onDisposed();
}
@@ -303,14 +318,16 @@
* Disposes all transient item states in the cache and in the attic.
*/
void disposeAllItemStates() {
- // dispose item states in cache
- Iterator iter = entries();
+ // dispose item states in transient map & attic
+ // (use temp collection to avoid ConcurrentModificationException)
+ Collection tmp = new ArrayList(transientMap.values());
+ Iterator iter = tmp.iterator();
while (iter.hasNext()) {
ItemState state = (ItemState) iter.next();
disposeItemState(state);
}
- // dispose item states in attic
- iter = attic.entries();
+ tmp = new ArrayList(atticMap.values());
+ iter = tmp.iterator();
while (iter.hasNext()) {
ItemState state = (ItemState) iter.next();
disposeItemStateInAttic(state);
@@ -324,14 +341,21 @@
* @return attic
*/
ItemStateManager getAttic() {
+ if (attic == null) {
+ attic = new AtticItemStateManager();
+ }
return attic;
}
//--------------------------------------------------------< inner classes >
- class Attic extends ItemStateCache implements ItemStateManager {
+ /**
+ * ItemStateManager view of the states in the attic
+ *
+ * @see TransientItemStateManager#getAttic
+ */
+ private class AtticItemStateManager implements ItemStateManager {
- Attic() {
- super(ReferenceMap.HARD, ReferenceMap.HARD);
+ AtticItemStateManager() {
}
/**
@@ -340,7 +364,7 @@
public ItemState getItemState(ItemId id)
throws NoSuchItemStateException, ItemStateException {
- ItemState state = retrieve(id);
+ ItemState state = atticMap.get(id);
if (state != null) {
return state;
} else {
@@ -352,7 +376,7 @@
* {@inheritDoc}
*/
public boolean hasItemState(ItemId id) {
- return isCached(id);
+ return atticMap.contains(id);
}
/**
@@ -360,7 +384,7 @@
*/
public NodeReferences getNodeReferences(NodeReferencesId id)
throws NoSuchItemStateException, ItemStateException {
-
+ // n/a
throw new ItemStateException("getNodeReferences() not implemented");
}
@@ -368,6 +392,7 @@
* {@inheritDoc}
*/
public boolean hasNodeReferences(NodeReferencesId id) {
+ // n/a
return false;
}
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java?rev=227042&r1=227041&r2=227042&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java (original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/virtual/AbstractVISProvider.java Tue Aug 2 09:56:07 2005
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.core.virtual;
-import org.apache.commons.collections.map.ReferenceMap;
import org.apache.jackrabbit.Constants;
import org.apache.jackrabbit.core.ItemId;
import org.apache.jackrabbit.core.NodeId;
@@ -33,6 +32,7 @@
import org.apache.jackrabbit.core.state.NodeReferences;
import org.apache.jackrabbit.core.state.NodeReferencesId;
import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.ItemStateReferenceMap;
import org.apache.jackrabbit.name.QName;
import org.apache.jackrabbit.uuid.UUID;
import org.apache.log4j.Logger;
@@ -40,7 +40,6 @@
import javax.jcr.RepositoryException;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.Map;
/**
* This Class implements a virtual item state provider, in order to expose the
@@ -70,7 +69,7 @@
/**
* the cache node states. key=ItemId, value=ItemState
*/
- private Map nodes = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
+ private ItemStateReferenceMap nodes = new ItemStateReferenceMap();
/**
* Creates an abstract virtual item state provider
@@ -98,7 +97,7 @@
*/
public boolean hasItemState(ItemId id) {
if (id instanceof NodeId) {
- if (nodes.containsKey(id)) {
+ if (nodes.contains(id)) {
return true;
} else if (id.equals(rootNodeId)) {
return true;
@@ -118,7 +117,7 @@
if (id instanceof NodeId) {
ItemState s;
- if (nodes.containsKey(id)) {
+ if (nodes.contains(id)) {
s = (ItemState) nodes.get(id);
} else if (id.equals(rootNodeId)) {
s = getRootState();
@@ -302,7 +301,7 @@
*/
protected NodeState cache(NodeState state) {
if (state != null) {
- nodes.put(state.getId(), state);
+ nodes.put(state);
state.addListener(this);
log.debug("item added to cache. size=" + nodes.size());
}
@@ -310,12 +309,12 @@
}
/**
- * removes the nodes state from the cache
+ * removes the node state from the cache
*
* @param id
*/
- protected NodeState evict(NodeId id) {
- return (NodeState) nodes.remove(id);
+ protected void evict(NodeId id) {
+ nodes.remove(id);
}
/**