[jboss-svn-commits] JBL Code SVN: r36533 - labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532/drools-core/src/main/java/org/drools/reteoo.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Jan 14 15:55:54 EST 2011


Author: tsurdilovic
Date: 2011-01-14 15:55:53 -0500 (Fri, 14 Jan 2011)
New Revision: 36533

Modified:
   labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532/drools-core/src/main/java/org/drools/reteoo/EntryPointNode.java
Log:
BRMS-532: Drools Session insert ConcurrentModificationException in Multithreading Environment

Modified: labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532/drools-core/src/main/java/org/drools/reteoo/EntryPointNode.java
===================================================================
--- labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532/drools-core/src/main/java/org/drools/reteoo/EntryPointNode.java	2011-01-14 20:55:20 UTC (rev 36532)
+++ labs/jbossrules/soa_branches/BRMS-5.0.2-GA_BRMS-532/drools-core/src/main/java/org/drools/reteoo/EntryPointNode.java	2011-01-14 20:55:53 UTC (rev 36533)
@@ -1,6 +1,4 @@
-package org.drools.reteoo;
-
-/*
+/**
  * Copyright 2007 JBoss Inc
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,32 +12,32 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
- * Created on January 8th, 2007
  */
 
+package org.drools.reteoo;
+
 import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.drools.base.ShadowProxy;
 import org.drools.common.BaseNode;
 import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.common.InternalWorkingMemoryEntryPoint;
-import org.drools.common.NodeMemory;
 import org.drools.common.PropagationContextImpl;
 import org.drools.common.RuleBasePartitionId;
+import org.drools.core.util.Iterator;
+import org.drools.core.util.ObjectHashSet;
+import org.drools.core.util.ObjectHashSet.ObjectEntry;
 import org.drools.reteoo.builder.BuildContext;
 import org.drools.rule.EntryPoint;
 import org.drools.spi.ObjectType;
 import org.drools.spi.PropagationContext;
-import org.drools.util.Iterator;
-import org.drools.util.ObjectHashSet;
-import org.drools.util.ObjectHashSet.ObjectEntry;
 
 /**
  * A node that is an entry point into the Rete network.
@@ -62,7 +60,7 @@
     // Instance members
     // ------------------------------------------------------------
 
-    private static final long               serialVersionUID = 420L;
+    private static final long               serialVersionUID = 510l;
 
     /**
      * The entry point ID for this node
@@ -102,13 +100,14 @@
                objectSource,
                999 ); // irrelevant for this node, since it overrides sink management
         this.entryPoint = entryPoint;
-        this.objectTypeNodes = new HashMap<ObjectType, ObjectTypeNode>();
+        this.objectTypeNodes = new ConcurrentHashMap<ObjectType, ObjectTypeNode>();
     }
 
     // ------------------------------------------------------------
     // Instance methods
     // ------------------------------------------------------------
 
+    @SuppressWarnings("unchecked")
     public void readExternal(ObjectInput in) throws IOException,
                                             ClassNotFoundException {
         super.readExternal( in );
@@ -148,6 +147,45 @@
                                          workingMemory );
         }
     }
+    
+    public void modifyObject(final InternalFactHandle handle,
+                             final PropagationContext context,
+                             final ObjectTypeConf objectTypeConf,
+                             final InternalWorkingMemory workingMemory) {
+        // checks if shadow is enabled
+        if ( objectTypeConf.isShadowEnabled() ) {
+            // the user has implemented the ShadowProxy interface, let their implementation
+            // know it is safe to update the information the engine can see.
+            ((ShadowProxy) handle.getObject()).updateProxy();
+        }
+        
+        ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();
+        
+        // make a reference to the previous tuples, then null then on the handle
+        ModifyPreviousTuples modifyPreviousTuples = new ModifyPreviousTuples(handle.getFirstLeftTuple(), handle.getFirstRightTuple() );
+        handle.setFirstLeftTuple( null );
+        handle.setFirstRightTuple( null );
+        handle.setLastLeftTuple( null );
+        handle.setLastRightTuple( null ); 
+        
+        for ( int i = 0, length = cachedNodes.length; i < length; i++ ) {
+            cachedNodes[i].modifyObject( handle,
+                                         modifyPreviousTuples,
+                                         context, workingMemory );
+        }     
+        modifyPreviousTuples.retractTuples( context, workingMemory );
+        
+      
+    }
+    
+    public void modifyObject(InternalFactHandle factHandle,
+                                   ModifyPreviousTuples modifyPreviousTuples,
+                                   PropagationContext context,
+                                   InternalWorkingMemory workingMemory) {
+        // this method was silently failing, so I am now throwing an exception to make
+        // sure no one calls it by mistake
+        throw new UnsupportedOperationException( "This method should NEVER EVER be called" );
+    }    
 
     /**
      * This is the entry point into the network for all asserted Facts. Iterates a cache
@@ -182,8 +220,6 @@
                               final PropagationContext context,
                               final ObjectTypeConf objectTypeConf,
                               final InternalWorkingMemory workingMemory) {
-        final Object object = handle.getObject();
-
         ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes();
 
         if ( cachedNodes == null ) {
@@ -207,7 +243,7 @@
      *            <code>Objects</code>. Rete only accepts <code>ObjectTypeNode</code>s
      *            as parameters to this method, though.
      */
-    protected void addObjectSink(final ObjectSink objectSink) {
+    public void addObjectSink(final ObjectSink objectSink) {
         final ObjectTypeNode node = (ObjectTypeNode) objectSink;
         this.objectTypeNodes.put( node.getObjectType(),
                                   node );
@@ -227,6 +263,7 @@
 
         for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
             final InternalWorkingMemory workingMemory = workingMemories[i];
+            workingMemory.updateEntryPointsCache();
             final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                       PropagationContext.RULE_ADDITION,
                                                                                       null,
@@ -244,10 +281,6 @@
                             final InternalWorkingMemory[] workingMemories) {
         final ObjectTypeNode objectTypeNode = (ObjectTypeNode) node;
         removeObjectSink( objectTypeNode );
-        for ( int i = 0; i < workingMemories.length; i++ ) {
-            // clear the node memory for each working memory.
-            workingMemories[i].clearNodeMemory( (NodeMemory) node );
-        }
     }
 
     public Map<ObjectType, ObjectTypeNode> getObjectTypeNodes() {



More information about the jboss-svn-commits mailing list