use of org.drools.core.reteoo.BetaMemory in project drools by kiegroup.
the class LeftLeftTupleIndexHashTableIteratorTest method test1.
@Test
public void test1() {
BetaNodeFieldConstraint constraint0 = getConstraint("d", Operator.EQUAL, "this", Foo.class);
BetaNodeFieldConstraint[] constraints = new BetaNodeFieldConstraint[] { constraint0 };
RuleBaseConfiguration config = new RuleBaseConfiguration();
BetaConstraints betaConstraints = null;
betaConstraints = new SingleBetaConstraints(constraints, config);
BetaMemory betaMemory = betaConstraints.createBetaMemory(config, NodeTypeEnums.JoinNode);
InternalKnowledgeBase kBase = (InternalKnowledgeBase) KnowledgeBaseFactory.newKnowledgeBase();
KieSession ss = kBase.newKieSession();
InternalFactHandle fh1 = (InternalFactHandle) ss.insert(new Foo("brie", 1));
InternalFactHandle fh2 = (InternalFactHandle) ss.insert(new Foo("brie", 1));
InternalFactHandle fh3 = (InternalFactHandle) ss.insert(new Foo("soda", 1));
InternalFactHandle fh4 = (InternalFactHandle) ss.insert(new Foo("soda", 1));
InternalFactHandle fh5 = (InternalFactHandle) ss.insert(new Foo("bread", 3));
InternalFactHandle fh6 = (InternalFactHandle) ss.insert(new Foo("bread", 3));
InternalFactHandle fh7 = (InternalFactHandle) ss.insert(new Foo("cream", 3));
InternalFactHandle fh8 = (InternalFactHandle) ss.insert(new Foo("gorda", 15));
InternalFactHandle fh9 = (InternalFactHandle) ss.insert(new Foo("beer", 16));
InternalFactHandle fh10 = (InternalFactHandle) ss.insert(new Foo("mars", 0));
InternalFactHandle fh11 = (InternalFactHandle) ss.insert(new Foo("snicker", 0));
InternalFactHandle fh12 = (InternalFactHandle) ss.insert(new Foo("snicker", 0));
InternalFactHandle fh13 = (InternalFactHandle) ss.insert(new Foo("snicker", 0));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh1, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh2, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh3, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh4, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh5, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh6, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh7, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh8, null, true));
betaMemory.getLeftTupleMemory().add(new LeftTupleImpl(fh9, null, true));
TupleIndexHashTable hashTable = (TupleIndexHashTable) betaMemory.getLeftTupleMemory();
// can't create a 0 hashCode, so forcing
TupleList leftTupleList = new TupleList();
leftTupleList.add(new LeftTupleImpl(fh10, null, true));
hashTable.getTable()[0] = leftTupleList;
leftTupleList = new TupleList();
leftTupleList.add(new LeftTupleImpl(fh11, null, true));
leftTupleList.add(new LeftTupleImpl(fh12, null, true));
leftTupleList.add(new LeftTupleImpl(fh13, null, true));
((TupleList) hashTable.getTable()[0]).setNext(leftTupleList);
Entry[] table = hashTable.getTable();
List list = new ArrayList();
for (int i = 0; i < table.length; i++) {
if (table[i] != null) {
List entries = new ArrayList();
entries.add(i);
Entry entry = table[i];
while (entry != null) {
entries.add(entry);
entry = entry.getNext();
}
list.add(entries.toArray());
}
}
assertEquals(5, list.size());
// This tests the hashcode index allocation. If the rehash function (or any other way hashcodes are computed) changes, these numbers will change.
Object[] entries = (Object[]) list.get(0);
assertEquals(0, entries[0]);
assertEquals(3, entries.length);
entries = (Object[]) list.get(1);
assertEquals(102, entries[0]);
assertEquals(2, entries.length);
entries = (Object[]) list.get(2);
assertEquals(103, entries[0]);
assertEquals(2, entries.length);
entries = (Object[]) list.get(3);
assertEquals(115, entries[0]);
assertEquals(3, entries.length);
entries = (Object[]) list.get(4);
assertEquals(117, entries[0]);
assertEquals(3, entries.length);
// System.out.println( entries );
list = new ArrayList<LeftTupleImpl>();
Iterator it = betaMemory.getLeftTupleMemory().iterator();
for (LeftTupleImpl leftTuple = (LeftTupleImpl) it.next(); leftTuple != null; leftTuple = (LeftTupleImpl) it.next()) {
list.add(leftTuple);
}
assertEquals(13, list.size());
}
use of org.drools.core.reteoo.BetaMemory in project drools by kiegroup.
the class ProtobufOutputMarshaller method writeRIANodeMemory.
private static ProtobufMessages.NodeMemory writeRIANodeMemory(final int nodeId, final BaseNode node, final NodeMemories memories) {
RightInputAdapterNode riaNode = (RightInputAdapterNode) node;
ObjectSink[] sinks = riaNode.getObjectSinkPropagator().getSinks();
BetaNode betaNode = (BetaNode) sinks[0];
Memory betaMemory = memories.peekNodeMemory(betaNode);
if (betaMemory == null) {
return null;
}
BetaMemory bm;
if (betaNode.getType() == NodeTypeEnums.AccumulateNode) {
bm = ((AccumulateMemory) betaMemory).getBetaMemory();
} else {
bm = (BetaMemory) betaMemory;
}
// for RIA nodes, we need to store the ID of the created handles
bm.getRightTupleMemory().iterator();
if (bm.getRightTupleMemory().size() > 0) {
ProtobufMessages.NodeMemory.RIANodeMemory.Builder _ria = ProtobufMessages.NodeMemory.RIANodeMemory.newBuilder();
final org.drools.core.util.Iterator it = bm.getRightTupleMemory().iterator();
// iterates over all propagated handles and assert them to the new sink
for (RightTuple entry = (RightTuple) it.next(); entry != null; entry = (RightTuple) it.next()) {
LeftTuple leftTuple = entry instanceof LeftTuple ? // with phreak the entry is always both a right and a left tuple
(LeftTuple) entry : // this is necessary only for reteoo
(LeftTuple) entry.getFactHandle().getObject();
InternalFactHandle handle = (InternalFactHandle) leftTuple.getFactHandle();
if (handle == null) {
continue;
}
FactHandle _handle = ProtobufMessages.FactHandle.newBuilder().setId(handle.getId()).setRecency(handle.getRecency()).build();
_ria.addContext(ProtobufMessages.NodeMemory.RIANodeMemory.RIAContext.newBuilder().setTuple(PersisterHelper.createTuple(leftTuple)).setResultHandle(_handle).build());
}
return ProtobufMessages.NodeMemory.newBuilder().setNodeId(nodeId).setNodeType(ProtobufMessages.NodeMemory.NodeType.RIA).setRia(_ria.build()).build();
}
return null;
}
use of org.drools.core.reteoo.BetaMemory in project drools by kiegroup.
the class AddRemoveRule method processLeftTuples.
/**
* Populates the SegmentMemory with staged LeftTuples. If the parent is not a Beta or From node, it iterates up to find the first node with memory. If necessary
* It traverses to the LiaNode's ObjectTypeNode. It then iterates the LeftTuple chains, where an existing LeftTuple is staged
* as delete. Or a new LeftTuple is created and staged as an insert.
*/
private static void processLeftTuples(LeftTupleNode node, InternalWorkingMemory wm, boolean insert, Rule rule) {
// *** if you make a fix here, it most likely needs to be in PhreakActivationIteratorToo ***
// Must iterate up until a node with memory is found, this can be followed to find the LeftTuples
// which provide the potential peer of the tuple being added or removed
Memory memory = wm.getNodeMemories().peekNodeMemory(node);
if (memory == null || memory.getSegmentMemory() == null) {
// segment has never been initialized, which means the rule(s) have never been linked and thus no Tuples to fix
return;
}
SegmentMemory sm = memory.getSegmentMemory();
while (NodeTypeEnums.LeftInputAdapterNode != node.getType()) {
if (NodeTypeEnums.isBetaNode(node)) {
BetaMemory bm;
if (NodeTypeEnums.AccumulateNode == node.getType()) {
AccumulateMemory am = (AccumulateMemory) memory;
bm = am.getBetaMemory();
FastIterator it = bm.getLeftTupleMemory().fullFastIterator();
Tuple lt = BetaNode.getFirstTuple(bm.getLeftTupleMemory(), it);
for (; lt != null; lt = (LeftTuple) it.next(lt)) {
AccumulateContext accctx = (AccumulateContext) lt.getContextObject();
visitChild(accctx.getResultLeftTuple(), insert, wm, rule);
}
} else if (NodeTypeEnums.ExistsNode == node.getType()) {
bm = (BetaMemory) wm.getNodeMemory((MemoryFactory) node);
// done off the RightTupleMemory, as exists only have unblocked tuples on the left side
FastIterator it = bm.getRightTupleMemory().fullFastIterator();
RightTuple rt = (RightTuple) BetaNode.getFirstTuple(bm.getRightTupleMemory(), it);
for (; rt != null; rt = (RightTuple) it.next(rt)) {
for (LeftTuple lt = rt.getBlocked(); lt != null; lt = lt.getBlockedNext()) {
visitChild(wm, insert, rule, it, lt);
}
}
} else {
bm = (BetaMemory) wm.getNodeMemory((MemoryFactory) node);
FastIterator it = bm.getLeftTupleMemory().fullFastIterator();
Tuple lt = BetaNode.getFirstTuple(bm.getLeftTupleMemory(), it);
visitChild(wm, insert, rule, it, lt);
}
return;
} else if (NodeTypeEnums.FromNode == node.getType()) {
FromMemory fm = (FromMemory) wm.getNodeMemory((MemoryFactory) node);
TupleMemory ltm = fm.getBetaMemory().getLeftTupleMemory();
FastIterator it = ltm.fullFastIterator();
for (LeftTuple lt = (LeftTuple) ltm.getFirst(null); lt != null; lt = (LeftTuple) it.next(lt)) {
visitChild(lt, insert, wm, rule);
}
return;
}
if (sm.getRootNode() == node) {
sm = wm.getNodeMemory((MemoryFactory<Memory>) node.getLeftTupleSource()).getSegmentMemory();
}
node = node.getLeftTupleSource();
}
// No beta or from nodes, so must retrieve LeftTuples from the LiaNode.
// This is done by scanning all the LeftTuples referenced from the FactHandles in the ObjectTypeNode
LeftInputAdapterNode lian = (LeftInputAdapterNode) node;
ObjectSource os = lian.getObjectSource();
while (os.getType() != NodeTypeEnums.ObjectTypeNode) {
os = os.getParentObjectSource();
}
ObjectTypeNode otn = (ObjectTypeNode) os;
final ObjectTypeNodeMemory omem = wm.getNodeMemory(otn);
if (omem == null) {
// no OTN memory yet, i.e. no inserted matching objects, so no Tuples to process
return;
}
Iterator<InternalFactHandle> it = omem.iterator();
while (it.hasNext()) {
InternalFactHandle fh = it.next();
fh.forEachLeftTuple(lt -> {
LeftTuple nextLt = lt.getHandleNext();
// Each lt is for a different lian, skip any lian not associated with the rule. Need to use lt parent (souce) not child to check the lian.
if (lt.getTupleSource().isAssociatedWith(rule)) {
visitChild(lt, insert, wm, rule);
if (lt.getHandlePrevious() != null) {
lt.getHandlePrevious().setHandleNext(nextLt);
}
if (nextLt != null) {
nextLt.setHandlePrevious(lt.getHandlePrevious());
}
}
});
}
}
use of org.drools.core.reteoo.BetaMemory in project drools by kiegroup.
the class AddRemoveRule method deleteRightInputData.
private static void deleteRightInputData(LeftTupleSink node, InternalWorkingMemory wm) {
if (wm.getNodeMemories().peekNodeMemory(node) != null) {
BetaNode bn = (BetaNode) node;
BetaMemory bm;
if (bn.getType() == NodeTypeEnums.AccumulateNode) {
bm = ((AccumulateMemory) wm.getNodeMemory(bn)).getBetaMemory();
} else {
bm = (BetaMemory) wm.getNodeMemory(bn);
}
TupleMemory rtm = bm.getRightTupleMemory();
FastIterator it = rtm.fullFastIterator();
for (Tuple rightTuple = BetaNode.getFirstTuple(rtm, it); rightTuple != null; ) {
Tuple next = (Tuple) it.next(rightTuple);
rtm.remove(rightTuple);
rightTuple.unlinkFromRightParent();
rightTuple = next;
}
if (!bm.getStagedRightTuples().isEmpty()) {
bm.setNodeDirtyWithoutNotify();
}
TupleSets<RightTuple> srcRightTuples = bm.getStagedRightTuples().takeAll();
unlinkRightTuples(srcRightTuples.getInsertFirst());
unlinkRightTuples(srcRightTuples.getUpdateFirst());
unlinkRightTuples(srcRightTuples.getDeleteFirst());
deleteFactsFromRightInput(bn, wm);
}
}
use of org.drools.core.reteoo.BetaMemory in project drools by kiegroup.
the class PhreakAccumulateNode method doRightUpdates.
public void doRightUpdates(AccumulateNode accNode, AccumulateMemory am, InternalWorkingMemory wm, TupleSets<RightTuple> srcRightTuples, TupleSets<LeftTuple> trgLeftTuples) {
BetaMemory bm = am.getBetaMemory();
TupleMemory ltm = bm.getLeftTupleMemory();
ContextEntry[] contextEntry = bm.getContext();
BetaConstraints constraints = accNode.getRawConstraints();
Accumulate accumulate = accNode.getAccumulate();
for (RightTuple rightTuple = srcRightTuples.getUpdateFirst(); rightTuple != null; ) {
RightTuple next = rightTuple.getStagedNext();
if (ltm != null && ltm.size() > 0) {
LeftTuple childLeftTuple = rightTuple.getFirstChild();
FastIterator leftIt = accNode.getLeftIterator(ltm);
LeftTuple leftTuple = accNode.getFirstLeftTuple(rightTuple, ltm, leftIt);
constraints.updateFromFactHandle(contextEntry, wm, rightTuple.getFactHandleForEvaluation());
// We assume a bucket change if leftTuple == null
if (childLeftTuple != null && ltm.isIndexed() && !leftIt.isFullIterator() && (leftTuple == null || (leftTuple.getMemory() != childLeftTuple.getLeftParent().getMemory()))) {
// our index has changed, so delete all the previous matches
removePreviousMatchesForRightTuple(accNode, accumulate, rightTuple, wm, am, childLeftTuple, trgLeftTuples);
// null so the next check will attempt matches for new bucket
childLeftTuple = null;
}
// if LeftTupleMemory is empty, there are no matches to modify
if (leftTuple != null) {
if (leftTuple.getStagedType() == LeftTuple.NONE) {
trgLeftTuples.addUpdate(leftTuple);
}
doRightUpdatesProcessChildren(accNode, am, wm, bm, constraints, accumulate, leftIt, rightTuple, childLeftTuple, leftTuple, trgLeftTuples);
}
}
rightTuple.clearStaged();
rightTuple = next;
}
constraints.resetFactHandle(contextEntry);
}
Aggregations