a27935c3a4624f11c39ce3d652d696166a1f89af
[epoint] / pkg / 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         "io/ioutil"
12         "os"
13         "path/filepath"
14 )
15
16 type Conn struct {
17         path string
18 }
19
20 type NotFoundError struct {
21         path string
22 }
23
24 func (e NotFoundError) Error() string {
25         return "not found: " + e.path
26 }
27
28 func Open(root string) (c *Conn, err error) {
29         c = new(Conn)
30         c.path, err = filepath.Abs(root)
31         if err != nil {
32                 return
33         }
34         err = os.MkdirAll(c.path, 0755)
35         if err != nil {
36                 return
37         }
38         return
39 }
40
41 func (c *Conn) Get(name, k string) (v []byte, err error) {
42         v, err = ioutil.ReadFile(filepath.Join(c.path, name, k))
43         if err != nil {
44                 if p, ok := err.(*os.PathError); ok && p.Err == os.ENOENT {
45                         err = NotFoundError{name + "/" + k}
46                 }
47         }
48         return
49 }
50
51 func (c *Conn) Ensure(name string) (err error) {
52         return os.MkdirAll(filepath.Join(c.path, name), 0755)
53 }
54
55 func (c *Conn) Set(name, k string, v []byte) (err error) {
56         fn := filepath.Join(c.path, name, k)
57         f, err := os.OpenFile(fn+".tmp", os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_SYNC, 0666)
58         if err != nil {
59                 return
60         }
61         defer f.Close()
62         _, err = f.Write(v)
63         if err != nil {
64                 return
65         }
66         err = os.Rename(fn+".tmp", fn)
67         return
68 }
69
70 func (c *Conn) Append(name, k string, v []byte) (err error) {
71         fn := filepath.Join(c.path, name, k)
72         f, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY|os.O_SYNC, 0666)
73         if err != nil {
74                 return
75         }
76         defer f.Close()
77         _, err = f.Write(v)
78         return
79 }
80
81 func (c *Conn) Close() (err error) {
82         return
83 }