kv.go 1.5 KB

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