public void modifyChildLeftTuplesforQuery( final RightTuple rightTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { LeftTuple childLeftTuple = rightTuple.firstChild; while (childLeftTuple != null) { childLeftTuple.getLeftTupleSink().modifyLeftTuple(childLeftTuple, context, workingMemory); childLeftTuple = childLeftTuple.getRightParentNext(); } }
public void propagateRetractRightTuple( final RightTuple rightTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { LeftTuple child = rightTuple.firstChild; while (child != null) { LeftTuple temp = child.getRightParentNext(); doPropagateRetractLeftTuple(context, workingMemory, child, child.getLeftTupleSink()); child.unlinkFromLeftParent(); child.unlinkFromRightParent(); child = temp; } }
public LeftTuple propagateRetractChildLeftTuple( LeftTuple childLeftTuple, LeftTuple parentLeftTuple, PropagationContext context, InternalWorkingMemory workingMemory) { // iterate to find all child tuples for the shared node while (childLeftTuple != null && childLeftTuple.getLeftParent() == parentLeftTuple) { // this will iterate for each child node when the // the current node is shared LeftTuple temp = childLeftTuple.getRightParentNext(); doPropagateRetractLeftTuple( context, workingMemory, childLeftTuple, childLeftTuple.getLeftTupleSink()); childLeftTuple.unlinkFromRightParent(); childLeftTuple.unlinkFromLeftParent(); childLeftTuple = temp; } return childLeftTuple; }
public LeftTuple propagateModifyChildLeftTuple( LeftTuple childLeftTuple, LeftTuple parentLeftTuple, PropagationContext context, InternalWorkingMemory workingMemory, boolean tupleMemoryEnabled) { // iterate to find all child tuples for the shared node while (childLeftTuple != null && childLeftTuple.getLeftParent() == parentLeftTuple) { // this will iterate for each child node when the // the current node is shared // preserve the current LeftTuple, as we need to iterate to the next before re-adding LeftTuple temp = childLeftTuple; childLeftTuple.getLeftTupleSink().modifyLeftTuple(childLeftTuple, context, workingMemory); childLeftTuple = childLeftTuple.getRightParentNext(); temp.reAddLeft(); } return childLeftTuple; }
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 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()); }