*
* @param wm
*/
public static synchronized SegmentMemory createSegmentMemory(LeftTupleSource tupleSource,
final InternalWorkingMemory wm) {
SegmentMemory smem = wm.getNodeMemory((MemoryFactory) tupleSource).getSegmentMemory();
if ( smem != null ) {
return smem; // this can happen when multiple threads are trying to initialize the segment
}
// find segment root
while (tupleSource.getType() != NodeTypeEnums.LeftInputAdapterNode &&
SegmentUtilities.parentInSameSegment(tupleSource, null)) {
tupleSource = tupleSource.getLeftTupleSource();
}
LeftTupleSource segmentRoot = tupleSource;
smem = restoreSegmentFromPrototype(wm, segmentRoot);
if ( smem != null ) {
return smem;
}
smem = new SegmentMemory(segmentRoot);
// Iterate all nodes on the same segment, assigning their position as a bit mask value
// allLinkedTestMask is the resulting mask used to test if all nodes are linked in
long nodePosMask = 1;
long allLinkedTestMask = 0;
boolean updateNodeBit = true; // nodes after a branch CE can notify, but they cannot impact linking
while (true) {
if ( tupleSource.isStreamMode() && smem.getTupleQueue() == null ) {
// need to make sure there is one Queue, for the rule, when a stream mode node is found.
Queue<TupleEntry> queue = initAndGetTupleQueue(tupleSource, wm);
smem.setTupleQueue( queue );
}
if (NodeTypeEnums.isBetaNode(tupleSource)) {
allLinkedTestMask = processBetaNode(tupleSource, wm, smem, nodePosMask, allLinkedTestMask, updateNodeBit);
} else {
switch (tupleSource.getType()) {
case NodeTypeEnums.LeftInputAdapterNode:
allLinkedTestMask = processLiaNode((LeftInputAdapterNode) tupleSource, wm, smem, nodePosMask, allLinkedTestMask);
break;
case NodeTypeEnums.EvalConditionNode:
processEvalNode((EvalConditionNode) tupleSource, wm, smem);
break;
case NodeTypeEnums.ConditionalBranchNode:
updateNodeBit = processBranchNode((ConditionalBranchNode) tupleSource, wm, smem);
break;
case NodeTypeEnums.FromNode:
processFromNode((FromNode) tupleSource, wm, smem);
break;
case NodeTypeEnums.TimerConditionNode:
processTimerNode((TimerNode) tupleSource, wm, smem, nodePosMask);
break;
case NodeTypeEnums.QueryElementNode:
processQueryNode((QueryElementNode) tupleSource, wm, segmentRoot, smem, nodePosMask);
break;
}
}
nodePosMask = nodePosMask << 1;
if (tupleSource.getSinkPropagator().size() == 1) {
LeftTupleSinkNode sink = (LeftTupleSinkNode) tupleSource.getSinkPropagator().getFirstLeftTupleSink();
if (NodeTypeEnums.isLeftTupleSource(sink)) {
tupleSource = (LeftTupleSource) sink;
} else {
// rtn or rian
// While not technically in a segment, we want to be able to iterate easily from the last node memory to the ria/rtn memory
// we don't use createNodeMemory, as these may already have been created by, but not added, by the method updateRiaAndTerminalMemory
Memory memory = wm.getNodeMemory((MemoryFactory) sink);
if (sink.getType() == NodeTypeEnums.RightInputAdaterNode) {
PathMemory riaPmem = ((RiaNodeMemory)memory).getRiaPathMemory();
smem.getNodeMemories().add( riaPmem );
RightInputAdapterNode rian = ( RightInputAdapterNode ) sink;
ObjectSink[] nodes = rian.getSinkPropagator().getSinks();
for ( ObjectSink node : nodes ) {
if ( NodeTypeEnums.isLeftTupleSource(node) ) {
SegmentMemory parentSmem = createSegmentMemory( (LeftTupleSource) node, wm );
}
}
} else if (NodeTypeEnums.isTerminalNode(sink)) {
smem.getNodeMemories().add((PathMemory)memory);
}