Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.mapdb.volume.ByteBufferVol Maven / Gradle / Ivy
package org.mapdb.volume;
import org.mapdb.CC;
import org.mapdb.DBException;
import org.mapdb.DataInput2;
import org.mapdb.volume.CleanerUtil;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.util.concurrent.locks.ReentrantLock;
/**
* Abstract Volume over bunch of ByteBuffers
* It leaves ByteBufferVol details (allocation, disposal) on subclasses.
* Most methods are final for better performance (JIT compiler can inline those).
*/
abstract public class ByteBufferVol extends Volume {
protected final boolean cleanerHackEnabled;
protected final ReentrantLock growLock = new ReentrantLock();
protected final int sliceShift;
protected final int sliceSizeModMask;
protected final int sliceSize;
protected volatile ByteBuffer[] slices = new ByteBuffer[0];
protected final boolean readOnly;
protected ByteBufferVol(boolean readOnly, int sliceShift, boolean cleanerHackEnabled) {
this.readOnly = readOnly;
this.sliceShift = sliceShift;
this.cleanerHackEnabled = cleanerHackEnabled;
this.sliceSize = 1<< sliceShift;
this.sliceSizeModMask = sliceSize -1;
}
protected final ByteBuffer getSlice(long offset){
ByteBuffer[] slices = this.slices;
int pos = (int)(offset >>> sliceShift);
if(pos>=slices.length)
throw new DBException.VolumeEOF("Get/Set beyond file size. Requested offset: "+offset+", volume size: "+length());
return slices[pos];
}
@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();
}
getSlice(offset).putLong((int) (offset & sliceSizeModMask), 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();
}
getSlice(offset).putInt((int) (offset & sliceSizeModMask), 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();
}
getSlice(offset).put((int) (offset & sliceSizeModMask), 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 = getSlice(offset).duplicate();
final int bufPos = (int) (offset& sliceSizeModMask);
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 = getSlice(offset).duplicate();
final int bufPos = (int) (offset& sliceSizeModMask);
//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 =getSlice(inputOffset).duplicate();
final int bufPos = (int) (inputOffset& sliceSizeModMask);
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 = getSlice(offset).duplicate();
final int bufPos = (int) (offset& sliceSizeModMask);
b1.position(bufPos);
b1.get(src, srcPos, srcSize);
}
@Override final public long getLong(long offset) {
return getSlice(offset).getLong((int) (offset & sliceSizeModMask));
}
@Override final public int getInt(long offset) {
return getSlice(offset).getInt((int) (offset & sliceSizeModMask));
}
@Override public final byte getByte(long offset) {
return getSlice(offset).get((int) (offset & sliceSizeModMask));
}
@Override
public final DataInput2.ByteBuffer getDataInput(long offset, int size) {
return new DataInput2.ByteBuffer(getSlice(offset), (int) (offset& sliceSizeModMask));
}
@Override
public void putDataOverlap(long offset, byte[] data, int pos, int len) {
boolean overlap = (offset>>>sliceShift != (offset+len)>>>sliceShift);
if(overlap){
while(len>0){
ByteBuffer b = getSlice(offset).duplicate();
b.position((int) (offset&sliceSizeModMask));
int toPut = Math.min(len,sliceSize - b.position());
b.limit(b.position()+toPut);
b.put(data, pos, toPut);
pos+=toPut;
len-=toPut;
offset+=toPut;
}
}else{
putData(offset,data,pos,len);
}
}
@Override
public DataInput2 getDataInputOverlap(long offset, int size) {
boolean overlap = (offset>>>sliceShift != (offset+size)>>>sliceShift);
if(overlap){
byte[] bb = new byte[size];
final int origLen = size;
while(size>0){
ByteBuffer b = getSlice(offset).duplicate();
b.position((int) (offset&sliceSizeModMask));
int toPut = Math.min(size,sliceSize - b.position());
b.limit(b.position()+toPut);
b.get(bb,origLen-size,toPut);
size -=toPut;
offset+=toPut;
}
return new DataInput2.ByteArray(bb);
}else{
//return mapped buffer
return getDataInput(offset,size);
}
}
@Override
public void putUnsignedShort(long offset, int value) {
final ByteBuffer b = getSlice(offset);
int bpos = (int) (offset & sliceSizeModMask);
b.put(bpos++, (byte) (value >> 8));
b.put(bpos, (byte) (value));
}
@Override
public int getUnsignedShort(long offset) {
final ByteBuffer b = getSlice(offset);
int bpos = (int) (offset & sliceSizeModMask);
return (( (b.get(bpos++) & 0xff) << 8) |
( (b.get(bpos) & 0xff)));
}
@Override
public int getUnsignedByte(long offset) {
final ByteBuffer b = getSlice(offset);
int bpos = (int) (offset & sliceSizeModMask);
return b.get(bpos) & 0xff;
}
@Override
public void putUnsignedByte(long offset, int byt) {
final ByteBuffer b = getSlice(offset);
int bpos = (int) (offset & sliceSizeModMask);
b.put(bpos, toByte(byt));
}
protected static byte toByte(int byt) {
return (byte) (byt & 0xff);
}
protected static byte toByte(long l) {
return (byte) (l & 0xff);
}
@Override
public long getSixLong(long pos) {
final ByteBuffer bb = getSlice(pos);
int bpos = (int) (pos & sliceSizeModMask);
return
((long) (bb.get(bpos++) & 0xff) << 40) |
((long) (bb.get(bpos++) & 0xff) << 32) |
((long) (bb.get(bpos++) & 0xff) << 24) |
((long) (bb.get(bpos++) & 0xff) << 16) |
((long) (bb.get(bpos++) & 0xff) << 8) |
((long) (bb.get(bpos) & 0xff));
}
@Override
public void putSixLong(long pos, long value) {
final ByteBuffer b = getSlice(pos);
int bpos = (int) (pos & sliceSizeModMask);
if(CC.ASSERT && (value >>>48!=0))
throw new DBException.DataCorruption("six long out of range");
b.put(bpos++, (byte) (0xff & (value >> 40)));
b.put(bpos++, (byte) (0xff & (value >> 32)));
b.put(bpos++, (byte) (0xff & (value >> 24)));
b.put(bpos++, (byte) (0xff & (value >> 16)));
b.put(bpos++, (byte) (0xff & (value >> 8)));
b.put(bpos, (byte) (0xff & (value)));
}
@Override
public int putPackedLong(long pos, long value) {
final ByteBuffer b = getSlice(pos);
int bpos = (int) (pos & sliceSizeModMask);
//$DELAY$
int ret = 0;
int shift = 63-Long.numberOfLeadingZeros(value);
shift -= shift%7; // round down to nearest multiple of 7
while(shift!=0){
b.put(bpos + (ret++), (byte) (((value >>> shift) & 0x7F) ));
//$DELAY$
shift-=7;
}
b.put(bpos +(ret++),(byte) ((value & 0x7F) | 0x80));
return ret;
}
@Override
public long getPackedLong(long position) {
final ByteBuffer b = getSlice(position);
int bpos = (int) (position & sliceSizeModMask);
long ret = 0;
int pos2 = 0;
byte v;
do{
v = b.get(bpos +(pos2++));
ret = (ret<<7 ) | (v & 0x7F);
}while((v&0x80)==0);
return (((long)pos2)<<60) | ret;
}
@Override
public void clear(long startOffset, long endOffset) {
if(CC.ASSERT && (startOffset >>> sliceShift) != ((endOffset-1) >>> sliceShift))
throw new AssertionError();
ByteBuffer buf = getSlice(startOffset);
int start = (int) (startOffset&sliceSizeModMask);
int end = (int) (start+(endOffset-startOffset));
int pos = start;
while(pos