Chris Lu
3 years ago
6 changed files with 193 additions and 28 deletions
-
60weed/util/bptree/README.md
-
4weed/util/bptree/bpmap.go
-
12weed/util/bptree/bptree.go
-
67weed/util/bptree/bptree_node.go
-
34weed/util/bptree/bptree_store_test.go
-
44weed/util/bptree/getter_setter.go
@ -0,0 +1,60 @@ |
|||||
|
This adapts one b+ tree implementation |
||||
|
https://sourcegraph.com/github.com/timtadh/data-structures@master/-/tree/tree/bptree |
||||
|
to persist changes to on disk. |
||||
|
|
||||
|
# When a node needs to persist itself? |
||||
|
|
||||
|
* A node changed its key or value |
||||
|
* When an item is added. |
||||
|
* When an item is updated. |
||||
|
* When an item is deleted. |
||||
|
|
||||
|
* When a node is split. |
||||
|
* 2 new nodes are created (they shoud persist themselves). |
||||
|
* Parent node need to point to the new nodes. |
||||
|
|
||||
|
* When a node is merged. |
||||
|
* delete one node |
||||
|
* persist the merged node |
||||
|
|
||||
|
|
||||
|
In general, if one node is returned from a function, the node should have already been persisted. |
||||
|
The parent node may need to delete the old node. |
||||
|
|
||||
|
BpTree |
||||
|
Add(key ItemKey, value ItemValue) |
||||
|
new_root = self.getRoot().put(key,value) |
||||
|
a, b, err := self.insert(key, value) |
||||
|
self.internal_insert(key, value) |
||||
|
self.internal_split(q.keys[0], q) |
||||
|
persist(a,b) |
||||
|
self.persist() // child add q node |
||||
|
self.maybePersist(child == p) |
||||
|
self.leaf_insert(key, value) |
||||
|
self.persist() // if dedup |
||||
|
self.leaf_split(key, value) |
||||
|
self.pure_leaf_split(key, value) |
||||
|
persist(a,b) |
||||
|
a.persist() |
||||
|
persist(a,b) |
||||
|
self.put_kv(key, value) |
||||
|
new_root.persist() |
||||
|
self.setRoot(new_root) |
||||
|
oldroot.destroy() |
||||
|
// maybe persist BpTree new root |
||||
|
|
||||
|
Replace(key ItemKey, where WhereFunc, value ItemValue) |
||||
|
leaf.persist() |
||||
|
RemoveWhere(key ItemKey, where WhereFunc) |
||||
|
self.getRoot().remove(key, where) |
||||
|
self.internal_remove(key, nil, where) |
||||
|
child.leaf_remove(key, nil, where) |
||||
|
child.leaf_remove(key, sibling.keys[0], where) |
||||
|
l.destroy() // when the node is empty |
||||
|
a.maybePersist(hasChange) |
||||
|
self.destroy() // when no keys left |
||||
|
self.persist() // when some keys are left |
||||
|
self.leaf_remove(key, self.keys[len(self.keys)-1], where) |
||||
|
new_root.persist() // when new root is added |
||||
|
// maybe persist BpTree new root |
||||
|
|
@ -0,0 +1,34 @@ |
|||||
|
package bptree |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"testing" |
||||
|
) |
||||
|
|
||||
|
func TestAddRemove(t *testing.T) { |
||||
|
tree := NewBpTree(32) |
||||
|
PersistFn = func(node *BpNode) error { |
||||
|
println("saving", node.protoNodeId) |
||||
|
return nil |
||||
|
} |
||||
|
DestroyFn = func(node *BpNode) error { |
||||
|
println("delete", node.protoNodeId) |
||||
|
return nil |
||||
|
} |
||||
|
for i:=0;i<1024;i++{ |
||||
|
println("++++++++++", i) |
||||
|
tree.Add(String(fmt.Sprintf("%02d", i)), String(fmt.Sprintf("%02d", i))) |
||||
|
printTree(tree.root, "") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func printTree(node *BpNode, prefix string) { |
||||
|
fmt.Printf("%sNode %d\n", prefix, node.protoNodeId) |
||||
|
prefix += " " |
||||
|
for i:=0;i<len(node.keys);i++{ |
||||
|
fmt.Printf("%skey %s\n", prefix, node.keys[i]) |
||||
|
if i < len(node.pointers) && node.pointers[i] != nil { |
||||
|
printTree(node.pointers[i], prefix+" ") |
||||
|
} |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue