basic get

This commit is contained in:
Xiang Li 2013-09-03 21:27:46 -04:00
parent 45ab5238fe
commit 45c9ec9f29
3 changed files with 119 additions and 30 deletions

View File

@ -7,6 +7,7 @@ import (
) )
const ( const (
Get = "get"
Set = "set" Set = "set"
Delete = "delete" Delete = "delete"
TestAndSet = "testAndSet" TestAndSet = "testAndSet"
@ -15,10 +16,11 @@ const (
type Event struct { type Event struct {
Action string `json:"action"` Action string `json:"action"`
Key string `json:"key"` Key string `json:"key, omitempty"`
Dir bool `json:"dir,omitempty"` Dir bool `json:"dir,omitempty"`
PrevValue string `json:"prevValue,omitempty"` PrevValue string `json:"prevValue,omitempty"`
Value string `json:"value,omitempty"` Value string `json:"value,omitempty"`
Pairs []KeyValuePair `json:"kvs,omitempty"`
Expiration *time.Time `json:"expiration,omitempty"` Expiration *time.Time `json:"expiration,omitempty"`
TTL int64 `json:"ttl,omitempty"` // Time to live in second TTL int64 `json:"ttl,omitempty"` // Time to live in second
// The command index of the raft machine when the command is executed // The command index of the raft machine when the command is executed
@ -26,6 +28,14 @@ type Event struct {
Term uint64 `json:"term"` Term uint64 `json:"term"`
} }
// When user list a directory, we add all the node into key-value pair slice
type KeyValuePair struct {
Key string `json:"key, omitempty"`
Value string `json:"value,omitempty"`
Dir bool `json:"dir,omitempty"`
Pairs []KeyValuePair `json:"kvs,omitempty"`
}
func newEvent(action string, key string, index uint64, term uint64) *Event { func newEvent(action string, key string, index uint64, term uint64) *Event {
return &Event{ return &Event{
Action: action, Action: action,

View File

@ -25,29 +25,42 @@ func New() *FileSystem {
} }
func (fs *FileSystem) InternalGet(path string, index uint64, term uint64) (*Node, error) { func (fs *FileSystem) Get(path string, recusive bool, index uint64, term uint64) (*Event, error) {
fmt.Println("GET: ", path) // TODO: add recursive get
path = filepath.Clean("/" + path) n, err := fs.InternalGet(path, index, term)
// update file system known index and term
fs.Index, fs.Term = index, term
walkFunc := func(parent *Node, dirName string) (*Node, error) {
child, ok := parent.Children[dirName]
if ok {
return child, nil
}
return nil, etcdErr.NewError(100, "get")
}
f, err := fs.walk(path, walkFunc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return f, nil e := newEvent(Get, path, index, term)
if n.IsDir() { // node is dir
e.Pairs = make([]KeyValuePair, len(n.Children))
i := 0
for _, subN := range n.Children {
if subN.IsDir() {
e.Pairs[i] = KeyValuePair{
Key: subN.Path,
Dir: true,
}
} else {
e.Pairs[i] = KeyValuePair{
Key: subN.Path,
Value: subN.Value,
}
}
i++
}
} else { // node is file
e.Value = n.Value
}
return e, nil
} }
func (fs *FileSystem) Set(path string, value string, expireTime time.Time, index uint64, term uint64) error { func (fs *FileSystem) Set(path string, value string, expireTime time.Time, index uint64, term uint64) error {
@ -66,17 +79,35 @@ func (fs *FileSystem) Set(path string, value string, expireTime time.Time, index
} }
f := newFile(name, value, fs.Index, fs.Term, d, "", expireTime) f := newFile(name, value, fs.Index, fs.Term, d, "", expireTime)
e := newEvent(Set, path, fs.Index, fs.Term)
e.Value = f.Value
// remove previous file if exist
oldFile, err := d.GetFile(name)
if err == nil {
if oldFile != nil {
oldFile.Remove(false)
e.PrevValue = oldFile.Value
}
} else {
return err
}
err = d.Add(f) err = d.Add(f)
if err == nil { if err != nil {
return err
}
// Node with TTL
if expireTime != Permanent { if expireTime != Permanent {
go f.Expire() go f.Expire()
} e.Expiration = &f.ExpireTime
e.TTL = int64(expireTime.Sub(time.Now()) / time.Second)
} }
return err return nil
} }
func (fs *FileSystem) TestAndSet() { func (fs *FileSystem) TestAndSet() {
@ -119,6 +150,32 @@ func (fs *FileSystem) walk(path string, walkFunc func(prev *Node, component stri
return curr, nil return curr, nil
} }
// InternalGet function get the node of the given path.
func (fs *FileSystem) InternalGet(path string, index uint64, term uint64) (*Node, error) {
fmt.Println("GET: ", path)
path = filepath.Clean("/" + path)
// update file system known index and term
fs.Index, fs.Term = index, term
walkFunc := func(parent *Node, dirName string) (*Node, error) {
child, ok := parent.Children[dirName]
if ok {
return child, nil
}
return nil, etcdErr.NewError(100, "get")
}
f, err := fs.walk(path, walkFunc)
if err != nil {
return nil, err
}
return f, nil
}
// checkDir function will check whether the component is a directory under parent node. // checkDir function will check whether the component is a directory under parent node.
// If it is a directory, this function will return the pointer to that node. // If it is a directory, this function will return the pointer to that node.
// If it does not exist, this function will create a new directory and return the pointer to that node. // If it does not exist, this function will create a new directory and return the pointer to that node.

View File

@ -141,6 +141,28 @@ func (n *Node) List() ([]*Node, error) {
return nodes, nil return nodes, nil
} }
func (n *Node) GetFile(name string) (*Node, error) {
n.mu.Lock()
n.mu.Unlock()
if !n.IsDir() {
return nil, etcdErr.NewError(104, n.Path)
}
f, ok := n.Children[name]
if ok {
if !f.IsDir() {
return f, nil
} else {
return nil, etcdErr.NewError(102, f.Path)
}
}
return nil, nil
}
// Add function adds a node to the receiver node. // Add function adds a node to the receiver node.
// If the receiver is not a directory, a "Not A Directory" error will be returned. // If the receiver is not a directory, a "Not A Directory" error will be returned.
// If there is a existing node with the same name under the directory, a "Already Exist" // If there is a existing node with the same name under the directory, a "Already Exist"