bloat/util/kv.go

92 lines
1.5 KiB
Go

package util
import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"strings"
"sync"
)
var (
errInvalidKey = errors.New("invalid key")
errNoSuchKey = errors.New("no such key")
)
type Database struct {
cache 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{
cache: make(map[string][]byte),
basedir: basedir,
}, nil
}
func (db *Database) Set(key string, val []byte) (err error) {
if len(key) < 1 || strings.ContainsRune(key, os.PathSeparator) {
return errInvalidKey
}
err = ioutil.WriteFile(filepath.Join(db.basedir, key), val, 0644)
if err != nil {
return
}
db.m.Lock()
db.cache[key] = val
db.m.Unlock()
return
}
func (db *Database) Get(key string) (val []byte, err error) {
if len(key) < 1 || strings.ContainsRune(key, os.PathSeparator) {
return nil, errInvalidKey
}
db.m.RLock()
data, ok := db.cache[key]
db.m.RUnlock()
if !ok {
data, err = ioutil.ReadFile(filepath.Join(db.basedir, key))
if err != nil {
err = errNoSuchKey
return nil, err
}
db.m.Lock()
db.cache[key] = data
db.m.Unlock()
}
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
}
os.Remove(filepath.Join(db.basedir, key))
db.m.Lock()
delete(db.cache, key)
db.m.Unlock()
return
}