/store.go

https://code.google.com/p/diskv/ · Go · 298 lines · 239 code · 23 blank · 36 comment · 60 complexity · 53d2678d298b5594b8abd0201f2371b8 MD5 · raw file

  1. package diskv
  2. import (
  3. "fmt"
  4. "strings"
  5. "sync"
  6. "os"
  7. "time"
  8. "log"
  9. "io/ioutil"
  10. "path/filepath"
  11. "github.com/petar/GoLLRB/llrb"
  12. )
  13. type DStore struct {
  14. basedir string
  15. xf TransformFunc
  16. fileperm uint32
  17. dirperm uint32
  18. cache map[Key]Value
  19. mutex *sync.RWMutex
  20. cachesz uint
  21. cachemaxsz uint
  22. index *llrb.Tree
  23. lf llrb.LessFunc
  24. }
  25. // Returns a new, unordered Store that represents the data in the given
  26. // basedir directory. The cache will grow to a maximum maxsz bytes.
  27. func NewDStore(basedir string, xf TransformFunc, maxsz uint) *DStore {
  28. s := &DStore{}
  29. s.basedir = fmt.Sprintf("%s/%s", basedir, "diskv")
  30. s.xf = xf
  31. s.fileperm, s.dirperm = 0777, 0777
  32. s.cache = make(map[Key]Value)
  33. s.mutex = &sync.RWMutex{}
  34. s.cachesz, s.cachemaxsz = 0, maxsz
  35. s.index, s.lf = nil, nil
  36. return s
  37. }
  38. // Returns a new, ordered Store that represents the data in the given
  39. // basedir directory. The directory tree at basedir will be scanned at
  40. // initialization time, to populate the index with existing Keys.
  41. func NewODStore(basedir string, xf TransformFunc, maxsz uint, lf llrb.LessFunc) *DStore {
  42. s := NewDStore(basedir, xf, maxsz)
  43. s.index = llrb.New(lf)
  44. s.lf = lf
  45. s.populate_index()
  46. return s
  47. }
  48. func (s *DStore) populate_index() {
  49. t1 := time.Nanoseconds() / 1e6
  50. c := s.Keys()
  51. for k := <-c; len(k) > 0; k = <-c {
  52. s.index.ReplaceOrInsert(k)
  53. }
  54. td := (time.Nanoseconds() / 1e6) - t1
  55. log.Printf("index populated with %d elements in %d ms\n", s.index.Len(), td)
  56. }
  57. // Returns the directory that will hold the given Key.
  58. func (s *DStore) dir(k Key) string {
  59. pathlist := s.xf(k)
  60. return fmt.Sprintf("%s/%s", s.basedir, strings.Join(pathlist, "/"))
  61. }
  62. // Returns the full path to the file holding data for the given Key.
  63. func (s *DStore) filename(k Key) string {
  64. return fmt.Sprintf("%s/%s", s.dir(k), k)
  65. }
  66. // Creates all necessary directories on disk to hold the given Key.
  67. func (s *DStore) ensure_dir(k Key) os.Error {
  68. return os.MkdirAll(s.dir(k), s.dirperm)
  69. }
  70. // Deletes empty directories in the path walk leading to the Key k.
  71. // Typically this function is called after an Erase() is made.
  72. func (s *DStore) prune_dirs(k Key) os.Error {
  73. pathlist := s.xf(k)
  74. for i := range pathlist {
  75. pslice := pathlist[:len(pathlist)-i]
  76. dir := fmt.Sprintf("%s/%s", s.basedir, strings.Join(pslice, "/"))
  77. // thanks to Steven Blenkinsop for this snippet
  78. switch fi, err := os.Stat(dir); true {
  79. case err != nil:
  80. return err
  81. case !fi.IsDirectory():
  82. panic(fmt.Sprintf("corrupt dirstate at %s", dir))
  83. case fi.Nlink != 2:
  84. return nil
  85. default:
  86. if err = os.Remove(dir); err != nil {
  87. return err
  88. }
  89. }
  90. }
  91. return nil
  92. }
  93. // Deletes entries from the cache until it has at least sz bytes available.
  94. func (s *DStore) ensure_space(sz uint) {
  95. for k, v := range s.cache {
  96. if (s.cachesz + sz) <= s.cachemaxsz {
  97. break
  98. }
  99. s.cachesz -= uint(len(v)) // len should return uint :|
  100. s.cache[k] = Value{}, false // delete is safe, per spec
  101. }
  102. }
  103. func (s *DStore) cache_with_lock(k Key, v Value) {
  104. vsz := uint(len(v))
  105. s.ensure_space(vsz)
  106. if (s.cachesz + vsz) <= s.cachemaxsz {
  107. s.cache[k] = v
  108. s.cachesz += vsz
  109. }
  110. if s.index != nil {
  111. s.index.ReplaceOrInsert(k)
  112. }
  113. }
  114. func (s *DStore) cache_without_lock(k Key, v Value) {
  115. s.mutex.Lock()
  116. defer s.mutex.Unlock()
  117. s.cache_with_lock(k, v)
  118. }
  119. // Writes the Value to the store under the given Key.
  120. // Overwrites anything already existing under the given Key.
  121. func (s *DStore) Write(k Key, v Value) os.Error {
  122. s.mutex.Lock()
  123. defer s.mutex.Unlock()
  124. if len(k) <= 0 {
  125. return os.NewError("empty key")
  126. }
  127. // write the data to disk (overwrite if exists)
  128. if err := s.ensure_dir(k); err != nil {
  129. return err
  130. }
  131. mode := os.O_WRONLY | os.O_CREATE
  132. if f, err := os.OpenFile(s.filename(k), mode, s.fileperm); err == nil {
  133. defer f.Close()
  134. if _, err = f.Write(v); err != nil {
  135. return err
  136. }
  137. } else {
  138. return err
  139. }
  140. // index immediately
  141. if s.index != nil {
  142. s.index.ReplaceOrInsert(k)
  143. }
  144. // cache only on read
  145. return nil
  146. }
  147. // Returns the Value stored under the given Key, if it exists.
  148. // Returns error if the Key doesn't exist.
  149. func (s *DStore) Read(k Key) (Value, os.Error) {
  150. s.mutex.RLock()
  151. defer s.mutex.RUnlock()
  152. // check cache first
  153. if v, ok := s.cache[k]; ok {
  154. return v, nil
  155. }
  156. // read from disk
  157. v, err := ioutil.ReadFile(s.filename(k))
  158. if err != nil {
  159. return Value{}, err
  160. }
  161. // cache lazily
  162. go s.cache_without_lock(k, v)
  163. return v, nil
  164. }
  165. // Erases the Value stored under the given Key, if it exists.
  166. // Returns error if the Key doesn't exist.
  167. func (s *DStore) Erase(k Key) os.Error {
  168. s.mutex.Lock()
  169. defer s.mutex.Unlock()
  170. // erase from cache
  171. if v, ok := s.cache[k]; ok {
  172. s.cachesz -= uint(len(v))
  173. s.cache[k] = Value{}, false
  174. }
  175. // erase from index
  176. if s.index != nil {
  177. s.index.Delete(k)
  178. }
  179. // erase from disk
  180. filename := s.filename(k)
  181. if s, err := os.Stat(filename); err == nil {
  182. if !s.IsRegular() {
  183. return os.NewError("bad key")
  184. }
  185. if err = os.Remove(filename); err != nil {
  186. return err
  187. }
  188. } else {
  189. return err
  190. }
  191. if s.index != nil {
  192. s.index.Delete(k)
  193. }
  194. // clean up
  195. s.prune_dirs(k)
  196. return nil
  197. }
  198. // Erase all Keys and Values from the DStore.
  199. func (s *DStore) Flush() os.Error {
  200. s.mutex.Lock()
  201. defer s.mutex.Unlock()
  202. // flush cache
  203. s.cache = make(map[Key]Value)
  204. s.cachesz = 0
  205. // flush index
  206. if s.index != nil {
  207. s.index.Init(s.lf)
  208. }
  209. // flush disk
  210. return os.RemoveAll(s.basedir)
  211. }
  212. type DiskvVisitor struct {
  213. c chan<- Key
  214. }
  215. func (v DiskvVisitor) VisitDir(path string, f *os.FileInfo) bool {
  216. return true // descend
  217. }
  218. func (v DiskvVisitor) VisitFile(path string, f *os.FileInfo) {
  219. v.c <- Key(f.Name)
  220. }
  221. // Returns channel generating list of all keys in the store,
  222. // based on the state of the disk. No order guarantee.
  223. func (s *DStore) Keys() <-chan Key {
  224. c := make(chan Key)
  225. go func() {
  226. filepath.Walk(s.basedir, DiskvVisitor{c}, nil)
  227. close(c)
  228. }()
  229. return c
  230. }
  231. func (s *DStore) IsCached(k Key) bool {
  232. s.mutex.Lock()
  233. defer s.mutex.Unlock()
  234. _, present := s.cache[k]
  235. return present
  236. }
  237. func (s *DStore) IsIndexed(k Key) bool {
  238. if s.index != nil {
  239. s.mutex.Lock()
  240. defer s.mutex.Unlock()
  241. return s.index.Has(k)
  242. }
  243. return false
  244. }
  245. // Return a maximum of count keys from the index, starting at
  246. // one beyond the given key and iterating forward
  247. func (s *DStore) KeysFrom(k Key, count int) ([]Key, os.Error) {
  248. if s.index == nil {
  249. panic("KeysFrom cannot be called on non-ordered store")
  250. }
  251. if s.index.Len() <= 0 {
  252. return []Key{}, nil
  253. }
  254. skip_first := true
  255. if len(k) <= 0 || !s.index.Has(k) {
  256. k = s.index.Min().(Key) // no such key, so start at the top
  257. skip_first = false
  258. }
  259. keys := make([]Key, count)
  260. c := s.index.IterRange(k, s.index.Max())
  261. total := 0
  262. if skip_first {
  263. <-c
  264. }
  265. for i, k := 0, <-c; i < count && k != nil; i, k = i+1, <-c {
  266. keys[i] = k.(Key)
  267. total++
  268. }
  269. if total < count { // hack to get around IterRange returning only E < @upper
  270. keys[total] = s.index.Max().(Key)
  271. total++
  272. }
  273. keys = keys[:total]
  274. return keys, nil
  275. }