예제 #1
0
  @SuppressWarnings("unchecked")
  public RightTuple createRightTuple(
      final LeftTuple leftTuple,
      final PropagationContext context,
      final InternalWorkingMemory workingMemory,
      final Object object) {
    InternalFactHandle handle;
    ProtobufMessages.FactHandle _handle = null;
    if (objectTypeConf == null) {
      // use default entry point and object class. Notice that at this point object is assignable to
      // resultClass
      objectTypeConf =
          new ClassObjectTypeConf(
              workingMemory.getEntryPoint(), resultClass, workingMemory.getKnowledgeBase());
    }
    if (context.getReaderContext() != null) {
      Map<ProtobufInputMarshaller.TupleKey, List<FactHandle>> map =
          (Map<ProtobufInputMarshaller.TupleKey, List<ProtobufMessages.FactHandle>>)
              context.getReaderContext().nodeMemories.get(getId());
      if (map != null) {
        TupleKey key = PersisterHelper.createTupleKey(leftTuple);
        List<FactHandle> list = map.get(key);
        if (list != null && !list.isEmpty()) {
          // it is a linked list, so the operation is fairly efficient
          _handle = ((java.util.LinkedList<ProtobufMessages.FactHandle>) list).removeFirst();
          if (list.isEmpty()) {
            map.remove(key);
          }
        }
      }
    }
    if (_handle != null) {
      // create a handle with the given id
      handle =
          workingMemory
              .getFactHandleFactory()
              .newFactHandle(
                  _handle.getId(),
                  object,
                  _handle.getRecency(),
                  objectTypeConf,
                  workingMemory,
                  null);
    } else {
      handle =
          workingMemory
              .getFactHandleFactory()
              .newFactHandle(object, objectTypeConf, workingMemory, null);
    }

    return newRightTuple(handle, null);
  }
예제 #2
0
    public void execute(InternalWorkingMemory workingMemory) {

      final PropagationContext context =
          new PropagationContextImpl(
              workingMemory.getNextPropagationIdCounter(),
              PropagationContext.INSERTION,
              this.ruleOrigin,
              this.leftTuple,
              this.factHandle);
      ReteooRuleBase ruleBase = (ReteooRuleBase) workingMemory.getRuleBase();
      ruleBase.assertObject(this.factHandle, this.factHandle.getObject(), context, workingMemory);
      context.evaluateActionQueue(workingMemory);
    }
예제 #3
0
  public void closeLiveQuery(final InternalFactHandle factHandle) {

    try {
      startOperation();
      this.ruleBase.readLock();
      this.lock.lock();

      final PropagationContext pCtx =
          new PropagationContextImpl(
              getNextPropagationIdCounter(),
              PropagationContext.INSERTION,
              null,
              null,
              factHandle,
              getEntryPoint());

      if (this.ruleBase.getConfiguration().isPhreakEnabled()) {
        LeftInputAdapterNode lian =
            (LeftInputAdapterNode)
                factHandle.getFirstLeftTuple().getLeftTupleSink().getLeftTupleSource();
        LiaNodeMemory lmem = (LiaNodeMemory) getNodeMemory((MemoryFactory) lian);
        SegmentMemory lsmem = lmem.getSegmentMemory();

        LeftTuple childLeftTuple =
            factHandle.getFirstLeftTuple(); // there is only one, all other LTs are peers
        LeftInputAdapterNode.doDeleteObject(
            childLeftTuple, childLeftTuple.getPropagationContext(), lsmem, this, lian, false, lmem);

        List<PathMemory> rmems = lmem.getSegmentMemory().getPathMemories();
        for (int i = 0, length = rmems.size(); i < length; i++) {
          PathMemory rm = rmems.get(i);

          RuleNetworkEvaluatorActivation evaluator =
              agenda.createRuleNetworkEvaluatorActivation(
                  Integer.MAX_VALUE, rm, (TerminalNode) rm.getNetworkNode());
          evaluator.evaluateNetwork(this, 0, -1);
        }
      } else {
        getEntryPointNode().retractQuery(factHandle, pCtx, this);

        pCtx.evaluateActionQueue(this);
      }

      getFactHandleFactory().destroyFactHandle(factHandle);

    } finally {
      this.lock.unlock();
      this.ruleBase.readUnlock();
      endOperation();
    }
  }
예제 #4
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);
    }
  }
예제 #5
0
파일: NotNode.java 프로젝트: JaneVan/drools
  public void retractRightTuple(
      final RightTuple rightTuple,
      final PropagationContext pctx,
      final InternalWorkingMemory workingMemory) {
    final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this);
    rightTuple.setPropagationContext(pctx);
    RightTupleSets stagedRightTuples = memory.getStagedRightTuples();
    boolean stagedDeleteWasEmpty = false;
    if (streamMode) {
      stagedDeleteWasEmpty = memory.getSegmentMemory().getTupleQueue().isEmpty();
      memory
          .getSegmentMemory()
          .getTupleQueue()
          .add(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType()));
      // log.trace( "NotNode delete queue={} size={} lt={}", System.identityHashCode(
      // memory.getSegmentMemory().getTupleQueue() ),
      // memory.getSegmentMemory().getTupleQueue().size(), rightTuple );
    } else {
      stagedDeleteWasEmpty = stagedRightTuples.addDelete(rightTuple);
    }

    if (memory.getAndDecCounter() == 1 && isEmptyBetaConstraints()) {
      // NotNodes can only be unlinked, if they have no variable constraints
      memory.linkNode(workingMemory);
    } else if (stagedDeleteWasEmpty) {
      // nothing staged before, notify rule, so it can evaluate network
      memory.setNodeDirty(workingMemory);
    }
  }
예제 #6
0
파일: NotNode.java 프로젝트: JaneVan/drools
  public void assertObject(
      final InternalFactHandle factHandle,
      final PropagationContext pctx,
      final InternalWorkingMemory wm) {
    final BetaMemory memory = (BetaMemory) getBetaMemoryFromRightInput(this, wm);

    RightTuple rightTuple = createRightTuple(factHandle, this, pctx);

    rightTuple.setPropagationContext(pctx);

    // strangely we link here, this is actually just to force a network evaluation
    // The assert is then processed and the rule unlinks then.
    // This is because we need the first RightTuple to link with it's blocked
    boolean stagedInsertWasEmpty = false;
    if (streamMode) {
      stagedInsertWasEmpty = memory.getSegmentMemory().getTupleQueue().isEmpty();
      memory
          .getSegmentMemory()
          .getTupleQueue()
          .add(new RightTupleEntry(rightTuple, pctx, memory, pctx.getType()));
      // log.trace( "NotNode insert queue={} size={} lt={}", System.identityHashCode(
      // memory.getSegmentMemory().getTupleQueue() ),
      // memory.getSegmentMemory().getTupleQueue().size(), rightTuple );
    } else {
      stagedInsertWasEmpty = memory.getStagedRightTuples().addInsert(rightTuple);
    }

    if (memory.getAndIncCounter() == 0 && isEmptyBetaConstraints()) {
      // NotNodes can only be unlinked, if they have no variable constraints
      memory.linkNode(wm);
    } else if (stagedInsertWasEmpty) {
      // nothing staged before, notify rule, so it can evaluate network
      memory.setNodeDirty(wm);
    }
  }
 @SuppressWarnings("unchecked")
 public InternalFactHandle createFactHandle(
     final LeftTuple leftTuple,
     final PropagationContext context,
     final InternalWorkingMemory workingMemory) {
   InternalFactHandle handle;
   ProtobufMessages.FactHandle _handle = null;
   if (context.getReaderContext() != null) {
     Map<ProtobufInputMarshaller.TupleKey, ProtobufMessages.FactHandle> map =
         (Map<ProtobufInputMarshaller.TupleKey, ProtobufMessages.FactHandle>)
             context.getReaderContext().nodeMemories.get(getId());
     if (map != null) {
       _handle = map.get(PersisterHelper.createTupleKey(leftTuple));
     }
   }
   if (_handle != null) {
     // create a handle with the given id
     handle =
         workingMemory
             .getFactHandleFactory()
             .newFactHandle(
                 _handle.getId(),
                 leftTuple,
                 _handle.getRecency(),
                 workingMemory
                     .getObjectTypeConfigurationRegistry()
                     .getObjectTypeConf(context.getEntryPoint(), leftTuple),
                 workingMemory,
                 null); // so far, result is not an event
   } else {
     handle =
         workingMemory
             .getFactHandleFactory()
             .newFactHandle(
                 leftTuple,
                 workingMemory
                     .getObjectTypeConfigurationRegistry()
                     .getObjectTypeConf(context.getEntryPoint(), leftTuple),
                 workingMemory,
                 null); // so far, result is not an event
   }
   return handle;
 }
예제 #8
0
  private static void removeQueuedTupleEntry(TupleEntryQueue tupleQueue) {
    TupleEntry tupleEntry = tupleQueue.remove();
    PropagationContext originalPctx = tupleEntry.getPropagationContext();

    while (true) {
      processStreamTupleEntry(tupleQueue, tupleEntry);
      if (tupleQueue.isEmpty()) {
        return;
      }
      tupleEntry = tupleQueue.peek();
      PropagationContext pctx = tupleEntry.getPropagationContext();

      // repeat if either the pctx number is the same, or the event time is the same or before
      if (pctx.getPropagationNumber() != originalPctx.getPropagationNumber()) {
        break;
      }
      tupleEntry = tupleQueue.remove();
    }
  }
예제 #9
0
  public void cancelActivation(
      final LeftTuple leftTuple,
      final PropagationContext context,
      final InternalWorkingMemory workingMemory,
      final Activation activation,
      final TerminalNode rtn) {
    AgendaItem item = (AgendaItem) activation;
    item.removeAllBlockersAndBlocked(this);

    if (isDeclarativeAgenda() && activation.getFactHandle() == null) {
      // This a control rule activation, nothing to do except update counters. As control rules are
      // not in agenda-groups etc.
      return;
    } else {
      // we are retracting an actual Activation, so also remove it and it's handle from the WM.
      removeActivation(item);
    }

    if (activation.isQueued()) {
      // on fact expiration, we don't remove the activation, but let it fire
      if (context.getType() == PropagationContext.EXPIRATION
          && context.getFactHandleOrigin() != null) {
      } else {
        activation.remove();

        if (activation.getActivationGroupNode() != null) {
          activation.getActivationGroupNode().getActivationGroup().removeActivation(activation);
        }
        leftTuple.decreaseActivationCountForEvents();

        ((EventSupport) workingMemory)
            .getAgendaEventSupport()
            .fireActivationCancelled(activation, workingMemory, MatchCancelledCause.WME_MODIFY);
      }
    }

    if (item.getActivationUnMatchListener() != null) {
      item.getActivationUnMatchListener().unMatch(workingMemory.getKnowledgeRuntime(), item);
    }

    TruthMaintenanceSystemHelper.removeLogicalDependencies(activation, context, rtn.getRule());
  }
예제 #10
0
파일: Rete.java 프로젝트: tkobayas/drools
 /**
  * This is the entry point into the network for all asserted Facts. Iterates a cache of matching
  * <code>ObjectTypdeNode</code>s asserting the Fact. If the cache does not exist it first iteraes
  * and builds the cache.
  *
  * @param factHandle The FactHandle of the fact to assert
  * @param context The <code>PropagationContext</code> of the <code>WorkingMemory</code> action
  * @param workingMemory The working memory session.
  */
 public void assertObject(
     final InternalFactHandle factHandle,
     final PropagationContext context,
     final InternalWorkingMemory workingMemory) {
   EntryPointId entryPoint = context.getEntryPoint();
   EntryPointNode node = this.entryPoints.get(entryPoint);
   ObjectTypeConf typeConf =
       ((InternalWorkingMemoryEntryPoint)
               workingMemory.getWorkingMemoryEntryPoint(entryPoint.getEntryPointId()))
           .getObjectTypeConfigurationRegistry()
           .getObjectTypeConf(entryPoint, factHandle.getObject());
   node.assertObject(factHandle, context, typeConf, workingMemory);
 }
예제 #11
0
  public static void doModifyLeftTuple(
      InternalFactHandle factHandle,
      ModifyPreviousTuples modifyPreviousTuples,
      PropagationContext context,
      InternalWorkingMemory workingMemory,
      LeftTupleSink sink,
      ObjectTypeNode.Id leftInputOtnId,
      BitMask leftInferredMask) {
    LeftTuple leftTuple = modifyPreviousTuples.peekLeftTuple();
    while (leftTuple != null
        && leftTuple.getLeftTupleSink().getLeftInputOtnId() != null
        && leftTuple.getLeftTupleSink().getLeftInputOtnId().before(leftInputOtnId)) {
      modifyPreviousTuples.removeLeftTuple();

      // we skipped this node, due to alpha hashing, so retract now
      ((LeftInputAdapterNode) leftTuple.getLeftTupleSink().getLeftTupleSource())
          .retractLeftTuple(leftTuple, context, workingMemory);

      leftTuple = modifyPreviousTuples.peekLeftTuple();
    }

    if (leftTuple != null
        && leftTuple.getLeftTupleSink().getLeftInputOtnId() != null
        && leftTuple.getLeftTupleSink().getLeftInputOtnId().equals(leftInputOtnId)) {
      modifyPreviousTuples.removeLeftTuple();
      leftTuple.reAdd();
      if (context.getModificationMask().intersects(leftInferredMask)) {
        // LeftTuple previously existed, so continue as modify, unless it's currently staged
        sink.modifyLeftTuple(leftTuple, context, workingMemory);
      }
    } else {
      if (context.getModificationMask().intersects(leftInferredMask)) {
        // LeftTuple does not exist, so create and continue as assert
        LeftTuple newLeftTuple = sink.createLeftTuple(factHandle, sink, true);

        sink.assertLeftTuple(newLeftTuple, context, workingMemory);
      }
    }
  }
예제 #12
0
    public void execute(InternalWorkingMemory workingMemory) {
      if (this.factHandle.isValid()) {
        // if the fact is still in the working memory (since it may have been previously retracted
        // already
        final PropagationContext context =
            new PropagationContextImpl(
                workingMemory.getNextPropagationIdCounter(),
                PropagationContext.EXPIRATION,
                null,
                null,
                this.factHandle);
        ((EventFactHandle) factHandle).setExpired(true);
        this.node.retractObject(factHandle, context, workingMemory);

        context.evaluateActionQueue(workingMemory);
        // if no activations for this expired event
        if (((EventFactHandle) factHandle).getActivationsCount() == 0) {
          // remove it from the object store and clean up resources
          ((EventFactHandle) factHandle).getEntryPoint().retract(factHandle);
        }
        context.evaluateActionQueue(workingMemory);
      }
    }
예제 #13
0
    public void execute(InternalWorkingMemory workingMemory) {
      leftTuple.setLeftTupleSink(this.node);
      if (leftTuple.getFirstChild() == null) {
        this.node.assertLeftTuple(leftTuple, context, workingMemory);
      } else {
        if (retract) {
          this.node
              .getSinkPropagator()
              .propagateRetractLeftTuple(leftTuple, context, workingMemory);
        } else {
          this.node
              .getSinkPropagator()
              .propagateModifyChildLeftTuple(leftTuple, context, workingMemory, true);
        }
      }

      if (leftTuple.getLeftParent() == null) {
        // It's not an open query, as we aren't recording parent chains, so we need to clear out
        // right memory

        Object node = workingMemory.getNodeMemory(this.node);

        RightTupleMemory rightMemory = null;
        if (node instanceof BetaMemory) {
          rightMemory = ((BetaMemory) node).getRightTupleMemory();
        } else if (node instanceof AccumulateMemory) {
          rightMemory = ((AccumulateMemory) node).betaMemory.getRightTupleMemory();
        }

        final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
        TupleStartEqualsConstraintContextEntry contextEntry =
            new TupleStartEqualsConstraintContextEntry();
        contextEntry.updateFromTuple(workingMemory, leftTuple);

        FastIterator rightIt = rightMemory.fastIterator();
        RightTuple temp = null;
        for (RightTuple rightTuple =
                rightMemory.getFirst(
                    leftTuple, (InternalFactHandle) context.getFactHandle(), rightIt);
            rightTuple != null; ) {
          temp = (RightTuple) rightIt.next(rightTuple);

          if (constraint.isAllowedCachedLeft(contextEntry, rightTuple.getFactHandle())) {
            rightMemory.remove(rightTuple);
          }
          rightTuple = temp;
        }
      }
    }
예제 #14
0
  private BaseNode[] evalQuery(
      String queryName,
      DroolsQuery queryObject,
      InternalFactHandle handle,
      PropagationContext pCtx) {
    BaseNode[] tnodes = (BaseNode[]) ruleBase.getReteooBuilder().getTerminalNodes(queryName);
    if (this.ruleBase.getConfiguration().isPhreakEnabled()) {
      if (tnodes == null) {
        throw new RuntimeException("Query '" + queryName + "' does not exist");
      }

      QueryTerminalNode tnode = (QueryTerminalNode) tnodes[0];
      LeftTupleSource lts = tnode.getLeftTupleSource();
      while (lts.getType() != NodeTypeEnums.LeftInputAdapterNode) {
        lts = lts.getLeftTupleSource();
      }
      LeftInputAdapterNode lian = (LeftInputAdapterNode) lts;
      LiaNodeMemory lmem = (LiaNodeMemory) getNodeMemory((MemoryFactory) lts);
      SegmentMemory lsmem = lmem.getSegmentMemory();
      if (lsmem == null) {
        lsmem = SegmentUtilities.createSegmentMemory(lts, this);
      }
      LeftInputAdapterNode.doInsertObject(
          handle, pCtx, lian, this, lmem, false, queryObject.isOpen());

      List<PathMemory> rmems = lmem.getSegmentMemory().getPathMemories();
      for (int i = 0, length = rmems.size(); i < length; i++) {
        PathMemory rm = rmems.get(i);

        RuleNetworkEvaluatorActivation evaluator =
            agenda.createRuleNetworkEvaluatorActivation(
                Integer.MAX_VALUE, rm, (TerminalNode) rm.getNetworkNode());
        evaluator.evaluateNetwork(this, 0, -1);
      }
    } else {
      // no need to call retract, as no leftmemory used.
      getEntryPointNode().assertQuery(handle, pCtx, this);

      pCtx.evaluateActionQueue(this);
    }
    return tnodes;
  }
예제 #15
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());
  }
예제 #16
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());
  }
예제 #17
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());
  }