slowpoke.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Package slowpoke implements a low-level key/value store in pure Go.
  2. // Keys stored in memory, Value stored on disk
  3. package slowpoke
  4. import (
  5. "bytes"
  6. "encoding/binary"
  7. "encoding/gob"
  8. "reflect"
  9. "github.com/recoilme/pudge"
  10. )
  11. // Set store val and key with sync at end
  12. // File - may be existing file or new
  13. // If path to file contains dirs - dirs will be created
  14. // If val is nil - will store only key
  15. func Set(file string, key []byte, val []byte) (err error) {
  16. return pudge.Set(file, key, val)
  17. }
  18. // Put store val and key with sync at end. It's wrapper for Set.
  19. func Put(file string, key []byte, val []byte) (err error) {
  20. return pudge.Set(file, key, val)
  21. }
  22. // SetGob - experimental future for lazy usage, see tests
  23. func SetGob(file string, key interface{}, val interface{}) (err error) {
  24. bufKey := bytes.Buffer{}
  25. if reflect.TypeOf(key).String() == "[]uint8" {
  26. v := key.([]byte)
  27. _, err = bufKey.Write(v)
  28. } else {
  29. err = gob.NewEncoder(&bufKey).Encode(key)
  30. }
  31. return pudge.Set(file, bufKey.Bytes(), val)
  32. }
  33. // Has return true if key exist or error if any
  34. func Has(file string, key []byte) (exist bool, err error) {
  35. return pudge.Has(file, key)
  36. }
  37. // Count return count of keys or error if any
  38. func Count(file string) (uint64, error) {
  39. cnt, err := pudge.Count(file)
  40. return uint64(cnt), err
  41. }
  42. // Counter return unique uint64
  43. func Counter(file string, key []byte) (counter uint64, err error) {
  44. val, err := Get(file, key)
  45. if val == nil || len(val) != 8 {
  46. err = nil
  47. counter = 0
  48. } else {
  49. counter = binary.BigEndian.Uint64(val)
  50. }
  51. counter++
  52. b := make([]byte, 8)
  53. binary.BigEndian.PutUint64(b, counter)
  54. err = Set(file, key, b)
  55. return counter, err
  56. }
  57. // Open open/create Db (with dirs)
  58. // This operation is locked by mutex
  59. // Return error if any
  60. // Create .idx file for key storage
  61. func Open(file string) (db *pudge.Db, err error) {
  62. return pudge.Open(file, nil)
  63. }
  64. // Get return value by key or nil and error
  65. // Get will open Db if it closed
  66. // return error if any
  67. func Get(file string, key []byte) (val []byte, err error) {
  68. err = pudge.Get(file, key, &val)
  69. return val, err
  70. }
  71. // GetGob - experimental future for lazy usage, see tests
  72. func GetGob(file string, key interface{}, val interface{}) (err error) {
  73. bufKey := bytes.Buffer{}
  74. if reflect.TypeOf(key).String() == "[]uint8" {
  75. v := key.([]byte)
  76. _, err = bufKey.Write(v)
  77. } else {
  78. err = gob.NewEncoder(&bufKey).Encode(key)
  79. }
  80. return pudge.Get(file, bufKey.Bytes(), val)
  81. }
  82. // Keys return keys in ascending or descending order (false - descending,true - ascending)
  83. // if limit == 0 return all keys
  84. // if offset>0 - skip offset records
  85. // If from not nil - return keys after from (from not included)
  86. // If last byte of from == "*" - return keys with this prefix
  87. func Keys(file string, from []byte, limit, offset uint32, asc bool) ([][]byte, error) {
  88. if from == nil {
  89. return pudge.Keys(file, nil, int(limit), int(offset), asc)
  90. }
  91. return pudge.Keys(file, from, int(limit), int(offset), asc)
  92. }
  93. // Close - close Db and free used memory
  94. // It run finalizer and cancel goroutine
  95. func Close(file string) (err error) {
  96. return pudge.Close(file)
  97. }
  98. // CloseAll - close all opened Db
  99. func CloseAll() (err error) {
  100. return pudge.CloseAll()
  101. }
  102. // DeleteFile close file key and file val and delete db from map and disk
  103. // All data will be loss!
  104. func DeleteFile(file string) (err error) {
  105. return pudge.DeleteFile(file)
  106. }
  107. // Gets return key/value pairs in random order
  108. // result contains key and value
  109. // Gets not return error if key not found
  110. // If no keys found return empty result
  111. func Gets(file string, keys [][]byte) (result [][]byte) {
  112. db, err := Open(file)
  113. if err != nil {
  114. return nil
  115. }
  116. for _, key := range keys {
  117. var v []byte
  118. err := db.Get(key, &v)
  119. if err == nil {
  120. result = append(result, key)
  121. result = append(result, v)
  122. }
  123. }
  124. return result
  125. }
  126. // Sets store vals and keys
  127. // Sync will called only at end of insertion
  128. // Use it for mass insertion
  129. // every pair must contain key and value
  130. func Sets(file string, pairs [][]byte) (err error) {
  131. db, err := Open(file)
  132. //fmt.Println("set", db, err)
  133. if err != nil {
  134. return err
  135. }
  136. for i := range pairs {
  137. if i%2 != 0 {
  138. // on odd - append val and store key
  139. if pairs[i] == nil || pairs[i-1] == nil {
  140. break
  141. }
  142. err = db.Set(pairs[i-1], pairs[i])
  143. if err != nil {
  144. break
  145. }
  146. }
  147. }
  148. return err
  149. }
  150. // Delete key (always return true)
  151. // Delete not remove any data from files
  152. // Return error if any
  153. func Delete(file string, key []byte) (bool, error) {
  154. err := pudge.Delete(file, key)
  155. if err == nil {
  156. return true, nil
  157. }
  158. return false, err
  159. }