You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by st...@apache.org on 2004/08/18 15:13:52 UTC
cvs commit: jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state ItemStateCache.java ItemStateProvider.java TicketItemStateManager.java TransientItemStateManager.java
stefan 2004/08/18 06:13:52
Modified: proposals/jcrri/src/org/apache/slide/jcr/core/state
ItemStateCache.java ItemStateProvider.java
TicketItemStateManager.java
TransientItemStateManager.java
Log:
#0000 fixed performance issues when saving on root
Revision Changes Path
1.10 +10 -1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/ItemStateCache.java
Index: ItemStateCache.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/ItemStateCache.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ItemStateCache.java 2 Aug 2004 16:22:22 -0000 1.9
+++ ItemStateCache.java 18 Aug 2004 13:13:52 -0000 1.10
@@ -129,6 +129,15 @@
}
/**
+ * 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.
*
1.7 +3 -1 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/ItemStateProvider.java
Index: ItemStateProvider.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/ItemStateProvider.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ItemStateProvider.java 2 Aug 2004 16:22:22 -0000 1.6
+++ ItemStateProvider.java 18 Aug 2004 13:13:52 -0000 1.7
@@ -17,6 +17,8 @@
import org.apache.slide.jcr.core.ItemId;
+import java.util.Iterator;
+
/**
* The <code>ItemStateProvider</code> interface...
*
1.7 +237 -30 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/TicketItemStateManager.java
Index: TicketItemStateManager.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/TicketItemStateManager.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TicketItemStateManager.java 2 Aug 2004 16:22:22 -0000 1.6
+++ TicketItemStateManager.java 18 Aug 2004 13:13:52 -0000 1.7
@@ -1,6 +1,6 @@
/*
* Copyright 2002-2004 The Apache Software Foundation.
- *
+ *
* 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
@@ -20,10 +20,7 @@
import javax.jcr.RepositoryException;
import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
/**
* <code>TicketItemStateManager</code> ...
@@ -55,31 +52,44 @@
hierMgr = new HierarchyManagerImpl(rootNodeUUID, this, nsResolver);
}
- static synchronized void collectDescendantItemStates(ItemId id, HierarchyManager hierMgr, ItemStateProvider provider, List descendents) {
+ private synchronized void collectDescendantItemStates(ItemId id, List descendents) {
+ // XXX very inefficient implementation, especially if # of transient states
+ // is relatively small compared to the total # of persistent states
+ if (descendents.size() == transientStateMgr.getEntriesCount()) {
+ return;
+ }
try {
if (id.denotesNode()) {
NodeId parentId = (NodeId) id;
ItemId[] childIds = hierMgr.listChildren(parentId);
for (int i = 0; i < childIds.length; i++) {
ItemId childId = childIds[i];
- if (provider.hasItemState(childId)) {
- descendents.add(provider.getItemState(childId));
+ if (transientStateMgr.hasItemState(childId)) {
+ ItemState state = transientStateMgr.getItemState(childId);
+ if (!descendents.contains(state)) {
+ descendents.add(state);
+ }
+ }
+ if (childId.denotesNode()) {
+ // recurse
+ collectDescendantItemStates(childId, descendents);
}
- // recurse
- collectDescendantItemStates(childId, hierMgr, provider, descendents);
}
// also add transient child nodes that have been unlinked from
// the specified parent node but are not orphaned yet (i.e.
// they are still linked to at least one other parent node)
- if (provider.hasItemState(parentId)) {
- NodeState parentState = (NodeState) provider.getItemState(parentId);
+ if (transientStateMgr.hasItemState(parentId)) {
+ NodeState parentState = (NodeState) transientStateMgr.getItemState(parentId);
Iterator iter = parentState.getRemovedChildNodeEntries().iterator();
while (iter.hasNext()) {
// removed child nodes
NodeState.ChildNodeEntry cne = (NodeState.ChildNodeEntry) iter.next();
NodeId removedChildId = new NodeId(cne.getUUID());
- if (provider.hasItemState(removedChildId)) {
- descendents.add(provider.getItemState(removedChildId));
+ if (transientStateMgr.hasItemState(removedChildId)) {
+ ItemState state = transientStateMgr.getItemState(removedChildId);
+ if (!descendents.contains(state)) {
+ descendents.add(state);
+ }
}
}
}
@@ -91,7 +101,12 @@
}
}
- static synchronized void collectDescendantItemStatesInAttic(ItemId id, HierarchyManager hierMgr, ItemStateProvider provider, List descendents) {
+ private synchronized void collectDescendantItemStatesInAttic(ItemId id, List descendents) {
+ // XXX very inefficient implementation, especially if # of transient states
+ // is relatively small compared to the total # of persistent states
+ if (descendents.size() == transientStateMgr.getEntriesInAtticCount()) {
+ return;
+ }
try {
if (id.denotesNode()) {
NodeId parentId = (NodeId) id;
@@ -101,26 +116,27 @@
for (int i = 0; i < childIds.length; i++) {
ItemId childId = childIds[i];
// check attic
- if (provider.hasItemStateInAttic(childId)) {
+ if (transientStateMgr.hasItemStateInAttic(childId)) {
// found on attic, add to descendents list
- descendents.add(provider.getItemStateInAttic(childId));
+ ItemState state = transientStateMgr.getItemStateInAttic(childId);
+ if (!descendents.contains(state)) {
+ descendents.add(state);
+ }
+ }
+ if (childId.denotesNode()) {
+ // recurse
+ collectDescendantItemStatesInAttic(childId, descendents);
}
- // recurse
- collectDescendantItemStatesInAttic(childId, hierMgr, provider, descendents);
}
- // traverse existing children (because parentId might denote
- // a node that was marked removed)
+ // traverse existing children (because they might have zombie children)
childIds = hierMgr.listChildren(parentId);
for (int i = 0; i < childIds.length; i++) {
ItemId childId = childIds[i];
- // check attic
- if (provider.hasItemStateInAttic(childId)) {
- // found on attic, add to descendents list
- descendents.add(provider.getItemStateInAttic(childId));
+ if (childId.denotesNode()) {
+ // recurse
+ collectDescendantItemStatesInAttic(childId, descendents);
}
- // recurse
- collectDescendantItemStatesInAttic(childId, hierMgr, provider, descendents);
}
}
} catch (ItemStateException ise) {
@@ -234,9 +250,104 @@
*/
public Iterator getDescendantTransientItemStates(ItemId parentId) {
// @todo need a more efficient way to find descendents in cache (e.g. using hierarchical index)
+ if (!transientStateMgr.hasAnyItemStates()) {
+ return Collections.EMPTY_LIST.iterator();
+ }
+ // collection of descendant transient states:
+ // the path serves as key and sort criteria
+ TreeMap descendants = new TreeMap(new PathComparator());
+ try {
+ Path[] parentPaths = hierMgr.getAllPaths(parentId);
+ /**
+ * walk through list of transient states and check if
+ * they are descendants of the specified parent
+ */
+ Iterator iter = transientStateMgr.getEntries();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ ItemId id = state.getId();
+ Path[] paths = hierMgr.getAllPaths(id);
+ boolean isDescendant = false;
+ /**
+ * check if any of the paths to the transient state
+ * is a descendant of any of the specified parentId's paths
+ */
+ for (int i = 0; i < paths.length; i++) {
+ Path p0 = paths[i]; // path to transient state
+ // walk through array of the specified parentId's paths
+ for (int j = 0; j < parentPaths.length; j++) {
+ Path p1 = parentPaths[j]; // path to specified parentId
+ if (p0.isDescendantOf(p1)) {
+ // this is a descendant, add it to the list and
+ // continue with next transient state
+ descendants.put(p0, state);
+ isDescendant = true;
+ break;
+ }
+ }
+ if (isDescendant) {
+ break;
+ }
+ }
+ if (!isDescendant && id.denotesNode()) {
+ /**
+ * finally check if transient state has been unlinked
+ * from a parent node (but is not orphaned yet, i.e. is
+ * still linked to at least one other parent node);
+ * if that's the case, check if that parent is a
+ * descendant of/identical with any of the specified
+ * parentId's paths.
+ */
+ NodeState nodeState = (NodeState) state;
+ Iterator iterUUIDs = nodeState.getRemovedParentUUIDs().iterator();
+ while (iterUUIDs.hasNext()) {
+ /**
+ * check if any of the paths to the removed parent
+ * is a descendant of/identical with any of the
+ * specified parentId's paths.
+ */
+ Path[] pa = hierMgr.getAllPaths(new NodeId((String) iterUUIDs.next()));
+ for (int k = 0; k < pa.length; k++) {
+ Path p0 = pa[k]; // path to removed parent
+ // walk through array of the specified parentId's paths
+ for (int j = 0; j < parentPaths.length; j++) {
+ Path p1 = parentPaths[j]; // path to specified parentId
+ if (p0.equals(p1) || p0.isDescendantOf(p1)) {
+ // this is a descendant, add it to the list and
+ // continue with next transient state
+
+ // FIXME need to create dummy path in order
+ // to avoid conflicts
+ Path.PathBuilder pb = new Path.PathBuilder(p0.getElements());
+ pb.addFirst(NamespaceRegistryImpl.NS_DEFAULT_URI, Integer.toString(new Random().nextInt()));
+ descendants.put(pb.getPath(), state);
+ isDescendant = true;
+ break;
+ }
+ }
+ if (isDescendant) {
+ break;
+ }
+ }
+ if (isDescendant) {
+ break;
+ }
+ }
+ }
+ // continue with next transient state
+ }
+ } catch (MalformedPathException mpe) {
+ log.warn("inconsistent hierarchy state", mpe);
+ } catch (RepositoryException re) {
+ log.warn("inconsistent hierarchy state", re);
+ }
+
+ return descendants.values().iterator();
+/*
ArrayList descendents = new ArrayList();
- collectDescendantItemStates(parentId, hierMgr, transientStateMgr, descendents);
+ collectDescendantItemStates(parentId, descendents);
return Collections.unmodifiableList(descendents).iterator();
+*/
}
/**
@@ -249,9 +360,59 @@
*/
public Iterator getDescendantTransientItemStatesInAttic(ItemId parentId) {
// @todo need a more efficient way to find descendents in attic (e.g. using hierarchical index)
+ if (!transientStateMgr.hasAnyItemStatesInAttic()) {
+ return Collections.EMPTY_LIST.iterator();
+ }
+ // collection of descendant transient states in attic:
+ // the path serves as key and sort criteria
+ TreeMap descendants = new TreeMap(new PathComparator());
+ try {
+ Path[] parentPaths = hierMgr.getAllPaths(parentId, true);
+ /**
+ * walk through list of transient states in attic and check if
+ * they are descendants of the specified parent
+ */
+ Iterator iter = transientStateMgr.getEntriesInAttic();
+ while (iter.hasNext()) {
+ ItemState state = (ItemState) iter.next();
+ ItemId id = state.getId();
+ Path[] paths = hierMgr.getAllPaths(id, true);
+ boolean isDescendant = false;
+ /**
+ * check if any of the paths to the transient state
+ * is a descendant of any of the specified parentId's paths
+ */
+ for (int i = 0; i < paths.length; i++) {
+ Path p0 = paths[i]; // path to transient state in attic
+ // walk through array of the specified parentId's paths
+ for (int j = 0; j < parentPaths.length; j++) {
+ Path p1 = parentPaths[j]; // path to specified parentId
+ if (p0.isDescendantOf(p1)) {
+ // this is a descendant, add it to the list and
+ // continue with next transient state
+ descendants.put(p0, state);
+ isDescendant = true;
+ break;
+ }
+ }
+ if (isDescendant) {
+ break;
+ }
+ }
+ // continue with next transient state
+ }
+ } catch (MalformedPathException mpe) {
+ log.warn("inconsistent hierarchy state", mpe);
+ } catch (RepositoryException re) {
+ log.warn("inconsistent hierarchy state", re);
+ }
+
+ return descendants.values().iterator();
+/*
ArrayList descendents = new ArrayList();
- collectDescendantItemStatesInAttic(parentId, hierMgr, transientStateMgr, descendents);
+ collectDescendantItemStatesInAttic(parentId, descendents);
return Collections.unmodifiableList(descendents).iterator();
+*/
}
//------< methods for creating & discarding transient ItemState instances >
@@ -373,5 +534,51 @@
public PersistentPropertyState createPersistentPropertyState(String parentUUID, QName propName)
throws ItemStateException {
return persistentStateMgr.createPropertyState(parentUUID, propName);
+ }
+
+ //--------------------------------------------------------< inner classes >
+ /**
+ * Comparator used to sort canonical <code>Path</code> objects
+ * hierarchically (in depth-first tree traversal order).
+ */
+ static class PathComparator implements Comparator {
+ /**
+ *
+ * @param o1
+ * @param o2
+ * @return
+ */
+ public int compare(Object o1, Object o2) {
+ Path p1 = (Path) o1;
+ Path p2 = (Path) o2;
+ if (p1.equals(p2)) {
+ return 0;
+ }
+ try {
+ if (p1.isAncestorOf(p2)) {
+ return -1;
+ } else if (p1.isDescendantOf(p2)) {
+ return 1;
+ }
+ } catch (MalformedPathException mpe) {
+ log.warn("unable to compare non-canonical (i.e. relative) paths", mpe);
+ }
+ // the 2 paths are not on the same graph;
+ // do string comparison of individual path elements
+ Path.PathElement[] pea1 = p1.getElements();
+ Path.PathElement[] pea2 = p2.getElements();
+ for (int i = 0; i < pea1.length; i++) {
+ if (i >= pea2.length) {
+ return 1;
+ }
+ String s1 = pea1[i].toString();
+ String s2 = pea2[i].toString();
+ int result = s1.compareTo(s2);
+ if (result != 0) {
+ return result;
+ }
+ }
+ return 0;
+ }
}
}
1.13 +39 -2 jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/TransientItemStateManager.java
Index: TransientItemStateManager.java
===================================================================
RCS file: /home/cvs/jakarta-slide/proposals/jcrri/src/org/apache/slide/jcr/core/state/TransientItemStateManager.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- TransientItemStateManager.java 2 Aug 2004 16:22:22 -0000 1.12
+++ TransientItemStateManager.java 18 Aug 2004 13:13:52 -0000 1.13
@@ -154,12 +154,49 @@
}
}
- //----------< more methods for listing and retrieving ItemState instances >
+ //------------------< methods for listing & querying state of cache/attic >
/**
* @return
*/
boolean hasAnyItemStates() {
return !isEmpty();
+ }
+
+ /**
+ * @return
+ */
+ boolean hasAnyItemStatesInAttic() {
+ return !attic.isEmpty();
+ }
+
+ /**
+ * @return
+ */
+ int getEntriesCount() {
+ return size();
+ }
+
+ /**
+ * @return
+ */
+ int getEntriesInAtticCount() {
+ return attic.size();
+ }
+
+ /**
+ *
+ * @return
+ */
+ Iterator getEntries() {
+ return entries();
+ }
+
+ /**
+ *
+ * @return
+ */
+ Iterator getEntriesInAttic() {
+ return attic.entries();
}
//----------------< methods for creating & discarding ItemState instances >
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org