@Override
  public FileCopyGetChunkResponse execute() throws Exception {
    final FileCopyGetChunkRequest request = new FileCopyGetChunkRequest(
        FileCopyGetChunkRequest.FILE_CHUNK_REQUEST_VERSION_V_1, fileCopyInfo.getCorrelationId(),
        fileCopyInfo.getClientId(), fileCopyInfo.getSourceReplicaId().getPartitionId(), fileChunkInfo.getFileName(),
        fileCopyInfo.getSourceReplicaId().getDataNodeId().getHostname(), snapshotId, fileChunkInfo.getStartOffset(),
        fileChunkInfo.getChunkLengthInBytes(), fileChunkInfo.isChunked());

    logger.info("Sending FileCopyGetChunkRequest: {}", request);
    long startTimeMs = System.currentTimeMillis();

    ConnectedChannel connectedChannel = getChannel(fileCopyInfo.getTargetReplicaId().getDataNodeId());

    ChannelOutput channelOutput = connectedChannel.sendAndReceive(request);
    FileCopyGetChunkResponse response = FileCopyGetChunkResponse.readFrom(channelOutput.getInputStream(), clusterMap);

    logger.info("Received FileCopyGetChunkResponse in {} ms", System.currentTimeMillis() - startTimeMs);
    return response;
  }
The execute method can be used with {@link OperationRetryHandler#executeWithRetry} to send the request to the
target replica and honor a retry policy.
@return The response received from the target replica of type {@link FileCopyGetChunkResponse}.
@throws IOException
@throws ConnectionPoolTimeoutException
@throws InterruptedException
ambry-file-transfer/src/main/java/com/github/ambry/filetransfer/workflow/GetChunkDataWorkflow.java