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.

180 lines
3.2 KiB

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
  1. package db
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "sync"
  7. )
  8. func init() {
  9. registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) {
  10. return NewMemDB(), nil
  11. }, false)
  12. }
  13. type MemDB struct {
  14. mtx sync.Mutex
  15. db map[string][]byte
  16. }
  17. func NewMemDB() *MemDB {
  18. database := &MemDB{db: make(map[string][]byte)}
  19. return database
  20. }
  21. func (db *MemDB) Get(key []byte) []byte {
  22. db.mtx.Lock()
  23. defer db.mtx.Unlock()
  24. return db.db[string(key)]
  25. }
  26. func (db *MemDB) Set(key []byte, value []byte) {
  27. db.mtx.Lock()
  28. defer db.mtx.Unlock()
  29. db.db[string(key)] = value
  30. }
  31. func (db *MemDB) SetSync(key []byte, value []byte) {
  32. db.mtx.Lock()
  33. defer db.mtx.Unlock()
  34. db.db[string(key)] = value
  35. }
  36. func (db *MemDB) Delete(key []byte) {
  37. db.mtx.Lock()
  38. defer db.mtx.Unlock()
  39. delete(db.db, string(key))
  40. }
  41. func (db *MemDB) DeleteSync(key []byte) {
  42. db.mtx.Lock()
  43. defer db.mtx.Unlock()
  44. delete(db.db, string(key))
  45. }
  46. func (db *MemDB) Close() {
  47. // Close is a noop since for an in-memory
  48. // database, we don't have a destination
  49. // to flush contents to nor do we want
  50. // any data loss on invoking Close()
  51. // See the discussion in https://github.com/tendermint/tmlibs/pull/56
  52. }
  53. func (db *MemDB) Print() {
  54. db.mtx.Lock()
  55. defer db.mtx.Unlock()
  56. for key, value := range db.db {
  57. fmt.Printf("[%X]:\t[%X]\n", []byte(key), value)
  58. }
  59. }
  60. func (db *MemDB) Stats() map[string]string {
  61. stats := make(map[string]string)
  62. stats["database.type"] = "memDB"
  63. return stats
  64. }
  65. type memDBIterator struct {
  66. last int
  67. keys []string
  68. db *MemDB
  69. }
  70. func newMemDBIterator() *memDBIterator {
  71. return &memDBIterator{}
  72. }
  73. func (it *memDBIterator) Next() bool {
  74. if it.last >= len(it.keys)-1 {
  75. return false
  76. }
  77. it.last++
  78. return true
  79. }
  80. func (it *memDBIterator) Key() []byte {
  81. return []byte(it.keys[it.last])
  82. }
  83. func (it *memDBIterator) Value() []byte {
  84. return it.db.Get(it.Key())
  85. }
  86. func (it *memDBIterator) Release() {
  87. it.db = nil
  88. it.keys = nil
  89. }
  90. func (it *memDBIterator) Error() error {
  91. return nil
  92. }
  93. func (db *MemDB) Iterator() Iterator {
  94. return db.IteratorPrefix([]byte{})
  95. }
  96. func (db *MemDB) IteratorPrefix(prefix []byte) Iterator {
  97. it := newMemDBIterator()
  98. it.db = db
  99. it.last = -1
  100. db.mtx.Lock()
  101. defer db.mtx.Unlock()
  102. // unfortunately we need a copy of all of the keys
  103. for key, _ := range db.db {
  104. if strings.HasPrefix(key, string(prefix)) {
  105. it.keys = append(it.keys, key)
  106. }
  107. }
  108. // and we need to sort them
  109. sort.Strings(it.keys)
  110. return it
  111. }
  112. func (db *MemDB) NewBatch() Batch {
  113. return &memDBBatch{db, nil}
  114. }
  115. //--------------------------------------------------------------------------------
  116. type memDBBatch struct {
  117. db *MemDB
  118. ops []operation
  119. }
  120. type opType int
  121. const (
  122. opTypeSet = 1
  123. opTypeDelete = 2
  124. )
  125. type operation struct {
  126. opType
  127. key []byte
  128. value []byte
  129. }
  130. func (mBatch *memDBBatch) Set(key, value []byte) {
  131. mBatch.ops = append(mBatch.ops, operation{opTypeSet, key, value})
  132. }
  133. func (mBatch *memDBBatch) Delete(key []byte) {
  134. mBatch.ops = append(mBatch.ops, operation{opTypeDelete, key, nil})
  135. }
  136. func (mBatch *memDBBatch) Write() {
  137. mBatch.db.mtx.Lock()
  138. defer mBatch.db.mtx.Unlock()
  139. for _, op := range mBatch.ops {
  140. if op.opType == opTypeSet {
  141. mBatch.db.db[string(op.key)] = op.value
  142. } else if op.opType == opTypeDelete {
  143. delete(mBatch.db.db, string(op.key))
  144. }
  145. }
  146. }