public static void writePropagationContexts(MarshallerWriteContext context) throws IOException { ObjectOutputStream stream = context.stream; if (context.terminalTupleMap != null && context.terminalTupleMap.size() > 0) { Entry<LeftTuple, Integer>[] entries = context.terminalTupleMap.entrySet().toArray(new Entry[context.terminalTupleMap.size()]); Arrays.sort(entries, TupleSorter.instance); // Map<LeftTuple, Integer> tuples = context.terminalTupleMap; if (entries.length != 0) { Map<Long, PropagationContext> pcMap = new HashMap<Long, PropagationContext>(); for (Entry<LeftTuple, Integer> entry : entries) { LeftTuple leftTuple = entry.getKey(); if (leftTuple.getObject() != null) { PropagationContext pc = ((Activation) leftTuple.getObject()).getPropagationContext(); if (!pcMap.containsKey(pc.getPropagationNumber())) { stream.writeShort(PersisterEnums.PROPAGATION_CONTEXT); writePropagationContext(context, pc); pcMap.put(pc.getPropagationNumber(), pc); } } } } } stream.writeShort(PersisterEnums.END); }
/** * @inheritDoc As the accumulate node will always generate a resulting tuple, we must always * destroy it */ public void retractLeftTuple( final LeftTuple leftTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this); if (leftTuple.getMemory().isStagingMemory()) { leftTuple.getMemory().remove(leftTuple); } else { ((BetaMemory) memory.getBetaMemory()).getLeftTupleMemory().remove(leftTuple); } leftTuple.setMemory(null); final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); if (accctx.getAction() != null) { // there is a scheduled activation, we must cancel it context.removeInsertAction(accctx.getAction()); } leftTuple.setObject(null); removePreviousMatchesForLeftTuple(leftTuple, workingMemory, memory, accctx); if (accctx.propagated) { // if tuple was previously propagated, retract it and destroy result fact handle this.sink.propagateRetractLeftTupleDestroyRightTuple(leftTuple, context, workingMemory); } else { // if not propagated, just destroy the result fact handle // workingMemory.getFactHandleFactory().destroyFactHandle( accctx.result.getFactHandle() ); } }
public void rowUpdated( final Rule rule, final LeftTuple resultLeftTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { RightTuple rightTuple = (RightTuple) resultLeftTuple.getObject(); if (rightTuple.getMemory() != null) { // Already sheduled as an insert return; } rightTuple.setLeftTuple(null); resultLeftTuple.setObject(null); // We need to recopy everything back again, as we don't know what has or hasn't changed QueryTerminalNode node = (QueryTerminalNode) resultLeftTuple.getLeftTupleSink(); Declaration[] decls = node.getDeclarations(); InternalFactHandle rootHandle = resultLeftTuple.get(0); DroolsQuery query = (DroolsQuery) rootHandle.getObject(); Object[] objects = new Object[query.getElements().length]; Declaration decl; for (int i = 0, length = this.variables.length; i < length; i++) { decl = decls[this.variables[i]]; objects[this.variables[i]] = decl.getValue(workingMemory, resultLeftTuple.get(decl).getObject()); } QueryElementFactHandle handle = (QueryElementFactHandle) rightTuple.getFactHandle(); handle.setRecency(workingMemory.getFactHandleFactory().getAtomicRecency().incrementAndGet()); handle.setObject(objects); if (query.isOpen()) { rightTuple.setLeftTuple(resultLeftTuple); resultLeftTuple.setObject(rightTuple); } // Don't need to recreate child links, as they will already be there form the first "add" RightTupleList rightTuples = query.getResultUpdateRightTupleList(); if (rightTuples == null) { rightTuples = new RightTupleList(); query.setResultUpdateRightTupleList(rightTuples); QueryResultUpdateAction updateAction = new QueryResultUpdateAction(context, this.factHandle, leftTuple, this.node); context.getQueue2().addFirst(updateAction); } rightTuples.add(rightTuple); }
/** * @inheritDoc When a new object is asserted into an AccumulateNode, do this: * <p>1. Select all matching tuples from left memory 2. For each matching tuple, call a modify * tuple */ public void assertRightTuple( final RightTuple rightTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this); memory.betaMemory.getRightTupleMemory().add(rightTuple); if (memory.betaMemory.getLeftTupleMemory() == null || memory.betaMemory.getLeftTupleMemory().size() == 0) { // do nothing here, as we know there are no left tuples at this stage in sequential mode or // for a query. // unless it's an "Open Query" and thus that will have left memory, so continue as normal return; } this.constraints.updateFromFactHandle( memory.betaMemory.getContext(), workingMemory, rightTuple.getFactHandle()); LeftTupleMemory leftMemory = memory.betaMemory.getLeftTupleMemory(); FastIterator leftIt = getLeftIterator(leftMemory); for (LeftTuple leftTuple = getFirstLeftTuple(rightTuple, leftMemory, context, leftIt); leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) { if (this.constraints.isAllowedCachedRight(memory.betaMemory.getContext(), leftTuple)) { final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); addMatch(leftTuple, rightTuple, null, null, workingMemory, memory, accctx, true); if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub networks // We set Source to LEFT, even though this is a right propagation, because it might end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } } } this.constraints.resetFactHandle(memory.betaMemory.getContext()); }
public Object next() { Activation acc = null; if (this.currentLeftTuple != null) { acc = (Activation) currentLeftTuple.getObject(); this.currentLeftTuple = (LeftTuple) leftTupleIter.next(); while (currentLeftTuple == null && (node = (TerminalNode) nodeIter.next()) != null) { if (!(node instanceof RuleTerminalNode)) { continue; } leftTupleIter = LeftTupleIterator.iterator(wm, node); this.currentLeftTuple = (LeftTuple) leftTupleIter.next(); } } return acc; }
private static ProtobufMessages.NodeMemory writeQueryElementNodeMemory( final int nodeId, final Memory memory, final InternalWorkingMemory wm) { LeftTupleIterator it = LeftTupleIterator.iterator(wm, ((QueryElementNodeMemory) memory).node); ProtobufMessages.NodeMemory.QueryElementNodeMemory.Builder _query = ProtobufMessages.NodeMemory.QueryElementNodeMemory.newBuilder(); for (LeftTuple leftTuple = (LeftTuple) it.next(); leftTuple != null; leftTuple = (LeftTuple) it.next()) { InternalFactHandle handle = (InternalFactHandle) leftTuple.getObject(); FactHandle _handle = ProtobufMessages.FactHandle.newBuilder() .setId(handle.getId()) .setRecency(handle.getRecency()) .build(); ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext.Builder _context = ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext.newBuilder() .setTuple(PersisterHelper.createTuple(leftTuple)) .setHandle(_handle); LeftTuple childLeftTuple = leftTuple.getFirstChild(); while (childLeftTuple != null) { RightTuple rightParent = childLeftTuple.getRightParent(); _context.addResult( ProtobufMessages.FactHandle.newBuilder() .setId(rightParent.getFactHandle().getId()) .setRecency(rightParent.getFactHandle().getRecency()) .build()); while (childLeftTuple != null && childLeftTuple.getRightParent() == rightParent) { // skip to the next child that has a different right parent childLeftTuple = childLeftTuple.getLeftParentNext(); } } _query.addContext(_context.build()); } return _query.getContextCount() > 0 ? ProtobufMessages.NodeMemory.newBuilder() .setNodeId(nodeId) .setNodeType(ProtobufMessages.NodeMemory.NodeType.QUERY_ELEMENT) .setQueryElement(_query.build()) .build() : null; }
public void updateSink( final LeftTupleSink sink, final PropagationContext context, final InternalWorkingMemory workingMemory) { final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this); final Iterator tupleIter = memory.betaMemory.getLeftTupleMemory().iterator(); for (LeftTuple leftTuple = (LeftTuple) tupleIter.next(); leftTuple != null; leftTuple = (LeftTuple) tupleIter.next()) { AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); if (accctx.propagated) { // temporarily break the linked list to avoid wrong interactions LeftTuple[] matchings = splitList(leftTuple, accctx, true); sink.assertLeftTuple( sink.createLeftTuple(leftTuple, accctx.result, null, null, sink, true), context, workingMemory); restoreList(leftTuple, matchings); } } }
public static void writeActivations(MarshallerWriteContext context) throws IOException { ObjectOutputStream stream = context.stream; Entry<LeftTuple, Integer>[] entries = context.terminalTupleMap.entrySet().toArray(new Entry[context.terminalTupleMap.size()]); Arrays.sort(entries, TupleSorter.instance); // Map<LeftTuple, Integer> tuples = context.terminalTupleMap; if (entries.length != 0) { for (Entry<LeftTuple, Integer> entry : entries) { if (entry.getKey().getObject() != null) { LeftTuple leftTuple = entry.getKey(); stream.writeShort(PersisterEnums.ACTIVATION); writeActivation( context, leftTuple, (AgendaItem) leftTuple.getObject(), (RuleTerminalNode) leftTuple.getLeftTupleSink()); } } } stream.writeShort(PersisterEnums.END); }
@SuppressWarnings("unchecked") private static ProtobufMessages.NodeMemory writeFromNodeMemory( final int nodeId, final Memory memory) { FromMemory fromMemory = (FromMemory) memory; if (fromMemory.betaMemory.getLeftTupleMemory().size() > 0) { ProtobufMessages.NodeMemory.FromNodeMemory.Builder _from = ProtobufMessages.NodeMemory.FromNodeMemory.newBuilder(); final org.drools.core.util.Iterator tupleIter = fromMemory.betaMemory.getLeftTupleMemory().iterator(); for (LeftTuple leftTuple = (LeftTuple) tupleIter.next(); leftTuple != null; leftTuple = (LeftTuple) tupleIter.next()) { Map<Object, RightTuple> matches = (Map<Object, RightTuple>) leftTuple.getObject(); ProtobufMessages.NodeMemory.FromNodeMemory.FromContext.Builder _context = ProtobufMessages.NodeMemory.FromNodeMemory.FromContext.newBuilder() .setTuple(PersisterHelper.createTuple(leftTuple)); for (RightTuple rightTuple : matches.values()) { FactHandle _handle = ProtobufMessages.FactHandle.newBuilder() .setId(rightTuple.getFactHandle().getId()) .setRecency(rightTuple.getFactHandle().getRecency()) .build(); _context.addHandle(_handle); } _from.addContext(_context.build()); } return ProtobufMessages.NodeMemory.newBuilder() .setNodeId(nodeId) .setNodeType(ProtobufMessages.NodeMemory.NodeType.FROM) .setFrom(_from.build()) .build(); } return null; }
private static ProtobufMessages.NodeMemory writeAccumulateNodeMemory( final int nodeId, final Memory memory) { // for accumulate nodes, we need to store the ID of created (result) handles AccumulateMemory accmem = (AccumulateMemory) memory; if (accmem.betaMemory.getLeftTupleMemory().size() > 0) { ProtobufMessages.NodeMemory.AccumulateNodeMemory.Builder _accumulate = ProtobufMessages.NodeMemory.AccumulateNodeMemory.newBuilder(); final org.drools.core.util.Iterator tupleIter = accmem.betaMemory.getLeftTupleMemory().iterator(); for (LeftTuple leftTuple = (LeftTuple) tupleIter.next(); leftTuple != null; leftTuple = (LeftTuple) tupleIter.next()) { AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); if (accctx.result != null) { FactHandle _handle = ProtobufMessages.FactHandle.newBuilder() .setId(accctx.result.getFactHandle().getId()) .setRecency(accctx.result.getFactHandle().getRecency()) .build(); _accumulate.addContext( ProtobufMessages.NodeMemory.AccumulateNodeMemory.AccumulateContext.newBuilder() .setTuple(PersisterHelper.createTuple(leftTuple)) .setResultHandle(_handle) .build()); } } return ProtobufMessages.NodeMemory.newBuilder() .setNodeId(nodeId) .setNodeType(ProtobufMessages.NodeMemory.NodeType.ACCUMULATE) .setAccumulate(_accumulate.build()) .build(); } return null; }
public void rowRemoved( final Rule rule, final LeftTuple resultLeftTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { RightTuple rightTuple = (RightTuple) resultLeftTuple.getObject(); rightTuple.setLeftTuple(null); resultLeftTuple.setObject(null); DroolsQuery query = (DroolsQuery) this.factHandle.getObject(); RightTupleList rightTuples = query.getResultRetractRightTupleList(); if (rightTuples == null) { rightTuples = new RightTupleList(); query.setResultRetractRightTupleList(rightTuples); QueryResultRetractAction retractAction = new QueryResultRetractAction(context, this.factHandle, leftTuple, this.node); context.getQueue2().addFirst(retractAction); } if (rightTuple.getMemory() != null) { throw new RuntimeException(); } rightTuples.add(rightTuple); }
private void removePreviousMatchesForRightTuple( final RightTuple rightTuple, final PropagationContext context, final InternalWorkingMemory workingMemory, final AccumulateMemory memory, final LeftTuple firstChild) { for (LeftTuple match = firstChild; match != null; ) { final LeftTuple tmp = match.getRightParentNext(); final LeftTuple parent = match.getLeftParent(); final AccumulateContext accctx = (AccumulateContext) parent.getObject(); removeMatch(rightTuple, match, workingMemory, memory, accctx, true); if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub networks // We set Source to LEFT, even though this is a right propagation, because it might end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, parent, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } match = tmp; } }
public static void writeLeftTuple( LeftTuple leftTuple, MarshallerWriteContext context, boolean recurse) throws IOException { ObjectOutputStream stream = context.stream; InternalRuleBase ruleBase = context.ruleBase; InternalWorkingMemory wm = context.wm; LeftTupleSink sink = leftTuple.getLeftTupleSink(); switch (sink.getType()) { case NodeTypeEnums.JoinNode: { // context.out.println( "JoinNode" ); for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { stream.writeShort(PersisterEnums.RIGHT_TUPLE); int childSinkId = childLeftTuple.getLeftTupleSink().getId(); stream.writeInt(childSinkId); stream.writeInt(childLeftTuple.getRightParent().getFactHandle().getId()); // context.out.println( "RightTuple int:" + childLeftTuple.getLeftTupleSink().getId() + // " int:" + childLeftTuple.getRightParent().getFactHandle().getId() ); writeLeftTuple(childLeftTuple, context, recurse); } stream.writeShort(PersisterEnums.END); // context.out.println( "JoinNode --- END" ); break; } case NodeTypeEnums.QueryRiaFixerNode: case NodeTypeEnums.EvalConditionNode: { // context.out.println( ".... EvalConditionNode" ); for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { stream.writeShort(PersisterEnums.LEFT_TUPLE); stream.writeInt(childLeftTuple.getLeftTupleSink().getId()); writeLeftTuple(childLeftTuple, context, recurse); } stream.writeShort(PersisterEnums.END); // context.out.println( "---- EvalConditionNode --- END" ); break; } case NodeTypeEnums.NotNode: case NodeTypeEnums.ForallNotNode: { if (leftTuple.getBlocker() == null) { // is not blocked so has children stream.writeShort(PersisterEnums.LEFT_TUPLE_NOT_BLOCKED); for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { stream.writeShort(PersisterEnums.LEFT_TUPLE); stream.writeInt(childLeftTuple.getLeftTupleSink().getId()); writeLeftTuple(childLeftTuple, context, recurse); } stream.writeShort(PersisterEnums.END); } else { stream.writeShort(PersisterEnums.LEFT_TUPLE_BLOCKED); stream.writeInt(leftTuple.getBlocker().getFactHandle().getId()); } break; } case NodeTypeEnums.ExistsNode: { if (leftTuple.getBlocker() == null) { // is blocked so has children stream.writeShort(PersisterEnums.LEFT_TUPLE_NOT_BLOCKED); } else { stream.writeShort(PersisterEnums.LEFT_TUPLE_BLOCKED); stream.writeInt(leftTuple.getBlocker().getFactHandle().getId()); for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { stream.writeShort(PersisterEnums.LEFT_TUPLE); stream.writeInt(childLeftTuple.getLeftTupleSink().getId()); writeLeftTuple(childLeftTuple, context, recurse); } stream.writeShort(PersisterEnums.END); } break; } case NodeTypeEnums.AccumulateNode: { // context.out.println( ".... AccumulateNode" ); // accumulate nodes generate new facts on-demand and need special procedures when // serializing to persistent storage AccumulateMemory memory = (AccumulateMemory) context.wm.getNodeMemory((BetaNode) sink); AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); // first we serialize the generated fact handle writeFactHandle( context, stream, context.objectMarshallingStrategyStore, accctx.result.getFactHandle()); // then we serialize the associated accumulation context stream.writeObject(accctx.context); // then we serialize the boolean propagated flag stream.writeBoolean(accctx.propagated); // then we serialize all the propagated tuples for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { if (leftTuple.getLeftTupleSink().getId() == childLeftTuple.getLeftTupleSink().getId()) { // this is a matching record, so, associate the right tuples // context.out.println( "RightTuple(match) int:" + // childLeftTuple.getLeftTupleSink().getId() + " int:" + // childLeftTuple.getRightParent().getFactHandle().getId() ); stream.writeShort(PersisterEnums.RIGHT_TUPLE); stream.writeInt(childLeftTuple.getRightParent().getFactHandle().getId()); } else { // this is a propagation record // context.out.println( "RightTuple(propagation) int:" + // childLeftTuple.getLeftTupleSink().getId() + " int:" + // childLeftTuple.getRightParent().getFactHandle().getId() ); stream.writeShort(PersisterEnums.LEFT_TUPLE); int sinkId = childLeftTuple.getLeftTupleSink().getId(); stream.writeInt(sinkId); writeLeftTuple(childLeftTuple, context, recurse); } } stream.writeShort(PersisterEnums.END); // context.out.println( "---- AccumulateNode --- END" ); break; } case NodeTypeEnums.RightInputAdaterNode: { // context.out.println( ".... RightInputAdapterNode" ); // RIANs generate new fact handles on-demand to wrap tuples and need special procedures // when serializing to persistent storage ObjectHashMap memory = (ObjectHashMap) context.wm.getNodeMemory((NodeMemory) sink); InternalFactHandle ifh = (InternalFactHandle) memory.get(leftTuple); // first we serialize the generated fact handle ID // context.out.println( "FactHandle id:"+ifh.getId() ); stream.writeInt(ifh.getId()); stream.writeLong(ifh.getRecency()); writeRightTuples(ifh, context); stream.writeShort(PersisterEnums.END); // context.out.println( "---- RightInputAdapterNode --- END" ); break; } case NodeTypeEnums.FromNode: { // context.out.println( ".... FromNode" ); // FNs generate new fact handles on-demand to wrap objects and need special procedures // when serializing to persistent storage FromMemory memory = (FromMemory) context.wm.getNodeMemory((NodeMemory) sink); Map<Object, RightTuple> matches = (Map<Object, RightTuple>) leftTuple.getObject(); for (RightTuple rightTuples : matches.values()) { // first we serialize the generated fact handle ID stream.writeShort(PersisterEnums.FACT_HANDLE); writeFactHandle( context, stream, context.objectMarshallingStrategyStore, rightTuples.getFactHandle()); writeRightTuples(rightTuples.getFactHandle(), context); } stream.writeShort(PersisterEnums.END); for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { stream.writeShort(PersisterEnums.RIGHT_TUPLE); stream.writeInt(childLeftTuple.getLeftTupleSink().getId()); stream.writeInt(childLeftTuple.getRightParent().getFactHandle().getId()); // context.out.println( "RightTuple int:" + childLeftTuple.getLeftTupleSink().getId() + // " int:" + childLeftTuple.getRightParent().getFactHandle().getId() ); writeLeftTuple(childLeftTuple, context, recurse); } stream.writeShort(PersisterEnums.END); // context.out.println( "---- FromNode --- END" ); break; } case NodeTypeEnums.UnificationNode: { // context.out.println( ".... UnificationNode" ); QueryElementNode node = (QueryElementNode) sink; boolean isOpen = node.isOpenQuery(); context.writeBoolean(isOpen); if (isOpen) { InternalFactHandle factHandle = (InternalFactHandle) leftTuple.getObject(); DroolsQuery query = (DroolsQuery) factHandle.getObject(); // context.out.println( "factHandle:" + factHandle ); factHandle.setObject(null); writeFactHandle(context, stream, context.objectMarshallingStrategyStore, 0, factHandle); factHandle.setObject(query); writeLeftTuples(context, new InternalFactHandle[] {factHandle}); } else { for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext()) { stream.writeShort(PersisterEnums.LEFT_TUPLE); stream.writeInt(childLeftTuple.getLeftTupleSink().getId()); InternalFactHandle factHandle = childLeftTuple.getLastHandle(); writeFactHandle( context, stream, context.objectMarshallingStrategyStore, 1, factHandle); writeLeftTuple(childLeftTuple, context, recurse); } stream.writeShort(PersisterEnums.END); } // context.out.println( "---- EvalConditionNode --- END" ); break; } case NodeTypeEnums.RuleTerminalNode: { // context.out.println( "RuleTerminalNode" ); int pos = context.terminalTupleMap.size(); context.terminalTupleMap.put(leftTuple, pos); break; } case NodeTypeEnums.QueryTerminalNode: { // context.out.println( ".... QueryTerminalNode" ); // LeftTuple entry = leftTuple; // // // find the DroolsQuery object // while ( entry.getParent() != null ) { // entry = entry.getParent(); // } // // // Now output all the child tuples in the caller network // DroolsQuery query = (DroolsQuery) entry.getLastHandle().getObject(); // if ( query.getQueryResultCollector() instanceof // UnificationNodeViewChangedEventListener ) { // context.writeBoolean( true ); // UnificationNodeViewChangedEventListener collector = // (UnificationNodeViewChangedEventListener) query.getQueryResultCollector(); // leftTuple = collector.getLeftTuple(); // context.writeBoolean(true); RightTuple rightTuple = (RightTuple) leftTuple.getObject(); // context.out.println( "rightTuple:" + rightTuple.getFactHandle() ); writeFactHandle( context, stream, context.objectMarshallingStrategyStore, 1, rightTuple.getFactHandle()); for (LeftTuple childLeftTuple = rightTuple.firstChild; childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getRightParentNext()) { stream.writeShort(PersisterEnums.LEFT_TUPLE); stream.writeInt(childLeftTuple.getLeftTupleSink().getId()); writeLeftTuple(childLeftTuple, context, recurse); } // for ( LeftTuple childLeftTuple = leftTuple.getFirstChild(); // childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getLeftParentNext() // ) { // stream.writeShort( PersisterEnums.LEFT_TUPLE ); // stream.writeInt( childLeftTuple.getLeftTupleSink().getId() ); // writeFactHandle( context, // stream, // context.objectMarshallingStrategyStore, // 1, // childLeftTuple.getLastHandle() ); // writeLeftTuple( childLeftTuple, // context, // recurse ); // } // } else { // context.writeBoolean( false ); // } stream.writeShort(PersisterEnums.END); // context.out.println( "---- QueryTerminalNode --- END" ); break; } } }
public void modifyLeftTuple( LeftTuple leftTuple, PropagationContext context, InternalWorkingMemory workingMemory) { boolean executeAsOpenQuery = openQuery; if (executeAsOpenQuery) { // There is no point in doing an open query if the caller is a non-open query. Object object = ((InternalFactHandle) leftTuple.get(0)).getObject(); if (object instanceof DroolsQuery && !((DroolsQuery) object).isOpen()) { executeAsOpenQuery = false; } } if (!executeAsOpenQuery) { // Was never open so execute as a retract + assert if (leftTuple.getFirstChild() != null) { this.sink.propagateRetractLeftTuple(leftTuple, context, workingMemory); } assertLeftTuple(leftTuple, context, workingMemory); return; } InternalFactHandle handle = (InternalFactHandle) leftTuple.getObject(); DroolsQuery queryObject = (DroolsQuery) handle.getObject(); if (queryObject.getAction() != null) { // we already have an insert scheduled for this query, but have re-entered it // do nothing return; } Object[] argTemplate = this.queryElement.getArgTemplate(); // an array of declr, variable and literals Object[] args = new Object[argTemplate.length]; // the actual args, to be created from the template // first copy everything, so that we get the literals. We will rewrite the declarations and // variables next System.arraycopy(argTemplate, 0, args, 0, args.length); int[] declIndexes = this.queryElement.getDeclIndexes(); for (int i = 0, length = declIndexes.length; i < length; i++) { Declaration declr = (Declaration) argTemplate[declIndexes[i]]; Object tupleObject = leftTuple.get(declr).getObject(); Object o; if (tupleObject instanceof DroolsQuery) { // If the query passed in a Variable, we need to use it ArrayElementReader arrayReader = (ArrayElementReader) declr.getExtractor(); if (((DroolsQuery) tupleObject).getVariables()[arrayReader.getIndex()] != null) { o = Variable.v; } else { o = declr.getValue(workingMemory, tupleObject); } } else { o = declr.getValue(workingMemory, tupleObject); } args[declIndexes[i]] = o; } int[] varIndexes = this.queryElement.getVariableIndexes(); for (int i = 0, length = varIndexes.length; i < length; i++) { if (argTemplate[varIndexes[i]] == Variable.v) { // Need to check against the arg template, as the varIndexes also includes re-declared // declarations args[varIndexes[i]] = Variable.v; } } queryObject.setParameters(args); ((UnificationNodeViewChangedEventListener) queryObject.getQueryResultCollector()) .setVariables(varIndexes); QueryUpdateAction action = new QueryUpdateAction(context, handle, leftTuple, this); context.getQueue1().addFirst(action); }
public void modifyRightTuple( RightTuple rightTuple, PropagationContext context, InternalWorkingMemory workingMemory) { final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this); BetaMemory bm = memory.betaMemory; // Add and remove to make sure we are in the right bucket and at the end // this is needed to fix for indexing and deterministic iteration bm.getRightTupleMemory().removeAdd(rightTuple); if (bm.getLeftTupleMemory() == null || bm.getLeftTupleMemory().size() == 0) { // do nothing here, as we know there are no left tuples at this stage in sequential mode. return; } LeftTuple childLeftTuple = rightTuple.firstChild; LeftTupleMemory leftMemory = bm.getLeftTupleMemory(); FastIterator leftIt = getLeftIterator(leftMemory); LeftTuple leftTuple = getFirstLeftTuple(rightTuple, leftMemory, context, leftIt); this.constraints.updateFromFactHandle( bm.getContext(), workingMemory, rightTuple.getFactHandle()); // first check our index (for indexed nodes only) hasn't changed and we are returning the same // bucket // We assume a bucket change if leftTuple == null if (childLeftTuple != null && leftMemory.isIndexed() && !leftIt.isFullIterator() && (leftTuple == null || (leftTuple.getMemory() != childLeftTuple.getLeftParent().getMemory()))) { // our index has changed, so delete all the previous matches removePreviousMatchesForRightTuple( rightTuple, context, workingMemory, memory, childLeftTuple); childLeftTuple = null; // null so the next check will attempt matches for new bucket } // if LeftTupleMemory is empty, there are no matches to modify if (leftTuple != null) { if (childLeftTuple == null) { // either we are indexed and changed buckets or // we had no children before, but there is a bucket to potentially match, so try as normal // assert for (; leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) { if (this.constraints.isAllowedCachedRight(bm.getContext(), leftTuple)) { final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); // add a new match addMatch(leftTuple, rightTuple, null, null, workingMemory, memory, accctx, true); if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub // networks // We set Source to LEFT, even though this is a right propagation, because it might // end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } } } } else { // in the same bucket, so iterate and compare for (; leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) { if (this.constraints.isAllowedCachedRight(bm.getContext(), leftTuple)) { final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); LeftTuple temp = null; if (childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple) { temp = childLeftTuple.getRightParentNext(); // we must re-add this to ensure deterministic iteration childLeftTuple.reAddLeft(); removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, true); childLeftTuple = temp; } // add a new match addMatch( leftTuple, rightTuple, null, childLeftTuple, workingMemory, memory, accctx, true); if (temp != null) { childLeftTuple = temp; } if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub // networks // We set Source to LEFT, even though this is a right propagation, because it might // end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } } else if (childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple) { LeftTuple temp = childLeftTuple.getRightParentNext(); final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); // remove the match removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, true); if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub // networks // We set Source to LEFT, even though this is a right propagation, because it might // end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } childLeftTuple = temp; } // else do nothing, was false before and false now. } } } this.constraints.resetFactHandle(bm.getContext()); }
public void modifyLeftTuple( LeftTuple leftTuple, PropagationContext context, InternalWorkingMemory workingMemory) { final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this); final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); BetaMemory bm = memory.betaMemory; // Add and remove to make sure we are in the right bucket and at the end // this is needed to fix for indexing and deterministic iteration bm.getLeftTupleMemory().removeAdd(leftTuple); this.constraints.updateFromTuple(bm.getContext(), workingMemory, leftTuple); LeftTuple childLeftTuple = getFirstMatch(leftTuple, accctx, false); RightTupleMemory rightMemory = bm.getRightTupleMemory(); FastIterator rightIt = getRightIterator(rightMemory); RightTuple rightTuple = getFirstRightTuple(leftTuple, rightMemory, context, rightIt); // first check our index (for indexed nodes only) hasn't changed and we are returning the same // bucket // if rightTuple is null, we assume there was a bucket change and that bucket is empty if (childLeftTuple != null && rightMemory.isIndexed() && !rightIt.isFullIterator() && (rightTuple == null || (rightTuple.getMemory() != childLeftTuple.getRightParent().getMemory()))) { // our index has changed, so delete all the previous matchings removePreviousMatchesForLeftTuple(leftTuple, workingMemory, memory, accctx); childLeftTuple = null; // null so the next check will attempt matches for new bucket } // we can't do anything if RightTupleMemory is empty if (rightTuple != null) { if (childLeftTuple == null) { // either we are indexed and changed buckets or // we had no children before, but there is a bucket to potentially match, so try as normal // assert for (; rightTuple != null; rightTuple = (RightTuple) rightIt.next(rightTuple)) { final InternalFactHandle handle = rightTuple.getFactHandle(); if (this.constraints.isAllowedCachedLeft(bm.getContext(), handle)) { // add a new match addMatch(leftTuple, rightTuple, null, null, workingMemory, memory, accctx, true); } } } else { boolean isDirty = false; // in the same bucket, so iterate and compare for (; rightTuple != null; rightTuple = (RightTuple) rightIt.next(rightTuple)) { final InternalFactHandle handle = rightTuple.getFactHandle(); if (this.constraints.isAllowedCachedLeft(bm.getContext(), handle)) { if (childLeftTuple == null || childLeftTuple.getRightParent() != rightTuple) { // add a new match addMatch( leftTuple, rightTuple, childLeftTuple, null, workingMemory, memory, accctx, true); } else { // we must re-add this to ensure deterministic iteration LeftTuple temp = childLeftTuple.getLeftParentNext(); childLeftTuple.reAddRight(); childLeftTuple = temp; } } else if (childLeftTuple != null && childLeftTuple.getRightParent() == rightTuple) { LeftTuple temp = childLeftTuple.getLeftParentNext(); // remove the match removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, false); childLeftTuple = temp; // the next line means that when a match is removed from the current leftTuple // and the accumulate does not support the reverse operation, then the whole // result is dirty (since removeMatch above is not recalculating the total) // and we need to do this later isDirty = !accumulate.supportsReverse(); } // else do nothing, was false before and false now. } if (isDirty) { reaccumulateForLeftTuple(leftTuple, workingMemory, memory, accctx); } } } this.constraints.resetTuple(memory.betaMemory.getContext()); if (accctx.getAction() == null) { evaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true); } // else evaluation is already scheduled, so do nothing }