package com.github.believe3301.nonheapdb; import java.nio.ByteBuffer; public class Record { public static class RecordInfo{ int vsize; int vstep; int ksize; int kstep; //head size: ksize和vsize不计算在内 //计算的是key|value之前的MAGIC|next|keyLen|valLen占用的字节大小 public final int hsize() { return vstep + kstep + 8 + 1; } //整个记录占用的大小.要把ksize,vsize计算在内了. 下面第一行是记录的格式,第二行是每个字段占用的大小 //MAGIC|next|keyLen|valLen| key |value // 1 8 kstep vstep ksize vsize public final int used() { return vsize + vstep + ksize + kstep + 8 + 1; } } public static final byte MAGICREC = (byte) 0xC8; public static final byte MAGICFB = (byte) 0xB0; //标示这是一个free block. FB public static final int MAXHEAD = 24; public static final int READUNIT = 64; public static final int MAXRECORDSIZE = 1 << 16 - 1; //一条记录要包含key和value.数据是字节数组,key是字符串 private String key; private byte data[]; private RecordInfo info; private RecordIndex index; private RecordIndex parent; private long next; private boolean free; public Record() { this.info = new RecordInfo(); } public RecordInfo getInfo() { return info; } public String getKey() { return key; } public byte[] getData() { return data; } public RecordIndex getIndex() { return index; } public boolean isFree() { return this.free; } public long getNext() { return this.next; } public RecordIndex getParent() { return parent; } public Record setNext(long next) { this.next = next; return this; } public Record setIndex(RecordIndex index) { this.index = index; return this; } public Record setKey(String key) { this.key = key; return this; } public Record setData(byte data[]) { this.data = data; return this; } public void setParent(RecordIndex parent) { this.parent = parent; } //这条记录的字节格式 public ByteBuffer getBuffer() { //一条记录的长度: HEAD + key和value的长度 int rsiz = MAXHEAD + this.key.length() + this.data.length; ByteBuffer nbuf = ByteBuffer.allocate(rsiz); nbuf.put(MAGICREC); // 1 nbuf.putLong(this.next); // 8 Util.writeVarInt(this.key.length(), nbuf); //key.length的值 Util.writeVarInt(this.data.length, nbuf); //value.length的值 assert nbuf.position() < MAXHEAD; //keyLen+valLen占用的长度不能超过15.即最多14. nbuf.put(this.key.getBytes()); //key nbuf.put(this.data);//value nbuf.flip(); return nbuf; } public int setBuffer(ByteBuffer nbuf) { byte magic = nbuf.get();//第一个字节标示是否是空闲块 if(magic == MAGICFB) { this.free = true; } else if(magic == MAGICREC) { this.free = false; } else { assert false; } this.next = nbuf.getLong();//long类型,8个字节 //keyLength和keySize是不一样的概念. keyLength表示写入的key一共有多少个字节. //而keySize是keyLength的值占用了多少个字节. 比如key="12345",则keyLength=5. //而keySize=1.因为5这个数字只占用了一个字节. this.info.ksize = Util.readVarInt(nbuf);//keyLength.只是读取里面的值. //由于写入时是varInt,所以要知道keyLength本身占用了多少个字节 //MAGIC|next|keyLength|valLength|key|value // 1 8 |pos // |<------->| // kstep this.info.kstep = nbuf.position() - 8 - 1; this.info.vsize = Util.readVarInt(nbuf); //MAGIC|next|keyLength|valLength|key|value // 1 8 |pos // |<------->|<------->| // kstep vstep=pos-1-8-kstep this.info.vstep = nbuf.position() - info.kstep - 8 - 1; //check has read key? if (nbuf.limit() > nbuf.position() + this.info.ksize) { //当前缓冲区的position位置是key的开始位置,一共要读取ksize个字节,ksize是存储在keyLength里 this.key = new String(nbuf.array(), nbuf.position(), this.info.ksize); nbuf.position(nbuf.position() + this.info.ksize); } //check has read value? if (nbuf.limit() > nbuf.position() + this.info.vsize) { //key通过字符串的offset,size获取,data由于直接是字节数组,直接获取 this.data = new byte[this.info.vsize]; //声明data字节数组的大小为vsize nbuf.get(this.data);//从缓冲区中获取出vsize大小的数组,设置到data里 } return this.info.hsize(); } }