fluoride: Fix syntax and formatting
[bloat] / kv / kv.go
1 package kv
2
3 import (
4         "errors"
5         "io/ioutil"
6         "os"
7         "path/filepath"
8         "strings"
9         "sync"
10 )
11
12 var (
13         errInvalidKey = errors.New("invalid key")
14         errNoSuchKey  = errors.New("no such key")
15 )
16
17 type Database struct {
18         data    map[string][]byte
19         basedir string
20         m       sync.RWMutex
21 }
22
23 func NewDatabse(basedir string) (db *Database, err error) {
24         err = os.Mkdir(basedir, 0755)
25         if err != nil && !os.IsExist(err) {
26                 return
27         }
28
29         return &Database{
30                 data:    make(map[string][]byte),
31                 basedir: basedir,
32         }, nil
33 }
34
35 func (db *Database) Set(key string, val []byte) (err error) {
36         if len(key) < 1 {
37                 return errInvalidKey
38         }
39
40         db.m.Lock()
41         defer func() {
42                 if err != nil {
43                         delete(db.data, key)
44                 }
45                 db.m.Unlock()
46         }()
47
48         db.data[key] = val
49
50         err = ioutil.WriteFile(filepath.Join(db.basedir, key), val, 0644)
51
52         return
53 }
54
55 func (db *Database) Get(key string) (val []byte, err error) {
56         if len(key) < 1 {
57                 return nil, errInvalidKey
58         }
59
60         db.m.RLock()
61         defer db.m.RUnlock()
62
63         data, ok := db.data[key]
64         if !ok {
65                 data, err = ioutil.ReadFile(filepath.Join(db.basedir, key))
66                 if err != nil {
67                         err = errNoSuchKey
68                         return nil, err
69                 }
70
71                 db.data[key] = data
72         }
73
74         val = make([]byte, len(data))
75         copy(val, data)
76
77         return
78 }
79
80 func (db *Database) Remove(key string) {
81         if len(key) < 1 || strings.ContainsRune(key, os.PathSeparator) {
82                 return
83         }
84
85         db.m.Lock()
86         defer db.m.Unlock()
87
88         delete(db.data, key)
89         os.Remove(filepath.Join(db.basedir, key))
90
91         return
92 }