slice具体使用 ByteSliceWriter ByteSliceReader
ByteBlockPool
维护多个字节数组,可自动扩容,来对外提供基本的字节类型数据存储的功能,类似于jdk ArrayList数据的实现,调用者可以把ByteBlockPool当成是一个无限扩容的数组使用
slice
在ByteBlockPool基础上 又封装出slice的逻辑,slice是ByteBlockPool 上的某一段数据,刚开始分配很少的字节数,写满后新创建slice,越往后slice越大,每个slice后四个字节存放下一个slice的位置信息,以此可以用多个间断的slice来表示一个数据,slice的扩容规则如下
public final static int[] NEXT_LEVEL_ARRAY = {1, 2, 3, 4, 5, 6, 7, 8, 9, 9};
public final static int[] LEVEL_SIZE_ARRAY = {5, 14, 20, 30, 40, 40, 80, 80, 120, 200};
final int level = slice[upto] & 15;//slice[upto]初始为16 在写入slice的时候 初始一定都为0 遇到不为0的就是slice的结束位置
final int newLevel = NEXT_LEVEL_ARRAY[level];
final int newSize = LEVEL_SIZE_ARRAY[newLevel];
buffers 字节数组
bufferUpto buffers写入位置
buffer buffers数组中当前的元素
byteUpto buffer的写入位置
public int allocSlice(final byte[] slice, final int upto) {
final int level = slice[upto] & 15;//buffers中位置
final int newLevel = NEXT_LEVEL_ARRAY[level];
final int newSize = LEVEL_SIZE_ARRAY[newLevel];
// Maybe allocate another block
if (byteUpto > BYTE_BLOCK_SIZE-newSize) {
nextBuffer();
}
final int newUpto = byteUpto;
final int offset = newUpto + byteOffset;
byteUpto += newSize;
// Copy forward the past 3 bytes (which we are about
// to overwrite with the forwarding address):
buffer[newUpto] = slice[upto-3];
buffer[newUpto+1] = slice[upto-2];
buffer[newUpto+2] = slice[upto-1];
// Write forwarding address at end of last slice: slice最后四个字节存放 下个slice的开始位置
slice[upto-3] = (byte) (offset >>> 24);
slice[upto-2] = (byte) (offset >>> 16);
slice[upto-1] = (byte) (offset >>> 8);
slice[upto] = (byte) offset;
// Write new level:
buffer[byteUpto-1] = (byte) (16|newLevel);
return newUpto+3;
}
public void readBytes(final long offset, final byte bytes[], int bytesOffset, int bytesLength) {
int bytesLeft = bytesLength;
int bufferIndex = (int) (offset >> BYTE_BLOCK_SHIFT);//offset 得到buffers中的其实位置
int pos = (int) (offset & BYTE_BLOCK_MASK);//得到buffer中的位置
while (bytesLeft > 0) {//处理数据属于两个buffer的情况
byte[] buffer = buffers[bufferIndex++];
int chunk = Math.min(bytesLeft, BYTE_BLOCK_SIZE - pos);
System.arraycopy(buffer, pos, bytes, bytesOffset, chunk);
bytesOffset += chunk;
bytesLeft -= chunk;
pos = 0;
}
}
public int newSlice(final int size) {
if (byteUpto > BYTE_BLOCK_SIZE-size)
nextBuffer();
final int upto = byteUpto;
byteUpto += size;
buffer[byteUpto-1] = 16;//赋值为16 调用时 会重upto开始写入,当遇到buffer[pos]位置不为0 时,会调用allocSlice方法 通过 16&15得到当前NEXT_LEVEL_ARRAY中level
return upto;
}
public void nextBuffer() {//buffers写入位置bufferUpto 达到buffers的最大长度时 对buffers拷贝 扩容
if (1+bufferUpto == buffers.length) {//bufferUpto
byte[][] newBuffers = new byte[ArrayUtil.oversize(buffers.length+1,//根据当前机器64/32位和对象引用占用字节数获得最新长度
NUM_BYTES_OBJECT_REF)][];
System.arraycopy(buffers, 0, newBuffers, 0, buffers.length);//拷贝操作
buffers = newBuffers;
}
buffer = buffers[1+bufferUpto] = allocator.getByteBlock();//allocator分配器负责初始化buffers中每个数组的大小
bufferUpto++;//buffers写入位置+1
byteUpto = 0;//buffer写入位置
byteOffset += BYTE_BLOCK_SIZE;//指针位置初始化
}
public void setBytesRef(BytesRef term, int textStart) {//通过指定位置开始读取一个BytesRes
final byte[] bytes = term.bytes = buffers[textStart >> BYTE_BLOCK_SHIFT];
int pos = textStart & BYTE_BLOCK_MASK;
if ((bytes[pos] & 0x80) == 0) {//小于128 一个字节 表示长度
// length is 1 byte
term.length = bytes[pos];
term.offset = pos+1;
} else {
// length is 2 bytes 大于128两个字节表示长度
term.length = (bytes[pos]&0x7f) + ((bytes[pos+1]&0xff)<<7);
term.offset = pos+2;
}
assert term.length >= 0;
}