public void execute() throws Exception { final String activeShardCountFailure = checkActiveShardCount(); final ShardRouting primaryRouting = primary.routingEntry(); final ShardId primaryId = primaryRouting.shardId(); if (activeShardCountFailure != null) { finishAsFailed( new UnavailableShardsException( primaryId, "{} Timeout: [{}], request: [{}]", activeShardCountFailure, request.timeout(), request)); return; } totalShards.incrementAndGet(); pendingShards.incrementAndGet(); primaryResult = primary.perform(request); final ReplicaRequest replicaRequest = primaryResult.replicaRequest(); assert replicaRequest.primaryTerm() > 0 : "replicaRequest doesn't have a primary term"; if (logger.isTraceEnabled()) { logger.trace( "[{}] op [{}] completed on primary for request [{}]", primaryId, opType, request); } performOnReplicas(primaryId, replicaRequest); successfulShards.incrementAndGet(); decPendingAndFinishIfNeeded(); }
@Override public void readFrom(StreamInput in) throws IOException { shardId = in.readVInt(); request = newReplicaRequestInstance(); request.readFrom(in); }
@Override public void writeTo(StreamOutput out) throws IOException { out.writeVInt(shardId); request.writeTo(out); }
/** send operation to the given node or perform it if local */ void performOnReplica(final ShardRouting shard, final String nodeId) { // if we don't have that node, it means that it might have failed and will be created again, // in // this case, we don't have to do the operation, and just let it failover if (!observer.observedState().nodes().nodeExists(nodeId)) { onReplicaFailure(nodeId, null); return; } replicaRequest.internalShardId = shardIt.shardId(); if (!nodeId.equals(observer.observedState().nodes().localNodeId())) { final DiscoveryNode node = observer.observedState().nodes().get(nodeId); transportService.sendRequest( node, transportReplicaAction, replicaRequest, transportOptions, new EmptyTransportResponseHandler(ThreadPool.Names.SAME) { @Override public void handleResponse(TransportResponse.Empty vResponse) { onReplicaSuccess(); } @Override public void handleException(TransportException exp) { logger.trace( "[{}] transport failure during replica request [{}] ", exp, node, replicaRequest); if (ignoreReplicaException(exp)) { onReplicaFailure(nodeId, exp); } else { logger.warn( "{} failed to perform {} on node {}", exp, shardIt.shardId(), actionName, node); shardStateAction.shardFailed( shard, indexMetaData.getIndexUUID(), "failed to perform " + actionName + " on replica on node " + node, exp, shardFailedTimeout, new ReplicationFailedShardStateListener(nodeId, exp)); } } }); } else { try { threadPool .executor(executor) .execute( new AbstractRunnable() { @Override protected void doRun() { try { shardOperationOnReplica(shard.shardId(), replicaRequest); onReplicaSuccess(); } catch (Throwable e) { onReplicaFailure(nodeId, e); failReplicaIfNeeded(shard.index(), shard.id(), e); } } // we must never reject on because of thread pool capacity on replicas @Override public boolean isForceExecution() { return true; } @Override public void onFailure(Throwable t) { onReplicaFailure(nodeId, t); } }); } catch (Throwable e) { failReplicaIfNeeded(shard.index(), shard.id(), e); onReplicaFailure(nodeId, e); } } }