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.

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