This is an automated email from the ASF dual-hosted git repository.

mariofusco pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new 575c4c93b3 [incubator-kie-issues #203] Cleanup Phreak code - Extract 
SegmentCursor (#6510)
575c4c93b3 is described below

commit 575c4c93b3b14f41be26dbb2a6cf1f66bef40728
Author: Paolo Bizzarri <[email protected]>
AuthorDate: Sat Nov 8 16:40:53 2025 +0100

    [incubator-kie-issues #203] Cleanup Phreak code - Extract SegmentCursor 
(#6510)
    
    * Slowly moving code away
    
    * Encapsulated SegmentCursor so far
    
    * Encapsulating more of the SegmentCursor logic
    
    * Now SegmentCursor correctly contains also the tuples
    
    * StagedLeftTuples are now inside the core
    
    * Encapsulated also the staged tuples
    
    * Fix for incorrect refactoring
    
    * Added tracing methods
    
    * Completing the work for SegmentCursor - starting encapsulation of fields
    
    * Spreading usage of SegmentCursor
    
    * More cleaning up and proper separation of the code
    
    * StackEntry are now properly separated
    
    * Separated SegmentCursor to its own file
    
    * Fixed header file
    
    * Some minor fixes
---
 .../drools/core/phreak/PhreakAccumulateNode.java   |   4 +-
 .../org/drools/core/phreak/PhreakBranchNode.java   |   4 +-
 .../org/drools/core/phreak/PhreakEvalNode.java     |   4 +-
 .../org/drools/core/phreak/PhreakExistsNode.java   |   4 +-
 .../org/drools/core/phreak/PhreakFromNode.java     |   4 +-
 .../org/drools/core/phreak/PhreakJoinNode.java     |   4 +-
 .../java/org/drools/core/phreak/PhreakNotNode.java |   4 +-
 .../org/drools/core/phreak/PhreakQueryNode.java    |   8 +-
 .../drools/core/phreak/PhreakReactiveFromNode.java |   6 +-
 .../core/phreak/PhreakSubnetworkNotExistsNode.java |   3 +-
 .../org/drools/core/phreak/PhreakTimerNode.java    |  17 +-
 .../core/phreak/RuleNetworkEvaluatorImpl.java      | 683 +++++++--------------
 .../java/org/drools/core/phreak/SegmentCursor.java | 475 ++++++++++++++
 .../metric/phreak/PhreakAccumulateNodeMetric.java  |   6 +-
 .../metric/phreak/PhreakBranchNodeMetric.java      |   6 +-
 .../drools/metric/phreak/PhreakEvalNodeMetric.java |   6 +-
 .../metric/phreak/PhreakExistsNodeMetric.java      |   6 +-
 .../drools/metric/phreak/PhreakFromNodeMetric.java |   6 +-
 .../metric/phreak/PhreakGroupByNodeMetric.java     |   6 +-
 .../drools/metric/phreak/PhreakJoinNodeMetric.java |   6 +-
 .../drools/metric/phreak/PhreakNotNodeMetric.java  |   6 +-
 .../metric/phreak/PhreakQueryNodeMetric.java       |  10 +-
 .../phreak/PhreakReactiveFromNodeMetric.java       |   6 +-
 .../metric/phreak/PhreakTimerNodeMetric.java       |  16 +-
 .../mvel/integrationtests/phreak/Scenario.java     |   6 +-
 25 files changed, 767 insertions(+), 539 deletions(-)

diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java
index 0defc2d5e1..ffb4abf744 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java
@@ -61,8 +61,8 @@ public class PhreakAccumulateNode {
                        LeftTupleSink sink,
                        AccumulateMemory am,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         BetaMemory bm             = am.getBetaMemory();
         TupleSets srcRightTuples = bm.getStagedRightTuples().takeAll();
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 1d75fa1cdc..20fb11a1a4 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
@@ -47,13 +47,13 @@ public class PhreakBranchNode {
     }
 
     public void doNode(ActivationsManager activationsManager,
+                       RuleExecutor executor,
                        ConditionalBranchNode branchNode,
                        ConditionalBranchMemory cbm,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
                        TupleSets stagedLeftTuples,
-                       RuleExecutor executor) {
+                       TupleSets trgLeftTuples) {
 
         if (srcLeftTuples.getDeleteFirst() != null) {
             doLeftDeletes(sink, activationsManager, srcLeftTuples, 
trgLeftTuples, stagedLeftTuples, executor);
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java
index edc3e4b5e2..d8b540c8c2 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakEvalNode.java
@@ -54,8 +54,8 @@ public class PhreakEvalNode {
                        EvalMemory em,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         if (srcLeftTuples.getDeleteFirst() != null) {
             doLeftDeletes(srcLeftTuples, trgLeftTuples, stagedLeftTuples);
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakExistsNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakExistsNode.java
index 9a04d17567..4057e27366 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakExistsNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakExistsNode.java
@@ -51,8 +51,8 @@ public class PhreakExistsNode {
                        LeftTupleSink sink,
                        BetaMemory bm,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
         if (!existsNode.getRightInput().inputIsTupleToObjectNode()) {
             doNormalNode(existsNode, sink, bm, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
         } else {
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java
index a1df534ad8..ead533567d 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakFromNode.java
@@ -57,8 +57,8 @@ public class PhreakFromNode {
                        FromMemory fm,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         if (srcLeftTuples.getDeleteFirst() != null) {
             doLeftDeletes(fm, srcLeftTuples, trgLeftTuples, stagedLeftTuples);
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakJoinNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakJoinNode.java
index 47e8d94086..de4b6f06d5 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakJoinNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakJoinNode.java
@@ -48,8 +48,8 @@ public class PhreakJoinNode {
                        LeftTupleSink sink,
                        BetaMemory bm,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         TupleSets srcRightTuples = bm.getStagedRightTuples().takeAll();
 
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakNotNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakNotNode.java
index ae3da6f756..730de5a669 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakNotNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakNotNode.java
@@ -52,8 +52,8 @@ public class PhreakNotNode {
                        LeftTupleSink sink,
                        BetaMemory bm,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         if (!notNode.getRightInput().inputIsTupleToObjectNode()) {
             doNormalNode(notNode, sink, bm, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java
index b56b4af96f..8e5ec1649d 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakQueryNode.java
@@ -41,12 +41,12 @@ public class PhreakQueryNode {
         this.reteEvaluator = reteEvaluator;
     }
 
-    public void doNode(QueryElementNode queryNode,
+    public void doNode(StackEntry stackEntry,
+                       QueryElementNode queryNode,
                        QueryElementNodeMemory qmem,
-                       StackEntry stackEntry,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         if (srcLeftTuples.getDeleteFirst() != null) {
             doLeftDeletes(qmem, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakReactiveFromNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakReactiveFromNode.java
index b76fe05a2b..a431442e99 100644
--- 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakReactiveFromNode.java
+++ 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakReactiveFromNode.java
@@ -36,10 +36,10 @@ public class PhreakReactiveFromNode extends PhreakFromNode {
                        ReactiveFromMemory fm,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
-        super.doNode(fromNode, fm, sink, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+        super.doNode(fromNode, fm, sink, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
         trgLeftTuples.addAll(fm.getStagedLeftTuples().takeAll());
     }
 }
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakSubnetworkNotExistsNode.java
 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakSubnetworkNotExistsNode.java
index f96fce139a..2bfebc03ac 100644
--- 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakSubnetworkNotExistsNode.java
+++ 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakSubnetworkNotExistsNode.java
@@ -23,7 +23,6 @@ import org.drools.core.common.TupleSets;
 import org.drools.core.reteoo.BetaMemory;
 import org.drools.core.reteoo.BetaNode;
 import org.drools.core.reteoo.LeftTupleSink;
-import org.drools.core.reteoo.SubnetworkTuple;
 import org.drools.core.reteoo.Tuple;
 import org.drools.core.reteoo.TupleImpl;
 import org.drools.core.reteoo.TupleMemory;
@@ -88,7 +87,7 @@ public class PhreakSubnetworkNotExistsNode {
             for (TupleImpl rightTuple = srcRightTuples.getDeleteFirst(); 
rightTuple != null; ) {
                 TupleImpl next = rightTuple.getStagedNext();
 
-                TupleImpl leftTuple = 
node.getStartTuple((SubnetworkTuple)rightTuple);
+                TupleImpl leftTuple = node.getStartTuple(rightTuple);
                 // don't use matches here, as it may be null, if the LT was 
also being removed.
                 rightTuple.getMemory().remove(rightTuple);
 
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakTimerNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakTimerNode.java
index 0c46f07294..3e0951a8b2 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakTimerNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakTimerNode.java
@@ -62,26 +62,25 @@ public class PhreakTimerNode {
         this.reteEvaluator = reteEvaluator;
     }
 
-    public void doNode(TimerNode timerNode,
+    public void doNode(ActivationsManager activationsManager,
+                       SegmentCursor sc, 
+                       TimerNode timerNode,
                        TimerNodeMemory tm,
-                       PathMemory pmem,
-                       SegmentMemory smem,
                        LeftTupleSink sink,
-                       ActivationsManager activationsManager,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         if ( srcLeftTuples.getDeleteFirst() != null ) {
-            doLeftDeletes( timerNode, tm, pmem, sink, srcLeftTuples, 
trgLeftTuples, stagedLeftTuples );
+            doLeftDeletes( timerNode, tm, sc.getPathMemory(), sink, 
srcLeftTuples, trgLeftTuples, stagedLeftTuples );
         }
 
         if ( srcLeftTuples.getUpdateFirst() != null ) {
-            doLeftUpdates( timerNode, tm, pmem, smem, sink, 
activationsManager, srcLeftTuples, trgLeftTuples, stagedLeftTuples );
+            doLeftUpdates( timerNode, tm, sc.getPathMemory(), 
sc.getCurrentSegment(), sink, activationsManager, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples );
         }
 
         if ( srcLeftTuples.getInsertFirst() != null ) {
-            doLeftInserts( timerNode, tm, pmem, smem, sink, 
activationsManager, srcLeftTuples, trgLeftTuples );
+            doLeftInserts( timerNode, tm, sc.getPathMemory(), 
sc.getCurrentSegment(), sink, activationsManager, srcLeftTuples, trgLeftTuples 
);
         }
 
         doPropagateChildLeftTuples( tm, sink, trgLeftTuples, stagedLeftTuples 
);
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluatorImpl.java
 
b/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluatorImpl.java
index 8766deb094..3d97f30642 100644
--- 
a/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluatorImpl.java
+++ 
b/drools-core/src/main/java/org/drools/core/phreak/RuleNetworkEvaluatorImpl.java
@@ -51,7 +51,6 @@ import org.drools.core.reteoo.FromNode;
 import org.drools.core.reteoo.FromNode.FromMemory;
 import org.drools.core.reteoo.JoinNode;
 import org.drools.core.reteoo.LeftTuple;
-import org.drools.core.reteoo.LeftTupleNode;
 import org.drools.core.reteoo.LeftTupleSink;
 import org.drools.core.reteoo.LeftTupleSinkNode;
 import org.drools.core.reteoo.NotNode;
@@ -65,7 +64,6 @@ import org.drools.core.reteoo.ReactiveFromNode;
 import org.drools.core.reteoo.RightInputAdapterNode;
 import org.drools.core.reteoo.SegmentMemory;
 import org.drools.core.reteoo.SubnetworkTuple;
-import org.drools.core.reteoo.TerminalNode;
 import org.drools.core.reteoo.TimerNode;
 import org.drools.core.reteoo.TimerNode.TimerNodeMemory;
 import org.drools.core.reteoo.Tuple;
@@ -73,17 +71,12 @@ import org.drools.core.reteoo.TupleFactory;
 import org.drools.core.reteoo.TupleImpl;
 import org.drools.core.reteoo.TupleToObjectNode;
 import org.drools.core.util.LinkedList;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import static org.drools.base.reteoo.NodeTypeEnums.AccumulateNode;
 import static org.drools.core.common.TupleSetsImpl.createLeftTupleTupleSets;
-import static org.drools.core.phreak.BuildtimeSegmentUtilities.nextNodePosMask;
 
 public class RuleNetworkEvaluatorImpl implements RuleNetworkEvaluator {
 
-    private static final Logger log = 
LoggerFactory.getLogger(RuleNetworkEvaluatorImpl.class);
-
+    
     private final PhreakJoinNode         pJoinNode;
     private final PhreakEvalNode         pEvalNode;
     private final PhreakFromNode         pFromNode;
@@ -136,65 +129,30 @@ public class RuleNetworkEvaluatorImpl implements 
RuleNetworkEvaluator {
     public void evaluateNetwork(ActivationsManager activationsManager,
                                 RuleExecutor executor,
                                 PathMemory pmem) {
-        SegmentMemory[] smems = pmem.getSegmentMemories();
-
 
-        SegmentMemory smem = smems[0];
-        if (smem == null) {
-            // if there's no first smem it's a pure alpha firing and then 
doesn't require any furthe evaluation
+        if (pmem.getSegmentMemories()[0] == null) {
+            // if there's no first smem it's a pure alpha firing and then 
doesn't require any further evaluation
             return;
         }
+        
+        SegmentCursor sc = SegmentCursor.createSegmentCursor(pmem);
 
-        LeftTupleNode liaNode = smem.getRootNode();
-
-        NetworkNode node;
-        Memory nodeMem;
-        boolean firstSegmentIsOnlyLia = liaNode == smem.getTipNode();
-        if (firstSegmentIsOnlyLia) {
-            // segment only has liaNode in it
-            // nothing is staged in the liaNode, so skip to next segment
-            smem = smems[1];
-            node = smem.getRootNode();
-            nodeMem = smem.getNodeMemories()[0];
-        } else {
-            // lia is in shared segment, so point to next node
-            node = liaNode.getSinkPropagator().getFirstLeftTupleSink();
-            nodeMem = smem.getNodeMemories()[1]; // skip the liaNode memory
-        }
-
-        TupleSets srcTuples = smem.getStagedLeftTuples();
-        if (log.isTraceEnabled()) {
-            log.trace("Rule[name={}] segments={} {}", 
((TerminalNode)pmem.getPathEndNode()).getRule().getName(), smems.length, 
srcTuples.toStringSizes());
-        }
-        outerEval(activationsManager, executor, pmem, smems, 
firstSegmentIsOnlyLia ? 1 : 0, firstSegmentIsOnlyLia ? 1L : 2L, nodeMem, node, 
srcTuples, true);
+        
+        sc.traceNetworkEvaluation();
+        outerEval(activationsManager, executor, sc);
     }
-    
+
     @Override
     public void evaluate(PathMemory pmem,
                           ActivationsManager activationsManager,
                           NetworkNode sink,
                           Memory tm,
                           TupleSets trgLeftTuples) {
-        SegmentMemory[] smems = pmem.getSegmentMemories();
-        SegmentMemory sm = tm.getSegmentMemory();
-        int smemIndex = 0;
-        for (SegmentMemory smem : smems) {
-            if (smem == sm) {
-                break;
-            }
-            smemIndex++;
-        }
-
-        long bit = 1;
-        for (NetworkNode node = sm.getRootNode(); node != sink; node = 
((LeftTupleNode) node).getSinkPropagator()
-                .getFirstLeftTupleSink()) {
-            //update the bit to the correct node position.
-            bit = nextNodePosMask(bit);
-        }
-
-        outerEval(activationsManager, 
pmem.getRuleAgendaItem().getRuleExecutor(), pmem, smems,
-                smemIndex, bit, tm, sink, trgLeftTuples, true);
+        SegmentCursor segmentCursor = SegmentCursor.createSegmentCursor(pmem, 
sink, tm, trgLeftTuples);
+        
+        outerEval(activationsManager, 
pmem.getRuleAgendaItem().getRuleExecutor(), segmentCursor);
     }
+
     
     
     @Override
@@ -243,31 +201,19 @@ public class RuleNetworkEvaluatorImpl implements 
RuleNetworkEvaluator {
     public void forceFlushLeftTuple(PathMemory pmem,
                                     SegmentMemory sm, 
                                     TupleSets leftTupleSets) {
-        SegmentMemory[] smems = pmem.getSegmentMemories();
-
-        LeftTupleNode node;
-        Memory mem;
-        long bit = 1;
-        if (NodeTypeEnums.isLeftInputAdapterNode(sm.getRootNode()) && 
!NodeTypeEnums.isLeftInputAdapterNode(sm
-                .getTipNode())) {
-            // The segment is the first and it has the lian shared with other 
nodes, the lian must be skipped, so adjust the bit and sink
-            node = 
sm.getRootNode().getSinkPropagator().getFirstLeftTupleSink();
-            mem = sm.getNodeMemories()[1];
-            bit = 2; // adjust bit to point to next node
-        } else {
-            node = sm.getRootNode();
-            mem = sm.getNodeMemories()[0];
-        }
+
+        SegmentCursor segmentCursor = SegmentCursor.createSegmentCursor(pmem, 
sm, leftTupleSets);
 
         PathMemory rtnPmem = 
NodeTypeEnums.isTerminalNode(pmem.getPathEndNode()) ? pmem : 
nodeMemories.getNodeMemory(
                 (AbstractTerminalNode) 
pmem.getPathEndNode().getPathEndNodes()[0]);
 
         ActivationsManager activationsManager = 
pmem.getActualActivationsManager();
-        outerEval(activationsManager, 
rtnPmem.getOrCreateRuleAgendaItem().getRuleExecutor(), pmem, smems, 
sm.getPos(), bit, mem, node,
-                leftTupleSets,
-                true);
+
+        
+        outerEval(activationsManager, 
rtnPmem.getOrCreateRuleAgendaItem().getRuleExecutor(), segmentCursor);
     }
-    
+
+
     
     @Override
     public boolean flushLeftTupleIfNecessary(SegmentMemory sm, boolean 
streamMode) {
@@ -295,26 +241,19 @@ public class RuleNetworkEvaluatorImpl implements 
RuleNetworkEvaluator {
                 .getFactHandle().isEvent());
         return forceFlush ? sm.getPathMemories().get(0) : 
sm.getFirstDataDrivenPathMemory();
     }
-
+    
     private void outerEval(ActivationsManager activationsManager,
-                          RuleExecutor executor,
-                          PathMemory pmem,
-                          SegmentMemory[] smems,
-                          int smemIndex,
-                          long bit,
-                          Memory nodeMem,
-                          NetworkNode node,
-                          TupleSets trgTuples,
-                          boolean processSubnetwork) {
-
-        LinkedList<StackEntry> stack = new LinkedList<>();
-        innerEval(activationsManager, executor, stack, pmem, smems, smemIndex, 
bit, nodeMem, node, trgTuples, processSubnetwork);
-        while (!stack.isEmpty()) {
-            // eval
-            StackEntry entry = stack.removeLast();
-            evalStackEntry(activationsManager, executor, stack, entry);
-        }
-    }
+                           RuleExecutor executor,
+                           SegmentCursor sc) {
+
+         LinkedList<StackEntry> stack = new LinkedList<>();
+         innerEval(activationsManager, executor, stack, sc, true);
+         while (!stack.isEmpty()) {
+             // eval
+             StackEntry entry = stack.removeLast();
+             evalStackEntry(activationsManager, executor, stack, entry);
+         }
+     }
 
     private void evalStackEntry(ActivationsManager activationsManager,
                                RuleExecutor executor,
@@ -322,462 +261,311 @@ public class RuleNetworkEvaluatorImpl implements 
RuleNetworkEvaluator {
                                StackEntry entry) {
         NetworkNode node = entry.getNode();
         Memory nodeMem = entry.getNodeMem();
-        TupleSets trgTuples = entry.getTrgTuples();
         if (node.getType() == NodeTypeEnums.QueryElementNode) {
             // copy across the results, if any from the query node memory
             QueryElementNodeMemory qmem = (QueryElementNodeMemory) nodeMem;
             qmem.setNodeCleanWithoutNotify();
-            qmem.getResultLeftTuples().addTo(trgTuples);
+            qmem.getResultLeftTuples().addTo(entry.getTrgTuples());
         }
 
-        LeftTupleSinkNode sink = entry.getSink();
-        PathMemory pmem = entry.getRmem();
-
-        SegmentMemory[] smems = entry.getSmems();
-        int smemIndex = entry.getSmemIndex();
-        boolean processSubnetwork = entry.isProcessSubnetwork();
-
-        long bit = entry.getBit();
+        SegmentCursor sc;
         if (entry.isResumeFromNextNode()) {
-            SegmentMemory smem = smems[smemIndex];
-            if (node != smem.getTipNode()) {
-                // get next node and node memory in the segment
-                LeftTupleSink nextSink = sink.getNextLeftTupleSinkNode();
-                if (nextSink == null) {
-                    node = sink;
-                } else {
-                    // there is a nested subnetwork, take out path
-                    node = nextSink;
-                }
-
-                nodeMem = nodeMem.getNext();
-                bit = nextNodePosMask(bit); // update bit to new node
-            } else {
-                // Reached end of segment, start on new segment.
-                propagate(smem, trgTuples);
-                smem = smems[++smemIndex];
-                trgTuples = smem.getStagedLeftTuples().takeAll();
-                node = smem.getRootNode();
-                nodeMem = smem.getNodeMemories()[0];
-                bit = 1; // update bit to start of new segment
+            
+            if (node == entry.getSmems()[entry.getSmemIndex()].getTipNode()) {
+                propagate(entry.getSmems()[entry.getSmemIndex()], 
entry.getTrgTuples());
             }
-        }
 
-        if (log.isTraceEnabled()) {
-            int offset = getOffset(node);
-            log.trace("{} Resume {} {}", indent(offset), node.toString(), 
trgTuples.toStringSizes());
+            sc = SegmentCursor.createForResume(entry);
+        } else {
+            sc = SegmentCursor.createForNonResume(entry);
         }
-        innerEval(activationsManager, executor, stack, pmem, smems, smemIndex, 
bit, nodeMem, node, trgTuples, processSubnetwork);
+        sc.traceResumeFromStack();
+        innerEval(activationsManager, executor, stack, sc, 
entry.isProcessSubnetwork());
     }
 
     private void innerEval(ActivationsManager activationsManager,
-                          RuleExecutor executor,
-                          LinkedList<StackEntry> stack,
-                          PathMemory pmem,
-                          final SegmentMemory[] smems,
-                          int smemIndex,
-                          long bit,
-                          Memory nodeMem,
-                          NetworkNode node,
-                          TupleSets trgTuples,
-                          boolean processSubnetwork) {
-        SegmentMemory smem = smems[smemIndex];
-        TupleSets stagedLeftTuples = null;
+                           RuleExecutor executor,
+                           LinkedList<StackEntry> stack,
+                           SegmentCursor sc,
+                           boolean processSubnetwork) {
+        
         while (true) {
-            TupleSets srcTuples = trgTuples; // previous target, is now the 
source
-            if (log.isTraceEnabled()) {
-                int offset = getOffset(node);
-                log.trace("{} {} {} {}", indent(offset), ++cycle, 
node.toString(), srcTuples.toStringSizes());
-            }
+            sc.traceStartOfEvaluation(++cycle);
 
-            if (!(NodeTypeEnums.isBetaNodeWithSubnetwork(node))) {
+            if 
(!(NodeTypeEnums.isBetaNodeWithSubnetwork(sc.getCurrentNode()))) {
                 // The engine cannot skip a TupleToObjectNode node, as the 
dirty might be several levels deep
-                if (srcTuples.isEmpty() && smem.getDirtyNodeMask() == 0) {
+                if (sc.isOnEmptyOrNonDirtySegment()) {
                     // empty sources and segment is not dirty, skip to non 
empty src tuples or dirty segment.
-                    boolean foundDirty = false;
-                    for (int i = ++smemIndex, length = smems.length; i < 
length; i++) {
-                        if (log.isTraceEnabled()) {
-                            int offset = getOffset(node);
-                            log.trace("{} Skip Segment {}", indent(offset), 
i-1);
-                        }
-
-                        // this is needed for subnetworks that feed into a 
parent network that has no right inputs,
-                        // and may not yet be initialized
-                        if (!NodeTypeEnums.isTerminalNode(smem.getTipNode())) {
-                            
segmentMemorySupport.initializeChildSegmentsIfNeeded(smem);
-                        }
-                        
-                        smem = smems[i];
-                        bit = 1;
-                        srcTuples = smem.getStagedLeftTuples().takeAll();
-                        node = smem.getRootNode();
-                        nodeMem = smem.getNodeMemories()[0];
-                        if (!srcTuples.isEmpty() ||
-                             smem.getDirtyNodeMask() != 0 ||
-                             (NodeTypeEnums.isBetaNode(node) && 
((BetaNode)node).getRightInput().inputIsTupleToObjectNode())) {
-                            // break if dirty or if we reach a subnetwork. It 
must break for subnetworks, so they can be searched.
-                            foundDirty = true;
-                            smemIndex = i;
-                            break;
-                        }
-                    }
+                    boolean foundDirty = moveToFirstDirtyOrNonEmptySegment(sc);
                     if (!foundDirty) {
                         break;
                     }
                 }
-                if (log.isTraceEnabled()) {
-                    int offset = getOffset(node);
-                    log.trace("{} Segment {}", indent(offset), smemIndex);
-                    log.trace("{} {} {} {}", indent(offset), cycle, 
node.toString(), srcTuples.toStringSizes());
-                }
-            }
-
-            if (srcTuples.isEmpty()) {
-                while ((smem.getDirtyNodeMask() & bit) == 0 && node != 
smem.getTipNode() && !NodeTypeEnums.isBetaNodeWithSubnetwork(node)) {
-                //while ((dirtyMask & bit) == 0 && node != smem.getTipNode() 
&& NodeTypeEnums.isBetaNodeWithoutSubnetwork(node)) {
-                    if (log.isTraceEnabled()) {
-                        int offset = getOffset(node);
-                        log.trace("{} Skip Node {}", indent(offset), node);
-                    }
-                    bit = nextNodePosMask(bit); // shift to check the next node
-                    node = ((LeftTupleNode) 
node).getSinkPropagator().getFirstLeftTupleSink();
-                    nodeMem = nodeMem.getNext();
-                }
+                sc.traceMoveToDirtySegment(cycle);
             }
 
-            boolean terminalNode = true;
-            switch (node.getType()) {
-                case NodeTypeEnums.RuleTerminalNode:
-                    pRtNode.doNode(activationsManager, executor, 
(AbstractTerminalNode) node, srcTuples);
-                    break;
-                case NodeTypeEnums.QueryTerminalNode:
-                    pQtNode.doNode(stack, (QueryTerminalNode) node, srcTuples);
-                    break;
-                case NodeTypeEnums.TupleToObjectNode:
-                    doSubnetwork2((TupleToObjectNode) node, srcTuples);
-                    break;
-                default:
-                    terminalNode = false;
+            if (sc.hasNoSourceTuples()) {
+                sc.moveToNextAvailableSegment();
             }
-            if (terminalNode) {
+            
+            if (NodeTypeEnums.isEndNode(sc.getCurrentNode())) {
+                evaluateEndNode(activationsManager, executor, stack, sc);
                 break;
             }
 
-            stagedLeftTuples = getTargetStagedLeftTuples(smem, node);
-            LeftTupleSinkNode sink = ((LeftTupleNode) 
node).getSinkPropagator().getFirstLeftTupleSink();
+            prepareStagedLeftTuples(sc);
 
-            trgTuples = evalNode(activationsManager, executor, stack, pmem, 
smems, smem, smemIndex, bit, nodeMem, node, sink, srcTuples, stagedLeftTuples, 
processSubnetwork);
-            if (trgTuples == null) {
+            sc.setSourceTuples(evaluateNonTerminalNode(activationsManager, 
executor, stack, sc, processSubnetwork));
+            if (sc.getSourceTuples() == null) {
                 break; // Queries exists and has been placed StackEntry, and 
there are no current trgTuples to process
             }
-
-            if (node != smem.getTipNode()) {
-                // get next node and node memory in the segment
-                node = sink;
-                nodeMem = nodeMem.getNext();
-                bit = nextNodePosMask(bit);
-            } else {
-                // Reached end of segment, start on new segment.
-                
smem.getFirst().getStagedLeftTuples().addAll(stagedLeftTuples); // must put 
back all the LTs
+            
+            if (sc.isAtEndOfSegmentMemory()) {
                 // end of SegmentMemory, so we know that stagedLeftTuples is 
not null
-                propagate(smem, trgTuples);
-                bit = 1;
-                smem = smems[++smemIndex];
-                trgTuples = smem.getStagedLeftTuples().takeAll();
-
-                if (log.isTraceEnabled()) {
-                    int offset = getOffset(node);
-                    log.trace("{} Segment {}", indent(offset), smemIndex);
-                }
-                node = smem.getRootNode();
-                nodeMem = smem.getNodeMemories()[0];
+                sc.restoreStagedLeftTuples(); // must put back all the LTs
+                propagate(sc.getCurrentSegment(), sc.getSourceTuples());
             }
+
+            sc.moveToNextNodeOrSegment();
             processSubnetwork = true; //  make sure it's reset, so ria nodes 
are processed
         }
 
-        if (stagedLeftTuples != null && !stagedLeftTuples.isEmpty()) {
-            smem.getFirst().getStagedLeftTuples().addAll(stagedLeftTuples); // 
must put back all the LTs
+        if (sc.stagedLeftTuplesAreNotEmpty()) {
+            sc.restoreStagedLeftTuples(); // must put back all the LTs
         }
     }
 
-    private TupleSets evalNode(ActivationsManager activationsManager,
+
+    private void evaluateEndNode(ActivationsManager activationsManager,
+                          RuleExecutor executor,
+                          LinkedList<StackEntry> stack,
+                          SegmentCursor sc) {
+        switch (sc.getCurrentNode().getType()) {
+            case NodeTypeEnums.RuleTerminalNode:
+                pRtNode.doNode(activationsManager, executor, 
(AbstractTerminalNode) sc.getCurrentNode(), sc.getSourceTuples());
+                break;
+            case NodeTypeEnums.QueryTerminalNode:
+                pQtNode.doNode(stack, (QueryTerminalNode) sc.getCurrentNode(), 
sc.getSourceTuples());
+                break;
+            case NodeTypeEnums.TupleToObjectNode:
+                doSubnetwork2((TupleToObjectNode) sc.getCurrentNode(), 
sc.getSourceTuples());
+                break;
+            default:
+                // Nothing to do
+        }
+    }
+
+    private boolean moveToFirstDirtyOrNonEmptySegment(SegmentCursor sc) {
+        for (int i = sc.getSegmentMemoryIndex() + 1, length = 
sc.getSegmentMemorySize(); i < length; i++) {
+            sc.traceSkipNonDirtySegment(i);
+
+            // this is needed for subnetworks that feed into a parent network 
that has no right inputs,
+            // and may not yet be initialized
+            if 
(!NodeTypeEnums.isTerminalNode(sc.getCurrentSegment().getTipNode())) {
+                
segmentMemorySupport.initializeChildSegmentsIfNeeded(sc.getCurrentSegment());
+            }
+            
+            sc.moveToSegment(i);
+            if (sc.isDirtySegmentOrIsSubnetwork()) {
+                // break if dirty or if we reach a subnetwork. It must break 
for subnetworks, so they can be searched.
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private TupleSets evaluateNonTerminalNode(ActivationsManager 
activationsManager,
                               RuleExecutor executor,
                               LinkedList<StackEntry> stack,
-                              PathMemory pmem,
-                              SegmentMemory[] smems,
-                              SegmentMemory smem,
-                              int smemIndex,
-                              long bit,
-                              Memory nodeMem,
-                              NetworkNode node,
-                              LeftTupleSinkNode sink,
-                              TupleSets srcTuples,
-                              TupleSets stagedLeftTuples,
+                              SegmentCursor sc, 
                               boolean processSubnetwork) {
-        TupleSets trgTuples = new TupleSetsImpl();
-        if (NodeTypeEnums.isBetaNode(node)) {
-            boolean exitInnerEval = evalBetaNode(activationsManager, executor, 
stack, pmem, smems, smemIndex, nodeMem, node, sink, trgTuples, srcTuples, 
stagedLeftTuples, processSubnetwork);
-            if (exitInnerEval) {
-                return null;
-            }
+        if (NodeTypeEnums.isBetaNode(sc.getCurrentNode())) {
+            return evaluateBetaNode(activationsManager, executor, stack, sc, 
processSubnetwork);
         } else {
-            boolean exitInnerEval = false;
-            switch (node.getType()) {
-                case NodeTypeEnums.EvalConditionNode: {
-                    pEvalNode.doNode((EvalConditionNode) node, (EvalMemory) 
nodeMem, sink,
-                            srcTuples, trgTuples, stagedLeftTuples);
-                    break;
+            return evaluateNonBetaNonTerminalNode(activationsManager, 
executor, stack, sc);
+                
+        }
+    }
 
-                }
-                case NodeTypeEnums.FromNode: {
-                    pFromNode.doNode((FromNode) node, (FromMemory) nodeMem, 
sink,
-                            srcTuples, trgTuples, stagedLeftTuples);
-                    break;
-                }
-                case NodeTypeEnums.ReactiveFromNode: {
-                    pReactiveFromNode.doNode((ReactiveFromNode) node, 
(ReactiveFromNode.ReactiveFromMemory) nodeMem, sink,
-                                             srcTuples, trgTuples, 
stagedLeftTuples);
-                    break;
-                }
-                case NodeTypeEnums.QueryElementNode: {
-                    exitInnerEval =  evalQueryNode(stack, pmem, smems, 
smemIndex, bit, nodeMem, node,
-                                                   sink, trgTuples, srcTuples, 
stagedLeftTuples);
-                    break;
-                }
-                case NodeTypeEnums.TimerConditionNode: {
-                    pTimerNode.doNode((TimerNode) node, (TimerNodeMemory) 
nodeMem, pmem, smem, sink, activationsManager, srcTuples, trgTuples, 
stagedLeftTuples);
-                    break;
-                }
-                case NodeTypeEnums.ConditionalBranchNode: {
-                    pBranchNode.doNode(activationsManager, 
(ConditionalBranchNode) node, (ConditionalBranchMemory) nodeMem,
-                            sink, srcTuples, trgTuples, stagedLeftTuples, 
executor);
-                    break;
-                }
-                case NodeTypeEnums.AsyncSendNode: {
-                    pSendNode.doNode((AsyncSendNode) node, (AsyncSendMemory) 
nodeMem, srcTuples);
-                    break;
-                }
-                case NodeTypeEnums.AsyncReceiveNode: {
-                    pReceiveNode.doNode((AsyncReceiveNode) node, 
(AsyncReceiveMemory) nodeMem, sink, srcTuples, trgTuples);
-                    break;
-                }
+    public TupleSets evaluateNonBetaNonTerminalNode(ActivationsManager 
activationsManager,
+                                                    RuleExecutor executor,
+                                                    LinkedList<StackEntry> 
stack,
+                                                    SegmentCursor sc) {
+        TupleSets trgTuples = new TupleSetsImpl();
+        LeftTupleSinkNode sink = sc.getFirstLeftTupleSink();
+        boolean exitInnerEval = false;
+        switch (sc.getCurrentNode().getType()) {
+            case NodeTypeEnums.EvalConditionNode: {
+                pEvalNode.doNode((EvalConditionNode) sc.getCurrentNode(), 
(EvalMemory) sc.getCurrentNodeMemory(), sink,
+                        sc.getSourceTuples(), sc.getStagedLeftTuples(), 
trgTuples);
+                break;
+
+            }
+            case NodeTypeEnums.FromNode: {
+                pFromNode.doNode((FromNode) sc.getCurrentNode(), (FromMemory) 
sc.getCurrentNodeMemory(), sink,
+                        sc.getSourceTuples(), sc.getStagedLeftTuples(), 
trgTuples);
+                break;
+            }
+            case NodeTypeEnums.ReactiveFromNode: {
+                pReactiveFromNode.doNode((ReactiveFromNode) 
sc.getCurrentNode(), (ReactiveFromNode.ReactiveFromMemory) 
sc.getCurrentNodeMemory(), sink,
+                                         sc.getSourceTuples(), 
sc.getStagedLeftTuples(), trgTuples);
+                break;
             }
-            if (exitInnerEval && trgTuples.isEmpty()) {
-                return null;
+            case NodeTypeEnums.QueryElementNode: {
+                exitInnerEval =  evaluateQueryNode(stack, sc, trgTuples);
+                break;
+            }
+            case NodeTypeEnums.TimerConditionNode: {
+                pTimerNode.doNode(activationsManager, sc, (TimerNode) 
sc.getCurrentNode(), (TimerNodeMemory) sc.getCurrentNodeMemory(), sink, 
sc.getSourceTuples(), sc.getStagedLeftTuples(), trgTuples);
+                break;
+            }
+            case NodeTypeEnums.ConditionalBranchNode: {
+                pBranchNode.doNode(activationsManager, executor, 
(ConditionalBranchNode) sc.getCurrentNode(),
+                        (ConditionalBranchMemory) sc.getCurrentNodeMemory(), 
sink, sc.getSourceTuples(), sc.getStagedLeftTuples(), trgTuples);
+                break;
+            }
+            case NodeTypeEnums.AsyncSendNode: {
+                pSendNode.doNode((AsyncSendNode) sc.getCurrentNode(), 
(AsyncSendMemory) sc.getCurrentNodeMemory(), sc.getSourceTuples());
+                break;
+            }
+            case NodeTypeEnums.AsyncReceiveNode: {
+                pReceiveNode.doNode((AsyncReceiveNode) sc.getCurrentNode(), 
(AsyncReceiveMemory) sc.getCurrentNodeMemory(), sink, sc.getSourceTuples(), 
trgTuples);
+                break;
             }
         }
-        return trgTuples;
+        if (exitInnerEval && trgTuples.isEmpty()) {
+            return null;
+        } else {
+            return trgTuples;
+        }
     }
 
-    private TupleSets getTargetStagedLeftTuples(SegmentMemory smem,
-                                                       NetworkNode node) {
-        if (node == smem.getTipNode()) {
+    private void prepareStagedLeftTuples(SegmentCursor sc) {
+        if (sc.isAtEndOfSegmentMemory()) {
             // we are about to process the segment tip, allow it to merge 
insert/update/delete clashes
-            segmentMemorySupport.initializeChildSegmentsIfNeeded(smem);
-            return smem.getFirst().getStagedLeftTuples().takeAll();
+            
segmentMemorySupport.initializeChildSegmentsIfNeeded(sc.getCurrentSegment());
+            sc.saveStagedLeftTuples();
         } else {
-            return null;
+            sc.resetStagedLeftTuples();
         }
     }
 
-    private boolean evalQueryNode(LinkedList<StackEntry> stack,
-                                  PathMemory pmem,
-                                  SegmentMemory[] smems,
-                                  int smemIndex,
-                                  long bit,
-                                  Memory nodeMem,
-                                  NetworkNode node,
-                                  LeftTupleSinkNode sink,
-                                  TupleSets trgTuples,
-                                  TupleSets srcTuples,
-                                  TupleSets stagedLeftTuples) {
-        QueryElementNodeMemory qmem = (QueryElementNodeMemory) nodeMem;
-
-        if (srcTuples.isEmpty() && qmem.getResultLeftTuples().isEmpty()) {
+    private boolean evaluateQueryNode(LinkedList<StackEntry> stack,
+                                      SegmentCursor sc1,
+                                      TupleSets trgTuples) {
+        QueryElementNodeMemory qmem = (QueryElementNodeMemory) 
sc1.getCurrentNodeMemory();
+
+        if (sc1.getSourceTuples().isEmpty() && 
qmem.getResultLeftTuples().isEmpty()) {
             // no point in evaluating query element, and setting up stack, if 
there is nothing to process
             return false;
         }
-
-        QueryElementNode qnode = (QueryElementNode) node;
-
-        if (log.isTraceEnabled()) {
-            int offset = getOffset(node);
-            log.trace("{} query result tuples {}", indent(offset), 
qmem.getResultLeftTuples().toStringSizes());
-        }
+        sc1.traceQueryResultTuples();
 
         // result tuples can happen when reactivity occurs inside of the 
query, prior to evaluation
         // we will need special behaviour to add the results again, when this 
query result resumes
         qmem.getResultLeftTuples().addTo(trgTuples);
         qmem.setNodeCleanWithoutNotify();
 
-        if (srcTuples.isEmpty()) {
+        if (sc1.getSourceTuples().isEmpty()) {
             return false;
         } 
         // only process the Query Node if there are src tuples
-        StackEntry stackEntry = new StackEntry(node, bit, sink, pmem, nodeMem, 
smems,
-                                               smemIndex, trgTuples, true, 
true);
-
+        StackEntry stackEntry = 
sc1.saveForResumeAfterQueryExecution(trgTuples);
         stack.add(stackEntry);
 
-        pQueryNode.doNode(qnode, (QueryElementNodeMemory) nodeMem, stackEntry,
-                srcTuples, trgTuples, stagedLeftTuples);
+        pQueryNode.doNode(stackEntry, (QueryElementNode) sc1.getCurrentNode(), 
(QueryElementNodeMemory) sc1.getCurrentNodeMemory(),
+                sc1.getSourceTuples(), sc1.getStagedLeftTuples(), trgTuples);
 
-        SegmentMemory qsmem = ((QueryElementNodeMemory) 
nodeMem).getQuerySegmentMemory();
+        SegmentMemory qsmem = ((QueryElementNodeMemory) 
sc1.getCurrentNodeMemory()).getQuerySegmentMemory();
         List<PathMemory> qpmems = qsmem.getPathMemories();
 
         // Build the evaluation information for each 'or' branch
         for (int i = 0; i < qpmems.size() ; i++) {
             PathMemory qpmem = qpmems.get(i);
-
-            pmem = qpmem;
-            smems = qpmem.getSegmentMemories();
-            smemIndex = 0;
-            SegmentMemory smem = smems[smemIndex]; // 0
-
-            LeftTupleNode liaNode = qpmem.getPathEndNode().getPathNodes()[0];
-
-            if (liaNode == smem.getTipNode()) {
-                // segment only has liaNode in it
-                // nothing is staged in the liaNode, so skip to next segment
-                smem = smems[++smemIndex]; // 1
-                node = smem.getRootNode();
-                nodeMem = smem.getNodeMemories()[0];
-                bit = 1;
-            } else {
-                // lia is in shared segment, so point to next node
-                node = liaNode.getSinkPropagator().getFirstLeftTupleSink();
-                nodeMem = smem.getNodeMemories()[1]; // skip the liaNode memory
-                bit = 2;
-            }
-
-            trgTuples = smem.getStagedLeftTuples().takeAll();
-            stackEntry = new StackEntry(node, bit, null, pmem,
-                                        nodeMem, smems, smemIndex,
-                                        trgTuples, false, true);
-            if (log.isTraceEnabled()) {
-                int offset = getOffset(stackEntry.getNode());
-                log.trace("{} ORQueue branch={} {} {}", indent(offset), i, 
stackEntry.getNode().toString(), trgTuples.toStringSizes());
-            }
-            stack.add(stackEntry);
+            SegmentCursor scForOrQueries = 
SegmentCursor.createSegmentCursorForQueryExecution(qpmem);
+            StackEntry stackEntryForQueryBranchEvaluation = 
scForOrQueries.saveForQueryBranchEvaluation();
+            scForOrQueries.traceOrQueryBranchQueued(i);
+            stack.add(stackEntryForQueryBranchEvaluation);
         }
         return true;
 
     }
 
-    private boolean evalBetaNode(ActivationsManager activationsManager,
+    private TupleSets evaluateBetaNode(ActivationsManager activationsManager,
                                  RuleExecutor executor,
                                  LinkedList<StackEntry> stack,
-                                 PathMemory pmem,
-                                 SegmentMemory[] smems,
-                                 int smemIndex,
-                                 Memory nodeMem,
-                                 NetworkNode node,
-                                 LeftTupleSinkNode sink,
-                                 TupleSets trgTuples,
-                                 TupleSets srcTuples,
-                                 TupleSets stagedLeftTuples,
+                                 SegmentCursor sc,
                                  boolean processSubnetwork) {
-        BetaNode betaNode = (BetaNode) node;
+
         BetaMemory bm;
         AccumulateMemory am = null;
-        if (NodeTypeEnums.AccumulateNode == node.getType()) {
-            am = (AccumulateMemory) nodeMem;
+        if (NodeTypeEnums.AccumulateNode == sc.getCurrentNode().getType()) {
+            am = (AccumulateMemory) sc.getCurrentNodeMemory();
             bm = am.getBetaMemory();
         } else {
-            bm = (BetaMemory) nodeMem;
+            bm = (BetaMemory) sc.getCurrentNodeMemory();
         }
 
-        if (processSubnetwork && 
betaNode.getRightInput().inputIsTupleToObjectNode()) {
+        if (processSubnetwork && ((BetaNode) 
sc.getCurrentNode()).getRightInput().inputIsTupleToObjectNode()) {
             // if the subnetwork is nested in this segment, it will create 
srcTuples containing
             // peer LeftTuples, suitable for the node in the main path.
-            doSubnetwork(activationsManager, executor, stack,
-                         pmem, smems, smemIndex, nodeMem, srcTuples, bm, 
betaNode, sink);
-            return true; // return here, TupleToObjectNode queues the 
evaluation on the stack, which is necessary to handled nested query nodes
+            doSubnetwork(activationsManager, executor, stack, sc, bm);
+            return null; // return here, TupleToObjectNode queues the 
evaluation on the stack, which is necessary to handled nested query nodes
         }
-
-        switchOnDoBetaNode(bm, am, node, sink, trgTuples, srcTuples, 
stagedLeftTuples);
-
-        return false;
+        return switchOnDoBetaNode(sc, bm, am);
     }
 
-    private void switchOnDoBetaNode(BetaMemory bm,
-                                    AccumulateMemory am,
-                                    NetworkNode node,
-                                    LeftTupleSinkNode sink,
-                                    TupleSets trgTuples,
-                                    TupleSets srcTuples,
-                                    TupleSets stagedLeftTuples) {
-        if (log.isTraceEnabled()) {
-            int offset = getOffset(node);
-            log.trace("{} rightTuples {}", indent(offset), 
bm.getStagedRightTuples().toStringSizes());
-        }
+    private TupleSets switchOnDoBetaNode(SegmentCursor sc,
+                                    BetaMemory bm,
+                                    AccumulateMemory am) {
+        TupleSets trgTuples = new TupleSetsImpl();
+        sc.traceSwitchOnBetaNodes(bm);
 
-        switch (node.getType()) {
+        LeftTupleSinkNode sink = sc.getFirstLeftTupleSink();
+        switch (sc.getCurrentNode().getType()) {
             case NodeTypeEnums.JoinNode: {
-                pJoinNode.doNode((JoinNode) node, sink, bm,
-                        srcTuples, trgTuples, stagedLeftTuples);
+                pJoinNode.doNode((JoinNode) sc.getCurrentNode(), sink, bm,
+                        sc.getSourceTuples(), sc.getStagedLeftTuples(), 
trgTuples);
                 break;
             }
             case NodeTypeEnums.NotNode: {
-                pNotNode.doNode((NotNode) node, sink, bm,
-                        srcTuples, trgTuples, stagedLeftTuples);
+                pNotNode.doNode((NotNode) sc.getCurrentNode(), sink, bm,
+                        sc.getSourceTuples(), sc.getStagedLeftTuples(), 
trgTuples);
                 break;
             }
             case NodeTypeEnums.ExistsNode: {
-                pExistsNode.doNode((ExistsNode) node, sink, bm,
-                        srcTuples, trgTuples, stagedLeftTuples);
+                pExistsNode.doNode((ExistsNode) sc.getCurrentNode(), sink, bm,
+                        sc.getSourceTuples(), sc.getStagedLeftTuples(), 
trgTuples);
                 break;
             }
             case NodeTypeEnums.AccumulateNode: {
-                AccumulateNode accumulateNode = (AccumulateNode) node;
+                AccumulateNode accumulateNode = (AccumulateNode) 
sc.getCurrentNode();
                 if (accumulateNode.getAccumulate().isGroupBy()) {
-                    pGroupByNode.doNode(accumulateNode, sink, am, srcTuples, 
trgTuples, stagedLeftTuples);
+                    pGroupByNode.doNode(accumulateNode, sink, am, 
sc.getSourceTuples(), sc.getStagedLeftTuples(), trgTuples);
                 } else {
-                    pAccNode.doNode(accumulateNode, sink, am, srcTuples, 
trgTuples, stagedLeftTuples);
+                    pAccNode.doNode(accumulateNode, sink, am, 
sc.getSourceTuples(), sc.getStagedLeftTuples(), trgTuples);
                 }
                 break;
             }
         }
+        return trgTuples;
     }
 
     private void doSubnetwork(ActivationsManager activationsManager,
                               RuleExecutor executor,
                               LinkedList<StackEntry> stack,
-                              PathMemory pmem,
-                              SegmentMemory[] smems,
-                              int smemIndex,
-                              Memory nodeMem,
-                              TupleSets srcTuples,
-                              BetaMemory bm,
-                              BetaNode betaNode,
-                              LeftTupleSinkNode sink) {
-        PathMemory pathMem = bm.getSubnetworkPathMemory();
-        SegmentMemory[]      subnetworkSmems = pathMem.getSegmentMemories();
-        SegmentMemory subSmem = null;
-        for (int i = 0; subSmem == null; i++) {
-            // segment positions outside of the subnetwork, in the parent 
chain, are null
-            // so we must iterate to find the first non null segment memory
-            subSmem =  subnetworkSmems[i];
-        }
+                              SegmentCursor sc,
+                              BetaMemory bm) {
+
 
-        // Resume the node after the TupleToObjectNode segment has been 
processed and the right input memory populated
-        StackEntry stackEntry = new StackEntry(betaNode, 
bm.getNodePosMaskBit(), sink, pmem, nodeMem, smems,
-                                               smemIndex, srcTuples, false, 
false);
+        StackEntry stackEntry = sc.saveForResumeAfterSubnetworkExecution();
         stack.add(stackEntry);
-        if (log.isTraceEnabled()) {
-            int offset = getOffset(betaNode);
-            log.trace("{} SubnetworkQueue {} {}", indent(offset), 
betaNode.toString(), srcTuples.toStringSizes());
-        }
+        sc.traceSubnetworkQueue();
 
+        PathMemory pathMem = bm.getSubnetworkPathMemory();
+        SegmentCursor scNew = SegmentCursor.createForSubNetwork(pathMem);
         
-        
-
-        TupleSets subLts = subSmem.getStagedLeftTuples().takeAll();
-        // node is first in the segment, so bit is 1
-        innerEval(activationsManager, executor, stack,
-                   pathMem,
-                   subnetworkSmems, subSmem.getPos(),
-                   1, subSmem.getNodeMemories()[0], subSmem.getRootNode(), 
subLts, true);
+        innerEval(activationsManager, executor, stack, scNew, true);
     }
 
     private void doSubnetwork2(TupleToObjectNode tton,
@@ -993,7 +781,7 @@ public class RuleNetworkEvaluatorImpl implements 
RuleNetworkEvaluator {
                 break;
             default:
                 // no clash, so just add
-                if (childLeftTuple.getSink().getType() == AccumulateNode ) {
+                if (childLeftTuple.getSink().getType() == 
NodeTypeEnums.AccumulateNode ) {
                     trgLeftTuples.addInsert(childLeftTuple);
                 } else {
                     trgLeftTuples.addUpdate(childLeftTuple);
@@ -1016,36 +804,5 @@ public class RuleNetworkEvaluatorImpl implements 
RuleNetworkEvaluator {
         }
     }
 
-    
-    
-    
-    
 
-    private static String indent(int size) {
-        StringBuilder sbuilder = new StringBuilder();
-        for (int i = 0; i < size; i++) {
-            sbuilder.append("  ");
-        }
-
-        return sbuilder.toString();
-    }
-
-    private static int getOffset(NetworkNode node) {
-        LeftTupleNode lt;
-        int offset = 1;
-        if (NodeTypeEnums.isTerminalNode(node)) {
-            lt = ((TerminalNode) node).getLeftTupleSource();
-            offset++;
-        } else if (node.getType() == NodeTypeEnums.TupleToObjectNode) {
-            lt = ((TupleToObjectNode) node).getLeftTupleSource();
-        } else {
-            lt = (LeftTupleNode) node;
-        }
-        while (!NodeTypeEnums.isLeftInputAdapterNode(lt)) {
-            offset++;
-            lt = lt.getLeftTupleSource();
-        }
-
-        return offset;
-    }
 }
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/SegmentCursor.java 
b/drools-core/src/main/java/org/drools/core/phreak/SegmentCursor.java
new file mode 100644
index 0000000000..2cb90c27b7
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/core/phreak/SegmentCursor.java
@@ -0,0 +1,475 @@
+/*
+ * 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
+ *
+ *   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.
+ */
+package org.drools.core.phreak;
+
+import org.drools.base.common.NetworkNode;
+import org.drools.base.reteoo.NodeTypeEnums;
+import org.drools.core.common.Memory;
+import org.drools.core.common.TupleSets;
+import org.drools.core.reteoo.BetaMemory;
+import org.drools.core.reteoo.BetaNode;
+import org.drools.core.reteoo.LeftTupleNode;
+import org.drools.core.reteoo.LeftTupleSink;
+import org.drools.core.reteoo.LeftTupleSinkNode;
+import org.drools.core.reteoo.PathMemory;
+import org.drools.core.reteoo.SegmentMemory;
+import org.drools.core.reteoo.SegmentNodeMemory;
+import org.drools.core.reteoo.TerminalNode;
+import org.drools.core.reteoo.TupleToObjectNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.drools.core.phreak.BuildtimeSegmentUtilities.nextNodePosMask;
+
+public class SegmentCursor {
+    private static final Logger log = 
LoggerFactory.getLogger(SegmentCursor.class);
+    
+    private final PathMemory pmem;
+    private final SegmentMemory[] smems;
+
+    private int smemIndex;
+    private long bit;
+    private Memory nodeMem;
+    private NetworkNode node;
+    private TupleSets srcTuples;
+    private TupleSets stagedLeftTuples;
+    
+    public SegmentCursor(PathMemory pmem,
+                         SegmentMemory[] smems,
+                         int smemIndex,
+                         long bit,
+                         Memory nodeMem,
+                         NetworkNode node, 
+                         TupleSets srcTuples) {
+        this.pmem = pmem;
+        this.smems = smems;
+        this.smemIndex = smemIndex;
+        this.bit = bit;
+        this.nodeMem = nodeMem;
+        this.node = node;
+        this.srcTuples = srcTuples;
+    }
+    
+    public PathMemory getPathMemory() {
+        return pmem;
+    }
+    
+    public int getSegmentMemorySize() {
+        return smems.length;
+    }
+    
+    public Memory getCurrentNodeMemory() {
+        return nodeMem;
+    }
+    
+    public int getSegmentMemoryIndex() {
+        return smemIndex;
+    }
+    
+    public NetworkNode getCurrentNode() {
+        return node;
+    }
+    
+    public TupleSets getSourceTuples() {
+        return srcTuples;
+    }
+    
+    public TupleSets getStagedLeftTuples() {
+        return stagedLeftTuples;
+    }
+    
+    public SegmentMemory getCurrentSegment() {
+        return smems[smemIndex];
+    }
+    
+    public void setSourceTuples(TupleSets srcTuples) {
+        this.srcTuples = srcTuples;
+    }
+    
+    
+    public void moveToNextAvailableSegment() {
+        while ((getCurrentSegment().getDirtyNodeMask() & bit) == 0 && node != 
getCurrentSegment().getTipNode() && 
!NodeTypeEnums.isBetaNodeWithSubnetwork(node)) {
+        //while ((dirtyMask & bit) == 0 && node != smem.getTipNode() && 
NodeTypeEnums.isBetaNodeWithoutSubnetwork(node)) {
+            if (log.isTraceEnabled()) {
+                int offset = getOffset(node);
+                log.trace("{} Skip Node {}", indent(offset), node);
+            }
+            bit = nextNodePosMask(bit); // shift to check the next node
+            node = ((LeftTupleNode) 
node).getSinkPropagator().getFirstLeftTupleSink();
+            nodeMem = nodeMem.getNext();
+        }
+    }
+
+    public void moveToNextNodeInSegment() {
+        node = ((LeftTupleNode) 
node).getSinkPropagator().getFirstLeftTupleSink();
+        nodeMem = nodeMem.getNext();
+        bit = nextNodePosMask(bit);
+    }
+
+    public void moveToNextSegment() {
+        // Reached end of segment, start on new segment.
+        bit = 1;
+        smemIndex = smemIndex + 1;
+    
+        node = getCurrentSegment().getRootNode();
+        nodeMem = getCurrentSegment().getNodeMemories()[0];
+    }
+
+    public void moveToNextNodeOrSegment() {
+        if (node == getCurrentSegment().getTipNode()) {
+            moveToNextSegment();
+            srcTuples = getCurrentSegment().getStagedLeftTuples().takeAll();
+            traceMoveToNextNodeOrSegment();
+        } else {
+            // get next node and node memory in the segment
+            moveToNextNodeInSegment();
+        }
+    }
+
+    public void moveToSegment(int i) {
+        smemIndex = i;
+        bit = 1;
+        srcTuples = getCurrentSegment().getStagedLeftTuples().takeAll();
+        node = getCurrentSegment().getRootNode();
+        nodeMem = getCurrentSegment().getNodeMemories()[0];
+    }
+
+    public boolean isDirtySegmentOrIsSubnetwork() {
+        return !srcTuples.isEmpty() ||
+             getCurrentSegment().getDirtyNodeMask() != 0 ||
+             (NodeTypeEnums.isBetaNode(node) && 
((BetaNode)node).getRightInput().inputIsTupleToObjectNode());
+    }
+
+    public boolean isOnEmptyOrNonDirtySegment() {
+        return srcTuples.isEmpty() && getCurrentSegment().getDirtyNodeMask() 
== 0;
+    }
+
+    public boolean isAtEndOfSegmentMemory() {
+        return node == getCurrentSegment().getTipNode();
+    }
+
+    public boolean hasNoSourceTuples() {
+        return srcTuples.isEmpty();
+    }
+
+    public void restoreStagedLeftTuples() {
+        
getCurrentSegment().getFirst().getStagedLeftTuples().addAll(stagedLeftTuples);
+    }
+
+    public boolean stagedLeftTuplesAreNotEmpty() {
+        return stagedLeftTuples != null && !stagedLeftTuples.isEmpty();
+    }
+
+    public void traceStartOfEvaluation(int cycle) {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} {} {} {}", indent(offset), cycle, node.toString(), 
srcTuples.toStringSizes());
+        }
+    }
+
+    public void traceMoveToDirtySegment(int cycle2) {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} Segment {}", indent(offset), smemIndex);
+            log.trace("{} {} {} {}", indent(offset), cycle2, node.toString(), 
srcTuples.toStringSizes());
+        }
+    }
+
+    public void traceSkipNonDirtySegment(int i) {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} Skip Segment {}", indent(offset), i-1);
+        }
+    }
+
+    public void traceMoveToNextNodeOrSegment() {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} Segment {}", indent(offset), smemIndex);
+        }
+    }
+    
+    public void traceResumeFromStack() {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} Resume {} {}", indent(offset), node.toString(), 
srcTuples.toStringSizes());
+        }
+    }
+
+    public void traceSubnetworkQueue() {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} SubnetworkQueue {} {}", indent(offset), 
node.toString(), srcTuples.toStringSizes());
+        }
+    }
+
+    public void traceSwitchOnBetaNodes(BetaMemory bm) {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} rightTuples {}", indent(offset), 
bm.getStagedRightTuples().toStringSizes());
+        }
+    }
+
+    public void traceQueryResultTuples() {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} query result tuples {}", indent(offset), 
((org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory) 
nodeMem).getResultLeftTuples().toStringSizes());
+        }
+    }
+
+    public void traceOrQueryBranchQueued(int i) {
+        if (log.isTraceEnabled()) {
+            int offset = getOffset(node);
+            log.trace("{} ORQueue branch={} {} {}", indent(offset), i, 
node.toString(), srcTuples.toStringSizes());
+        }
+    }
+
+    public void traceNetworkEvaluation() {
+        if (log.isTraceEnabled()) {
+            log.trace("Rule[name={}] segments={} {}", 
((TerminalNode)pmem.getPathEndNode()).getRule().getName(), 
pmem.getSegmentMemories().length, srcTuples.toStringSizes());
+        }
+    }
+
+    public StackEntry saveForResumeAfterQueryExecution(TupleSets trgTuples) {
+        LeftTupleSinkNode sink = getFirstLeftTupleSink();
+        StackEntry stackEntry = new StackEntry(node, bit, sink, pmem, nodeMem, 
smems,
+                                               smemIndex, trgTuples, true, 
true);
+        return stackEntry;
+    }
+
+    public StackEntry saveForResumeAfterSubnetworkExecution() {
+        LeftTupleSinkNode sink = getFirstLeftTupleSink();
+        // Resume the node after the TupleToObjectNode segment has been 
processed and the right input memory populated
+        return new StackEntry(node, ((SegmentNodeMemory) 
nodeMem).getNodePosMaskBit(), sink, pmem, nodeMem, smems,
+                                               smemIndex, srcTuples, false, 
false);
+    }
+
+    public StackEntry saveForQueryBranchEvaluation() {
+        return new StackEntry(node, bit, null, pmem,
+                                    nodeMem, pmem.getSegmentMemories(), 
smemIndex,
+                                    srcTuples, false, true);
+    }
+
+    public LeftTupleSinkNode getFirstLeftTupleSink() {
+        return ((LeftTupleNode) 
node).getSinkPropagator().getFirstLeftTupleSink();
+    }
+
+    public void saveStagedLeftTuples() {
+        stagedLeftTuples = 
getCurrentSegment().getFirst().getStagedLeftTuples().takeAll();
+    }
+
+    public void resetStagedLeftTuples() {
+        stagedLeftTuples = null;
+    }
+
+    public static SegmentCursor createForSubNetwork(PathMemory pathMem) {
+        SegmentMemory[]      subnetworkSmems = pathMem.getSegmentMemories();
+        SegmentMemory subSmem = null;
+        for (int i = 0; subSmem == null; i++) {
+            // segment positions outside of the subnetwork, in the parent 
chain, are null
+            // so we must iterate to find the first non null segment memory
+            subSmem =  subnetworkSmems[i];
+        }
+        TupleSets subLts = subSmem.getStagedLeftTuples().takeAll();
+        // node is first in the segment, so bit is 1
+        
+        return new SegmentCursor(pathMem, 
+                subnetworkSmems, 
+                subSmem.getPos(), 
+                1, 
+                subSmem.getNodeMemories()[0], 
+                subSmem.getRootNode(), 
+                subLts);
+    }
+
+    public static SegmentCursor createForResume(StackEntry entry) {
+        NetworkNode node;
+        SegmentMemory smem = entry.getSmems()[entry.getSmemIndex()];
+        if (entry.getNode() == smem.getTipNode()) {
+            // Reached end of segment, start on new segment.
+            smem = entry.getSmems()[entry.getSmemIndex() + 1];
+            return new SegmentCursor(entry.getRmem(), 
+                    entry.getSmems(), 
+                    entry.getSmemIndex() + 1, 
+                    1, // update bit to start of new segment
+                    smem.getNodeMemories()[0], 
+                    smem.getRootNode(), 
+                    smem.getStagedLeftTuples().takeAll());
+            
+    
+        } else {
+            // get next node and node memory in the segment
+            LeftTupleSink nextSink = 
entry.getSink().getNextLeftTupleSinkNode();
+            if (nextSink == null) {
+                node = entry.getSink();
+            } else {
+                // there is a nested subnetwork, take out path
+                node = nextSink;
+            }
+            return new SegmentCursor(entry.getRmem(), 
+                    entry.getSmems(), 
+                    entry.getSmemIndex(), 
+                    nextNodePosMask(entry.getBit()), // update bit to new 
node, 
+                    entry.getNodeMem().getNext(), 
+                    node, 
+                    entry.getTrgTuples());
+        }
+    }
+
+    public static SegmentCursor createForNonResume(StackEntry entry) {
+        SegmentCursor sc;
+        sc = new SegmentCursor(entry.getRmem(), 
+                entry.getSmems(), 
+                entry.getSmemIndex(), 
+                entry.getBit(), 
+                entry.getNodeMem(), 
+                entry.getNode(), 
+                entry.getTrgTuples());
+        return sc;
+    }
+
+    public static SegmentCursor createSegmentCursor(PathMemory pmem, 
SegmentMemory sm, TupleSets tupleSets) {
+        if (NodeTypeEnums.isLeftInputAdapterNode(sm.getRootNode()) && 
!NodeTypeEnums.isLeftInputAdapterNode(sm.getTipNode())) {
+            return new SegmentCursor(pmem, 
+                    pmem.getSegmentMemories(), 
+                    sm.getPos(),
+                    2L,
+                    sm.getNodeMemories()[1],
+                    // The segment is the first and it has the lian shared 
with other nodes, the lian must be skipped, so adjust the bit and sink
+                    
sm.getRootNode().getSinkPropagator().getFirstLeftTupleSink(), 
+                    tupleSets);
+        } else {
+            return new SegmentCursor(pmem, 
+                    pmem.getSegmentMemories(), 
+                    sm.getPos(),
+                    1L,
+                    sm.getNodeMemories()[0],
+                    sm.getRootNode(), 
+                    tupleSets);
+        }
+    }
+
+    
+
+    public static SegmentCursor createSegmentCursor(PathMemory pmem, 
NetworkNode sink, Memory tm, TupleSets tupleSets) {
+        SegmentMemory[] smems = pmem.getSegmentMemories();
+        SegmentMemory sm = tm.getSegmentMemory();
+        int smemIndex = 0;
+        for (SegmentMemory smem : smems) {
+            if (smem == sm) {
+                break;
+            }
+            smemIndex++;
+        }
+
+        long bit = 1;
+        for (NetworkNode node = sm.getRootNode(); node != sink; node = 
((LeftTupleNode) node).getSinkPropagator()
+                .getFirstLeftTupleSink()) {
+            //update the bit to the correct node position.
+            bit = nextNodePosMask(bit);
+        }
+
+        return new SegmentCursor(pmem, 
+                smems,
+                smemIndex,
+                bit,
+                tm,
+                sink, tupleSets);
+    }
+
+    public static SegmentCursor 
createSegmentCursorForQueryExecution(PathMemory pmem) {
+        if (pmem.getPathEndNode().getPathNodes()[0] == 
pmem.getSegmentMemories()[0].getTipNode()) {
+            // segment only has liaNode in it
+            // nothing is staged in the liaNode, so skip to next segment
+            return new SegmentCursor(
+                    pmem, 
+                    pmem.getSegmentMemories(), 
+                    1, 
+                    1L,  
+                    pmem.getSegmentMemories()[1].getNodeMemories()[0], 
+                    pmem.getSegmentMemories()[1].getRootNode(), 
+                    
pmem.getSegmentMemories()[1].getStagedLeftTuples().takeAll());
+        } else {
+            // lia is in shared segment, so point to next node
+            return new SegmentCursor(
+                    pmem, 
+                    pmem.getSegmentMemories(), 
+                    0, 
+                    2L,  
+                    pmem.getSegmentMemories()[0].getNodeMemories()[1], 
+                    
pmem.getPathEndNode().getPathNodes()[0].getSinkPropagator().getFirstLeftTupleSink(),
 
+                    
pmem.getSegmentMemories()[0].getStagedLeftTuples().takeAll());
+        }
+    }
+
+    public static SegmentCursor createSegmentCursor(PathMemory pmem) {
+        if (pmem.getSegmentMemories()[0].isOnlyLiaSegment()) {
+            return new SegmentCursor(
+                    pmem,
+                    pmem.getSegmentMemories(),
+                    1,
+                    1L,
+                    // segment only has liaNode in it
+                    // nothing is staged in the liaNode, so skip to next 
segment
+                    pmem.getSegmentMemories()[1].getNodeMemories()[0],
+                    pmem.getSegmentMemories()[1].getRootNode(), 
+                    pmem.getSegmentMemories()[1].getStagedLeftTuples());
+            
+        } else {
+            // lia is in shared segment, so point to next node
+            return new SegmentCursor(
+                    pmem, 
+                    pmem.getSegmentMemories(),
+                    0,
+                    2L,
+                    pmem.getSegmentMemories()[0].getNodeMemories()[1],
+                    
pmem.getSegmentMemories()[0].getRootNode().getSinkPropagator().getFirstLeftTupleSink(),
+                    pmem.getSegmentMemories()[0].getStagedLeftTuples());
+        }
+    }
+
+    private static String indent(int size) {
+        StringBuilder sbuilder = new StringBuilder();
+        for (int i = 0; i < size; i++) {
+            sbuilder.append("  ");
+        }
+
+        return sbuilder.toString();
+    }
+
+    private static int getOffset(NetworkNode node) {
+        LeftTupleNode lt;
+        int offset = 1;
+        if (NodeTypeEnums.isTerminalNode(node)) {
+            lt = ((TerminalNode) node).getLeftTupleSource();
+            offset++;
+        } else if (node.getType() == NodeTypeEnums.TupleToObjectNode) {
+            lt = ((TupleToObjectNode) node).getLeftTupleSource();
+        } else {
+            lt = (LeftTupleNode) node;
+        }
+        while (!NodeTypeEnums.isLeftInputAdapterNode(lt)) {
+            offset++;
+            lt = lt.getLeftTupleSource();
+        }
+
+        return offset;
+    }
+    
+}
\ No newline at end of file
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakAccumulateNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakAccumulateNodeMetric.java
index e23aa8690e..d5eac5e629 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakAccumulateNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakAccumulateNodeMetric.java
@@ -37,13 +37,13 @@ public class PhreakAccumulateNodeMetric extends 
PhreakAccumulateNode {
                        LeftTupleSink sink,
                        AccumulateMemory am,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(accNode);
 
-            super.doNode(accNode, sink, am, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(accNode, sink, am, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakBranchNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakBranchNodeMetric.java
index 12db5d3f16..0f21849bc6 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakBranchNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakBranchNodeMetric.java
@@ -36,18 +36,18 @@ public class PhreakBranchNodeMetric extends 
PhreakBranchNode {
 
     @Override
     public void doNode(ActivationsManager activationsManager,
+                       RuleExecutor executor,
                        ConditionalBranchNode branchNode,
                        ConditionalBranchMemory cbm,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
                        TupleSets stagedLeftTuples,
-                       RuleExecutor executor) {
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(branchNode);
 
-            super.doNode(activationsManager, branchNode, cbm, sink, 
srcLeftTuples, trgLeftTuples, stagedLeftTuples, executor);
+            super.doNode(activationsManager, executor, branchNode, cbm, sink, 
srcLeftTuples, stagedLeftTuples, trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakEvalNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakEvalNodeMetric.java
index 732b43a36a..234b3c9ece 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakEvalNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakEvalNodeMetric.java
@@ -37,13 +37,13 @@ public class PhreakEvalNodeMetric extends PhreakEvalNode {
                        EvalMemory em,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(evalNode);
 
-            super.doNode(evalNode, em, sink, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(evalNode, em, sink, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakExistsNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakExistsNodeMetric.java
index a4dd925f2e..6408f81480 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakExistsNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakExistsNodeMetric.java
@@ -37,13 +37,13 @@ public class PhreakExistsNodeMetric extends 
PhreakExistsNode {
                        LeftTupleSink sink,
                        BetaMemory bm,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(existsNode);
 
-            super.doNode(existsNode, sink, bm, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(existsNode, sink, bm, srcLeftTuples, 
stagedLeftTuples, trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakFromNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakFromNodeMetric.java
index e5895305fc..d6d5aaedfa 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakFromNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakFromNodeMetric.java
@@ -38,13 +38,13 @@ public class PhreakFromNodeMetric extends PhreakFromNode {
                        FromMemory fm,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(fromNode);
 
-            super.doNode(fromNode, fm, sink, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(fromNode, fm, sink, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakGroupByNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakGroupByNodeMetric.java
index f3b937aeb2..31fb2d479a 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakGroupByNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakGroupByNodeMetric.java
@@ -36,13 +36,13 @@ public class PhreakGroupByNodeMetric extends 
PhreakGroupByNode {
                         LeftTupleSink sink,
                         AccumulateNode.AccumulateMemory am,
                         TupleSets srcLeftTuples,
-                        TupleSets trgLeftTuples,
-                        TupleSets stagedLeftTuples) {
+                        TupleSets stagedLeftTuples,
+                        TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(accNode);
 
-            super.doNode(accNode, sink, am, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(accNode, sink, am, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakJoinNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakJoinNodeMetric.java
index 6dad21dd1f..0e071c04b6 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakJoinNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakJoinNodeMetric.java
@@ -37,12 +37,12 @@ public class PhreakJoinNodeMetric extends PhreakJoinNode {
                        LeftTupleSink sink,
                        BetaMemory bm,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
         try {
             MetricLogUtils.getInstance().startMetrics(joinNode);
 
-            super.doNode(joinNode, sink, bm, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(joinNode, sink, bm, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakNotNodeMetric.java 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakNotNodeMetric.java
index 0a4594f3a7..ca8a894d7b 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakNotNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakNotNodeMetric.java
@@ -37,13 +37,13 @@ public class PhreakNotNodeMetric extends PhreakNotNode {
                        LeftTupleSink sink,
                        BetaMemory bm,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(notNode);
 
-            super.doNode(notNode, sink, bm, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(notNode, sink, bm, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakQueryNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakQueryNodeMetric.java
index 578672627d..851d2b2d6a 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakQueryNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakQueryNodeMetric.java
@@ -33,17 +33,17 @@ public class PhreakQueryNodeMetric extends PhreakQueryNode {
     }
 
     @Override
-    public void doNode(QueryElementNode queryNode,
+    public void doNode(StackEntry stackEntry,
+                       QueryElementNode queryNode,
                        QueryElementNodeMemory qmem,
-                       StackEntry stackEntry,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(queryNode);
 
-            super.doNode(queryNode, qmem, stackEntry, srcLeftTuples, 
trgLeftTuples, stagedLeftTuples);
+            super.doNode(stackEntry, queryNode, qmem, srcLeftTuples, 
stagedLeftTuples, trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakReactiveFromNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakReactiveFromNodeMetric.java
index 76d1d62704..68e1007895 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakReactiveFromNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakReactiveFromNodeMetric.java
@@ -37,13 +37,13 @@ public class PhreakReactiveFromNodeMetric extends 
PhreakReactiveFromNode {
                        ReactiveFromMemory fm,
                        LeftTupleSink sink,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(fromNode);
 
-            super.doNode(fromNode, fm, sink, srcLeftTuples, trgLeftTuples, 
stagedLeftTuples);
+            super.doNode(fromNode, fm, sink, srcLeftTuples, stagedLeftTuples, 
trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakTimerNodeMetric.java
 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakTimerNodeMetric.java
index f86ec081ac..0beab0fe96 100644
--- 
a/drools-metric/src/main/java/org/drools/metric/phreak/PhreakTimerNodeMetric.java
+++ 
b/drools-metric/src/main/java/org/drools/metric/phreak/PhreakTimerNodeMetric.java
@@ -22,9 +22,8 @@ import org.drools.core.common.ActivationsManager;
 import org.drools.core.common.ReteEvaluator;
 import org.drools.core.common.TupleSets;
 import org.drools.core.phreak.PhreakTimerNode;
+import org.drools.core.phreak.SegmentCursor;
 import org.drools.core.reteoo.LeftTupleSink;
-import org.drools.core.reteoo.PathMemory;
-import org.drools.core.reteoo.SegmentMemory;
 import org.drools.core.reteoo.TimerNode;
 import org.drools.core.reteoo.TimerNode.TimerNodeMemory;
 import org.drools.metric.util.MetricLogUtils;
@@ -36,20 +35,19 @@ public class PhreakTimerNodeMetric extends PhreakTimerNode {
     }
 
     @Override
-    public void doNode(TimerNode timerNode,
+    public void doNode(ActivationsManager activationsManager,
+                       SegmentCursor sc,
+                       TimerNode timerNode,
                        TimerNodeMemory tm,
-                       PathMemory pmem,
-                       SegmentMemory smem,
                        LeftTupleSink sink,
-                       ActivationsManager activationsManager,
                        TupleSets srcLeftTuples,
-                       TupleSets trgLeftTuples,
-                       TupleSets stagedLeftTuples) {
+                       TupleSets stagedLeftTuples,
+                       TupleSets trgLeftTuples) {
 
         try {
             MetricLogUtils.getInstance().startMetrics(timerNode);
 
-            super.doNode(timerNode, tm, pmem, smem, sink, activationsManager, 
srcLeftTuples, trgLeftTuples, stagedLeftTuples);
+            super.doNode(activationsManager, sc, timerNode, tm, sink, 
srcLeftTuples, stagedLeftTuples, trgLeftTuples);
 
         } finally {
             MetricLogUtils.getInstance().logAndEndMetrics();
diff --git 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/phreak/Scenario.java
 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/phreak/Scenario.java
index 582fe8b9df..b8e12d6bb1 100644
--- 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/phreak/Scenario.java
+++ 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/phreak/Scenario.java
@@ -177,14 +177,14 @@ public class Scenario {
         
         if ( phreakNode == PhreakJoinNode.class ) {
             new PhreakJoinNode(wm).doNode( (JoinNode) betaNode, sinkNode,
-                                          bm, leftTuples, 
actualResultLeftTuples, previousResultTuples );
+                                          bm, leftTuples, 
previousResultTuples, actualResultLeftTuples );
             
         } else if ( phreakNode == PhreakNotNode.class ) {
             new PhreakNotNode(wm).doNode( (NotNode) betaNode, sinkNode,
-                                        bm, leftTuples, 
actualResultLeftTuples, previousResultTuples );            
+                                        bm, leftTuples, previousResultTuples, 
actualResultLeftTuples );            
         } else if ( phreakNode == PhreakExistsNode.class ) {
             new PhreakExistsNode(wm).doNode( (ExistsNode) betaNode, sinkNode,
-                                           bm, leftTuples, 
actualResultLeftTuples, previousResultTuples );            
+                                           bm, leftTuples, 
previousResultTuples, actualResultLeftTuples );            
         }
         
         if ( expectedResultBuilder != null ) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to