/*
# Licensed Materials - Property of IBM
# Copyright IBM Corp. 2015
*/
package com.ibm.streamsx.topology.generator.spl;
import static com.ibm.streamsx.topology.generator.spl.GraphUtilities.getUpstream;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.array;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.jboolean;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.jobject;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.jstring;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.nestedObject;
import static com.ibm.streamsx.topology.internal.gson.GsonUtilities.objectCreate;
import java.util.Set;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.ibm.streamsx.topology.function.Consumer;
import com.ibm.streamsx.topology.generator.operator.OpProperties;
class ThreadingModel {
@SuppressWarnings("serial")
static void preProcessThreadedPorts(final JsonObject graph){
// Remove the threaded port configuration from the operator and its
// params if:
// 1) The operator has a lowLatencyTag assigned
// 2) The upstream operator has a different colocationTag as the
// the operator.
// Added threaded port configuration if the operator is non-functional
// and it has a threaded port.
Set<JsonObject> starts = GraphUtilities.findStarts(graph);
GraphUtilities.visitOnce(starts, null, graph, new Consumer<JsonObject>(){
@Override
public void accept(JsonObject op) {
// These booleans will be used to determine whether to delete the
// threaded port from the operator.
boolean regionTagExists = false;
boolean differentColocationThanParent = false;
boolean functional=false;
JsonArray inputs = array(op, "inputs");
// Currently, threadedPorts are only supported on operators
// with one input port.
if(inputs == null || inputs.size() != 1){
return;
}
JsonObject input = inputs.get(0).getAsJsonObject();
JsonObject queue = jobject(input, "queue");
// If the queue is null, simply return. Nothing to be done.
if(queue == null){
return;
}
// If the operator is not functional, the we don't have to
// remove anything from the operator's params.
functional = jboolean(queue, "functional");
JsonObject placement = jobject(op, OpProperties.PLACEMENT);
// See if operator is in a lowLatency region
String regionTag = null;
if (placement != null) {
regionTag = jstring(placement, OpProperties.PLACEMENT_LOW_LATENCY_REGION_ID);
}
if (regionTag != null && !regionTag.isEmpty()) {
regionTagExists = true;
}
// See if operator has different colocation tag than any of
// its parents.
String colocTag = null;
if (placement != null) {
colocTag = jstring(placement, OpProperties.PLACEMENT_ISOLATE_REGION_ID);
}
for(JsonObject parent : getUpstream(op, graph)){
JsonObject parentPlacement = nestedObject(parent, OpProperties.CONFIG, OpProperties.PLACEMENT);
String parentColocTag = null;
if (parentPlacement != null)
parentColocTag = jstring(parentPlacement, OpProperties.PLACEMENT_ISOLATE_REGION_ID);
// Test whether colocation tags are different. If they are,
// don't insert a threaded port.
if(!colocTag.equals(parentColocTag)){
differentColocationThanParent = true;
}
}
// Remove the threaded port if necessary
if(differentColocationThanParent || regionTagExists){
input.remove("queue");
if(functional){
JsonObject params = jobject(op, "parameters");
params.remove("queueSize");
}
}
if(functional &&
!(differentColocationThanParent || regionTagExists)){
return;
}
// Add to SPL operator config if necessary
if(!functional &&
!(differentColocationThanParent || regionTagExists)){
JsonObject newQueue = objectCreate(op, OpProperties.CONFIG, "queue");
newQueue.addProperty("queueSize", new Integer(100));
newQueue.addProperty("inputPortName", input.get("name").getAsString());
newQueue.addProperty("congestionPolicy", "Sys.Wait");
}
}
});
}
}