use of com.datatorrent.common.util.Pair in project apex-core by apache.
the class AppDataPushAgent method getPushData.
private JSONObject getPushData() {
// assemble the json that contains the app stats and logical operator stats and counters
JSONObject json = new JSONObject();
try {
json.put("type", DATA);
json.put("appId", dnmgr.getLogicalPlan().getValue(DAGContext.APPLICATION_ID));
json.put("appName", dnmgr.getLogicalPlan().getValue(DAGContext.APPLICATION_NAME));
json.put("appUser", appContext.getUser());
List<LogicalOperatorInfo> logicalOperatorInfoList = dnmgr.getLogicalOperatorInfoList();
JSONObject logicalOperators = new JSONObject();
for (LogicalOperatorInfo logicalOperator : logicalOperatorInfoList) {
JSONObject logicalOperatorJson = extractFields(logicalOperator);
JSONArray metricsList = new JSONArray();
Queue<Pair<Long, Map<String, Object>>> windowMetrics = dnmgr.getWindowMetrics(logicalOperator.name);
if (windowMetrics != null) {
while (!windowMetrics.isEmpty()) {
Pair<Long, Map<String, Object>> metrics = windowMetrics.remove();
long windowId = metrics.first;
// metric name, aggregated value
Map<String, Object> aggregates = metrics.second;
long now = System.currentTimeMillis();
if (!operatorsSchemaLastSentTime.containsKey(logicalOperator.name) || (metricsTransport.getSchemaResendInterval() > 0 && operatorsSchemaLastSentTime.get(logicalOperator.name) < now - metricsTransport.getSchemaResendInterval())) {
try {
pushMetricsSchema(dnmgr.getLogicalPlan().getOperatorMeta(logicalOperator.name), aggregates);
operatorsSchemaLastSentTime.put(logicalOperator.name, now);
} catch (IOException ex) {
LOG.error("Cannot push metrics schema", ex);
}
}
JSONObject metricsItem = new JSONObject();
metricsItem.put("_windowId", windowId);
long windowToMillis = dnmgr.windowIdToMillis(windowId);
LOG.debug("metric window {} time {}", windowId, windowToMillis);
metricsItem.put("_time", windowToMillis);
for (Map.Entry<String, Object> entry : aggregates.entrySet()) {
String metricName = entry.getKey();
Object aggregateValue = entry.getValue();
metricsItem.put(metricName, aggregateValue);
}
metricsList.put(metricsItem);
}
}
logicalOperatorJson.put("metrics", metricsList);
logicalOperators.put(logicalOperator.name, logicalOperatorJson);
}
json.put("time", System.currentTimeMillis());
json.put("logicalOperators", logicalOperators);
json.put("stats", extractFields(appContext.getStats()));
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
return json;
}
use of com.datatorrent.common.util.Pair in project apex-core by apache.
the class StreamMapping method redoMapping.
/**
* rebuild the tree, which may cause more changes to execution layer than need be
* TODO: investigate incremental logic
*/
private void redoMapping() {
Set<Pair<PTOperator, InputPortMeta>> downstreamOpers = Sets.newHashSet();
// figure out the downstream consumers
for (InputPortMeta ipm : streamMeta.getSinks()) {
// skipped for parallel partitions - those are handled elsewhere
if (!ipm.getValue(PortContext.PARTITION_PARALLEL) && plan.hasMapping(ipm.getOperatorMeta())) {
List<PTOperator> partitions = plan.getOperators(ipm.getOperatorMeta());
for (PTOperator doper : partitions) {
downstreamOpers.add(new Pair<>(doper, ipm));
}
}
}
if (!downstreamOpers.isEmpty()) {
// unifiers are required
for (PTOperator unifier : this.cascadingUnifiers) {
detachUnifier(unifier);
}
if (this.finalUnifier != null) {
detachUnifier(finalUnifier);
}
List<PTOperator> currentUnifiers = Lists.newArrayList(this.cascadingUnifiers);
this.cascadingUnifiers.clear();
plan.undeployOpers.addAll(currentUnifiers);
addSlidingUnifiers();
int limit = streamMeta.getSource().getValue(PortContext.UNIFIER_LIMIT);
boolean separateUnifiers = false;
Integer lastId = null;
for (InputPortMeta ipm : streamMeta.getSinks()) {
Integer id = plan.getStreamCodecIdentifier(ipm.getStreamCodec());
if (lastId == null) {
lastId = id;
} else if (!id.equals(lastId)) {
separateUnifiers = true;
break;
}
}
List<PTOutput> unifierSources = this.upstream;
Map<StreamCodec<?>, List<PTOutput>> cascadeUnifierSourcesMap = Maps.newHashMap();
if (limit > 1 && this.upstream.size() > limit) {
// cascading unifier
if (!separateUnifiers) {
unifierSources = setupCascadingUnifiers(this.upstream, currentUnifiers, limit, 0);
} else {
for (InputPortMeta ipm : streamMeta.getSinks()) {
StreamCodec<?> streamCodec = ipm.getStreamCodec();
if (!cascadeUnifierSourcesMap.containsKey(streamCodec)) {
unifierSources = setupCascadingUnifiers(this.upstream, currentUnifiers, limit, 0);
cascadeUnifierSourcesMap.put(streamCodec, unifierSources);
}
}
}
}
// remove remaining unifiers
for (PTOperator oper : currentUnifiers) {
plan.removePTOperator(oper);
}
// Directly getting attribute from map to know if it is set or not as it can be overriden by the input
Boolean sourceSingleFinal = streamMeta.getSource().getAttributes().get(PortContext.UNIFIER_SINGLE_FINAL);
// link the downstream operators with the unifiers
for (Pair<PTOperator, InputPortMeta> doperEntry : downstreamOpers) {
Map<LogicalPlan.InputPortMeta, PartitionKeys> partKeys = doperEntry.first.partitionKeys;
PartitionKeys pks = partKeys != null ? partKeys.get(doperEntry.second) : null;
Boolean sinkSingleFinal = doperEntry.second.getAttributes().get(PortContext.UNIFIER_SINGLE_FINAL);
boolean lastSingle = (sinkSingleFinal != null) ? sinkSingleFinal : (sourceSingleFinal != null ? sourceSingleFinal.booleanValue() : PortContext.UNIFIER_SINGLE_FINAL.defaultValue);
if (upstream.size() > 1) {
// detach downstream from upstream operator for the case where no unifier existed previously
for (PTOutput source : upstream) {
Iterator<PTInput> sinks = source.sinks.iterator();
while (sinks.hasNext()) {
PTInput sink = sinks.next();
if (sink.target == doperEntry.first) {
doperEntry.first.inputs.remove(sink);
sinks.remove();
}
}
}
if (!separateUnifiers && lastSingle) {
if (finalUnifier == null) {
finalUnifier = createUnifier(streamMeta, plan);
}
setInput(doperEntry.first, doperEntry.second, finalUnifier, (pks == null) || (pks.mask == 0) ? null : pks);
if (finalUnifier.inputs.isEmpty()) {
// set unifier inputs once, regardless how many downstream operators there are
for (PTOutput out : unifierSources) {
addInput(this.finalUnifier, out, null);
}
}
} else {
// MxN partitioning: unifier per downstream partition
LOG.debug("MxN unifier for {} {} {}", new Object[] { doperEntry.first, doperEntry.second.getPortName(), pks });
PTOperator unifier = doperEntry.first.upstreamMerge.get(doperEntry.second);
if (unifier == null) {
unifier = createUnifier(streamMeta, plan);
doperEntry.first.upstreamMerge.put(doperEntry.second, unifier);
setInput(doperEntry.first, doperEntry.second, unifier, null);
}
// sources may change dynamically, rebuild inputs (as for cascading unifiers)
for (PTInput in : unifier.inputs) {
in.source.sinks.remove(in);
}
unifier.inputs.clear();
List<PTOutput> doperUnifierSources = unifierSources;
if (separateUnifiers) {
List<PTOutput> cascadeSources = cascadeUnifierSourcesMap.get(doperEntry.second.getStreamCodec());
if (cascadeSources != null) {
doperUnifierSources = cascadeSources;
}
}
// add new inputs
for (PTOutput out : doperUnifierSources) {
addInput(unifier, out, (pks == null) || (pks.mask == 0) ? null : pks);
}
}
} else {
// no partitioning
PTOperator unifier = doperEntry.first.upstreamMerge.remove(doperEntry.second);
if (unifier != null) {
plan.removePTOperator(unifier);
}
setInput(doperEntry.first, doperEntry.second, upstream.get(0).source, pks);
}
}
// 2) Downstream operators partitions are scaled up from one to multiple. (replaced by merged unifier)
if (finalUnifier != null && finalUnifier.inputs.isEmpty()) {
plan.removePTOperator(finalUnifier);
finalUnifier = null;
}
}
}
use of com.datatorrent.common.util.Pair in project apex-core by apache.
the class StreamingContainerManager method aggregateMetrics.
private void aggregateMetrics(long windowId, Map<Integer, EndWindowStats> endWindowStatsMap) {
Collection<OperatorMeta> logicalOperators = getLogicalPlan().getAllOperators();
//for backward compatibility
for (OperatorMeta operatorMeta : logicalOperators) {
@SuppressWarnings("deprecation") Context.CountersAggregator aggregator = operatorMeta.getValue(OperatorContext.COUNTERS_AGGREGATOR);
if (aggregator == null) {
continue;
}
Collection<PTOperator> physicalOperators = plan.getAllOperators(operatorMeta);
List<Object> counters = Lists.newArrayList();
for (PTOperator operator : physicalOperators) {
EndWindowStats stats = endWindowStatsMap.get(operator.getId());
if (stats != null && stats.counters != null) {
counters.add(stats.counters);
}
}
if (counters.size() > 0) {
@SuppressWarnings("deprecation") Object aggregate = aggregator.aggregate(counters);
latestLogicalCounters.put(operatorMeta.getName(), aggregate);
}
}
for (OperatorMeta operatorMeta : logicalOperators) {
AutoMetric.Aggregator aggregator = operatorMeta.getMetricAggregatorMeta() != null ? operatorMeta.getMetricAggregatorMeta().getAggregator() : null;
if (aggregator == null) {
continue;
}
Collection<PTOperator> physicalOperators = plan.getAllOperators(operatorMeta);
List<AutoMetric.PhysicalMetricsContext> metricPool = Lists.newArrayList();
for (PTOperator operator : physicalOperators) {
EndWindowStats stats = endWindowStatsMap.get(operator.getId());
if (stats != null && stats.metrics != null) {
PhysicalMetricsContextImpl physicalMetrics = new PhysicalMetricsContextImpl(operator.getId(), stats.metrics);
metricPool.add(physicalMetrics);
}
}
if (metricPool.isEmpty()) {
//nothing to aggregate
continue;
}
Map<String, Object> lm = aggregator.aggregate(windowId, metricPool);
if (lm != null && lm.size() > 0) {
Queue<Pair<Long, Map<String, Object>>> windowMetrics = logicalMetrics.get(operatorMeta.getName());
if (windowMetrics == null) {
windowMetrics = new LinkedBlockingQueue<Pair<Long, Map<String, Object>>>(METRIC_QUEUE_SIZE) {
private static final long serialVersionUID = 1L;
@Override
public boolean add(Pair<Long, Map<String, Object>> longMapPair) {
if (remainingCapacity() <= 1) {
remove();
}
return super.add(longMapPair);
}
};
logicalMetrics.put(operatorMeta.getName(), windowMetrics);
}
LOG.debug("Adding to logical metrics for {}", operatorMeta.getName());
windowMetrics.add(new Pair<>(windowId, lm));
Map<String, Object> oldValue = latestLogicalMetrics.put(operatorMeta.getName(), lm);
if (oldValue == null) {
try {
saveMetaInfo();
} catch (IOException ex) {
LOG.error("Cannot save application meta info to DFS. App data sources will not be available.", ex);
}
}
}
}
}
use of com.datatorrent.common.util.Pair in project apex-core by apache.
the class EventsAgent method getLatestEvents.
public List<EventInfo> getLatestEvents(String appId, int limit) {
LinkedList<EventInfo> result = new LinkedList<>();
String dir = getEventsDirectory(appId);
if (dir == null) {
return null;
}
long totalNumEvents = 0;
LinkedList<Pair<String, Long>> partFiles = new LinkedList<>();
try (IndexFileBufferedReader ifbr = new IndexFileBufferedReader(new InputStreamReader(stramAgent.getFileSystem().open(new Path(dir, FSPartFileCollection.INDEX_FILE))), dir)) {
EventsIndexLine indexLine;
while ((indexLine = (EventsIndexLine) ifbr.readIndexLine()) != null) {
if (indexLine.isEndLine) {
continue;
}
partFiles.add(new Pair<>(indexLine.partFile, indexLine.numEvents));
totalNumEvents += indexLine.numEvents;
}
} catch (Exception ex) {
LOG.warn("Cannot read events for {}: {}", appId, ex);
return result;
}
long offset = 0;
while (totalNumEvents > limit && !partFiles.isEmpty()) {
Pair<String, Long> head = partFiles.getFirst();
if (totalNumEvents - head.second < limit) {
offset = Math.max(0, totalNumEvents - limit);
break;
}
totalNumEvents -= head.second;
partFiles.removeFirst();
}
String lastProcessPartFile = null;
for (Pair<String, Long> partFile : partFiles) {
try (BufferedReader partBr = new BufferedReader(new InputStreamReader(stramAgent.getFileSystem().open(new Path(dir, partFile.first))))) {
processPartFile(partBr, null, null, offset, limit, result);
offset = 0;
lastProcessPartFile = partFile.first;
} catch (Exception ex) {
LOG.warn("Cannot read events for {}: {}", appId, ex);
}
}
BufferedReader partBr = null;
try {
String extraPartFile = getNextPartFile(lastProcessPartFile);
if (extraPartFile != null && limit > 0) {
partBr = new BufferedReader(new InputStreamReader(stramAgent.getFileSystem().open(new Path(dir, extraPartFile))));
processPartFile(partBr, null, null, 0, Integer.MAX_VALUE, result);
}
} catch (Exception ex) {
// ignore
} finally {
IOUtils.closeQuietly(partBr);
}
while (result.size() > limit) {
result.removeFirst();
}
return result;
}
use of com.datatorrent.common.util.Pair in project apex-core by apache.
the class StreamingContainerManager method processHeartbeat.
/**
* process the heartbeat from each container.
* called by the RPC thread for each container. (i.e. called by multiple threads)
*
* @param heartbeat
* @return heartbeat response
*/
@SuppressWarnings("StatementWithEmptyBody")
public ContainerHeartbeatResponse processHeartbeat(ContainerHeartbeat heartbeat) {
long currentTimeMillis = clock.getTime();
final StreamingContainerAgent sca = this.containers.get(heartbeat.getContainerId());
if (sca == null || sca.container.getState() == PTContainer.State.KILLED) {
// could be orphaned container that was replaced and needs to terminate
LOG.error("Unknown container {}", heartbeat.getContainerId());
ContainerHeartbeatResponse response = new ContainerHeartbeatResponse();
response.shutdown = ShutdownType.ABORT;
return response;
}
//LOG.debug("{} {} {}", new Object[]{sca.container.containerId, sca.container.bufferServerAddress, sca.container.getState()});
if (sca.container.getState() == PTContainer.State.ALLOCATED) {
// capture dynamically assigned address from container
if (sca.container.bufferServerAddress == null && heartbeat.bufferServerHost != null) {
sca.container.bufferServerAddress = InetSocketAddress.createUnresolved(heartbeat.bufferServerHost, heartbeat.bufferServerPort);
LOG.info("Container {} buffer server: {}", sca.container.getExternalId(), sca.container.bufferServerAddress);
}
final long containerStartTime = System.currentTimeMillis();
sca.container.setState(PTContainer.State.ACTIVE);
sca.container.setStartedTime(containerStartTime);
sca.container.setFinishedTime(-1);
sca.jvmName = heartbeat.jvmName;
poolExecutor.submit(new Runnable() {
@Override
public void run() {
try {
containerFile.append(sca.getContainerInfo());
} catch (IOException ex) {
LOG.warn("Cannot write to container file");
}
for (PTOperator ptOp : sca.container.getOperators()) {
try {
JSONObject operatorInfo = new JSONObject();
operatorInfo.put("name", ptOp.getName());
operatorInfo.put("id", ptOp.getId());
operatorInfo.put("container", sca.container.getExternalId());
operatorInfo.put("startTime", containerStartTime);
operatorFile.append(operatorInfo);
} catch (IOException | JSONException ex) {
LOG.warn("Cannot write to operator file: ", ex);
}
}
}
});
}
sca.containerStackTrace = heartbeat.stackTrace;
if (heartbeat.restartRequested) {
LOG.error("Container {} restart request", sca.container.getExternalId());
containerStopRequests.put(sca.container.getExternalId(), sca.container.getExternalId());
}
sca.memoryMBFree = heartbeat.memoryMBFree;
sca.gcCollectionCount = heartbeat.gcCollectionCount;
sca.gcCollectionTime = heartbeat.gcCollectionTime;
sca.undeployOpers.clear();
sca.deployOpers.clear();
if (!this.deployChangeInProgress.get()) {
sca.deployCnt = this.deployChangeCnt;
}
Set<Integer> reportedOperators = Sets.newHashSetWithExpectedSize(sca.container.getOperators().size());
for (OperatorHeartbeat shb : heartbeat.getContainerStats().operators) {
long maxEndWindowTimestamp = 0;
reportedOperators.add(shb.nodeId);
PTOperator oper = this.plan.getAllOperators().get(shb.getNodeId());
if (oper == null) {
LOG.info("Heartbeat for unknown operator {} (container {})", shb.getNodeId(), heartbeat.getContainerId());
sca.undeployOpers.add(shb.nodeId);
continue;
}
if (shb.requestResponse != null) {
for (StatsListener.OperatorResponse obj : shb.requestResponse) {
if (obj instanceof OperatorResponse) {
// This is to identify platform requests
commandResponse.put((Long) obj.getResponseId(), obj.getResponse());
LOG.debug(" Got back the response {} for the request {}", obj, obj.getResponseId());
} else {
// This is to identify user requests
oper.stats.responses.add(obj);
}
}
}
//LOG.debug("heartbeat {} {}/{} {}", oper, oper.getState(), shb.getState(), oper.getContainer().getExternalId());
if (!(oper.getState() == PTOperator.State.ACTIVE && shb.getState() == OperatorHeartbeat.DeployState.ACTIVE)) {
// deploy state may require synchronization
processOperatorDeployStatus(oper, shb, sca);
}
oper.stats.lastHeartbeat = shb;
List<ContainerStats.OperatorStats> statsList = shb.getOperatorStatsContainer();
if (!statsList.isEmpty()) {
long tuplesProcessed = 0;
long tuplesEmitted = 0;
long totalCpuTimeUsed = 0;
int statCount = 0;
long maxDequeueTimestamp = -1;
oper.stats.recordingId = null;
final OperatorStatus status = oper.stats;
status.statsRevs.checkout();
for (Map.Entry<String, PortStatus> entry : status.inputPortStatusList.entrySet()) {
entry.getValue().recordingId = null;
}
for (Map.Entry<String, PortStatus> entry : status.outputPortStatusList.entrySet()) {
entry.getValue().recordingId = null;
}
for (ContainerStats.OperatorStats stats : statsList) {
if (stats == null) {
LOG.warn("Operator {} statistics list contains null element", shb.getNodeId());
continue;
}
/* report checkpoint-ed WindowId status of the operator */
if (stats.checkpoint instanceof Checkpoint) {
if (oper.getRecentCheckpoint() == null || oper.getRecentCheckpoint().windowId < stats.checkpoint.getWindowId()) {
addCheckpoint(oper, (Checkpoint) stats.checkpoint);
if (stats.checkpointStats != null) {
status.checkpointStats = stats.checkpointStats;
status.checkpointTimeMA.add(stats.checkpointStats.checkpointTime);
}
oper.failureCount = 0;
}
}
oper.stats.recordingId = stats.recordingId;
/* report all the other stuff */
// calculate the stats related to end window
// end window stats for a particular window id for a particular node
EndWindowStats endWindowStats = new EndWindowStats();
Collection<ContainerStats.OperatorStats.PortStats> ports = stats.inputPorts;
if (ports != null) {
Set<String> currentInputPortSet = Sets.newHashSetWithExpectedSize(ports.size());
for (ContainerStats.OperatorStats.PortStats s : ports) {
currentInputPortSet.add(s.id);
PortStatus ps = status.inputPortStatusList.get(s.id);
if (ps == null) {
ps = status.new PortStatus();
ps.portName = s.id;
status.inputPortStatusList.put(s.id, ps);
}
ps.totalTuples += s.tupleCount;
ps.recordingId = s.recordingId;
tuplesProcessed += s.tupleCount;
endWindowStats.dequeueTimestamps.put(s.id, s.endWindowTimestamp);
Pair<Integer, String> operatorPortName = new Pair<>(oper.getId(), s.id);
Long lastEndWindowTimestamp = operatorPortLastEndWindowTimestamps.get(operatorPortName);
if (lastEndWindowTimestamp == null) {
lastEndWindowTimestamp = lastStatsTimestamp;
}
long portElapsedMillis = Math.max(s.endWindowTimestamp - lastEndWindowTimestamp, 0);
//LOG.debug("=== PROCESSED TUPLE COUNT for {}: {}, {}, {}, {}", operatorPortName, s.tupleCount, portElapsedMillis, operatorPortLastEndWindowTimestamps.get(operatorPortName), lastStatsTimestamp);
ps.tuplesPMSMA.add(s.tupleCount, portElapsedMillis);
ps.bufferServerBytesPMSMA.add(s.bufferServerBytes, portElapsedMillis);
ps.queueSizeMA.add(s.queueSize);
operatorPortLastEndWindowTimestamps.put(operatorPortName, s.endWindowTimestamp);
if (maxEndWindowTimestamp < s.endWindowTimestamp) {
maxEndWindowTimestamp = s.endWindowTimestamp;
}
if (s.endWindowTimestamp > maxDequeueTimestamp) {
maxDequeueTimestamp = s.endWindowTimestamp;
}
}
// need to remove dead ports, for unifiers
Iterator<Map.Entry<String, PortStatus>> it = status.inputPortStatusList.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, PortStatus> entry = it.next();
if (!currentInputPortSet.contains(entry.getKey())) {
it.remove();
}
}
}
ports = stats.outputPorts;
if (ports != null) {
Set<String> currentOutputPortSet = Sets.newHashSetWithExpectedSize(ports.size());
for (ContainerStats.OperatorStats.PortStats s : ports) {
currentOutputPortSet.add(s.id);
PortStatus ps = status.outputPortStatusList.get(s.id);
if (ps == null) {
ps = status.new PortStatus();
ps.portName = s.id;
status.outputPortStatusList.put(s.id, ps);
}
ps.totalTuples += s.tupleCount;
ps.recordingId = s.recordingId;
tuplesEmitted += s.tupleCount;
Pair<Integer, String> operatorPortName = new Pair<>(oper.getId(), s.id);
Long lastEndWindowTimestamp = operatorPortLastEndWindowTimestamps.get(operatorPortName);
if (lastEndWindowTimestamp == null) {
lastEndWindowTimestamp = lastStatsTimestamp;
}
long portElapsedMillis = Math.max(s.endWindowTimestamp - lastEndWindowTimestamp, 0);
//LOG.debug("=== EMITTED TUPLE COUNT for {}: {}, {}, {}, {}", operatorPortName, s.tupleCount, portElapsedMillis, operatorPortLastEndWindowTimestamps.get(operatorPortName), lastStatsTimestamp);
ps.tuplesPMSMA.add(s.tupleCount, portElapsedMillis);
ps.bufferServerBytesPMSMA.add(s.bufferServerBytes, portElapsedMillis);
operatorPortLastEndWindowTimestamps.put(operatorPortName, s.endWindowTimestamp);
if (maxEndWindowTimestamp < s.endWindowTimestamp) {
maxEndWindowTimestamp = s.endWindowTimestamp;
}
}
if (ports.size() > 0) {
endWindowStats.emitTimestamp = ports.iterator().next().endWindowTimestamp;
}
// need to remove dead ports, for unifiers
Iterator<Map.Entry<String, PortStatus>> it = status.outputPortStatusList.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, PortStatus> entry = it.next();
if (!currentOutputPortSet.contains(entry.getKey())) {
it.remove();
}
}
}
// (we don't know the latency for output operators because they don't emit tuples)
if (endWindowStats.emitTimestamp < 0) {
endWindowStats.emitTimestamp = maxDequeueTimestamp;
}
if (status.currentWindowId.get() != stats.windowId) {
status.lastWindowIdChangeTms = currentTimeMillis;
status.currentWindowId.set(stats.windowId);
}
totalCpuTimeUsed += stats.cpuTimeUsed;
statCount++;
if (oper.getOperatorMeta().getValue(OperatorContext.COUNTERS_AGGREGATOR) != null) {
endWindowStats.counters = stats.counters;
}
if (oper.getOperatorMeta().getMetricAggregatorMeta() != null && oper.getOperatorMeta().getMetricAggregatorMeta().getAggregator() != null) {
endWindowStats.metrics = stats.metrics;
}
if (stats.windowId > currentEndWindowStatsWindowId) {
Map<Integer, EndWindowStats> endWindowStatsMap = endWindowStatsOperatorMap.get(stats.windowId);
if (endWindowStatsMap == null) {
endWindowStatsMap = new ConcurrentSkipListMap<>();
Map<Integer, EndWindowStats> endWindowStatsMapPrevious = endWindowStatsOperatorMap.putIfAbsent(stats.windowId, endWindowStatsMap);
if (endWindowStatsMapPrevious != null) {
endWindowStatsMap = endWindowStatsMapPrevious;
}
}
endWindowStatsMap.put(shb.getNodeId(), endWindowStats);
Set<Integer> allCurrentOperators = plan.getAllOperators().keySet();
int numOperators = plan.getAllOperators().size();
if (allCurrentOperators.containsAll(endWindowStatsMap.keySet()) && endWindowStatsMap.size() == numOperators) {
completeEndWindowStatsWindowId = stats.windowId;
}
}
}
status.totalTuplesProcessed.add(tuplesProcessed);
status.totalTuplesEmitted.add(tuplesEmitted);
OperatorMeta logicalOperator = oper.getOperatorMeta();
LogicalOperatorStatus logicalStatus = logicalOperator.getStatus();
if (!oper.isUnifier()) {
logicalStatus.totalTuplesProcessed += tuplesProcessed;
logicalStatus.totalTuplesEmitted += tuplesEmitted;
}
long lastMaxEndWindowTimestamp = operatorLastEndWindowTimestamps.containsKey(oper.getId()) ? operatorLastEndWindowTimestamps.get(oper.getId()) : lastStatsTimestamp;
if (maxEndWindowTimestamp >= lastMaxEndWindowTimestamp) {
double tuplesProcessedPMSMA = 0.0;
double tuplesEmittedPMSMA = 0.0;
if (statCount != 0) {
//LOG.debug("CPU for {}: {} / {} - {}", oper.getId(), totalCpuTimeUsed, maxEndWindowTimestamp, lastMaxEndWindowTimestamp);
status.cpuNanosPMSMA.add(totalCpuTimeUsed, maxEndWindowTimestamp - lastMaxEndWindowTimestamp);
}
for (PortStatus ps : status.inputPortStatusList.values()) {
tuplesProcessedPMSMA += ps.tuplesPMSMA.getAvg();
}
for (PortStatus ps : status.outputPortStatusList.values()) {
tuplesEmittedPMSMA += ps.tuplesPMSMA.getAvg();
}
status.tuplesProcessedPSMA.set(Math.round(tuplesProcessedPMSMA * 1000));
status.tuplesEmittedPSMA.set(Math.round(tuplesEmittedPMSMA * 1000));
} else {
//LOG.warn("This timestamp for {} is lower than the previous!! {} < {}", oper.getId(),
// maxEndWindowTimestamp, lastMaxEndWindowTimestamp);
}
operatorLastEndWindowTimestamps.put(oper.getId(), maxEndWindowTimestamp);
status.listenerStats.add(statsList);
this.reportStats.put(oper, oper);
status.statsRevs.commit();
}
if (lastStatsTimestamp < maxEndWindowTimestamp) {
lastStatsTimestamp = maxEndWindowTimestamp;
}
}
sca.lastHeartbeatMillis = currentTimeMillis;
for (PTOperator oper : sca.container.getOperators()) {
if (!reportedOperators.contains(oper.getId())) {
processOperatorDeployStatus(oper, null, sca);
}
}
ContainerHeartbeatResponse rsp = getHeartbeatResponse(sca);
if (heartbeat.getContainerStats().operators.isEmpty() && isApplicationIdle()) {
LOG.info("requesting idle shutdown for container {}", heartbeat.getContainerId());
rsp.shutdown = ShutdownType.ABORT;
} else {
if (sca.isShutdownRequested()) {
LOG.info("requesting shutdown for container {}", heartbeat.getContainerId());
rsp.shutdown = sca.shutdownRequest;
}
}
List<StramToNodeRequest> requests = rsp.nodeRequests != null ? rsp.nodeRequests : new ArrayList<StramToNodeRequest>();
ConcurrentLinkedQueue<StramToNodeRequest> operatorRequests = sca.getOperatorRequests();
while (true) {
StramToNodeRequest r = operatorRequests.poll();
if (r == null) {
break;
}
requests.add(r);
}
rsp.nodeRequests = requests;
rsp.committedWindowId = committedWindowId;
rsp.stackTraceRequired = sca.stackTraceRequested;
sca.stackTraceRequested = false;
apexPluginDispatcher.dispatch(new DAGExecutionEvent.HeartbeatExecutionEvent(heartbeat));
return rsp;
}
Aggregations