public static ProtobufMessages.Activation writeActivation( MarshallerWriteContext context, AgendaItem agendaItem) { ProtobufMessages.Activation.Builder _activation = ProtobufMessages.Activation.newBuilder(); RuleImpl rule = agendaItem.getRule(); _activation.setPackageName(rule.getPackage()); _activation.setRuleName(rule.getName()); _activation.setTuple(writeTuple(agendaItem.getTuple())); _activation.setSalience(agendaItem.getSalience()); _activation.setIsActivated(agendaItem.isQueued()); _activation.setEvaluated(agendaItem.isRuleAgendaItem()); if (agendaItem.getActivationGroupNode() != null) { _activation.setActivationGroup( agendaItem.getActivationGroupNode().getActivationGroup().getName()); } if (agendaItem.getFactHandle() != null) { _activation.setHandleId(agendaItem.getFactHandle().getId()); } org.drools.core.util.LinkedList<LogicalDependency> list = agendaItem.getLogicalDependencies(); if (list != null && !list.isEmpty()) { for (LogicalDependency node = list.getFirst(); node != null; node = node.getNext()) { _activation.addLogicalDependency(((BeliefSet) node.getJustified()).getFactHandle().getId()); } } return _activation.build(); }
public static void writeActivation( MarshallerWriteContext context, LeftTuple leftTuple, AgendaItem agendaItem, RuleTerminalNode ruleTerminalNode) throws IOException { ObjectOutputStream stream = context.stream; stream.writeLong(agendaItem.getActivationNumber()); stream.writeInt(context.terminalTupleMap.get(leftTuple)); stream.writeInt(agendaItem.getSalience()); Rule rule = agendaItem.getRule(); stream.writeUTF(rule.getPackage()); stream.writeUTF(rule.getName()); // context.out.println( "Rule " + rule.getPackage() + "." + rule.getName() ); // context.out.println( "AgendaItem long:" + // agendaItem.getPropagationContext().getPropagationNumber() ); stream.writeLong(agendaItem.getPropagationContext().getPropagationNumber()); if (agendaItem.getActivationGroupNode() != null) { stream.writeBoolean(true); // context.out.println( "ActivationGroup bool:" + true ); stream.writeUTF(agendaItem.getActivationGroupNode().getActivationGroup().getName()); // context.out.println( "ActivationGroup string:" + // agendaItem.getActivationGroupNode().getActivationGroup().getName() ); } else { stream.writeBoolean(false); // context.out.println( "ActivationGroup bool:" + false ); } stream.writeBoolean(agendaItem.isActivated()); // context.out.println( "AgendaItem bool:" + agendaItem.isActivated() ); if (agendaItem.getFactHandle() != null) { stream.writeBoolean(true); stream.writeInt(agendaItem.getFactHandle().getId()); } else { stream.writeBoolean(false); } org.drools.core.util.LinkedList list = agendaItem.getLogicalDependencies(); if (list != null && !list.isEmpty()) { for (LogicalDependency node = (LogicalDependency) list.getFirst(); node != null; node = (LogicalDependency) node.getNext()) { stream.writeShort(PersisterEnums.LOGICAL_DEPENDENCY); stream.writeInt(((InternalFactHandle) node.getJustified()).getId()); // context.out.println( "Logical Depenency : int " + ((InternalFactHandle) // node.getFactHandle()).getId() ); } } stream.writeShort(PersisterEnums.END); }
private void doRiaNode( InternalWorkingMemory wm, LeftInputAdapterNode liaNode, PathMemory pmem, TupleSets<LeftTuple> srcTuples, BetaNode betaNode, LeftTupleSinkNode sink, SegmentMemory[] smems, int smemIndex, Memory nodeMem, BetaMemory bm, LinkedList<StackEntry> stack, RuleExecutor executor) { RiaPathMemory pathMem = bm.getRiaRuleMemory(); SegmentMemory[] subnetworkSmems = pathMem.getSegmentMemories(); SegmentMemory subSmem = null; for (int i = 0; subSmem == null; i++) { // segment positions outside of the subnetwork, in the parent chain, are null // so we must iterate to find the first non null segment memory subSmem = subnetworkSmems[i]; } // Resume the node after the riaNode segment has been processed and the right input memory // populated StackEntry stackEntry = new StackEntry( liaNode, betaNode, bm.getNodePosMaskBit(), sink, pmem, nodeMem, smems, smemIndex, srcTuples, false, false); stack.add(stackEntry); if (log.isTraceEnabled()) { int offset = getOffset(betaNode); log.trace( "{} RiaQueue {} {}", indent(offset), betaNode.toString(), srcTuples.toStringSizes()); } TupleSets<LeftTuple> subLts = subSmem.getStagedLeftTuples().takeAll(); // node is first in the segment, so bit is 1 innerEval( liaNode, pathMem, subSmem.getRootNode(), 1, subSmem.getNodeMemories().getFirst(), subnetworkSmems, subSmem.getPos(), subLts, wm, stack, true, executor); }
public void clearAndCancelStagedActivations() { if (getStageActivationsGroup().isEmpty()) { return; } org.drools.core.util.LinkedList<ActivationGroupNode> list = getStageActivationsGroup().getList(); final EventSupport eventsupport = (EventSupport) this.workingMemory; for (ActivationGroupNode node = list.removeFirst(); node != null; node = list.removeFirst()) { AgendaItem item = (AgendaItem) node.getActivation(); // This must be set to false otherwise modify won't work properly item.setQueued(false); eventsupport .getAgendaEventSupport() .fireActivationCancelled(item, this.workingMemory, MatchCancelledCause.CLEAR); } }
public int unstageActivations() { if (!declarativeAgenda || getStageActivationsGroup().isEmpty()) { return 0; } org.drools.core.util.LinkedList<ActivationGroupNode> list = getStageActivationsGroup().getList(); int i = 0; for (ActivationGroupNode node = list.removeFirst(); node != null; node = list.removeFirst()) { AgendaItem item = (AgendaItem) node.getActivation(); item.setActivationGroupNode(null); addActivation(item, false); i++; } notifyHalt(); return i; }
public static ProtobufMessages.Activation writeActivation( MarshallerWriteContext context, AgendaItem agendaItem) { ProtobufMessages.Activation.Builder _activation = ProtobufMessages.Activation.newBuilder(); Rule rule = agendaItem.getRule(); _activation.setPackageName(rule.getPackage()); _activation.setRuleName(rule.getName()); ProtobufMessages.Tuple.Builder _tb = ProtobufMessages.Tuple.newBuilder(); for (LeftTuple entry = agendaItem.getTuple(); entry != null; entry = entry.getParent()) { InternalFactHandle handle = entry.getLastHandle(); _tb.addHandleId(handle.getId()); } _activation.setTuple(_tb.build()); _activation.setSalience(agendaItem.getSalience()); _activation.setIsActivated(agendaItem.isActivated()); if (agendaItem.getActivationGroupNode() != null) { _activation.setActivationGroup( agendaItem.getActivationGroupNode().getActivationGroup().getName()); } if (agendaItem.getFactHandle() != null) { _activation.setHandleId(agendaItem.getFactHandle().getId()); } org.drools.core.util.LinkedList list = agendaItem.getLogicalDependencies(); if (list != null && !list.isEmpty()) { for (LogicalDependency node = (LogicalDependency) list.getFirst(); node != null; node = (LogicalDependency) node.getNext()) { _activation.addLogicalDependency(((InternalFactHandle) node.getJustified()).getId()); } } return _activation.build(); }
public void outerEval( LeftInputAdapterNode liaNode, PathMemory pmem, NetworkNode node, long bit, Memory nodeMem, SegmentMemory[] smems, int smemIndex, TupleSets<LeftTuple> trgTuples, InternalWorkingMemory wm, LinkedList<StackEntry> stack, boolean processRian, RuleExecutor executor) { innerEval( liaNode, pmem, node, bit, nodeMem, smems, smemIndex, trgTuples, wm, stack, processRian, executor); while (true) { // eval if (!stack.isEmpty()) { StackEntry entry = stack.removeLast(); evalStackEntry(entry, stack, executor, wm); } else { return; // stack is empty return; } } }
private int fire( InternalWorkingMemory wm, AgendaFilter filter, int fireCount, int fireLimit, LinkedList<StackEntry> outerStack, InternalAgenda agenda, boolean fireUntilHalt) { int localFireCount = 0; if (!tupleList.isEmpty()) { RuleTerminalNode rtn = (RuleTerminalNode) pmem.getNetworkNode(); if (!fireExitedEarly && isDeclarativeAgendaEnabled()) { // Network Evaluation can notify meta rules, which should be given a chance to fire first RuleAgendaItem nextRule = agenda.peekNextRule(); if (!isHighestSalience(nextRule, ruleAgendaItem.getSalience())) { fireExitedEarly = true; return localFireCount; } } while (!tupleList.isEmpty()) { LeftTuple leftTuple; if (queue != null) { leftTuple = (LeftTuple) queue.dequeue(); tupleList.remove(leftTuple); } else { leftTuple = tupleList.removeFirst(); ((Activation) leftTuple).setQueued(false); } rtn = (RuleTerminalNode) leftTuple .getSink(); // branches result in multiple RTN's for a given rule, so unwrap per // LeftTuple RuleImpl rule = rtn.getRule(); PropagationContext pctx = leftTuple.getPropagationContext(); pctx = RuleTerminalNode.findMostRecentPropagationContext(leftTuple, pctx); // check if the rule is not effective or // if the current Rule is no-loop and the origin rule is the same then return if (cancelAndContinue(wm, rtn, rule, leftTuple, pctx, filter)) { continue; } AgendaItem item = (AgendaItem) leftTuple; if (agenda.getActivationsFilter() != null && !agenda.getActivationsFilter().accept(item, wm, rtn)) { // only relevant for seralization, to not refire Matches already fired continue; } agenda.fireActivation(item); localFireCount++; if (rtn.getLeftTupleSource() == null) { break; // The activation firing removed this rule from the rule base } int salience = ruleAgendaItem.getSalience(); // dyanmic salience may have updated it, so get again. if (queue != null && !queue.isEmpty() && salience != queue.peek().getSalience()) { ruleAgendaItem.dequeue(); ruleAgendaItem.setSalience(queue.peek().getSalience()); ruleAgendaItem.getAgendaGroup().add(ruleAgendaItem); salience = ruleAgendaItem.getSalience(); } RuleAgendaItem nextRule = agenda.peekNextRule(); if (haltRuleFiring(nextRule, fireCount, fireLimit, localFireCount, agenda, salience)) { break; // another rule has high priority and is on the agenda, so evaluate it first } reEvaluateNetwork(wm, outerStack, fireUntilHalt); wm.executeQueuedActions(); if (tupleList.isEmpty() && !outerStack.isEmpty()) { // the outer stack is nodes needing evaluation, once all rule firing is done // such as window expiration, which must be done serially StackEntry entry = outerStack.removeFirst(); NETWORK_EVALUATOR.evalStackEntry(entry, outerStack, outerStack, this, wm); } } } removeRuleAgendaItemWhenEmpty(wm); fireExitedEarly = false; return localFireCount; }
public static void writeTruthMaintenanceSystem( MarshallerWriteContext context, ProtobufMessages.RuleData.Builder _session) throws IOException { ObjectHashMap assertMap = context.wm.getTruthMaintenanceSystem().getAssertMap(); ObjectHashMap justifiedMap = context.wm.getTruthMaintenanceSystem().getJustifiedMap(); if (!assertMap.isEmpty() || !justifiedMap.isEmpty()) { EqualityKey[] keys = new EqualityKey[assertMap.size()]; org.drools.core.util.Iterator it = assertMap.iterator(); int i = 0; for (org.drools.core.util.ObjectHashMap.ObjectEntry entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next(); entry != null; entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next()) { EqualityKey key = (EqualityKey) entry.getKey(); keys[i++] = key; } Arrays.sort(keys, EqualityKeySorter.instance); ProtobufMessages.TruthMaintenanceSystem.Builder _tms = ProtobufMessages.TruthMaintenanceSystem.newBuilder(); // write the assert map of Equality keys for (EqualityKey key : keys) { ProtobufMessages.EqualityKey.Builder _key = ProtobufMessages.EqualityKey.newBuilder(); _key.setStatus(key.getStatus()); _key.setHandleId(key.getFactHandle().getId()); if (key.getOtherFactHandle() != null && !key.getOtherFactHandle().isEmpty()) { for (InternalFactHandle handle : key.getOtherFactHandle()) { _key.addOtherHandle(handle.getId()); } } _tms.addKey(_key.build()); } it = justifiedMap.iterator(); i = 0; for (org.drools.core.util.ObjectHashMap.ObjectEntry entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next(); entry != null; entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next()) { ProtobufMessages.Justification.Builder _justification = ProtobufMessages.Justification.newBuilder(); _justification.setHandleId(((Integer) entry.getKey()).intValue()); org.drools.core.util.LinkedList list = (org.drools.core.util.LinkedList) entry.getValue(); for (LinkedListEntry node = (LinkedListEntry) list.getFirst(); node != null; node = (LinkedListEntry) node.getNext()) { LogicalDependency dependency = (LogicalDependency) node.getObject(); org.drools.spi.Activation activation = dependency.getJustifier(); ProtobufMessages.Activation _activation = ProtobufMessages.Activation.newBuilder() .setPackageName(activation.getRule().getPackage()) .setRuleName(activation.getRule().getName()) .setTuple(PersisterHelper.createTuple(activation.getTuple())) .build(); _justification.addActivation(_activation); } _tms.addJustification(_justification.build()); } _session.setTms(_tms.build()); } }
public void writeExternal(ObjectOutput out) throws IOException { super.writeExternal(out); out.writeInt(hashCode); out.writeInt(status); }
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); hashCode = in.readInt(); status = in.readInt(); }
private boolean evalQueryNode( LeftInputAdapterNode liaNode, 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 trgTuples.addAll(qmem.getResultLeftTuples()); qmem.setNodeCleanWithoutNotify(); if (!srcTuples.isEmpty()) { // only process the Query Node if there are src tuples StackEntry stackEntry = new StackEntry( liaNode, 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; SegmentMemory smem = smems[smemIndex]; // 0 liaNode = (LeftInputAdapterNode) smem.getRootNode(); if (liaNode == smem.getTipNode()) { // segment only has liaNode in it // nothing is staged in the liaNode, so skip to next segment smem = smems[++smemIndex]; // 1 node = smem.getRootNode(); nodeMem = smem.getNodeMemories().getFirst(); bit = 1; } else { // lia is in shared segment, so point to next node node = liaNode.getSinkPropagator().getFirstLeftTupleSink(); nodeMem = smem.getNodeMemories().getFirst().getNext(); // skip the liaNode memory bit = 2; } trgTuples = smem.getStagedLeftTuples().takeAll(); stackEntry = new StackEntry( liaNode, 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; } }
private void doRiaNode( InternalWorkingMemory wm, LeftInputAdapterNode liaNode, PathMemory rmem, LeftTupleSets srcTuples, BetaNode betaNode, LeftTupleSinkNode sink, SegmentMemory[] smems, int smemIndex, Memory nodeMem, BetaMemory bm, LinkedList<StackEntry> stack, Set<String> visitedRules, RuleExecutor executor) { RiaPathMemory pathMem = bm.getRiaRuleMemory(); SegmentMemory[] subnetworkSmems = pathMem.getSegmentMemories(); SegmentMemory subSmem = null; for (int i = 0; subSmem == null; i++) { // segment positions outside of the subnetwork, in the parent chain, are null // so we must iterate to find the first non null segment memory subSmem = subnetworkSmems[i]; } // if (betaNode.getLeftTupleSource().getSinkPropagator().size() == 2) { // // sub network is not part of share split, so need to handle propagation // // this ensures the first LeftTuple is actually the subnetwork node // // and the main outer network now receives the peer, notice the swap at the end // "srcTuples == peerTuples" // LeftTupleSets peerTuples = new LeftTupleSets(); // SegmentPropagator.processPeers(srcTuples, peerTuples, betaNode); // // Make sure subnetwork Segment has tuples to process // LeftTupleSets subnetworkStaged = subSmem.getStagedLeftTuples(); // subnetworkStaged.addAll(srcTuples); // // srcTuples.resetAll(); // // srcTuples = peerTuples; // } // Resume the node after the riaNode segment has been processed and the right input memory // populated StackEntry stackEntry = new StackEntry( liaNode, betaNode, sink, rmem, nodeMem, smems, smemIndex, srcTuples, visitedRules, false); stack.add(stackEntry); if (log.isTraceEnabled()) { int offset = getOffset(betaNode); log.trace( "{} RiaQueue {} {}", indent(offset), betaNode.toString(), srcTuples.toStringSizes()); } // RightInputAdapterNode riaNode = ( RightInputAdapterNode ) betaNode.getRightInput(); // RiaNodeMemory riaNodeMemory = (RiaNodeMemory) wm.getNodeMemory((MemoryFactory) // betaNode.getRightInput()); // LeftTupleSets riaStagedTuples = eval2( liaNode, pathMem, (LeftTupleSink) subSmem.getRootNode(), subSmem.getNodeMemories().getFirst(), subnetworkSmems, subSmem.getPos(), subSmem.getStagedLeftTuples(), wm, stack, visitedRules, true, executor); }
public void eval2( LeftInputAdapterNode liaNode, PathMemory rmem, NetworkNode node, Memory nodeMem, SegmentMemory[] smems, int smemIndex, LeftTupleSets trgTuples, InternalWorkingMemory wm, LinkedList<StackEntry> stack, Set<String> visitedRules, boolean processRian, RuleExecutor executor) { LeftTupleSets srcTuples; SegmentMemory smem = smems[smemIndex]; while (true) { srcTuples = trgTuples; // previous target, is now the source if (log.isTraceEnabled()) { int offset = getOffset(node); log.trace( "{} {} {} {}", indent(offset), ++cycle, node.toString(), srcTuples.toStringSizes()); } if (NodeTypeEnums.isTerminalNode(node)) { TerminalNode rtn = (TerminalNode) node; if (node.getType() == NodeTypeEnums.QueryTerminalNode) { pQtNode.doNode((QueryTerminalNode) rtn, wm, srcTuples, stack); } else { pRtNode.doNode(rtn, wm, srcTuples, executor); } return; } else if (NodeTypeEnums.RightInputAdaterNode == node.getType()) { doRiaNode2(wm, srcTuples, (RightInputAdapterNode) node, stack); return; } LeftTupleSets stagedLeftTuples; if (node == smem.getTipNode() && smem.getFirst() != null) { // we are about to process the segment tip, allow it to merge insert/update/delete clashes // Can happen if the next segments have not yet been initialized stagedLeftTuples = smem.getFirst().getStagedLeftTuples(); } else { stagedLeftTuples = null; } LeftTupleSinkNode sink = ((LeftTupleSource) node).getSinkPropagator().getFirstLeftTupleSink(); trgTuples = new LeftTupleSets(); if (NodeTypeEnums.isBetaNode(node)) { BetaNode betaNode = (BetaNode) node; BetaMemory bm = null; AccumulateMemory am = null; if (NodeTypeEnums.AccumulateNode == node.getType()) { am = (AccumulateMemory) nodeMem; bm = am.getBetaMemory(); } else { bm = (BetaMemory) nodeMem; } if (processRian && betaNode.isRightInputIsRiaNode()) { // if the subnetwork is nested in this segment, it will create srcTuples containing // peer LeftTuples, suitable for the node in the main path. doRiaNode( wm, liaNode, rmem, srcTuples, betaNode, sink, smems, smemIndex, nodeMem, bm, stack, visitedRules, executor); return; // return here is doRiaNode queues the evaluation on the stack, which is necessary // to handled nested query nodes } if (!bm.getDequeu().isEmpty()) { // If there are no staged RightTuples, then process the Dequeue, popping entries, until // another insert/expiration clash RightTupleSets rightTuples = bm.getStagedRightTuples(); if (rightTuples.isEmpty()) { // nothing staged, so now process the Dequeu Deque<RightTuple> que = bm.getDequeu(); while (!que.isEmpty()) { RightTuple rightTuple = que.peekFirst(); if (rightTuple.getPropagationContext().getType() == PropagationContext.EXPIRATION && // Cannot pop an expired fact, if the insert/update has not yet been evaluated. rightTuple.getStagedType() != LeftTuple.NONE) { break; } switch (rightTuple.getPropagationContext().getType()) { case PropagationContext.INSERTION: case PropagationContext.RULE_ADDITION: rightTuples.addInsert(rightTuple); break; case PropagationContext.MODIFICATION: rightTuples.addUpdate(rightTuple); break; case PropagationContext.DELETION: case PropagationContext.EXPIRATION: case PropagationContext.RULE_REMOVAL: rightTuples.addDelete(rightTuple); break; } que.removeFirst(); } } if (!bm.getDequeu().isEmpty()) { // The DeQue is not empty, add StackEntry for reprocessing. StackEntry stackEntry = new StackEntry( liaNode, node, sink, rmem, nodeMem, smems, smemIndex, trgTuples, visitedRules, false); stack.add(stackEntry); } } switch (node.getType()) { case NodeTypeEnums.JoinNode: { pJoinNode.doNode( (JoinNode) node, sink, bm, wm, srcTuples, trgTuples, stagedLeftTuples); break; } case NodeTypeEnums.NotNode: { pNotNode.doNode((NotNode) node, sink, bm, wm, srcTuples, trgTuples, stagedLeftTuples); break; } case NodeTypeEnums.ExistsNode: { pExistsNode.doNode( (ExistsNode) node, sink, bm, wm, srcTuples, trgTuples, stagedLeftTuples); break; } case NodeTypeEnums.AccumulateNode: { pAccNode.doNode( (AccumulateNode) node, sink, am, wm, srcTuples, trgTuples, stagedLeftTuples); break; } } } else { switch (node.getType()) { case NodeTypeEnums.EvalConditionNode: { pEvalNode.doNode( (EvalConditionNode) node, (EvalMemory) nodeMem, sink, wm, srcTuples, trgTuples, stagedLeftTuples); break; } case NodeTypeEnums.FromNode: { pFromNode.doNode( (FromNode) node, (FromMemory) nodeMem, sink, wm, srcTuples, trgTuples, stagedLeftTuples); break; } case NodeTypeEnums.QueryElementNode: { 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 break; } QueryElementNode qnode = (QueryElementNode) node; if (visitedRules == Collections.<String>emptySet()) { visitedRules = new HashSet<String>(); } visitedRules.add(qnode.getQueryElement().getQueryName()); // 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 trgTuples.addAll(qmem.getResultLeftTuples()); if (!srcTuples.isEmpty()) { // only process the Query Node if there are src tuples StackEntry stackEntry = new StackEntry( liaNode, node, sink, rmem, nodeMem, smems, smemIndex, trgTuples, visitedRules, true); stack.add(stackEntry); pQueryNode.doNode( qnode, (QueryElementNodeMemory) nodeMem, stackEntry, sink, wm, srcTuples); SegmentMemory qsmem = ((QueryElementNodeMemory) nodeMem).getQuerySegmentMemory(); List<PathMemory> qrmems = qsmem.getPathMemories(); // Build the evaluation information for each 'or' branch // Exception fo the last, place each entry on the stack, the last one evaluate now. for (int i = qrmems.size() - 1; i >= 0; i--) { PathMemory qrmem = qrmems.get(i); rmem = qrmem; smems = qrmem.getSegmentMemories(); smemIndex = 0; smem = smems[smemIndex]; // 0 liaNode = (LeftInputAdapterNode) smem.getRootNode(); if (liaNode == smem.getTipNode()) { // segment only has liaNode in it // nothing is staged in the liaNode, so skip to next segment smem = smems[++smemIndex]; // 1 node = smem.getRootNode(); nodeMem = smem.getNodeMemories().getFirst(); } else { // lia is in shared segment, so point to next node node = liaNode.getSinkPropagator().getFirstLeftTupleSink(); nodeMem = smem.getNodeMemories().getFirst().getNext(); // skip the liaNode memory } trgTuples = smem.getStagedLeftTuples(); if (i != 0 && !trgTuples.isEmpty()) { // All entries except the last should be placed on the stack for evaluation // later. stackEntry = new StackEntry( liaNode, node, null, rmem, nodeMem, smems, smemIndex, trgTuples, visitedRules, false); if (log.isTraceEnabled()) { int offset = getOffset(stackEntry.getNode()); log.trace( "{} ORQueue branch={} {} {}", indent(offset), i, stackEntry.getNode().toString(), trgTuples.toStringSizes()); } stack.add(stackEntry); } } processRian = true; // make sure it's reset, so ria nodes are processed continue; } break; } case NodeTypeEnums.ConditionalBranchNode: { pBranchNode.doNode( (ConditionalBranchNode) node, (ConditionalBranchMemory) nodeMem, sink, wm, srcTuples, trgTuples, stagedLeftTuples, executor); break; } } } if (node != smem.getTipNode()) { // get next node and node memory in the segment node = sink; nodeMem = nodeMem.getNext(); } else { // Reached end of segment, start on new segment. SegmentPropagator.propagate(smem, trgTuples, wm); smem = smems[++smemIndex]; trgTuples = smem.getStagedLeftTuples(); if (log.isTraceEnabled()) { log.trace("Segment {}", smemIndex); } node = (LeftTupleSink) smem.getRootNode(); nodeMem = smem.getNodeMemories().getFirst(); } processRian = true; // make sure it's reset, so ria nodes are processed } }
public void eval1( LeftInputAdapterNode liaNode, PathMemory rmem, NetworkNode node, Memory nodeMem, SegmentMemory[] smems, int smemIndex, LeftTupleSets trgTuples, InternalWorkingMemory wm, LinkedList<StackEntry> stack, Set<String> visitedRules, boolean processRian, RuleExecutor executor) { while (true) { eval2( liaNode, rmem, node, nodeMem, smems, smemIndex, trgTuples, wm, stack, visitedRules, processRian, executor); // eval if (!stack.isEmpty()) { StackEntry entry = stack.removeLast(); node = entry.getNode(); nodeMem = entry.getNodeMem(); trgTuples = entry.getTrgTuples(); if (node.getType() == NodeTypeEnums.QueryElementNode) { // copy across the results, if any from the query node memory trgTuples.addAll(((QueryElementNodeMemory) nodeMem).getResultLeftTuples()); } LeftTupleSinkNode sink = entry.getSink(); rmem = entry.getRmem(); smems = entry.getSmems(); smemIndex = entry.getSmemIndex(); visitedRules = entry.getVisitedRules(); if (NodeTypeEnums.isBetaNode(node)) { // queued beta nodes do not want their ria node evaluated, otherwise there is recursion processRian = false; } else { processRian = true; } if (entry.isResumeFromNextNode()) { SegmentMemory smem = smems[smemIndex]; if (node != smem.getTipNode()) { // get next node and node memory in the segment LeftTupleSink nextSink = sink.getNextLeftTupleSinkNode(); if (nextSink == null) { node = sink; } else { // there is a nested subnetwork, take out path node = nextSink; } nodeMem = nodeMem.getNext(); } else { // Reached end of segment, start on new segment. SegmentPropagator.propagate(smem, trgTuples, wm); smem = smems[++smemIndex]; trgTuples = smem.getStagedLeftTuples(); node = (LeftTupleSink) smem.getRootNode(); nodeMem = smem.getNodeMemories().getFirst(); } } if (log.isTraceEnabled()) { int offset = getOffset(node); log.trace("{} Resume {} {}", indent(offset), node.toString(), trgTuples.toStringSizes()); } } else { return; // stack is empty return; } } }