goleveldb skiplist

这个函数用来找node的。

如果设置了prev则会在prevnode中存储前置节点,例子如下。

img

如果要找的key是22号。

那么第一次node为0号,h = 3.

next表示图中的六号节点,读取数据发现小于,node代表六号节点。

第二次node为六号节点,此时next为0,表示nil无后继。

于是如果有了prev,那么prevnode【3】 = 六号节点。

如果没有prev,过。

height为二。

第三次,node还是六号,此时next表示25号节点。

cmp>0;

如果设置了prev,那么prevnode[2] = 六号节点

height为1;

第四次,node还是六号,next表示九号,zmp《0;

node等于九号节点。height还是1

第五次,node为九号,next表示25号,则prevnode[1]就表示9.

然后height为0.

第六次,node为九号,next表示12号,cmp》0

第七次,node为12

第八次,node为21.next为25

则node[0] = 21号节点的位置

返回bool为false表示没找到。

// Must hold RW-lock if prev == true, as it use shared prevNode slice.
func (p *DB) findGE(key []byte, prev bool) (int, bool) {
node := 0//记住node0包含所有高度的指针
h := p.maxHeight - 1
for {
next := p.nodeData[node+nNext+h]
cmp := 1
if next != 0 {
o := p.nodeData[next]
cmp = p.cmp.Compare(p.kvData[o:o+p.nodeData[next+nKey]], key)
}
if cmp < 0 {
node = next
} else {

    if prev {
       p.prevNode[h] = node
    } else if cmp == 0 {
       return next, true
    }

    if h == 0 {    
       return next, cmp == 0
    }
    h--
}

}
}

// Put sets the value for the given key. It overwrites any previous value
// for that key; a DB is not a multi-map.
//
// It is safe to modify the contents of the arguments after Put returns.
func (p *DB) Put(key []byte, value []byte) error {
p.mu.Lock()
defer p.mu.Unlock()

if node, exact := p.findGE(key, true); exact {
kvOffset := len(p.kvData)
p.kvData = append(p.kvData, key...)
p.kvData = append(p.kvData, value...)
p.nodeData[node] = kvOffset
m := p.nodeData[node+nVal]
p.nodeData[node+nVal] = len(value)
p.kvSize += len(value) - m
return nil
}

h := p.randHeight()
if h > p.maxHeight {
for i := p.maxHeight; i < h; i++ {
p.prevNode[i] = 0
}
p.maxHeight = h
}

kvOffset := len(p.kvData)
p.kvData = append(p.kvData, key...)
p.kvData = append(p.kvData, value...)
// Node
node := len(p.nodeData)
p.nodeData = append(p.nodeData, kvOffset, len(key), len(value), h)
for i, n := range p.prevNode[:h] {
m := n + nNext + I
p.nodeData = append(p.nodeData, p.nodeData[m])
p.nodeData[m] = node
}

p.kvSize += len(key) + len(value)
p.n++
return nil
}

func (p *DB) randHeight() (h int) {
const branching = 4
h = 1
for h < tMaxHeight && p.rnd.Int()%branching == 0 {
h++
}
return
}

// Delete deletes the value for the given key. It returns ErrNotFound if
// the DB does not contain the key.
//
// It is safe to modify the contents of the arguments after Delete returns.
func (p *DB) Delete(key []byte) error {
p.mu.Lock()
defer p.mu.Unlock()

node, exact := p.findGE(key, true)
if !exact {
return ErrNotFound
}

h := p.nodeData[node+nHeight]
for i, n := range p.prevNode[:h] {
m := n + nNext + I
p.nodeData[m] = p.nodeData[p.nodeData[m]+nNext+I]
}

p.kvSize -= p.nodeData[node+nKey] + p.nodeData[node+nVal]
p.n--
return nil
}

// Range is a key range.
type Range struct {
// Start of the key range, include in the range.
Start []byte

// Limit of the key range, not include in the range.
Limit []byte
}

// Slice allows slicing the iterator to only contains keys in the given
// range. A nil Range.Start is treated as a key before all keys in the
// DB. And a nil Range.Limit is treated as a key after all keys in
// the DB.
//
// WARNING: Any slice returned by interator (e.g. slice returned by calling
// Iterator.Key() or Iterator.Key() methods), its content should not be modified
// unless noted otherwise.
//
// The iterator must be released after use, by calling Release method.
//
// Also read Iterator documentation of the leveldb/iterator package.
func (p *DB) NewIterator(slice *util.Range) iterator.Iterator {
return &dbIter{p: p, slice: slice}
}

type dbIter struct {
util.BasicReleaser
p *DB
slice *util.Range //范围

node int //当前node的指向
forward bool
key, value []byte
err error
}

func (i *dbIter) First() bool {
if i.Released() {
i.err = ErrIterReleased
return false
}

i.forward = true
i.p.mu.RLock()
defer i.p.mu.RUnlock()
if i.slice != nil && i.slice.Start != nil {
i.node, _ = i.p.findGE(i.slice.Start, false)
} else {
i.node = i.p.nodeData[nNext]
}
return i.fill(false, true)
}

func (i *dbIter) fill(checkStart, checkLimit bool) bool {
if i.node != 0 {
n := i.p.nodeData[i.node]
m := n + i.p.nodeData[i.node+nKey]
i.key = i.p.kvData[n:m]
if i.slice != nil {
switch {
case checkLimit && i.slice.Limit != nil && i.p.cmp.Compare(i.key, i.slice.Limit) >= 0:
fallthrough
case checkStart && i.slice.Start != nil && i.p.cmp.Compare(i.key, i.slice.Start) < 0:
i.node = 0
goto bail
}
}
i.value = i.p.kvData[m : m+i.p.nodeData[i.node+nVal]]
return true
}
bail:
i.key = nil
i.value = nil
return false
}

func (db *DB) get(auxm *memdb.DB, auxt tFiles, key []byte, seq uint64, ro opt.ReadOptions) (value []byte, err error) {
ikey := makeInternalKey(nil, key, seq, keyTypeSeek)

if auxm != nil {
if ok, mv, me := memGet(auxm, ikey, db.s.icmp); ok {
return append([]byte{}, mv...), me
}
}

em, fm := db.getMems()
for _, m := range [...]
memDB{em, fm} {
if m == nil {
continue
}
defer m.decref()

if ok, mv, me := memGet(m.DB, ikey, db.s.icmp); ok {
return append([]byte{}, mv...), me
}
}

v := db.s.version()
value, cSched, err := v.get(auxt, ikey, ro, false)
v.release()
if cSched {
// Trigger table compaction.
db.compTrigger(db.tcompCmdC)
}
return
}


// Value types encoded as the last component of internal keys.
// Don't modify; this value are saved to disk.
const (
keyTypeDel = keyType(0)
keyTypeVal = keyType(1)
)
const (
// Maximum value possible for sequence number; the 8-bits are
// used by value type, so its can packed together in single
// 64-bit integer.
keyMaxSeq = (uint64(1) << 56) - 1
// Maximum value possible for packed sequence number and type.
keyMaxNum = (keyMaxSeq << 8) | uint64(keyTypeSeek)
)

// Maximum number encoded in bytes.
var keyMaxNumBytes = make([]byte, 8)

func init() {
binary.LittleEndian.PutUint64(keyMaxNumBytes, keyMaxNum)
}

type internalKey []byte

func makeInternalKey(dst, ukey []byte, seq uint64, kt keyType) internalKey {
if seq > keyMaxSeq {
panic("leveldb: invalid sequence number")
} else if kt > keyTypeVal {
panic("leveldb: invalid type")
}

dst = ensureBuffer(dst, len(ukey)+8)
copy(dst, ukey)
binary.LittleEndian.PutUint64(dst[len(ukey):], (seq<<8)|uint64(kt))
return internalKey(dst)
}

func (littleEndian) PutUint64(b []byte, v uint64) {
_ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
}

现在我有一个UINT32 0x0000004C 在BIG-ENDIAN下表示为00 00 00 4C 现在有一个指针指向它 若我们把指针类型改为char*(也就是常说的byte,用两个16进制数表示)那么一种很朴素的想法就是不移动指针,但是由于它指向的是byte,所以对它取值得到的是00.可是这不是最理想的结果,一般来说应用的话没有人希望一个int(没有超过byte上界)被转成byte的时候变成0,所以在BIG-ENDIAN下做这样的指针转换时就要把指针向右(地址增大的方向)移动3个byte,这样转换后才能得到4C。然而在SMALL-ENDIAN下不存在这样的问题,因为最左边已经是最低位了。

Little-Endian优点:提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。 [1]

Big-Endian优点:靠首先提取高位字节,你总是可以由看看在偏移位置为0的字节来确定这个数字是正数还是负数。你不必知道这个数值有多长,或者你也不必过一些字节来看这个数值是否含有符号位。这个数值是以它们被打印出来的顺序存放的,所以从二进制到十进制的函数特别有效。因而,对于不同要求的机器,在设计存取方式时就会不同。 [1]

即低位字节排放在内存的低地址端,高位字节排放在内存的高地址端

内存低 内存高

0 0 1 0 1 0 0 1

内容低 内容高

然后就变成了。

1 0 0 1 0 1 0 0 (uint64)默认高位

随后通过这个比如说原来是

为什么为什么这个不用位为1来表示呢。

后一个字节是uint,全部为0表示删除,全部为一表示。。

userkey加8个字节,其中前七个字节是seq左移得到的。

每一次写入都会导致seq加一,然后获取的时候就通过这个internalkey去获取。

然后通过fill一方面去做一下检查,看看有没有超出范围,另一方面就是从db中取出数据。

然后iterator的node就会保存这个25这个node的位置

首先First语的意思,会通过findGE找到node,比方说是start为22.

这个iterator就是为了找出[start,limt],右开集。的所有key,value数据

delete也同样不会真的杉树数据,只是会更新prevnode的节点的指针。

每次都有1/4的可能性在下一层。

以此类推。

当前nodeData的增加0层的指针指向21号的0层的执政。

然后对prevnode的21号节点更新指针,指向22号节点。

最后,prevnode[0]为21号,【1】为九号,[2]为6号,[3]为六号。

然后在当前nodeData也是追加数据,追加kv偏移,k偏移,v偏移。和height。

比如说之前的22,那么它会在kvDATa的最后(这就是高性能关键只追加数据)追加keyvalue。

然后更新kvsize为旧的value和新的value之间的差值。(有可能增大也会减小)

随后由于len(key)长度不变所以不用在意。

然后原本这个node是比如说指向原先的旧的25号节点,现在就指向新的节点了。

于是他会在当前的kvdata的最后,注意是最后,添加新的key和value。(key和value都要追加)(这里会导致存储多份key,但是考虑到追加append的快速,还是值得的。)

我们发现如果刚好找到了这个节点,那么就说明是更新值。

这个put的话。
//比较internalkey
先比较userkey。
然后再比较sequence。
我们可以看到,当sequence number最大的时候,返回-1,也就是说,sequencenumber越大的越在前头。(这样就可以直接取到最新的值了)。
他们两个相等,当且仅当一个增加,之后一个是删除,然后nodeData就会抛弃第一个指向第二个。

func (icmp *iComparer) Compare(a, b []byte) int {
x := icmp.uCompare(internalKey(a).ukey(), internalKey(b).ukey())
if x == 0 {
if m, n := internalKey(a).num(), internalKey(b).num(); m > n {
return -1
} else if m < n {
return 1
}
}
return x
}

你可能感兴趣的:(goleveldb skiplist)