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.

332 lines
6.6 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. start, end := ...
  25. return newPrefixIterator(prefix, start, end, IteratePrefix(db, prefix))
  26. }
  27. */
  28. //----------------------------------------
  29. // prefixDB
  30. type prefixDB struct {
  31. mtx sync.Mutex
  32. prefix []byte
  33. db DB
  34. }
  35. // NewPrefixDB lets you namespace multiple DBs within a single DB.
  36. func NewPrefixDB(db DB, prefix []byte) *prefixDB {
  37. return &prefixDB{
  38. prefix: prefix,
  39. db: db,
  40. }
  41. }
  42. // Implements atomicSetDeleter.
  43. func (pdb *prefixDB) Mutex() *sync.Mutex {
  44. return &(pdb.mtx)
  45. }
  46. // Implements DB.
  47. func (pdb *prefixDB) Get(key []byte) []byte {
  48. pdb.mtx.Lock()
  49. defer pdb.mtx.Unlock()
  50. pkey := pdb.prefixed(key)
  51. value := pdb.db.Get(pkey)
  52. return value
  53. }
  54. // Implements DB.
  55. func (pdb *prefixDB) Has(key []byte) bool {
  56. pdb.mtx.Lock()
  57. defer pdb.mtx.Unlock()
  58. return pdb.db.Has(pdb.prefixed(key))
  59. }
  60. // Implements DB.
  61. func (pdb *prefixDB) Set(key []byte, value []byte) {
  62. pdb.mtx.Lock()
  63. defer pdb.mtx.Unlock()
  64. pkey := pdb.prefixed(key)
  65. pdb.db.Set(pkey, value)
  66. }
  67. // Implements DB.
  68. func (pdb *prefixDB) SetSync(key []byte, value []byte) {
  69. pdb.mtx.Lock()
  70. defer pdb.mtx.Unlock()
  71. pdb.db.SetSync(pdb.prefixed(key), value)
  72. }
  73. // Implements DB.
  74. func (pdb *prefixDB) Delete(key []byte) {
  75. pdb.mtx.Lock()
  76. defer pdb.mtx.Unlock()
  77. pdb.db.Delete(pdb.prefixed(key))
  78. }
  79. // Implements DB.
  80. func (pdb *prefixDB) DeleteSync(key []byte) {
  81. pdb.mtx.Lock()
  82. defer pdb.mtx.Unlock()
  83. pdb.db.DeleteSync(pdb.prefixed(key))
  84. }
  85. // Implements DB.
  86. func (pdb *prefixDB) Iterator(start, end []byte) Iterator {
  87. pdb.mtx.Lock()
  88. defer pdb.mtx.Unlock()
  89. var pstart, pend []byte
  90. pstart = append(cp(pdb.prefix), start...)
  91. if end == nil {
  92. pend = cpIncr(pdb.prefix)
  93. } else {
  94. pend = append(cp(pdb.prefix), end...)
  95. }
  96. return newPrefixIterator(
  97. pdb.prefix,
  98. start,
  99. end,
  100. pdb.db.Iterator(
  101. pstart,
  102. pend,
  103. ),
  104. )
  105. }
  106. // Implements DB.
  107. func (pdb *prefixDB) ReverseIterator(start, end []byte) Iterator {
  108. pdb.mtx.Lock()
  109. defer pdb.mtx.Unlock()
  110. var pstart, pend []byte
  111. pstart = append(cp(pdb.prefix), start...)
  112. if end == nil {
  113. pend = cpIncr(pdb.prefix)
  114. } else {
  115. pend = append(cp(pdb.prefix), end...)
  116. }
  117. ritr := pdb.db.ReverseIterator(pstart, pend)
  118. return newPrefixIterator(
  119. pdb.prefix,
  120. start,
  121. end,
  122. ritr,
  123. )
  124. }
  125. // Implements DB.
  126. // Panics if the underlying DB is not an
  127. // atomicSetDeleter.
  128. func (pdb *prefixDB) NewBatch() Batch {
  129. pdb.mtx.Lock()
  130. defer pdb.mtx.Unlock()
  131. return newPrefixBatch(pdb.prefix, pdb.db.NewBatch())
  132. }
  133. /* NOTE: Uncomment to use memBatch instead of prefixBatch
  134. // Implements atomicSetDeleter.
  135. func (pdb *prefixDB) SetNoLock(key []byte, value []byte) {
  136. pdb.db.(atomicSetDeleter).SetNoLock(pdb.prefixed(key), value)
  137. }
  138. // Implements atomicSetDeleter.
  139. func (pdb *prefixDB) SetNoLockSync(key []byte, value []byte) {
  140. pdb.db.(atomicSetDeleter).SetNoLockSync(pdb.prefixed(key), value)
  141. }
  142. // Implements atomicSetDeleter.
  143. func (pdb *prefixDB) DeleteNoLock(key []byte) {
  144. pdb.db.(atomicSetDeleter).DeleteNoLock(pdb.prefixed(key))
  145. }
  146. // Implements atomicSetDeleter.
  147. func (pdb *prefixDB) DeleteNoLockSync(key []byte) {
  148. pdb.db.(atomicSetDeleter).DeleteNoLockSync(pdb.prefixed(key))
  149. }
  150. */
  151. // Implements DB.
  152. func (pdb *prefixDB) Close() {
  153. pdb.mtx.Lock()
  154. defer pdb.mtx.Unlock()
  155. pdb.db.Close()
  156. }
  157. // Implements DB.
  158. func (pdb *prefixDB) Print() {
  159. fmt.Printf("prefix: %X\n", pdb.prefix)
  160. itr := pdb.Iterator(nil, nil)
  161. defer itr.Close()
  162. for ; itr.Valid(); itr.Next() {
  163. key := itr.Key()
  164. value := itr.Value()
  165. fmt.Printf("[%X]:\t[%X]\n", key, value)
  166. }
  167. }
  168. // Implements DB.
  169. func (pdb *prefixDB) Stats() map[string]string {
  170. stats := make(map[string]string)
  171. stats["prefixdb.prefix.string"] = string(pdb.prefix)
  172. stats["prefixdb.prefix.hex"] = fmt.Sprintf("%X", pdb.prefix)
  173. source := pdb.db.Stats()
  174. for key, value := range source {
  175. stats["prefixdb.source."+key] = value
  176. }
  177. return stats
  178. }
  179. func (pdb *prefixDB) prefixed(key []byte) []byte {
  180. return append(cp(pdb.prefix), key...)
  181. }
  182. //----------------------------------------
  183. // prefixBatch
  184. type prefixBatch struct {
  185. prefix []byte
  186. source Batch
  187. }
  188. func newPrefixBatch(prefix []byte, source Batch) prefixBatch {
  189. return prefixBatch{
  190. prefix: prefix,
  191. source: source,
  192. }
  193. }
  194. func (pb prefixBatch) Set(key, value []byte) {
  195. pkey := append(cp(pb.prefix), key...)
  196. pb.source.Set(pkey, value)
  197. }
  198. func (pb prefixBatch) Delete(key []byte) {
  199. pkey := append(cp(pb.prefix), key...)
  200. pb.source.Delete(pkey)
  201. }
  202. func (pb prefixBatch) Write() {
  203. pb.source.Write()
  204. }
  205. func (pb prefixBatch) WriteSync() {
  206. pb.source.WriteSync()
  207. }
  208. //----------------------------------------
  209. // prefixIterator
  210. var _ Iterator = (*prefixIterator)(nil)
  211. // Strips prefix while iterating from Iterator.
  212. type prefixIterator struct {
  213. prefix []byte
  214. start []byte
  215. end []byte
  216. source Iterator
  217. valid bool
  218. }
  219. func newPrefixIterator(prefix, start, end []byte, source Iterator) *prefixIterator {
  220. if !source.Valid() || !bytes.HasPrefix(source.Key(), prefix) {
  221. return &prefixIterator{
  222. prefix: prefix,
  223. start: start,
  224. end: end,
  225. source: source,
  226. valid: false,
  227. }
  228. } else {
  229. return &prefixIterator{
  230. prefix: prefix,
  231. start: start,
  232. end: end,
  233. source: source,
  234. valid: true,
  235. }
  236. }
  237. }
  238. func (itr *prefixIterator) Domain() (start []byte, end []byte) {
  239. return itr.start, itr.end
  240. }
  241. func (itr *prefixIterator) Valid() bool {
  242. return itr.valid && itr.source.Valid()
  243. }
  244. func (itr *prefixIterator) Next() {
  245. if !itr.valid {
  246. panic("prefixIterator invalid, cannot call Next()")
  247. }
  248. itr.source.Next()
  249. if !itr.source.Valid() || !bytes.HasPrefix(itr.source.Key(), itr.prefix) {
  250. itr.valid = false
  251. return
  252. }
  253. }
  254. func (itr *prefixIterator) Key() (key []byte) {
  255. if !itr.valid {
  256. panic("prefixIterator invalid, cannot call Key()")
  257. }
  258. return stripPrefix(itr.source.Key(), itr.prefix)
  259. }
  260. func (itr *prefixIterator) Value() (value []byte) {
  261. if !itr.valid {
  262. panic("prefixIterator invalid, cannot call Value()")
  263. }
  264. return itr.source.Value()
  265. }
  266. func (itr *prefixIterator) Close() {
  267. itr.source.Close()
  268. }
  269. //----------------------------------------
  270. func stripPrefix(key []byte, prefix []byte) (stripped []byte) {
  271. if len(key) < len(prefix) {
  272. panic("should not happen")
  273. }
  274. if !bytes.Equal(key[:len(prefix)], prefix) {
  275. panic("should not happne")
  276. }
  277. return key[len(prefix):]
  278. }