mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
tree store init commit
This commit is contained in:
parent
ab285a90bb
commit
c5901f4b88
2
etcd.go
2
etcd.go
@ -212,7 +212,7 @@ func main() {
|
||||
}
|
||||
|
||||
// open the snapshot
|
||||
go server.Snapshot()
|
||||
//go server.Snapshot()
|
||||
|
||||
if webPort != -1 {
|
||||
// start web
|
||||
|
@ -1,85 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type store struct {
|
||||
nodes map[string]node
|
||||
}
|
||||
|
||||
type node struct {
|
||||
value string
|
||||
dir bool // just for clearity
|
||||
nodes map[string]node
|
||||
}
|
||||
|
||||
// set the key to value, return the old value if the key exists
|
||||
func (s *store) set(key string, value string) string, error {
|
||||
|
||||
key = path.Clean(key)
|
||||
|
||||
nodeNames := strings.Split(key, "/")
|
||||
|
||||
levelNodes := s.nodes
|
||||
for i = 0; i < len(nodes) - 1; ++i {
|
||||
node, ok := levelNodes[nodeNames[i]]
|
||||
// add new dir
|
||||
if !ok {
|
||||
node := Node{nodeNames[i], true, make(map[string]node)}
|
||||
levelNodes[nodeNames[i]] := node
|
||||
} else if ok && !node.dir {
|
||||
return nil, errors.New("The key is a directory")
|
||||
}
|
||||
else {
|
||||
levelNodes = levelNodes.nodes
|
||||
}
|
||||
}
|
||||
// add the last node and value
|
||||
node, ok := levelNodes[nodeNames[i]]
|
||||
|
||||
if !ok {
|
||||
node := Node{nodeNames[i], false, nil}
|
||||
levelNodes[nodeNames] = node
|
||||
return nil, nil
|
||||
} else {
|
||||
oldValue := node.value
|
||||
node.value = value
|
||||
return oldValue ,nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get the node of the key
|
||||
func (s *store) get(key string) node {
|
||||
key = path.Clean(key)
|
||||
|
||||
nodeNames := strings.Split(key, "/")
|
||||
|
||||
levelNodes := s.nodes
|
||||
|
||||
for i = 0; i < len(nodes) - 1; ++i {
|
||||
node, ok := levelNodes[nodeNames[i]]
|
||||
if !ok || !node.dir {
|
||||
return nil
|
||||
}
|
||||
levelNodes = levelNodes.nodes
|
||||
}
|
||||
|
||||
node, ok := levelNodes[nodeNames[i]]
|
||||
if ok {
|
||||
return node
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// delete the key, return the old value if the key exists
|
||||
func (s *store) delete(key string) string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *node) Value() string{
|
||||
return n.value
|
||||
}
|
150
store/tree_store.go
Normal file
150
store/tree_store.go
Normal file
@ -0,0 +1,150 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
"errors"
|
||||
//"fmt"
|
||||
)
|
||||
|
||||
type treeStore struct {
|
||||
Root *treeNode
|
||||
}
|
||||
|
||||
type treeNode struct {
|
||||
Value string
|
||||
|
||||
Dir bool //for clearity
|
||||
|
||||
NodeMap map[string]*treeNode
|
||||
|
||||
// if the node is a permanent one the ExprieTime will be Unix(0,0)
|
||||
// Otherwise after the expireTime, the node will be deleted
|
||||
ExpireTime time.Time `json:"expireTime"`
|
||||
|
||||
// a channel to update the expireTime of the node
|
||||
update chan time.Time `json:"-"`
|
||||
}
|
||||
|
||||
// set the key to value, return the old value if the key exists
|
||||
func (s *treeStore) set(key string, value string, expireTime time.Time, index uint64) (string, error) {
|
||||
key = "/" + key
|
||||
key = path.Clean(key)
|
||||
|
||||
nodes := strings.Split(key, "/")
|
||||
nodes = nodes[1:]
|
||||
|
||||
//fmt.Println("TreeStore: Nodes ", nodes, " length: ", len(nodes))
|
||||
|
||||
nodeMap := s.Root.NodeMap
|
||||
|
||||
i := 0
|
||||
newDir := false
|
||||
|
||||
for i = 0; i < len(nodes) - 1; i++ {
|
||||
|
||||
if newDir {
|
||||
node := &treeNode{".", true, make(map[string]*treeNode)}
|
||||
nodeMap[nodes[i]] = node
|
||||
nodeMap = node.NodeMap
|
||||
continue
|
||||
}
|
||||
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
// add new dir
|
||||
if !ok {
|
||||
//fmt.Println("TreeStore: Add a dir ", nodes[i])
|
||||
newDir = true
|
||||
node := &treeNode{".", true, make(map[string]*treeNode)}
|
||||
nodeMap[nodes[i]] = node
|
||||
nodeMap = node.NodeMap
|
||||
|
||||
} else if ok && !node.Dir {
|
||||
|
||||
return "", errors.New("Try to add a key under a file")
|
||||
} else {
|
||||
|
||||
//fmt.Println("TreeStore: found dir ", nodes[i])
|
||||
nodeMap = node.NodeMap
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add the last node and value
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
|
||||
if !ok {
|
||||
node := &treeNode{value, false, nil}
|
||||
nodeMap[nodes[i]] = node
|
||||
//fmt.Println("TreeStore: Add a new Node ", key, "=", value)
|
||||
return "", nil
|
||||
} else {
|
||||
oldValue := node.Value
|
||||
node.Value = value
|
||||
//fmt.Println("TreeStore: Update a Node ", key, "=", value, "[", oldValue, "]")
|
||||
return oldValue ,nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get the node of the key
|
||||
func (s *treeStore) get(key string) *treeNode {
|
||||
key = "/" + key
|
||||
key = path.Clean(key)
|
||||
|
||||
nodes := strings.Split(key, "/")
|
||||
nodes = nodes[1:]
|
||||
|
||||
//fmt.Println("TreeStore: Nodes ", nodes, " length: ", len(nodes))
|
||||
|
||||
nodeMap := s.Root.NodeMap
|
||||
|
||||
var i int
|
||||
|
||||
for i = 0; i < len(nodes) - 1; i++ {
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if !ok || !node.Dir {
|
||||
return nil
|
||||
}
|
||||
nodeMap = node.NodeMap
|
||||
}
|
||||
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if ok {
|
||||
return node
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// delete the key, return the old value if the key exists
|
||||
func (s *treeStore) delete(key string) string {
|
||||
key = "/" + key
|
||||
key = path.Clean(key)
|
||||
|
||||
nodes := strings.Split(key, "/")
|
||||
nodes = nodes[1:]
|
||||
|
||||
//fmt.Println("TreeStore: Nodes ", nodes, " length: ", len(nodes))
|
||||
|
||||
nodeMap := s.Root.NodeMap
|
||||
|
||||
var i int
|
||||
|
||||
for i = 0; i < len(nodes) - 1; i++ {
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if !ok || !node.Dir {
|
||||
return ""
|
||||
}
|
||||
nodeMap = node.NodeMap
|
||||
}
|
||||
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if ok && !node.Dir{
|
||||
oldValue := node.Value
|
||||
delete(nodeMap, nodes[i])
|
||||
return oldValue
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
82
store/tree_store_test.go
Normal file
82
store/tree_store_test.go
Normal file
@ -0,0 +1,82 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func TestStoreGet(t *testing.T) {
|
||||
|
||||
ts := &treeStore{
|
||||
&treeNode{
|
||||
"/",
|
||||
true,
|
||||
make(map[string]*treeNode),
|
||||
},
|
||||
}
|
||||
|
||||
// create key
|
||||
ts.set("/foo", "bar")
|
||||
// change value
|
||||
ts.set("/foo", "barbar")
|
||||
// create key
|
||||
ts.set("/hello/foo", "barbarbar")
|
||||
treeNode := ts.get("/foo")
|
||||
|
||||
if treeNode == nil {
|
||||
t.Fatalf("Expect to get node, but not")
|
||||
}
|
||||
if treeNode.Value != "barbar" {
|
||||
t.Fatalf("Expect value barbar, but got %s", treeNode.Value)
|
||||
}
|
||||
|
||||
// create key
|
||||
treeNode = ts.get("/hello/foo")
|
||||
if treeNode == nil {
|
||||
t.Fatalf("Expect to get node, but not")
|
||||
}
|
||||
if treeNode.Value != "barbarbar" {
|
||||
t.Fatalf("Expect value barbarbar, but got %s", treeNode.Value)
|
||||
}
|
||||
|
||||
// create a key under other key
|
||||
_, err := ts.set("/foo/foo", "bar")
|
||||
if err == nil {
|
||||
t.Fatalf("shoud not add key under a exisiting key")
|
||||
}
|
||||
|
||||
// delete a key
|
||||
oldValue := ts.delete("/foo")
|
||||
if oldValue != "barbar" {
|
||||
t.Fatalf("Expect Oldvalue bar, but got %s", oldValue)
|
||||
}
|
||||
|
||||
// delete a directory
|
||||
oldValue = ts.delete("/hello")
|
||||
if oldValue != "" {
|
||||
t.Fatalf("Expect cannot delet /hello, but deleted! %s", oldValue)
|
||||
}
|
||||
|
||||
|
||||
// speed test
|
||||
for i:=0; i < 10000; i++ {
|
||||
key := "/"
|
||||
depth := rand.Intn(10)
|
||||
for j := 0; j < depth; j++ {
|
||||
key += "/" + strconv.Itoa(rand.Int())
|
||||
}
|
||||
value := strconv.Itoa(rand.Int())
|
||||
ts.set(key, value)
|
||||
treeNode := ts.get(key)
|
||||
|
||||
if treeNode == nil {
|
||||
t.Fatalf("Expect to get node, but not")
|
||||
}
|
||||
if treeNode.Value != value {
|
||||
t.Fatalf("Expect value %s, but got %s", value, treeNode.Value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user