store += append
[epoint] / store / store.go
1 package store
2
3 // persistent key-value store
4 // multiple key-value store can be managed by a single db connection
5 // each store has a name, before usage the name of the store must be
6 // ensured to exist
7 //
8 // TODO: this is a toy implementation
9
10 import (
11         "os"
12         "path/filepath"
13         "io/ioutil"
14 )
15
16
17 type Conn struct {
18         path string
19 }
20
21 func Open(root string) (c *Conn, err error) {
22         c = new(Conn)
23         c.path, err = filepath.Abs(root)
24         if err != nil {
25                 return
26         }
27         err = os.MkdirAll(c.path, 0755)
28         if err != nil {
29                 return
30         }
31         return
32 }
33
34 func (c *Conn) Get(name, k string) (v []byte, err error) {
35         return ioutil.ReadFile(filepath.Join(c.path, name, k))
36 }
37
38 func (c *Conn) Ensure(name string) (err error) {
39         return os.MkdirAll(filepath.Join(c.path, name), 0755)
40 }
41
42 func (c *Conn) Set(name, k string, v []byte) (err error) {
43         fn := filepath.Join(c.path, name, k)
44         f, err := os.OpenFile(fn+".tmp", os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0666)
45         if err != nil {
46                 return
47         }
48         defer f.Close()
49         _, err = f.Write(v)
50         if err != nil {
51                 return
52         }
53         err = os.Rename(fn+".tmp", fn)
54         return
55 }
56
57 func (c *Conn) Append(name, k string, v []byte) (err error) {
58         fn := filepath.Join(c.path, name, k)
59         f, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY|os.O_SYNC, 0666)
60         if err != nil {
61                 return
62         }
63         defer f.Close()
64         _, err = f.Write(v)
65         return
66 }
67
68 func (c *Conn) Close() (err error) {
69         return
70 }