[jboss-svn-commits] JBL Code SVN: r19397 - 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 15:07:07 EDT 2008
Author: tirelli
Date: 2008-04-03 15:07:07 -0400 (Thu, 03 Apr 2008)
New Revision: 19397
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java
Log:
JBRULES-1520: fixing collect node
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java 2008-04-03 17:02:16 UTC (rev 19396)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java 2008-04-03 19:07:07 UTC (rev 19397)
@@ -1,6 +1,5 @@
package org.drools.reteoo;
-import java.io.Serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
@@ -53,6 +52,13 @@
public LeftTupleMemory getLeftTupleMemory() {
return this.leftTupleMemory;
}
+
+ public ObjectHashMap getCreatedHandles() {
+ if( this.createdHandles == null ) {
+ this.createdHandles = new ObjectHashMap();
+ }
+ return this.createdHandles;
+ }
/**
* @return the context
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java 2008-04-03 17:02:16 UTC (rev 19396)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/CollectNode.java 2008-04-03 19:07:07 UTC (rev 19397)
@@ -126,6 +126,7 @@
public void assertLeftTuple(final LeftTuple leftTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+ if ( this.getId() == 7 ) System.out.println( "AssertLeft : " + leftTuple );
final CollectMemory memory = (CollectMemory) workingMemory.getNodeMemory( this );
@@ -133,12 +134,16 @@
final InternalFactHandle resultHandle = workingMemory.getFactHandleFactory().newFactHandle( result,
false,
workingMemory );
- final RightTuple resultTuple = new RightTuple( resultHandle,
- this );
+ final CollectContext colctx = new CollectContext();
+ colctx.resultTuple = new RightTuple( resultHandle,
+ this );
+
// do not add tuple and result to the memory in sequential mode
if ( this.tupleMemoryEnabled ) {
memory.betaMemory.getLeftTupleMemory().add( leftTuple );
+ memory.betaMemory.getCreatedHandles().put( leftTuple,
+ colctx );
}
this.constraints.updateFromTuple( memory.betaMemory.getContext(),
@@ -154,38 +159,24 @@
}
result.add( handle.getObject() );
- // linking left tuple to the right tuple children list
- leftTuple.setRightParentNext( rightTuple.getBetaChildren() );
- rightTuple.setBetaChildren( leftTuple );
+ // 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() );
- // First alpha node filters
- boolean isAllowed = true;
- for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
- if ( !this.resultConstraints[i].isAllowed( resultHandle,
- workingMemory,
- memory.alphaContexts[i] ) ) {
- isAllowed = false;
- break;
- }
- }
- if ( isAllowed ) {
- this.resultsBinder.updateFromTuple( memory.resultsContext,
- workingMemory,
- leftTuple );
- if ( this.resultsBinder.isAllowedCachedLeft( memory.resultsContext,
- resultHandle ) ) {
- this.sink.propagateAssertLeftTuple( leftTuple,
- resultTuple,
- context,
- workingMemory,
- this.tupleMemoryEnabled );
- }
- this.resultsBinder.resetTuple( memory.resultsContext );
- }
+ evaluateResultConstraints( leftTuple,
+ context,
+ workingMemory,
+ memory,
+ colctx );
}
/**
@@ -195,15 +186,52 @@
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+ if ( this.getId() == 7 ) System.out.println( "RetractLeft : " + leftTuple );
+
final CollectMemory memory = (CollectMemory) workingMemory.getNodeMemory( this );
memory.betaMemory.getLeftTupleMemory().remove( leftTuple );
+ final CollectContext colctx = (CollectContext) memory.betaMemory.getCreatedHandles().remove( leftTuple );
- this.sink.propagateRetractLeftTupleDestroyRightTuple( leftTuple,
- context,
- workingMemory );
+ LeftTuple child = getFirstMatch( leftTuple,
+ colctx );
+
+ // Now, unlink the matches
+ while ( child != null ) {
+ LeftTuple tmp = child.getLeftParentNext();
+ child.unlinkFromLeftParent();
+ child.unlinkFromRightParent();
+ child = tmp;
+ }
+
+ if ( colctx.propagated ) {
+ // if tuple was previously propagated, retract it
+ this.sink.propagateRetractLeftTupleDestroyRightTuple( leftTuple,
+ context,
+ workingMemory );
+ }
}
/**
+ * @param leftTuple
+ * @param colctx
+ * @return
+ */
+ private LeftTuple getFirstMatch(final LeftTuple leftTuple,
+ final CollectContext 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;
+ }
+
+ /**
* @inheritDoc
*
* When a new object is asserted into a CollectNode, do this:
@@ -216,6 +244,8 @@
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+ if ( this.getId() == 7 ) System.out.println( "AssertRight : " + factHandle );
+
final CollectMemory memory = (CollectMemory) workingMemory.getNodeMemory( this );
final RightTuple rightTuple = new RightTuple( factHandle,
this );
@@ -232,6 +262,7 @@
factHandle );
// need to clone the tuples to avoid concurrent modification exceptions
+ // @TODO: now that we use linked lists, can we avoid the cloning?
Entry[] tuples = memory.betaMemory.getLeftTupleMemory().toArray();
for ( int i = 0; i < tuples.length; i++ ) {
LeftTuple tuple = (LeftTuple) tuples[i];
@@ -241,7 +272,8 @@
tuple,
rightTuple,
context,
- workingMemory );
+ workingMemory,
+ memory );
}
}
@@ -257,22 +289,31 @@
public void retractRightTuple(final RightTuple rightTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+ if ( this.getId() == 7 ) System.out.println( "retractRight: " + rightTuple );
+
final CollectMemory memory = (CollectMemory) workingMemory.getNodeMemory( this );
memory.betaMemory.getRightTupleMemory().remove( rightTuple );
- this.constraints.updateFromFactHandle( memory.betaMemory.getContext(),
- workingMemory,
- rightTuple.getFactHandle() );
-
- for ( LeftTuple leftTuple = rightTuple.getBetaChildren(); leftTuple != null; leftTuple = rightTuple.getBetaChildren() ) {
+ for ( LeftTuple leftTuple = getFirstMatchFromRight( rightTuple ); leftTuple != null; ) {
+ LeftTuple tmp = leftTuple.getRightParentNext();
this.modifyTuple( false,
- leftTuple,
+ leftTuple.getParent(),
rightTuple,
context,
- workingMemory );
+ workingMemory,
+ memory );
+ leftTuple = tmp;
}
}
+ private LeftTuple getFirstMatchFromRight(RightTuple rightTuple) {
+ LeftTuple match = rightTuple.getBetaChildren();
+ while( match.getRightParent() != rightTuple ) {
+ match = match.getRightParentNext();
+ }
+ return match;
+ }
+
/**
* Modifies the results match for a tuple, retracting it and repropagating
* if constraints allow it
@@ -286,19 +327,46 @@
final LeftTuple leftTuple,
final RightTuple rightTuple,
final PropagationContext context,
- final InternalWorkingMemory workingMemory) {
+ final InternalWorkingMemory workingMemory,
+ final CollectMemory memory) {
- final CollectMemory memory = (CollectMemory) workingMemory.getNodeMemory( this );
+ final CollectContext colctx = (CollectContext) memory.betaMemory.getCreatedHandles().get( leftTuple );
- RightTuple result = leftTuple.getBetaChildren().getRightParent();
-
// if tuple was propagated
- if ( leftTuple.getBetaChildren() != null ) {
+ if ( colctx.propagated ) {
+ LeftTuple firstMatch = getFirstMatch( leftTuple, colctx );
+
+ // we may have no matches yet
+ if( firstMatch != null ) {
+ // temporarily break the linked list to avoid wrong retracts
+ firstMatch.getLeftParentPrevious().setLeftParentNext( null );
+ }
this.sink.propagateRetractLeftTuple( leftTuple,
context,
workingMemory );
+ // now set the beta children to the first match
+ leftTuple.setBetaChildren( firstMatch );
+ colctx.propagated = false;
}
+ if( isAssert ) {
+ // linking left and right by creating a new left tuple
+ new LeftTuple( leftTuple,
+ rightTuple,
+ this,
+ this.tupleMemoryEnabled );
+ } else {
+ 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();
+ }
+ }
+
// if there is a subnetwork, we need to unwrapp the object from inside the tuple
InternalFactHandle handle = rightTuple.getFactHandle();
if ( this.unwrapRightObject ) {
@@ -306,22 +374,42 @@
}
if ( context.getType() == PropagationContext.ASSERTION ) {
- ((Collection) result.getFactHandle().getObject()).add( handle.getObject() );
+ ((Collection) colctx.resultTuple.getFactHandle().getObject()).add( handle.getObject() );
} else if ( context.getType() == PropagationContext.RETRACTION ) {
- ((Collection) result.getFactHandle().getObject()).remove( handle.getObject() );
- rightTuple.setBetaChildren( leftTuple.getRightParentNext() );
+ ((Collection) colctx.resultTuple.getFactHandle().getObject()).remove( handle.getObject() );
} else if ( context.getType() == PropagationContext.MODIFICATION || context.getType() == PropagationContext.RULE_ADDITION || context.getType() == PropagationContext.RULE_REMOVAL ) {
if ( isAssert ) {
- ((Collection) result.getFactHandle().getObject()).add( handle.getObject() );
+ ((Collection) colctx.resultTuple.getFactHandle().getObject()).add( handle.getObject() );
} else {
- ((Collection) result.getFactHandle().getObject()).remove( handle.getObject() );
+ ((Collection) colctx.resultTuple.getFactHandle().getObject()).remove( handle.getObject() );
}
}
+
+ evaluateResultConstraints( leftTuple,
+ context,
+ workingMemory,
+ memory,
+ colctx );
+ }
+ /**
+ * Evaluate result constraints and propagate tuple if it evaluates to true
+ *
+ * @param leftTuple
+ * @param context
+ * @param workingMemory
+ * @param memory
+ * @param colctx
+ */
+ private void evaluateResultConstraints(final LeftTuple leftTuple,
+ final PropagationContext context,
+ final InternalWorkingMemory workingMemory,
+ final CollectMemory memory,
+ final CollectContext colctx) {
// First alpha node filters
boolean isAllowed = true;
for ( int i = 0, length = this.resultConstraints.length; i < length; i++ ) {
- if ( !this.resultConstraints[i].isAllowed( result.getFactHandle(),
+ if ( !this.resultConstraints[i].isAllowed( colctx.resultTuple.getFactHandle(),
workingMemory,
memory.alphaContexts[i] ) ) {
isAllowed = false;
@@ -333,9 +421,10 @@
workingMemory,
leftTuple );
if ( this.resultsBinder.isAllowedCachedLeft( memory.resultsContext,
- result.getFactHandle() ) ) {
+ colctx.resultTuple.getFactHandle() ) ) {
+ colctx.propagated = true;
this.sink.propagateAssertLeftTuple( leftTuple,
- result,
+ colctx.resultTuple,
context,
workingMemory,
this.tupleMemoryEnabled );
@@ -420,4 +509,14 @@
public ContextEntry[] resultsContext;
public ContextEntry[] alphaContexts;
}
+
+ private static class CollectContext
+ implements
+ Serializable {
+ private static final long serialVersionUID = -3076306175989410574L;
+ public RightTuple resultTuple;
+ public boolean propagated;
+
+ }
+
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java 2008-04-03 17:02:16 UTC (rev 19396)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java 2008-04-03 19:07:07 UTC (rev 19397)
@@ -12,7 +12,6 @@
import org.drools.spi.Activation;
import org.drools.spi.Tuple;
import org.drools.util.Entry;
-import org.drools.util.RightTupleList;
import org.drools.util.LeftTupleList;
public class LeftTuple
@@ -495,4 +494,8 @@
// @todo should not serialise in part of the rete network
out.writeObject( sink );
}
+
+ public LeftTuple getParent() {
+ return parent;
+ }
}
More information about the jboss-svn-commits
mailing list