-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathutils.go
112 lines (103 loc) · 1.97 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package btree
import (
"bytes"
"fmt"
"github.com/golang/protobuf/proto"
"sync/atomic"
)
type treeOperation struct {
TreeLog
valueChan chan []byte
errChan chan error
}
// genrate node/leaf id
func (t *Btree) genrateID() int64 {
var id int64
id = -1
for k, _ := range t.dupnodelist {
id = k
delete(t.dupnodelist, k)
break
}
if id == -1 {
if t.GetIndexCursor() >= t.GetSize() {
t.Nodes = append(t.Nodes, make([][]byte, TreeSize)...)
*t.Size += int64(TreeSize)
}
id = t.GetIndexCursor()
*t.IndexCursor++
}
return id
}
//alloc new tree node
func (t *Btree) newTreeNode() *TreeNode {
id := t.genrateID()
node := &TreeNode{
Id: proto.Int64(id),
IsDirt: proto.Int32(0),
}
return node
}
func (t *Btree) getTreeNode(id int64) (*TreeNode, error) {
var tnode TreeNode
var err error
if len(t.Nodes[id]) > 0 {
err = proto.Unmarshal(t.Nodes[id], &tnode)
} else {
err = fmt.Errorf("no data")
}
return &tnode, err
}
//locate key's index in a node
func (n *TreeNode) locate(key []byte) int {
i := 0
size := len(n.Keys)
for {
mid := (i + size) / 2
if i == size {
break
}
if bytes.Compare(n.Keys[mid], key) <= 0 {
i = mid + 1
} else {
size = mid
}
}
return i
}
//clone node
func (n *TreeNode) clone(tree *Btree) *TreeNode {
nnode := tree.newTreeNode()
nnode.Keys = n.GetKeys()
nnode.Childrens = n.GetChildrens()
nnode.Values = n.GetValues()
nnode.NodeType = proto.Int32(n.GetNodeType())
atomic.StoreInt32(n.IsDirt, 1)
tree.Nodes[n.GetId()], _ = proto.Marshal(n)
return nnode
}
//gc dupnodelist
func (t *Btree) gc() {
pos := t.gcIndex
for i, n := range t.Nodes[pos:] {
t.gcIndex++
if t.gcIndex > t.GetIndexCursor() {
t.gcIndex = 0
break
}
if i > 100 {
break
}
var v TreeNode
err := proto.Unmarshal(n, &v)
if err == nil && v.isReleaseAble() {
t.dupnodelist[v.GetId()] = 1
}
}
}
func (n *TreeNode) isReleaseAble() bool {
if n.IsDirt == nil || atomic.LoadInt32(n.IsDirt) > 0 {
return true
}
return false
}