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  }