etcd/store/tree.go

279 lines
5.7 KiB
Go
Raw Normal View History

2013-07-03 05:09:54 +04:00
package store
import (
"path"
"sort"
2013-07-16 21:44:09 +04:00
"strings"
)
2013-07-03 05:09:54 +04:00
2013-07-09 08:20:50 +04:00
//------------------------------------------------------------------------------
//
// Typedefs
//
//------------------------------------------------------------------------------
2013-07-16 21:40:41 +04:00
// A file system like tree structure. Each non-leaf node of the tree has a hashmap to
2013-07-09 08:20:50 +04:00
// store its children nodes. Leaf nodes has no hashmap (a nil pointer)
2013-07-03 23:57:23 +04:00
type tree struct {
2013-07-03 05:09:54 +04:00
Root *treeNode
}
2013-07-09 08:20:50 +04:00
// A treeNode wraps a Node. It has a hashmap to keep records of its children treeNodes.
2013-07-03 05:09:54 +04:00
type treeNode struct {
2013-07-09 08:20:50 +04:00
InternalNode Node
2013-07-16 21:44:09 +04:00
Dir bool
NodeMap map[string]*treeNode
2013-07-03 05:09:54 +04:00
}
2013-07-09 08:20:50 +04:00
// TreeNode with its key. We use it when we need to sort the treeNodes.
2013-07-16 21:44:09 +04:00
type tnWithKey struct {
key string
tn *treeNode
}
2013-07-09 08:20:50 +04:00
// Define type and functions to match sort interface
type tnWithKeySlice []tnWithKey
func (s tnWithKeySlice) Len() int { return len(s) }
func (s tnWithKeySlice) Less(i, j int) bool { return s[i].key < s[j].key }
func (s tnWithKeySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
2013-07-09 08:20:50 +04:00
// CONSTANT VARIABLE
2013-07-09 08:20:50 +04:00
// Represent an empty node
2013-07-03 23:57:23 +04:00
var emptyNode = Node{".", PERMANENT, nil}
2013-07-09 08:20:50 +04:00
//------------------------------------------------------------------------------
//
// Methods
//
//------------------------------------------------------------------------------
2013-07-03 05:09:54 +04:00
2013-07-09 08:20:50 +04:00
// Set the key to the given value, return true if success
// If any intermidate path of the key is not a directory type, it will fail
// For example if the /foo = Node(bar) exists, set /foo/foo = Node(barbar)
// will fail.
func (t *tree) set(key string, value Node) bool {
2013-07-03 05:09:54 +04:00
2013-07-09 08:20:50 +04:00
nodesName := split(key)
2013-07-03 05:09:54 +04:00
2013-07-06 03:22:45 +04:00
nodeMap := t.Root.NodeMap
2013-07-03 05:09:54 +04:00
i := 0
newDir := false
2013-07-09 08:20:50 +04:00
// go through all the path
2013-07-16 21:44:09 +04:00
for i = 0; i < len(nodesName)-1; i++ {
2013-07-03 05:09:54 +04:00
2013-07-09 08:20:50 +04:00
// if we meet a new directory, all the directory after it must be new
2013-07-03 05:09:54 +04:00
if newDir {
2013-07-09 08:20:50 +04:00
tn := &treeNode{emptyNode, true, make(map[string]*treeNode)}
nodeMap[nodesName[i]] = tn
nodeMap = tn.NodeMap
2013-07-03 05:09:54 +04:00
continue
}
2013-07-09 08:20:50 +04:00
// get the node from the nodeMap of the current level
tn, ok := nodeMap[nodesName[i]]
2013-07-16 21:40:41 +04:00
2013-07-03 05:09:54 +04:00
if !ok {
2013-07-09 08:20:50 +04:00
// add a new directory and set newDir to true
2013-07-03 05:09:54 +04:00
newDir = true
2013-07-09 08:20:50 +04:00
tn := &treeNode{emptyNode, true, make(map[string]*treeNode)}
nodeMap[nodesName[i]] = tn
nodeMap = tn.NodeMap
2013-07-03 05:09:54 +04:00
2013-07-09 08:20:50 +04:00
} else if ok && !tn.Dir {
2013-07-03 05:09:54 +04:00
2013-07-16 21:40:41 +04:00
// if we meet a non-directory node, we cannot set the key
2013-07-03 23:57:23 +04:00
return false
2013-07-03 05:09:54 +04:00
} else {
2013-07-09 08:20:50 +04:00
// update the nodeMap to next level
nodeMap = tn.NodeMap
2013-07-03 05:09:54 +04:00
}
}
2013-07-09 08:20:50 +04:00
// Add the last node
tn, ok := nodeMap[nodesName[i]]
2013-07-03 05:09:54 +04:00
if !ok {
2013-07-09 08:20:50 +04:00
// we add a new treeNode
tn := &treeNode{value, false, nil}
nodeMap[nodesName[i]] = tn
2013-07-16 21:40:41 +04:00
2013-07-03 05:09:54 +04:00
} else {
2013-07-13 03:36:21 +04:00
if tn.Dir {
return false
}
2013-07-09 08:20:50 +04:00
// we change the value of a old Treenode
tn.InternalNode = value
2013-07-03 05:09:54 +04:00
}
2013-07-03 23:57:23 +04:00
return true
2013-07-03 05:09:54 +04:00
}
2013-07-16 21:40:41 +04:00
// Get the tree node of the key
2013-07-16 21:44:09 +04:00
func (t *tree) internalGet(key string) (*treeNode, bool) {
2013-07-09 08:20:50 +04:00
nodesName := split(key)
2013-07-03 05:09:54 +04:00
2013-07-06 03:22:45 +04:00
nodeMap := t.Root.NodeMap
2013-07-16 21:40:41 +04:00
2013-07-03 05:09:54 +04:00
var i int
2013-07-16 21:44:09 +04:00
for i = 0; i < len(nodesName)-1; i++ {
2013-07-09 08:20:50 +04:00
node, ok := nodeMap[nodesName[i]]
2013-07-03 05:09:54 +04:00
if !ok || !node.Dir {
2013-07-06 03:22:45 +04:00
return nil, false
2013-07-03 05:09:54 +04:00
}
nodeMap = node.NodeMap
}
2013-07-09 08:20:50 +04:00
tn, ok := nodeMap[nodesName[i]]
2013-07-06 03:22:45 +04:00
if ok {
2013-07-09 08:20:50 +04:00
return tn, ok
2013-07-06 03:22:45 +04:00
} else {
return nil, ok
}
2013-07-16 21:40:41 +04:00
}
2013-07-06 03:22:45 +04:00
2013-07-09 08:20:50 +04:00
// get the internalNode of the key
2013-07-06 03:22:45 +04:00
func (t *tree) get(key string) (Node, bool) {
2013-07-09 08:20:50 +04:00
tn, ok := t.internalGet(key)
2013-07-06 03:22:45 +04:00
2013-07-03 05:09:54 +04:00
if ok {
2013-07-12 21:10:56 +04:00
if tn.Dir {
return emptyNode, false
}
2013-07-09 08:20:50 +04:00
return tn.InternalNode, ok
2013-07-03 23:57:23 +04:00
} else {
return emptyNode, ok
2013-07-03 05:09:54 +04:00
}
2013-07-06 03:22:45 +04:00
}
2013-07-12 21:10:56 +04:00
// get the internalNode of the key
func (t *tree) list(directory string) ([]Node, []string, []bool, bool) {
2013-07-09 08:20:50 +04:00
treeNode, ok := t.internalGet(directory)
2013-07-03 05:09:54 +04:00
2013-07-06 03:22:45 +04:00
if !ok {
return nil, nil, nil, ok
} else {
2013-07-12 21:10:56 +04:00
if !treeNode.Dir {
nodes := make([]Node, 1)
nodes[0] = treeNode.InternalNode
return nodes, make([]string, 1), make([]bool, 1), true
2013-07-16 21:40:41 +04:00
}
2013-07-06 03:22:45 +04:00
length := len(treeNode.NodeMap)
nodes := make([]Node, length)
keys := make([]string, length)
2013-07-12 21:10:56 +04:00
dirs := make([]bool, length)
2013-07-06 03:22:45 +04:00
i := 0
for key, node := range treeNode.NodeMap {
2013-07-09 08:20:50 +04:00
nodes[i] = node.InternalNode
2013-07-06 03:22:45 +04:00
keys[i] = key
if node.Dir {
2013-07-12 21:10:56 +04:00
dirs[i] = true
2013-07-06 03:22:45 +04:00
} else {
2013-07-12 21:10:56 +04:00
dirs[i] = false
2013-07-06 03:22:45 +04:00
}
i++
}
return nodes, keys, dirs, ok
}
2013-07-03 05:09:54 +04:00
}
2013-07-09 08:20:50 +04:00
// delete the key, return true if success
2013-07-06 03:22:45 +04:00
func (t *tree) delete(key string) bool {
2013-07-09 08:20:50 +04:00
nodesName := split(key)
2013-07-03 05:09:54 +04:00
2013-07-06 03:22:45 +04:00
nodeMap := t.Root.NodeMap
2013-07-16 21:40:41 +04:00
2013-07-03 05:09:54 +04:00
var i int
2013-07-16 21:44:09 +04:00
for i = 0; i < len(nodesName)-1; i++ {
2013-07-09 08:20:50 +04:00
node, ok := nodeMap[nodesName[i]]
2013-07-03 05:09:54 +04:00
if !ok || !node.Dir {
2013-07-03 23:57:23 +04:00
return false
2013-07-03 05:09:54 +04:00
}
nodeMap = node.NodeMap
}
2013-07-09 08:20:50 +04:00
node, ok := nodeMap[nodesName[i]]
2013-07-16 21:44:09 +04:00
if ok && !node.Dir {
2013-07-09 08:20:50 +04:00
delete(nodeMap, nodesName[i])
2013-07-03 23:57:23 +04:00
return true
2013-07-03 05:09:54 +04:00
}
2013-07-03 23:57:23 +04:00
return false
2013-07-03 05:09:54 +04:00
}
2013-07-09 08:20:50 +04:00
// traverse wrapper
func (t *tree) traverse(f func(string, *Node), sort bool) {
if sort {
sortDfs("", t.Root, f)
} else {
2013-07-16 21:40:41 +04:00
dfs("", t.Root, f)
}
2013-07-04 02:00:50 +04:00
}
2013-07-16 21:40:41 +04:00
// deep first search to traverse the tree
2013-07-09 08:20:50 +04:00
// apply the func f to each internal node
func dfs(key string, t *treeNode, f func(string, *Node)) {
2013-07-09 08:20:50 +04:00
// base case
2013-07-16 21:44:09 +04:00
if len(t.NodeMap) == 0 {
2013-07-09 08:20:50 +04:00
f(key, &t.InternalNode)
2013-07-16 21:44:09 +04:00
// recursion
2013-07-04 02:00:50 +04:00
} else {
2013-07-09 08:20:50 +04:00
for tnKey, tn := range t.NodeMap {
tnKey := key + "/" + tnKey
dfs(tnKey, tn, f)
}
}
}
2013-07-09 08:20:50 +04:00
// sort deep first search to traverse the tree
// apply the func f to each internal node
func sortDfs(key string, t *treeNode, f func(string, *Node)) {
// base case
2013-07-16 21:44:09 +04:00
if len(t.NodeMap) == 0 {
2013-07-09 08:20:50 +04:00
f(key, &t.InternalNode)
2013-07-16 21:44:09 +04:00
// recursion
} else {
s := make(tnWithKeySlice, len(t.NodeMap))
i := 0
// copy
2013-07-09 08:20:50 +04:00
for tnKey, tn := range t.NodeMap {
tnKey := key + "/" + tnKey
s[i] = tnWithKey{tnKey, tn}
i++
}
// sort
sort.Sort(s)
// traverse
for i = 0; i < len(t.NodeMap); i++ {
sortDfs(s[i].key, s[i].tn, f)
2013-07-04 02:00:50 +04:00
}
}
}
2013-07-09 08:20:50 +04:00
// split the key by '/', get the intermediate node name
func split(key string) []string {
key = "/" + key
key = path.Clean(key)
2013-07-04 02:35:25 +04:00
2013-07-09 08:20:50 +04:00
// get the intermidate nodes name
nodesName := strings.Split(key, "/")
// we do not need the root node, since we start with it
nodesName = nodesName[1:]
return nodesName
}