/** * Returns the appropriate {@link DataBuffer} representing the data to send, depending on the * configurable transfer type. * * @param req The initiating {@link RPCBlockReadRequest} * @param reader The {@link BlockReader} for the block to read * @param readLength The length, in bytes, of the data to read from the block * @return a {@link DataBuffer} representing the data * @throws IOException * @throws IllegalArgumentException */ private DataBuffer getDataBuffer(RPCBlockReadRequest req, BlockReader reader, long readLength) throws IOException, IllegalArgumentException { switch (mTransferType) { case MAPPED: ByteBuffer data = reader.read(req.getOffset(), (int) readLength); return new DataByteBuffer(data, readLength); case TRANSFER: // intend to fall through as TRANSFER is the default type. default: if (reader.getChannel() instanceof FileChannel) { return new DataFileChannel( (FileChannel) reader.getChannel(), req.getOffset(), readLength); } reader.close(); throw new IllegalArgumentException("Only FileChannel is supported!"); } }
private void validateBounds(final RPCBlockReadRequest req, final long fileLength) { Preconditions.checkArgument( req.getOffset() <= fileLength, "Offset(%s) is larger than file length(%s)", req.getOffset(), fileLength); Preconditions.checkArgument( req.getLength() == -1 || req.getOffset() + req.getLength() <= fileLength, "Offset(%s) plus length(%s) is larger than file length(%s)", req.getOffset(), req.getLength(), fileLength); }
private void handleBlockReadRequest( final ChannelHandlerContext ctx, final RPCBlockReadRequest req) throws IOException { final long blockId = req.getBlockId(); final long offset = req.getOffset(); final long len = req.getLength(); final long lockId = req.getLockId(); final long sessionId = req.getSessionId(); BlockReader reader; try { reader = mBlockWorker.readBlockRemote(sessionId, blockId, lockId); } catch (BlockDoesNotExistException e) { throw new IOException(e); } catch (InvalidWorkerStateException e) { throw new IOException(e); } try { req.validate(); final long fileLength = reader.getLength(); validateBounds(req, fileLength); final long readLength = returnLength(offset, len, fileLength); RPCBlockReadResponse resp = new RPCBlockReadResponse( blockId, offset, readLength, getDataBuffer(req, reader, readLength), RPCResponse.Status.SUCCESS); ChannelFuture future = ctx.writeAndFlush(resp); future.addListener(ChannelFutureListener.CLOSE); future.addListener(new ClosableResourceChannelListener(reader)); mBlockWorker.accessBlock(sessionId, blockId); LOG.info("Preparation for responding to remote block request for: {} done.", blockId); } catch (Exception e) { LOG.error("The file is not here : {}", e.getMessage(), e); RPCBlockReadResponse resp = RPCBlockReadResponse.createErrorResponse(req, RPCResponse.Status.FILE_DNE); ChannelFuture future = ctx.writeAndFlush(resp); future.addListener(ChannelFutureListener.CLOSE); if (reader != null) { reader.close(); } } }