use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class PhreakQueryNode method doLeftUpdates.
public void doLeftUpdates(QueryElementNode queryNode, QueryElementNodeMemory qmem, InternalWorkingMemory wm, TupleSets<LeftTuple> srcLeftTuples) {
for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple != null; ) {
LeftTuple next = leftTuple.getStagedNext();
InternalFactHandle fh = (InternalFactHandle) leftTuple.getContextObject();
DroolsQuery dquery = (DroolsQuery) fh.getObject();
dquery.setParameters(queryNode.getActualArguments(leftTuple, wm));
SegmentMemory qsmem = qmem.getQuerySegmentMemory();
LeftInputAdapterNode lian = (LeftInputAdapterNode) qsmem.getRootNode();
LiaNodeMemory lmem = (LiaNodeMemory) qsmem.getNodeMemories().getFirst();
if (dquery.isOpen()) {
// there is only one, all other LTs are peers
LeftTuple childLeftTuple = fh.getFirstLeftTuple();
LeftInputAdapterNode.doUpdateObject(childLeftTuple, childLeftTuple.getPropagationContext(), wm, lian, false, lmem, qmem.getQuerySegmentMemory());
} else {
if (fh.getFirstLeftTuple() != null) {
// @TODO remove later (mdp)
throw new RuntimeException("defensive programming while testing");
}
LiaNodeMemory lm = (LiaNodeMemory) qmem.getQuerySegmentMemory().getNodeMemories().get(0);
LeftInputAdapterNode.doInsertObject(fh, leftTuple.getPropagationContext(), lian, wm, lm, false, dquery.isOpen());
}
leftTuple.clearStaged();
leftTuple = next;
}
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class RuleNetworkEvaluator method evalQueryNode.
private boolean evalQueryNode(PathMemory pmem, NetworkNode node, long bit, Memory nodeMem, SegmentMemory[] smems, int smemIndex, TupleSets<LeftTuple> trgTuples, InternalWorkingMemory wm, LinkedList<StackEntry> stack, TupleSets<LeftTuple> srcTuples, LeftTupleSinkNode sink, TupleSets<LeftTuple> stagedLeftTuples) {
QueryElementNodeMemory qmem = (QueryElementNodeMemory) nodeMem;
if (srcTuples.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());
}
// 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()) {
// only process the Query Node if there are src tuples
StackEntry stackEntry = new StackEntry(node, bit, sink, pmem, nodeMem, smems, smemIndex, trgTuples, true, true);
stack.add(stackEntry);
pQueryNode.doNode(qnode, (QueryElementNodeMemory) nodeMem, stackEntry, wm, srcTuples, trgTuples, stagedLeftTuples);
SegmentMemory qsmem = ((QueryElementNodeMemory) nodeMem).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;
// 0
SegmentMemory smem = smems[smemIndex];
LeftTupleNode liaNode = (LeftInputAdapterNode) 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
// 1
smem = smems[++smemIndex];
node = smem.getRootNode();
nodeMem = smem.getNodeMemories().getFirst();
bit = 1;
} else {
// lia is in shared segment, so point to next node
node = liaNode.getSinkPropagator().getFirstLeftTupleSink();
// skip the liaNode memory
nodeMem = smem.getNodeMemories().getFirst().getNext();
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);
}
return true;
} else {
return false;
}
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class RuleNetworkEvaluator method doRiaNode.
private void doRiaNode(InternalAgenda agenda, PathMemory pmem, TupleSets<LeftTuple> srcTuples, BetaNode betaNode, LeftTupleSinkNode sink, SegmentMemory[] smems, int smemIndex, Memory nodeMem, BetaMemory bm, LinkedList<StackEntry> stack, RuleExecutor executor) {
RiaPathMemory pathMem = bm.getRiaRuleMemory();
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];
}
// Resume the node after the riaNode 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);
stack.add(stackEntry);
if (log.isTraceEnabled()) {
int offset = getOffset(betaNode);
log.trace("{} RiaQueue {} {}", indent(offset), betaNode.toString(), srcTuples.toStringSizes());
}
TupleSets<LeftTuple> subLts = subSmem.getStagedLeftTuples().takeAll();
// node is first in the segment, so bit is 1
innerEval(pathMem, subSmem.getRootNode(), 1, subSmem.getNodeMemories().getFirst(), subnetworkSmems, subSmem.getPos(), subLts, agenda, stack, true, executor);
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class RuleNetworkEvaluator method evaluateNetwork.
public void evaluateNetwork(PathMemory pmem, RuleExecutor executor, InternalAgenda agenda) {
SegmentMemory[] smems = pmem.getSegmentMemories();
int smemIndex = 0;
// 0
SegmentMemory smem = smems[smemIndex];
LeftInputAdapterNode liaNode = (LeftInputAdapterNode) smem.getRootNode();
LinkedList<StackEntry> stack = new LinkedList<StackEntry>();
NetworkNode node;
Memory nodeMem;
long bit = 1;
if (liaNode == smem.getTipNode()) {
// segment only has liaNode in it
// nothing is staged in the liaNode, so skip to next segment
// 1
smem = smems[++smemIndex];
node = smem.getRootNode();
nodeMem = smem.getNodeMemories().getFirst();
} else {
// lia is in shared segment, so point to next node
bit = 2;
node = liaNode.getSinkPropagator().getFirstLeftTupleSink();
// skip the liaNode memory
nodeMem = smem.getNodeMemories().getFirst().getNext();
}
TupleSets<LeftTuple> srcTuples = smem.getStagedLeftTuples();
if (log.isTraceEnabled()) {
log.trace("Rule[name={}] segments={} {}", ((TerminalNode) pmem.getPathEndNode()).getRule().getName(), smems.length, srcTuples.toStringSizes());
}
outerEval(pmem, node, bit, nodeMem, smems, smemIndex, srcTuples, agenda, stack, true, executor);
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class RuleNetworkEvaluator method innerEval.
public void innerEval(PathMemory pmem, NetworkNode node, long bit, Memory nodeMem, SegmentMemory[] smems, int smemIndex, TupleSets<LeftTuple> trgTuples, InternalAgenda agenda, LinkedList<StackEntry> stack, boolean processRian, RuleExecutor executor) {
TupleSets<LeftTuple> srcTuples;
SegmentMemory smem = smems[smemIndex];
TupleSets<LeftTuple> stagedLeftTuples = null;
while (true) {
// previous target, is now the source
srcTuples = trgTuples;
if (log.isTraceEnabled()) {
int offset = getOffset(node);
log.trace("{} {} {} {}", indent(offset), ++cycle, node.toString(), srcTuples.toStringSizes());
}
boolean emptySrcTuples = srcTuples.isEmpty();
if (!(NodeTypeEnums.isBetaNode(node) && ((BetaNode) node).isRightInputIsRiaNode())) {
// The engine cannot skip a ria node, as the dirty might be several levels deep
if (emptySrcTuples && smem.getDirtyNodeMask() == 0) {
// 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);
}
// and may not yet be initialized
if (smem.isEmpty() && !NodeTypeEnums.isTerminalNode(smem.getTipNode())) {
SegmentUtilities.createChildSegments(agenda.getWorkingMemory(), smem, ((LeftTupleSource) smem.getTipNode()).getSinkPropagator());
}
smem = smems[i];
bit = 1;
srcTuples = smem.getStagedLeftTuples().takeAll();
emptySrcTuples = srcTuples.isEmpty();
node = smem.getRootNode();
nodeMem = smem.getNodeMemories().getFirst();
if (!emptySrcTuples || smem.getDirtyNodeMask() != 0 || (NodeTypeEnums.isBetaNode(node) && ((BetaNode) node).isRightInputIsRiaNode())) {
// break if dirty or if we reach a subnetwork. It must break for subnetworks, so they can be searched.
foundDirty = true;
smemIndex = i;
break;
}
}
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());
}
}
long dirtyMask = smem.getDirtyNodeMask();
if (emptySrcTuples) {
while ((dirtyMask & bit) == 0 && node != smem.getTipNode() && !(NodeTypeEnums.isBetaNode(node) && ((BetaNode) node).isRightInputIsRiaNode())) {
if (log.isTraceEnabled()) {
int offset = getOffset(node);
log.trace("{} Skip Node {}", indent(offset), node);
}
// shift to check the next node
bit = bit << 1;
node = ((LeftTupleSource) node).getSinkPropagator().getFirstLeftTupleSink();
nodeMem = nodeMem.getNext();
}
}
boolean terminalNode = true;
switch(node.getType()) {
case NodeTypeEnums.RuleTerminalNode:
pRtNode.doNode((TerminalNode) node, agenda, srcTuples, executor);
break;
case NodeTypeEnums.QueryTerminalNode:
pQtNode.doNode((QueryTerminalNode) node, agenda, srcTuples, stack);
break;
case NodeTypeEnums.RightInputAdaterNode:
doRiaNode2(agenda.getWorkingMemory(), srcTuples, (RightInputAdapterNode) node);
break;
default:
terminalNode = false;
}
if (terminalNode) {
break;
}
stagedLeftTuples = getTargetStagedLeftTuples(node, agenda.getWorkingMemory(), smem);
LeftTupleSinkNode sink = ((LeftTupleSource) node).getSinkPropagator().getFirstLeftTupleSink();
trgTuples = evalNode(pmem, node, bit, nodeMem, smems, smemIndex, agenda, stack, processRian, executor, srcTuples, smem, stagedLeftTuples, sink);
if (trgTuples == null) {
// Queries exists and has been placed StackEntry, and there are no current trgTuples to process
break;
}
if (node != smem.getTipNode()) {
// get next node and node memory in the segment
node = sink;
nodeMem = nodeMem.getNext();
bit = bit << 1;
} else {
// Reached end of segment, start on new segment.
// must put back all the LTs
smem.getFirst().getStagedLeftTuples().addAll(stagedLeftTuples);
// end of SegmentMemory, so we know that stagedLeftTuples is not null
SegmentPropagator.propagate(smem, trgTuples, agenda.getWorkingMemory());
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().getFirst();
}
// make sure it's reset, so ria nodes are processed
processRian = true;
}
if (stagedLeftTuples != null && !stagedLeftTuples.isEmpty()) {
// must put back all the LTs
smem.getFirst().getStagedLeftTuples().addAll(stagedLeftTuples);
}
}
Aggregations