You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2006/02/17 18:20:04 UTC

svn commit: r378574 - /incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java

Author: mreutegg
Date: Fri Feb 17 09:20:00 2006
New Revision: 378574

URL: http://svn.apache.org/viewcvs?rev=378574&view=rev
Log:
- use copy-on-write in NodeState for: child node entries, mixin type names and property names.

Modified:
    incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java

Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java?rev=378574&r1=378573&r2=378574&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java (original)
+++ incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java Fri Feb 17 09:20:00 2006
@@ -60,7 +60,7 @@
     /**
      * the names of this node's mixin types
      */
-    private HashSet mixinTypeNames = new HashSet();
+    private Set mixinTypeNames = Collections.EMPTY_SET;
 
     /**
      * the id of this node state.
@@ -83,11 +83,23 @@
     private ChildNodeEntries childNodeEntries = new ChildNodeEntries();
 
     /**
+     * Set to <code>true</code> if {@link #childNodeEntries} are shared between
+     * different <code>NodeState</code> instance.
+     */
+    private boolean sharedChildNodeEntries = false;
+
+    /**
      * set of property names (QName objects)
      */
     private HashSet propertyNames = new HashSet();
 
     /**
+     * Set to <code>true</code> if {@link #propertyNames} is shared between
+     * different <code>NodeState</code> instances.
+     */
+    private boolean sharedPropertyNames = false;
+
+    /**
      * Listeners (weak references)
      */
     private final transient Collection listeners = new WeakIdentityCollection(3);
@@ -132,10 +144,12 @@
             id = nodeState.id;
             parentId = nodeState.parentId;
             nodeTypeName = nodeState.nodeTypeName;
-            mixinTypeNames = (HashSet) nodeState.mixinTypeNames.clone();
+            mixinTypeNames = nodeState.mixinTypeNames;
             defId = nodeState.defId;
-            propertyNames = (HashSet) nodeState.propertyNames.clone();
-            childNodeEntries = (ChildNodeEntries) nodeState.childNodeEntries.clone();
+            propertyNames = nodeState.propertyNames;
+            sharedPropertyNames = nodeState.sharedPropertyNames = true;
+            childNodeEntries = nodeState.childNodeEntries;
+            sharedChildNodeEntries = nodeState.sharedChildNodeEntries = true;
         }
     }
 
@@ -208,8 +222,11 @@
      * @param names set of names of mixin types
      */
     public synchronized void setMixinTypeNames(Set names) {
-        mixinTypeNames.clear();
-        mixinTypeNames.addAll(names);
+        if (names instanceof HashSet) {
+            mixinTypeNames = (Set) ((HashSet) names).clone();
+        } else {
+            mixinTypeNames = new HashSet(names);
+        }
     }
 
     /**
@@ -349,6 +366,10 @@
      */
     public synchronized ChildNodeEntry addChildNodeEntry(QName nodeName,
                                                          NodeId id) {
+        if (sharedChildNodeEntries) {
+            childNodeEntries = (ChildNodeEntries) childNodeEntries.clone();
+            sharedChildNodeEntries = false;
+        }
         ChildNodeEntry entry = childNodeEntries.add(nodeName, id);
         notifyNodeAdded(entry);
         return entry;
@@ -365,6 +386,10 @@
      */
     public synchronized boolean renameChildNodeEntry(QName oldName, int index,
                                                      QName newName) {
+        if (sharedChildNodeEntries) {
+            childNodeEntries = (ChildNodeEntries) childNodeEntries.clone();
+            sharedChildNodeEntries = false;
+        }
         ChildNodeEntry oldEntry = childNodeEntries.remove(oldName, index);
         if (oldEntry != null) {
             ChildNodeEntry newEntry =
@@ -385,6 +410,10 @@
      *         in the list of child node entries and could be removed.
      */
     public synchronized boolean removeChildNodeEntry(QName nodeName, int index) {
+        if (sharedChildNodeEntries) {
+            childNodeEntries = (ChildNodeEntries) childNodeEntries.clone();
+            sharedChildNodeEntries = false;
+        }
         ChildNodeEntry entry = childNodeEntries.remove(nodeName, index);
         if (entry != null) {
             notifyNodeRemoved(entry);
@@ -400,6 +429,10 @@
      *         in the list of child node entries and could be removed.
      */
     public synchronized boolean removeChildNodeEntry(NodeId id) {
+        if (sharedChildNodeEntries) {
+            childNodeEntries = (ChildNodeEntries) childNodeEntries.clone();
+            sharedChildNodeEntries = false;
+        }
         ChildNodeEntry entry = childNodeEntries.remove(id);
         if (entry != null) {
             notifyNodeRemoved(entry);
@@ -411,6 +444,10 @@
      * Removes all <code>ChildNodeEntry</code>s.
      */
     public synchronized void removeAllChildNodeEntries() {
+        if (sharedChildNodeEntries) {
+            childNodeEntries = (ChildNodeEntries) childNodeEntries.clone();
+            sharedChildNodeEntries = false;
+        }
         childNodeEntries.removeAll();
     }
 
@@ -423,9 +460,16 @@
             // optimization
             ChildNodeEntries entries = (ChildNodeEntries) nodeEntries;
             childNodeEntries = (ChildNodeEntries) entries.clone();
+            sharedChildNodeEntries = false;
         } else {
-            childNodeEntries.removeAll();
+            if (sharedChildNodeEntries) {
+                childNodeEntries = new ChildNodeEntries();
+                sharedChildNodeEntries = false;
+            } else {
+                childNodeEntries.removeAll();
+            }
             childNodeEntries.addAll(nodeEntries);
+
         }
         notifyNodesReplaced();
     }
@@ -448,6 +492,10 @@
      * @param propName <code>QName</code> object specifying the property name
      */
     public synchronized void addPropertyName(QName propName) {
+        if (sharedPropertyNames) {
+            propertyNames = (HashSet) propertyNames.clone();
+            sharedPropertyNames = false;
+        }
         propertyNames.add(propName);
     }
 
@@ -459,6 +507,10 @@
      *         in the list of property name entries and could be removed.
      */
     public synchronized boolean removePropertyName(QName propName) {
+        if (sharedPropertyNames) {
+            propertyNames = (HashSet) propertyNames.clone();
+            sharedPropertyNames = false;
+        }
         return propertyNames.remove(propName);
     }
 
@@ -466,7 +518,12 @@
      * Removes all property name entries.
      */
     public synchronized void removeAllPropertyNames() {
-        propertyNames.clear();
+        if (sharedPropertyNames) {
+            propertyNames = new HashSet();
+            sharedPropertyNames = false;
+        } else {
+            propertyNames.clear();
+        }
     }
 
     /**
@@ -476,10 +533,17 @@
     public synchronized void setPropertyNames(Set propNames) {
         if (propNames instanceof HashSet) {
             HashSet names = (HashSet) propNames;
-            propNames = (HashSet) names.clone();
+            propertyNames = (HashSet) names.clone();
+            sharedPropertyNames = false;
+        } else {
+            if (sharedPropertyNames) {
+                propertyNames = new HashSet();
+                sharedPropertyNames = false;
+            } else {
+                propertyNames.clear();
+            }
+            propertyNames.addAll(propNames);
         }
-        propertyNames.clear();
-        propertyNames.addAll(propNames);
     }
 
     /**



Re: svn commit: r378574 - /incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java

Posted by Marcel Reutegger <ma...@gmx.net>.
just wanted to give some more details on the NodeState change I did last 
friday. Even though the actual code change is only minor, the underlying 
concept changed somewhat more significant.

Instead of cloning state information in NodeState on read, child node 
entries, mixin type names and property names are now cloned on write.

Mixin type names are copied on each write, as I think those change only 
rarely and the size of the collection is rather small.

Property names and in particular child node entries now have an 
additional flag that indicates if the collection is shared. The shared 
flag is set if the collection (prop names or child node entries) is 
shallow-copied in NodeState.copy(). From that point on the collection 
must not be changed anymore. If a NodeState modifies e.g. child node 
entries, it first has to check if it is shared and in effect read-only. 
If it is shared the NodeState then clones the read-only child node 
entries, modifies the resulting child node entries and resets the shared 
flag.

With this change the usage of ChildNodeEntries.clone() drops significantly.

# of clone() calls while running o.a.j.test.api.TestAll:

Before: ~84'000

After:   ~4'100

regards
  marcel

mreutegg@apache.org wrote:
> Author: mreutegg
> Date: Fri Feb 17 09:20:00 2006
> New Revision: 378574
> 
> URL: http://svn.apache.org/viewcvs?rev=378574&view=rev
> Log:
> - use copy-on-write in NodeState for: child node entries, mixin type names and property names.
> 
> Modified:
>     incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java
> 
> Modified: incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java
> URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/state/NodeState.java?rev=378574&r1=378573&r2=378574&view=diff