public static void dpUpdatesReorderRightMemory(BetaMemory bm, RightTupleSets srcRightTuples) { RightTupleMemory rtm = bm.getRightTupleMemory(); for (RightTuple rightTuple = srcRightTuples.getUpdateFirst(); rightTuple != null; ) { RightTuple next = rightTuple.getStagedNext(); if (rightTuple.getMemory() != null) { rightTuple.setTempRightTupleMemory(rightTuple.getMemory()); rtm.remove(rightTuple); } rightTuple = next; } for (RightTuple rightTuple = srcRightTuples.getUpdateFirst(); rightTuple != null; ) { RightTuple next = rightTuple.getStagedNext(); if (rightTuple.getTempRightTupleMemory() != null) { rtm.add(rightTuple); for (LeftTuple childLeftTuple = rightTuple.getFirstChild(); childLeftTuple != null; ) { LeftTuple childNext = childLeftTuple.getRightParentNext(); childLeftTuple.reAddLeft(); childLeftTuple = childNext; } } rightTuple = next; } }
/** * Tests the assertion of objects into LeftInputAdapterNode * * @throws Exception */ @Test public void testAssertObjectWithoutMemory() throws Exception { PropagationContextFactory pctxFactory = kBase.getConfiguration().getComponentFactory().getPropagationContextFactory(); final PropagationContext pcontext = pctxFactory.createPropagationContext(0, PropagationContext.INSERTION, null, null, null); BuildContext context = new BuildContext(kBase, kBase.getReteooBuilder().getIdGenerator()); final EntryPointNode entryPoint = new EntryPointNode(-1, kBase.getRete(), context); entryPoint.attach(context); final ObjectTypeNode objectTypeNode = new ObjectTypeNode(0, entryPoint, new ClassObjectType(Object.class), context); objectTypeNode.attach(context); final LeftInputAdapterNode liaNode = new LeftInputAdapterNode(23, objectTypeNode, buildContext); liaNode.attach(context); final StatefulKnowledgeSessionImpl workingMemory = new StatefulKnowledgeSessionImpl(1L, kBase); final MockLeftTupleSink sink = new MockLeftTupleSink(); liaNode.addTupleSink(sink); final Object string1 = "cheese"; // assert object final DefaultFactHandle f0 = (DefaultFactHandle) workingMemory.insert(string1); liaNode.assertObject(f0, pcontext, workingMemory); final List asserted = sink.getAsserted(); assertLength(1, asserted); final LeftTuple tuple0 = (LeftTuple) ((Object[]) asserted.get(0))[0]; assertSame(string1, workingMemory.getObject(tuple0.get(0))); }
public static void dpUpdatesExistentialReorderLeftMemory( BetaMemory bm, LeftTupleSets srcLeftTuples) { LeftTupleMemory ltm = bm.getLeftTupleMemory(); // sides must first be re-ordered, to ensure iteration integrity for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple != null; ) { LeftTuple next = leftTuple.getStagedNext(); if (leftTuple.getMemory() != null) { ltm.remove(leftTuple); } leftTuple = next; } for (LeftTuple leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple != null; ) { LeftTuple next = leftTuple.getStagedNext(); if (leftTuple.getBlocker() == null) { ltm.add(leftTuple); for (LeftTuple childLeftTuple = leftTuple.getFirstChild(); childLeftTuple != null; ) { LeftTuple childNext = childLeftTuple.getLeftParentNext(); childLeftTuple.reAddRight(); childLeftTuple = childNext; } } leftTuple = next; } }
public void execute(InternalWorkingMemory workingMemory) { DroolsQuery query = (DroolsQuery) factHandle.getObject(); RightTupleList rightTuples = query.getResultInsertRightTupleList(); query.setResultInsertRightTupleList( null); // null so further operations happen on a new stack element for (RightTuple rightTuple = rightTuples.getFirst(); rightTuple != null; ) { RightTuple tmp = (RightTuple) rightTuple.getNext(); rightTuples.remove(rightTuple); for (LeftTuple childLeftTuple = rightTuple.firstChild; childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getRightParentNext()) { node.getSinkPropagator() .doPropagateAssertLeftTuple( context, workingMemory, childLeftTuple, childLeftTuple.getLeftTupleSink()); } rightTuple = tmp; } // @FIXME, this should work, but it's closing needed fact handles // actually an evaluation 34 appears on the stack twice.... // if ( !node.isOpenQuery() ) { // workingMemory.getFactHandleFactory().destroyFactHandle( this.factHandle ); // } }
public void closeLiveQuery(final InternalFactHandle factHandle) { try { startOperation(); this.ruleBase.readLock(); this.lock.lock(); final PropagationContext pCtx = new PropagationContextImpl( getNextPropagationIdCounter(), PropagationContext.INSERTION, null, null, factHandle, getEntryPoint()); if (this.ruleBase.getConfiguration().isPhreakEnabled()) { LeftInputAdapterNode lian = (LeftInputAdapterNode) factHandle.getFirstLeftTuple().getLeftTupleSink().getLeftTupleSource(); LiaNodeMemory lmem = (LiaNodeMemory) getNodeMemory((MemoryFactory) lian); SegmentMemory lsmem = lmem.getSegmentMemory(); LeftTuple childLeftTuple = factHandle.getFirstLeftTuple(); // there is only one, all other LTs are peers LeftInputAdapterNode.doDeleteObject( childLeftTuple, childLeftTuple.getPropagationContext(), lsmem, this, lian, false, lmem); List<PathMemory> rmems = lmem.getSegmentMemory().getPathMemories(); for (int i = 0, length = rmems.size(); i < length; i++) { PathMemory rm = rmems.get(i); RuleNetworkEvaluatorActivation evaluator = agenda.createRuleNetworkEvaluatorActivation( Integer.MAX_VALUE, rm, (TerminalNode) rm.getNetworkNode()); evaluator.evaluateNetwork(this, 0, -1); } } else { getEntryPointNode().retractQuery(factHandle, pCtx, this); pCtx.evaluateActionQueue(this); } getFactHandleFactory().destroyFactHandle(factHandle); } finally { this.lock.unlock(); this.ruleBase.readUnlock(); endOperation(); } }
/** * Assert a new <code>ReteTuple</code> from the left input. It iterates over the right <code> * FactHandleImpl</code>'s and if any match is found, a copy of the <code>ReteTuple</code> is made * and propagated. * * @param tuple The <code>Tuple</code> being asserted. * @param context The <code>PropagationContext</code> * @param workingMemory The working memory session. */ public void assertLeftTuple( final LeftTuple leftTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); RightTupleMemory rightMemory = memory.getRightTupleMemory(); ContextEntry[] contextEntry = memory.getContext(); boolean useLeftMemory = true; if (!this.tupleMemoryEnabled) { // This is a hack, to not add closed DroolsQuery objects Object object = ((InternalFactHandle) context.getFactHandle()).getObject(); if (!(object instanceof DroolsQuery) || !((DroolsQuery) object).isOpen()) { useLeftMemory = false; } } this.constraints.updateFromTuple(contextEntry, workingMemory, leftTuple); FastIterator it = getRightIterator(rightMemory); for (RightTuple rightTuple = getFirstRightTuple( leftTuple, rightMemory, (InternalFactHandle) context.getFactHandle(), it); rightTuple != null; rightTuple = (RightTuple) it.next(rightTuple)) { if (this.constraints.isAllowedCachedLeft(contextEntry, rightTuple.getFactHandle())) { leftTuple.setBlocker(rightTuple); if (useLeftMemory) { rightTuple.addBlocked(leftTuple); } break; } } this.constraints.resetTuple(contextEntry); if (leftTuple.getBlocker() != null) { // tuple is not blocked to propagate this.sink.propagateAssertLeftTuple(leftTuple, context, workingMemory, useLeftMemory); } else if (useLeftMemory) { // LeftTuple is not blocked, so add to memory so other RightTuples can match memory.getLeftTupleMemory().add(leftTuple); } }
public void execute(InternalWorkingMemory workingMemory) { leftTuple.setLeftTupleSink(this.node); if (leftTuple.getFirstChild() == null) { this.node.assertLeftTuple(leftTuple, context, workingMemory); } else { if (retract) { this.node .getSinkPropagator() .propagateRetractLeftTuple(leftTuple, context, workingMemory); } else { this.node .getSinkPropagator() .propagateModifyChildLeftTuple(leftTuple, context, workingMemory, true); } } if (leftTuple.getLeftParent() == null) { // It's not an open query, as we aren't recording parent chains, so we need to clear out // right memory Object node = workingMemory.getNodeMemory(this.node); RightTupleMemory rightMemory = null; if (node instanceof BetaMemory) { rightMemory = ((BetaMemory) node).getRightTupleMemory(); } else if (node instanceof AccumulateMemory) { rightMemory = ((AccumulateMemory) node).betaMemory.getRightTupleMemory(); } final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance(); TupleStartEqualsConstraintContextEntry contextEntry = new TupleStartEqualsConstraintContextEntry(); contextEntry.updateFromTuple(workingMemory, leftTuple); FastIterator rightIt = rightMemory.fastIterator(); RightTuple temp = null; for (RightTuple rightTuple = rightMemory.getFirst( leftTuple, (InternalFactHandle) context.getFactHandle(), rightIt); rightTuple != null; ) { temp = (RightTuple) rightIt.next(rightTuple); if (constraint.isAllowedCachedLeft(contextEntry, rightTuple.getFactHandle())) { rightMemory.remove(rightTuple); } rightTuple = temp; } } }
public static void findLeftTupleBlocker( BetaNode betaNode, RightTupleMemory rtm, ContextEntry[] contextEntry, BetaConstraints constraints, LeftTuple leftTuple, FastIterator it, PropagationContext context, boolean useLeftMemory) { // This method will also remove rightTuples that are from subnetwork where no leftmemory use // used for (RightTuple rightTuple = betaNode.getFirstRightTuple(leftTuple, rtm, null, it); rightTuple != null; ) { RightTuple nextRight = (RightTuple) it.next(rightTuple); if (constraints.isAllowedCachedLeft(contextEntry, rightTuple.getFactHandle())) { leftTuple.setBlocker(rightTuple); if (useLeftMemory) { rightTuple.addBlocked(leftTuple); break; } else if (betaNode.isRightInputIsRiaNode()) { // If we aren't using leftMemory and the right input is a RIAN, then we must iterate and // find all subetwork right tuples and remove them // so we don't break rtm.remove(rightTuple); } else { break; } } rightTuple = nextRight; } }
@Override public LeftTuple createPeer(LeftTuple original) { FromNodeLeftTuple peer = new FromNodeLeftTuple(); peer.initPeer((BaseLeftTuple) original, this); original.setPeer(peer); return peer; }
public static LeftTuple deleteRightChild( LeftTuple childLeftTuple, LeftTupleSets trgLeftTuples, LeftTupleSets stagedLeftTuples) { switch (childLeftTuple.getStagedType()) { // handle clash with already staged entries case LeftTuple.INSERT: stagedLeftTuples.removeInsert(childLeftTuple); break; case LeftTuple.UPDATE: stagedLeftTuples.removeUpdate(childLeftTuple); break; } LeftTuple next = childLeftTuple.getRightParentNext(); trgLeftTuples.addDelete(childLeftTuple); childLeftTuple.unlinkFromRightParent(); childLeftTuple.unlinkFromLeftParent(); return next; }
public static boolean useLeftMemory(LeftTupleSource tupleSource, LeftTuple leftTuple) { boolean useLeftMemory = true; if (!tupleSource.isLeftTupleMemoryEnabled()) { // This is a hack, to not add closed DroolsQuery objects Object object = leftTuple.getRootLeftTuple().getLastHandle().getObject(); if (!(object instanceof DroolsQuery) || !((DroolsQuery) object).isOpen()) { useLeftMemory = false; } } return useLeftMemory; }
public void execute(InternalWorkingMemory workingMemory) { InternalFactHandle factHandle = (InternalFactHandle) leftTuple.getObject(); if (node.isOpenQuery()) { // iterate to the query terminal node, as the child leftTuples will get picked up there workingMemory .getEntryPointNode() .retractObject( factHandle, context, workingMemory .getObjectTypeConfigurationRegistry() .getObjectTypeConf(workingMemory.getEntryPoint(), factHandle.getObject()), workingMemory); // workingMemory.getFactHandleFactory().destroyFactHandle( factHandle ); } else { // get child left tuples, as there is no open query if (leftTuple.getFirstChild() != null) { node.getSinkPropagator().propagateRetractLeftTuple(leftTuple, context, workingMemory); } } }
/** Updates the given sink propagating all previously propagated tuples to it */ public void updateSink( final LeftTupleSink sink, final PropagationContext context, final InternalWorkingMemory workingMemory) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); Iterator it = memory.getRightTupleMemory().iterator(); // Relies on the fact that any propagated LeftTuples are blocked, but due to lazy blocking // they will only be blocked once. So we can iterate the right memory to find the left tuples to // propagate for (RightTuple rightTuple = (RightTuple) it.next(); rightTuple != null; rightTuple = (RightTuple) it.next()) { LeftTuple leftTuple = rightTuple.getBlocked(); while (leftTuple != null) { sink.assertLeftTuple( sink.createLeftTuple(leftTuple, sink, context, true), context, workingMemory); leftTuple = leftTuple.getBlockedNext(); } } }
public static void doModifyLeftTuple( InternalFactHandle factHandle, ModifyPreviousTuples modifyPreviousTuples, PropagationContext context, InternalWorkingMemory workingMemory, LeftTupleSink sink, ObjectTypeNode.Id leftInputOtnId, BitMask leftInferredMask) { LeftTuple leftTuple = modifyPreviousTuples.peekLeftTuple(); while (leftTuple != null && leftTuple.getLeftTupleSink().getLeftInputOtnId() != null && leftTuple.getLeftTupleSink().getLeftInputOtnId().before(leftInputOtnId)) { modifyPreviousTuples.removeLeftTuple(); // we skipped this node, due to alpha hashing, so retract now ((LeftInputAdapterNode) leftTuple.getLeftTupleSink().getLeftTupleSource()) .retractLeftTuple(leftTuple, context, workingMemory); leftTuple = modifyPreviousTuples.peekLeftTuple(); } if (leftTuple != null && leftTuple.getLeftTupleSink().getLeftInputOtnId() != null && leftTuple.getLeftTupleSink().getLeftInputOtnId().equals(leftInputOtnId)) { modifyPreviousTuples.removeLeftTuple(); leftTuple.reAdd(); if (context.getModificationMask().intersects(leftInferredMask)) { // LeftTuple previously existed, so continue as modify, unless it's currently staged sink.modifyLeftTuple(leftTuple, context, workingMemory); } } else { if (context.getModificationMask().intersects(leftInferredMask)) { // LeftTuple does not exist, so create and continue as assert LeftTuple newLeftTuple = sink.createLeftTuple(factHandle, sink, true); sink.assertLeftTuple(newLeftTuple, context, workingMemory); } } }
/** * Assert a new <code>FactHandleImpl</code> from the right input. If it matches any left * ReteTuple's that had no matches before, propagate tuple as an assertion. * * @param factHandle The <code>FactHandleImpl</code> being asserted. * @param context The <code>PropagationContext</code> * @param workingMemory The working memory session. */ public void assertRightTuple( final RightTuple rightTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); memory.getRightTupleMemory().add(rightTuple); if (memory.getLeftTupleMemory() == null || memory.getLeftTupleMemory().size() == 0) { // do nothing here, as no left memory return; } this.constraints.updateFromFactHandle( memory.getContext(), workingMemory, rightTuple.getFactHandle()); LeftTupleMemory leftMemory = memory.getLeftTupleMemory(); FastIterator it = getLeftIterator(leftMemory); for (LeftTuple leftTuple = getFirstLeftTuple(rightTuple, leftMemory, context, it); leftTuple != null; ) { // preserve next now, in case we remove this leftTuple LeftTuple temp = (LeftTuple) it.next(leftTuple); // we know that only unblocked LeftTuples are still in the memory if (this.constraints.isAllowedCachedRight(memory.getContext(), leftTuple)) { leftTuple.setBlocker(rightTuple); rightTuple.addBlocked(leftTuple); memory.getLeftTupleMemory().remove(leftTuple); this.sink.propagateAssertLeftTuple(leftTuple, context, workingMemory, true); } leftTuple = temp; } this.constraints.resetFactHandle(memory.getContext()); }
/** * Retract the * <code>ReteTuple<code>, any resulting propagated joins are also retracted. * * @param leftTuple * The tuple being retracted * @param context * The <code>PropagationContext</code> * @param workingMemory * The working memory session. */ public void retractLeftTuple( final LeftTuple leftTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { RightTuple blocker = leftTuple.getBlocker(); if (blocker == null) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); memory.getLeftTupleMemory().remove(leftTuple); } else { this.sink.propagateRetractLeftTuple(leftTuple, context, workingMemory); blocker.removeBlocked(leftTuple); } }
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) { ProtobufMessages.ActionQueue.Assert.Builder _assert = ProtobufMessages.ActionQueue.Assert.newBuilder(); _assert .setHandleId(this.factHandle.getId()) .setRemoveLogical(this.removeLogical) .setUpdateEqualsMap(this.updateEqualsMap); if (this.leftTuple != null) { ProtobufMessages.Tuple.Builder _tuple = ProtobufMessages.Tuple.newBuilder(); for (LeftTuple entry = this.leftTuple; entry != null; entry = entry.getParent()) { _tuple.addHandleId(entry.getLastHandle().getId()); } _assert .setOriginPkgName(ruleOrigin.getPackageName()) .setOriginRuleName(ruleOrigin.getName()) .setTuple(_tuple.build()); } return ProtobufMessages.ActionQueue.Action.newBuilder() .setType(ProtobufMessages.ActionQueue.ActionType.ASSERT) .setAssert(_assert.build()) .build(); }
public void modifyRightTuple( RightTuple rightTuple, PropagationContext context, InternalWorkingMemory workingMemory) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); if (memory.getLeftTupleMemory() == null || (memory.getLeftTupleMemory().size() == 0 && rightTuple.getBlocked() == null)) { // do nothing here, as we know there are no left tuples // normally do this at the end, but as we are exiting early, make sure the buckets are still // correct. memory.getRightTupleMemory().removeAdd(rightTuple); return; } // TODO: wtd with behaviours? // if ( !behavior.assertRightTuple( memory.getBehaviorContext(), // rightTuple, // workingMemory ) ) { // // destroy right tuple // rightTuple.unlinkFromRightParent(); // return; // } this.constraints.updateFromFactHandle( memory.getContext(), workingMemory, rightTuple.getFactHandle()); LeftTupleMemory leftMemory = memory.getLeftTupleMemory(); FastIterator leftIt = getLeftIterator(leftMemory); LeftTuple firstLeftTuple = getFirstLeftTuple(rightTuple, leftMemory, context, leftIt); LeftTuple firstBlocked = rightTuple.getBlocked(); // we now have reference to the first Blocked, so null it in the rightTuple itself, so we can // rebuild rightTuple.nullBlocked(); // first process non-blocked tuples, as we know only those ones are in the left memory. for (LeftTuple leftTuple = firstLeftTuple; leftTuple != null; ) { // preserve next now, in case we remove this leftTuple LeftTuple temp = (LeftTuple) leftIt.next(leftTuple); // we know that only unblocked LeftTuples are still in the memory if (this.constraints.isAllowedCachedRight(memory.getContext(), leftTuple)) { leftTuple.setBlocker(rightTuple); rightTuple.addBlocked(leftTuple); // this is now blocked so remove from memory leftMemory.remove(leftTuple); // subclasses like ForallNotNode might override this propagation this.sink.propagateAssertLeftTuple(leftTuple, context, workingMemory, true); } leftTuple = temp; } RightTupleMemory rightTupleMemory = memory.getRightTupleMemory(); if (firstBlocked != null) { boolean useComparisonIndex = rightTupleMemory.getIndexType().isComparison(); // now process existing blocks, we only process existing and not new from above loop FastIterator rightIt = getRightIterator(rightTupleMemory); RightTuple rootBlocker = useComparisonIndex ? null : (RightTuple) rightIt.next(rightTuple); RightTupleList list = rightTuple.getMemory(); // we must do this after we have the next in memory // We add to the end to give an opportunity to re-match if in same bucket rightTupleMemory.removeAdd(rightTuple); if (!useComparisonIndex && rootBlocker == null && list == rightTuple.getMemory()) { // we are at the end of the list, but still in same bucket, so set to self, to give self a // chance to rematch rootBlocker = rightTuple; } // iterate all the existing previous blocked LeftTuples for (LeftTuple leftTuple = (LeftTuple) firstBlocked; leftTuple != null; ) { LeftTuple temp = leftTuple.getBlockedNext(); leftTuple.setBlockedPrevious(null); // must null these as we are re-adding them to the list leftTuple.setBlockedNext(null); leftTuple.setBlocker(null); this.constraints.updateFromTuple(memory.getContext(), workingMemory, leftTuple); if (useComparisonIndex) { rootBlocker = getFirstRightTuple( leftTuple, rightTupleMemory, (InternalFactHandle) context.getFactHandle(), rightIt); } // we know that older tuples have been checked so continue next for (RightTuple newBlocker = rootBlocker; newBlocker != null; newBlocker = (RightTuple) rightIt.next(newBlocker)) { if (this.constraints.isAllowedCachedLeft( memory.getContext(), newBlocker.getFactHandle())) { leftTuple.setBlocker(newBlocker); newBlocker.addBlocked(leftTuple); break; } } if (leftTuple.getBlocker() == null) { // was previous blocked and not in memory, so add memory.getLeftTupleMemory().add(leftTuple); // subclasses like ForallNotNode might override this propagation this.sink.propagateRetractLeftTuple(leftTuple, context, workingMemory); } leftTuple = temp; } } else { // we had to do this at the end, rather than beginning as this 'if' block needs the next // memory tuple rightTupleMemory.removeAdd(rightTuple); } this.constraints.resetFactHandle(memory.getContext()); this.constraints.resetTuple(memory.getContext()); }
public void modifyLeftTuple( LeftTuple leftTuple, PropagationContext context, InternalWorkingMemory workingMemory) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); RightTupleMemory rightMemory = memory.getRightTupleMemory(); FastIterator rightIt = getRightIterator(rightMemory); RightTuple firstRightTuple = getFirstRightTuple( leftTuple, rightMemory, (InternalFactHandle) context.getFactHandle(), rightIt); // If in memory, remove it, because we'll need to add it anyway if it's not blocked, to ensure // iteration order RightTuple blocker = leftTuple.getBlocker(); if (blocker == null) { memory.getLeftTupleMemory().remove(leftTuple); } else { // check if we changed bucket if (rightMemory.isIndexed() && !rightIt.isFullIterator()) { // if newRightTuple is null, we assume there was a bucket change and that bucket is empty if (firstRightTuple == null || firstRightTuple.getMemory() != blocker.getMemory()) { // we changed bucket, so blocker no longer blocks blocker.removeBlocked(leftTuple); blocker = null; } } } this.constraints.updateFromTuple(memory.getContext(), workingMemory, leftTuple); // if we where not blocked before (or changed buckets), or the previous blocker no longer // blocks, then find the next blocker if (blocker == null || !this.constraints.isAllowedCachedLeft(memory.getContext(), blocker.getFactHandle())) { if (blocker != null) { // remove previous blocker if it exists, as we know it doesn't block any more blocker.removeBlocked(leftTuple); } FastIterator it = memory.getRightTupleMemory().fastIterator(); // find first blocker, because it's a modify, we need to start from the beginning again for (RightTuple newBlocker = firstRightTuple; newBlocker != null; newBlocker = (RightTuple) rightIt.next(newBlocker)) { if (this.constraints.isAllowedCachedLeft(memory.getContext(), newBlocker.getFactHandle())) { leftTuple.setBlocker(newBlocker); newBlocker.addBlocked(leftTuple); break; } } } if (leftTuple.getBlocker() == null) { // not blocked memory .getLeftTupleMemory() .add(leftTuple); // add to memory so other fact handles can attempt to match if (leftTuple.getFirstChild() != null) { // with previous children, retract this.sink.propagateRetractLeftTuple(leftTuple, context, workingMemory); } // with no previous children. do nothing. } else if (leftTuple.getFirstChild() == null) { // blocked, with no previous children, assert this.sink.propagateAssertLeftTuple(leftTuple, context, workingMemory, true); } else { // blocked, with previous children, modify this.sink.propagateModifyChildLeftTuple(leftTuple, context, workingMemory, true); } this.constraints.resetTuple(memory.getContext()); }
/** * Retract the <code>FactHandleImpl</code>. If the handle has any <code>ReteTuple</code> matches * and those tuples now have no other match, retract tuple * * @param handle the <codeFactHandleImpl</code> being retracted * @param context The <code>PropagationContext</code> * @param workingMemory The working memory session. */ public void retractRightTuple( final RightTuple rightTuple, final PropagationContext context, final InternalWorkingMemory workingMemory) { final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this); if (isUnlinkingEnabled()) { doDeleteRightTuple(rightTuple, workingMemory, memory); return; } RightTupleMemory rightTupleMemory = memory.getRightTupleMemory(); boolean useComparisonIndex = rightTupleMemory.getIndexType().isComparison(); FastIterator rightIt = rightTupleMemory.fastIterator(); RightTuple rootBlocker = useComparisonIndex ? null : (RightTuple) rightIt.next(rightTuple); rightTupleMemory.remove(rightTuple); rightTuple.setMemory(null); if (rightTuple.getBlocked() == null) { return; } for (LeftTuple leftTuple = (LeftTuple) rightTuple.getBlocked(); leftTuple != null; ) { LeftTuple temp = leftTuple.getBlockedNext(); leftTuple.setBlocker(null); leftTuple.setBlockedPrevious(null); leftTuple.setBlockedNext(null); this.constraints.updateFromTuple(memory.getContext(), workingMemory, leftTuple); if (useComparisonIndex) { rootBlocker = getFirstRightTuple( leftTuple, rightTupleMemory, (InternalFactHandle) context.getFactHandle(), rightIt); } // we know that older tuples have been checked so continue previously for (RightTuple newBlocker = rootBlocker; newBlocker != null; newBlocker = (RightTuple) rightIt.next(newBlocker)) { if (this.constraints.isAllowedCachedLeft(memory.getContext(), newBlocker.getFactHandle())) { leftTuple.setBlocker(newBlocker); newBlocker.addBlocked(leftTuple); break; } } if (leftTuple.getBlocker() == null) { // was previous blocked and not in memory, so add memory.getLeftTupleMemory().add(leftTuple); this.sink.propagateRetractLeftTuple(leftTuple, context, workingMemory); } leftTuple = temp; } rightTuple.nullBlocked(); this.constraints.resetTuple(memory.getContext()); }
public void modifyObject( final InternalFactHandle handle, final PropagationContext context, final ObjectTypeConf objectTypeConf, final InternalWorkingMemory wm) { if (log.isTraceEnabled()) { log.trace("Update {}", handle.toString()); } // checks if shadow is enabled if (objectTypeConf.isShadowEnabled()) { // the user has implemented the ShadowProxy interface, let their implementation // know it is safe to update the information the engine can see. ((ShadowProxy) handle.getObject()).updateProxy(); } ObjectTypeNode[] cachedNodes = objectTypeConf.getObjectTypeNodes(); // make a reference to the previous tuples, then null then on the handle ModifyPreviousTuples modifyPreviousTuples = new ModifyPreviousTuples( handle.getFirstLeftTuple(), handle.getFirstRightTuple(), unlinkingEnabled); handle.clearLeftTuples(); handle.clearRightTuples(); for (int i = 0, length = cachedNodes.length; i < length; i++) { cachedNodes[i].modifyObject(handle, modifyPreviousTuples, context, wm); // remove any right tuples that matches the current OTN before continue the modify on the next // OTN cache entry if (i < cachedNodes.length - 1) { RightTuple rightTuple = modifyPreviousTuples.peekRightTuple(); while (rightTuple != null && ((BetaNode) rightTuple.getRightTupleSink()).getObjectTypeNode() == cachedNodes[i]) { modifyPreviousTuples.removeRightTuple(); if (unlinkingEnabled) { BetaMemory bm = BetaNode.getBetaMemory((BetaNode) rightTuple.getRightTupleSink(), wm); BetaNode.doDeleteRightTuple(rightTuple, wm, bm); } else { ((BetaNode) rightTuple.getRightTupleSink()).retractRightTuple(rightTuple, context, wm); } rightTuple = modifyPreviousTuples.peekRightTuple(); } LeftTuple leftTuple; ObjectTypeNode otn; while (true) { leftTuple = modifyPreviousTuples.peekLeftTuple(); otn = null; if (leftTuple != null) { LeftTupleSink leftTupleSink = leftTuple.getLeftTupleSink(); if (leftTupleSink instanceof LeftTupleSource) { otn = ((LeftTupleSource) leftTupleSink).getLeftTupleSource().getObjectTypeNode(); } else if (leftTupleSink instanceof RuleTerminalNode) { otn = ((RuleTerminalNode) leftTupleSink).getObjectTypeNode(); } } if (otn == null || otn == cachedNodes[i + 1]) break; modifyPreviousTuples.removeLeftTuple(); if (unlinkingEnabled) { LeftInputAdapterNode liaNode = (LeftInputAdapterNode) leftTuple.getLeftTupleSink().getLeftTupleSource(); LiaNodeMemory lm = (LiaNodeMemory) wm.getNodeMemory(liaNode); LeftInputAdapterNode.doDeleteObject( leftTuple, context, lm.getSegmentMemory(), wm, liaNode, true, lm); } else { leftTuple.getLeftTupleSink().retractLeftTuple(leftTuple, context, wm); } } } } modifyPreviousTuples.retractTuples(context, wm); }
public void execute(InternalWorkingMemory workingMemory) { final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); accctx.setAction(null); node.evaluateResultConstraints( source, leftTuple, context, workingMemory, memory, accctx, useLeftMemory); }
private void doRiaNode2( InternalWorkingMemory wm, LeftTupleSets srcTuples, RightInputAdapterNode riaNode, LinkedList<StackEntry> stack) { ObjectSink[] sinks = riaNode.getSinkPropagator().getSinks(); BetaNode betaNode = (BetaNode) sinks[0]; BetaMemory bm; Memory nodeMem = wm.getNodeMemory(betaNode); if (NodeTypeEnums.AccumulateNode == betaNode.getType()) { bm = ((AccumulateMemory) nodeMem).getBetaMemory(); } else { bm = (BetaMemory) nodeMem; } // Build up iteration array for other sinks BetaNode[] bns = null; BetaMemory[] bms = null; int length = sinks.length; if (length > 1) { bns = new BetaNode[sinks.length - 1]; bms = new BetaMemory[sinks.length - 1]; for (int i = 1; i < length; i++) { bns[i - 1] = (BetaNode) sinks[i]; Memory nodeMem2 = wm.getNodeMemory(bns[i - 1]); if (NodeTypeEnums.AccumulateNode == betaNode.getType()) { bms[i - 1] = ((AccumulateMemory) nodeMem2).getBetaMemory(); } else { bms[i - 1] = (BetaMemory) nodeMem2; } } } length--; // subtract one, as first is not in the array; for (LeftTuple leftTuple = srcTuples.getInsertFirst(); leftTuple != null; ) { LeftTuple next = leftTuple.getStagedNext(); PropagationContext pctx = leftTuple.getPropagationContext(); InternalFactHandle handle = riaNode.createFactHandle(leftTuple, pctx, wm); RightTuple rightTuple = new RightTuple(handle, betaNode); leftTuple.setObject(rightTuple); rightTuple.setPropagationContext(pctx); bm.getStagedRightTuples().addInsert(rightTuple); if (bns != null) { // Add peered RightTuples, they are attached to FH - unlink LeftTuples that has a peer ref for (int i = 0; i < length; i++) { rightTuple = new RightTuple(handle, bns[i]); rightTuple.setPropagationContext(pctx); bms[i].getStagedRightTuples().addInsert(rightTuple); } } leftTuple.clearStaged(); leftTuple = next; } for (LeftTuple leftTuple = srcTuples.getDeleteFirst(); leftTuple != null; ) { LeftTuple next = leftTuple.getStagedNext(); RightTuple rightTuple = (RightTuple) leftTuple.getObject(); RightTupleSets rightTuples = bm.getStagedRightTuples(); switch (rightTuple.getStagedType()) { case LeftTuple.INSERT: { rightTuples.removeInsert(rightTuple); break; } case LeftTuple.UPDATE: { rightTuples.removeUpdate(rightTuple); break; } } rightTuples.addDelete(rightTuple); if (bns != null) { // Add peered RightTuples, they are attached to FH - unlink LeftTuples that has a peer ref for (int i = 0; i < length; i++) { rightTuple = rightTuple.getHandleNext(); rightTuples = bms[i].getStagedRightTuples(); switch (rightTuple.getStagedType()) { case LeftTuple.INSERT: { rightTuples.removeInsert(rightTuple); break; } case LeftTuple.UPDATE: { rightTuples.removeUpdate(rightTuple); break; } } rightTuples.addDelete(rightTuple); } } leftTuple.clearStaged(); leftTuple = next; } for (LeftTuple leftTuple = srcTuples.getUpdateFirst(); leftTuple != null; ) { LeftTuple next = leftTuple.getStagedNext(); RightTuple rightTuple = (RightTuple) leftTuple.getObject(); RightTupleSets rightTuples = bm.getStagedRightTuples(); switch (rightTuple.getStagedType()) { case LeftTuple.INSERT: { rightTuples.removeInsert(rightTuple); break; } case LeftTuple.UPDATE: { rightTuples.removeUpdate(rightTuple); break; } } rightTuples.addUpdate(rightTuple); if (bns != null) { // Add peered RightTuples, they are attached to FH - unlink LeftTuples that has a peer ref for (int i = 0; i < length; i++) { rightTuple = rightTuple.getHandleNext(); rightTuples = bms[i].getStagedRightTuples(); switch (rightTuple.getStagedType()) { case LeftTuple.INSERT: { rightTuples.removeInsert(rightTuple); break; } case LeftTuple.UPDATE: { rightTuples.removeUpdate(rightTuple); break; } } rightTuples.addUpdate(rightTuple); } } leftTuple.clearStaged(); leftTuple = next; } srcTuples.resetAll(); }
public LeftTuple createPeer(LeftTuple original) { JoinNodeLeftTuple peer = new JoinNodeLeftTuple(); peer.initPeer((BaseLeftTuple) original, this); original.setPeer(peer); return peer; }
public static void dpUpdatesExistentialReorderRightMemory( BetaMemory bm, BetaNode betaNode, RightTupleSets srcRightTuples) { RightTupleMemory rtm = bm.getRightTupleMemory(); boolean resumeFromCurrent = !(betaNode.isIndexedUnificationJoin() || rtm.getIndexType().isComparison()); // remove all the staged rightTuples from the memory before to readd them all // this is to avoid split bucket when an updated rightTuple hasn't been moved yet // and so it is the first entry in the wrong bucket for (RightTuple rightTuple = srcRightTuples.getUpdateFirst(); rightTuple != null; ) { RightTuple next = rightTuple.getStagedNext(); if (rightTuple.getMemory() != null) { rightTuple.setTempRightTupleMemory(rightTuple.getMemory()); if (resumeFromCurrent) { if (rightTuple.getBlocked() != null) { // look for a non-staged right tuple first forward ... RightTuple tempRightTuple = (RightTuple) rightTuple.getNext(); while (tempRightTuple != null && tempRightTuple.getStagedType() != LeftTuple.NONE) { // next cannot be an updated or deleted rightTuple tempRightTuple = (RightTuple) tempRightTuple.getNext(); } // ... and if cannot find one try backward if (tempRightTuple == null) { tempRightTuple = (RightTuple) rightTuple.getPrevious(); while (tempRightTuple != null && tempRightTuple.getStagedType() != LeftTuple.NONE) { // next cannot be an updated or deleted rightTuple tempRightTuple = (RightTuple) tempRightTuple.getPrevious(); } } rightTuple.setTempNextRightTuple(tempRightTuple); } } rightTuple.setTempBlocked(rightTuple.getBlocked()); rightTuple.nullBlocked(); rtm.remove(rightTuple); } rightTuple = next; } for (RightTuple rightTuple = srcRightTuples.getUpdateFirst(); rightTuple != null; ) { RightTuple next = rightTuple.getStagedNext(); if (rightTuple.getTempRightTupleMemory() != null) { rtm.add(rightTuple); if (resumeFromCurrent) { RightTuple tempRightTuple = rightTuple.getTempNextRightTuple(); if (rightTuple.getBlocked() != null && tempRightTuple == null && rightTuple.getMemory() == rightTuple.getTempRightTupleMemory()) { // the next RightTuple was null, but current RightTuple was added back into the same // bucket, so reset as root blocker to re-match can be attempted rightTuple.setTempNextRightTuple(rightTuple); } } for (LeftTuple childLeftTuple = rightTuple.getFirstChild(); childLeftTuple != null; ) { LeftTuple childNext = childLeftTuple.getRightParentNext(); childLeftTuple.reAddLeft(); childLeftTuple = childNext; } } rightTuple = next; } }