aboutsummaryrefslogtreecommitdiff
path: root/kv/kv.go
diff options
context:
space:
mode:
authorr <r@freesoftwareextremist.com>2019-12-17 20:17:25 +0000
committerr <r@freesoftwareextremist.com>2019-12-17 20:17:25 +0000
commit59aad78f66cf58be7f88f2c0675f94a858163560 (patch)
tree95f00d18a8c847cdf4ee587e412de26960770a28 /kv/kv.go
parent3b50f40c081c499c2ecb8913b54186c622561d76 (diff)
downloadbloat-59aad78f66cf58be7f88f2c0675f94a858163560.tar.gz
bloat-59aad78f66cf58be7f88f2c0675f94a858163560.zip
Use filesystem based kv store instead of sqlite
Diffstat (limited to 'kv/kv.go')
-rw-r--r--kv/kv.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/kv/kv.go b/kv/kv.go
new file mode 100644
index 0000000..2cfcd60
--- /dev/null
+++ b/kv/kv.go
@@ -0,0 +1,92 @@
+package kv
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+var (
+ errInvalidKey = errors.New("invalid key")
+ errNoSuchKey = errors.New("no such key")
+)
+
+type Database struct {
+ data map[string][]byte
+ basedir string
+ m sync.RWMutex
+}
+
+func NewDatabse(basedir string) (db *Database, err error) {
+ err = os.Mkdir(basedir, 0755)
+ if err != nil && !os.IsExist(err) {
+ return
+ }
+
+ return &Database{
+ data: make(map[string][]byte),
+ basedir: basedir,
+ }, nil
+}
+
+func (db *Database) Set(key string, val []byte) (err error) {
+ if len(key) < 1 {
+ return errInvalidKey
+ }
+
+ db.m.Lock()
+ defer func() {
+ if err != nil {
+ delete(db.data, key)
+ }
+ db.m.Unlock()
+ }()
+
+ db.data[key] = val
+
+ err = ioutil.WriteFile(filepath.Join(db.basedir, key), val, 0644)
+
+ return
+}
+
+func (db *Database) Get(key string) (val []byte, err error) {
+ if len(key) < 1 {
+ return nil, errInvalidKey
+ }
+
+ db.m.RLock()
+ defer db.m.RUnlock()
+
+ data, ok := db.data[key]
+ if !ok {
+ data, err = ioutil.ReadFile(filepath.Join(db.basedir, key))
+ if err != nil {
+ err = errNoSuchKey
+ return nil, err
+ }
+
+ db.data[key] = data
+ }
+
+ val = make([]byte, len(data))
+ copy(val, data)
+
+ return
+}
+
+func (db *Database) Remove(key string) {
+ if len(key) < 1 || strings.ContainsRune(key, os.PathSeparator) {
+ return
+ }
+
+ db.m.Lock()
+ defer db.m.Unlock()
+
+ delete(db.data, key)
+ os.Remove(filepath.Join(db.basedir, key))
+
+ return
+}