private void onShardOperation(
     final NodeRequest request,
     final Object[] shardResults,
     final int shardIndex,
     final ShardRouting shardRouting) {
   try {
     logger.trace(
         "[{}]  executing operation for shard [{}]", actionName, shardRouting.shortSummary());
     ShardOperationResult result = shardOperation(request.indicesLevelRequest, shardRouting);
     shardResults[shardIndex] = result;
     logger.trace(
         "[{}]  completed operation for shard [{}]", actionName, shardRouting.shortSummary());
   } catch (Throwable t) {
     BroadcastShardOperationFailedException e =
         new BroadcastShardOperationFailedException(
             shardRouting.shardId(), "operation " + actionName + " failed", t);
     e.setIndex(shardRouting.getIndex());
     e.setShard(shardRouting.shardId());
     shardResults[shardIndex] = e;
     logger.debug(
         "[{}] failed to execute operation for shard [{}]",
         e,
         actionName,
         shardRouting.shortSummary());
   }
 }
 private Response newResponse(
     Request request,
     AtomicReferenceArray responses,
     List<NoShardAvailableActionException> unavailableShardExceptions,
     Map<String, List<ShardRouting>> nodes,
     ClusterState clusterState) {
   int totalShards = 0;
   int successfulShards = 0;
   List<ShardOperationResult> broadcastByNodeResponses = new ArrayList<>();
   List<ShardOperationFailedException> exceptions = new ArrayList<>();
   for (int i = 0; i < responses.length(); i++) {
     if (responses.get(i) instanceof FailedNodeException) {
       FailedNodeException exception = (FailedNodeException) responses.get(i);
       totalShards += nodes.get(exception.nodeId()).size();
       for (ShardRouting shard : nodes.get(exception.nodeId())) {
         exceptions.add(
             new DefaultShardOperationFailedException(shard.getIndex(), shard.getId(), exception));
       }
     } else {
       NodeResponse response = (NodeResponse) responses.get(i);
       broadcastByNodeResponses.addAll(response.results);
       totalShards += response.getTotalShards();
       successfulShards += response.getSuccessfulShards();
       for (BroadcastShardOperationFailedException throwable : response.getExceptions()) {
         if (!TransportActions.isShardNotAvailableException(throwable)) {
           exceptions.add(
               new DefaultShardOperationFailedException(
                   throwable.getIndex(), throwable.getShardId().getId(), throwable));
         }
       }
     }
   }
   totalShards += unavailableShardExceptions.size();
   int failedShards = exceptions.size();
   return newResponse(
       request,
       totalShards,
       successfulShards,
       failedShards,
       broadcastByNodeResponses,
       exceptions,
       clusterState);
 }