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