package io.zbus.mq.disk.support; import java.io.IOException; import java.io.RandomAccessFile; import java.util.zip.CRC32; import java.util.zip.Checksum; public class BlockReadBuffer { private static final int BUFFER_SIZE = 1024*1024; //TODO, Make it configuarable private RandomAccessFile file; private byte[] buffer; private long pos = 0; //the position of File where the buffer loaded private int offset = 0; private int bufferLen = 0; public BlockReadBuffer(RandomAccessFile file){ this.file = file; this.buffer = new byte[BUFFER_SIZE]; } public synchronized int remaining(){ return bufferLen - offset; } private void loadBuffer() throws IOException{ this.file.seek(this.pos); this.offset = 0; this.bufferLen = this.file.read(buffer); if(bufferLen < 0){ this.bufferLen = 0; } } public void seek(long pos) throws IOException{ if(pos < this.pos || pos >= (this.pos + this.bufferLen)){ //reset buffer this.pos = pos; loadBuffer(); return; } this.offset = (int)(pos - this.pos); } public int skipBytes(int n) throws IOException { if(n <= 0) return 0; this.offset += n; if(this.offset > bufferLen){ this.pos += this.offset; loadBuffer(); } return n; } public boolean checksum(int size, long checksum){ byte[] data = new byte[size]; try { int n = peek(data); if(n <= 0){ return false; } } catch (IOException e) { return false; } Checksum crc = new CRC32(); crc.update(data, 0, size); return checksum == crc.getValue(); } public static long calcChecksum(byte[] data){ Checksum crc = new CRC32(); crc.update(data, 0, data.length); return crc.getValue(); } public int read(byte[] data) throws IOException{ int required = data.length; if(required <= remaining()){ System.arraycopy(this.buffer, offset, data, 0, required); offset += required; return required; } int dst = 0; while(required > 0){ if(remaining() <= 0){ this.pos += bufferLen; this.loadBuffer(); if(bufferLen <= 0) return dst; //EOF } int bufRemaining = remaining(); int n = required>=bufRemaining? bufRemaining : required; System.arraycopy(this.buffer, offset, data, dst, n); offset += n; dst += n; required -= n; } return dst; } public int peek(byte[] data) throws IOException{ int required = data.length; if(required <= remaining()){ System.arraycopy(this.buffer, offset, data, 0, required); return required; } long peekPos = this.pos + offset; this.file.seek(peekPos); int n = this.file.read(data); return n; } public int readInt() throws IOException{ byte[] data = new byte[4]; int n = read(data); if(n != 4){ throw new IllegalStateException("Not enought data"); } int ch1 = data[0]&0XFF; int ch2 = data[1]&0XFF; int ch3 = data[2]&0XFF; int ch4 = data[3]&0XFF; return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); } public long readLong() throws IOException{ return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL); } }