예제 #1
0
 public static LeftTuple getFirstLeftTuple(final LeftTupleMemory memory, final FastIterator it) {
   if (!memory.isIndexed()) {
     return memory.getFirst(null);
   } else {
     return (LeftTuple) it.next(null);
   }
 }
예제 #2
0
 public FastIterator getLeftIterator(LeftTupleMemory memory) {
   if (!this.indexedUnificationJoin) {
     return memory.fastIterator();
   } else {
     return memory.fullFastIterator();
   }
 }
예제 #3
0
  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;
    }
  }
예제 #4
0
  /**
   * Test method for {@link
   * org.drools.reteoo.AccumulateNode#assertLeftTuple(org.drools.reteoo.LeftTupleImpl,
   * org.drools.spi.PropagationContext, org.drools.reteoo.ReteooWorkingMemory)}.
   */
  @Test
  public void testAssertTupleWithObjects() {
    final DefaultFactHandle f0 =
        (DefaultFactHandle)
            this.workingMemory
                .getFactHandleFactory()
                .newFactHandle("cheese", null, null, workingMemory);
    final DefaultFactHandle f1 =
        (DefaultFactHandle)
            this.workingMemory
                .getFactHandleFactory()
                .newFactHandle("other cheese", null, null, workingMemory);

    final LeftTupleImpl tuple0 = new LeftTupleImpl(f0, null, true);

    this.node.assertObject(f0, this.context, this.workingMemory);
    this.node.assertObject(f1, this.context, this.workingMemory);

    // assert tuple, should add one to left memory
    this.node.assertLeftTuple(tuple0, this.context, this.workingMemory);
    // check memories
    assertEquals(1, this.memory.getLeftTupleMemory().size());
    assertEquals(2, this.memory.getRightTupleMemory().size());
    assertEquals(
        "Wrong number of elements in matching objects list ",
        2,
        this.accumulator.getMatchingObjects().size());

    // assert tuple, should add left memory
    final LeftTupleImpl tuple1 = new LeftTupleImpl(f1, null, true);
    this.node.assertLeftTuple(tuple1, this.context, this.workingMemory);
    assertEquals(2, this.memory.getLeftTupleMemory().size());
    assertEquals(
        "Wrong number of elements in matching objects list ",
        2,
        this.accumulator.getMatchingObjects().size());

    final LeftTupleMemory memory = this.memory.getLeftTupleMemory();
    assertTrue(memory.contains(tuple0));
    assertTrue(memory.contains(tuple1));

    assertEquals("Two tuples should have been propagated", 2, this.sink.getAsserted().size());
  }
예제 #5
0
 public LeftTuple getFirstLeftTuple(
     final RightTuple rightTuple,
     final LeftTupleMemory memory,
     final PropagationContext context,
     final FastIterator it) {
   if (!this.indexedUnificationJoin) {
     return memory.getFirst(rightTuple);
   } else {
     return (LeftTuple) it.next(null);
   }
 }
예제 #6
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());
  }
예제 #7
0
  public void modifyRightTuple(
      RightTuple rightTuple, PropagationContext context, InternalWorkingMemory workingMemory) {
    final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this);

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

    if (bm.getLeftTupleMemory() == null || bm.getLeftTupleMemory().size() == 0) {
      // do nothing here, as we know there are no left tuples at this stage in sequential mode.
      return;
    }

    LeftTuple childLeftTuple = rightTuple.firstChild;

    LeftTupleMemory leftMemory = bm.getLeftTupleMemory();

    FastIterator leftIt = getLeftIterator(leftMemory);

    LeftTuple leftTuple = getFirstLeftTuple(rightTuple, leftMemory, context, leftIt);

    this.constraints.updateFromFactHandle(
        bm.getContext(), workingMemory, rightTuple.getFactHandle());

    // first check our index (for indexed nodes only) hasn't changed and we are returning the same
    // bucket
    // We assume a bucket change if leftTuple == null
    if (childLeftTuple != null
        && leftMemory.isIndexed()
        && !leftIt.isFullIterator()
        && (leftTuple == null
            || (leftTuple.getMemory() != childLeftTuple.getLeftParent().getMemory()))) {
      // our index has changed, so delete all the previous matches
      removePreviousMatchesForRightTuple(
          rightTuple, context, workingMemory, memory, childLeftTuple);
      childLeftTuple = null; // null so the next check will attempt matches for new bucket
    }

    // if LeftTupleMemory is empty, there are no matches to modify
    if (leftTuple != 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 (; leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) {
          if (this.constraints.isAllowedCachedRight(bm.getContext(), leftTuple)) {
            final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
            // add a new match
            addMatch(leftTuple, rightTuple, null, null, workingMemory, memory, accctx, true);
            if (accctx.getAction() == null) {
              // schedule a test to evaluate the constraints, this is an optimisation for sub
              // networks
              // We set Source to LEFT, even though this is a right propagation, because it might
              // end up
              // doing multiple right propagations anyway
              EvaluateResultConstraints action =
                  new EvaluateResultConstraints(
                      ActivitySource.LEFT,
                      leftTuple,
                      context,
                      workingMemory,
                      memory,
                      accctx,
                      true,
                      this);
              accctx.setAction(action);
              context.addInsertAction(action);
            }
          }
        }
      } else {
        // in the same bucket, so iterate and compare
        for (; leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) {
          if (this.constraints.isAllowedCachedRight(bm.getContext(), leftTuple)) {
            final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
            LeftTuple temp = null;
            if (childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple) {
              temp = childLeftTuple.getRightParentNext();
              // we must re-add this to ensure deterministic iteration
              childLeftTuple.reAddLeft();
              removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, true);
              childLeftTuple = temp;
            }
            // add a new match
            addMatch(
                leftTuple, rightTuple, null, childLeftTuple, workingMemory, memory, accctx, true);
            if (temp != null) {
              childLeftTuple = temp;
            }
            if (accctx.getAction() == null) {
              // schedule a test to evaluate the constraints, this is an optimisation for sub
              // networks
              // We set Source to LEFT, even though this is a right propagation, because it might
              // end up
              // doing multiple right propagations anyway
              EvaluateResultConstraints action =
                  new EvaluateResultConstraints(
                      ActivitySource.LEFT,
                      leftTuple,
                      context,
                      workingMemory,
                      memory,
                      accctx,
                      true,
                      this);
              accctx.setAction(action);
              context.addInsertAction(action);
            }
          } else if (childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple) {

            LeftTuple temp = childLeftTuple.getRightParentNext();
            final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
            // remove the match
            removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, true);
            if (accctx.getAction() == null) {
              // schedule a test to evaluate the constraints, this is an optimisation for sub
              // networks
              // We set Source to LEFT, even though this is a right propagation, because it might
              // end up
              // doing multiple right propagations anyway
              EvaluateResultConstraints action =
                  new EvaluateResultConstraints(
                      ActivitySource.LEFT,
                      leftTuple,
                      context,
                      workingMemory,
                      memory,
                      accctx,
                      true,
                      this);
              accctx.setAction(action);
              context.addInsertAction(action);
            }

            childLeftTuple = temp;
          }
          // else do nothing, was false before and false now.
        }
      }
    }

    this.constraints.resetFactHandle(bm.getContext());
  }