public void doRightDeletes( NotNode notNode, LeftTupleSink sink, BetaMemory bm, InternalWorkingMemory wm, RightTupleSets srcRightTuples, LeftTupleSets trgLeftTuples) { LeftTupleMemory ltm = bm.getLeftTupleMemory(); RightTupleMemory rtm = bm.getRightTupleMemory(); ContextEntry[] contextEntry = bm.getContext(); BetaConstraints constraints = notNode.getRawConstraints(); for (RightTuple rightTuple = srcRightTuples.getDeleteFirst(); rightTuple != null; ) { RightTuple next = rightTuple.getStagedNext(); FastIterator it = notNode.getRightIterator(rtm); // assign now, so we can remove from memory before doing any possible propagations boolean useComparisonIndex = rtm.getIndexType().isComparison(); RightTuple rootBlocker = useComparisonIndex ? null : (RightTuple) it.next(rightTuple); if (rightTuple.getMemory() != null) { // it may have been staged and never actually added rtm.remove(rightTuple); } if (rightTuple.getBlocked() != null) { for (LeftTuple leftTuple = rightTuple.getBlocked(); leftTuple != null; ) { LeftTuple temp = leftTuple.getBlockedNext(); leftTuple.clearBlocker(); if (leftTuple.getStagedType() == LeftTuple.UPDATE) { // ignore, as it will get processed via left iteration. Children cannot be processed // twice leftTuple = temp; continue; } constraints.updateFromTuple(contextEntry, wm, leftTuple); if (useComparisonIndex) { rootBlocker = rtm.getFirst(leftTuple, null, it); } // we know that older tuples have been checked so continue next for (RightTuple newBlocker = rootBlocker; newBlocker != null; newBlocker = (RightTuple) it.next(newBlocker)) { if (constraints.isAllowedCachedLeft(contextEntry, newBlocker.getFactHandle())) { leftTuple.setBlocker(newBlocker); newBlocker.addBlocked(leftTuple); break; } } if (leftTuple.getBlocker() == null) { // was previous blocked and not in memory, so add ltm.add(leftTuple); trgLeftTuples.addInsert( sink.createLeftTuple(leftTuple, sink, rightTuple.getPropagationContext(), true)); } leftTuple = temp; } } rightTuple.nullBlocked(); rightTuple.clearStaged(); rightTuple = next; } constraints.resetTuple(contextEntry); }
public void doRightUpdates( NotNode notNode, LeftTupleSink sink, BetaMemory bm, InternalWorkingMemory wm, RightTupleSets srcRightTuples, LeftTupleSets trgLeftTuples, LeftTupleSets stagedLeftTuples) { LeftTupleMemory ltm = bm.getLeftTupleMemory(); RightTupleMemory rtm = bm.getRightTupleMemory(); ContextEntry[] contextEntry = bm.getContext(); BetaConstraints constraints = notNode.getRawConstraints(); boolean iterateFromStart = notNode.isIndexedUnificationJoin() || rtm.getIndexType().isComparison(); for (RightTuple rightTuple = srcRightTuples.getUpdateFirst(); rightTuple != null; ) { RightTuple next = rightTuple.getStagedNext(); PropagationContext context = rightTuple.getPropagationContext(); constraints.updateFromFactHandle(contextEntry, wm, rightTuple.getFactHandle()); FastIterator leftIt = notNode.getLeftIterator(ltm); LeftTuple firstLeftTuple = notNode.getFirstLeftTuple(rightTuple, ltm, context, leftIt); LeftTuple firstBlocked = rightTuple.getTempBlocked(); // 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); if (leftTuple.getStagedType() == LeftTuple.UPDATE) { // ignore, as it will get processed via left iteration. Children cannot be processed twice leftTuple = temp; continue; } // we know that only unblocked LeftTuples are still in the memory if (constraints.isAllowedCachedRight(contextEntry, leftTuple)) { leftTuple.setBlocker(rightTuple); rightTuple.addBlocked(leftTuple); // this is now blocked so remove from memory ltm.remove(leftTuple); LeftTuple childLeftTuple = leftTuple.getFirstChild(); if (childLeftTuple != null) { childLeftTuple.setPropagationContext(rightTuple.getPropagationContext()); RuleNetworkEvaluator.deleteRightChild(childLeftTuple, trgLeftTuples, stagedLeftTuples); } } leftTuple = temp; } if (firstBlocked != null) { RightTuple rootBlocker = rightTuple.getTempNextRightTuple(); if (rootBlocker == null) { iterateFromStart = true; } FastIterator rightIt = notNode.getRightIterator(rtm); // iterate all the existing previous blocked LeftTuples for (LeftTuple leftTuple = firstBlocked; leftTuple != null; ) { LeftTuple temp = leftTuple.getBlockedNext(); leftTuple.clearBlocker(); if (leftTuple.getStagedType() == LeftTuple.UPDATE) { // ignore, as it will get processed via left iteration. Children cannot be processed // twice // but need to add it back into list first leftTuple.setBlocker(rightTuple); rightTuple.addBlocked(leftTuple); leftTuple = temp; continue; } constraints.updateFromTuple(contextEntry, wm, leftTuple); if (iterateFromStart) { rootBlocker = notNode.getFirstRightTuple(leftTuple, rtm, null, rightIt); } // we know that older tuples have been checked so continue next for (RightTuple newBlocker = rootBlocker; newBlocker != null; newBlocker = (RightTuple) rightIt.next(newBlocker)) { // cannot select a RightTuple queued in the delete list // There may be UPDATE RightTuples too, but that's ok. They've already been re-added to // the correct bucket, safe to be reprocessed. if (leftTuple.getStagedType() != LeftTuple.DELETE && newBlocker.getStagedType() != LeftTuple.DELETE && constraints.isAllowedCachedLeft(contextEntry, newBlocker.getFactHandle())) { leftTuple.setBlocker(newBlocker); newBlocker.addBlocked(leftTuple); break; } } if (leftTuple.getBlocker() == null) { // was previous blocked and not in memory, so add ltm.add(leftTuple); // subclasses like ForallNotNode might override this propagation trgLeftTuples.addInsert( sink.createLeftTuple(leftTuple, sink, rightTuple.getPropagationContext(), true)); } leftTuple = temp; } } rightTuple.clearStaged(); rightTuple = next; } constraints.resetFactHandle(contextEntry); constraints.resetTuple(contextEntry); }