github.com/jeffjen/go-libkv@v0.0.0-20151212051932-5df59a45a168/libkv/persist.go (about) 1 // Package libkv provides key value storage for embedded go application. 2 package libkv 3 4 import ( 5 "encoding/gob" 6 "io" 7 "os" 8 p "path" 9 "sync" 10 "time" 11 ) 12 13 const ( 14 KV_FILE = "kv.db" 15 KV_IDX_FILE = "kv.idx" 16 ) 17 18 var ( 19 g sync.Mutex 20 ) 21 22 func init() { 23 gob.Register([]thing{}) 24 gob.Register(thing{}) 25 } 26 27 // Load restores kv object from file. 28 // Method is protected by mutex to prevent multiple Load job. 29 // NOTE: this is an experimental feature 30 func Load(path string) (*Store, error) { 31 g.Lock() 32 defer g.Unlock() 33 34 var ( 35 s = NewStore() // initiate kv store object 36 37 store map[string]thing 38 ) 39 40 if fp, err := os.Open(p.Join(path, KV_FILE)); err != nil { 41 return s, err 42 } else { 43 defer fp.Close() 44 dec := gob.NewDecoder(fp) 45 if drr := dec.Decode(&store); drr != nil && drr != io.EOF { 46 return s, err 47 } 48 } 49 50 // loaded kv object file 51 s.m.store = store 52 53 // proceed to restore state 54 now := time.Now() 55 for k, v := range s.m.store { 56 if v.T != nil && now.After(*v.T) { 57 delete(store, k) 58 } else if v.T != nil { 59 s.expire(k, *v.T) 60 } 61 } 62 63 return s, nil 64 } 65 66 // Save stores the kv object and kv index object to designated path 67 // kv object is put under read lock to prevent changes 68 // Method is protected by mutex to prevent multiple Save job. 69 // NOTE: this is an experimental feature. Method best invoked in goroutine 70 func (s *Store) Save(path string) error { 71 s.RLock() 72 defer s.RUnlock() 73 74 g.Lock() 75 defer g.Unlock() 76 77 if fp, err := os.Create(p.Join(path, KV_FILE)); err != nil { 78 return err 79 } else { 80 defer fp.Close() 81 enc := gob.NewEncoder(fp) 82 if err = enc.Encode(s.m.store); err != nil { 83 return err 84 } 85 } 86 87 return nil 88 }