github.com/alpe/etcd@v0.1.2-0.20130915230056-09f31af88aeb/store/tree.go (about) 1 package store 2 3 import ( 4 "path" 5 "sort" 6 "strings" 7 "time" 8 ) 9 10 //------------------------------------------------------------------------------ 11 // 12 // Typedefs 13 // 14 //------------------------------------------------------------------------------ 15 16 // A file system like tree structure. Each non-leaf node of the tree has a hashmap to 17 // store its children nodes. Leaf nodes has no hashmap (a nil pointer) 18 type tree struct { 19 Root *treeNode 20 } 21 22 // A treeNode wraps a Node. It has a hashmap to keep records of its children treeNodes. 23 type treeNode struct { 24 InternalNode Node 25 Dir bool 26 NodeMap map[string]*treeNode 27 } 28 29 // TreeNode with its key. We use it when we need to sort the treeNodes. 30 type tnWithKey struct { 31 key string 32 tn *treeNode 33 } 34 35 // Define type and functions to match sort interface 36 type tnWithKeySlice []tnWithKey 37 38 func (s tnWithKeySlice) Len() int { return len(s) } 39 func (s tnWithKeySlice) Less(i, j int) bool { return s[i].key < s[j].key } 40 func (s tnWithKeySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 41 42 // CONSTANT VARIABLE 43 44 // Represent an empty node 45 var emptyNode = Node{"", PERMANENT, nil} 46 47 //------------------------------------------------------------------------------ 48 // 49 // Methods 50 // 51 //------------------------------------------------------------------------------ 52 53 // Set the key to the given value, return true if success 54 // If any intermidate path of the key is not a directory type, it will fail 55 // For example if the /foo = Node(bar) exists, set /foo/foo = Node(barbar) 56 // will fail. 57 func (t *tree) set(key string, value Node) bool { 58 59 nodesName := split(key) 60 61 // avoid set value to "/" 62 if len(nodesName) == 1 && len(nodesName[0]) == 0 { 63 return false 64 } 65 66 nodeMap := t.Root.NodeMap 67 68 i := 0 69 newDir := false 70 71 // go through all the path 72 for i = 0; i < len(nodesName)-1; i++ { 73 74 // if we meet a new directory, all the directory after it must be new 75 if newDir { 76 tn := &treeNode{emptyNode, true, make(map[string]*treeNode)} 77 nodeMap[nodesName[i]] = tn 78 nodeMap = tn.NodeMap 79 continue 80 } 81 82 // get the node from the nodeMap of the current level 83 tn, ok := nodeMap[nodesName[i]] 84 85 if !ok { 86 // add a new directory and set newDir to true 87 newDir = true 88 tn := &treeNode{emptyNode, true, make(map[string]*treeNode)} 89 nodeMap[nodesName[i]] = tn 90 nodeMap = tn.NodeMap 91 92 } else if ok && !tn.Dir { 93 94 // if we meet a non-directory node, we cannot set the key 95 return false 96 } else { 97 98 // update the nodeMap to next level 99 nodeMap = tn.NodeMap 100 } 101 102 } 103 104 // Add the last node 105 tn, ok := nodeMap[nodesName[i]] 106 107 if !ok { 108 // we add a new treeNode 109 tn := &treeNode{value, false, nil} 110 nodeMap[nodesName[i]] = tn 111 112 } else { 113 if tn.Dir { 114 return false 115 } 116 // we change the value of a old Treenode 117 tn.InternalNode = value 118 } 119 return true 120 121 } 122 123 // Get the tree node of the key 124 func (t *tree) internalGet(key string) (*treeNode, bool) { 125 nodesName := split(key) 126 127 // should be able to get root 128 if len(nodesName) == 1 && nodesName[0] == "" { 129 return t.Root, true 130 } 131 132 nodeMap := t.Root.NodeMap 133 134 var i int 135 136 for i = 0; i < len(nodesName)-1; i++ { 137 node, ok := nodeMap[nodesName[i]] 138 if !ok || !node.Dir { 139 return nil, false 140 } 141 nodeMap = node.NodeMap 142 } 143 144 tn, ok := nodeMap[nodesName[i]] 145 if ok { 146 return tn, ok 147 } else { 148 return nil, ok 149 } 150 } 151 152 // get the internalNode of the key 153 func (t *tree) get(key string) (Node, bool) { 154 tn, ok := t.internalGet(key) 155 156 if ok { 157 if tn.Dir { 158 return emptyNode, false 159 } 160 return tn.InternalNode, ok 161 } else { 162 return emptyNode, ok 163 } 164 } 165 166 // get the internalNode of the key 167 func (t *tree) list(directory string) (interface{}, []string, bool) { 168 treeNode, ok := t.internalGet(directory) 169 170 if !ok { 171 return nil, nil, ok 172 173 } else { 174 if !treeNode.Dir { 175 return &treeNode.InternalNode, nil, ok 176 } 177 length := len(treeNode.NodeMap) 178 nodes := make([]*Node, length) 179 keys := make([]string, length) 180 181 i := 0 182 for key, node := range treeNode.NodeMap { 183 nodes[i] = &node.InternalNode 184 keys[i] = key 185 i++ 186 } 187 188 return nodes, keys, ok 189 } 190 } 191 192 // delete the key, return true if success 193 func (t *tree) delete(key string) bool { 194 nodesName := split(key) 195 196 nodeMap := t.Root.NodeMap 197 198 var i int 199 200 for i = 0; i < len(nodesName)-1; i++ { 201 node, ok := nodeMap[nodesName[i]] 202 if !ok || !node.Dir { 203 return false 204 } 205 nodeMap = node.NodeMap 206 } 207 208 node, ok := nodeMap[nodesName[i]] 209 if ok && !node.Dir { 210 delete(nodeMap, nodesName[i]) 211 return true 212 } 213 return false 214 } 215 216 // traverse wrapper 217 func (t *tree) traverse(f func(string, *Node), sort bool) { 218 if sort { 219 sortDfs("", t.Root, f) 220 } else { 221 dfs("", t.Root, f) 222 } 223 } 224 225 // clone() will return a deep cloned tree 226 func (t *tree) clone() *tree { 227 newTree := new(tree) 228 newTree.Root = &treeNode{ 229 Node{ 230 "/", 231 time.Unix(0, 0), 232 nil, 233 }, 234 true, 235 make(map[string]*treeNode), 236 } 237 recursiveClone(t.Root, newTree.Root) 238 return newTree 239 } 240 241 // recursiveClone is a helper function for clone() 242 func recursiveClone(tnSrc *treeNode, tnDes *treeNode) { 243 if !tnSrc.Dir { 244 tnDes.InternalNode = tnSrc.InternalNode 245 return 246 247 } else { 248 tnDes.InternalNode = tnSrc.InternalNode 249 tnDes.Dir = true 250 tnDes.NodeMap = make(map[string]*treeNode) 251 252 for key, tn := range tnSrc.NodeMap { 253 newTn := new(treeNode) 254 recursiveClone(tn, newTn) 255 tnDes.NodeMap[key] = newTn 256 } 257 258 } 259 } 260 261 // deep first search to traverse the tree 262 // apply the func f to each internal node 263 func dfs(key string, t *treeNode, f func(string, *Node)) { 264 265 // base case 266 if len(t.NodeMap) == 0 { 267 f(key, &t.InternalNode) 268 269 // recursion 270 } else { 271 for tnKey, tn := range t.NodeMap { 272 tnKey := key + "/" + tnKey 273 dfs(tnKey, tn, f) 274 } 275 } 276 } 277 278 // sort deep first search to traverse the tree 279 // apply the func f to each internal node 280 func sortDfs(key string, t *treeNode, f func(string, *Node)) { 281 // base case 282 if len(t.NodeMap) == 0 { 283 f(key, &t.InternalNode) 284 285 // recursion 286 } else { 287 288 s := make(tnWithKeySlice, len(t.NodeMap)) 289 i := 0 290 291 // copy 292 for tnKey, tn := range t.NodeMap { 293 tnKey := key + "/" + tnKey 294 s[i] = tnWithKey{tnKey, tn} 295 i++ 296 } 297 298 // sort 299 sort.Sort(s) 300 301 // traverse 302 for i = 0; i < len(t.NodeMap); i++ { 303 sortDfs(s[i].key, s[i].tn, f) 304 } 305 } 306 } 307 308 // split the key by '/', get the intermediate node name 309 func split(key string) []string { 310 key = "/" + key 311 key = path.Clean(key) 312 313 // get the intermidate nodes name 314 nodesName := strings.Split(key, "/") 315 // we do not need the root node, since we start with it 316 nodesName = nodesName[1:] 317 return nodesName 318 }