public boolean sendMessages(ContentCluster cluster, Communicator communicator, NodeListener listener) {
        boolean sentAnyMessages = false;
        long currentTime = timer.getCurrentTimeInMillis();
        for (NodeInfo info : cluster.getNodeInfos()) {
            Long requestTime = info.getLatestNodeStateRequestTime();

            if (requestTime != null && (currentTime - requestTime < nodeStateRequestTimeoutMS)) continue; // pending request
            if (info.getTimeForNextStateRequestAttempt() > currentTime) continue; // too early

            if (info.getRpcAddress() == null || info.isNotInSlobrok()) { // Cannot query state of node without RPC address or not in slobrok
                log.log(Level.FINE, () -> "Not sending getNodeState request to node " + info.getNode() + ": Not in slobrok");
                NodeState reportedState = info.getReportedState().clone();
                if (( ! reportedState.getState().equals(DOWN) && currentTime - info.lastSeenInSlobrok() > maxSlobrokDisconnectGracePeriod)
                    || reportedState.getState().equals(STOPPING)) // Don't wait for grace period if we expect node to be stopping
                {
                    log.log(Level.FINE, () -> "Setting reported state to DOWN "
                            + (reportedState.getState().equals(STOPPING)
                                ? "as node completed stopping."
                                : "as node has been out of slobrok longer than " + maxSlobrokDisconnectGracePeriod + " ms."));
                    if (reportedState.getState().oneOf("iur") || ! reportedState.hasDescription()) {
                        reportedState.setDescription("Set node down as it has been out of slobrok for " +
                                                             (currentTime - info.lastSeenInSlobrok()) +
                                                             " ms which is more than the max limit of " +
                                                             maxSlobrokDisconnectGracePeriod + " ms.");
                    }
                    reportedState.setState(DOWN);
                    listener.handleNewNodeState(info, reportedState.clone());
                }
                info.setReportedState(reportedState, currentTime); // Must reset it to null to get connection attempts counted
                continue;
            }

            communicator.getNodeState(info, waiter);
            sentAnyMessages = true;
        }
        return sentAnyMessages;
    }
Sends state requests to nodes that does not have one pending and is due
for another attempt.
clustercontroller-core/src/main/java/com/yahoo/vespa/clustercontroller/core/NodeStateGatherer.java