|
@@ -1,6 +1,7 @@
|
|
|
package fileSystem
|
|
package fileSystem
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ "fmt"
|
|
|
"path"
|
|
"path"
|
|
|
"strings"
|
|
"strings"
|
|
|
"time"
|
|
"time"
|
|
@@ -84,7 +85,7 @@ func (fs *FileSystem) Set(keyPath string, value string, expireTime time.Time, in
|
|
|
|
|
|
|
|
if f != nil { // update previous file if exist
|
|
if f != nil { // update previous file if exist
|
|
|
e.PrevValue = f.Value
|
|
e.PrevValue = f.Value
|
|
|
- f.Write(e.Value)
|
|
|
|
|
|
|
+ f.Write(e.Value, index, term)
|
|
|
|
|
|
|
|
// if the previous ExpireTime is not Permanent and expireTime is given
|
|
// if the previous ExpireTime is not Permanent and expireTime is given
|
|
|
// we stop the previous expire routine
|
|
// we stop the previous expire routine
|
|
@@ -115,12 +116,43 @@ func (fs *FileSystem) Set(keyPath string, value string, expireTime time.Time, in
|
|
|
return e, nil
|
|
return e, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (fs *FileSystem) TestAndSet(keyPath string, prevValue string, prevIndex uint64, index uint64, term uint64) {
|
|
|
|
|
|
|
+func (fs *FileSystem) TestAndSet(keyPath string, prevValue string, prevIndex uint64, value string, expireTime time.Time, index uint64, term uint64) (*Event, error) {
|
|
|
|
|
+ f, err := fs.InternalGet(keyPath, index, term)
|
|
|
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+
|
|
|
|
|
+ etcdError, _ := err.(etcdErr.Error)
|
|
|
|
|
+ if etcdError.ErrorCode == 100 { // file does not exist
|
|
|
|
|
+
|
|
|
|
|
+ if prevValue == "" && prevIndex == 0 { // test against if prevValue is empty
|
|
|
|
|
+ fs.Set(keyPath, value, expireTime, index, term)
|
|
|
|
|
+ e := newEvent(TestAndSet, keyPath, index, term)
|
|
|
|
|
+ e.Value = value
|
|
|
|
|
+ return e, nil
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-func (fs *FileSystem) TestIndexAndSet() {
|
|
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ if f.IsDir() { // can only test and set file
|
|
|
|
|
+ return nil, etcdErr.NewError(102, keyPath)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if f.Value == prevValue || f.ModifiedIndex == prevIndex {
|
|
|
|
|
+ // if test succeed, write the value
|
|
|
|
|
+ e := newEvent(TestAndSet, keyPath, index, term)
|
|
|
|
|
+ e.PrevValue = f.Value
|
|
|
|
|
+ e.Value = value
|
|
|
|
|
+ f.Write(value, index, term)
|
|
|
|
|
+ return e, nil
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cause := fmt.Sprintf("[%v/%v] [%v/%v]", prevValue, f.Value, prevIndex, f.ModifiedIndex)
|
|
|
|
|
+ return nil, etcdErr.NewError(101, cause)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (fs *FileSystem) Delete(keyPath string, recurisive bool, index uint64, term uint64) (*Event, error) {
|
|
func (fs *FileSystem) Delete(keyPath string, recurisive bool, index uint64, term uint64) (*Event, error) {
|
|
@@ -176,13 +208,18 @@ func (fs *FileSystem) InternalGet(keyPath string, index uint64, term uint64) (*N
|
|
|
// update file system known index and term
|
|
// update file system known index and term
|
|
|
fs.Index, fs.Term = index, term
|
|
fs.Index, fs.Term = index, term
|
|
|
|
|
|
|
|
- walkFunc := func(parent *Node, dirName string) (*Node, error) {
|
|
|
|
|
- child, ok := parent.Children[dirName]
|
|
|
|
|
|
|
+ walkFunc := func(parent *Node, name string) (*Node, error) {
|
|
|
|
|
+
|
|
|
|
|
+ if !parent.IsDir() {
|
|
|
|
|
+ return nil, etcdErr.NewError(104, parent.Path)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ child, ok := parent.Children[name]
|
|
|
if ok {
|
|
if ok {
|
|
|
return child, nil
|
|
return child, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return nil, etcdErr.NewError(100, "get")
|
|
|
|
|
|
|
+ return nil, etcdErr.NewError(100, path.Join(parent.Path, name))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
f, err := fs.walk(keyPath, walkFunc)
|
|
f, err := fs.walk(keyPath, walkFunc)
|