package com.jivesoftware.os.amza.service.storage.filer; import com.jivesoftware.os.amza.api.filer.IReadable; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; import java.util.concurrent.atomic.AtomicBoolean; /** * @author jonathan.colt */ public class DiskBackedWALFilerChannelReader implements IReadable { private final DiskBackedWALFiler parent; private final AtomicBoolean closed; private FileChannel fc; private volatile long fp; private final ByteBuffer singleByteBuffer = ByteBuffer.allocate(1); public DiskBackedWALFilerChannelReader(DiskBackedWALFiler parent, FileChannel fc, AtomicBoolean closed) { this.parent = parent; this.fc = fc; this.closed = closed; } @Override public Object lock() { return this; } @Override public void seek(long position) throws IOException { if (position < 0 || position > parent.length()) { throw new IOException("seek overflow " + position + " " + this); } fp = position; } @Override public long length() throws IOException { return parent.length(); } @Override public long getFilePointer() throws IOException { return fp; } @Override public int read() throws IOException { while (!closed.get()) { try { singleByteBuffer.position(0); int read = fc.read(singleByteBuffer, fp); fp++; singleByteBuffer.position(0); return read != 1 ? -1 : singleByteBuffer.get() & 0xFF; } catch (ClosedChannelException e) { fc = parent.getFileChannel(); } } return -1; } @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @Override public int read(byte[] b, int _offset, int _len) throws IOException { ByteBuffer bb = ByteBuffer.wrap(b, _offset, _len); while (!closed.get()) { try { fc.read(bb, fp); fp += _len; return _len; } catch (ClosedChannelException e) { fc = parent.getFileChannel(); bb.position(0); } } return -1; } @Override public void close() throws IOException { closed.compareAndSet(false, true); fc.close(); } }