package store // persistent key-value store // TODO: thread safety, persistence, efficient update and query, incremental backup import ( "fmt" "os" "path/filepath" "io/ioutil" "sync" ) type Conn struct { name string path string mutex sync.RWMutex memstore map[string][]byte } func Open(name string) (c *Conn, err error) { c = new(Conn) c.memstore = make(map[string][]byte) c.name = name c.path, err = filepath.Abs(name) if err != nil { return } err = os.MkdirAll(c.path, 0755) if err != nil { return } err = filepath.Walk(c.path, func(path string, info *os.FileInfo, err error) error { if info.IsDirectory() { if info.Name == c.name { return nil } return filepath.SkipDir } if err != nil { return err } k := info.Name v, err := ioutil.ReadFile(filepath.Join(c.path, k)) if err != nil { return err } c.memstore[k] = v return nil }) return } func (c *Conn) Get(k string) (v []byte, err error) { c.mutex.RLock() defer c.mutex.RUnlock() v, ok := c.memstore[k] if !ok { err = fmt.Errorf("key not found") } return } func (c *Conn) Set(k string, v []byte) (err error) { c.mutex.Lock() defer c.mutex.Unlock() f, err := os.Create(filepath.Join(c.path, k)) if err != nil { return } _, err = f.Write(v) if err != nil { return } c.memstore[k] = v return } func (c *Conn) Close() (err error) { return }