package org.dcache.xrootd.pool; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.util.ReferenceCountUtil; import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; import org.dcache.xrootd.core.XrootdException; import org.dcache.xrootd.protocol.messages.ReadVRequest; import org.dcache.xrootd.stream.AbstractChunkedReadvResponse; import static org.dcache.xrootd.protocol.XrootdProtocol.kXR_FileNotOpen; public class ChunkedFileDescriptorReadvResponse extends AbstractChunkedReadvResponse { private final List<FileDescriptor> descriptors; public ChunkedFileDescriptorReadvResponse(ReadVRequest request, int maxFrameSize, List<FileDescriptor> descriptors) { super(request, maxFrameSize); this.descriptors = descriptors; } @Override protected long getSize(int fd) throws IOException, XrootdException { if (fd < 0 || fd >= descriptors.size() || descriptors.get(fd) == null) { throw new XrootdException(kXR_FileNotOpen, "Invalid file descriptor"); } return descriptors.get(fd).getChannel().size(); } @Override protected ByteBuf read(ByteBufAllocator alloc, int fd, long position, int length) throws IOException, XrootdException { if (fd < 0 || fd >= descriptors.size() || descriptors.get(fd) == null) { throw new XrootdException(kXR_FileNotOpen, "Invalid file descriptor"); } FileDescriptor descriptor = descriptors.get(fd); ByteBuf chunk = alloc.ioBuffer(length); try { ByteBuffer buffer = chunk.nioBuffer(0, length); descriptor.read(buffer, position); chunk.writerIndex(buffer.position()); return chunk; } catch (RuntimeException | IOException e) { ReferenceCountUtil.release(chunk); throw e; } } }