use of org.drools.core.reteoo.SegmentMemory 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;
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class SegmentUtilities method createChildSegments.
public static void createChildSegments(final InternalWorkingMemory wm, SegmentMemory smem, LeftTupleSinkPropagator sinkProp) {
if (!smem.isEmpty()) {
// this can happen when multiple threads are trying to initialize the segment
return;
}
for (LeftTupleSinkNode sink = sinkProp.getFirstLeftTupleSink(); sink != null; sink = sink.getNextLeftTupleSinkNode()) {
SegmentMemory childSmem = createChildSegment(wm, sink);
childSmem.setPos(smem.getPos() + 1);
smem.add(childSmem);
}
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class SegmentUtilities method createChildSegmentForTerminalNode.
public static SegmentMemory createChildSegmentForTerminalNode(LeftTupleNode node, Memory memory) {
// rtns or riatns don't need a queue
SegmentMemory childSmem = new SegmentMemory(node);
PathMemory pmem = NodeTypeEnums.isTerminalNode(node) ? (PathMemory) memory : ((RiaNodeMemory) memory).getRiaPathMemory();
childSmem.setPos(pmem.getSegmentMemories().length - 1);
pmem.setSegmentMemory(childSmem.getPos(), childSmem);
pmem.setSegmentMemory(childSmem);
childSmem.addPathMemory(pmem);
childSmem.setTipNode(node);
return childSmem;
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class AddRemoveRule method splitNodeMemories.
private static void splitNodeMemories(SegmentMemory sm1, SegmentMemory sm2, int pos) {
LinkedList<Memory> smNodeMemories1 = sm1.getNodeMemories();
LinkedList<Memory> smNodeMemories2 = sm2.getNodeMemories();
Memory mem = smNodeMemories1.getFirst();
int nodePosMask = 1;
for (int i = 0, length = smNodeMemories1.size(); i < length; i++) {
Memory next = mem.getNext();
if (i > pos) {
smNodeMemories1.remove(mem);
smNodeMemories2.add(mem);
mem.setSegmentMemory(sm2);
// correct the NodePosMaskBit
if (mem instanceof SegmentNodeMemory) {
((SegmentNodeMemory) mem).setNodePosMaskBit(nodePosMask);
}
nodePosMask = nodePosMask << 1;
}
mem = next;
}
}
use of org.drools.core.reteoo.SegmentMemory in project drools by kiegroup.
the class AddRemoveRule method flushStagedTuples.
private static void flushStagedTuples(TerminalNode tn, PathMemory pmem, PathEndNodes pathEndNodes, InternalWorkingMemory wm) {
// first flush the subject rule, then flush any staging lists that are part of a merge
if (pmem.isInitialized()) {
new RuleNetworkEvaluator().evaluateNetwork(pmem, pmem.getRuleAgendaItem().getRuleExecutor(), wm);
}
// With the removing rules being flushed, we need to check any splits that will be merged, to see if they need flushing
// Beware that flushing a higher up node, might again cause lower nodes to have more staged items. So track flushed items
// incase they need to be reflushed
List<Flushed> flushed = new ArrayList<Flushed>();
for (LeftTupleNode node : pathEndNodes.subjectSplits) {
if (!isSplit(node, tn)) {
// check if the split is there even without the processed rule
Memory mem = wm.getNodeMemories().peekNodeMemory(node);
if (mem != null) {
SegmentMemory smem = mem.getSegmentMemory();
if (!smem.isEmpty()) {
for (SegmentMemory childSmem = smem.getFirst(); childSmem != null; childSmem = childSmem.getNext()) {
if (!childSmem.getStagedLeftTuples().isEmpty()) {
PathMemory childPmem = childSmem.getPathMemories().get(0);
flushed.add(new Flushed(childSmem, childPmem));
forceFlushLeftTuple(childPmem, childSmem, wm, childSmem.getStagedLeftTuples().takeAll());
}
}
}
}
}
}
// need to ensure that there is one full iteration, without any flushing. To avoid one flush causing populat of another already flushed segment
int flushCount = 1;
while (!flushed.isEmpty() && flushCount != 0) {
flushCount = 0;
for (Flushed path : flushed) {
if (!path.segmentMemory.getStagedLeftTuples().isEmpty()) {
flushCount++;
forceFlushLeftTuple(pmem, path.segmentMemory, wm, path.segmentMemory.getStagedLeftTuples().takeAll());
}
}
}
}
Aggregations