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
8 // TODO: this is a toy implementation
20 type NotFoundError struct {
24 func (e NotFoundError) Error() string {
25 return "not found: " + e.path
28 func Open(root string) (c *Conn, err error) {
30 c.path, err = filepath.Abs(root)
34 err = os.MkdirAll(c.path, 0755)
41 func (c *Conn) Get(name, k string) (v []byte, err error) {
42 v, err = ioutil.ReadFile(filepath.Join(c.path, name, k))
44 if p, ok := err.(*os.PathError); ok && p.Err == os.ENOENT {
45 err = NotFoundError{name + "/" + k}
51 func (c *Conn) Ensure(name string) (err error) {
52 return os.MkdirAll(filepath.Join(c.path, name), 0755)
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)
66 err = os.Rename(fn+".tmp", fn)
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)
81 func (c *Conn) Close() (err error) {