Пример #1
0
  /**
   * 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);

    FastIterator it = memory.getRightTupleMemory().fastIterator();
    final RightTuple rootBlocker = (RightTuple) it.next(rightTuple);

    memory.getRightTupleMemory().remove(rightTuple);

    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);

      // we know that older tuples have been checked so continue previously
      for (RightTuple newBlocker = rootBlocker;
          newBlocker != null;
          newBlocker = (RightTuple) it.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());
  }
Пример #2
0
  protected void doRemove(
      final RuleRemovalContext context,
      final ReteooBuilder builder,
      final BaseNode node,
      final InternalWorkingMemory[] workingMemories) {
    if (!node.isInUse()) {
      removeTupleSink((LeftTupleSink) node);
    }
    if (!this.isInUse() || context.getCleanupAdapter() != null) {
      for (InternalWorkingMemory workingMemory : workingMemories) {
        BetaMemory memory;
        Object object = workingMemory.getNodeMemory(this);

        // handle special cases for Accumulate to make sure they tidy up their specific data
        // like destroying the local FactHandles
        if (object instanceof AccumulateMemory) {
          memory = ((AccumulateMemory) object).betaMemory;
        } else {
          memory = (BetaMemory) object;
        }

        FastIterator it = memory.getLeftTupleMemory().fullFastIterator();
        for (LeftTuple leftTuple = getFirstLeftTuple(memory.getLeftTupleMemory(), it);
            leftTuple != null; ) {
          LeftTuple tmp = (LeftTuple) it.next(leftTuple);
          if (context.getCleanupAdapter() != null) {
            LeftTuple child;
            while ((child = leftTuple.getFirstChild()) != null) {
              if (child.getLeftTupleSink() == this) {
                // this is a match tuple on collect and accumulate nodes, so just unlink it
                child.unlinkFromLeftParent();
                child.unlinkFromRightParent();
              } else {
                // the cleanupAdapter will take care of the unlinking
                context.getCleanupAdapter().cleanUp(child, workingMemory);
              }
            }
          }
          memory.getLeftTupleMemory().remove(leftTuple);
          leftTuple.unlinkFromLeftParent();
          leftTuple.unlinkFromRightParent();
          leftTuple = tmp;
        }

        // handle special cases for Accumulate to make sure they tidy up their specific data
        // like destroying the local FactHandles
        if (object instanceof AccumulateMemory) {
          ((AccumulateNode) this).doRemove(workingMemory, (AccumulateMemory) object);
        }

        if (!this.isInUse()) {
          it = memory.getRightTupleMemory().fullFastIterator();
          for (RightTuple rightTuple = getFirstRightTuple(memory.getRightTupleMemory(), it);
              rightTuple != null; ) {
            RightTuple tmp = (RightTuple) it.next(rightTuple);
            if (rightTuple.getBlocked() != null) {
              // special case for a not, so unlink left tuple from here, as they aren't in the left
              // memory
              for (LeftTuple leftTuple = rightTuple.getBlocked(); leftTuple != null; ) {
                LeftTuple temp = leftTuple.getBlockedNext();

                leftTuple.setBlocker(null);
                leftTuple.setBlockedPrevious(null);
                leftTuple.setBlockedNext(null);
                leftTuple.unlinkFromLeftParent();
                leftTuple = temp;
              }
            }
            memory.getRightTupleMemory().remove(rightTuple);
            rightTuple.unlinkFromRightParent();
            rightTuple = tmp;
          }
          workingMemory.clearNodeMemory(this);
        }
      }
      context.setCleanupAdapter(null);
    }
    this.rightInput.remove(context, builder, this, workingMemories);
    this.leftInput.remove(context, builder, this, workingMemories);
  }
Пример #3
0
  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;
    }

    if (firstBlocked != null) {
      // now process existing blocks, we only process existing and not new from above loop
      FastIterator rightIt = getRightIterator(memory.getRightTupleMemory());
      RightTuple rootBlocker = (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
      memory.getRightTupleMemory().removeAdd(rightTuple);

      if (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);

        // 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
      memory.getRightTupleMemory().removeAdd(rightTuple);
    }

    this.constraints.resetFactHandle(memory.getContext());
    this.constraints.resetTuple(memory.getContext());
  }
Пример #4
0
  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, context, 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);
          leftTuple.setBlocker(null);
          leftTuple.setBlockedPrevious(null);
          leftTuple.setBlockedNext(null);
          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);
        leftTuple.setBlocker(null);
        leftTuple.setBlockedPrevious(null);
        leftTuple.setBlockedNext(null);
      }

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