This is an automated email from the ASF dual-hosted git repository.
mariofusco pushed a commit to branch 8.44.x
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/8.44.x by this push:
new 29ae61b055 [KIE-1064] simplify session serialization by adding dormant
activations to rule executor (#5852)
29ae61b055 is described below
commit 29ae61b0550128600c2f7cd4a762a4d856c9dcf5
Author: mdproctor <[email protected]>
AuthorDate: Fri Apr 19 06:14:45 2024 +0100
[KIE-1064] simplify session serialization by adding dormant activations to
rule executor (#5852)
backported from main
---
.../org/drools/core/common/ActivationsManager.java | 2 +-
.../drools/core/common/AgendaGroupsManager.java | 8 +-
.../org/drools/core/phreak/EagerPhreakBuilder.java | 5 +-
.../org/drools/core/phreak/LazyPhreakBuilder.java | 5 +-
.../org/drools/core/phreak/PhreakBranchNode.java | 42 ++--
.../drools/core/phreak/PhreakRuleTerminalNode.java | 84 ++++----
.../java/org/drools/core/phreak/RuleExecutor.java | 135 +++++++++---
.../org/drools/core/reteoo/AlphaTerminalNode.java | 8 +-
.../drools/core/reteoo/ModifyPreviousTuples.java | 2 +-
.../org/drools/core/reteoo/RuleTerminalNode.java | 2 +-
.../core/reteoo/RuleTerminalNodeLeftTuple.java | 19 +-
.../main/java/org/drools/core/util/LinkedList.java | 2 +-
.../java/org/drools/core/util/index/TupleList.java | 14 +-
.../drools/kiesession/agenda/DefaultAgenda.java | 2 +-
.../iterators/PhreakActivationIterator.java | 230 +++------------------
.../integrationtests/ExecutionFlowControlTest.java | 12 +-
...MaintenanceSystemRuleTerminalNodeLeftTuple.java | 2 +-
17 files changed, 252 insertions(+), 322 deletions(-)
diff --git
a/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
b/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
index bee0ce5d22..14139c6c23 100644
--- a/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
+++ b/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
@@ -93,7 +93,7 @@ public interface ActivationsManager {
if (!ruleAgendaItem.isQueued()) {
ruleAgendaItem.getRuleExecutor().getPathMemory().queueRuleAgendaItem(this);
}
- ruleAgendaItem.getRuleExecutor().addLeftTuple( justified.getTuple() );
+
ruleAgendaItem.getRuleExecutor().modifyActiveTuple((RuleTerminalNodeLeftTuple)
justified.getTuple() );
}
default ActivationsManager getPartitionedAgenda(int partitionNr) {
diff --git
a/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
b/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
index 320be2dd17..73b5337bd9 100644
--- a/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
+++ b/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
@@ -216,8 +216,8 @@ public interface AgendaGroupsManager extends Externalizable
{
}
int count = 0;
for ( RuleAgendaItem item : mainAgendaGroup.getActivations() ) {
- if (!(item.getRuleExecutor().getLeftTupleList().isEmpty())) {
- count = count +
item.getRuleExecutor().getLeftTupleList().size();
+ if (!(item.getRuleExecutor().getActiveMatches().isEmpty())) {
+ count = count +
item.getRuleExecutor().getActiveMatches().size();
}
}
return count;
@@ -510,8 +510,8 @@ public interface AgendaGroupsManager extends Externalizable
{
int count = 0;
for ( RuleAgendaItem item : group.getActivations() ) {
- if (!item.getRuleExecutor().getLeftTupleList().isEmpty()) {
- count = count +
item.getRuleExecutor().getLeftTupleList().size();
+ if (!item.getRuleExecutor().getActiveMatches().isEmpty()) {
+ count = count +
item.getRuleExecutor().getActiveMatches().size();
}
}
return count;
diff --git
a/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
b/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
index 3c58d684a5..765b26b77d 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
@@ -47,6 +47,7 @@ import org.drools.core.reteoo.PathMemory;
import org.drools.core.reteoo.QueryElementNode;
import org.drools.core.reteoo.RightInputAdapterNode;
import org.drools.core.reteoo.RightTuple;
+import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
import org.drools.core.reteoo.RuntimeComponentFactory;
import org.drools.core.reteoo.SegmentMemory;
import org.drools.core.reteoo.SegmentMemory.MemoryPrototype;
@@ -1224,7 +1225,7 @@ public class EagerPhreakBuilder implements PhreakBuilder {
TerminalNode rtn = ( TerminalNode ) node;
InternalAgenda agenda = wm.getAgenda();
RuleAgendaItem agendaItem =
AlphaTerminalNode.getRuleAgendaItem( wm, agenda, rtn, insert );
- PhreakRuleTerminalNode.doLeftTupleInsert( rtn,
agendaItem.getRuleExecutor(), agenda, agendaItem, peer );
+ PhreakRuleTerminalNode.doLeftTupleInsert( rtn,
agendaItem.getRuleExecutor(), agenda, agendaItem, (RuleTerminalNodeLeftTuple)
peer);
}
return peer;
}
@@ -1253,7 +1254,7 @@ public class EagerPhreakBuilder implements PhreakBuilder {
if (NodeTypeEnums.isTerminalNode(lt.getTupleSink())) {
PathMemory pmem = (PathMemory)
wm.getNodeMemories().peekNodeMemory( lt.getTupleSink() );
if (pmem != null) {
- PhreakRuleTerminalNode.doLeftDelete(
pmem.getActualActivationsManager( wm ),
pmem.getRuleAgendaItem().getRuleExecutor(), lt );
+ PhreakRuleTerminalNode.doLeftDelete(
pmem.getActualActivationsManager( wm ),
pmem.getRuleAgendaItem().getRuleExecutor(), (RuleTerminalNodeLeftTuple) lt );
}
} else {
if (lt.getContextObject() instanceof AccumulateContext) {
diff --git
a/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
b/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
index 698e2fb244..862f828189 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
@@ -57,6 +57,7 @@ import org.drools.core.reteoo.QueryElementNode;
import org.drools.core.reteoo.RightInputAdapterNode;
import org.drools.core.reteoo.RightInputAdapterNode.RiaPathMemory;
import org.drools.core.reteoo.RightTuple;
+import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
import org.drools.core.reteoo.RuntimeComponentFactory;
import org.drools.core.reteoo.SegmentMemory;
import org.drools.core.reteoo.SegmentNodeMemory;
@@ -975,7 +976,7 @@ class LazyPhreakBuilder implements PhreakBuilder {
TerminalNode rtn = ( TerminalNode ) node;
InternalAgenda agenda = wm.getAgenda();
RuleAgendaItem agendaItem =
AlphaTerminalNode.getRuleAgendaItem( wm, agenda, rtn, insert );
- PhreakRuleTerminalNode.doLeftTupleInsert( rtn,
agendaItem.getRuleExecutor(), agenda, agendaItem, peer );
+ PhreakRuleTerminalNode.doLeftTupleInsert( rtn,
agendaItem.getRuleExecutor(), agenda, agendaItem, (RuleTerminalNodeLeftTuple)
peer);
}
return peer;
}
@@ -1004,7 +1005,7 @@ class LazyPhreakBuilder implements PhreakBuilder {
if (NodeTypeEnums.isTerminalNode(lt.getTupleSink())) {
PathMemory pmem = (PathMemory)
wm.getNodeMemories().peekNodeMemory( lt.getTupleSink() );
if (pmem != null) {
- PhreakRuleTerminalNode.doLeftDelete(
pmem.getActualActivationsManager( wm ),
pmem.getRuleAgendaItem().getRuleExecutor(), lt );
+ PhreakRuleTerminalNode.doLeftDelete(
pmem.getActualActivationsManager( wm ),
pmem.getRuleAgendaItem().getRuleExecutor(), (RuleTerminalNodeLeftTuple) lt );
}
} else {
if (lt.getContextObject() instanceof AccumulateContext) {
diff --git
a/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
b/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
index 8cd2b535c9..d72d9a606c 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
@@ -15,6 +15,7 @@
package org.drools.core.phreak;
+import org.drools.base.reteoo.NodeTypeEnums;
import org.drools.core.common.ActivationsManager;
import org.drools.core.common.TupleSets;
import org.drools.core.reteoo.ConditionalBranchEvaluator;
@@ -24,6 +25,7 @@ import
org.drools.core.reteoo.ConditionalBranchNode.ConditionalBranchMemory;
import org.drools.core.reteoo.LeftTuple;
import org.drools.core.reteoo.LeftTupleSink;
import org.drools.core.reteoo.RuleTerminalNode;
+import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
import static
org.drools.core.phreak.RuleNetworkEvaluator.normalizeStagedTuples;
@@ -62,8 +64,6 @@ public class PhreakBranchNode {
RuleExecutor executor) {
ConditionalBranchEvaluator branchEvaluator =
branchNode.getBranchEvaluator();
- RuleAgendaItem ruleAgendaItem = executor.getRuleAgendaItem();
-
for (LeftTuple leftTuple = srcLeftTuples.getInsertFirst(); leftTuple
!= null; ) {
LeftTuple next = leftTuple.getStagedNext();
@@ -74,9 +74,10 @@ public class PhreakBranchNode {
if (conditionalExecution != null) {
RuleTerminalNode rtn = (RuleTerminalNode)
conditionalExecution.getSink().getFirstLeftTupleSink();
- LeftTuple branchedLeftTuple = rtn.createLeftTuple(leftTuple,
- rtn,
-
leftTuple.getPropagationContext(), useLeftMemory);
+ RuleTerminalNodeLeftTuple branchedLeftTuple =
(RuleTerminalNodeLeftTuple) rtn.createLeftTuple(leftTuple,
+
rtn,
+
leftTuple.getPropagationContext(),
+
useLeftMemory);
PhreakRuleTerminalNode.doLeftTupleInsert( rtn, executor,
activationsManager,
executor.getRuleAgendaItem(), branchedLeftTuple) ;
breaking = conditionalExecution.isBreaking();
@@ -102,7 +103,6 @@ public class PhreakBranchNode {
TupleSets<LeftTuple> stagedLeftTuples,
RuleExecutor executor) {
ConditionalBranchEvaluator branchEvaluator =
branchNode.getBranchEvaluator();
- RuleAgendaItem ruleAgendaItem = executor.getRuleAgendaItem();
for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple
!= null; ) {
LeftTuple next = leftTuple.getStagedNext();
@@ -129,7 +129,7 @@ public class PhreakBranchNode {
if (newRtn == null) {
// old exits, new does not, so delete
if ( branchTuples.rtnLeftTuple.getMemory() != null ) {
- executor.removeLeftTuple(branchTuples.rtnLeftTuple);
+ executor.removeActiveTuple(branchTuples.rtnLeftTuple);
}
PhreakRuleTerminalNode.doLeftDelete(activationsManager,
executor, branchTuples.rtnLeftTuple);
@@ -140,21 +140,21 @@ public class PhreakBranchNode {
} else {
// old and new on different branches, delete one and
insert the other
if ( branchTuples.rtnLeftTuple.getMemory() != null ) {
- executor.removeLeftTuple(branchTuples.rtnLeftTuple);
+ executor.removeActiveTuple(branchTuples.rtnLeftTuple);
}
PhreakRuleTerminalNode.doLeftDelete(activationsManager,
executor, branchTuples.rtnLeftTuple);
- branchTuples.rtnLeftTuple =
newRtn.createLeftTuple(leftTuple,
- newRtn,
-
leftTuple.getPropagationContext(), true);
+ branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple)
newRtn.createLeftTuple(leftTuple,
+
newRtn,
+
leftTuple.getPropagationContext(), true);
PhreakRuleTerminalNode.doLeftTupleInsert( newRtn,
executor, activationsManager,
executor.getRuleAgendaItem(), branchTuples.rtnLeftTuple) ;
}
} else if (newRtn != null) {
// old does not exist, new exists, so insert
- branchTuples.rtnLeftTuple = newRtn.createLeftTuple(leftTuple,
newRtn,
-
leftTuple.getPropagationContext(), true);
+ branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple)
newRtn.createLeftTuple(leftTuple, newRtn,
+
leftTuple.getPropagationContext(), true);
PhreakRuleTerminalNode.doLeftTupleInsert( newRtn, executor,
activationsManager,
executor.getRuleAgendaItem(), branchTuples.rtnLeftTuple) ;
}
@@ -163,12 +163,12 @@ public class PhreakBranchNode {
if (branchTuples.mainLeftTuple != null) {
normalizeStagedTuples( stagedLeftTuples,
branchTuples.mainLeftTuple );
- if (!breaking) {
- // child exist, new one does, so update
- trgLeftTuples.addUpdate(branchTuples.mainLeftTuple);
- } else {
+ if (breaking &&
!NodeTypeEnums.isTerminalNode(branchTuples.mainLeftTuple.getTupleSink())) {
// child exist, new one does not, so delete
trgLeftTuples.addDelete(branchTuples.mainLeftTuple);
+ } else {
+ // child exist, new one does, so update
+ trgLeftTuples.addUpdate(branchTuples.mainLeftTuple);
}
} else if (!breaking) {
// child didn't exist, new one does, so insert
@@ -195,7 +195,7 @@ public class PhreakBranchNode {
if (branchTuples.rtnLeftTuple != null) {
if ( branchTuples.rtnLeftTuple.getMemory() != null ) {
- executor.removeLeftTuple(branchTuples.rtnLeftTuple);
+ executor.removeActiveTuple(branchTuples.rtnLeftTuple);
}
PhreakRuleTerminalNode.doLeftDelete(activationsManager,
executor, branchTuples.rtnLeftTuple);
}
@@ -225,14 +225,14 @@ public class PhreakBranchNode {
if ( child.getTupleSink() == sink ) {
branchTuples.mainLeftTuple = child;
} else {
- branchTuples.rtnLeftTuple = child;
+ branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple) child;
}
child = child.getHandleNext();
if ( child != null ) {
if ( child.getTupleSink() == sink ) {
branchTuples.mainLeftTuple = child;
} else {
- branchTuples.rtnLeftTuple = child;
+ branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple)
child;
}
}
}
@@ -240,7 +240,7 @@ public class PhreakBranchNode {
}
private static class BranchTuples {
- LeftTuple rtnLeftTuple;
+ RuleTerminalNodeLeftTuple rtnLeftTuple;
LeftTuple mainLeftTuple;
}
}
diff --git
a/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
b/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
index 1ea2957922..2e2f0c1709 100644
---
a/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
+++
b/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
@@ -33,13 +33,6 @@ import org.drools.core.rule.consequence.InternalMatch;
import org.kie.api.definition.rule.Rule;
import org.kie.api.event.rule.MatchCancelledCause;
-/**
-* Created with IntelliJ IDEA.
-* User: mdproctor
-* Date: 03/05/2013
-* Time: 15:42
-* To change this template use File | Settings | File Templates.
-*/
public class PhreakRuleTerminalNode {
public void doNode(TerminalNode rtnNode,
ActivationsManager activationsManager,
@@ -70,8 +63,8 @@ public class PhreakRuleTerminalNode {
activationsManager.getAgendaGroupsManager().setFocus(
ruleAgendaItem.getAgendaGroup() );
}
- for (LeftTuple leftTuple = srcLeftTuples.getInsertFirst(); leftTuple
!= null; ) {
- LeftTuple next = leftTuple.getStagedNext();
+ for (RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple)
srcLeftTuples.getInsertFirst(); leftTuple != null; ) {
+ RuleTerminalNodeLeftTuple next = (RuleTerminalNodeLeftTuple)
leftTuple.getStagedNext();
doLeftTupleInsert(rtnNode, executor, activationsManager,
ruleAgendaItem, leftTuple);
@@ -91,10 +84,10 @@ public class PhreakRuleTerminalNode {
}
public static void doLeftTupleInsert(TerminalNode rtnNode, RuleExecutor
executor,
ActivationsManager
activationsManager, RuleAgendaItem ruleAgendaItem,
- LeftTuple leftTuple) {
+ RuleTerminalNodeLeftTuple leftTuple) {
ReteEvaluator reteEvaluator = activationsManager.getReteEvaluator();
if ( reteEvaluator.getRuleSessionConfiguration().isDirectFiring() ) {
- executor.addLeftTuple(leftTuple);
+ executor.addActiveTuple(leftTuple);
return;
}
@@ -108,32 +101,32 @@ public class PhreakRuleTerminalNode {
pctx = leftTuple.getPropagationContext();
}
- int salienceInt = getSalienceValue(rtnNode, ruleAgendaItem,
(InternalMatch) leftTuple, reteEvaluator);
+ int salienceInt = getSalienceValue(rtnNode, ruleAgendaItem, leftTuple,
reteEvaluator);
- RuleTerminalNodeLeftTuple rtnLeftTuple = (RuleTerminalNodeLeftTuple)
leftTuple;
- activationsManager.createAgendaItem( rtnLeftTuple, salienceInt, pctx,
ruleAgendaItem, ruleAgendaItem.getAgendaGroup() );
+ activationsManager.createAgendaItem( leftTuple, salienceInt, pctx,
ruleAgendaItem, ruleAgendaItem.getAgendaGroup() );
-
activationsManager.getAgendaEventSupport().fireActivationCreated(rtnLeftTuple,
activationsManager.getReteEvaluator());
+
activationsManager.getAgendaEventSupport().fireActivationCreated(leftTuple,
activationsManager.getReteEvaluator());
if ( rtnNode.getRule().isLockOnActive() && pctx.getType() !=
PropagationContext.Type.RULE_ADDITION ) {
pctx = leftTuple.findMostRecentPropagationContext();
InternalAgendaGroup agendaGroup =
executor.getRuleAgendaItem().getAgendaGroup();
if (blockedByLockOnActive(rtnNode.getRule(), pctx, agendaGroup)) {
-
activationsManager.getAgendaEventSupport().fireActivationCancelled(rtnLeftTuple,
reteEvaluator, MatchCancelledCause.FILTER );
+
activationsManager.getAgendaEventSupport().fireActivationCancelled(leftTuple,
reteEvaluator, MatchCancelledCause.FILTER );
return;
}
}
- if (activationsManager.getActivationsFilter() != null &&
!activationsManager.getActivationsFilter().accept( rtnLeftTuple )) {
+ if (activationsManager.getActivationsFilter() != null &&
!activationsManager.getActivationsFilter().accept( leftTuple )) {
// only relevant for seralization, to not refire Matches already
fired
+ executor.addDormantTuple(leftTuple );
return;
}
- executor.addLeftTuple( leftTuple );
+ executor.addActiveTuple(leftTuple);
- activationsManager.addItemToActivationGroup( rtnLeftTuple );
+ activationsManager.addItemToActivationGroup( leftTuple );
if ( !rtnNode.isFireDirect() && executor.isDeclarativeAgendaEnabled()
) {
- insertAndStageActivation( reteEvaluator, rtnLeftTuple );
+ insertAndStageActivation( reteEvaluator, leftTuple );
}
}
@@ -160,8 +153,8 @@ public class PhreakRuleTerminalNode {
activationsManager.getAgendaGroupsManager().setFocus(ruleAgendaItem.getAgendaGroup());
}
- for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple
!= null; ) {
- LeftTuple next = leftTuple.getStagedNext();
+ for (RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple)
srcLeftTuples.getUpdateFirst(); leftTuple != null; ) {
+ RuleTerminalNodeLeftTuple next = (RuleTerminalNodeLeftTuple)
leftTuple.getStagedNext();
doLeftTupleUpdate(rtnNode, executor, activationsManager,
leftTuple);
@@ -171,14 +164,13 @@ public class PhreakRuleTerminalNode {
}
public static void doLeftTupleUpdate(TerminalNode rtnNode, RuleExecutor
executor,
- ActivationsManager
activationsManager, LeftTuple leftTuple) {
- RuleTerminalNodeLeftTuple rtnLeftTuple = (RuleTerminalNodeLeftTuple)
leftTuple;
+ ActivationsManager
activationsManager, RuleTerminalNodeLeftTuple leftTuple) {
ReteEvaluator reteEvaluator = activationsManager.getReteEvaluator();
if ( reteEvaluator.getRuleSessionConfiguration().isDirectFiring() ) {
- if (!rtnLeftTuple.isQueued() ) {
- executor.addLeftTuple( leftTuple );
- reteEvaluator.getRuleEventSupport().onUpdateMatch(
rtnLeftTuple );
+ if (!leftTuple.isQueued() ) {
+ executor.modifyActiveTuple(leftTuple );
+ reteEvaluator.getRuleEventSupport().onUpdateMatch( leftTuple );
}
return;
}
@@ -187,7 +179,7 @@ public class PhreakRuleTerminalNode {
boolean blocked = false;
if ( executor.isDeclarativeAgendaEnabled() ) {
- if ( rtnLeftTuple.hasBlockers() ) {
+ if ( leftTuple.hasBlockers() ) {
blocked = true; // declarativeAgenda still blocking LeftTuple,
so don't add back ot list
}
} else {
@@ -197,10 +189,11 @@ public class PhreakRuleTerminalNode {
}
}
- int salienceInt = getSalienceValue(rtnNode,
executor.getRuleAgendaItem(), (InternalMatch) leftTuple, reteEvaluator);
+ int salienceInt = getSalienceValue(rtnNode,
executor.getRuleAgendaItem(), leftTuple, reteEvaluator);
- if (activationsManager.getActivationsFilter() != null &&
!activationsManager.getActivationsFilter().accept( rtnLeftTuple)) {
+ if (activationsManager.getActivationsFilter() != null &&
!activationsManager.getActivationsFilter().accept( leftTuple)) {
// only relevant for serialization, to not re-fire Matches already
fired
+ executor.addDormantTuple(leftTuple);
return;
}
@@ -214,23 +207,23 @@ public class PhreakRuleTerminalNode {
}
}
if ( addToExector ) {
- if (!rtnLeftTuple.isQueued() ) {
+ if (!leftTuple.isQueued() ) {
// not queued, so already fired, so it's effectively
recreated
-
activationsManager.getAgendaEventSupport().fireActivationCreated( rtnLeftTuple,
reteEvaluator );
+
activationsManager.getAgendaEventSupport().fireActivationCreated( leftTuple,
reteEvaluator );
- rtnLeftTuple.update( salienceInt, pctx );
- executor.addLeftTuple( leftTuple );
- reteEvaluator.getRuleEventSupport().onUpdateMatch(
rtnLeftTuple );
+ leftTuple.update( salienceInt, pctx );
+ executor.modifyActiveTuple(leftTuple );
+ reteEvaluator.getRuleEventSupport().onUpdateMatch(
leftTuple );
}
}
} else {
// LeftTuple is blocked, and thus not queued, so just update it's
values
- rtnLeftTuple.update(salienceInt, pctx);
+ leftTuple.update(salienceInt, pctx);
}
if( !rtnNode.isFireDirect() && executor.isDeclarativeAgendaEnabled()) {
- modifyActivation(reteEvaluator, rtnLeftTuple);
+ modifyActivation(reteEvaluator, leftTuple);
}
}
@@ -249,22 +242,23 @@ public class PhreakRuleTerminalNode {
for (LeftTuple leftTuple = srcLeftTuples.getDeleteFirst(); leftTuple
!= null; ) {
LeftTuple next = leftTuple.getStagedNext();
- doLeftDelete(activationsManager, executor, leftTuple);
+ doLeftDelete(activationsManager, executor,
(RuleTerminalNodeLeftTuple) leftTuple);
leftTuple.clearStaged();
leftTuple = next;
}
}
- public static void doLeftDelete(ActivationsManager activationsManager,
RuleExecutor executor, Tuple leftTuple) {
- RuleTerminalNodeLeftTuple rtnLt = ( RuleTerminalNodeLeftTuple )
leftTuple;
- rtnLt.setMatched( false );
+ public static void doLeftDelete(ActivationsManager activationsManager,
RuleExecutor executor, RuleTerminalNodeLeftTuple leftTuple) {
+ leftTuple.setMatched( false );
- rtnLt.cancelActivation( activationsManager );
+ leftTuple.cancelActivation( activationsManager );
if ( leftTuple.getMemory() != null ) {
// Expiration propagations should not be removed from the list, as
they still need to fire
- executor.removeLeftTuple(leftTuple);
+ executor.removeActiveTuple( leftTuple );
+ } else if ( leftTuple.getStagedType() == Tuple.DELETE &&
!leftTuple.isQueued() ) {
+ executor.removeDormantTuple( leftTuple );
}
leftTuple.setContextObject( null );
@@ -282,10 +276,10 @@ public class PhreakRuleTerminalNode {
if ( isActive && activatedForRecency < handleRecency &&
agendaGroup.getAutoFocusActivator() != pctx ) {
return true;
- } else {
- return clearedForRecency != -1 && clearedForRecency >=
handleRecency;
}
+ return clearedForRecency != -1 && clearedForRecency >=
handleRecency;
+
}
return false;
}
diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
index df3b9f06c7..64d677ddbd 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
@@ -27,12 +27,14 @@ import org.drools.core.common.ReteEvaluator;
import org.drools.core.conflict.MatchConflictResolver;
import org.drools.core.conflict.RuleAgendaConflictResolver;
import org.drools.core.event.RuleEventListenerSupport;
+import org.drools.core.reteoo.AbstractTuple;
import org.drools.core.reteoo.PathMemory;
import org.drools.core.reteoo.RuleTerminalNode;
import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
import org.drools.core.reteoo.Tuple;
import org.drools.core.rule.consequence.InternalMatch;
import org.drools.core.rule.consequence.KnowledgeHelper;
+import org.drools.core.util.LinkedList;
import org.drools.core.util.Queue;
import org.drools.core.util.QueueFactory;
import org.drools.core.util.index.TupleList;
@@ -44,12 +46,15 @@ import org.slf4j.LoggerFactory;
public class RuleExecutor {
+ private static final boolean DEBUG_DORMANT_TUPLE = true;
+
protected static final Logger log =
LoggerFactory.getLogger(RuleExecutor.class);
private final PathMemory pmem;
- private final RuleAgendaItem ruleAgendaItem;
- private final TupleList tupleList;
- private final Queue<InternalMatch> queue;
+ private final RuleAgendaItem ruleAgendaItem;
+ private final TupleList activeMatches;
+ private final DormantTupleList dormantMatches;
+ private final Queue<InternalMatch> queue;
private volatile boolean dirty;
private final boolean declarativeAgendaEnabled;
private boolean fireExitedEarly;
@@ -58,12 +63,38 @@ public class RuleExecutor {
RuleAgendaItem ruleAgendaItem,
boolean declarativeAgendaEnabled) {
this.pmem = pmem;
- this.ruleAgendaItem = ruleAgendaItem;
- this.tupleList = new TupleList();
+ this.ruleAgendaItem = ruleAgendaItem;
+ this.activeMatches = new TupleList();
+ this.dormantMatches = new DormantTupleList();
this.declarativeAgendaEnabled = declarativeAgendaEnabled;
this.queue = ruleAgendaItem.getRule().getSalience().isDynamic() ?
QueueFactory.createQueue(MatchConflictResolver.INSTANCE) : null;
}
+ public static class DormantTupleList<C> extends TupleList<C> {
+ public DormantTupleList() {
+ }
+
+ public DormantTupleList(C c) {
+ super(c);
+ }
+
+ public DormantTupleList( Tuple first, Tuple last, int size ) {
+ super( first, last, size );
+ }
+
+ public void add(final Tuple tuple) {
+ if ( this.last != null ) {
+ this.last.setNext( (AbstractTuple) tuple );
+ tuple.setPrevious( this.last );
+ this.last = tuple;
+ } else {
+ this.first = tuple;
+ this.last = tuple;
+ }
+ this.size++;
+ }
+ }
+
public int evaluateNetworkAndFire( ReteEvaluator reteEvaluator,
AgendaFilter filter,
int fireCount,
@@ -85,15 +116,15 @@ public class RuleExecutor {
private int doDirectFirings(ActivationsManager activationsManager,
AgendaFilter filter, ReteEvaluator reteEvaluator) {
RuleTerminalNode rtn = (RuleTerminalNode) pmem.getPathEndNode();
- int directFirings = tupleList.size();
+ int directFirings = activeMatches.size();
- for (Tuple tuple = tupleList.getFirst(); tuple != null; tuple =
tupleList.getFirst()) {
+ for (Tuple tuple = activeMatches.getFirst(); tuple != null; tuple =
activeMatches.getFirst()) {
if (cancelAndContinue(reteEvaluator, rtn, tuple, filter)) {
directFirings--;
} else {
fireActivationEvent(reteEvaluator, activationsManager,
(InternalMatch) tuple, ((InternalMatch) tuple).getConsequence());
}
- removeLeftTuple( tuple );
+ removeActiveTuple((RuleTerminalNodeLeftTuple) tuple);
}
ruleAgendaItem.remove();
return directFirings;
@@ -114,7 +145,7 @@ public class RuleExecutor {
int fireLimit) {
int localFireCount = 0;
- if (!tupleList.isEmpty()) {
+ if (!activeMatches.isEmpty()) {
if (!fireExitedEarly && isDeclarativeAgendaEnabled()) {
// Network Evaluation can notify meta rules, which should be
given a chance to fire first
RuleAgendaItem nextRule = activationsManager.peekNextRule();
@@ -185,17 +216,19 @@ public class RuleExecutor {
}
private Tuple getNextTuple() {
- if (tupleList.isEmpty()) {
+ if (activeMatches.isEmpty()) {
return null;
}
Tuple leftTuple;
if (queue != null) {
leftTuple = (Tuple) queue.dequeue();
- tupleList.remove(leftTuple);
+ activeMatches.remove(leftTuple);
} else {
- leftTuple = tupleList.removeFirst();
+ leftTuple = activeMatches.removeFirst();
((InternalMatch) leftTuple).setQueued(false);
}
+
+ addDormantTuple((RuleTerminalNodeLeftTuple) leftTuple);
return leftTuple;
}
@@ -204,7 +237,7 @@ public class RuleExecutor {
}
public void removeRuleAgendaItemWhenEmpty(ReteEvaluator reteEvaluator) {
- if (!dirty && tupleList.isEmpty()) {
+ if (!dirty && activeMatches.isEmpty()) {
if (log.isTraceEnabled()) {
log.trace("Removing RuleAgendaItem " + ruleAgendaItem);
}
@@ -280,40 +313,81 @@ public class RuleExecutor {
return RuleAgendaConflictResolver.doCompare(ruleAgendaItem, nextRule)
>= 0;
}
- public TupleList getLeftTupleList() {
- return tupleList;
+ public TupleList getActiveMatches() {
+ return activeMatches;
+ }
+
+ public DormantTupleList getDormantMatches() {
+ return dormantMatches;
+ }
+
+ public void addDormantTuple(RuleTerminalNodeLeftTuple tuple) {
+ if (DEBUG_DORMANT_TUPLE) {
+ if (tuple.isDormant()) {
+ throw new IllegalStateException();
+ }
+ }
+ dormantMatches.add(tuple);
+ if (DEBUG_DORMANT_TUPLE) {
+ tuple.setDormant(true);
+ }
}
- public void addLeftTuple(Tuple tuple) {
- ((InternalMatch) tuple).setQueued(true);
- this.tupleList.add(tuple);
+ public void removeDormantTuple(RuleTerminalNodeLeftTuple tuple) {
+ if (DEBUG_DORMANT_TUPLE) {
+ if (!tuple.isDormant()) {
+ throw new IllegalStateException();
+ }
+ }
+ dormantMatches.remove(tuple);
+ if (DEBUG_DORMANT_TUPLE) {
+ tuple.setDormant(false);
+ }
+ }
+
+ public void addActiveTuple(RuleTerminalNodeLeftTuple tuple) {
+ tuple.setQueued(true);
+ if (DEBUG_DORMANT_TUPLE) {
+ if (tuple.isDormant()) {
+ throw new IllegalStateException();
+ }
+ }
+ this.activeMatches.add(tuple);
if (queue != null) {
addQueuedLeftTuple(tuple);
}
}
- public void addQueuedLeftTuple(Tuple tuple) {
- int currentSalience = queue.isEmpty() ? 0 : queue.peek().getSalience();
- queue.enqueue((InternalMatch) tuple);
- updateSalience(currentSalience);
+ public void modifyActiveTuple(RuleTerminalNodeLeftTuple tuple) {
+ removeDormantTuple(tuple);
+ addActiveTuple(tuple);
}
- public void removeLeftTuple(Tuple tuple) {
- ((InternalMatch) tuple).setQueued(false);
- this.tupleList.remove(tuple);
+ public void removeActiveTuple(RuleTerminalNodeLeftTuple tuple) {
+ tuple.setQueued(false);
+ activeMatches.remove(tuple);
+ if (tuple.getStagedType() != Tuple.DELETE) {
+ addDormantTuple(tuple);
+ }
if (queue != null) {
removeQueuedLeftTuple(tuple);
}
}
- private void removeQueuedLeftTuple(Tuple tuple) {
+ public void addQueuedLeftTuple(RuleTerminalNodeLeftTuple tuple) {
+ int currentSalience = queue.isEmpty() ? 0 : queue.peek().getSalience();
+ queue.enqueue(tuple);
+ updateSalience(currentSalience);
+ }
+
+ private void removeQueuedLeftTuple(RuleTerminalNodeLeftTuple tuple) {
int currentSalience = queue.isEmpty() ? 0 : queue.peek().getSalience();
- queue.dequeue(((InternalMatch) tuple));
+ queue.dequeue((tuple));
updateSalience(currentSalience);
}
private void updateSalience(int currentSalience) {
- // the queue may be emtpy if no more matches are left, so reset it to
default salience 0
+ // the queue may be empty if no more matches are left, so reset it to
default salience 0
int newSalience = queue.isEmpty() ?
SalienceInteger.DEFAULT_SALIENCE.getValue() : queue.peek().getSalience();
if (currentSalience != newSalience) {
// salience changed, so the RuleAgendaItem needs to be removed and
re-added, for sorting
@@ -326,8 +400,8 @@ public class RuleExecutor {
}
public void cancel(ReteEvaluator reteEvaluator, EventSupport es) {
- while (!tupleList.isEmpty()) {
- RuleTerminalNodeLeftTuple rtnLt = (RuleTerminalNodeLeftTuple)
tupleList.removeFirst();
+ while (!activeMatches.isEmpty()) {
+ RuleTerminalNodeLeftTuple rtnLt = (RuleTerminalNodeLeftTuple)
activeMatches.removeFirst();
if (queue != null) {
queue.dequeue(rtnLt);
}
@@ -391,7 +465,6 @@ public class RuleExecutor {
internalMatch.setActive(false);
knowledgeHelper.reset();
} catch ( final Exception e ) {
- e.printStackTrace();
knowledgeHelper.restoreActivationOnConsequenceFailure(internalMatch);
activationsManager.handleException(internalMatch, e);
} finally {
diff --git
a/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
b/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
index ae622a915f..056e7f567d 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
@@ -42,7 +42,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
for (int i = 0; i < sinks.length; i++) {
TerminalNode rtn = ( TerminalNode ) sinks[i];
RuleAgendaItem agendaItem = getRuleAgendaItem( reteEvaluator,
activationsManager, rtn, true );
- LeftTuple leftTuple = rtn.createLeftTuple(factHandle, true );
+ RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple)
rtn.createLeftTuple(factHandle, true );
leftTuple.setPropagationContext( propagationContext );
if ( rtn.getRule().getAutoFocus() &&
!agendaItem.getAgendaGroup().isActive() ) {
@@ -71,7 +71,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
leftTuple.reAdd();
if ( context.getModificationMask().intersects(
rtn.getLeftInferredMask() ) ) {
leftTuple.setPropagationContext( context );
- PhreakRuleTerminalNode.doLeftTupleUpdate( rtn, executor,
activationsManager, leftTuple );
+ PhreakRuleTerminalNode.doLeftTupleUpdate( rtn, executor,
activationsManager, (RuleTerminalNodeLeftTuple) leftTuple );
if (leftTuple instanceof InternalMatch) {
((InternalMatch) leftTuple).setActive(true);
}
@@ -80,7 +80,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
if ( context.getModificationMask().intersects(
rtn.getLeftInferredMask() ) ) {
leftTuple = rtn.createLeftTuple( factHandle, true );
leftTuple.setPropagationContext( context );
- PhreakRuleTerminalNode.doLeftTupleInsert( rtn, executor,
activationsManager, agendaItem, leftTuple );
+ PhreakRuleTerminalNode.doLeftTupleInsert( rtn, executor,
activationsManager, agendaItem, (RuleTerminalNodeLeftTuple) leftTuple );
}
}
}
@@ -91,7 +91,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
ActivationsManager activationsManager =
reteEvaluator.getActivationsManager();
leftTuple.setPropagationContext( context );
TerminalNode rtn = (TerminalNode) leftTuple.getTupleSink();
- PhreakRuleTerminalNode.doLeftDelete( activationsManager,
getRuleAgendaItem( reteEvaluator, activationsManager, rtn, false
).getRuleExecutor(), leftTuple );
+ PhreakRuleTerminalNode.doLeftDelete( activationsManager,
getRuleAgendaItem( reteEvaluator, activationsManager, rtn, false
).getRuleExecutor(), (RuleTerminalNodeLeftTuple) leftTuple );
}
public static RuleAgendaItem getRuleAgendaItem(ReteEvaluator
reteEvaluator, ActivationsManager activationsManager, TerminalNode rtn, boolean
linkPmem ) {
diff --git
a/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
b/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
index b2760f0f53..efc271ad68 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
@@ -79,7 +79,7 @@ public class ModifyPreviousTuples {
ActivationsManager activationsManager =
reteEvaluator.getActivationsManager();
TerminalNode rtn = (TerminalNode) leftTuple.getTupleSink();
PathMemory pathMemory = reteEvaluator.getNodeMemory( rtn );
- PhreakRuleTerminalNode.doLeftDelete(activationsManager,
pathMemory.getRuleAgendaItem().getRuleExecutor(), leftTuple);
+ PhreakRuleTerminalNode.doLeftDelete(activationsManager,
pathMemory.getRuleAgendaItem().getRuleExecutor(), (RuleTerminalNodeLeftTuple)
leftTuple);
}
}
diff --git
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
index f4fbdb09a4..ee22d798a6 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
@@ -142,7 +142,7 @@ public class RuleTerminalNode extends AbstractTerminalNode {
}
}
RuleExecutor ruleExecutor =
((RuleTerminalNodeLeftTuple)leftTuple).getRuleAgendaItem().getRuleExecutor();
-
PhreakRuleTerminalNode.doLeftDelete(ruleExecutor.getPathMemory().getActualActivationsManager(
reteEvaluator ), ruleExecutor, leftTuple);
+
PhreakRuleTerminalNode.doLeftDelete(ruleExecutor.getPathMemory().getActualActivationsManager(
reteEvaluator ), ruleExecutor, (RuleTerminalNodeLeftTuple) leftTuple);
}
}
diff --git
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
index 4626a017d9..222e0a98a7 100644
---
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
+++
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
@@ -62,6 +62,9 @@ public class RuleTerminalNodeLeftTuple extends LeftTuple
implements InternalMatc
private RuleImpl rule;
private Consequence consequence;
+ // left here for debugging purposes: switch
RuleExecutor.DEBUG_DORMANT_TUPLE to true to enable this debugging
+ private boolean dormant;
+
public RuleTerminalNodeLeftTuple() {
// constructor needed for serialisation
}
@@ -218,7 +221,7 @@ public class RuleTerminalNodeLeftTuple extends LeftTuple
implements InternalMatc
}
public void dequeue() {
- ruleAgendaItem.getRuleExecutor().removeLeftTuple(this);
+ ruleAgendaItem.getRuleExecutor().removeActiveTuple(this);
}
public void remove() {
@@ -335,4 +338,18 @@ public class RuleTerminalNodeLeftTuple extends LeftTuple
implements InternalMatc
public int hashCode() {
return Objects.hash(super.hashCode(),
ruleAgendaItem.getRule().getName());
}
+
+ public boolean isFullMatch() {
+ return true;
+ }
+
+ public boolean isDormant() {
+ //throw new IllegalStateException("This method can be called only for
debugging purposes. Uncomment dormant boolean to enable debugging.");
+ return dormant;
+ }
+
+ public void setDormant(boolean dormant) {
+ //throw new IllegalStateException("This method can be called only for
debugging purposes. Uncomment dormant boolean to enable debugging.");
+ this.dormant = dormant;
+ }
}
diff --git a/drools-core/src/main/java/org/drools/core/util/LinkedList.java
b/drools-core/src/main/java/org/drools/core/util/LinkedList.java
index c78fb30ca8..3123640acc 100644
--- a/drools-core/src/main/java/org/drools/core/util/LinkedList.java
+++ b/drools-core/src/main/java/org/drools/core/util/LinkedList.java
@@ -22,6 +22,7 @@ import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.util.Collection;
import java.util.NoSuchElementException;
/**
@@ -471,5 +472,4 @@ public class LinkedList<T extends LinkedListNode<T>>
}
}
}
-
}
diff --git
a/drools-core/src/main/java/org/drools/core/util/index/TupleList.java
b/drools-core/src/main/java/org/drools/core/util/index/TupleList.java
index d31445f4a4..3790379edb 100644
--- a/drools-core/src/main/java/org/drools/core/util/index/TupleList.java
+++ b/drools-core/src/main/java/org/drools/core/util/index/TupleList.java
@@ -16,6 +16,7 @@
package org.drools.core.util.index;
+import java.util.Collection;
import java.io.Serializable;
import org.drools.core.common.InternalFactHandle;
@@ -27,18 +28,19 @@ import org.drools.core.util.FastIterator;
import org.drools.core.util.Iterator;
import org.drools.core.util.LinkedList;
+
public class TupleList<C> implements TupleMemory, Entry<TupleList<C>>,
Serializable {
public static final long serialVersionUID = 510l;
private TupleList<C> next;
- private Tuple first;
- private Tuple last;
+ protected Tuple first;
+ protected Tuple last;
private TupleHashTableIterator iterator;
- private int size;
+ protected int size;
private C context;
@@ -279,4 +281,10 @@ public class TupleList<C> implements TupleMemory,
Entry<TupleList<C>>, Serializa
current.setMemory(other);
}
}
+
+ public <I> void addAllToCollection(Collection<I> c) {
+ for (Tuple item = getFirst(); item != null; item = item.getNext()) {
+ c.add((I) item);
+ }
+ }
}
diff --git
a/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
b/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
index 146d870740..e92968d094 100644
---
a/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
+++
b/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
@@ -282,7 +282,7 @@ public class DefaultAgenda implements InternalAgenda {
// The lazy RuleAgendaItem must be fully evaluated, to see if
there is a rule match
RuleExecutor ruleExecutor = item.getRuleExecutor();
ruleExecutor.evaluateNetwork(this);
- TupleList list = ruleExecutor.getLeftTupleList();
+ TupleList list = ruleExecutor.getActiveMatches();
for (RuleTerminalNodeLeftTuple lt = (RuleTerminalNodeLeftTuple)
list.getFirst(); lt != null; lt = (RuleTerminalNodeLeftTuple) lt.getNext()) {
if ( ruleName.equals( lt.getRule().getName() ) && (
lt.checkProcessInstance( workingMemory, processInstanceId ) )) {
return true;
diff --git
a/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
b/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
index d4ea495dbe..fe77550a88 100644
---
a/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
+++
b/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
@@ -1,76 +1,48 @@
-/*
- * Copyright 2015 Red Hat, Inc. and/or its affiliates.
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * 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.
-*/
-
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, 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.
+ */
package org.drools.serialization.protobuf.iterators;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import org.drools.base.reteoo.NodeTypeEnums;
-import org.drools.core.common.InternalFactHandle;
-import org.drools.core.common.InternalWorkingMemory;
-import org.drools.core.common.Memory;
import org.drools.core.common.ReteEvaluator;
import org.drools.core.impl.InternalRuleBase;
-import org.drools.core.reteoo.AccumulateNode.AccumulateContext;
-import org.drools.core.reteoo.AccumulateNode.AccumulateMemory;
-import org.drools.core.reteoo.BetaMemory;
-import org.drools.core.reteoo.BetaNode;
-import org.drools.core.reteoo.FromNode.FromMemory;
-import org.drools.core.reteoo.LeftInputAdapterNode;
-import org.drools.core.reteoo.LeftTuple;
-import org.drools.core.reteoo.LeftTupleSink;
-import org.drools.core.reteoo.LeftTupleSource;
-import org.drools.core.reteoo.ObjectSource;
-import org.drools.core.reteoo.ObjectTypeNode;
-import org.drools.core.reteoo.RightTuple;
-import org.drools.core.reteoo.RuleTerminalNode;
+import org.drools.core.phreak.RuleExecutor;
+import org.drools.core.reteoo.PathMemory;
import org.drools.core.reteoo.TerminalNode;
-import org.drools.core.reteoo.Tuple;
-import org.drools.core.reteoo.TupleMemory;
import org.drools.core.rule.consequence.InternalMatch;
-import org.drools.core.util.FastIterator;
import org.drools.core.util.Iterator;
-public class PhreakActivationIterator
- implements
- Iterator {
-
- private java.util.Iterator<InternalMatch> agendaItemIter;
-
- List<InternalMatch> internalMatches;
+public class PhreakActivationIterator implements Iterator<InternalMatch> {
- PhreakActivationIterator() {
+ private final java.util.Iterator<InternalMatch> agendaItemIter;
- }
-
- private PhreakActivationIterator(ReteEvaluator reteEvaluator,
- InternalRuleBase kbase) {
- internalMatches = collectAgendaItems(kbase, reteEvaluator);
- agendaItemIter = internalMatches.iterator();
+ private PhreakActivationIterator(ReteEvaluator reteEvaluator,
InternalRuleBase kbase) {
+ agendaItemIter = collectAgendaItems(kbase, reteEvaluator).iterator();
}
public static PhreakActivationIterator iterator(ReteEvaluator
reteEvaluator) {
return new PhreakActivationIterator( reteEvaluator,
reteEvaluator.getKnowledgeBase() );
}
- public Object next() {
+ public InternalMatch next() {
if ( agendaItemIter.hasNext() ) {
return agendaItemIter.next();
} else {
@@ -78,158 +50,22 @@ public class PhreakActivationIterator
}
}
- public static List<RuleTerminalNode>
populateRuleTerminalNodes(InternalRuleBase kbase, Set<RuleTerminalNode>
nodeSet) {
- Collection<TerminalNode[]> nodesWithArray =
kbase.getReteooBuilder().getTerminalNodes().values();
+ private static List<InternalMatch> collectAgendaItems(InternalRuleBase
kbase, ReteEvaluator reteEvaluator) {
+ List<InternalMatch> internalMatches = new ArrayList<>();
- for (TerminalNode[] nodeArray : nodesWithArray) {
+ for (TerminalNode[] nodeArray :
kbase.getReteooBuilder().getTerminalNodes().values()) {
for (TerminalNode node : nodeArray) {
if (node.getType() == NodeTypeEnums.RuleTerminalNode) {
- nodeSet.add((RuleTerminalNode) node);
- }
- }
- }
-
- return Arrays.asList(nodeSet.toArray(new
RuleTerminalNode[nodeSet.size()]));
- }
-
- public static List<InternalMatch> collectAgendaItems(InternalRuleBase
kbase, ReteEvaluator reteEvaluator) {
- Set<RuleTerminalNode> nodeSet = new HashSet<>();
- List<RuleTerminalNode> nodeList = populateRuleTerminalNodes(kbase,
nodeSet);
-
- List<InternalMatch> internalMatches = new ArrayList<>();
- for ( RuleTerminalNode rtn : nodeList ) {
- if ( !nodeSet.contains(rtn) ) {
- // this node has already been processed
- continue;
- }
- processLeftTuples(rtn.getLeftTupleSource(), internalMatches,
nodeSet, reteEvaluator);
- }
- return internalMatches;
- }
-
- public static void processLeftTuples(LeftTupleSource node,
List<InternalMatch> internalMatches, Set<RuleTerminalNode> nodeSet,
ReteEvaluator reteEvaluator) {
- LeftTupleSource node1 = node;
- while (NodeTypeEnums.LeftInputAdapterNode != node1.getType()) {
- node1 = node1.getLeftTupleSource();
- }
- int maxShareCount = node1.getAssociationsSize();
-
- while (NodeTypeEnums.LeftInputAdapterNode != node.getType()) {
- Memory memory =
reteEvaluator.getNodeMemories().peekNodeMemory(node);
- if (memory == null || memory.getSegmentMemory() == null) {
- // segment has never been initialized, which means the rule
has never been linked.
- return;
- }
- if ( node.getAssociationsSize() == maxShareCount ) {
- // the recurse must start from the first split node, otherwise
we get partial overlaps in propagations
- if (NodeTypeEnums.isBetaNode(node)) {
- BetaMemory bm;
- if (NodeTypeEnums.AccumulateNode == node.getType()) {
- AccumulateMemory am = (AccumulateMemory) memory;
- bm = am.getBetaMemory();
- FastIterator it =
bm.getLeftTupleMemory().fullFastIterator();
- Tuple lt = BetaNode.getFirstTuple(
bm.getLeftTupleMemory(), it );
- for (; lt != null; lt = (LeftTuple) it.next(lt)) {
- AccumulateContext accctx = (AccumulateContext)
lt.getContextObject();
- collectFromPeers((LeftTuple)
accctx.getResultLeftTuple(), internalMatches, nodeSet, reteEvaluator);
- }
- } else if ( NodeTypeEnums.ExistsNode == node.getType() ) {
- bm = (BetaMemory)
reteEvaluator.getNodeMemories().peekNodeMemory(node);
- if (bm != null) {
- bm = (BetaMemory)
reteEvaluator.getNodeMemories().peekNodeMemory(node);
- FastIterator it =
bm.getRightTupleMemory().fullFastIterator(); // done off the RightTupleMemory,
as exists only have unblocked tuples on the left side
- RightTuple rt = (RightTuple)
BetaNode.getFirstTuple(bm.getRightTupleMemory(), it);
- for (; rt != null; rt = (RightTuple) it.next(rt)) {
- for (LeftTuple lt = rt.getBlocked(); lt !=
null; lt = lt.getBlockedNext()) {
- if (lt.getFirstChild() != null) {
- collectFromPeers(lt.getFirstChild(),
internalMatches, nodeSet, reteEvaluator);
- }
- }
- }
- }
- } else {
- bm = (BetaMemory)
reteEvaluator.getNodeMemories().peekNodeMemory(node);
- if (bm != null) {
- FastIterator it =
bm.getLeftTupleMemory().fullFastIterator();
- Tuple lt =
BetaNode.getFirstTuple(bm.getLeftTupleMemory(), it);
- for (; lt != null; lt = (LeftTuple) it.next(lt)) {
- if (lt.getFirstChild() != null) {
- collectFromLeftInput(lt.getFirstChild(),
internalMatches, nodeSet, reteEvaluator);
- }
- }
- }
- }
- return;
- } else if (NodeTypeEnums.FromNode == node.getType()) {
- FromMemory fm = (FromMemory)
reteEvaluator.getNodeMemories().peekNodeMemory(node);
- if (fm != null) {
- TupleMemory ltm =
fm.getBetaMemory().getLeftTupleMemory();
- FastIterator it = ltm.fullFastIterator();
- for (LeftTuple lt = (LeftTuple) ltm.getFirst(null); lt
!= null; lt = (LeftTuple) it.next(lt)) {
- if (lt.getFirstChild() != null) {
- collectFromLeftInput(lt.getFirstChild(),
internalMatches, nodeSet, reteEvaluator);
- }
- }
+ PathMemory pathMemory = (PathMemory)
reteEvaluator.getNodeMemories().peekNodeMemory(node);
+ if (pathMemory != null && pathMemory.getRuleAgendaItem()
!= null) {
+ RuleExecutor ruleExecutor =
pathMemory.getRuleAgendaItem().getRuleExecutor();
+
ruleExecutor.getDormantMatches().addAllToCollection(internalMatches);
+
ruleExecutor.getActiveMatches().addAllToCollection(internalMatches);
}
- return;
}
}
- node = node.getLeftTupleSource();
- }
-
- // No beta or from nodes, so must retrieve LeftTuples from the LiaNode.
- // This is done by scanning all the LeftTuples referenced from the
FactHandles in the ObjectTypeNode
- LeftInputAdapterNode lian = (LeftInputAdapterNode) node;
- if ( !lian.isTerminal() ) {
- Memory memory =
reteEvaluator.getNodeMemories().peekNodeMemory(node);
- if (memory == null || memory.getSegmentMemory() == null) {
- // segment has never been initialized, which means the rule
has never been linked.
- return;
- }
- }
-
- ObjectSource os = lian.getObjectSource();
- while (os.getType() != NodeTypeEnums.ObjectTypeNode) {
- os = os.getParentObjectSource();
- }
- ObjectTypeNode otn = (ObjectTypeNode) os;
- LeftTupleSink firstLiaSink =
lian.getSinkPropagator().getFirstLeftTupleSink();
-
- java.util.Iterator<InternalFactHandle> it =
otn.getFactHandlesIterator((InternalWorkingMemory) reteEvaluator);
- while (it.hasNext()) {
- InternalFactHandle fh = it.next();
- fh.forEachLeftTuple( lt -> {
- if ( lt.getTupleSink() == firstLiaSink ) {
- collectFromLeftInput(lt, internalMatches, nodeSet,
reteEvaluator);
- }
- });
}
- }
- private static void collectFromLeftInput(LeftTuple lt, List<InternalMatch>
internalMatches, Set<RuleTerminalNode> nodeSet, ReteEvaluator reteEvaluator) {
- for (; lt != null; lt = lt.getHandleNext()) {
- collectFromPeers(lt, internalMatches, nodeSet, reteEvaluator);
- }
- }
-
- private static void collectFromPeers(LeftTuple peer, List<InternalMatch>
internalMatches, Set<RuleTerminalNode> nodeSet, ReteEvaluator reteEvaluator) {
- while (peer != null) {
- if ( peer.getTupleSink().getType() == NodeTypeEnums.AccumulateNode
) {
- Object accctx = peer.getContextObject();
- if (accctx instanceof AccumulateContext) {
- // lefttuple representing an accumulated value now have
that value as context object (it was null before) and must be skipped here
- collectFromLeftInput((LeftTuple) ((AccumulateContext)
accctx).getResultLeftTuple(), internalMatches, nodeSet, reteEvaluator);
- }
- } else if ( peer.getFirstChild() != null ) {
- for (LeftTuple childLt = peer.getFirstChild(); childLt !=
null; childLt = childLt.getHandleNext()) {
- collectFromPeers(childLt, internalMatches, nodeSet,
reteEvaluator);
- }
- } else if ( peer.getTupleSink().getType() ==
NodeTypeEnums.RuleTerminalNode ) {
- internalMatches.add((InternalMatch) peer);
- nodeSet.remove(peer.getTupleSink()); // remove this
RuleTerminalNode, as we know we've visited it already
- }
- peer = peer.getPeer();
- }
+ return internalMatches;
}
-
-}
+}
\ No newline at end of file
diff --git
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
index 2422c93680..81351d090a 100644
---
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
+++
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
@@ -472,31 +472,31 @@ public class ExecutionFlowControlTest {
assertThat(group1.size()).isEqualTo(1);
RuleAgendaItem ruleItem1 = group1.getActivations().iterator().next();
ruleItem1.getRuleExecutor().evaluateNetwork(wm.getAgenda());
-
assertThat(ruleItem1.getRuleExecutor().getLeftTupleList().size()).isEqualTo(3);
+
assertThat(ruleItem1.getRuleExecutor().getActiveMatches().size()).isEqualTo(3);
ruleItem1.getRuleExecutor().fire(agenda);
assertThat(group1.size()).isEqualTo(1);
-
assertThat(ruleItem1.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+
assertThat(ruleItem1.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
ksession.update( brieHandle, brie );
assertThat(group1.size()).isEqualTo(1);
ruleItem1.getRuleExecutor().evaluateNetwork(wm.getAgenda());
-
assertThat(ruleItem1.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+
assertThat(ruleItem1.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
InternalAgendaGroup group2 =
agenda.getAgendaGroupsManager().getAgendaGroup( "group2" );
agenda.getAgendaGroupsManager().setFocus( group2);
assertThat(group2.size()).isEqualTo(1);
RuleAgendaItem ruleItem2 = group2.getActivations().iterator().next();
ruleItem2.getRuleExecutor().evaluateNetwork(wm.getAgenda());
-
assertThat(ruleItem2.getRuleExecutor().getLeftTupleList().size()).isEqualTo(3);
+
assertThat(ruleItem2.getRuleExecutor().getActiveMatches().size()).isEqualTo(3);
ruleItem2.getRuleExecutor().fire(agenda);
assertThat(group2.size()).isEqualTo(1);
-
assertThat(ruleItem2.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+
assertThat(ruleItem2.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
ksession.update( brieHandle, brie );
assertThat(group2.size()).isEqualTo(1);
-
assertThat(ruleItem2.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+
assertThat(ruleItem2.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
}
@Test
diff --git
a/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
b/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
index 7dda3486c2..48ef10ed39 100644
---
a/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
+++
b/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
@@ -105,7 +105,7 @@ public class
TruthMaintenanceSystemRuleTerminalNodeLeftTuple<T extends ModedAsse
removeBlocked(dep);
TruthMaintenanceSystemRuleTerminalNodeLeftTuple justified =
(TruthMaintenanceSystemRuleTerminalNodeLeftTuple) dep.getJustified();
if (justified.getBlockers().isEmpty() && justified.isActive())
{
- activationsManager.stageLeftTuple(ruleAgendaItem,
justified);
+
activationsManager.stageLeftTuple(justified.getRuleAgendaItem(), justified);
}
dep = tmp;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]