Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 76660 invoked from network); 20 Sep 2007 18:39:35 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 20 Sep 2007 18:39:35 -0000 Received: (qmail 98192 invoked by uid 500); 20 Sep 2007 18:39:26 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 98160 invoked by uid 500); 20 Sep 2007 18:39:26 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 98151 invoked by uid 99); 20 Sep 2007 18:39:26 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Sep 2007 11:39:26 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 20 Sep 2007 18:41:33 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 6E59D1A983E; Thu, 20 Sep 2007 11:39:10 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r577864 - in /jackrabbit/branches/1.3: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/PathMap.java Date: Thu, 20 Sep 2007 18:39:09 -0000 To: commits@jackrabbit.apache.org From: jukka@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070920183910.6E59D1A983E@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jukka Date: Thu Sep 20 11:39:09 2007 New Revision: 577864 URL: http://svn.apache.org/viewvc?rev=577864&view=rev Log: 1.3: Merged revision 570736 (JCR-1082) Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java jackrabbit/branches/1.3/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/PathMap.java Modified: jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java?rev=577864&r1=577863&r2=577864&view=diff ============================================================================== --- jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java (original) +++ jackrabbit/branches/1.3/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/CachingHierarchyManager.java Thu Sep 20 11:39:09 2007 @@ -375,35 +375,47 @@ /** * {@inheritDoc} *

- * Generate subsequent add and remove notifications for every replacement. This method - * currently assumes that the reordering is detectable by comparing the state's child - * node entries to the overlayed state's child node entries. It is not able to handle - * a transient reordering and will therefore evict its cached entry if such a situation - * is detected. + * Iterate over all cached children of this state and verify each + * child's position. */ public void nodesReplaced(NodeState state) { - List entries = state.getReorderedChildNodeEntries(); - if (entries.size() == 0) { - synchronized (cacheMonitor) { - if (idCache.containsKey(state.getNodeId())) { - evict(state.getNodeId()); + synchronized (cacheMonitor) { + LRUEntry entry = (LRUEntry) idCache.get(state.getNodeId()); + if (entry != null) { + PathMap.Element element = entry.getElement(); + Iterator iter = element.getChildren(); + while (iter.hasNext()) { + PathMap.Element child = (PathMap.Element) iter.next(); + LRUEntry childEntry = (LRUEntry) child.get(); + if (childEntry == null) { + /** + * Child has no associated UUID information: we're + * therefore unable to determine if this child's + * position is still accurate and have to assume + * the worst and remove it. + */ + child.remove(false); + remove(child); + continue; + } + NodeId childId = childEntry.getId(); + NodeState.ChildNodeEntry cne = state.getChildNodeEntry(childId); + if (cne == null) { + /* Child no longer in parent node state, so remove it */ + child.remove(false); + remove(child); + continue; + } + if (!cne.getName().equals(child.getName()) || + cne.getIndex() != child.getNormalizedIndex()) { + /* Child still exists but at a different position */ + element.move(child.getPathElement(), + Path.PathElement.create(cne.getName(), cne.getIndex())); + continue; + } + /* At this point the child's position is still valid */ } } - return; - } - Iterator iter = entries.iterator(); - while (iter.hasNext()) { - NodeState.ChildNodeEntry now = (NodeState.ChildNodeEntry) iter.next(); - NodeState.ChildNodeEntry old = - ((NodeState) state.getOverlayedState()).getChildNodeEntry(now.getId()); - - if (old == null) { - log.warn("Reordered child node not found in old list."); - continue; - } - - nodeAdded(state, now.getName(), now.getIndex(), now.getId()); - nodeRemoved(state, old.getName(), old.getIndex(), old.getId()); } } @@ -486,23 +498,6 @@ synchronized (cacheMonitor) { if (idCache.get(id) != null) { return; - } - - /** - * Do not cache paths to elements if the parent is transient, since - * children may be reordered multiple times (see JCR-993). If a - * child's position is cached at some intermediate stage but the - * total reordering effectively leaves the child at its initial - * position, the child's bad position is hardly detectable. - */ - try { - NodeId parentId = state.getParentId(); - if (parentId != null && provider.getItemState(parentId).isTransient()) { - return; - } - } catch (ItemStateException e) { - String msg = "Unable to retrieve parent state of: " + id; - log.warn(msg, e); } if (idCache.size() >= upperLimit) { Modified: jackrabbit/branches/1.3/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/PathMap.java URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.3/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/PathMap.java?rev=577864&r1=577863&r2=577864&view=diff ============================================================================== --- jackrabbit/branches/1.3/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/PathMap.java (original) +++ jackrabbit/branches/1.3/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/PathMap.java Thu Sep 20 11:39:09 2007 @@ -264,22 +264,28 @@ * @return removed child, may be null */ public Element remove(Path.PathElement nameIndex) { - return remove(nameIndex, true); + return remove(nameIndex, true, true); } /** * Remove a child. If shift is set to true, * will shift all children having an index greater than the child - * removed to the left. If there are no more children left in + * removed to the left. If removeIfEmpty is set to + * true and there are no more children left in * this element and no object is associated with this element, the * element itself gets removed. * * @param nameIndex child's path element * @param shift whether to shift same name siblings having a greater * index to the left + * @param removeIfEmpty remove this element itself if it contains + * no more children and is not associated to + * an element * @return removed child, may be null */ - private Element remove(Path.PathElement nameIndex, boolean shift) { + private Element remove(Path.PathElement nameIndex, boolean shift, + boolean removeIfEmpty) { + // convert 1-based index value to 0-base value int index = getZeroBasedIndex(nameIndex); if (children == null) { @@ -303,8 +309,8 @@ element.parent = null; childrenCount--; } - if (childrenCount == 0 && obj == null && parent != null) { - parent.remove(getPathElement(), shift); + if (removeIfEmpty && childrenCount == 0 && obj == null && parent != null) { + parent.remove(getPathElement(), shift, true); } return element; } @@ -323,7 +329,7 @@ */ public void remove(boolean shift) { if (parent != null) { - parent.remove(getPathElement(), shift); + parent.remove(getPathElement(), shift, true); } else { // Removing the root node is not possible: if it has become // invalid, remove all its children and the associated object @@ -342,8 +348,28 @@ childrenCount = 0; if (obj == null && parent != null) { - parent.remove(getPathElement(), false); + parent.remove(getPathElement(), false, true); + } + } + + /** + * Move a child of this element to a different location inside the + * same parent. + * + * @param oldNameIndex old name/index + * @param newNameIndex new name/index + * @return true if the element was successfully moved; + * otherwise false + */ + public boolean move(Path.PathElement oldNameIndex, + Path.PathElement newNameIndex) { + + Element child = remove(oldNameIndex, false, false); + if (child != null) { + put(newNameIndex, child); + return true; } + return false; } /** @@ -362,7 +388,7 @@ this.obj = obj; if (obj == null && childrenCount == 0 && parent != null) { - parent.remove(getPathElement(), false); + parent.remove(getPathElement(), false, true); } }