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.

226 lines
4.2 KiB

9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
7 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
7 years ago
7 years ago
  1. package db
  2. import (
  3. "fmt"
  4. "sort"
  5. "sync"
  6. )
  7. func init() {
  8. registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) {
  9. return NewMemDB(), nil
  10. }, false)
  11. }
  12. var _ DB = (*MemDB)(nil)
  13. type MemDB struct {
  14. mtx sync.Mutex
  15. db map[string][]byte
  16. }
  17. func NewMemDB() *MemDB {
  18. database := &MemDB{
  19. db: make(map[string][]byte),
  20. }
  21. return database
  22. }
  23. func (db *MemDB) Get(key []byte) []byte {
  24. db.mtx.Lock()
  25. defer db.mtx.Unlock()
  26. panicNilKey(key)
  27. return db.db[string(key)]
  28. }
  29. func (db *MemDB) Has(key []byte) bool {
  30. db.mtx.Lock()
  31. defer db.mtx.Unlock()
  32. panicNilKey(key)
  33. _, ok := db.db[string(key)]
  34. return ok
  35. }
  36. func (db *MemDB) Set(key []byte, value []byte) {
  37. db.mtx.Lock()
  38. defer db.mtx.Unlock()
  39. panicNilKey(key)
  40. db.SetNoLock(key, value)
  41. }
  42. func (db *MemDB) SetSync(key []byte, value []byte) {
  43. db.mtx.Lock()
  44. defer db.mtx.Unlock()
  45. panicNilKey(key)
  46. db.SetNoLock(key, value)
  47. }
  48. // NOTE: Implements atomicSetDeleter
  49. func (db *MemDB) SetNoLock(key []byte, value []byte) {
  50. if value == nil {
  51. value = []byte{}
  52. }
  53. panicNilKey(key)
  54. db.db[string(key)] = value
  55. }
  56. func (db *MemDB) Delete(key []byte) {
  57. db.mtx.Lock()
  58. defer db.mtx.Unlock()
  59. panicNilKey(key)
  60. delete(db.db, string(key))
  61. }
  62. func (db *MemDB) DeleteSync(key []byte) {
  63. db.mtx.Lock()
  64. defer db.mtx.Unlock()
  65. panicNilKey(key)
  66. delete(db.db, string(key))
  67. }
  68. // NOTE: Implements atomicSetDeleter
  69. func (db *MemDB) DeleteNoLock(key []byte) {
  70. panicNilKey(key)
  71. delete(db.db, string(key))
  72. }
  73. func (db *MemDB) Close() {
  74. // Close is a noop since for an in-memory
  75. // database, we don't have a destination
  76. // to flush contents to nor do we want
  77. // any data loss on invoking Close()
  78. // See the discussion in https://github.com/tendermint/tmlibs/pull/56
  79. }
  80. func (db *MemDB) Print() {
  81. db.mtx.Lock()
  82. defer db.mtx.Unlock()
  83. for key, value := range db.db {
  84. fmt.Printf("[%X]:\t[%X]\n", []byte(key), value)
  85. }
  86. }
  87. func (db *MemDB) Stats() map[string]string {
  88. db.mtx.Lock()
  89. defer db.mtx.Unlock()
  90. stats := make(map[string]string)
  91. stats["database.type"] = "memDB"
  92. stats["database.size"] = fmt.Sprintf("%d", len(db.db))
  93. return stats
  94. }
  95. func (db *MemDB) NewBatch() Batch {
  96. db.mtx.Lock()
  97. defer db.mtx.Unlock()
  98. return &memBatch{db, nil}
  99. }
  100. func (db *MemDB) Mutex() *sync.Mutex {
  101. return &(db.mtx)
  102. }
  103. //----------------------------------------
  104. func (db *MemDB) Iterator(start, end []byte) Iterator {
  105. it := newMemDBIterator(db, start, end)
  106. db.mtx.Lock()
  107. defer db.mtx.Unlock()
  108. // We need a copy of all of the keys.
  109. // Not the best, but probably not a bottleneck depending.
  110. it.keys = db.getSortedKeys(start, end)
  111. return it
  112. }
  113. func (db *MemDB) ReverseIterator(start, end []byte) Iterator {
  114. it := newMemDBIterator(db, start, end)
  115. db.mtx.Lock()
  116. defer db.mtx.Unlock()
  117. // We need a copy of all of the keys.
  118. // Not the best, but probably not a bottleneck depending.
  119. it.keys = db.getSortedKeys(end, start)
  120. // reverse the order
  121. l := len(it.keys) - 1
  122. for i, v := range it.keys {
  123. it.keys[i] = it.keys[l-i]
  124. it.keys[l-i] = v
  125. }
  126. return nil
  127. }
  128. func (db *MemDB) getSortedKeys(start, end []byte) []string {
  129. keys := []string{}
  130. for key, _ := range db.db {
  131. if IsKeyInDomain(key, start, end) {
  132. keys = append(keys, key)
  133. }
  134. }
  135. sort.Strings(keys)
  136. return keys
  137. }
  138. var _ Iterator = (*memDBIterator)(nil)
  139. type memDBIterator struct {
  140. cur int
  141. keys []string
  142. db DB
  143. start, end []byte
  144. }
  145. func newMemDBIterator(db DB, start, end []byte) *memDBIterator {
  146. return &memDBIterator{
  147. db: db,
  148. start: start,
  149. end: end,
  150. }
  151. }
  152. func (it *memDBIterator) Domain() ([]byte, []byte) {
  153. return it.start, it.end
  154. }
  155. func (it *memDBIterator) Valid() bool {
  156. return 0 <= it.cur && it.cur < len(it.keys)
  157. }
  158. func (it *memDBIterator) Next() {
  159. if !it.Valid() {
  160. panic("memDBIterator Next() called when invalid")
  161. }
  162. it.cur++
  163. }
  164. func (it *memDBIterator) Prev() {
  165. if !it.Valid() {
  166. panic("memDBIterator Next() called when invalid")
  167. }
  168. it.cur--
  169. }
  170. func (it *memDBIterator) Key() []byte {
  171. if !it.Valid() {
  172. panic("memDBIterator Key() called when invalid")
  173. }
  174. return []byte(it.keys[it.cur])
  175. }
  176. func (it *memDBIterator) Value() []byte {
  177. if !it.Valid() {
  178. panic("memDBIterator Value() called when invalid")
  179. }
  180. return it.db.Get(it.Key())
  181. }
  182. func (it *memDBIterator) Close() {
  183. it.db = nil
  184. it.keys = nil
  185. }
  186. func (it *memDBIterator) Release() {}