You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
5.1 KiB

  1. package db
  2. import (
  3. "bytes"
  4. "fmt"
  5. "sync"
  6. )
  7. // IteratePrefix is a convenience function for iterating over a key domain
  8. // restricted by prefix.
  9. func IteratePrefix(db DB, prefix []byte) Iterator {
  10. var start, end []byte
  11. if len(prefix) == 0 {
  12. start = nil
  13. end = nil
  14. } else {
  15. start = cp(prefix)
  16. end = cpIncr(prefix)
  17. }
  18. return db.Iterator(start, end)
  19. }
  20. /*
  21. TODO: Make test, maybe rename.
  22. // Like IteratePrefix but the iterator strips the prefix from the keys.
  23. func IteratePrefixStripped(db DB, prefix []byte) Iterator {
  24. return newUnprefixIterator(prefix, IteratePrefix(db, prefix))
  25. }
  26. */
  27. //----------------------------------------
  28. // prefixDB
  29. type prefixDB struct {
  30. mtx sync.Mutex
  31. prefix []byte
  32. db DB
  33. }
  34. // NewPrefixDB lets you namespace multiple DBs within a single DB.
  35. func NewPrefixDB(db DB, prefix []byte) *prefixDB {
  36. return &prefixDB{
  37. prefix: prefix,
  38. db: db,
  39. }
  40. }
  41. // Implements atomicSetDeleter.
  42. func (pdb *prefixDB) Mutex() *sync.Mutex {
  43. return &(pdb.mtx)
  44. }
  45. // Implements DB.
  46. func (pdb *prefixDB) Get(key []byte) []byte {
  47. pdb.mtx.Lock()
  48. defer pdb.mtx.Unlock()
  49. return pdb.db.Get(pdb.prefixed(key))
  50. }
  51. // Implements DB.
  52. func (pdb *prefixDB) Has(key []byte) bool {
  53. pdb.mtx.Lock()
  54. defer pdb.mtx.Unlock()
  55. return pdb.db.Has(pdb.prefixed(key))
  56. }
  57. // Implements DB.
  58. func (pdb *prefixDB) Set(key []byte, value []byte) {
  59. pdb.mtx.Lock()
  60. defer pdb.mtx.Unlock()
  61. pdb.db.Set(pdb.prefixed(key), value)
  62. }
  63. // Implements DB.
  64. func (pdb *prefixDB) SetSync(key []byte, value []byte) {
  65. pdb.mtx.Lock()
  66. defer pdb.mtx.Unlock()
  67. pdb.db.SetSync(pdb.prefixed(key), value)
  68. }
  69. // Implements atomicSetDeleter.
  70. func (pdb *prefixDB) SetNoLock(key []byte, value []byte) {
  71. pdb.db.Set(pdb.prefixed(key), value)
  72. }
  73. // Implements atomicSetDeleter.
  74. func (pdb *prefixDB) SetNoLockSync(key []byte, value []byte) {
  75. pdb.db.SetSync(pdb.prefixed(key), value)
  76. }
  77. // Implements DB.
  78. func (pdb *prefixDB) Delete(key []byte) {
  79. pdb.mtx.Lock()
  80. defer pdb.mtx.Unlock()
  81. pdb.db.Delete(pdb.prefixed(key))
  82. }
  83. // Implements DB.
  84. func (pdb *prefixDB) DeleteSync(key []byte) {
  85. pdb.mtx.Lock()
  86. defer pdb.mtx.Unlock()
  87. pdb.db.DeleteSync(pdb.prefixed(key))
  88. }
  89. // Implements atomicSetDeleter.
  90. func (pdb *prefixDB) DeleteNoLock(key []byte) {
  91. pdb.db.Delete(pdb.prefixed(key))
  92. }
  93. // Implements atomicSetDeleter.
  94. func (pdb *prefixDB) DeleteNoLockSync(key []byte) {
  95. pdb.db.DeleteSync(pdb.prefixed(key))
  96. }
  97. // Implements DB.
  98. func (pdb *prefixDB) Iterator(start, end []byte) Iterator {
  99. pdb.mtx.Lock()
  100. defer pdb.mtx.Unlock()
  101. pstart := append(pdb.prefix, start...)
  102. pend := []byte(nil)
  103. if end != nil {
  104. pend = append(pdb.prefix, end...)
  105. }
  106. return newUnprefixIterator(
  107. pdb.prefix,
  108. pdb.db.Iterator(
  109. pstart,
  110. pend,
  111. ),
  112. )
  113. }
  114. // Implements DB.
  115. func (pdb *prefixDB) ReverseIterator(start, end []byte) Iterator {
  116. pdb.mtx.Lock()
  117. defer pdb.mtx.Unlock()
  118. pstart := []byte(nil)
  119. if start != nil {
  120. pstart = append(pdb.prefix, start...)
  121. }
  122. pend := []byte(nil)
  123. if end != nil {
  124. pend = append(pdb.prefix, end...)
  125. }
  126. return newUnprefixIterator(
  127. pdb.prefix,
  128. pdb.db.ReverseIterator(
  129. pstart,
  130. pend,
  131. ),
  132. )
  133. }
  134. // Implements DB.
  135. func (pdb *prefixDB) NewBatch() Batch {
  136. pdb.mtx.Lock()
  137. defer pdb.mtx.Unlock()
  138. return &memBatch{pdb, nil}
  139. }
  140. // Implements DB.
  141. func (pdb *prefixDB) Close() {
  142. pdb.mtx.Lock()
  143. defer pdb.mtx.Unlock()
  144. pdb.db.Close()
  145. }
  146. // Implements DB.
  147. func (pdb *prefixDB) Print() {
  148. fmt.Printf("prefix: %X\n", pdb.prefix)
  149. itr := pdb.Iterator(nil, nil)
  150. defer itr.Close()
  151. for ; itr.Valid(); itr.Next() {
  152. key := itr.Key()
  153. value := itr.Value()
  154. fmt.Printf("[%X]:\t[%X]\n", key, value)
  155. }
  156. }
  157. // Implements DB.
  158. func (pdb *prefixDB) Stats() map[string]string {
  159. stats := make(map[string]string)
  160. stats["prefixdb.prefix.string"] = string(pdb.prefix)
  161. stats["prefixdb.prefix.hex"] = fmt.Sprintf("%X", pdb.prefix)
  162. source := pdb.db.Stats()
  163. for key, value := range source {
  164. stats["prefixdb.source."+key] = value
  165. }
  166. return stats
  167. }
  168. func (pdb *prefixDB) prefixed(key []byte) []byte {
  169. return append(pdb.prefix, key...)
  170. }
  171. //----------------------------------------
  172. // Strips prefix while iterating from Iterator.
  173. type unprefixIterator struct {
  174. prefix []byte
  175. source Iterator
  176. }
  177. func newUnprefixIterator(prefix []byte, source Iterator) unprefixIterator {
  178. return unprefixIterator{
  179. prefix: prefix,
  180. source: source,
  181. }
  182. }
  183. func (itr unprefixIterator) Domain() (start []byte, end []byte) {
  184. start, end = itr.source.Domain()
  185. if len(start) > 0 {
  186. start = stripPrefix(start, itr.prefix)
  187. }
  188. if len(end) > 0 {
  189. end = stripPrefix(end, itr.prefix)
  190. }
  191. return
  192. }
  193. func (itr unprefixIterator) Valid() bool {
  194. return itr.source.Valid()
  195. }
  196. func (itr unprefixIterator) Next() {
  197. itr.source.Next()
  198. }
  199. func (itr unprefixIterator) Key() (key []byte) {
  200. return stripPrefix(itr.source.Key(), itr.prefix)
  201. }
  202. func (itr unprefixIterator) Value() (value []byte) {
  203. return itr.source.Value()
  204. }
  205. func (itr unprefixIterator) Close() {
  206. itr.source.Close()
  207. }
  208. //----------------------------------------
  209. func stripPrefix(key []byte, prefix []byte) (stripped []byte) {
  210. if len(key) < len(prefix) {
  211. panic("should not happen")
  212. }
  213. if !bytes.Equal(key[:len(prefix)], prefix) {
  214. panic("should not happne")
  215. }
  216. return key[len(prefix):]
  217. }