use of org.drools.core.reteoo.PathMemory in project drools by kiegroup.
the class PhreakQueryTerminalNode method checkAndTriggerQueryReevaluation.
public static void checkAndTriggerQueryReevaluation(InternalAgenda agenda, LinkedList<StackEntry> stack, Tuple rootEntry, DroolsQuery dquery) {
StackEntry stackEntry = dquery.getStackEntry();
if (!isAdded(stack, stackEntry)) {
// Ignore unless stackEntry is not added to stack
// node must be marked as dirty
((QueryElementNodeMemory) stackEntry.getNodeMem()).setNodeDirtyWithoutNotify();
if (stackEntry.getRmem().getPathEndNode().getPathNodes()[0] == ((LeftTupleSink) rootEntry.getTupleSink()).getLeftTupleSource()) {
// query is recursive, so just re-add the stack entry to the current stack. This happens for reactive queries, triggered by a beta node right input
stack.add(stackEntry);
} else {
// parents is anther rule/query need to notify for agenda to schedule. query is reactive, triggered by right input,
List<PathMemory> pmems = dquery.getRuleMemories();
if (pmems != null) {
// reactivity comes form within the query, so need to notify parent rules to evaluate the results
for (int i = 0, length = pmems.size(); i < length; i++) {
PathMemory pmem = pmems.get(i);
// method already ignores is rule is activated and on agenda
pmem.doLinkRule(agenda);
}
}
}
}
}
use of org.drools.core.reteoo.PathMemory 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.PathMemory 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.PathMemory in project drools by kiegroup.
the class SegmentPropagator method processPeers.
private static void processPeers(SegmentMemory sourceSegment, TupleSets<LeftTuple> leftTuples, InternalWorkingMemory wm) {
SegmentMemory firstSmem = sourceSegment.getFirst();
// Process Deletes
processPeerDeletes(leftTuples, leftTuples.getDeleteFirst(), firstSmem, wm);
processPeerDeletes(leftTuples, leftTuples.getNormalizedDeleteFirst(), firstSmem, wm);
// Process Updates
for (LeftTuple leftTuple = leftTuples.getUpdateFirst(); leftTuple != null; leftTuple = leftTuple.getStagedNext()) {
SegmentMemory smem = firstSmem.getNext();
if (smem != null) {
for (LeftTuple peer = leftTuple.getPeer(); peer != null; peer = peer.getPeer()) {
// only stage, if not already staged, if insert, leave as insert
if (peer.getStagedType() == LeftTuple.NONE) {
peer.setPropagationContext(leftTuple.getPropagationContext());
smem.getStagedLeftTuples().addUpdate(peer);
}
smem = smem.getNext();
}
}
}
// Process Inserts
for (LeftTuple leftTuple = leftTuples.getInsertFirst(); leftTuple != null; leftTuple = leftTuple.getStagedNext()) {
SegmentMemory smem = firstSmem.getNext();
if (smem != null) {
LeftTuple peer = leftTuple;
for (; smem != null; smem = smem.getNext()) {
if (peer.getPeer() != null) {
// if the tuple already has a peer avoid to create a new one ...
peer = peer.getPeer();
peer.setPropagationContext(leftTuple.getPropagationContext());
// ... and update the staged LeftTupleSets according to its current staged state
PhreakJoinNode.updateChildLeftTuple(peer, smem.getStagedLeftTuples(), smem.getStagedLeftTuples());
} else {
peer = ((LeftTupleSink) smem.getRootNode()).createPeer(peer);
smem.getStagedLeftTuples().addInsert(peer);
if (smem.hasDataDrivenPathMemories()) {
for (PathMemory dataDrivenPmem : smem.getDataDrivenPathMemories()) {
// on insert only totally linked pmems need to be flushed
if (dataDrivenPmem.isRuleLinked()) {
forceFlushLeftTuple(dataDrivenPmem, smem, wm, smem.getStagedLeftTuples());
break;
}
}
}
}
}
}
}
firstSmem.getStagedLeftTuples().addAll(leftTuples);
leftTuples.resetAll();
}
use of org.drools.core.reteoo.PathMemory in project drools by kiegroup.
the class SegmentUtilities method createSegmentMemory.
public static SegmentMemory createSegmentMemory(LeftTupleSource tupleSource, Memory mem, InternalWorkingMemory wm) {
// find segment root
while (!SegmentUtilities.isRootNode(tupleSource, null)) {
tupleSource = tupleSource.getLeftTupleSource();
}
LeftTupleSource segmentRoot = tupleSource;
int nodeTypesInSegment = 0;
SegmentMemory smem = restoreSegmentFromPrototype(wm, segmentRoot, nodeTypesInSegment);
if (smem != null) {
if (NodeTypeEnums.isBetaNode(segmentRoot) && ((BetaNode) segmentRoot).isRightInputIsRiaNode()) {
createRiaSegmentMemory((BetaNode) segmentRoot, wm);
}
return smem;
}
smem = new SegmentMemory(segmentRoot);
// Iterate all nodes on the same segment, assigning their position as a bit mask value
// allLinkedTestMask is the resulting mask used to test if all nodes are linked in
long nodePosMask = 1;
long allLinkedTestMask = 0;
// nodes after a branch CE can notify, but they cannot impact linking
boolean updateNodeBit = true;
while (true) {
nodeTypesInSegment = updateNodeTypesMask(tupleSource, nodeTypesInSegment);
if (NodeTypeEnums.isBetaNode(tupleSource)) {
allLinkedTestMask = processBetaNode((BetaNode) tupleSource, wm, smem, nodePosMask, allLinkedTestMask, updateNodeBit);
} else {
switch(tupleSource.getType()) {
case NodeTypeEnums.LeftInputAdapterNode:
allLinkedTestMask = processLiaNode((LeftInputAdapterNode) tupleSource, wm, smem, nodePosMask, allLinkedTestMask);
break;
case NodeTypeEnums.EvalConditionNode:
processEvalNode((EvalConditionNode) tupleSource, wm, smem);
break;
case NodeTypeEnums.ConditionalBranchNode:
updateNodeBit = processBranchNode((ConditionalBranchNode) tupleSource, wm, smem);
break;
case NodeTypeEnums.FromNode:
processFromNode((FromNode) tupleSource, wm, smem);
break;
case NodeTypeEnums.ReactiveFromNode:
processReactiveFromNode((MemoryFactory) tupleSource, wm, smem, nodePosMask);
break;
case NodeTypeEnums.TimerConditionNode:
processTimerNode((TimerNode) tupleSource, wm, smem, nodePosMask);
break;
case NodeTypeEnums.QueryElementNode:
updateNodeBit = processQueryNode((QueryElementNode) tupleSource, wm, segmentRoot, smem, nodePosMask);
break;
}
}
nodePosMask = nodePosMask << 1;
if (tupleSource.getSinkPropagator().size() == 1) {
LeftTupleSinkNode sink = tupleSource.getSinkPropagator().getFirstLeftTupleSink();
if (NodeTypeEnums.isLeftTupleSource(sink)) {
tupleSource = (LeftTupleSource) sink;
} else {
// rtn or rian
// While not technically in a segment, we want to be able to iterate easily from the last node memory to the ria/rtn memory
// we don't use createNodeMemory, as these may already have been created by, but not added, by the method updateRiaAndTerminalMemory
Memory memory = wm.getNodeMemory((MemoryFactory) sink);
if (sink.getType() == NodeTypeEnums.RightInputAdaterNode) {
PathMemory riaPmem = ((RiaNodeMemory) memory).getRiaPathMemory();
smem.getNodeMemories().add(riaPmem);
RightInputAdapterNode rian = (RightInputAdapterNode) sink;
ObjectSink[] nodes = rian.getObjectSinkPropagator().getSinks();
for (ObjectSink node : nodes) {
if (NodeTypeEnums.isLeftTupleSource(node)) {
createSegmentMemory((LeftTupleSource) node, wm);
}
}
} else if (NodeTypeEnums.isTerminalNode(sink)) {
smem.getNodeMemories().add(memory);
}
memory.setSegmentMemory(smem);
smem.setTipNode(sink);
break;
}
} else {
// not in same segment
smem.setTipNode(tupleSource);
break;
}
}
smem.setAllLinkedMaskTest(allLinkedTestMask);
// iterate to find root and determine the SegmentNodes position in the RuleSegment
LeftTupleSource pathRoot = segmentRoot;
int ruleSegmentPosMask = 1;
int counter = 0;
while (pathRoot.getType() != NodeTypeEnums.LeftInputAdapterNode) {
LeftTupleSource leftTupleSource = pathRoot.getLeftTupleSource();
if (SegmentUtilities.isNonTerminalTipNode(leftTupleSource, null)) {
// for each new found segment, increase the mask bit position
ruleSegmentPosMask = ruleSegmentPosMask << 1;
counter++;
}
pathRoot = leftTupleSource;
}
smem.setSegmentPosMaskBit(ruleSegmentPosMask);
smem.setPos(counter);
nodeTypesInSegment = updateRiaAndTerminalMemory(tupleSource, tupleSource, smem, wm, false, nodeTypesInSegment);
((KnowledgeBaseImpl) wm.getKnowledgeBase()).registerSegmentPrototype(segmentRoot, smem);
return smem;
}
Aggregations