Example #1
0
  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;
    }
  }
Example #2
0
  /**
   * 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);
    }
  }
Example #3
0
  /**
   * 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());
  }
Example #4
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;
    }

    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());
  }
Example #5
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, (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());
  }
Example #6
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);
    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());
  }