Search in sources :

Example 1 with LeftTupleSinkNode

use of org.drools.core.reteoo.LeftTupleSinkNode 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);
    }
}
Also used : LeftTupleSource(org.drools.core.reteoo.LeftTupleSource) SegmentMemory(org.drools.core.reteoo.SegmentMemory) BetaNode(org.drools.core.reteoo.BetaNode) LeftTupleSinkNode(org.drools.core.reteoo.LeftTupleSinkNode) LeftTuple(org.drools.core.reteoo.LeftTuple)

Example 2 with LeftTupleSinkNode

use of org.drools.core.reteoo.LeftTupleSinkNode in project drools by kiegroup.

the class SegmentUtilities method isNonTerminalTipNode.

public static boolean isNonTerminalTipNode(LeftTupleNode node, TerminalNode removingTN) {
    LeftTupleSinkPropagator sinkPropagator = node.getSinkPropagator();
    if (removingTN == null) {
        return sinkPropagator.size() > 1;
    }
    if (sinkPropagator.size() == 1) {
        return false;
    }
    // we know the sink size is creater than 1 and that there is a removingRule that needs to be ignored.
    int count = 0;
    for (LeftTupleSinkNode sink = sinkPropagator.getFirstLeftTupleSink(); sink != null; sink = sink.getNextLeftTupleSinkNode()) {
        if (sinkNotExclusivelyAssociatedWithTerminal(removingTN, sink)) {
            count++;
            if (count > 1) {
                // There is more than one sink that is not for the removing rule
                return true;
            }
        }
    }
    return false;
}
Also used : LeftTupleSinkNode(org.drools.core.reteoo.LeftTupleSinkNode) LeftTupleSinkPropagator(org.drools.core.reteoo.LeftTupleSinkPropagator) QueryNameConstraint(org.drools.core.rule.constraint.QueryNameConstraint)

Example 3 with LeftTupleSinkNode

use of org.drools.core.reteoo.LeftTupleSinkNode 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;
}
Also used : SegmentMemory(org.drools.core.reteoo.SegmentMemory) BetaNode(org.drools.core.reteoo.BetaNode) Memory(org.drools.core.common.Memory) TimerNodeMemory(org.drools.core.reteoo.TimerNode.TimerNodeMemory) LiaNodeMemory(org.drools.core.reteoo.LeftInputAdapterNode.LiaNodeMemory) BetaMemory(org.drools.core.reteoo.BetaMemory) EvalMemory(org.drools.core.reteoo.EvalConditionNode.EvalMemory) QueryElementNodeMemory(org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory) SegmentMemory(org.drools.core.reteoo.SegmentMemory) PathMemory(org.drools.core.reteoo.PathMemory) InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) ConditionalBranchMemory(org.drools.core.reteoo.ConditionalBranchNode.ConditionalBranchMemory) RiaNodeMemory(org.drools.core.reteoo.RightInputAdapterNode.RiaNodeMemory) AccumulateMemory(org.drools.core.reteoo.AccumulateNode.AccumulateMemory) QueryElementNode(org.drools.core.reteoo.QueryElementNode) ConditionalBranchNode(org.drools.core.reteoo.ConditionalBranchNode) KnowledgeBaseImpl(org.drools.core.impl.KnowledgeBaseImpl) QueryNameConstraint(org.drools.core.rule.constraint.QueryNameConstraint) LeftTupleSource(org.drools.core.reteoo.LeftTupleSource) RiaNodeMemory(org.drools.core.reteoo.RightInputAdapterNode.RiaNodeMemory) LeftTupleSinkNode(org.drools.core.reteoo.LeftTupleSinkNode) ObjectSink(org.drools.core.reteoo.ObjectSink) RightInputAdapterNode(org.drools.core.reteoo.RightInputAdapterNode) LeftInputAdapterNode(org.drools.core.reteoo.LeftInputAdapterNode) PathMemory(org.drools.core.reteoo.PathMemory)

Example 4 with LeftTupleSinkNode

use of org.drools.core.reteoo.LeftTupleSinkNode 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);
    }
}
Also used : SegmentMemory(org.drools.core.reteoo.SegmentMemory) LeftTupleSinkNode(org.drools.core.reteoo.LeftTupleSinkNode)

Example 5 with LeftTupleSinkNode

use of org.drools.core.reteoo.LeftTupleSinkNode in project drools by kiegroup.

the class AddRemoveRule method visitChild.

private static void visitChild(LeftTuple lt, boolean insert, InternalWorkingMemory wm, Rule rule) {
    LeftTuple prevLt = null;
    LeftTupleSinkNode sink = lt.getTupleSink();
    for (; sink != null; sink = sink.getNextLeftTupleSinkNode()) {
        if (lt != null) {
            if (lt.getTupleSink().isAssociatedWith(rule)) {
                if (lt.getTupleSink().getAssociationsSize() > 1) {
                    if (lt.getFirstChild() != null) {
                        for (LeftTuple child = lt.getFirstChild(); child != null; child = child.getHandleNext()) {
                            visitChild(child, insert, wm, rule);
                        }
                    } else if (lt.getTupleSink().getType() == NodeTypeEnums.RightInputAdaterNode) {
                        insertPeerRightTuple(lt, wm, rule, insert);
                    }
                } else if (!insert) {
                    iterateLeftTuple(lt, wm);
                    LeftTuple lt2 = null;
                    for (LeftTuple peerLt = lt.getPeer(); peerLt != null && peerLt.getTupleSink().isAssociatedWith(rule) && peerLt.getTupleSink().getAssociationsSize() == 1; peerLt = peerLt.getPeer()) {
                        iterateLeftTuple(peerLt, wm);
                        lt2 = peerLt;
                    }
                    // this sink is not shared and is associated with the rule being removed delete it's children
                    deleteLeftTuple(lt, lt2, prevLt);
                    // only one rule is deleted at a time, we know there are no more peers to delete so break.
                    break;
                }
            }
            prevLt = lt;
            lt = lt.getPeer();
        } else {
            // there is a sink without a peer LT, so create the peer LT
            prevLt = insertPeerLeftTuple(prevLt, sink, wm);
        }
    }
}
Also used : LeftTupleSinkNode(org.drools.core.reteoo.LeftTupleSinkNode) LeftTuple(org.drools.core.reteoo.LeftTuple)

Aggregations

LeftTupleSinkNode (org.drools.core.reteoo.LeftTupleSinkNode)7 LeftTuple (org.drools.core.reteoo.LeftTuple)4 SegmentMemory (org.drools.core.reteoo.SegmentMemory)4 InternalWorkingMemory (org.drools.core.common.InternalWorkingMemory)3 Memory (org.drools.core.common.Memory)2 AccumulateMemory (org.drools.core.reteoo.AccumulateNode.AccumulateMemory)2 BetaMemory (org.drools.core.reteoo.BetaMemory)2 BetaNode (org.drools.core.reteoo.BetaNode)2 ConditionalBranchMemory (org.drools.core.reteoo.ConditionalBranchNode.ConditionalBranchMemory)2 EvalMemory (org.drools.core.reteoo.EvalConditionNode.EvalMemory)2 LeftTupleSource (org.drools.core.reteoo.LeftTupleSource)2 PathMemory (org.drools.core.reteoo.PathMemory)2 QueryElementNodeMemory (org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory)2 TimerNodeMemory (org.drools.core.reteoo.TimerNode.TimerNodeMemory)2 QueryNameConstraint (org.drools.core.rule.constraint.QueryNameConstraint)2 NetworkNode (org.drools.core.common.NetworkNode)1 KnowledgeBaseImpl (org.drools.core.impl.KnowledgeBaseImpl)1 PhreakFromNode.deleteChildLeftTuple (org.drools.core.phreak.PhreakFromNode.deleteChildLeftTuple)1 ConditionalBranchNode (org.drools.core.reteoo.ConditionalBranchNode)1 FromMemory (org.drools.core.reteoo.FromNode.FromMemory)1