You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2009/04/20 19:05:34 UTC

svn commit: r766756 - in /jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi: ./ hierarchy/ state/

Author: mduerig
Date: Mon Apr 20 17:05:33 2009
New Revision: 766756

URL: http://svn.apache.org/viewvc?rev=766756&view=rev
Log:
1.5: Backported revision 722470 (JCR-1886)

Modified:
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemLifeCycleListener.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntriesImpl.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildPropertyEntriesImpl.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntryImpl.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/UniqueIdResolver.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/AbstractItemStateFactory.java
    jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemCacheImpl.java Mon Apr 20 17:05:33 2009
@@ -72,19 +72,22 @@
         cacheItem(((ItemImpl)item).getItemState(), item);
     }
 
-    /**
-     * @see ItemLifeCycleListener#itemInvalidated(Item)
-     */
-    public void itemInvalidated(Item item) {
+    public void itemUpdated(Item item, boolean modified) {
         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);
+            log.debug("update item " + item);
+        }
+
+        ItemState state = ((ItemImpl) item).getItemState();
+        // touch the corresponding cache entry
+        Item cacheEntry = getItem(state);
+        if (cacheEntry == null) {
+            // .. or add the item to the cache, if not present yet.
+            cacheItem(state, item);
         }
-        // remove instance from cache
-        evictItem(((ItemImpl)item).getItemState());
     }
 
     /**
@@ -163,4 +166,4 @@
             ps.println(state + "\t" + path + " (" + item + ")");
         }
     }
-}
\ No newline at end of file
+}

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemImpl.java Mon Apr 20 17:05:33 2009
@@ -316,13 +316,22 @@
             /**
              * Nothing to do for
              * - Status#EXISTING : modifications reverted or saved
+             *   inform listeneres about an update (status was MODIFIED before)
+             *   or a simple refresh without modification (status was INVALIDATED).
+             */
+            case Status.EXISTING:
+                if (previousStatus == Status.INVALIDATED || previousStatus == Status.MODIFIED) {
+                    notifyUpdated(previousStatus == Status.MODIFIED);
+                }
+                break;
+            /**
+             * Nothing to do for
              * - Status#EXISTING_MODIFIED : transient modification
              * - Status#STALE_MODIFIED : external modifications while transient changes pending
              * - Status#STALE_DESTROYED : external modifications while transient changes pending
              * - Status#MODIFIED : externaly modified -> marker for sessionISM states only
              * - Status#EXISTING_REMOVED : transient removal
              */
-            case Status.EXISTING:
             case Status.EXISTING_MODIFIED:
             case Status.STALE_MODIFIED:
             case Status.STALE_DESTROYED:
@@ -351,8 +360,7 @@
     //----------------------------------------------------------< LiveCycle >---
 
     /**
-     * Notify the listeners that this instance has been discarded
-     * (i.e. it has been temporarily rendered 'invalid').
+     * Notify the listeners that this instance has been created.
      */
     private void notifyCreated() {
         // copy listeners to array to avoid ConcurrentModificationException
@@ -363,22 +371,20 @@
     }
 
     /**
-     * Notify the listeners that this instance has been invalidated
-     * (i.e. it has been temporarily rendered 'invalid').
+     * Notify the listeners that this instance has been updated.
      */
-    private  void notifyInvalidated() {
+    private void notifyUpdated(boolean modified) {
         // copy listeners to array to avoid ConcurrentModificationException
         ItemLifeCycleListener[] la = (ItemLifeCycleListener[]) listeners.values().toArray(new ItemLifeCycleListener[listeners.size()]);
         for (int i = 0; i < la.length; i++) {
             if (la[i] != null) {
-                la[i].itemInvalidated(this);
+                la[i].itemUpdated(this, modified);
             }
         }
     }
 
     /**
-     * Notify the listeners that this instance has been destroyed
-     * (i.e. it has been permanently rendered 'invalid').
+     * Notify the listeners that this instance has been destroyed.
      */
     private void notifyDestroyed() {
         // copy listeners to array to avoid ConcurrentModificationException

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemLifeCycleListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemLifeCycleListener.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemLifeCycleListener.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/ItemLifeCycleListener.java Mon Apr 20 17:05:33 2009
@@ -34,17 +34,13 @@
     public void itemCreated(Item item);
 
     /**
-     * Called when an <code>Item</code> instance has been invalidated
-     * (i.e. it has been temporarily rendered 'invalid').
-     * <p/>
-     * Note that most methods of <code>{@link javax.jcr.Item}</code>,
-     * <code>{@link javax.jcr.Node}</code> and <code>{@link javax.jcr.Property}</code>
-     * will throw an <code>InvalidItemStateException</code> when called
-     * on an 'invalidated' item.
+     * Called when an <code>Item</code> instance has been refreshed. If
+     * <code>modified</code> is <code>true</code>, the refresh included
+     * some modification.
      *
-     * @param item the instance which has been discarded
+     * @param item the instance which has been refreshed
      */
-    void itemInvalidated(Item item);
+    void itemUpdated(Item item, boolean modified);
 
     /**
      * Called when an <code>ItemImpl</code> instance has been destroyed

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntriesImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntriesImpl.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntriesImpl.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildNodeEntriesImpl.java Mon Apr 20 17:05:33 2009
@@ -36,7 +36,7 @@
 import java.util.HashMap;
 import java.util.Collections;
 import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
 
 /**
  * <code>ChildNodeEntriesImpl</code> implements a memory sensitive implementation
@@ -637,9 +637,9 @@
             }
 
             protected LinkNode(Object value, int index) {
-                // add weak reference from linkNode to the NodeEntry (value)
+                // add soft reference from linkNode to the NodeEntry (value)
                 // unless the entry is a SNSibling. TODO: review again.
-                super(index > Path.INDEX_DEFAULT ? value : new WeakReference(value));
+                super(index > Path.INDEX_DEFAULT ? value : new SoftReference(value));
                 qName = ((NodeEntry) value).getName();
             }
 
@@ -661,7 +661,7 @@
                 // create a new NodeEntry in order to avoid returning null.
                 if (ne == null && this != header) {
                     ne = factory.createNodeEntry(parent, qName, null);
-                    super.setValue(new WeakReference(ne));
+                    super.setValue(new SoftReference(ne));
                 }
                 return ne;
             }

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildPropertyEntriesImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildPropertyEntriesImpl.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildPropertyEntriesImpl.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/ChildPropertyEntriesImpl.java Mon Apr 20 17:05:33 2009
@@ -28,7 +28,7 @@
 import java.util.HashSet;
 import java.util.Collections;
 import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
 
 /**
  * <code>ChildPropertyEntriesImpl</code>...
@@ -99,7 +99,7 @@
      */
     public void add(PropertyEntry propertyEntry) {
         synchronized (properties) {
-            Reference ref = new WeakReference(propertyEntry);
+            Reference ref = new SoftReference(propertyEntry);
             properties.put(propertyEntry.getName(), ref);
         }
     }
@@ -131,4 +131,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntryImpl.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntryImpl.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/HierarchyEntryImpl.java Mon Apr 20 17:05:33 2009
@@ -27,7 +27,7 @@
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.RepositoryException;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
 import java.lang.ref.Reference;
 
 /**
@@ -39,7 +39,7 @@
     private static Logger log = LoggerFactory.getLogger(HierarchyEntryImpl.class);
 
     /**
-     * Cached weak reference to the target ItemState.
+     * Cached soft reference to the target ItemState.
      */
     private Reference target;
 
@@ -90,7 +90,7 @@
     ItemState resolve() throws ItemNotFoundException, RepositoryException {
         // check if already resolved
         ItemState state = internalGetItemState();
-        // not yet resolved. retrieve and keep weak reference to state
+        // not yet resolved. retrieve and keep soft reference to state
         if (state == null) {
             try {
                 state = doResolve();
@@ -216,7 +216,7 @@
         if (currentState == null) {
             // not connected yet to an item state. either a new entry or
             // an unresolved hierarchy entry.
-            target = new WeakReference(state);
+            target = new SoftReference(state);
         } else {
             // was already resolved before -> merge the existing state
             // with the passed state.

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/NodeEntryImpl.java Mon Apr 20 17:05:33 2009
@@ -1345,7 +1345,7 @@
             int index = Path.INDEX_DEFAULT;
             for (Iterator it = sns.iterator(); it.hasNext(); ) {
                 NodeEntry entry = (NodeEntry) it.next();
-                if (entry == cne) {
+                if (entry == cne) { // TODO see below
                     return index;
                 }
                 // for wsp index ignore all transiently added items.
@@ -1358,9 +1358,9 @@
                     index++;
                 }
             }
-            // not found, since child entries are only weakly connected to the
-            // LinkNode in ChildNodeEntries, equality may not determine the
-            // correct matching entry -> return default index.
+            // not found, since child entries are only connected with soft refs
+            // to the LinkNode in ChildNodeEntries, equality may not determine
+            // the correct matching entry -> return default index.
             return Path.INDEX_DEFAULT;
         }
     }

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/UniqueIdResolver.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/UniqueIdResolver.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/UniqueIdResolver.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/hierarchy/UniqueIdResolver.java Mon Apr 20 17:05:33 2009
@@ -50,7 +50,7 @@
      * Creates a new <code>UniqueIdResolver</code>.
      */
     public UniqueIdResolver(ItemStateFactory isf) {
-        this.lookUp = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.WEAK);
+        this.lookUp = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
         this.isf = isf;
         isf.addCreationListener(this);
     }

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/AbstractItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/AbstractItemStateFactory.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/AbstractItemStateFactory.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/AbstractItemStateFactory.java Mon Apr 20 17:05:33 2009
@@ -76,4 +76,16 @@
             listeners[i].created(createdState);
         }
     }
-}
\ No newline at end of file
+
+    /**
+     *
+     * @param state
+     */
+    void notifyUpdated(ItemState state, int previousStatus) {
+        ItemStateCreationListener[] listeners = getListeners();
+        for (int i = 0; i < listeners.length; i++) {
+            // now inform about creation
+            listeners[i].statusChanged(state, previousStatus);
+        }
+    }
+}

Modified: jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java?rev=766756&r1=766755&r2=766756&view=diff
==============================================================================
--- jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java (original)
+++ jackrabbit/branches/1.5/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/WorkspaceItemStateFactory.java Mon Apr 20 17:05:33 2009
@@ -198,8 +198,8 @@
         NodeState nodeState;
         ItemInfos infos = new ItemInfos(itemInfos);
         // first entry in the iterator is the originally requested Node.
-        if (itemInfos.hasNext()) {
-            NodeInfo first = (NodeInfo) itemInfos.next();
+        if (infos.hasNext()) {
+            NodeInfo first = (NodeInfo) infos.next();
             if (isDeep) {
                 // for a deep state, the hierarchy entry does not correspond to
                 // the given NodeEntry -> retrieve NodeState before executing
@@ -219,8 +219,8 @@
 
         // deal with all additional ItemInfos that may be present.
         NodeEntry parentEntry = nodeState.getNodeEntry();
-        while (itemInfos.hasNext()) {
-            ItemInfo info = (ItemInfo) itemInfos.next();
+        while (infos.hasNext()) {
+            ItemInfo info = (ItemInfo) infos.next();
             if (info.denotesNode()) {
                 createDeepNodeState((NodeInfo) info, parentEntry, infos);
             } else {
@@ -254,7 +254,8 @@
             parent.setUniqueID(uniqueID);
         }
 
-        if (Status.isTransient(entry.getStatus()) || Status.isStale(entry.getStatus())) {
+        int previousStatus = entry.getStatus();
+        if (Status.isTransient(previousStatus) || Status.isStale(previousStatus)) {
             log.debug("Node has pending changes; omit resetting the state.");
             return entry.getNodeState();
         }
@@ -285,11 +286,13 @@
         entry.setItemState(tmp);
 
         NodeState nState = entry.getNodeState();
-        if (nState == tmp) {
+        if (previousStatus == Status._UNDEFINED_) {
             // tmp state was used as resolution for the given entry i.e. the
             // entry was not available before. otherwise the 2 states were
             // merged. see HierarchyEntryImpl#setItemState
             notifyCreated(nState);
+        } else {
+            notifyUpdated(nState, previousStatus);
         }
         return nState;
     }
@@ -312,7 +315,8 @@
             parent.setUniqueID(uniqueID);
         }
 
-        if (Status.isTransient(entry.getStatus()) || Status.isStale(entry.getStatus())) {
+        int previousStatus = entry.getStatus();
+        if (Status.isTransient(previousStatus) || Status.isStale(previousStatus)) {
             log.debug("Property has pending changes; omit resetting the state.");
             return entry.getPropertyState();
         }
@@ -322,11 +326,13 @@
         entry.setItemState(tmp);
 
         PropertyState pState = entry.getPropertyState();
-        if (pState == tmp) {
+        if (previousStatus == Status._UNDEFINED_) {
             // tmp state was used as resolution for the given entry i.e. the
             // entry was not available before. otherwise the 2 states were
             // merged. see HierarchyEntryImpl#setItemState
             notifyCreated(pState);
+        }  else {
+            notifyUpdated(pState, previousStatus);
         }
         return pState;
     }
@@ -421,7 +427,7 @@
     private static NodeEntry createIntermediateNodeEntry(NodeEntry parentEntry,
                                                          Name name, int index,
                                                          ItemInfos infos) throws RepositoryException {
-        if (infos != null && !parentEntry.hasNodeEntry(name, index)) {
+        if (infos != null) {
             Iterator childInfos = infos.getChildInfos(parentEntry.getWorkspaceId());
             if (childInfos != null) {
                 parentEntry.setNodeEntries(childInfos);
@@ -535,7 +541,11 @@
             if (prefetchQueue.isEmpty()) {
                 throw new NoSuchElementException();
             } else {
-                return prefetchQueue.remove(0);
+                Object next = prefetchQueue.remove(0);
+                if (next instanceof NodeInfo) {
+                    nodeInfos.remove(((NodeInfo) next).getId());
+                }
+                return next;
             }
         }
 
@@ -551,7 +561,8 @@
          * @param parentId
          * @return The children <code>NodeInfo</code>s for the parent identified
          * by the given <code>parentId</code> or <code>null</code> if the parent
-         * has not been read yet or does not provide child infos.
+         * has not been read yet, has already been processed (childInfo is up
+         * to date) or does not provide child infos.
          */
         private Iterator getChildInfos(NodeId parentId) {
             NodeInfo nodeInfo = (NodeInfo) nodeInfos.get(parentId);