/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.core.phreak;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.TupleSets;
import org.drools.core.reteoo.LeftTuple;
import org.drools.core.reteoo.LeftTupleSink;
import org.drools.core.reteoo.LeftTupleSource;
import org.drools.core.reteoo.PathMemory;
import org.drools.core.reteoo.SegmentMemory;
import static org.drools.core.phreak.AddRemoveRule.forceFlushLeftTuple;
public class SegmentPropagator {
public static void propagate(SegmentMemory sourceSegment, TupleSets<LeftTuple> leftTuples, InternalWorkingMemory wm) {
if (leftTuples.isEmpty()) {
return;
}
LeftTupleSource source = ( LeftTupleSource ) sourceSegment.getTipNode();
if ( sourceSegment.isEmpty() ) {
SegmentUtilities.createChildSegments( wm, sourceSegment, source.getSinkPropagator() );
}
processPeers(sourceSegment, leftTuples, wm);
}
private static void processPeers(SegmentMemory sourceSegment, TupleSets<LeftTuple> leftTuples, InternalWorkingMemory wm) {
SegmentMemory firstSmem = sourceSegment.getFirst();
// Process Deletes
processPeerDeletes( leftTuples, leftTuples.getDeleteFirst(), firstSmem, wm );
processPeerDeletes( leftTuples, leftTuples.getNormalizedDeleteFirst(), firstSmem, wm );
// Process Updates
for ( LeftTuple leftTuple = leftTuples.getUpdateFirst(); leftTuple != null; leftTuple = leftTuple.getStagedNext()) {
SegmentMemory smem = firstSmem.getNext();
if ( smem != null ) {
for ( LeftTuple peer = leftTuple.getPeer(); peer != null; peer = peer.getPeer() ) {
// only stage, if not already staged, if insert, leave as insert
if ( peer.getStagedType() == LeftTuple.NONE ) {
peer.setPropagationContext( leftTuple.getPropagationContext() );
smem.getStagedLeftTuples().addUpdate( peer );
}
smem = smem.getNext();
}
}
}
// Process Inserts
for ( LeftTuple leftTuple = leftTuples.getInsertFirst(); leftTuple != null; leftTuple = leftTuple.getStagedNext()) {
SegmentMemory smem = firstSmem.getNext();
if ( smem != null ) {
LeftTuple peer = leftTuple;
for (; smem != null; smem = smem.getNext() ) {
if (peer.getPeer() != null) {
// if the tuple already has a peer avoid to create a new one ...
peer = peer.getPeer();
peer.setPropagationContext( leftTuple.getPropagationContext() );
// ... and update the staged LeftTupleSets according to its current staged state
PhreakJoinNode.updateChildLeftTuple(peer, smem.getStagedLeftTuples(), smem.getStagedLeftTuples());
} else {
peer = ((LeftTupleSink)smem.getRootNode()).createPeer( peer );
smem.getStagedLeftTuples().addInsert( peer );
if (smem.hasDataDrivenPathMemories()) {
for (PathMemory dataDrivenPmem : smem.getDataDrivenPathMemories()) {
// on insert only totally linked pmems need to be flushed
if (dataDrivenPmem.isRuleLinked()) {
forceFlushLeftTuple(dataDrivenPmem, smem, wm, smem.getStagedLeftTuples());
break;
}
}
}
}
}
}
}
firstSmem.getStagedLeftTuples().addAll( leftTuples );
leftTuples.resetAll();
}
private static void processPeerDeletes( TupleSets<LeftTuple> leftTuples, LeftTuple leftTuple, SegmentMemory firstSmem, InternalWorkingMemory wm ) {
for (; leftTuple != null; leftTuple = leftTuple.getStagedNext()) {
SegmentMemory smem = firstSmem.getNext();
if ( smem != null ) {
for ( LeftTuple peer = leftTuple.getPeer(); peer != null; peer = peer.getPeer() ) {
peer.setPropagationContext( leftTuple.getPropagationContext() );
TupleSets<LeftTuple> stagedLeftTuples = smem.getStagedLeftTuples();
// if the peer is already staged as insert or update the LeftTupleSets will reconcile it internally
stagedLeftTuples.addDelete( peer );
if (smem.hasDataDrivenPathMemories()) {
forceFlushLeftTuple(smem.getFirstDataDrivenPathMemory(), smem, wm, smem.getStagedLeftTuples());
}
smem = smem.getNext();
}
}
}
}
}