Browse Source

treeStruct first commit

Xiang Li 12 years ago
parent
commit
6e3379c3ef
4 changed files with 70 additions and 63 deletions
  1. 39 25
      store/store.go
  2. 20 27
      store/tree_store.go
  3. 1 1
      store/tree_store_test.go
  4. 10 10
      web/web.go

+ 39 - 25
store/store.go

@@ -22,9 +22,11 @@ const (
 var PERMANENT = time.Unix(0, 0)
 var PERMANENT = time.Unix(0, 0)
 
 
 type Store struct {
 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
 	// the string channel to send messages to the outside world
 	// now we use it to send changes to the hub of the web service
 	// now we use it to send changes to the hub of the web service
 	messager *chan string
 	messager *chan string
@@ -77,11 +79,23 @@ type Response struct {
 func CreateStore(max int) *Store {
 func CreateStore(max int) *Store {
 	s = new(Store)
 	s = new(Store)
 	s.messager = nil
 	s.messager = nil
-	s.Nodes = make(map[string]Node)
 	s.ResponseMap = make(map[string]Response)
 	s.ResponseMap = make(map[string]Response)
 	s.ResponseStartIndex = 0
 	s.ResponseStartIndex = 0
 	s.ResponseMaxSize = max
 	s.ResponseMaxSize = max
 	s.ResponseCurrSize = 0
 	s.ResponseCurrSize = 0
+
+	s.Tree = &tree{ 
+		&treeNode{ 
+			Node {
+				"/",
+				time.Unix(0,0),
+				nil,
+			},
+			true, 
+			make(map[string]*treeNode),
+		},
+	} 
+
 	return s
 	return s
 }
 }
 
 
@@ -125,7 +139,7 @@ func Set(key string, value string, expireTime time.Time, index uint64) ([]byte,
 	}
 	}
 
 
 	// get the node
 	// get the node
-	node, ok := s.Nodes[key]
+	node, ok := s.Tree.get(key)
 
 
 	if ok {
 	if ok {
 		// if node is not permanent before
 		// 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
 		// 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}
 		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)
 		update := make(chan time.Time)
 
 
-		s.Nodes[key] = Node{value, expireTime, update}
+		s.Tree.set(key, Node{value, expireTime, update})
 
 
 		if isExpire {
 		if isExpire {
 			go expire(key, update, expireTime)
 			go expire(key, update, expireTime)
@@ -200,12 +214,12 @@ func expire(key string, update chan time.Time, expireTime time.Time) {
 		select {
 		select {
 		// timeout delete the node
 		// timeout delete the node
 		case <-time.After(duration):
 		case <-time.After(duration):
-			node, ok := s.Nodes[key]
+			node, ok := s.Tree.get(key)
 			if !ok {
 			if !ok {
 				return
 				return
 			} else {
 			} else {
 
 
-				delete(s.Nodes, key)
+				s.Tree.delete(key)
 
 
 				resp := Response{DELETE, key, node.Value, "", true, node.ExpireTime, 0, s.Index}
 				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)
 	key = path.Clean(key)
 
 
-	node, ok := s.Nodes[key]
+	node, ok := s.Tree.get(key)
 
 
 	if ok {
 	if ok {
 		var TTL int64
 		var TTL int64
@@ -298,19 +312,19 @@ func Delete(key string, index uint64) ([]byte, error) {
 
 
 	key = path.Clean(key)
 	key = path.Clean(key)
 
 
-	node, ok := s.Nodes[key]
+	node, ok := s.Tree.get(key)
 
 
 	if ok {
 	if ok {
 
 
 		if node.ExpireTime.Equal(PERMANENT) {
 		if node.ExpireTime.Equal(PERMANENT) {
 
 
-			delete(s.Nodes, key)
+			s.Tree.delete(key)
 
 
 		} else {
 		} else {
 
 
 			// kill the expire go routine
 			// kill the expire go routine
 			node.update <- PERMANENT
 			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
 // clean all expired keys
 func clean() {
 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)
+	// 		}
+	// 	}
 
 
-	}
+	// }
 }
 }

+ 20 - 27
store/tree_store.go

@@ -3,31 +3,26 @@ package store
 import (
 import (
 	"path"
 	"path"
 	"strings"
 	"strings"
-	"errors"
-	//"fmt"
 	)
 	)
 
 
-type treeStore struct {
+type tree struct {
 	Root *treeNode
 	Root *treeNode
 }
 }
 
 
 type treeNode struct {
 type treeNode struct {
-	Value string
+
+	Value Node
 
 
 	Dir bool //for clearity
 	Dir bool //for clearity
 
 
 	NodeMap map[string]*treeNode
 	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 
 // 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 = "/" + key
 	key = path.Clean(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++ {
 	for i = 0; i < len(nodes) - 1; i++ {
 
 
 		if newDir {
 		if newDir {
-			node := &treeNode{".", true, make(map[string]*treeNode)}
+			node := &treeNode{emptyNode, true, make(map[string]*treeNode)}
 			nodeMap[nodes[i]] = node
 			nodeMap[nodes[i]] = node
 			nodeMap = node.NodeMap
 			nodeMap = node.NodeMap
 			continue
 			continue
@@ -55,13 +50,13 @@ func (s *treeStore) set(key string, value string, expireTime time.Time, index ui
 		if !ok {
 		if !ok {
 			//fmt.Println("TreeStore: Add a dir ", nodes[i])
 			//fmt.Println("TreeStore: Add a dir ", nodes[i])
 			newDir = true
 			newDir = true
-			node := &treeNode{".", true, make(map[string]*treeNode)}
+			node := &treeNode{emptyNode, true, make(map[string]*treeNode)}
 			nodeMap[nodes[i]] = node
 			nodeMap[nodes[i]] = node
 			nodeMap = node.NodeMap
 			nodeMap = node.NodeMap
 
 
 		} else if ok && !node.Dir {
 		} else if ok && !node.Dir {
 
 
-			return "", errors.New("Try to add a key under a file")
+			return false
 		} else {
 		} else {
 
 
 			//fmt.Println("TreeStore: found dir ", nodes[i])
 			//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}
 		node := &treeNode{value, false, nil}
 		nodeMap[nodes[i]] = node
 		nodeMap[nodes[i]] = node
 		//fmt.Println("TreeStore: Add a new Node ", key, "=", value)
 		//fmt.Println("TreeStore: Add a new Node ", key, "=", value)
-		return "", nil
 	} else {
 	} else {
-		oldValue := node.Value
 		node.Value = value
 		node.Value = value
 		//fmt.Println("TreeStore: Update a Node ", key, "=", value, "[", oldValue, "]")
 		//fmt.Println("TreeStore: Update a Node ", key, "=", value, "[", oldValue, "]")
-		return oldValue ,nil
 	}
 	}
+	return true
 
 
 }
 }
 
 
 // get the node of the key
 // get the node of the key
-func (s *treeStore) get(key string) *treeNode {
+func (s *tree) get(key string) (Node, bool) {
 	key = "/" + key
 	key = "/" + key
 	key = path.Clean(key)
 	key = path.Clean(key)
 
 
@@ -104,21 +97,22 @@ func (s *treeStore) get(key string) *treeNode {
 	for i = 0; i < len(nodes) - 1; i++ {
 	for i = 0; i < len(nodes) - 1; i++ {
 		node, ok := nodeMap[nodes[i]]
 		node, ok := nodeMap[nodes[i]]
 		if !ok || !node.Dir {
 		if !ok || !node.Dir {
-			return nil
+			return emptyNode, false
 		}
 		}
 		nodeMap = node.NodeMap
 		nodeMap = node.NodeMap
 	}
 	}
 
 
-	node, ok := nodeMap[nodes[i]]
+	treeNode, ok := nodeMap[nodes[i]]
 	if ok {
 	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
 // 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 = "/" + key
 	key = path.Clean(key)
 	key = path.Clean(key)
 
 
@@ -134,17 +128,16 @@ func (s *treeStore) delete(key string) string {
 	for i = 0; i < len(nodes) - 1; i++ {
 	for i = 0; i < len(nodes) - 1; i++ {
 		node, ok := nodeMap[nodes[i]]
 		node, ok := nodeMap[nodes[i]]
 		if !ok || !node.Dir {
 		if !ok || !node.Dir {
-			return ""
+			return false
 		}
 		}
 		nodeMap = node.NodeMap
 		nodeMap = node.NodeMap
 	}
 	}
 
 
 	node, ok := nodeMap[nodes[i]]
 	node, ok := nodeMap[nodes[i]]
 	if ok && !node.Dir{
 	if ok && !node.Dir{
-		oldValue := node.Value
 		delete(nodeMap, nodes[i])
 		delete(nodeMap, nodes[i])
-		return oldValue
+		return true
 	}
 	}
-	return ""
+	return false
 }
 }
 
 

+ 1 - 1
store/tree_store_test.go

@@ -8,7 +8,7 @@ import (
 
 
 func TestStoreGet(t *testing.T) {
 func TestStoreGet(t *testing.T) {
 
 
-	ts := &treeStore{ 
+	ts := &tree{ 
 		&treeNode{
 		&treeNode{
 			"/", 
 			"/", 
 			true, 
 			true, 

+ 10 - 10
web/web.go

@@ -4,10 +4,10 @@ import (
 	"code.google.com/p/go.net/websocket"
 	"code.google.com/p/go.net/websocket"
 	"fmt"
 	"fmt"
 	"github.com/xiangli-cmu/go-raft"
 	"github.com/xiangli-cmu/go-raft"
-	"github.com/xiangli-cmu/raft-etcd/store"
+	//"github.com/xiangli-cmu/raft-etcd/store"
 	"html/template"
 	"html/template"
 	"net/http"
 	"net/http"
-	"time"
+	//"time"
 )
 )
 
 
 var s *raft.Server
 var s *raft.Server
@@ -28,15 +28,15 @@ func handler(w http.ResponseWriter, r *http.Request) {
 
 
 	fmt.Fprintf(w, "Data\n")
 	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)
+	// 	}
+	// }
 
 
 }
 }