public LeftTuple propagateModifyChildLeftTuple( LeftTuple childLeftTuple, RightTuple parentRightTuple, PropagationContext context, InternalWorkingMemory workingMemory, boolean tupleMemoryEnabled) { // iterate to find all child tuples for the shared node while (childLeftTuple != null && childLeftTuple.getRightParent() == parentRightTuple) { // 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.getLeftParentNext(); temp.reAddRight(); } return childLeftTuple; }
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 }