merge get and list

This commit is contained in:
Xiang Li 2013-07-12 10:10:56 -07:00
parent 00d2d6eb4e
commit 4b9b5d8069
5 changed files with 65 additions and 69 deletions

View File

@ -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/"):]

View File

@ -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 {

View File

@ -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{})
}

View File

@ -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
}

View File

@ -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++
}