protected AsyncAction(Request request, ActionListener<Response> listener) { this.request = request; this.listener = listener; clusterState = clusterService.state(); nodes = clusterState.nodes(); ClusterBlockException globalBlockException = checkGlobalBlock(clusterState, request); if (globalBlockException != null) { throw globalBlockException; } String[] concreteIndices = indexNameExpressionResolver.concreteIndices(clusterState, request); ClusterBlockException requestBlockException = checkRequestBlock(clusterState, request, concreteIndices); if (requestBlockException != null) { throw requestBlockException; } logger.trace( "resolving shards for [{}] based on cluster state version [{}]", actionName, clusterState.version()); ShardsIterator shardIt = shards(clusterState, request, concreteIndices); nodeIds = new HashMap<>(); for (ShardRouting shard : shardIt.asUnordered()) { if (shard.assignedToNode()) { String nodeId = shard.currentNodeId(); if (!nodeIds.containsKey(nodeId)) { nodeIds.put(nodeId, new ArrayList<>()); } nodeIds.get(nodeId).add(shard); } else { unavailableShardExceptions.add( new NoShardAvailableActionException( shard.shardId(), " no shards available for shard " + shard.toString() + " while executing " + actionName)); } } responses = new AtomicReferenceArray<>(nodeIds.size()); }
private void perform(final Throwable lastException) { final ShardRouting shard = shardsIt == null ? null : shardsIt.nextOrNull(); if (shard == null) { Throwable failure = lastException; if (failure == null) { failure = new NoShardAvailableActionException( null, "No shard available for [" + internalRequest.request() + "]"); } else { if (logger.isDebugEnabled()) { logger.debug("failed to execute [" + internalRequest.request() + "]", failure); } } listener.onFailure(failure); } else { if (shard.currentNodeId().equals(nodes.localNodeId())) { // we don't prefer local shard, so try and do it here if (!internalRequest.request().preferLocalShard()) { try { if (internalRequest.request().operationThreaded()) { internalRequest.request().beforeLocalFork(); threadPool .executor(executor) .execute( new Runnable() { @Override public void run() { try { Response response = shardOperation(internalRequest.request(), shard.shardId()); listener.onResponse(response); } catch (Throwable e) { onFailure(shard, e); } } }); } else { final Response response = shardOperation(internalRequest.request(), shard.shardId()); listener.onResponse(response); } } catch (Throwable e) { onFailure(shard, e); } } else { perform(lastException); } } else { DiscoveryNode node = nodes.get(shard.currentNodeId()); transportService.sendRequest( node, transportShardAction, new ShardSingleOperationRequest(internalRequest.request(), shard.shardId()), new BaseTransportResponseHandler<Response>() { @Override public Response newInstance() { return newResponse(); } @Override public String executor() { return ThreadPool.Names.SAME; } @Override public void handleResponse(final Response response) { listener.onResponse(response); } @Override public void handleException(TransportException exp) { onFailure(shard, exp); } }); } } }
private void perform(@Nullable final Throwable currentFailure) { Throwable lastFailure = this.lastFailure; if (lastFailure == null || TransportActions.isReadOverrideException(currentFailure)) { lastFailure = currentFailure; this.lastFailure = currentFailure; } final ShardRouting shardRouting = shardIt.nextOrNull(); if (shardRouting == null) { Throwable failure = lastFailure; if (failure == null || isShardNotAvailableException(failure)) { failure = new NoShardAvailableActionException( null, LoggerMessageFormat.format( "No shard available for [{}]", internalRequest.request()), failure); } else { if (logger.isDebugEnabled()) { logger.debug("{}: failed to execute [{}]", failure, null, internalRequest.request()); } } listener.onFailure(failure); return; } DiscoveryNode node = nodes.get(shardRouting.currentNodeId()); if (node == null) { onFailure(shardRouting, new NoShardAvailableActionException(shardRouting.shardId())); } else { internalRequest.request().internalShardId = shardRouting.shardId(); if (logger.isTraceEnabled()) { logger.trace( "sending request [{}] to shard [{}] on node [{}]", internalRequest.request(), internalRequest.request().internalShardId, node); } transportService.sendRequest( node, transportShardAction, internalRequest.request(), new BaseTransportResponseHandler<Response>() { @Override public Response newInstance() { return newResponse(); } @Override public String executor() { return ThreadPool.Names.SAME; } @Override public void handleResponse(final Response response) { listener.onResponse(response); } @Override public void handleException(TransportException exp) { onFailure(shardRouting, exp); } }); } }
/** First get should try and use a shard that exists on a local node for better performance */ private void performFirst() { if (shardsIt == null) { // just execute it on the local node if (internalRequest.request().operationThreaded()) { internalRequest.request().beforeLocalFork(); threadPool .executor(executor()) .execute( new Runnable() { @Override public void run() { try { Response response = shardOperation(internalRequest.request(), null); listener.onResponse(response); } catch (Throwable e) { onFailure(null, e); } } }); return; } else { try { final Response response = shardOperation(internalRequest.request(), null); listener.onResponse(response); return; } catch (Throwable e) { onFailure(null, e); } } return; } if (internalRequest.request().preferLocalShard()) { boolean foundLocal = false; ShardRouting shardX; while ((shardX = shardsIt.nextOrNull()) != null) { final ShardRouting shard = shardX; if (shard.currentNodeId().equals(nodes.localNodeId())) { foundLocal = true; if (internalRequest.request().operationThreaded()) { internalRequest.request().beforeLocalFork(); threadPool .executor(executor()) .execute( new Runnable() { @Override public void run() { try { Response response = shardOperation(internalRequest.request(), shard.shardId()); listener.onResponse(response); } catch (Throwable e) { shardsIt.reset(); onFailure(shard, e); } } }); return; } else { try { final Response response = shardOperation(internalRequest.request(), shard.shardId()); listener.onResponse(response); return; } catch (Throwable e) { shardsIt.reset(); onFailure(shard, e); } } } } if (!foundLocal) { // no local node get, go remote shardsIt.reset(); perform(null); } } else { perform(null); } }