mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
treeStruct first commit
This commit is contained in:
parent
c5901f4b88
commit
6e3379c3ef
@ -22,9 +22,11 @@ const (
|
||||
var PERMANENT = time.Unix(0, 0)
|
||||
|
||||
type Store struct {
|
||||
// use the build-in hash map as the key-value store structure
|
||||
Nodes map[string]Node `json:"nodes"`
|
||||
// // use the build-in hash map as the key-value store structure
|
||||
// Nodes map[string]Node `json:"nodes"`
|
||||
|
||||
// use treeMap as the key-value stroe structure
|
||||
Tree *tree
|
||||
// the string channel to send messages to the outside world
|
||||
// now we use it to send changes to the hub of the web service
|
||||
messager *chan string
|
||||
@ -77,11 +79,23 @@ type Response struct {
|
||||
func CreateStore(max int) *Store {
|
||||
s = new(Store)
|
||||
s.messager = nil
|
||||
s.Nodes = make(map[string]Node)
|
||||
s.ResponseMap = make(map[string]Response)
|
||||
s.ResponseStartIndex = 0
|
||||
s.ResponseMaxSize = max
|
||||
s.ResponseCurrSize = 0
|
||||
|
||||
s.Tree = &tree{
|
||||
&treeNode{
|
||||
Node {
|
||||
"/",
|
||||
time.Unix(0,0),
|
||||
nil,
|
||||
},
|
||||
true,
|
||||
make(map[string]*treeNode),
|
||||
},
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
@ -125,7 +139,7 @@ func Set(key string, value string, expireTime time.Time, index uint64) ([]byte,
|
||||
}
|
||||
|
||||
// get the node
|
||||
node, ok := s.Nodes[key]
|
||||
node, ok := s.Tree.get(key)
|
||||
|
||||
if ok {
|
||||
// if node is not permanent before
|
||||
@ -145,7 +159,7 @@ func Set(key string, value string, expireTime time.Time, index uint64) ([]byte,
|
||||
}
|
||||
|
||||
// update the information of the node
|
||||
s.Nodes[key] = Node{value, expireTime, node.update}
|
||||
s.Tree.set(key, Node{value, expireTime, node.update})
|
||||
|
||||
resp := Response{SET, key, node.Value, value, true, expireTime, TTL, index}
|
||||
|
||||
@ -168,7 +182,7 @@ func Set(key string, value string, expireTime time.Time, index uint64) ([]byte,
|
||||
|
||||
update := make(chan time.Time)
|
||||
|
||||
s.Nodes[key] = Node{value, expireTime, update}
|
||||
s.Tree.set(key, Node{value, expireTime, update})
|
||||
|
||||
if isExpire {
|
||||
go expire(key, update, expireTime)
|
||||
@ -200,12 +214,12 @@ func expire(key string, update chan time.Time, expireTime time.Time) {
|
||||
select {
|
||||
// timeout delete the node
|
||||
case <-time.After(duration):
|
||||
node, ok := s.Nodes[key]
|
||||
node, ok := s.Tree.get(key)
|
||||
if !ok {
|
||||
return
|
||||
} else {
|
||||
|
||||
delete(s.Nodes, key)
|
||||
s.Tree.delete(key)
|
||||
|
||||
resp := Response{DELETE, key, node.Value, "", true, node.ExpireTime, 0, s.Index}
|
||||
|
||||
@ -267,7 +281,7 @@ func Get(key string) Response {
|
||||
|
||||
key = path.Clean(key)
|
||||
|
||||
node, ok := s.Nodes[key]
|
||||
node, ok := s.Tree.get(key)
|
||||
|
||||
if ok {
|
||||
var TTL int64
|
||||
@ -298,19 +312,19 @@ func Delete(key string, index uint64) ([]byte, error) {
|
||||
|
||||
key = path.Clean(key)
|
||||
|
||||
node, ok := s.Nodes[key]
|
||||
node, ok := s.Tree.get(key)
|
||||
|
||||
if ok {
|
||||
|
||||
if node.ExpireTime.Equal(PERMANENT) {
|
||||
|
||||
delete(s.Nodes, key)
|
||||
s.Tree.delete(key)
|
||||
|
||||
} else {
|
||||
|
||||
// kill the expire go routine
|
||||
node.update <- PERMANENT
|
||||
delete(s.Nodes, key)
|
||||
s.Tree.delete(key)
|
||||
|
||||
}
|
||||
|
||||
@ -361,21 +375,21 @@ func (s *Store) Recovery(state []byte) error {
|
||||
|
||||
// clean all expired keys
|
||||
func clean() {
|
||||
for key, node := range s.Nodes {
|
||||
// for key, node := range s.Nodes {
|
||||
|
||||
if node.ExpireTime.Equal(PERMANENT) {
|
||||
continue
|
||||
} else {
|
||||
// if node.ExpireTime.Equal(PERMANENT) {
|
||||
// continue
|
||||
// } else {
|
||||
|
||||
if node.ExpireTime.Sub(time.Now()) >= time.Second {
|
||||
node.update = make(chan time.Time)
|
||||
go expire(key, node.update, node.ExpireTime)
|
||||
// if node.ExpireTime.Sub(time.Now()) >= time.Second {
|
||||
// node.update = make(chan time.Time)
|
||||
// go expire(key, node.update, node.ExpireTime)
|
||||
|
||||
} else {
|
||||
// we should delete this node
|
||||
delete(s.Nodes, key)
|
||||
}
|
||||
}
|
||||
// } else {
|
||||
// // we should delete this node
|
||||
// delete(s.Nodes, key)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
@ -3,31 +3,26 @@ package store
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
"errors"
|
||||
//"fmt"
|
||||
)
|
||||
|
||||
type treeStore struct {
|
||||
type tree struct {
|
||||
Root *treeNode
|
||||
}
|
||||
|
||||
type treeNode struct {
|
||||
Value string
|
||||
|
||||
Value Node
|
||||
|
||||
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:"-"`
|
||||
}
|
||||
|
||||
var emptyNode = Node{".", PERMANENT, nil}
|
||||
|
||||
// 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) {
|
||||
func (s *tree) set(key string, value Node) bool {
|
||||
key = "/" + key
|
||||
key = path.Clean(key)
|
||||
|
||||
@ -44,7 +39,7 @@ func (s *treeStore) set(key string, value string, expireTime time.Time, index ui
|
||||
for i = 0; i < len(nodes) - 1; i++ {
|
||||
|
||||
if newDir {
|
||||
node := &treeNode{".", true, make(map[string]*treeNode)}
|
||||
node := &treeNode{emptyNode, true, make(map[string]*treeNode)}
|
||||
nodeMap[nodes[i]] = node
|
||||
nodeMap = node.NodeMap
|
||||
continue
|
||||
@ -55,13 +50,13 @@ func (s *treeStore) set(key string, value string, expireTime time.Time, index ui
|
||||
if !ok {
|
||||
//fmt.Println("TreeStore: Add a dir ", nodes[i])
|
||||
newDir = true
|
||||
node := &treeNode{".", true, make(map[string]*treeNode)}
|
||||
node := &treeNode{emptyNode, 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")
|
||||
return false
|
||||
} else {
|
||||
|
||||
//fmt.Println("TreeStore: found dir ", nodes[i])
|
||||
@ -77,18 +72,16 @@ func (s *treeStore) set(key string, value string, expireTime time.Time, index ui
|
||||
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
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// get the node of the key
|
||||
func (s *treeStore) get(key string) *treeNode {
|
||||
func (s *tree) get(key string) (Node, bool) {
|
||||
key = "/" + key
|
||||
key = path.Clean(key)
|
||||
|
||||
@ -104,21 +97,22 @@ func (s *treeStore) get(key string) *treeNode {
|
||||
for i = 0; i < len(nodes) - 1; i++ {
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if !ok || !node.Dir {
|
||||
return nil
|
||||
return emptyNode, false
|
||||
}
|
||||
nodeMap = node.NodeMap
|
||||
}
|
||||
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
treeNode, ok := nodeMap[nodes[i]]
|
||||
if ok {
|
||||
return node
|
||||
return treeNode.Value, ok
|
||||
} else {
|
||||
return emptyNode, ok
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// delete the key, return the old value if the key exists
|
||||
func (s *treeStore) delete(key string) string {
|
||||
func (s *tree) delete(key string) bool {
|
||||
key = "/" + key
|
||||
key = path.Clean(key)
|
||||
|
||||
@ -134,17 +128,16 @@ func (s *treeStore) delete(key string) string {
|
||||
for i = 0; i < len(nodes) - 1; i++ {
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if !ok || !node.Dir {
|
||||
return ""
|
||||
return false
|
||||
}
|
||||
nodeMap = node.NodeMap
|
||||
}
|
||||
|
||||
node, ok := nodeMap[nodes[i]]
|
||||
if ok && !node.Dir{
|
||||
oldValue := node.Value
|
||||
delete(nodeMap, nodes[i])
|
||||
return oldValue
|
||||
return true
|
||||
}
|
||||
return ""
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
func TestStoreGet(t *testing.T) {
|
||||
|
||||
ts := &treeStore{
|
||||
ts := &tree{
|
||||
&treeNode{
|
||||
"/",
|
||||
true,
|
||||
|
20
web/web.go
20
web/web.go
@ -4,10 +4,10 @@ import (
|
||||
"code.google.com/p/go.net/websocket"
|
||||
"fmt"
|
||||
"github.com/xiangli-cmu/go-raft"
|
||||
"github.com/xiangli-cmu/raft-etcd/store"
|
||||
//"github.com/xiangli-cmu/raft-etcd/store"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
//"time"
|
||||
)
|
||||
|
||||
var s *raft.Server
|
||||
@ -28,15 +28,15 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fmt.Fprintf(w, "Data\n")
|
||||
|
||||
s := store.GetStore()
|
||||
//s := store.GetStore()
|
||||
|
||||
for key, node := range s.Nodes {
|
||||
if node.ExpireTime.Equal(time.Unix(0, 0)) {
|
||||
fmt.Fprintf(w, "%s %s\n", key, node.Value)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s %s %s\n", key, node.Value, node.ExpireTime)
|
||||
}
|
||||
}
|
||||
// for key, node := range s.Nodes {
|
||||
// if node.ExpireTime.Equal(time.Unix(0, 0)) {
|
||||
// fmt.Fprintf(w, "%s %s\n", key, node.Value)
|
||||
// } else {
|
||||
// fmt.Fprintf(w, "%s %s %s\n", key, node.Value, node.ExpireTime)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user