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; } }
/** * 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); } }
/** * 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 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()); }