public boolean isConnected() { rwLock.readLock().lock(); try { return connectionStatus != null && connectionStatus.getState() == NodeConnectionState.CONNECTED; } finally { rwLock.readLock().unlock(); } }
@Override public Map<NodeConnectionState, List<NodeIdentifier>> getConnectionStates() { final Map<NodeConnectionState, List<NodeIdentifier>> connectionStates = new HashMap<>(); for (final Map.Entry<NodeIdentifier, NodeConnectionStatus> entry : nodeStatuses.entrySet()) { final NodeConnectionState state = entry.getValue().getState(); final List<NodeIdentifier> nodeIds = connectionStates.computeIfAbsent(state, s -> new ArrayList<>()); nodeIds.add(entry.getKey()); } return connectionStates; }
private NodeConnectionState getConnectionState(final NodeIdentifier nodeId) { final NodeConnectionStatus status = getConnectionStatus(nodeId); return status == null ? null : status.getState(); }
@Override public Set<NodeIdentifier> getNodeIdentifiers(final NodeConnectionState... states) { final Set<NodeConnectionState> statesOfInterest = new HashSet<>(); if (states.length == 0) { for (final NodeConnectionState state : NodeConnectionState.values()) { statesOfInterest.add(state); } } else { for (final NodeConnectionState state : states) { statesOfInterest.add(state); } } return nodeStatuses.entrySet().stream() .filter(entry -> statesOfInterest.contains(entry.getValue().getState())) .map(entry -> entry.getKey()) .collect(Collectors.toSet()); }
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof NodeConnectionStatus)) { return false; } NodeConnectionStatus other = (NodeConnectionStatus) obj; return Objects.deepEquals(getNodeIdentifier(), other.getNodeIdentifier()) && Objects.deepEquals(getState(), other.getState()); } }
private String summarizeStatusChange(final NodeConnectionStatus oldStatus, final NodeConnectionStatus status) { final StringBuilder sb = new StringBuilder(); if (oldStatus == null || status.getState() != oldStatus.getState()) { sb.append("Node Status changed from ").append(oldStatus == null ? "[Unknown Node]" : oldStatus.getState().toString()).append(" to ").append(status.getState().toString()); if (status.getReason() != null) { sb.append(" due to ").append(status.getReason()); } else if (status.getDisconnectCode() != null) { sb.append(" due to ").append(status.getDisconnectCode().toString()); } } return sb.toString(); }
private NodeConnectionStatus updateNodeStatus(final NodeIdentifier nodeId, final NodeConnectionStatus updatedStatus, final boolean storeState) { final NodeConnectionStatus evictedStatus = nodeStatuses.put(nodeId, updatedStatus); if (evictedStatus == null) { onNodeAdded(nodeId, storeState); } else { onNodeStateChange(nodeId, updatedStatus.getState()); } return evictedStatus; }
@Override public String toString() { final StringBuilder sb = new StringBuilder(); final NodeConnectionState state = getState(); sb.append("NodeConnectionStatus[nodeId=").append(nodeId).append(", state=").append(state); if (state == NodeConnectionState.OFFLOADED || state == NodeConnectionState.OFFLOADING) { sb.append(", Offload Code=").append(getOffloadCode()).append(", Offload Reason=").append(getReason()); } if (state == NodeConnectionState.DISCONNECTED || state == NodeConnectionState.DISCONNECTING) { sb.append(", Disconnect Code=").append(getDisconnectCode()).append(", Disconnect Reason=").append(getReason()); } sb.append(", updateId=").append(getUpdateIdentifier()); sb.append("]"); return sb.toString(); }
private boolean updateNodeStatusConditionally(final NodeIdentifier nodeId, final NodeConnectionStatus expectedStatus, final NodeConnectionStatus updatedStatus) { final boolean updated; if (expectedStatus == null) { final NodeConnectionStatus existingValue = nodeStatuses.putIfAbsent(nodeId, updatedStatus); updated = existingValue == null; if (updated) { onNodeAdded(nodeId, true); } } else { updated = nodeStatuses.replace(nodeId, expectedStatus, updatedStatus); } if (updated) { onNodeStateChange(nodeId, updatedStatus.getState()); } return updated; }
@Override public void resetNodeStatuses(final Map<NodeIdentifier, NodeConnectionStatus> statusMap) { logger.info("Resetting cluster node statuses from {} to {}", nodeStatuses, statusMap); // For each proposed replacement, update the nodeStatuses map if and only if the replacement // has a larger update id than the current value. for (final Map.Entry<NodeIdentifier, NodeConnectionStatus> entry : statusMap.entrySet()) { final NodeIdentifier nodeId = entry.getKey(); final NodeConnectionStatus proposedStatus = entry.getValue(); if (proposedStatus.getState() == NodeConnectionState.REMOVED) { removeNode(nodeId); } else { updateNodeStatus(nodeId, proposedStatus, false); } } storeState(); }
void updateNodeStatus(final NodeConnectionStatus status, final boolean waitForCoordinator) { final NodeIdentifier nodeId = status.getNodeIdentifier(); // In this case, we are using nodeStatuses.put() instead of getting the current value and // comparing that to the new value and using the one with the largest update id. This is because // this method is called when something occurs that causes this node to change the status of the // node in question. We only use comparisons against the current value when we receive an update // about a node status from a different node, since those may be received out-of-order. final NodeConnectionStatus currentStatus = updateNodeStatus(nodeId, status); final NodeConnectionState currentState = currentStatus == null ? null : currentStatus.getState(); logger.info("Status of {} changed from {} to {}", nodeId, currentStatus, status); logger.debug("State of cluster nodes is now {}", nodeStatuses); latestUpdateId.updateAndGet(curVal -> Math.max(curVal, status.getUpdateIdentifier())); if (currentState == null || currentState != status.getState()) { final boolean notifyAllNodes = isActiveClusterCoordinator(); if (notifyAllNodes) { logger.debug("Notifying all nodes that status changed from {} to {}", currentStatus, status); } else { logger.debug("Notifying cluster coordinator that node status changed from {} to {}", currentStatus, status); } notifyOthersOfNodeStatusChange(status, notifyAllNodes, waitForCoordinator); } else { logger.debug("Not notifying other nodes that status changed because previous state of {} is same as new state of {}", currentState, status.getState()); } }
@Override public void deleteNode(final String nodeId) { final NiFiUser user = NiFiUserUtils.getNiFiUser(); if (user == null) { throw new WebApplicationException(new Throwable("Unable to access details for current user.")); } final String userDn = user.getIdentity(); final NodeIdentifier nodeIdentifier = clusterCoordinator.getNodeIdentifier(nodeId); if (nodeIdentifier == null) { throw new UnknownNodeException("Cannot remove Node with ID " + nodeId + " because it is not part of the cluster"); } final NodeConnectionStatus nodeConnectionStatus = clusterCoordinator.getConnectionStatus(nodeIdentifier); if (!nodeConnectionStatus.getState().equals(NodeConnectionState.OFFLOADED) && !nodeConnectionStatus.getState().equals(NodeConnectionState.DISCONNECTED)) { throw new IllegalNodeDeletionException("Cannot remove Node with ID " + nodeId + " because it is not disconnected or offloaded, current state = " + nodeConnectionStatus.getState()); } clusterCoordinator.removeNode(nodeIdentifier, userDn); heartbeatMonitor.removeHeartbeat(nodeIdentifier); }
if (status != null && status.getState() == NodeConnectionState.CONNECTED) { nodesToKeep.add(nodeId);
final NodeConnectionState connectionState = connectionStatus.getState(); if (connectionState != NodeConnectionState.CONNECTED) { logger.debug("Notifying Client {} that node is not connected because current state is {}", client, connectionState);
public NodeConnectionStatus(final NodeConnectionStatus status) { this(status.getNodeIdentifier(), status.getState(), status.getOffloadCode(), status.getDisconnectCode(), status.getReason(), status.getConnectionRequestTime()); }
private ProtocolMessage handleClusterWorkload(final ClusterWorkloadRequestMessage msg) { final ClusterWorkloadResponseMessage response = new ClusterWorkloadResponseMessage(); final Map<NodeIdentifier, NodeWorkload> workloads = new HashMap<>(); getLatestHeartbeats().values().stream() .filter(hb -> NodeConnectionState.CONNECTED.equals(hb.getConnectionStatus().getState())) .forEach(hb -> { NodeWorkload wl = new NodeWorkload(); wl.setReportedTimestamp(hb.getTimestamp()); wl.setSystemStartTime(hb.getSystemStartTime()); wl.setActiveThreadCount(hb.getActiveThreadCount()); wl.setFlowFileCount(hb.getFlowFileCount()); wl.setFlowFileBytes(hb.getFlowFileBytes()); workloads.put(hb.getNodeIdentifier(), wl); }); response.setNodeWorkloads(workloads); return response; }
private void handleNodeStatusChange(final NodeStatusChangeMessage statusChangeMessage) { final NodeConnectionStatus updatedStatus = statusChangeMessage.getNodeConnectionStatus(); final NodeIdentifier nodeId = statusChangeMessage.getNodeId(); logger.debug("Handling request {}", statusChangeMessage); final NodeConnectionStatus oldStatus = nodeStatuses.get(statusChangeMessage.getNodeId()); // Either remove the value from the map or update the map depending on the connection state if (statusChangeMessage.getNodeConnectionStatus().getState() == NodeConnectionState.REMOVED) { if (removeNodeConditionally(nodeId, oldStatus)) { storeState(); } } else { updateNodeStatus(nodeId, updatedStatus); } logger.info("Status of {} changed from {} to {}", statusChangeMessage.getNodeId(), oldStatus, updatedStatus); logger.debug("State of cluster nodes is now {}", nodeStatuses); final NodeConnectionStatus status = statusChangeMessage.getNodeConnectionStatus(); final String summary = summarizeStatusChange(oldStatus, status); if (!StringUtils.isEmpty(summary)) { addNodeEvent(nodeId, summary); } // Update our counter so that we are in-sync with the cluster on the // most up-to-date version of the NodeConnectionStatus' Update Identifier. // We do this so that we can accurately compare status updates that are generated // locally against those generated from other nodes in the cluster. NodeConnectionStatus.updateIdGenerator(updatedStatus.getUpdateIdentifier()); if (isActiveClusterCoordinator()) { notifyOthersOfNodeStatusChange(statusChangeMessage.getNodeConnectionStatus()); } }
nodeDto.setAddress(nodeId.getApiAddress()); nodeDto.setApiPort(nodeId.getApiPort()); nodeDto.setStatus(status.getState().name()); nodeDto.setRoles(roles); if (status.getConnectionRequestTime() != null) {
@Override public AdaptedNodeConnectionStatus marshal(final NodeConnectionStatus toAdapt) throws Exception { final AdaptedNodeConnectionStatus adapted = new AdaptedNodeConnectionStatus(); if (toAdapt != null) { adapted.setUpdateId(toAdapt.getUpdateIdentifier()); adapted.setNodeId(toAdapt.getNodeIdentifier()); adapted.setConnectionRequestTime(toAdapt.getConnectionRequestTime()); adapted.setOffloadCode(toAdapt.getOffloadCode()); adapted.setDisconnectCode(toAdapt.getDisconnectCode()); adapted.setReason(toAdapt.getReason()); adapted.setState(toAdapt.getState()); } return adapted; } }