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.

255 lines
4.8 KiB

9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 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
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(MemDBBackend, 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. // Implements atomicSetDeleter.
  24. func (db *MemDB) Mutex() *sync.Mutex {
  25. return &(db.mtx)
  26. }
  27. // Implements DB.
  28. func (db *MemDB) Get(key []byte) []byte {
  29. db.mtx.Lock()
  30. defer db.mtx.Unlock()
  31. key = nonNilBytes(key)
  32. value := db.db[string(key)]
  33. return value
  34. }
  35. // Implements DB.
  36. func (db *MemDB) Has(key []byte) bool {
  37. db.mtx.Lock()
  38. defer db.mtx.Unlock()
  39. key = nonNilBytes(key)
  40. _, ok := db.db[string(key)]
  41. return ok
  42. }
  43. // Implements DB.
  44. func (db *MemDB) Set(key []byte, value []byte) {
  45. db.mtx.Lock()
  46. defer db.mtx.Unlock()
  47. db.SetNoLock(key, value)
  48. }
  49. // Implements DB.
  50. func (db *MemDB) SetSync(key []byte, value []byte) {
  51. db.mtx.Lock()
  52. defer db.mtx.Unlock()
  53. db.SetNoLock(key, value)
  54. }
  55. // Implements atomicSetDeleter.
  56. func (db *MemDB) SetNoLock(key []byte, value []byte) {
  57. db.SetNoLockSync(key, value)
  58. }
  59. // Implements atomicSetDeleter.
  60. func (db *MemDB) SetNoLockSync(key []byte, value []byte) {
  61. key = nonNilBytes(key)
  62. value = nonNilBytes(value)
  63. db.db[string(key)] = value
  64. }
  65. // Implements DB.
  66. func (db *MemDB) Delete(key []byte) {
  67. db.mtx.Lock()
  68. defer db.mtx.Unlock()
  69. db.DeleteNoLock(key)
  70. }
  71. // Implements DB.
  72. func (db *MemDB) DeleteSync(key []byte) {
  73. db.mtx.Lock()
  74. defer db.mtx.Unlock()
  75. db.DeleteNoLock(key)
  76. }
  77. // Implements atomicSetDeleter.
  78. func (db *MemDB) DeleteNoLock(key []byte) {
  79. db.DeleteNoLockSync(key)
  80. }
  81. // Implements atomicSetDeleter.
  82. func (db *MemDB) DeleteNoLockSync(key []byte) {
  83. key = nonNilBytes(key)
  84. delete(db.db, string(key))
  85. }
  86. // Implements DB.
  87. func (db *MemDB) Close() {
  88. // Close is a noop since for an in-memory
  89. // database, we don't have a destination
  90. // to flush contents to nor do we want
  91. // any data loss on invoking Close()
  92. // See the discussion in https://github.com/tendermint/tmlibs/pull/56
  93. }
  94. // Implements DB.
  95. func (db *MemDB) Print() {
  96. db.mtx.Lock()
  97. defer db.mtx.Unlock()
  98. for key, value := range db.db {
  99. fmt.Printf("[%X]:\t[%X]\n", []byte(key), value)
  100. }
  101. }
  102. // Implements DB.
  103. func (db *MemDB) Stats() map[string]string {
  104. db.mtx.Lock()
  105. defer db.mtx.Unlock()
  106. stats := make(map[string]string)
  107. stats["database.type"] = "memDB"
  108. stats["database.size"] = fmt.Sprintf("%d", len(db.db))
  109. return stats
  110. }
  111. // Implements DB.
  112. func (db *MemDB) NewBatch() Batch {
  113. db.mtx.Lock()
  114. defer db.mtx.Unlock()
  115. return &memBatch{db, nil}
  116. }
  117. //----------------------------------------
  118. // Iterator
  119. // Implements DB.
  120. func (db *MemDB) Iterator(start, end []byte) Iterator {
  121. db.mtx.Lock()
  122. defer db.mtx.Unlock()
  123. keys := db.getSortedKeys(start, end, false)
  124. return newMemDBIterator(db, keys, start, end)
  125. }
  126. // Implements DB.
  127. func (db *MemDB) ReverseIterator(start, end []byte) Iterator {
  128. db.mtx.Lock()
  129. defer db.mtx.Unlock()
  130. keys := db.getSortedKeys(start, end, true)
  131. return newMemDBIterator(db, keys, start, end)
  132. }
  133. // We need a copy of all of the keys.
  134. // Not the best, but probably not a bottleneck depending.
  135. type memDBIterator struct {
  136. db DB
  137. cur int
  138. keys []string
  139. start []byte
  140. end []byte
  141. }
  142. var _ Iterator = (*memDBIterator)(nil)
  143. // Keys is expected to be in reverse order for reverse iterators.
  144. func newMemDBIterator(db DB, keys []string, start, end []byte) *memDBIterator {
  145. return &memDBIterator{
  146. db: db,
  147. cur: 0,
  148. keys: keys,
  149. start: start,
  150. end: end,
  151. }
  152. }
  153. // Implements Iterator.
  154. func (itr *memDBIterator) Domain() ([]byte, []byte) {
  155. return itr.start, itr.end
  156. }
  157. // Implements Iterator.
  158. func (itr *memDBIterator) Valid() bool {
  159. return 0 <= itr.cur && itr.cur < len(itr.keys)
  160. }
  161. // Implements Iterator.
  162. func (itr *memDBIterator) Next() {
  163. itr.assertIsValid()
  164. itr.cur++
  165. }
  166. // Implements Iterator.
  167. func (itr *memDBIterator) Key() []byte {
  168. itr.assertIsValid()
  169. return []byte(itr.keys[itr.cur])
  170. }
  171. // Implements Iterator.
  172. func (itr *memDBIterator) Value() []byte {
  173. itr.assertIsValid()
  174. key := []byte(itr.keys[itr.cur])
  175. return itr.db.Get(key)
  176. }
  177. // Implements Iterator.
  178. func (itr *memDBIterator) Close() {
  179. itr.keys = nil
  180. itr.db = nil
  181. }
  182. func (itr *memDBIterator) assertIsValid() {
  183. if !itr.Valid() {
  184. panic("memDBIterator is invalid")
  185. }
  186. }
  187. //----------------------------------------
  188. // Misc.
  189. func (db *MemDB) getSortedKeys(start, end []byte, reverse bool) []string {
  190. keys := []string{}
  191. for key := range db.db {
  192. inDomain := IsKeyInDomain([]byte(key), start, end, reverse)
  193. if inDomain {
  194. keys = append(keys, key)
  195. }
  196. }
  197. sort.Strings(keys)
  198. if reverse {
  199. nkeys := len(keys)
  200. for i := 0; i < nkeys/2; i++ {
  201. temp := keys[i]
  202. keys[i] = keys[nkeys-i-1]
  203. keys[nkeys-i-1] = temp
  204. }
  205. }
  206. return keys
  207. }