github.com/tendermint/tmlibs@v0.9.0/db/mem_db.go (about) 1 package db 2 3 import ( 4 "fmt" 5 "sort" 6 "sync" 7 ) 8 9 func init() { 10 registerDBCreator(MemDBBackend, func(name string, dir string) (DB, error) { 11 return NewMemDB(), nil 12 }, false) 13 } 14 15 var _ DB = (*MemDB)(nil) 16 17 type MemDB struct { 18 mtx sync.Mutex 19 db map[string][]byte 20 } 21 22 func NewMemDB() *MemDB { 23 database := &MemDB{ 24 db: make(map[string][]byte), 25 } 26 return database 27 } 28 29 // Implements atomicSetDeleter. 30 func (db *MemDB) Mutex() *sync.Mutex { 31 return &(db.mtx) 32 } 33 34 // Implements DB. 35 func (db *MemDB) Get(key []byte) []byte { 36 db.mtx.Lock() 37 defer db.mtx.Unlock() 38 key = nonNilBytes(key) 39 40 value := db.db[string(key)] 41 return value 42 } 43 44 // Implements DB. 45 func (db *MemDB) Has(key []byte) bool { 46 db.mtx.Lock() 47 defer db.mtx.Unlock() 48 key = nonNilBytes(key) 49 50 _, ok := db.db[string(key)] 51 return ok 52 } 53 54 // Implements DB. 55 func (db *MemDB) Set(key []byte, value []byte) { 56 db.mtx.Lock() 57 defer db.mtx.Unlock() 58 59 db.SetNoLock(key, value) 60 } 61 62 // Implements DB. 63 func (db *MemDB) SetSync(key []byte, value []byte) { 64 db.mtx.Lock() 65 defer db.mtx.Unlock() 66 67 db.SetNoLock(key, value) 68 } 69 70 // Implements atomicSetDeleter. 71 func (db *MemDB) SetNoLock(key []byte, value []byte) { 72 db.SetNoLockSync(key, value) 73 } 74 75 // Implements atomicSetDeleter. 76 func (db *MemDB) SetNoLockSync(key []byte, value []byte) { 77 key = nonNilBytes(key) 78 value = nonNilBytes(value) 79 80 db.db[string(key)] = value 81 } 82 83 // Implements DB. 84 func (db *MemDB) Delete(key []byte) { 85 db.mtx.Lock() 86 defer db.mtx.Unlock() 87 88 db.DeleteNoLock(key) 89 } 90 91 // Implements DB. 92 func (db *MemDB) DeleteSync(key []byte) { 93 db.mtx.Lock() 94 defer db.mtx.Unlock() 95 96 db.DeleteNoLock(key) 97 } 98 99 // Implements atomicSetDeleter. 100 func (db *MemDB) DeleteNoLock(key []byte) { 101 db.DeleteNoLockSync(key) 102 } 103 104 // Implements atomicSetDeleter. 105 func (db *MemDB) DeleteNoLockSync(key []byte) { 106 key = nonNilBytes(key) 107 108 delete(db.db, string(key)) 109 } 110 111 // Implements DB. 112 func (db *MemDB) Close() { 113 // Close is a noop since for an in-memory 114 // database, we don't have a destination 115 // to flush contents to nor do we want 116 // any data loss on invoking Close() 117 // See the discussion in https://github.com/tendermint/tmlibs/pull/56 118 } 119 120 // Implements DB. 121 func (db *MemDB) Print() { 122 db.mtx.Lock() 123 defer db.mtx.Unlock() 124 125 for key, value := range db.db { 126 fmt.Printf("[%X]:\t[%X]\n", []byte(key), value) 127 } 128 } 129 130 // Implements DB. 131 func (db *MemDB) Stats() map[string]string { 132 db.mtx.Lock() 133 defer db.mtx.Unlock() 134 135 stats := make(map[string]string) 136 stats["database.type"] = "memDB" 137 stats["database.size"] = fmt.Sprintf("%d", len(db.db)) 138 return stats 139 } 140 141 // Implements DB. 142 func (db *MemDB) NewBatch() Batch { 143 db.mtx.Lock() 144 defer db.mtx.Unlock() 145 146 return &memBatch{db, nil} 147 } 148 149 //---------------------------------------- 150 // Iterator 151 152 // Implements DB. 153 func (db *MemDB) Iterator(start, end []byte) Iterator { 154 db.mtx.Lock() 155 defer db.mtx.Unlock() 156 157 keys := db.getSortedKeys(start, end, false) 158 return newMemDBIterator(db, keys, start, end) 159 } 160 161 // Implements DB. 162 func (db *MemDB) ReverseIterator(start, end []byte) Iterator { 163 db.mtx.Lock() 164 defer db.mtx.Unlock() 165 166 keys := db.getSortedKeys(start, end, true) 167 return newMemDBIterator(db, keys, start, end) 168 } 169 170 // We need a copy of all of the keys. 171 // Not the best, but probably not a bottleneck depending. 172 type memDBIterator struct { 173 db DB 174 cur int 175 keys []string 176 start []byte 177 end []byte 178 } 179 180 var _ Iterator = (*memDBIterator)(nil) 181 182 // Keys is expected to be in reverse order for reverse iterators. 183 func newMemDBIterator(db DB, keys []string, start, end []byte) *memDBIterator { 184 return &memDBIterator{ 185 db: db, 186 cur: 0, 187 keys: keys, 188 start: start, 189 end: end, 190 } 191 } 192 193 // Implements Iterator. 194 func (itr *memDBIterator) Domain() ([]byte, []byte) { 195 return itr.start, itr.end 196 } 197 198 // Implements Iterator. 199 func (itr *memDBIterator) Valid() bool { 200 return 0 <= itr.cur && itr.cur < len(itr.keys) 201 } 202 203 // Implements Iterator. 204 func (itr *memDBIterator) Next() { 205 itr.assertIsValid() 206 itr.cur++ 207 } 208 209 // Implements Iterator. 210 func (itr *memDBIterator) Key() []byte { 211 itr.assertIsValid() 212 return []byte(itr.keys[itr.cur]) 213 } 214 215 // Implements Iterator. 216 func (itr *memDBIterator) Value() []byte { 217 itr.assertIsValid() 218 key := []byte(itr.keys[itr.cur]) 219 return itr.db.Get(key) 220 } 221 222 // Implements Iterator. 223 func (itr *memDBIterator) Close() { 224 itr.keys = nil 225 itr.db = nil 226 } 227 228 func (itr *memDBIterator) assertIsValid() { 229 if !itr.Valid() { 230 panic("memDBIterator is invalid") 231 } 232 } 233 234 //---------------------------------------- 235 // Misc. 236 237 func (db *MemDB) getSortedKeys(start, end []byte, reverse bool) []string { 238 keys := []string{} 239 for key := range db.db { 240 inDomain := IsKeyInDomain([]byte(key), start, end, reverse) 241 if inDomain { 242 keys = append(keys, key) 243 } 244 } 245 sort.Strings(keys) 246 if reverse { 247 nkeys := len(keys) 248 for i := 0; i < nkeys/2; i++ { 249 temp := keys[i] 250 keys[i] = keys[nkeys-i-1] 251 keys[nkeys-i-1] = temp 252 } 253 } 254 return keys 255 }