various fixes to make testing possible
[epoint] / pkg / store / store.go
index a27935c..7ea1ded 100644 (file)
@@ -18,26 +18,39 @@ type Conn struct {
 }
 
 type NotFoundError struct {
-       path string
+       Path string
+}
+
+type AlreadyExistsError struct {
+       Path string
 }
 
 func (e NotFoundError) Error() string {
-       return "not found: " + e.path
+       return "not found: " + e.Path
 }
 
+func (e AlreadyExistsError) Error() string {
+       return "already exists: " + e.Path
+}
+
+// Open db connection
 func Open(root string) (c *Conn, err error) {
        c = new(Conn)
        c.path, err = filepath.Abs(root)
        if err != nil {
                return
        }
-       err = os.MkdirAll(c.path, 0755)
+       fn := filepath.Join(c.path, ".journal")
+       err = os.MkdirAll(fn, 0755)
        if err != nil {
                return
        }
        return
 }
 
+// TODO: list .journal for recovery after a crash
+
+// Get the value of k
 func (c *Conn) Get(name, k string) (v []byte, err error) {
        v, err = ioutil.ReadFile(filepath.Join(c.path, name, k))
        if err != nil {
@@ -48,10 +61,12 @@ func (c *Conn) Get(name, k string) (v []byte, err error) {
        return
 }
 
+// Ensure k-v store with the given name exists
 func (c *Conn) Ensure(name string) (err error) {
        return os.MkdirAll(filepath.Join(c.path, name), 0755)
 }
 
+// Set k to v
 func (c *Conn) Set(name, k string, v []byte) (err error) {
        fn := filepath.Join(c.path, name, k)
        f, err := os.OpenFile(fn+".tmp", os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0666)
@@ -67,6 +82,22 @@ func (c *Conn) Set(name, k string, v []byte) (err error) {
        return
 }
 
+// Set k to v, but fail if k already exists
+func (c *Conn) Insert(name, k string, v []byte) (err error) {
+       fn := filepath.Join(c.path, name, k)
+       f, err := os.OpenFile(fn, os.O_CREATE|os.O_EXCL|os.O_WRONLY|os.O_SYNC, 0666)
+       if err != nil {
+               if p, ok := err.(*os.PathError); ok && p.Err == os.EEXIST {
+                       err = AlreadyExistsError{name + "/" + k}
+               }
+               return
+       }
+       defer f.Close()
+       _, err = f.Write(v)
+       return
+}
+
+// Append v to value of k
 func (c *Conn) Append(name, k string, v []byte) (err error) {
        fn := filepath.Join(c.path, name, k)
        f, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY|os.O_SYNC, 0666)
@@ -78,6 +109,25 @@ func (c *Conn) Append(name, k string, v []byte) (err error) {
        return
 }
 
+// Begin transaction identified by k
+func (c *Conn) Begin(k string) (err error) {
+       fn := filepath.Join(c.path, ".journal", k)
+       f, err := os.OpenFile(fn, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0666)
+       if err != nil {
+               return
+       }
+       err = f.Close()
+       return
+}
+
+// End transaction identified by k
+func (c *Conn) End(k string) (err error) {
+       fn := filepath.Join(c.path, ".journal", k)
+       err = os.Remove(fn)
+       return
+}
+
+// Close db connection
 func (c *Conn) Close() (err error) {
        return
 }