package org.mapdb.volume; import org.mapdb.CC; import org.mapdb.DataInput2; import java.io.IOException; import java.nio.ByteBuffer; /** * Abstract Volume over single ByteBuffer, maximal size is 2GB (32bit limit). * It leaves ByteBufferVol details (allocation, disposal) on subclasses. * Most methods are final for better performance (JIT compiler can inline those). */ abstract public class ByteBufferVolSingle extends Volume { protected final boolean cleanerHackEnabled; protected ByteBuffer buffer; protected final boolean readOnly; protected final long maxSize; protected ByteBufferVolSingle(boolean readOnly, long maxSize, boolean cleanerHackEnabled) { //TODO assert size this.readOnly = readOnly; this.maxSize = maxSize; this.cleanerHackEnabled = cleanerHackEnabled; } @Override public void ensureAvailable(long offset) { //TODO throw error if too big } @Override public final void putLong(final long offset, final long value) { if(CC.VOLUME_PRINT_STACK_AT_OFFSET!=0 && CC.VOLUME_PRINT_STACK_AT_OFFSET>=offset && CC.VOLUME_PRINT_STACK_AT_OFFSET <= offset+8){ new IOException("VOL STACK:").printStackTrace(); } buffer.putLong((int) offset, value); } @Override public final void putInt(final long offset, final int value) { if(CC.VOLUME_PRINT_STACK_AT_OFFSET!=0 && CC.VOLUME_PRINT_STACK_AT_OFFSET>=offset && CC.VOLUME_PRINT_STACK_AT_OFFSET <= offset+4){ new IOException("VOL STACK:").printStackTrace(); } buffer.putInt((int) (offset), value); } @Override public final void putByte(final long offset, final byte value) { if(CC.VOLUME_PRINT_STACK_AT_OFFSET!=0 && CC.VOLUME_PRINT_STACK_AT_OFFSET>=offset && CC.VOLUME_PRINT_STACK_AT_OFFSET <= offset+1){ new IOException("VOL STACK:").printStackTrace(); } buffer.put((int) offset, value); } @Override public void putData(final long offset, final byte[] src, int srcPos, int srcSize){ if(CC.VOLUME_PRINT_STACK_AT_OFFSET!=0 && CC.VOLUME_PRINT_STACK_AT_OFFSET>=offset && CC.VOLUME_PRINT_STACK_AT_OFFSET <= offset+srcSize){ new IOException("VOL STACK:").printStackTrace(); } final ByteBuffer b1 = buffer.duplicate(); final int bufPos = (int) offset; b1.position(bufPos); b1.put(src, srcPos, srcSize); } @Override public final void putData(final long offset, final ByteBuffer buf) { if(CC.VOLUME_PRINT_STACK_AT_OFFSET!=0 && CC.VOLUME_PRINT_STACK_AT_OFFSET>=offset && CC.VOLUME_PRINT_STACK_AT_OFFSET <= offset+buf.remaining()){ new IOException("VOL STACK:").printStackTrace(); } final ByteBuffer b1 = buffer.duplicate(); final int bufPos = (int) offset; //no overlap, so just write the value b1.position(bufPos); b1.put(buf); } @Override public void copyTo(long inputOffset, Volume target, long targetOffset, long size) { final ByteBuffer b1 = buffer.duplicate(); final int bufPos = (int) inputOffset; b1.position(bufPos); //TODO size>Integer.MAX_VALUE b1.limit((int) (bufPos + size)); target.putData(targetOffset, b1); } @Override public void getData(final long offset, final byte[] src, int srcPos, int srcSize){ final ByteBuffer b1 = buffer.duplicate(); final int bufPos = (int) offset; b1.position(bufPos); b1.get(src, srcPos, srcSize); } @Override final public long getLong(long offset) { return buffer.getLong((int) offset); } @Override final public int getInt(long offset) { return buffer.getInt((int) offset); } @Override public final byte getByte(long offset) { return buffer.get((int) offset); } @Override public final DataInput2.ByteBuffer getDataInput(long offset, int size) { return new DataInput2.ByteBuffer(buffer, (int) (offset)); } @Override public void putDataOverlap(long offset, byte[] data, int pos, int len) { putData(offset,data,pos,len); } @Override public DataInput2 getDataInputOverlap(long offset, int size) { //return mapped buffer return getDataInput(offset,size); } @Override public void clear(long startOffset, long endOffset) { int start = (int) (startOffset); int end = (int) (endOffset); ByteBuffer buf = buffer; int pos = start; while(pos<end){ buf = buf.duplicate(); buf.position(pos); buf.put(CLEAR, 0, Math.min(CLEAR.length, end-pos)); pos+=CLEAR.length; } } @Override public int sliceSize() { return -1; } @Override public boolean isSliced() { return false; } }