/** * {@inheritDoc} * * <p>Release the underlying buffer of previous/current read response. */ @Override public void close() throws IOException { if (mReadResponse != null) { mReadResponse.getPayloadDataBuffer().release(); mReadResponse = null; } }
@Override public ByteBuffer readRemoteBlock( InetSocketAddress address, long blockId, long offset, long length, long lockId, long sessionId) throws IOException { SingleResponseListener listener = null; Channel channel = null; Metrics.NETTY_BLOCK_READ_OPS.inc(); try { channel = BlockStoreContext.acquireNettyChannel(address, mClientBootstrap); listener = new SingleResponseListener(); channel.pipeline().get(ClientHandler.class).addListener(listener); ChannelFuture channelFuture = channel.writeAndFlush( new RPCBlockReadRequest(blockId, offset, length, lockId, sessionId)); channelFuture = channelFuture.sync(); if (channelFuture.isDone() && !channelFuture.isSuccess()) { LOG.error( "Failed to write to %s for block %d with error %s.", address.toString(), blockId, channelFuture.cause()); throw new IOException(channelFuture.cause()); } RPCResponse response = listener.get(NettyClient.TIMEOUT_MS, TimeUnit.MILLISECONDS); switch (response.getType()) { case RPC_BLOCK_READ_RESPONSE: RPCBlockReadResponse blockResponse = (RPCBlockReadResponse) response; LOG.debug("Data {} from remote machine {} received", blockId, address); RPCResponse.Status status = blockResponse.getStatus(); if (status == RPCResponse.Status.SUCCESS) { // always clear the previous response before reading another one close(); mReadResponse = blockResponse; return blockResponse.getPayloadDataBuffer().getReadOnlyByteBuffer(); } throw new IOException(status.getMessage() + " response: " + blockResponse); case RPC_ERROR_RESPONSE: RPCErrorResponse error = (RPCErrorResponse) response; throw new IOException(error.getStatus().getMessage()); default: throw new IOException( ExceptionMessage.UNEXPECTED_RPC_RESPONSE.getMessage( response.getType(), RPCMessage.Type.RPC_BLOCK_READ_RESPONSE)); } } catch (Exception e) { Metrics.NETTY_BLOCK_READ_FAILURES.inc(); try { if (channel != null) { channel.close().sync(); } } catch (InterruptedException ee) { throw Throwables.propagate(ee); } throw new IOException(e); } finally { if (channel != null && listener != null && channel.isActive()) { channel.pipeline().get(ClientHandler.class).removeListener(listener); } if (channel != null) { BlockStoreContext.releaseNettyChannel(address, channel); } } }