[jboss-svn-commits] JBL Code SVN: r19401 - labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Apr 3 18:25:53 EDT 2008


Author: tirelli
Date: 2008-04-03 18:25:53 -0400 (Thu, 03 Apr 2008)
New Revision: 19401

Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java
Log:
JBRULES-1520: fixing accumulate

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java	2008-04-03 22:25:31 UTC (rev 19400)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/AccumulateNode.java	2008-04-03 22:25:53 UTC (rev 19401)
@@ -16,29 +16,26 @@
 
 package org.drools.reteoo;
 
-import java.util.Arrays;
+import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
-import java.io.Externalizable;
+import java.util.Arrays;
 
 import org.drools.RuleBaseConfiguration;
 import org.drools.RuntimeDroolsException;
 import org.drools.common.BetaConstraints;
 import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalWorkingMemory;
-import org.drools.reteoo.CollectNode.CollectMemory;
 import org.drools.reteoo.builder.BuildContext;
 import org.drools.rule.Accumulate;
 import org.drools.rule.ContextEntry;
 import org.drools.spi.AlphaNodeFieldConstraint;
 import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
 import org.drools.util.ArrayUtils;
 import org.drools.util.Entry;
-import org.drools.util.FactEntry;
 import org.drools.util.Iterator;
-import org.drools.util.ObjectHashMap;
-import org.drools.util.ObjectHashMap.ObjectEntry;
 
 /**
  * AccumulateNode
@@ -123,20 +120,19 @@
 
         final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
 
-        AccumulateResult accresult = new AccumulateResult();
+        AccumulateContext accresult = new AccumulateContext();
 
         if ( this.tupleMemoryEnabled ) {
             memory.betaMemory.getLeftTupleMemory().add( leftTuple );
-            memory.resultMap.put( leftTuple,
-                                      accresult,
-                                      false );
+            memory.betaMemory.getCreatedHandles().put( leftTuple,
+                                                       accresult,
+                                                       false );
         }
 
-        final Object accContext = this.accumulate.createContext();
+        accresult.context = this.accumulate.createContext();
 
-        accresult.context = accContext;
         this.accumulate.init( memory.workingMemoryContext,
-                              accContext,
+                              accresult.context,
                               leftTuple,
                               workingMemory );
 
@@ -148,29 +144,33 @@
             InternalFactHandle handle = rightTuple.getFactHandle();
             if ( this.constraints.isAllowedCachedLeft( memory.betaMemory.getContext(),
                                                        handle ) ) {
+                LeftTuple tuple = leftTuple;
                 if ( this.unwrapRightObject ) {
                     // if there is a subnetwork, handle must be unwrapped
-                    LeftTuple tuple = (LeftTuple) handle.getObject();
+                    tuple = (LeftTuple) handle.getObject();
                     handle = tuple.getLastHandle();
-                    this.accumulate.accumulate( memory.workingMemoryContext,
-                                                accContext,
-                                                tuple,
-                                                handle,
-                                                workingMemory );
-                } else {
-                    this.accumulate.accumulate( memory.workingMemoryContext,
-                                                accContext,
-                                                leftTuple,
-                                                handle,
-                                                workingMemory );
                 }
+                this.accumulate.accumulate( memory.workingMemoryContext,
+                                            accresult.context,
+                                            tuple,
+                                            handle,
+                                            workingMemory );
+
+                // in sequential mode, we don't need to keep record of matched tuples
+                if ( this.tupleMemoryEnabled ) {
+                    // linking left and right by creating a new left tuple
+                    new LeftTuple( leftTuple,
+                                   rightTuple,
+                                   this,
+                                   this.tupleMemoryEnabled );
+                }
             }
         }
 
         this.constraints.resetTuple( memory.betaMemory.getContext() );
 
         final Object result = this.accumulate.getResult( memory.workingMemoryContext,
-                                                         accContext,
+                                                         accresult.context,
                                                          leftTuple,
                                                          workingMemory );
 
@@ -178,48 +178,26 @@
             throw new RuntimeDroolsException( "Accumulate must not return a null value." );
         }
 
-        // First alpha node filters
-        boolean isAllowed = true;
         final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( result,
                                                                                               false,
                                                                                               workingMemory ); // so far, result is not an event
-        
-        final RightTuple resultTuple = new RightTuple( handle,
-                                                       this );        
 
-        for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
-            if ( !this.resultConstraints[i].isAllowed( handle,
-                                                       workingMemory,
-                                                       memory.alphaContexts[i] ) ) {
-                isAllowed = false;
-                break;
-            }
-        }
-        if ( isAllowed ) {
-            this.resultBinder.updateFromTuple( memory.resultsContext,
-                                               workingMemory,
-                                               leftTuple );
-            if ( this.resultBinder.isAllowedCachedLeft( memory.resultsContext,
-                                                        handle ) ) {
-                this.sink.propagateAssertLeftTuple( leftTuple,
-                                                    resultTuple,
-                                                    context,
-                                                    workingMemory,
-                                                    this.tupleMemoryEnabled );
-            } else {
-                workingMemory.getFactHandleFactory().destroyFactHandle( handle );
-            }
-        } else {
-            workingMemory.getFactHandleFactory().destroyFactHandle( handle );
-        }
+        accresult.result = new RightTuple( handle,
+                                           this );
 
+        evaluateResultConstraints( leftTuple,
+                                   context,
+                                   workingMemory,
+                                   memory,
+                                   accresult );
+
     }
 
     /**
      * @inheritDoc
      *
-     * As the accumulate node will always propagate the tuple,
-     * it must always also retreat it.
+     * As the accumulate node will always generate a resulting tuple,
+     * we must always destroy it
      *
      */
     public void retractLeftTuple(final LeftTuple leftTuple,
@@ -227,12 +205,25 @@
                                  final InternalWorkingMemory workingMemory) {
         final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
         memory.betaMemory.getLeftTupleMemory().remove( leftTuple );
-        
-        memory.resultMap.remove( leftTuple );
+        final AccumulateContext accctx = (AccumulateContext) memory.betaMemory.getCreatedHandles().remove( leftTuple );
 
-        this.sink.propagateRetractLeftTupleDestroyRightTuple( leftTuple,
-                                                              context,
-                                                              workingMemory );
+        LeftTuple child = getFirstMatch( leftTuple,
+                                         accctx );
+
+        // Now, unlink the matches 
+        while ( child != null ) {
+            LeftTuple tmp = child.getLeftParentNext();
+            child.unlinkFromLeftParent();
+            child.unlinkFromRightParent();
+            child = tmp;
+        }
+
+        if ( accctx.propagated ) {
+            // if tuple was previously propagated, retract it
+            this.sink.propagateRetractLeftTupleDestroyRightTuple( leftTuple,
+                                                                  context,
+                                                                  workingMemory );
+        }
     }
 
     /**
@@ -250,7 +241,7 @@
 
         final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
         final RightTuple rightTuple = new RightTuple( factHandle,
-                                                      this );        
+                                                      this );
         memory.betaMemory.getRightTupleMemory().add( rightTuple );
 
         if ( !this.tupleMemoryEnabled ) {
@@ -271,9 +262,10 @@
                 if ( this.accumulate.supportsReverse() || context.getType() == PropagationContext.ASSERTION ) {
                     modifyTuple( true,
                                  tuple,
-                                 factHandle,
+                                 rightTuple,
                                  context,
-                                 workingMemory );
+                                 workingMemory,
+                                 memory );
                 } else {
                     // context is MODIFICATION and does not supports reverse
                     this.retractLeftTuple( tuple,
@@ -296,78 +288,108 @@
      *  tuple match.
      */
     public void retractRightTuple(final RightTuple rightTuple,
-                              final PropagationContext context,
-                              final InternalWorkingMemory workingMemory) {
+                                  final PropagationContext context,
+                                  final InternalWorkingMemory workingMemory) {
         final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
         memory.betaMemory.getRightTupleMemory().remove( rightTuple );
-        
-        InternalFactHandle handle = rightTuple.getFactHandle(); 
 
-        this.constraints.updateFromFactHandle( memory.betaMemory.getContext(),
-                                               workingMemory,
-                                               handle );
-        // need to clone the tuples to avoid concurrent modification exceptions
-        Entry[] tuples = memory.betaMemory.getLeftTupleMemory().toArray();
-        for ( int i = 0; i < tuples.length; i++ ) {
-            LeftTuple tuple = (LeftTuple) tuples[i];
-            if ( this.constraints.isAllowedCachedRight( memory.betaMemory.getContext(),
-                                                        tuple ) ) {
-                if ( this.accumulate.supportsReverse() ) {
-                    this.modifyTuple( false,
-                                      tuple,
-                                      handle,
+        for ( LeftTuple childTuple = rightTuple.getBetaChildren(); childTuple != null; ) {
+            LeftTuple tmp = childTuple.getRightParentNext();
+            if ( this.accumulate.supportsReverse() ) {
+                this.modifyTuple( false,
+                                  childTuple.getParent(),
+                                  rightTuple,
+                                  context,
+                                  workingMemory,
+                                  memory );
+            } else {
+                // does not support reverse, so needs to be fully retracted and reasserted
+                LeftTuple match = childTuple.getParent();
+                
+                // but first, needs to remove the matching child
+                childTuple.unlinkFromLeftParent();
+                childTuple.unlinkFromRightParent();
+                
+                this.retractLeftTuple( match,
+                                       context,
+                                       workingMemory );
+                this.assertLeftTuple( match,
                                       context,
                                       workingMemory );
-                } else {
-                    this.retractLeftTuple( tuple,
-                                           context,
-                                           workingMemory );
-                    this.assertLeftTuple( tuple,
-                                          context,
-                                          workingMemory );
-                }
             }
+            childTuple = tmp;
         }
 
-        this.constraints.resetFactHandle( memory.betaMemory.getContext() );
     }
 
+    /**
+     * @param rightTuple
+     * @param leftTuple
+     */
+    private void removeMatchingChild(final LeftTuple leftTuple,
+                                     final RightTuple rightTuple ) {
+        if ( leftTuple.getBetaChildren() != null ) {
+            // removing link between left and right
+            LeftTuple match = leftTuple.getBetaChildren();
+            while ( match.getRightParent() != rightTuple ) {
+                match = match.getLeftParentNext();
+            }
+            match.unlinkFromLeftParent();
+            match.unlinkFromRightParent();
+        }
+    }
+
     public void modifyTuple(final boolean isAssert,
                             final LeftTuple leftTuple,
-                            InternalFactHandle handle,
+                            final RightTuple rightTuple,
                             final PropagationContext context,
-                            final InternalWorkingMemory workingMemory) {
+                            final InternalWorkingMemory workingMemory,
+                            final AccumulateMemory memory) {
 
-        final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory( this );
-        AccumulateResult accresult = (AccumulateResult) memory.resultMap.get( leftTuple );
+        final AccumulateContext accctx = (AccumulateContext) memory.betaMemory.getCreatedHandles().get( leftTuple );
 
         // if tuple was propagated
-        this.sink.propagateRetractLeftTupleDestroyRightTuple( leftTuple,
-                                                              context,
-                                                              workingMemory );
+        if ( accctx.propagated ) {
+            LeftTuple firstMatch = getFirstMatch( leftTuple,
+                                                  accctx );
 
+            // we may have no matches yet
+            if ( firstMatch != null ) {
+                // temporarily break the linked list to avoid wrong retracts
+                firstMatch.getLeftParentPrevious().setLeftParentNext( null );
+                firstMatch.setLeftParentPrevious( null );
+            }
+            this.sink.propagateRetractLeftTuple( leftTuple,
+                                                 context,
+                                                 workingMemory );
+            // now set the beta children to the first match
+            leftTuple.setBetaChildren( firstMatch );
+            accctx.propagated = false;
+        }
+
+        if ( isAssert ) {
+            // linking left and right by creating a new left tuple
+            new LeftTuple( leftTuple,
+                           rightTuple,
+                           this,
+                           this.tupleMemoryEnabled );
+        } else {
+            removeMatchingChild( leftTuple,
+                                 rightTuple );
+        }
+
+        // if there is a subnetwork, we need to unwrapp the object from inside the tuple
+        InternalFactHandle handle = rightTuple.getFactHandle();
         LeftTuple tuple = leftTuple;
         if ( this.unwrapRightObject ) {
-            // if there is a subnetwork, handle must be unwrapped
-            tuple = (LeftTuple) handle.getObject();
+            tuple = ((LeftTuple) handle.getObject());
             handle = tuple.getLastHandle();
         }
 
         if ( context.getType() == PropagationContext.ASSERTION ) {
             // assertion
-            if ( accresult.context == null ) {
-                final Object accContext = this.accumulate.createContext();
-
-                this.accumulate.init( memory.workingMemoryContext,
-                                      accContext,
-                                      leftTuple,
-                                      workingMemory );
-
-                accresult.context = accContext;
-            }
-
             this.accumulate.accumulate( memory.workingMemoryContext,
-                                        accresult.context,
+                                        accctx.context,
                                         tuple,
                                         handle,
                                         workingMemory );
@@ -375,13 +397,13 @@
             // modification
             if ( isAssert ) {
                 this.accumulate.accumulate( memory.workingMemoryContext,
-                                            accresult.context,
+                                            accctx.context,
                                             tuple,
                                             handle,
                                             workingMemory );
             } else {
                 this.accumulate.reverse( memory.workingMemoryContext,
-                                         accresult.context,
+                                         accctx.context,
                                          tuple,
                                          handle,
                                          workingMemory );
@@ -389,14 +411,14 @@
         } else {
             // retraction
             this.accumulate.reverse( memory.workingMemoryContext,
-                                     accresult.context,
+                                     accctx.context,
                                      tuple,
                                      handle,
                                      workingMemory );
         }
 
         final Object result = this.accumulate.getResult( memory.workingMemoryContext,
-                                                         accresult.context,
+                                                         accctx.context,
                                                          leftTuple,
                                                          workingMemory );
 
@@ -404,17 +426,36 @@
             throw new RuntimeDroolsException( "Accumulate must not return a null value." );
         }
 
+        // update result object 
+        accctx.result.getFactHandle().setObject( result );
+
+        evaluateResultConstraints( leftTuple,
+                                   context,
+                                   workingMemory,
+                                   memory,
+                                   accctx );
+
+    }
+
+    /**
+     * Evaluate result constraints and propagate assert in case they are true
+     * 
+     * @param leftTuple
+     * @param context
+     * @param workingMemory
+     * @param memory
+     * @param accresult
+     * @param handle
+     */
+    private void evaluateResultConstraints(final LeftTuple leftTuple,
+                                           final PropagationContext context,
+                                           final InternalWorkingMemory workingMemory,
+                                           final AccumulateMemory memory,
+                                           final AccumulateContext accctx ) {
         // First alpha node filters
         boolean isAllowed = true;
-        final InternalFactHandle createdHandle = workingMemory.getFactHandleFactory().newFactHandle( result,
-                                                                                                     false,
-                                                                                                     workingMemory ); // so far, result is not an event
-        
-        final RightTuple resultTuple = new RightTuple( handle,
-                                                       this );
-        
         for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
-            if ( !this.resultConstraints[i].isAllowed( createdHandle,
+            if ( !this.resultConstraints[i].isAllowed( accctx.result.getFactHandle(),
                                                        workingMemory,
                                                        memory.alphaContexts[i] ) ) {
                 isAllowed = false;
@@ -426,22 +467,41 @@
                                                workingMemory,
                                                leftTuple );
             if ( this.resultBinder.isAllowedCachedLeft( memory.resultsContext,
-                                                        createdHandle ) ) {
+                                                        accctx.result.getFactHandle() ) ) {
+                accctx.propagated = true;
                 this.sink.propagateAssertLeftTuple( leftTuple,
-                                                    resultTuple,
+                                                    accctx.result,
                                                     context,
                                                     workingMemory,
                                                     this.tupleMemoryEnabled );
-            } else {
-                workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
             }
-
             this.resultBinder.resetTuple( memory.resultsContext );
-        } else {
-            workingMemory.getFactHandleFactory().destroyFactHandle( createdHandle );
         }
     }
 
+    /**
+     * Skips the propagated tuple handles and return the first handle
+     * in the list that correspond to a match
+     * 
+     * @param leftTuple
+     * @param colctx
+     * @return
+     */
+    private LeftTuple getFirstMatch(final LeftTuple leftTuple,
+                                    final AccumulateContext colctx) {
+        // unlink all right matches 
+        LeftTuple child = leftTuple.getBetaChildren();
+
+        if ( colctx.propagated ) {
+            // To do that, we need to skip the first N children that are in fact
+            // the propagated tuples
+            for ( int i = 0; i < this.sink.size(); i++ ) {
+                child = child.getLeftParentNext();
+            }
+        }
+        return child;
+    }
+
     public void updateSink(final LeftTupleSink sink,
                            final PropagationContext context,
                            final InternalWorkingMemory workingMemory) {
@@ -449,11 +509,10 @@
 
         final Iterator tupleIter = memory.betaMemory.getLeftTupleMemory().iterator();
         for ( LeftTuple leftTuple = (LeftTuple) tupleIter.next(); leftTuple != null; leftTuple = (LeftTuple) tupleIter.next() ) {
-            LeftTuple childLeftTuple = leftTuple.getBetaChildren();
-            if ( childLeftTuple != null ) {
-                RightTuple rightTuple = childLeftTuple.getRightParent();
+            AccumulateContext accctx = (AccumulateContext) memory.betaMemory.getCreatedHandles().get( leftTuple );
+            if( accctx.propagated ) {
                 sink.assertLeftTuple( new LeftTuple( leftTuple,
-                                                     rightTuple,
+                                                     accctx.result,
                                                      sink,
                                                      this.tupleMemoryEnabled ),
                                       context,
@@ -501,7 +560,6 @@
     public Object createMemory(final RuleBaseConfiguration config) {
         AccumulateMemory memory = new AccumulateMemory();
         memory.betaMemory = this.constraints.createBetaMemory( config );
-        memory.resultMap = new ObjectHashMap();
         memory.workingMemoryContext = this.accumulate.createWorkingMemoryContext();
         memory.resultsContext = this.resultBinder.createContext();
         memory.alphaContexts = new ContextEntry[this.resultConstraints.length];
@@ -518,7 +576,6 @@
 
         public Object             workingMemoryContext;
         public BetaMemory         betaMemory;
-        public ObjectHashMap      resultMap;
         public ContextEntry[]     resultsContext;
         public ContextEntry[]     alphaContexts;
 
@@ -526,7 +583,6 @@
                                                 ClassNotFoundException {
             workingMemoryContext = in.readObject();
             betaMemory = (BetaMemory) in.readObject();
-            resultMap = (ObjectHashMap) in.readObject();
             resultsContext = (ContextEntry[]) in.readObject();
             alphaContexts = (ContextEntry[]) in.readObject();
         }
@@ -534,25 +590,30 @@
         public void writeExternal(ObjectOutput out) throws IOException {
             out.writeObject( workingMemoryContext );
             out.writeObject( betaMemory );
-            out.writeObject( resultMap );
             out.writeObject( resultsContext );
             out.writeObject( alphaContexts );
         }
 
     }
 
-    public static class AccumulateResult
+    public static class AccumulateContext
         implements
         Externalizable {
-        public Object             context;
+        public Object     context;
+        public RightTuple result;
+        public boolean    propagated;
 
         public void readExternal(ObjectInput in) throws IOException,
                                                 ClassNotFoundException {
             context = in.readObject();
+            result = (RightTuple) in.readObject();
+            propagated = in.readBoolean();
         }
 
         public void writeExternal(ObjectOutput out) throws IOException {
             out.writeObject( context );
+            out.writeObject( result );
+            out.writeBoolean( propagated );
         }
 
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java	2008-04-03 22:25:31 UTC (rev 19400)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CompositeLeftTupleSinkAdapter.java	2008-04-03 22:25:53 UTC (rev 19401)
@@ -74,15 +74,13 @@
         LeftTuple child = leftTuple.getBetaChildren();
         while ( child != null ) {
             LeftTuple temp = child.getLeftParentNext();
-            //child.unlinkFromParents();
             child.getSink().retractLeftTuple( child,
                                               context,
                                               workingMemory );
             child.unlinkFromRightParent();
-            //child = child.getLeftParentNext();
+            child.unlinkFromLeftParent();
             child = temp;
         }
-        leftTuple.setBetaChildren( null );
     }
 
     public void propagateRetractLeftTupleDestroyRightTuple(final LeftTuple leftTuple,
@@ -96,9 +94,9 @@
                                               workingMemory );
             workingMemory.getFactHandleFactory().destroyFactHandle( child.getRightParent().getFactHandle() );
             child.unlinkFromRightParent();
+            child.unlinkFromLeftParent();
             child = temp;
         }
-        leftTuple.setBetaChildren( null );
     }
 
     public void propagateRetractRightTuple(final RightTuple rightTuple,
@@ -107,15 +105,13 @@
         LeftTuple child = rightTuple.getBetaChildren();
         while ( child != null ) {
             LeftTuple temp = child.getRightParentNext();
-            //child.unlinkFromParents();
             child.getSink().retractLeftTuple( child,
                                               context,
                                               workingMemory );
             child.unlinkFromLeftParent();
-            //child = child.getRightParentNext();
+            child.unlinkFromRightParent();
             child = temp;
         }
-        rightTuple.setBetaChildren( null );
     }
 
     public LeftTupleSink[] getSinks() {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java	2008-04-03 22:25:31 UTC (rev 19400)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/SingleLeftTupleSinkAdapter.java	2008-04-03 22:25:53 UTC (rev 19401)
@@ -51,15 +51,13 @@
         LeftTuple child = leftTuple.getBetaChildren();
         while ( child != null ) {
             LeftTuple temp = child.getLeftParentNext();
-            //child.unlinkFromParents();
             child.getSink().retractLeftTuple( child,
                                               context,
                                               workingMemory );
             child.unlinkFromRightParent();
-            //child = child.getLeftParentNext();
+            child.unlinkFromLeftParent();
             child = temp;
         }
-        leftTuple.setBetaChildren( null );
     }
     
     public void propagateRetractLeftTupleDestroyRightTuple(final LeftTuple leftTuple,
@@ -73,9 +71,9 @@
                                               workingMemory );
             workingMemory.getFactHandleFactory().destroyFactHandle( child.getRightParent().getFactHandle() );
             child.unlinkFromRightParent();
+            child.unlinkFromLeftParent();
             child = temp;
         }
-        leftTuple.setBetaChildren( null );
     }    
 
     public void propagateRetractRightTuple(final RightTuple rightTuple,
@@ -84,15 +82,13 @@
         LeftTuple child = rightTuple.getBetaChildren();
         while ( child != null ) {
             LeftTuple temp = child.getRightParentNext();
-            //child.unlinkFromParents();
             child.getSink().retractLeftTuple( child,
                                               context,
                                               workingMemory );
             child.unlinkFromLeftParent();
-            //child = child.getRightParentNext();
+            child.unlinkFromRightParent();
             child = temp;
         }
-        rightTuple.setBetaChildren( null );
     }
 
     public void createAndPropagateAssertLeftTuple(final InternalFactHandle factHandle,




More information about the jboss-svn-commits mailing list