mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
merge get and list
This commit is contained in:
parent
00d2d6eb4e
commit
4b9b5d8069
@ -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/"):]
|
||||
|
22
command.go
22
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 {
|
||||
|
3
etcd.go
3
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{})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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++
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user