use of org.drools.core.reteoo.PathMemory in project drools by kiegroup.
the class SegmentUtilities method updateRiaAndTerminalMemory.
/**
* This adds the segment memory to the terminal node or ria node's list of memories.
* In the case of the terminal node this allows it to know that all segments from
* the tip to root are linked.
* In the case of the ria node its all the segments up to the start of the subnetwork.
* This is because the rianode only cares if all of it's segments are linked, then
* it sets the bit of node it is the right input for.
*/
private static int updateRiaAndTerminalMemory(LeftTupleSource lt, LeftTupleSource originalLt, SegmentMemory smem, InternalWorkingMemory wm, boolean fromPrototype, int nodeTypesInSegment) {
nodeTypesInSegment = checkSegmentBoundary(lt, wm, nodeTypesInSegment);
for (LeftTupleSink sink : lt.getSinkPropagator().getSinks()) {
if (NodeTypeEnums.isLeftTupleSource(sink)) {
nodeTypesInSegment = updateRiaAndTerminalMemory((LeftTupleSource) sink, originalLt, smem, wm, fromPrototype, nodeTypesInSegment);
} else if (sink.getType() == NodeTypeEnums.RightInputAdaterNode) {
// Even though we don't add the pmem and smem together, all pmem's for all pathend nodes must be initialized
RiaNodeMemory riaMem = (RiaNodeMemory) wm.getNodeMemory((MemoryFactory) sink);
// Only add the RIANode, if the LeftTupleSource is part of the RIANode subnetwork
if (inSubNetwork((RightInputAdapterNode) sink, originalLt)) {
PathMemory pmem = riaMem.getRiaPathMemory();
smem.addPathMemory(pmem);
if (smem.getPos() < pmem.getSegmentMemories().length) {
pmem.setSegmentMemory(smem.getPos(), smem);
}
if (fromPrototype) {
ObjectSink[] nodes = ((RightInputAdapterNode) sink).getObjectSinkPropagator().getSinks();
for (ObjectSink node : nodes) {
// check if the SegmentMemory has been already created by the BetaNode and if so avoid to build it twice
if (NodeTypeEnums.isLeftTupleSource(node) && wm.getNodeMemory((MemoryFactory) node).getSegmentMemory() == null) {
restoreSegmentFromPrototype(wm, (LeftTupleSource) node, nodeTypesInSegment);
}
}
} else if ((pmem.getAllLinkedMaskTest() & (1L << pmem.getSegmentMemories().length)) == 0) {
// must eagerly initialize child segment memories
ObjectSink[] nodes = ((RightInputAdapterNode) sink).getObjectSinkPropagator().getSinks();
for (ObjectSink node : nodes) {
if (NodeTypeEnums.isLeftTupleSource(node)) {
createSegmentMemory((LeftTupleSource) node, wm);
}
}
}
}
} else if (NodeTypeEnums.isTerminalNode(sink)) {
PathMemory pmem = (PathMemory) wm.getNodeMemory((MemoryFactory) sink);
smem.addPathMemory(pmem);
// with the former one and in this case doesn't have to be added to the the path memory
if (smem.getPos() < pmem.getSegmentMemories().length) {
pmem.setSegmentMemory(smem.getPos(), smem);
if (smem.isSegmentLinked()) {
// not's can cause segments to be linked, and the rules need to be notified for evaluation
smem.notifyRuleLinkSegment(wm);
}
checkEagerSegmentCreation(sink.getLeftTupleSource(), wm, nodeTypesInSegment);
}
}
}
return nodeTypesInSegment;
}
use of org.drools.core.reteoo.PathMemory 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.PathMemory 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());
}
}
}
}
use of org.drools.core.reteoo.PathMemory in project drools by kiegroup.
the class AddRemoveRule method removeRule.
/**
* This method is called before the rule nodes are removed from the network.
* For remove tuples are processed before the segments and pmems have been adjusted
*/
public static void removeRule(TerminalNode tn, InternalWorkingMemory[] wms, InternalKnowledgeBase kBase) {
if (log.isTraceEnabled()) {
log.trace("Removing Rule {}", tn.getRule().getName());
}
boolean hasProtos = kBase.hasSegmentPrototypes();
boolean hasWms = wms.length > 0;
if (!hasProtos && !hasWms) {
return;
}
RuleImpl rule = tn.getRule();
LeftTupleNode firstSplit = getNetworkSplitPoint(tn);
PathEndNodes pathEndNodes = getPathEndNodes(kBase, firstSplit, tn, rule, hasProtos, hasWms);
for (InternalWorkingMemory wm : wms) {
wm.flushPropagations();
PathEndNodeMemories tnms = getPathEndMemories(wm, pathEndNodes);
if (!tnms.subjectPmems.isEmpty()) {
if (NodeTypeEnums.LeftInputAdapterNode == firstSplit.getType() && firstSplit.getAssociationsSize() == 1) {
if (tnms.subjectPmem != null) {
flushStagedTuples(firstSplit, tnms.subjectPmem, wm);
}
processLeftTuples(firstSplit, wm, false, tn.getRule());
removeNewPaths(wm, tnms.subjectPmems);
} else {
flushStagedTuples(tn, tnms.subjectPmem, pathEndNodes, wm);
processLeftTuples(firstSplit, wm, false, tn.getRule());
removeNewPaths(wm, tnms.subjectPmems);
Map<PathMemory, SegmentMemory[]> prevSmemsLookup = reInitPathMemories(tnms.otherPmems, tn);
// must collect all visited SegmentMemories, for link notification
Set<SegmentMemory> smemsToNotify = handleExistingPaths(tn, prevSmemsLookup, tnms.otherPmems, wm, ExistingPathStrategy.REMOVE_STRATEGY);
notifySegments(smemsToNotify, wm);
}
}
if (tnms.subjectPmem != null && tnms.subjectPmem.isInitialized() && tnms.subjectPmem.getRuleAgendaItem().isQueued()) {
// SubjectPmem can be null, if it was never initialized
tnms.subjectPmem.getRuleAgendaItem().dequeue();
}
}
}
use of org.drools.core.reteoo.PathMemory in project drools by kiegroup.
the class AddRemoveRule method reInitPathMemories.
private static Map<PathMemory, SegmentMemory[]> reInitPathMemories(List<PathMemory> pathMems, TerminalNode removingTN) {
Map<PathMemory, SegmentMemory[]> previousSmems = new HashMap<PathMemory, SegmentMemory[]>();
for (PathMemory pmem : pathMems) {
// Re initialise all the PathMemories
previousSmems.put(pmem, pmem.getSegmentMemories());
LeftTupleSource startRianLts = null;
if (!NodeTypeEnums.isTerminalNode(pmem.getPathEndNode())) {
RightInputAdapterNode rian = (RightInputAdapterNode) pmem.getPathEndNode();
startRianLts = rian.getStartTupleSource();
}
PathEndNode pathEndNode = pmem.getPathEndNode();
// re-initialise the PathMemory
pathEndNode.resetPathMemSpec(removingTN);
AbstractTerminalNode.initPathMemory(pathEndNode, pmem);
}
return previousSmems;
}
Aggregations