/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* 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.apache.nifi.cluster.manager;
import org.apache.nifi.controller.status.RunStatus;
import org.apache.nifi.controller.status.TransmissionStatus;
import org.apache.nifi.util.FormatUtils;
import org.apache.nifi.web.api.dto.CounterDTO;
import org.apache.nifi.web.api.dto.CountersDTO;
import org.apache.nifi.web.api.dto.CountersSnapshotDTO;
import org.apache.nifi.web.api.dto.NodeCountersSnapshotDTO;
import org.apache.nifi.web.api.dto.NodeSystemDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.SystemDiagnosticsDTO;
import org.apache.nifi.web.api.dto.SystemDiagnosticsSnapshotDTO;
import org.apache.nifi.web.api.dto.SystemDiagnosticsSnapshotDTO.GarbageCollectionDTO;
import org.apache.nifi.web.api.dto.SystemDiagnosticsSnapshotDTO.StorageUsageDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatusDTO;
import org.apache.nifi.web.api.dto.status.ConnectionStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ControllerStatusDTO;
import org.apache.nifi.web.api.dto.status.NodeConnectionStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.NodePortStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.NodeProcessGroupStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.NodeProcessorStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.NodeRemoteProcessGroupStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.PortStatusDTO;
import org.apache.nifi.web.api.dto.status.PortStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ProcessGroupStatusDTO;
import org.apache.nifi.web.api.dto.status.ProcessGroupStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.ProcessorStatusDTO;
import org.apache.nifi.web.api.dto.status.ProcessorStatusSnapshotDTO;
import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusDTO;
import org.apache.nifi.web.api.dto.status.RemoteProcessGroupStatusSnapshotDTO;
import org.apache.nifi.web.api.entity.ConnectionStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.PortStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.ProcessorStatusSnapshotEntity;
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusSnapshotEntity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class StatusMerger {
public static void merge(final ControllerStatusDTO target, final ControllerStatusDTO toMerge) {
if (target == null || toMerge == null) {
return;
}
target.setActiveThreadCount(target.getActiveThreadCount() + toMerge.getActiveThreadCount());
target.setBytesQueued(target.getBytesQueued() + toMerge.getBytesQueued());
target.setFlowFilesQueued(target.getFlowFilesQueued() + toMerge.getFlowFilesQueued());
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final ControllerStatusDTO target) {
target.setQueued(prettyPrint(target.getFlowFilesQueued(), target.getBytesQueued()));
}
public static void merge(final ProcessGroupStatusDTO target, final boolean targetReadablePermission, final ProcessGroupStatusDTO toMerge, final boolean toMergeReadablePermission,
final String nodeId, final String nodeAddress, final Integer nodeApiPort) {
if (targetReadablePermission && !toMergeReadablePermission) {
target.setId(toMerge.getId());
target.setName(toMerge.getName());
}
merge(target.getAggregateSnapshot(), targetReadablePermission, toMerge.getAggregateSnapshot(), toMergeReadablePermission);
if (target.getNodeSnapshots() != null) {
final NodeProcessGroupStatusSnapshotDTO nodeSnapshot = new NodeProcessGroupStatusSnapshotDTO();
nodeSnapshot.setStatusSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshot.setAddress(nodeAddress);
nodeSnapshot.setApiPort(nodeApiPort);
nodeSnapshot.setNodeId(nodeId);
target.getNodeSnapshots().add(nodeSnapshot);
}
}
public static void merge(final ProcessGroupStatusSnapshotEntity target, ProcessGroupStatusSnapshotEntity toMerge) {
if (target == null || toMerge == null) {
return;
}
merge(target.getProcessGroupStatusSnapshot(), target.getCanRead(), toMerge.getProcessGroupStatusSnapshot(), toMerge.getCanRead());
}
public static void merge(final ProcessGroupStatusSnapshotDTO target, final boolean targetReadablePermission, final ProcessGroupStatusSnapshotDTO toMerge,
final boolean toMergeReadablePermission) {
if (target == null || toMerge == null) {
return;
}
if (targetReadablePermission && !toMergeReadablePermission) {
target.setId(toMerge.getId());
target.setName(toMerge.getName());
}
target.setBytesIn(target.getBytesIn() + toMerge.getBytesIn());
target.setFlowFilesIn(target.getFlowFilesIn() + toMerge.getFlowFilesIn());
target.setBytesQueued(target.getBytesQueued() + toMerge.getBytesQueued());
target.setFlowFilesQueued(target.getFlowFilesQueued() + toMerge.getFlowFilesQueued());
target.setBytesRead(target.getBytesRead() + toMerge.getBytesRead());
target.setBytesWritten(target.getBytesWritten() + toMerge.getBytesWritten());
target.setBytesOut(target.getBytesOut() + toMerge.getBytesOut());
target.setFlowFilesOut(target.getFlowFilesOut() + toMerge.getFlowFilesOut());
target.setBytesTransferred(target.getBytesTransferred() + toMerge.getBytesTransferred());
target.setFlowFilesTransferred(target.getFlowFilesTransferred() + toMerge.getFlowFilesTransferred());
target.setBytesReceived(target.getBytesReceived() + toMerge.getBytesReceived());
target.setFlowFilesReceived(target.getFlowFilesReceived() + toMerge.getFlowFilesReceived());
target.setBytesSent(target.getBytesSent() + toMerge.getBytesSent());
target.setFlowFilesSent(target.getFlowFilesSent() + toMerge.getFlowFilesSent());
target.setActiveThreadCount(target.getActiveThreadCount() + toMerge.getActiveThreadCount());
updatePrettyPrintedFields(target);
// connection status
// sort by id
final Map<String, ConnectionStatusSnapshotEntity> mergedConnectionMap = new HashMap<>();
for (final ConnectionStatusSnapshotEntity status : replaceNull(target.getConnectionStatusSnapshots())) {
mergedConnectionMap.put(status.getId(), status);
}
for (final ConnectionStatusSnapshotEntity statusToMerge : replaceNull(toMerge.getConnectionStatusSnapshots())) {
ConnectionStatusSnapshotEntity merged = mergedConnectionMap.get(statusToMerge.getId());
if (merged == null) {
mergedConnectionMap.put(statusToMerge.getId(), statusToMerge.clone());
continue;
}
merge(merged, statusToMerge);
}
target.setConnectionStatusSnapshots(mergedConnectionMap.values());
// processor status
final Map<String, ProcessorStatusSnapshotEntity> mergedProcessorMap = new HashMap<>();
for (final ProcessorStatusSnapshotEntity status : replaceNull(target.getProcessorStatusSnapshots())) {
mergedProcessorMap.put(status.getId(), status);
}
for (final ProcessorStatusSnapshotEntity statusToMerge : replaceNull(toMerge.getProcessorStatusSnapshots())) {
ProcessorStatusSnapshotEntity merged = mergedProcessorMap.get(statusToMerge.getId());
if (merged == null) {
mergedProcessorMap.put(statusToMerge.getId(), statusToMerge.clone());
continue;
}
merge(merged, statusToMerge);
}
target.setProcessorStatusSnapshots(mergedProcessorMap.values());
// input ports
final Map<String, PortStatusSnapshotEntity> mergedInputPortMap = new HashMap<>();
for (final PortStatusSnapshotEntity status : replaceNull(target.getInputPortStatusSnapshots())) {
mergedInputPortMap.put(status.getId(), status);
}
for (final PortStatusSnapshotEntity statusToMerge : replaceNull(toMerge.getInputPortStatusSnapshots())) {
PortStatusSnapshotEntity merged = mergedInputPortMap.get(statusToMerge.getId());
if (merged == null) {
mergedInputPortMap.put(statusToMerge.getId(), statusToMerge.clone());
continue;
}
merge(merged, statusToMerge);
}
target.setInputPortStatusSnapshots(mergedInputPortMap.values());
// output ports
final Map<String, PortStatusSnapshotEntity> mergedOutputPortMap = new HashMap<>();
for (final PortStatusSnapshotEntity status : replaceNull(target.getOutputPortStatusSnapshots())) {
mergedOutputPortMap.put(status.getId(), status);
}
for (final PortStatusSnapshotEntity statusToMerge : replaceNull(toMerge.getOutputPortStatusSnapshots())) {
PortStatusSnapshotEntity merged = mergedOutputPortMap.get(statusToMerge.getId());
if (merged == null) {
mergedOutputPortMap.put(statusToMerge.getId(), statusToMerge.clone());
continue;
}
merge(merged, statusToMerge);
}
target.setOutputPortStatusSnapshots(mergedOutputPortMap.values());
// child groups
final Map<String, ProcessGroupStatusSnapshotEntity> mergedGroupMap = new HashMap<>();
for (final ProcessGroupStatusSnapshotEntity status : replaceNull(target.getProcessGroupStatusSnapshots())) {
mergedGroupMap.put(status.getId(), status);
}
for (final ProcessGroupStatusSnapshotEntity statusToMerge : replaceNull(toMerge.getProcessGroupStatusSnapshots())) {
ProcessGroupStatusSnapshotEntity merged = mergedGroupMap.get(statusToMerge.getId());
if (merged == null) {
mergedGroupMap.put(statusToMerge.getId(), statusToMerge.clone());
continue;
}
merge(merged, statusToMerge);
}
target.setOutputPortStatusSnapshots(mergedOutputPortMap.values());
// remote groups
final Map<String, RemoteProcessGroupStatusSnapshotEntity> mergedRemoteGroupMap = new HashMap<>();
for (final RemoteProcessGroupStatusSnapshotEntity status : replaceNull(target.getRemoteProcessGroupStatusSnapshots())) {
mergedRemoteGroupMap.put(status.getId(), status);
}
for (final RemoteProcessGroupStatusSnapshotEntity statusToMerge : replaceNull(toMerge.getRemoteProcessGroupStatusSnapshots())) {
RemoteProcessGroupStatusSnapshotEntity merged = mergedRemoteGroupMap.get(statusToMerge.getId());
if (merged == null) {
mergedRemoteGroupMap.put(statusToMerge.getId(), statusToMerge.clone());
continue;
}
merge(merged, statusToMerge);
}
target.setRemoteProcessGroupStatusSnapshots(mergedRemoteGroupMap.values());
}
private static <T> Collection<T> replaceNull(final Collection<T> collection) {
return (collection == null) ? Collections.<T>emptyList() : collection;
}
/**
* Updates the fields that are "pretty printed" based on the raw values currently set. For example,
* {@link ProcessGroupStatusSnapshotDTO#setInput(String)} will be called with the pretty-printed form of the
* FlowFile counts and sizes retrieved via {@link ProcessGroupStatusSnapshotDTO#getFlowFilesIn()} and
* {@link ProcessGroupStatusSnapshotDTO#getBytesIn()}.
* <p>
* This logic is performed here, rather than in the DTO itself because the DTO needs to be kept purely
* getters & setters - otherwise the automatic marshalling and unmarshalling to/from JSON becomes very
* complicated.
*
* @param target the DTO to update
*/
public static void updatePrettyPrintedFields(final ProcessGroupStatusSnapshotDTO target) {
target.setQueued(prettyPrint(target.getFlowFilesQueued(), target.getBytesQueued()));
target.setQueuedCount(formatCount(target.getFlowFilesQueued()));
target.setQueuedSize(formatDataSize(target.getBytesQueued()));
target.setInput(prettyPrint(target.getFlowFilesIn(), target.getBytesIn()));
target.setRead(formatDataSize(target.getBytesRead()));
target.setWritten(formatDataSize(target.getBytesWritten()));
target.setOutput(prettyPrint(target.getFlowFilesOut(), target.getBytesOut()));
target.setTransferred(prettyPrint(target.getFlowFilesTransferred(), target.getBytesTransferred()));
target.setReceived(prettyPrint(target.getFlowFilesReceived(), target.getBytesReceived()));
target.setSent(prettyPrint(target.getFlowFilesSent(), target.getBytesSent()));
}
public static void merge(final RemoteProcessGroupStatusDTO target, final boolean targetReadablePermission, final RemoteProcessGroupStatusDTO toMerge,
final boolean toMergeReadablePermission, final String nodeId, final String nodeAddress, final Integer nodeApiPort) {
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
target.setTargetUri(toMerge.getTargetUri());
}
merge(target.getAggregateSnapshot(), targetReadablePermission, toMerge.getAggregateSnapshot(), toMergeReadablePermission);
if (target.getNodeSnapshots() != null) {
final NodeRemoteProcessGroupStatusSnapshotDTO nodeSnapshot = new NodeRemoteProcessGroupStatusSnapshotDTO();
nodeSnapshot.setStatusSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshot.setAddress(nodeAddress);
nodeSnapshot.setApiPort(nodeApiPort);
nodeSnapshot.setNodeId(nodeId);
target.getNodeSnapshots().add(nodeSnapshot);
}
}
public static void merge(final PortStatusDTO target, final boolean targetReadablePermission, final PortStatusDTO toMerge, final boolean toMergeReadablePermission, final String nodeId,
final String nodeAddress, final Integer nodeApiPort) {
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
}
merge(target.getAggregateSnapshot(), targetReadablePermission, toMerge.getAggregateSnapshot(), toMergeReadablePermission);
target.setTransmitting(Boolean.TRUE.equals(target.isTransmitting()) || Boolean.TRUE.equals(toMerge.isTransmitting()));
if (target.getNodeSnapshots() != null) {
final NodePortStatusSnapshotDTO nodeSnapshot = new NodePortStatusSnapshotDTO();
nodeSnapshot.setStatusSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshot.setAddress(nodeAddress);
nodeSnapshot.setApiPort(nodeApiPort);
nodeSnapshot.setNodeId(nodeId);
target.getNodeSnapshots().add(nodeSnapshot);
}
}
public static void merge(final ConnectionStatusDTO target, final boolean targetReadablePermission, final ConnectionStatusDTO toMerge, final boolean toMergeReadablePermission,
final String nodeId, final String nodeAddress, final Integer nodeApiPort) {
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
target.setSourceId(toMerge.getSourceId());
target.setSourceName(toMerge.getSourceName());
target.setDestinationId(toMerge.getDestinationId());
target.setDestinationName(toMerge.getDestinationName());
}
merge(target.getAggregateSnapshot(), targetReadablePermission, toMerge.getAggregateSnapshot(), toMergeReadablePermission);
if (target.getNodeSnapshots() != null) {
final NodeConnectionStatusSnapshotDTO nodeSnapshot = new NodeConnectionStatusSnapshotDTO();
nodeSnapshot.setStatusSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshot.setAddress(nodeAddress);
nodeSnapshot.setApiPort(nodeApiPort);
nodeSnapshot.setNodeId(nodeId);
target.getNodeSnapshots().add(nodeSnapshot);
}
}
public static void merge(final ProcessorStatusDTO target, final boolean targetReadablePermission, final ProcessorStatusDTO toMerge, final boolean toMergeReadablePermission,
final String nodeId, final String nodeAddress, final Integer nodeApiPort) {
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
target.setType(toMerge.getType());
}
merge(target.getAggregateSnapshot(), targetReadablePermission, toMerge.getAggregateSnapshot(), toMergeReadablePermission);
if (target.getNodeSnapshots() != null) {
final NodeProcessorStatusSnapshotDTO nodeSnapshot = new NodeProcessorStatusSnapshotDTO();
nodeSnapshot.setStatusSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshot.setAddress(nodeAddress);
nodeSnapshot.setApiPort(nodeApiPort);
nodeSnapshot.setNodeId(nodeId);
target.getNodeSnapshots().add(nodeSnapshot);
}
}
public static void merge(final ProcessorStatusSnapshotEntity target, ProcessorStatusSnapshotEntity toMerge) {
if (target == null || toMerge == null) {
return;
}
merge(target.getProcessorStatusSnapshot(), target.getCanRead(), toMerge.getProcessorStatusSnapshot(), toMerge.getCanRead());
}
public static void merge(final ProcessorStatusSnapshotDTO target, final boolean targetReadablePermission, final ProcessorStatusSnapshotDTO toMerge,
final boolean toMergeReadablePermission) {
if (target == null || toMerge == null) {
return;
}
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
target.setType(toMerge.getType());
}
// if the status to merge is invalid allow it to take precedence. whether the
// processor run status is disabled/stopped/running is part of the flow configuration
// and should not differ amongst nodes. however, whether a processor is invalid
// can be driven by environmental conditions. this check allows any of those to
// take precedence over the configured run status.
if (RunStatus.Invalid.name().equals(toMerge.getRunStatus())) {
target.setRunStatus(RunStatus.Invalid.name());
}
target.setBytesRead(target.getBytesRead() + toMerge.getBytesRead());
target.setBytesWritten(target.getBytesWritten() + toMerge.getBytesWritten());
target.setFlowFilesIn(target.getFlowFilesIn() + toMerge.getFlowFilesIn());
target.setBytesIn(target.getBytesIn() + toMerge.getBytesIn());
target.setFlowFilesOut(target.getFlowFilesOut() + toMerge.getFlowFilesOut());
target.setBytesOut(target.getBytesOut() + toMerge.getBytesOut());
target.setTaskCount(target.getTaskCount() + toMerge.getTaskCount());
target.setTasksDurationNanos(target.getTasksDurationNanos() + toMerge.getTasksDurationNanos());
target.setActiveThreadCount(target.getActiveThreadCount() + toMerge.getActiveThreadCount());
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final ProcessorStatusSnapshotDTO target) {
target.setInput(prettyPrint(target.getFlowFilesIn(), target.getBytesIn()));
target.setRead(formatDataSize(target.getBytesRead()));
target.setWritten(formatDataSize(target.getBytesWritten()));
target.setOutput(prettyPrint(target.getFlowFilesOut(), target.getBytesOut()));
final Integer taskCount = target.getTaskCount();
final String tasks = (taskCount == null) ? "-" : formatCount(taskCount);
target.setTasks(tasks);
target.setTasksDuration(FormatUtils.formatHoursMinutesSeconds(target.getTasksDurationNanos(), TimeUnit.NANOSECONDS));
}
public static void merge(final ConnectionStatusSnapshotEntity target, ConnectionStatusSnapshotEntity toMerge) {
if (target == null || toMerge == null) {
return;
}
merge(target.getConnectionStatusSnapshot(), target.getCanRead(), toMerge.getConnectionStatusSnapshot(), toMerge.getCanRead());
}
public static void merge(final ConnectionStatusSnapshotDTO target, final boolean targetReadablePermission, final ConnectionStatusSnapshotDTO toMerge,
final boolean toMergeReadablePermission) {
if (target == null || toMerge == null) {
return;
}
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
target.setSourceId(toMerge.getSourceId());
target.setSourceName(toMerge.getSourceName());
target.setDestinationId(toMerge.getDestinationId());
target.setDestinationName(toMerge.getDestinationName());
}
target.setFlowFilesIn(target.getFlowFilesIn() + toMerge.getFlowFilesIn());
target.setBytesIn(target.getBytesIn() + toMerge.getBytesIn());
target.setFlowFilesOut(target.getFlowFilesOut() + toMerge.getFlowFilesOut());
target.setBytesOut(target.getBytesOut() + toMerge.getBytesOut());
target.setFlowFilesQueued(target.getFlowFilesQueued() + toMerge.getFlowFilesQueued());
target.setBytesQueued(target.getBytesQueued() + toMerge.getBytesQueued());
if (target.getPercentUseBytes() == null) {
target.setPercentUseBytes(toMerge.getPercentUseBytes());
} else if (toMerge.getPercentUseBytes() != null) {
target.setPercentUseBytes(Math.max(target.getPercentUseBytes(), toMerge.getPercentUseBytes()));
}
if (target.getPercentUseCount() == null) {
target.setPercentUseCount(toMerge.getPercentUseCount());
} else if (toMerge.getPercentUseCount() != null) {
target.setPercentUseCount(Math.max(target.getPercentUseCount(), toMerge.getPercentUseCount()));
}
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final ConnectionStatusSnapshotDTO target) {
target.setQueued(prettyPrint(target.getFlowFilesQueued(), target.getBytesQueued()));
target.setQueuedCount(formatCount(target.getFlowFilesQueued()));
target.setQueuedSize(formatDataSize(target.getBytesQueued()));
target.setInput(prettyPrint(target.getFlowFilesIn(), target.getBytesIn()));
target.setOutput(prettyPrint(target.getFlowFilesOut(), target.getBytesOut()));
}
public static void merge(final RemoteProcessGroupStatusSnapshotEntity target, RemoteProcessGroupStatusSnapshotEntity toMerge) {
if (target == null || toMerge == null) {
return;
}
merge(target.getRemoteProcessGroupStatusSnapshot(), target.getCanRead(), toMerge.getRemoteProcessGroupStatusSnapshot(), toMerge.getCanRead());
}
public static void merge(final RemoteProcessGroupStatusSnapshotDTO target, final boolean targetReadablePermission, final RemoteProcessGroupStatusSnapshotDTO toMerge,
final boolean toMergeReadablePermission) {
if (target == null || toMerge == null) {
return;
}
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
target.setTargetUri(toMerge.getTargetUri());
}
final String transmittingValue = TransmissionStatus.Transmitting.name();
if (transmittingValue.equals(target.getTransmissionStatus()) || transmittingValue.equals(toMerge.getTransmissionStatus())) {
target.setTransmissionStatus(transmittingValue);
}
target.setActiveThreadCount(target.getActiveThreadCount() + toMerge.getActiveThreadCount());
target.setFlowFilesSent(target.getFlowFilesSent() + toMerge.getFlowFilesSent());
target.setBytesSent(target.getBytesSent() + toMerge.getBytesSent());
target.setFlowFilesReceived(target.getFlowFilesReceived() + toMerge.getFlowFilesReceived());
target.setBytesReceived(target.getBytesReceived() + toMerge.getBytesReceived());
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final RemoteProcessGroupStatusSnapshotDTO target) {
target.setReceived(prettyPrint(target.getFlowFilesReceived(), target.getBytesReceived()));
target.setSent(prettyPrint(target.getFlowFilesSent(), target.getBytesSent()));
}
public static void merge(final PortStatusSnapshotEntity target, PortStatusSnapshotEntity toMerge) {
if (target == null || toMerge == null) {
return;
}
merge(target.getPortStatusSnapshot(), target.getCanRead(), toMerge.getPortStatusSnapshot(), toMerge.getCanRead());
}
public static void merge(final PortStatusSnapshotDTO target, final boolean targetReadablePermission, final PortStatusSnapshotDTO toMerge, final boolean toMergeReadablePermission) {
if (target == null || toMerge == null) {
return;
}
if (targetReadablePermission && !toMergeReadablePermission) {
target.setGroupId(toMerge.getGroupId());
target.setId(toMerge.getId());
target.setName(toMerge.getName());
}
target.setActiveThreadCount(target.getActiveThreadCount() + toMerge.getActiveThreadCount());
target.setFlowFilesIn(target.getFlowFilesIn() + toMerge.getFlowFilesIn());
target.setBytesIn(target.getBytesIn() + toMerge.getBytesIn());
target.setFlowFilesOut(target.getFlowFilesOut() + toMerge.getFlowFilesOut());
target.setBytesOut(target.getBytesOut() + toMerge.getBytesOut());
target.setTransmitting(Boolean.TRUE.equals(target.isTransmitting()) || Boolean.TRUE.equals(toMerge.isTransmitting()));
// should be unnecessary here since ports run status not should be affected by
// environmental conditions but doing so in case that changes
if (RunStatus.Invalid.name().equals(toMerge.getRunStatus())) {
target.setRunStatus(RunStatus.Invalid.name());
}
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final PortStatusSnapshotDTO target) {
target.setInput(prettyPrint(target.getFlowFilesIn(), target.getBytesIn()));
target.setOutput(prettyPrint(target.getFlowFilesOut(), target.getBytesOut()));
}
public static void merge(final SystemDiagnosticsDTO target, final SystemDiagnosticsDTO toMerge, final String nodeId, final String nodeAddress, final Integer nodeApiPort) {
merge(target.getAggregateSnapshot(), toMerge.getAggregateSnapshot());
List<NodeSystemDiagnosticsSnapshotDTO> nodeSnapshots = target.getNodeSnapshots();
if (nodeSnapshots == null) {
nodeSnapshots = new ArrayList<>();
}
final NodeSystemDiagnosticsSnapshotDTO nodeSnapshot = new NodeSystemDiagnosticsSnapshotDTO();
nodeSnapshot.setAddress(nodeAddress);
nodeSnapshot.setApiPort(nodeApiPort);
nodeSnapshot.setNodeId(nodeId);
nodeSnapshot.setSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshots.add(nodeSnapshot);
target.setNodeSnapshots(nodeSnapshots);
}
public static void merge(final SystemDiagnosticsSnapshotDTO target, final SystemDiagnosticsSnapshotDTO toMerge) {
if (target == null || toMerge == null) {
return;
}
target.setAvailableProcessors(target.getAvailableProcessors() + toMerge.getAvailableProcessors());
target.setDaemonThreads(target.getDaemonThreads() + toMerge.getDaemonThreads());
target.setFreeHeapBytes(target.getFreeHeapBytes() + toMerge.getFreeHeapBytes());
target.setFreeNonHeapBytes(target.getFreeNonHeapBytes() + toMerge.getFreeNonHeapBytes());
target.setMaxHeapBytes(target.getMaxHeapBytes() + toMerge.getMaxHeapBytes());
target.setMaxNonHeapBytes(target.getMaxNonHeapBytes() + toMerge.getMaxNonHeapBytes());
double systemLoad = target.getProcessorLoadAverage();
double toMergeSystemLoad = toMerge.getProcessorLoadAverage();
if (systemLoad >= 0 && toMergeSystemLoad >= 0) {
systemLoad += toMergeSystemLoad;
} else if (systemLoad < 0 && toMergeSystemLoad >= 0) {
systemLoad = toMergeSystemLoad;
}
target.setProcessorLoadAverage(systemLoad);
target.setTotalHeapBytes(target.getTotalHeapBytes() + toMerge.getTotalHeapBytes());
target.setTotalNonHeapBytes(target.getTotalNonHeapBytes() + toMerge.getTotalNonHeapBytes());
target.setTotalThreads(target.getTotalThreads() + toMerge.getTotalThreads());
target.setUsedHeapBytes(target.getUsedHeapBytes() + toMerge.getUsedHeapBytes());
target.setUsedNonHeapBytes(target.getUsedNonHeapBytes() + toMerge.getUsedNonHeapBytes());
merge(target.getContentRepositoryStorageUsage(), toMerge.getContentRepositoryStorageUsage());
merge(target.getFlowFileRepositoryStorageUsage(), toMerge.getFlowFileRepositoryStorageUsage());
mergeGarbageCollection(target.getGarbageCollection(), toMerge.getGarbageCollection());
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final SystemDiagnosticsSnapshotDTO target) {
// heap
target.setMaxHeap(FormatUtils.formatDataSize(target.getMaxHeapBytes()));
target.setTotalHeap(FormatUtils.formatDataSize(target.getTotalHeapBytes()));
target.setUsedHeap(FormatUtils.formatDataSize(target.getUsedHeapBytes()));
target.setFreeHeap(FormatUtils.formatDataSize(target.getFreeHeapBytes()));
if (target.getMaxHeapBytes() != -1) {
target.setHeapUtilization(FormatUtils.formatUtilization(getUtilization(target.getUsedHeapBytes(), target.getMaxHeapBytes())));
}
// non heap
target.setMaxNonHeap(FormatUtils.formatDataSize(target.getMaxNonHeapBytes()));
target.setTotalNonHeap(FormatUtils.formatDataSize(target.getTotalNonHeapBytes()));
target.setUsedNonHeap(FormatUtils.formatDataSize(target.getUsedNonHeapBytes()));
target.setFreeNonHeap(FormatUtils.formatDataSize(target.getFreeNonHeapBytes()));
if (target.getMaxNonHeapBytes() != -1) {
target.setNonHeapUtilization(FormatUtils.formatUtilization(getUtilization(target.getUsedNonHeapBytes(), target.getMaxNonHeapBytes())));
}
}
public static void merge(final Set<StorageUsageDTO> targetSet, final Set<StorageUsageDTO> toMerge) {
final Map<String, StorageUsageDTO> storageById = new HashMap<>();
for (final StorageUsageDTO targetUsage : targetSet) {
storageById.put(targetUsage.getIdentifier(), targetUsage);
}
for (final StorageUsageDTO usageToMerge : toMerge) {
final StorageUsageDTO targetUsage = storageById.get(usageToMerge.getIdentifier());
if (targetUsage == null) {
storageById.put(usageToMerge.getIdentifier(), usageToMerge);
} else {
merge(targetUsage, usageToMerge);
}
}
targetSet.clear();
targetSet.addAll(storageById.values());
}
public static void merge(final StorageUsageDTO target, final StorageUsageDTO toMerge) {
target.setFreeSpaceBytes(target.getFreeSpaceBytes() + toMerge.getFreeSpaceBytes());
target.setTotalSpaceBytes(target.getTotalSpaceBytes() + toMerge.getTotalSpaceBytes());
target.setUsedSpaceBytes(target.getUsedSpaceBytes() + toMerge.getUsedSpaceBytes());
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final StorageUsageDTO target) {
target.setFreeSpace(FormatUtils.formatDataSize(target.getFreeSpaceBytes()));
target.setTotalSpace(FormatUtils.formatDataSize(target.getTotalSpaceBytes()));
target.setUsedSpace(FormatUtils.formatDataSize(target.getUsedSpaceBytes()));
if (target.getTotalSpaceBytes() != -1) {
target.setUtilization(FormatUtils.formatUtilization(getUtilization(target.getUsedSpaceBytes(), target.getTotalSpaceBytes())));
}
}
public static void mergeGarbageCollection(final Set<GarbageCollectionDTO> targetSet, final Set<GarbageCollectionDTO> toMerge) {
final Map<String, GarbageCollectionDTO> storageById = new HashMap<>();
for (final GarbageCollectionDTO targetUsage : targetSet) {
storageById.put(targetUsage.getName(), targetUsage);
}
for (final GarbageCollectionDTO usageToMerge : toMerge) {
final GarbageCollectionDTO targetUsage = storageById.get(usageToMerge.getName());
if (targetUsage == null) {
storageById.put(usageToMerge.getName(), usageToMerge);
} else {
merge(targetUsage, usageToMerge);
}
}
targetSet.clear();
targetSet.addAll(storageById.values());
}
public static void merge(final GarbageCollectionDTO target, final GarbageCollectionDTO toMerge) {
target.setCollectionCount(target.getCollectionCount() + toMerge.getCollectionCount());
target.setCollectionMillis(target.getCollectionMillis() + toMerge.getCollectionMillis());
updatePrettyPrintedFields(target);
}
public static void updatePrettyPrintedFields(final GarbageCollectionDTO target) {
target.setCollectionTime(FormatUtils.formatHoursMinutesSeconds(target.getCollectionMillis(), TimeUnit.MILLISECONDS));
}
public static void merge(final CountersDTO target, final CountersDTO toMerge, final String nodeId, final String nodeAddress, final Integer nodeApiPort) {
merge(target.getAggregateSnapshot(), toMerge.getAggregateSnapshot());
List<NodeCountersSnapshotDTO> nodeSnapshots = target.getNodeSnapshots();
if (nodeSnapshots == null) {
nodeSnapshots = new ArrayList<>();
}
final NodeCountersSnapshotDTO nodeCountersSnapshot = new NodeCountersSnapshotDTO();
nodeCountersSnapshot.setNodeId(nodeId);
nodeCountersSnapshot.setAddress(nodeAddress);
nodeCountersSnapshot.setApiPort(nodeApiPort);
nodeCountersSnapshot.setSnapshot(toMerge.getAggregateSnapshot());
nodeSnapshots.add(nodeCountersSnapshot);
target.setNodeSnapshots(nodeSnapshots);
}
public static void merge(final CountersSnapshotDTO target, final CountersSnapshotDTO toMerge) {
final Map<String, CounterDTO> counters = new HashMap<>();
for (final CounterDTO counter : target.getCounters()) {
counters.put(counter.getId(), counter);
}
for (final CounterDTO counter : toMerge.getCounters()) {
final CounterDTO existing = counters.get(counter.getId());
if (existing == null) {
counters.put(counter.getId(), counter);
} else {
merge(existing, counter);
}
}
target.setCounters(counters.values());
}
public static void merge(final CounterDTO target, final CounterDTO toMerge) {
target.setValueCount(target.getValueCount() + toMerge.getValueCount());
target.setValue(FormatUtils.formatCount(target.getValueCount()));
}
public static int getUtilization(final double used, final double total) {
return (int) Math.round((used / total) * 100);
}
public static String formatCount(final Integer intStatus) {
return intStatus == null ? "-" : FormatUtils.formatCount(intStatus);
}
public static String formatDataSize(final Long longStatus) {
return longStatus == null ? "-" : FormatUtils.formatDataSize(longStatus);
}
public static String prettyPrint(final Integer count, final Long bytes) {
return formatCount(count) + " (" + formatDataSize(bytes) + ")";
}
}