public <T extends TransportResponse> void sendRequest( final DiscoveryNode node, final String action, final TransportRequest request, final TransportRequestOptions options, TransportResponseHandler<T> handler) { if (node == null) { throw new ElasticsearchIllegalStateException("can't send request to a null node"); } final long requestId = newRequestId(); TimeoutHandler timeoutHandler = null; try { clientHandlers.put(requestId, new RequestHolder<>(handler, node, action, timeoutHandler)); if (started.get() == false) { // if we are not started the exception handling will remove the RequestHolder again and // calls the handler to notify the caller. // it will only notify if the toStop code hasn't done the work yet. throw new TransportException("TransportService is closed stopped can't send request"); } if (options.timeout() != null) { timeoutHandler = new TimeoutHandler(requestId); timeoutHandler.future = threadPool.schedule(options.timeout(), ThreadPool.Names.GENERIC, timeoutHandler); } transport.sendRequest(node, requestId, action, request, options); } catch (final Throwable e) { // usually happen either because we failed to connect to the node // or because we failed serializing the message final RequestHolder holderToNotify = clientHandlers.remove(requestId); // if the scheduler raise a EsRejectedExecutionException (due to shutdown), we may have a // timeout handler, but no future if (timeoutHandler != null) { FutureUtils.cancel(timeoutHandler.future); } // If holderToNotify == null then handler has already been taken care of. if (holderToNotify != null) { // callback that an exception happened, but on a different thread since we don't // want handlers to worry about stack overflows final SendRequestTransportException sendRequestException = new SendRequestTransportException(node, action, e); threadPool .executor(ThreadPool.Names.GENERIC) .execute( new Runnable() { @Override public void run() { holderToNotify.handler().handleException(sendRequestException); } }); } } }
@Override protected void doSample() { HashSet<DiscoveryNode> newNodes = new HashSet<>(); HashSet<DiscoveryNode> newFilteredNodes = new HashSet<>(); for (DiscoveryNode listedNode : listedNodes) { if (!transportService.nodeConnected(listedNode)) { try { // its a listed node, light connect to it... logger.trace("connecting to listed node (light) [{}]", listedNode); transportService.connectToNodeLight(listedNode); } catch (Throwable e) { logger.debug("failed to connect to node [{}], removed from nodes list", e, listedNode); continue; } } try { LivenessResponse livenessResponse = transportService .submitRequest( listedNode, TransportLivenessAction.NAME, headers.applyTo(new LivenessRequest()), TransportRequestOptions.options() .withType(TransportRequestOptions.Type.STATE) .withTimeout(pingTimeout), new FutureTransportResponseHandler<LivenessResponse>() { @Override public LivenessResponse newInstance() { return new LivenessResponse(); } }) .txGet(); if (!ignoreClusterName && !clusterName.equals(livenessResponse.getClusterName())) { logger.warn("node {} not part of the cluster {}, ignoring...", listedNode, clusterName); newFilteredNodes.add(listedNode); } else if (livenessResponse.getDiscoveryNode() != null) { // use discovered information but do keep the original transport address, so people can // control which address is exactly used. DiscoveryNode nodeWithInfo = livenessResponse.getDiscoveryNode(); newNodes.add( new DiscoveryNode( nodeWithInfo.name(), nodeWithInfo.id(), nodeWithInfo.getHostName(), nodeWithInfo.getHostAddress(), listedNode.address(), nodeWithInfo.attributes(), nodeWithInfo.version())); } else { // although we asked for one node, our target may not have completed initialization yet // and doesn't have cluster nodes logger.debug( "node {} didn't return any discovery info, temporarily using transport discovery node", listedNode); newNodes.add(listedNode); } } catch (Throwable e) { logger.info("failed to get node info for {}, disconnecting...", e, listedNode); transportService.disconnectFromNode(listedNode); } } nodes = validateNewNodes(newNodes); filteredNodes = ImmutableList.copyOf(newFilteredNodes); }