github.com/klaytn/klaytn@v1.12.1/storage/database/memory_database.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from ethdb/memory_database.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package database 22 23 import ( 24 "errors" 25 "sort" 26 "strings" 27 "sync" 28 29 "github.com/klaytn/klaytn/common" 30 ) 31 32 // errMemorydbClosed is returned if a memory database was already closed at the 33 // invocation of a data access operation. 34 var errMemorydbClosed = errors.New("database closed") 35 36 /* 37 * This is a test memory database. Do not use for any production it does not get persisted 38 */ 39 type MemDB struct { 40 db map[string][]byte 41 lock sync.RWMutex 42 } 43 44 func NewMemDB() *MemDB { 45 return &MemDB{ 46 db: make(map[string][]byte), 47 } 48 } 49 50 func NewMemDBWithCap(size int) *MemDB { 51 return &MemDB{ 52 db: make(map[string][]byte, size), 53 } 54 } 55 56 // Close deallocates the internal map and ensures any consecutive data access op 57 // fails with an error. 58 func (db *MemDB) Close() { 59 db.lock.Lock() 60 defer db.lock.Unlock() 61 62 db.db = nil 63 } 64 65 func (db *MemDB) Type() DBType { 66 return MemoryDB 67 } 68 69 // Has retrieves if a key is present in the key-value store. 70 func (db *MemDB) Has(key []byte) (bool, error) { 71 db.lock.RLock() 72 defer db.lock.RUnlock() 73 74 if db.db == nil { 75 return false, errMemorydbClosed 76 } 77 _, ok := db.db[string(key)] 78 return ok, nil 79 } 80 81 // Get retrieves the given key if it's present in the key-value store. 82 func (db *MemDB) Get(key []byte) ([]byte, error) { 83 db.lock.RLock() 84 defer db.lock.RUnlock() 85 86 if db.db == nil { 87 return nil, errMemorydbClosed 88 } 89 if entry, ok := db.db[string(key)]; ok { 90 if entry == nil { 91 entry = []byte{} 92 } 93 return common.CopyBytes(entry), nil 94 } 95 return nil, dataNotFoundErr 96 } 97 98 // Put inserts the given value into the key-value store. 99 func (db *MemDB) Put(key []byte, value []byte) error { 100 db.lock.Lock() 101 defer db.lock.Unlock() 102 103 if db.db == nil { 104 return errMemorydbClosed 105 } 106 db.db[string(key)] = common.CopyBytes(value) 107 return nil 108 } 109 110 // Delete removes the key from the key-value store. 111 func (db *MemDB) Delete(key []byte) error { 112 db.lock.Lock() 113 defer db.lock.Unlock() 114 115 if db.db == nil { 116 return errMemorydbClosed 117 } 118 delete(db.db, string(key)) 119 return nil 120 } 121 122 func (db *MemDB) Keys() [][]byte { 123 db.lock.RLock() 124 defer db.lock.RUnlock() 125 126 keys := [][]byte{} 127 for key := range db.db { 128 keys = append(keys, []byte(key)) 129 } 130 return keys 131 } 132 133 func (db *MemDB) NewBatch() Batch { 134 return &memBatch{db: db} 135 } 136 137 // NewIterator creates a binary-alphabetical iterator over a subset 138 // of database content with a particular key prefix, starting at a particular 139 // initial key (or after, if it does not exist). 140 func (db *MemDB) NewIterator(prefix []byte, start []byte) Iterator { 141 db.lock.RLock() 142 defer db.lock.RUnlock() 143 144 var ( 145 pr = string(prefix) 146 st = string(append(prefix, start...)) 147 keys = make([]string, 0, len(db.db)) 148 values = make([][]byte, 0, len(db.db)) 149 ) 150 // Collect the keys from the memory database corresponding to the given prefix 151 // and start 152 for key := range db.db { 153 if !strings.HasPrefix(key, pr) { 154 continue 155 } 156 if key >= st { 157 keys = append(keys, key) 158 } 159 } 160 // Sort the items and retrieve the associated values 161 sort.Strings(keys) 162 for _, key := range keys { 163 values = append(values, db.db[key]) 164 } 165 return &iterator{ 166 keys: keys, 167 values: values, 168 } 169 } 170 171 // Stat returns a particular internal stat of the database. 172 func (db *MemDB) Stat(property string) (string, error) { 173 return "", errors.New("unknown property") 174 } 175 176 // Compact is not supported on a memory database, but there's no need either as 177 // a memory database doesn't waste space anyway. 178 func (db *MemDB) Compact(start []byte, limit []byte) error { 179 return nil 180 } 181 182 // Len returns the number of entries currently present in the memory database. 183 // 184 // Note, this method is only used for testing (i.e. not public in general) and 185 // does not have explicit checks for closed-ness to allow simpler testing code. 186 func (db *MemDB) Len() int { 187 db.lock.RLock() 188 defer db.lock.RUnlock() 189 190 return len(db.db) 191 } 192 193 func (db *MemDB) Meter(prefix string) { 194 logger.Warn("MemDB does not support metrics!") 195 } 196 197 func (db *MemDB) TryCatchUpWithPrimary() error { 198 return nil 199 } 200 201 // keyvalue is a key-value tuple tagged with a deletion field to allow creating 202 // memory-database write batches. 203 type keyvalue struct { 204 key []byte 205 value []byte 206 delete bool 207 } 208 209 // memBatch is a write-only memory batch that commits changes to its host 210 // database when Write is called. A batch cannot be used concurrently. 211 type memBatch struct { 212 db *MemDB 213 writes []keyvalue 214 size int 215 } 216 217 // Put inserts the given value into the batch for later committing. 218 func (b *memBatch) Put(key, value []byte) error { 219 b.writes = append(b.writes, keyvalue{common.CopyBytes(key), common.CopyBytes(value), false}) 220 b.size += len(value) 221 return nil 222 } 223 224 // Delete inserts the a key removal into the batch for later committing. 225 func (b *memBatch) Delete(key []byte) error { 226 b.writes = append(b.writes, keyvalue{common.CopyBytes(key), nil, true}) 227 b.size += 1 228 return nil 229 } 230 231 // ValueSize retrieves the amount of data queued up for writing. 232 func (b *memBatch) ValueSize() int { 233 return b.size 234 } 235 236 // Write flushes any accumulated data to the memory database. 237 func (b *memBatch) Write() error { 238 b.db.lock.Lock() 239 defer b.db.lock.Unlock() 240 241 for _, keyvalue := range b.writes { 242 if keyvalue.delete { 243 delete(b.db.db, string(keyvalue.key)) 244 continue 245 } 246 b.db.db[string(keyvalue.key)] = keyvalue.value 247 } 248 return nil 249 } 250 251 // Reset resets the batch for reuse. 252 func (b *memBatch) Reset() { 253 b.writes = b.writes[:0] 254 b.size = 0 255 } 256 257 func (b *memBatch) Release() { 258 // nothing to do with memBatch 259 } 260 261 // Replay replays the batch contents. 262 func (b *memBatch) Replay(w KeyValueWriter) error { 263 for _, keyvalue := range b.writes { 264 if keyvalue.delete { 265 if err := w.Delete(keyvalue.key); err != nil { 266 return err 267 } 268 continue 269 } 270 if err := w.Put(keyvalue.key, keyvalue.value); err != nil { 271 return err 272 } 273 } 274 return nil 275 } 276 277 // iterator can walk over the (potentially partial) keyspace of a memory key 278 // value store. Internally it is a deep copy of the entire iterated state, 279 // sorted by keys. 280 type iterator struct { 281 inited bool 282 keys []string 283 values [][]byte 284 } 285 286 // Next moves the iterator to the next key/value pair. It returns whether the 287 // iterator is exhausted. 288 func (it *iterator) Next() bool { 289 // If the iterator was not yet initialized, do it now 290 if !it.inited { 291 it.inited = true 292 return len(it.keys) > 0 293 } 294 // Iterator already initialize, advance it 295 if len(it.keys) > 0 { 296 it.keys = it.keys[1:] 297 it.values = it.values[1:] 298 } 299 return len(it.keys) > 0 300 } 301 302 // Error returns any accumulated error. Exhausting all the key/value pairs 303 // is not considered to be an error. A memory iterator cannot encounter errors. 304 func (it *iterator) Error() error { 305 return nil 306 } 307 308 // Key returns the key of the current key/value pair, or nil if done. The caller 309 // should not modify the contents of the returned slice, and its contents may 310 // change on the next call to Next. 311 func (it *iterator) Key() []byte { 312 if !it.inited { 313 return nil 314 } 315 if len(it.keys) > 0 { 316 return []byte(it.keys[0]) 317 } 318 return nil 319 } 320 321 // Value returns the value of the current key/value pair, or nil if done. The 322 // caller should not modify the contents of the returned slice, and its contents 323 // may change on the next call to Next. 324 func (it *iterator) Value() []byte { 325 if !it.inited { 326 return nil 327 } 328 if len(it.values) > 0 { 329 return it.values[0] 330 } 331 return nil 332 } 333 334 // Release releases associated resources. Release should always succeed and can 335 // be called multiple times without causing error. 336 func (it *iterator) Release() { 337 it.keys, it.values = nil, nil 338 }