Search in sources :

Example 1 with PathMemory

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);
                }
            }
        }
    }
}
Also used : QueryElementNodeMemory(org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory) PathMemory(org.drools.core.reteoo.PathMemory)

Example 2 with PathMemory

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;
    }
}
Also used : SegmentMemory(org.drools.core.reteoo.SegmentMemory) QueryElementNode(org.drools.core.reteoo.QueryElementNode) QueryElementNodeMemory(org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory) LeftTupleNode(org.drools.core.reteoo.LeftTupleNode) PathMemory(org.drools.core.reteoo.PathMemory) RiaPathMemory(org.drools.core.reteoo.RiaPathMemory) LeftInputAdapterNode(org.drools.core.reteoo.LeftInputAdapterNode)

Example 3 with PathMemory

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);
}
Also used : SegmentMemory(org.drools.core.reteoo.SegmentMemory) Memory(org.drools.core.common.Memory) QueryElementNodeMemory(org.drools.core.reteoo.QueryElementNode.QueryElementNodeMemory) PathMemory(org.drools.core.reteoo.PathMemory) InternalWorkingMemory(org.drools.core.common.InternalWorkingMemory) ConditionalBranchMemory(org.drools.core.reteoo.ConditionalBranchNode.ConditionalBranchMemory) AccumulateMemory(org.drools.core.reteoo.AccumulateNode.AccumulateMemory) TupleMemory(org.drools.core.reteoo.TupleMemory) TimerNodeMemory(org.drools.core.reteoo.TimerNode.TimerNodeMemory) BetaMemory(org.drools.core.reteoo.BetaMemory) EvalMemory(org.drools.core.reteoo.EvalConditionNode.EvalMemory) SegmentMemory(org.drools.core.reteoo.SegmentMemory) FromMemory(org.drools.core.reteoo.FromNode.FromMemory) RiaPathMemory(org.drools.core.reteoo.RiaPathMemory) NetworkNode(org.drools.core.common.NetworkNode) LeftTuple(org.drools.core.reteoo.LeftTuple) LinkedList(org.drools.core.util.LinkedList) QueryTerminalNode(org.drools.core.reteoo.QueryTerminalNode) TerminalNode(org.drools.core.reteoo.TerminalNode) LeftInputAdapterNode(org.drools.core.reteoo.LeftInputAdapterNode)

Example 4 with PathMemory

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();
}
Also used : SegmentMemory(org.drools.core.reteoo.SegmentMemory) AddRemoveRule.forceFlushLeftTuple(org.drools.core.phreak.AddRemoveRule.forceFlushLeftTuple) LeftTuple(org.drools.core.reteoo.LeftTuple) PathMemory(org.drools.core.reteoo.PathMemory)

Example 5 with PathMemory

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;
}
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)

Aggregations

PathMemory (org.drools.core.reteoo.PathMemory)34 InternalWorkingMemory (org.drools.core.common.InternalWorkingMemory)26 SegmentMemory (org.drools.core.reteoo.SegmentMemory)26 RuleTerminalNode (org.drools.core.reteoo.RuleTerminalNode)16 Test (org.junit.Test)16 InternalKnowledgeBase (org.drools.core.impl.InternalKnowledgeBase)14 BetaMemory (org.drools.core.reteoo.BetaMemory)13 LeftInputAdapterNode (org.drools.core.reteoo.LeftInputAdapterNode)13 JoinNode (org.drools.core.reteoo.JoinNode)12 ObjectTypeNode (org.drools.core.reteoo.ObjectTypeNode)11 LeftTupleNode (org.drools.core.reteoo.LeftTupleNode)9 Memory (org.drools.core.common.Memory)8 AccumulateMemory (org.drools.core.reteoo.AccumulateNode.AccumulateMemory)8 KnowledgeBuilder (org.kie.internal.builder.KnowledgeBuilder)8 ArrayList (java.util.ArrayList)7 FromMemory (org.drools.core.reteoo.FromNode.FromMemory)7 RightInputAdapterNode (org.drools.core.reteoo.RightInputAdapterNode)7 RiaNodeMemory (org.drools.core.reteoo.RightInputAdapterNode.RiaNodeMemory)7 TupleMemory (org.drools.core.reteoo.TupleMemory)7 List (java.util.List)6