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.

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