From 4b9b5d80696edaee4724b0398e0d62f33ba3fb41 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Fri, 12 Jul 2013 10:10:56 -0700 Subject: [PATCH] merge get and list --- client_handlers.go | 30 ----------------------- command.go | 22 ++++++++--------- etcd.go | 3 +-- store/store.go | 61 ++++++++++++++++++++++++++++++---------------- store/tree.go | 18 ++++++++++---- 5 files changed, 65 insertions(+), 69 deletions(-) diff --git a/client_handlers.go b/client_handlers.go index acb64919b..a57e0d65e 100644 --- a/client_handlers.go +++ b/client_handlers.go @@ -226,36 +226,6 @@ func GetHttpHandler(w *http.ResponseWriter, req *http.Request) { } -// List Handler -func ListHttpHandler(w http.ResponseWriter, req *http.Request) { - prefix := req.URL.Path[len("/v1/list/"):] - - debug("[recv] GET http://%v/v1/list/%s", raftServer.Name(), prefix) - - command := &ListCommand{} - command.Prefix = prefix - - if body, err := command.Apply(raftServer); err != nil { - if _, ok := err.(store.NotFoundError); ok { - http.NotFound(w, req) - return - } - w.WriteHeader(http.StatusInternalServerError) - return - } else { - w.WriteHeader(http.StatusOK) - - body, ok := body.([]byte) - if !ok { - panic("wrong type") - } - - w.Write(body) - return - } - -} - // Watch handler func WatchHttpHandler(w http.ResponseWriter, req *http.Request) { key := req.URL.Path[len("/v1/watch/"):] diff --git a/command.go b/command.go index 865b308e3..f09a4cf96 100644 --- a/command.go +++ b/command.go @@ -65,19 +65,19 @@ func (c *GetCommand) Apply(server *raft.Server) (interface{}, error) { } // List command -type ListCommand struct { - Prefix string `json:"prefix"` -} +// type ListCommand struct { +// Prefix string `json:"prefix"` +// } -// The name of the list command in the log -func (c *ListCommand) CommandName() string { - return "list" -} +// // The name of the list command in the log +// func (c *ListCommand) CommandName() string { +// return "list" +// } -// List all the keys have the given prefix path -func (c *ListCommand) Apply(server *raft.Server) (interface{}, error) { - return etcdStore.List(c.Prefix) -} +// // List all the keys have the given prefix path +// func (c *ListCommand) Apply(server *raft.Server) (interface{}, error) { +// return etcdStore.Get(c.Prefix) +// } // Delete command type DeleteCommand struct { diff --git a/etcd.go b/etcd.go index f2a9bb845..d91adad39 100644 --- a/etcd.go +++ b/etcd.go @@ -358,7 +358,6 @@ func startClientTransport(port int, st int) { // external commands http.HandleFunc("/"+version+"/keys/", Multiplexer) http.HandleFunc("/"+version+"/watch/", WatchHttpHandler) - http.HandleFunc("/"+version+"/list/", ListHttpHandler) http.HandleFunc("/"+version+"/testAndSet/", TestAndSetHttpHandler) http.HandleFunc("/leader", LeaderHttpHandler) @@ -571,6 +570,6 @@ func registerCommands() { raft.RegisterCommand(&GetCommand{}) raft.RegisterCommand(&DeleteCommand{}) raft.RegisterCommand(&WatchCommand{}) - raft.RegisterCommand(&ListCommand{}) + //raft.RegisterCommand(&ListCommand{}) raft.RegisterCommand(&TestAndSetCommand{}) } diff --git a/store/store.go b/store/store.go index a50e4d68b..69a485118 100644 --- a/store/store.go +++ b/store/store.go @@ -64,11 +64,12 @@ type Node struct { type Response struct { Action string `json:"action"` Key string `json:"key"` + Dir bool `json:"dir,omitempty"` PrevValue string `json:"prevValue,omitempty"` Value string `json:"value,omitempty"` - // If the key existed before the action, this field should be true - // If the key did not exist before the action, this field should be false + // If the key did not exist before the action, + // this field should be set to true NewKey bool `json:"newKey,omitempty"` Expiration *time.Time `json:"expiration,omitempty"` @@ -243,18 +244,6 @@ func (s *Store) Set(key string, value string, expireTime time.Time, index uint64 } } -// Get the value of the key -func (s *Store) Get(key string) ([]byte, error) { - resp := s.internalGet(key) - - if resp != nil { - return json.Marshal(resp) - } else { - err := NotFoundError(key) - return nil, err - } -} - // Get the value of the key and return the raw response func (s *Store) internalGet(key string) *Response { @@ -291,21 +280,51 @@ func (s *Store) internalGet(key string) *Response { } -// List all the item in the prefix -func (s *Store) List(prefix string) ([]byte, error) { +// Get all the items under key +// If key is a file return the file +// If key is a directory reuturn an array of files +func (s *Store) Get(key string) ([]byte, error) { - nodes, keys, dirs, ok := s.Tree.list(prefix) + key = path.Clean("/" + key) - var ln []ListNode + nodes, keys, dirs, ok := s.Tree.list(key) if ok { - ln = make([]ListNode, len(nodes)) + resps := make([]Response, len(nodes)) for i := 0; i < len(nodes); i++ { - ln[i] = ListNode{keys[i], nodes[i].Value, dirs[i]} + + var TTL int64 + var isExpire bool = false + + isExpire = !nodes[i].ExpireTime.Equal(PERMANENT) + + resps[i] = Response{ + Action: "GET", + Index: s.Index, + Key: path.Join(key, keys[i]), + } + + if !dirs[i] { + resps[i].Value = nodes[i].Value + } else { + resps[i].Dir = true + } + + // Update ttl + if isExpire { + TTL = int64(nodes[i].ExpireTime.Sub(time.Now()) / time.Second) + resps[i].Expiration = &nodes[i].ExpireTime + resps[i].TTL = TTL + } + } + if len(resps) == 1 { + return json.Marshal(resps[0]) + } + return json.Marshal(resps) } - err := NotFoundError(prefix) + err := NotFoundError(key) return nil, err } diff --git a/store/tree.go b/store/tree.go index 4ff77eef2..25e8795ed 100644 --- a/store/tree.go +++ b/store/tree.go @@ -140,32 +140,40 @@ func (t *tree) get(key string) (Node, bool) { tn, ok := t.internalGet(key) if ok { + if tn.Dir { + return emptyNode, false + } return tn.InternalNode, ok } else { return emptyNode, ok } } -// return the nodes information under the directory -func (t *tree) list(directory string) ([]Node, []string, []string, bool) { +// get the internalNode of the key +func (t *tree) list(directory string) ([]Node, []string, []bool, bool) { treeNode, ok := t.internalGet(directory) if !ok { return nil, nil, nil, ok } else { + if !treeNode.Dir { + nodes := make([]Node, 1) + nodes[0] = treeNode.InternalNode + return nodes, make([]string, 1), make([]bool, 1), true + } length := len(treeNode.NodeMap) nodes := make([]Node, length) keys := make([]string, length) - dirs := make([]string, length) + dirs := make([]bool, length) i := 0 for key, node := range treeNode.NodeMap { nodes[i] = node.InternalNode keys[i] = key if node.Dir { - dirs[i] = "d" + dirs[i] = true } else { - dirs[i] = "f" + dirs[i] = false } i++ }