Update of /var/cvs/src/org/mmbase/module/core
In directory james.mmbase.org:/tmp/cvs-serv19404

Modified Files:
      Tag: MMBase-1_8
        TransactionManager.java 
Log Message:
refactored a bit to be able to resolve the performance penalty introducecd to 
fix  MMB-1680 (backport)


See also: http://cvs.mmbase.org/viewcvs/src/org/mmbase/module/core
See also: http://www.mmbase.org/jira/browse/MMB-1680


Index: TransactionManager.java
===================================================================
RCS file: /var/cvs/src/org/mmbase/module/core/TransactionManager.java,v
retrieving revision 1.34
retrieving revision 1.34.2.1
diff -u -b -r1.34 -r1.34.2.1
--- TransactionManager.java     6 Jul 2006 11:24:44 -0000       1.34
+++ TransactionManager.java     4 Nov 2008 18:37:34 -0000       1.34.2.1
@@ -19,7 +19,7 @@
 /**
  * @javadoc
  * @author Rico Jansen
- * @version $Id: TransactionManager.java,v 1.34 2006/07/06 11:24:44 michiel 
Exp $
+ * @version $Id: TransactionManager.java,v 1.34.2.1 2008/11/04 18:37:34 
michiel Exp $
  */
 public class TransactionManager implements TransactionManagerInterface {
 
@@ -222,45 +222,25 @@
     private final static int NODE = 3;
     private final static int RELATION = 4;
 
-    boolean performCommits(Object user, Collection nodes) {
-        if (nodes == null || nodes.size() == 0) {
-            log.warn("Empty list of nodes");
-            return true;
+    private class NodeState {
+        public int exists;
+        public int state;
+        public boolean changed = true;
         }
 
-        int[] nodestate = new int[nodes.size()];
-        int[] nodeexist = new int[nodes.size()];
-        String username = findUserName(user),exists;
+    /**
+     * @since MMBase-1.8.7
+     */
+    private void commitNode(Object user, MMObjectNode node, NodeState state) {
 
-        log.debug("Checking types and existance");
+        if (state.exists == I_EXISTS_YES ) {
+            if (! state.changed) return;
+            // Commit also if not changed, because the node may have been 
deleted or changed by
+            // someone else. It is like this in the transaction it should be 
saved like this.
+            // See also MMB-1680
+            // TODO: what is the performance penalty here?
 
-        int i = 0;
-        for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); 
i++) {
-            MMObjectNode node = (MMObjectNode)nodeIterator.next();
-            // Nodes are uncommited by default
-            nodestate[i] = UNCOMMITED;
-            exists = node.getStringValue("_exists");
-            if (exists == null) {
-                throw new IllegalStateException("The _exists field does not 
exist on node "+node);
-            } else if (exists.equals(EXISTS_NO)) {
-                nodeexist[i]=I_EXISTS_NO;
-            } else if (exists.equals(EXISTS_YES)) {
-                nodeexist[i]=I_EXISTS_YES;
-            } else if (exists.equals(EXISTS_NOLONGER)) {
-                nodeexist[i]=I_EXISTS_NOLONGER;
-            } else {
-                throw new IllegalStateException("Invalid value for _exists on 
node "+node);
-            }
-        }
 
-        log.debug("Commiting nodes");
-
-        // First commit all the NODES
-        i = 0;
-        for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); 
i++) {
-            MMObjectNode node = (MMObjectNode)nodeIterator.next();
-            if (!(node.getBuilder() instanceof InsRel)) {
-                if (nodeexist[i] == I_EXISTS_YES ) {
                     // use safe commit, which locks the node cache
                     boolean commitOK;
                     if (user instanceof UserContext) {
@@ -269,108 +249,141 @@
                         commitOK = node.parent.safeCommit(node);
                     }
                     if (commitOK) {
-                        nodestate[i] = COMMITED;
+                state.state = COMMITED;
                     } else {
-                        nodestate[i] = FAILED;
+                state.state = FAILED;
                     }
-                } else if (nodeexist[i] == I_EXISTS_NO ) {
+        } else if (state.exists == I_EXISTS_NO ) {
                     int insertOK;
                     if (user instanceof UserContext) {
                         insertOK = node.insert((UserContext)user);
                     } else {
+                String username = findUserName(user);
                         insertOK = node.parent.safeInsert(node, username);
                     }
                     if (insertOK > 0) {
-                        nodestate[i] = COMMITED;
+                state.state = COMMITED;
                     } else {
-                        nodestate[i] = FAILED;
+                state.state = FAILED;
                         String message = "When this failed, it is possible 
that the creation of an insrel went right, which leads to a database 
inconsistency..  stop now.. (transaction 2.0: [rollback?])";
-                        log.error(message);
                         throw new RuntimeException(message);
                     }
                 }
             }
+
+    boolean performCommits(Object user, Collection nodes) {
+        if (nodes == null || nodes.size() == 0) {
+            log.warn("Empty list of nodes");
+            return true;
         }
 
-        log.debug("Commiting relations");
+        Map stati = new HashMap();
 
-        // Then commit all the RELATIONS
-        i = 0;
-        for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); 
i++) {
+        String username = findUserName(user);
+
+        log.debug("Checking types and existance");
+
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
             MMObjectNode node = (MMObjectNode)nodeIterator.next();
-            if (node.getBuilder() instanceof InsRel) {
-                // excactly the same code as 10 lines ago. Should be 
dispatched to some method..
-                if (nodeexist[i] == I_EXISTS_YES ) {
-                    boolean commitOK;
-                    if (user instanceof UserContext) {
-                        commitOK = node.commit((UserContext)user);
+            NodeState state = new NodeState();
+            state.state = UNCOMMITED;
+            state.changed = node.isChanged() || node.isNew();
+            // Nodes are uncommited by default
+            String exists = node.getStringValue("_exists");
+            if (exists == null) {
+                throw new IllegalStateException("The _exists field does not 
exist on node "+node);
+            } else if (exists.equals(EXISTS_NO)) {
+                state.exists = I_EXISTS_NO;
+            } else if (exists.equals(EXISTS_YES)) {
+                state.exists = I_EXISTS_YES;
+            } else if (exists.equals(EXISTS_NOLONGER)) {
+                state.exists = I_EXISTS_NOLONGER;
                     } else {
-                        commitOK = node.parent.safeCommit(node);
+                throw new IllegalStateException("Invalid value for _exists on 
node "+node);
                     }
-                    if (commitOK) {
-                        nodestate[i] = COMMITED;
-                    } else {
-                        nodestate[i] = FAILED;
+            stati.put(new Integer(node.getNumber()), state);
                     }
-                } else if (nodeexist[i] == I_EXISTS_NO ) {
-                    int insertOK;
-                    if (user instanceof UserContext) {
-                        insertOK = node.insert((UserContext)user);
-                    } else {
-                        insertOK = node.parent.safeInsert(node, username);
+
+        // Now set the 'chanaged' flag of all node to or frm a relation was 
made.
+        // Related to MMB-1680
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
+            MMObjectNode node = (MMObjectNode)nodeIterator.next();
+            if (node.getBuilder() instanceof InsRel) {
+                NodeState state = (NodeState) stati.get(new 
Integer(node.getNumber()));
+                if (state.changed) {
+                    NodeState sstate = (NodeState) stati.get(new 
Integer(node.getIntValue("snumber")));
+                    sstate.changed = true;
+                    NodeState dstate = (NodeState) stati.get(new 
Integer(node.getIntValue("dnumber")));
+                    dstate.changed = true;
                     }
-                    if (insertOK > 0) {
-                        nodestate[i] = COMMITED;
-                    } else {
-                        nodestate[i] = FAILED;
-                        String message = "relation failed(transaction 2.0: 
[rollback?])";
-                        log.error(message);
+
+            }
+        }
+
+
+        log.debug("Commiting nodes");
+
+        // First commit all the NODES
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
+            MMObjectNode node = (MMObjectNode)nodeIterator.next();
+            if (!(node.getBuilder() instanceof InsRel)) {
+                NodeState state = (NodeState) stati.get(new 
Integer(node.getNumber()));
+                commitNode(user, node, state);
                     }
                 }
+
+        log.debug("Commiting relations");
+
+        // Then commit all the RELATIONS
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
+            MMObjectNode node = (MMObjectNode)nodeIterator.next();
+            if (node.getBuilder() instanceof InsRel) {
+                NodeState state = (NodeState) stati.get(new 
Integer(node.getNumber()));
+                commitNode(user, node, state);
             }
         }
 
         log.debug("Deleting relations");
 
         // Then commit all the RELATIONS that must be deleted
-        i = 0;
-        for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); 
i++) {
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
             MMObjectNode node = (MMObjectNode)nodeIterator.next();
-            if (node.getBuilder() instanceof InsRel && nodeexist[i] == 
I_EXISTS_NOLONGER) {
+            NodeState state = (NodeState) stati.get(new 
Integer(node.getNumber()));
+            if (node.getBuilder() instanceof InsRel && state.exists == 
I_EXISTS_NOLONGER) {
                 // no return information
                 if (user instanceof UserContext) {
                     node.remove((UserContext)user);
                 } else {
                     node.parent.removeNode(node);
                 }
-                nodestate[i]=COMMITED;
+                state.state = COMMITED;
             }
         }
 
         log.debug("Deleting nodes");
         // Then commit all the NODES that must be deleted
-        i = 0;
-        for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); 
i++) {
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
             MMObjectNode node = (MMObjectNode)nodeIterator.next();
-            if (!(node.getBuilder() instanceof InsRel) && (nodeexist[i] == 
I_EXISTS_NOLONGER)) {
+            NodeState state = (NodeState) stati.get(new 
Integer(node.getNumber()));
+            if (!(node.getBuilder() instanceof InsRel) && (state.exists == 
I_EXISTS_NOLONGER)) {
                 // no return information
                 if (user instanceof UserContext) {
                     node.remove((UserContext)user);
                 } else {
                     node.parent.removeNode(node);
                 }
-                nodestate[i]=COMMITED;
+                state.state = COMMITED;
             }
         }
 
         // check for failures
-        boolean okay=true;
-        i = 0;
-        for (Iterator nodeIterator = nodes.iterator(); nodeIterator.hasNext(); 
i++) {
+        boolean okay = true;
+        for (Iterator nodeIterator = nodes.iterator(); 
nodeIterator.hasNext();) {
             MMObjectNode node = (MMObjectNode)nodeIterator.next();
-            if (nodestate[i] == FAILED) {
-                okay=false;
-                log.error("Failed node "+node.toString());
+            NodeState state = (NodeState) stati.get(new 
Integer(node.getNumber()));
+            if (state.state == FAILED) {
+                okay = false;
+                log.error("Failed node " + node.toString());
             }
         }
         return okay;
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to