github.com/ethereum/go-ethereum@v1.16.1/ethdb/memorydb/memorydb.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package memorydb implements the key-value database layer based on memory maps. 18 package memorydb 19 20 import ( 21 "bytes" 22 "errors" 23 "fmt" 24 "sort" 25 "strings" 26 "sync" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/ethdb" 30 ) 31 32 var ( 33 // errMemorydbClosed is returned if a memory database was already closed at the 34 // invocation of a data access operation. 35 errMemorydbClosed = errors.New("database closed") 36 37 // errMemorydbNotFound is returned if a key is requested that is not found in 38 // the provided memory database. 39 errMemorydbNotFound = errors.New("not found") 40 ) 41 42 // Database is an ephemeral key-value store. Apart from basic data storage 43 // functionality it also supports batch writes and iterating over the keyspace in 44 // binary-alphabetical order. 45 type Database struct { 46 db map[string][]byte 47 lock sync.RWMutex 48 } 49 50 // New returns a wrapped map with all the required database interface methods 51 // implemented. 52 func New() *Database { 53 return &Database{ 54 db: make(map[string][]byte), 55 } 56 } 57 58 // NewWithCap returns a wrapped map pre-allocated to the provided capacity with 59 // all the required database interface methods implemented. 60 func NewWithCap(size int) *Database { 61 return &Database{ 62 db: make(map[string][]byte, size), 63 } 64 } 65 66 // Close deallocates the internal map and ensures any consecutive data access op 67 // fails with an error. 68 func (db *Database) Close() error { 69 db.lock.Lock() 70 defer db.lock.Unlock() 71 72 db.db = nil 73 return nil 74 } 75 76 // Has retrieves if a key is present in the key-value store. 77 func (db *Database) Has(key []byte) (bool, error) { 78 db.lock.RLock() 79 defer db.lock.RUnlock() 80 81 if db.db == nil { 82 return false, errMemorydbClosed 83 } 84 _, ok := db.db[string(key)] 85 return ok, nil 86 } 87 88 // Get retrieves the given key if it's present in the key-value store. 89 func (db *Database) Get(key []byte) ([]byte, error) { 90 db.lock.RLock() 91 defer db.lock.RUnlock() 92 93 if db.db == nil { 94 return nil, errMemorydbClosed 95 } 96 if entry, ok := db.db[string(key)]; ok { 97 return common.CopyBytes(entry), nil 98 } 99 return nil, errMemorydbNotFound 100 } 101 102 // Put inserts the given value into the key-value store. 103 func (db *Database) Put(key []byte, value []byte) error { 104 db.lock.Lock() 105 defer db.lock.Unlock() 106 107 if db.db == nil { 108 return errMemorydbClosed 109 } 110 db.db[string(key)] = common.CopyBytes(value) 111 return nil 112 } 113 114 // Delete removes the key from the key-value store. 115 func (db *Database) Delete(key []byte) error { 116 db.lock.Lock() 117 defer db.lock.Unlock() 118 119 if db.db == nil { 120 return errMemorydbClosed 121 } 122 delete(db.db, string(key)) 123 return nil 124 } 125 126 // DeleteRange deletes all of the keys (and values) in the range [start,end) 127 // (inclusive on start, exclusive on end). If the start is nil, it represents 128 // the key before all keys; if the end is nil, it represents the key after 129 // all keys. 130 func (db *Database) DeleteRange(start, end []byte) error { 131 db.lock.Lock() 132 defer db.lock.Unlock() 133 134 if db.db == nil { 135 return errMemorydbClosed 136 } 137 for key := range db.db { 138 if start != nil && key < string(start) { 139 continue 140 } 141 if end != nil && key >= string(end) { 142 continue 143 } 144 delete(db.db, key) 145 } 146 return nil 147 } 148 149 // NewBatch creates a write-only key-value store that buffers changes to its host 150 // database until a final write is called. 151 func (db *Database) NewBatch() ethdb.Batch { 152 return &batch{ 153 db: db, 154 } 155 } 156 157 // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. 158 func (db *Database) NewBatchWithSize(size int) ethdb.Batch { 159 return &batch{ 160 db: db, 161 } 162 } 163 164 // NewIterator creates a binary-alphabetical iterator over a subset 165 // of database content with a particular key prefix, starting at a particular 166 // initial key (or after, if it does not exist). 167 func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator { 168 db.lock.RLock() 169 defer db.lock.RUnlock() 170 171 var ( 172 pr = string(prefix) 173 st = string(append(prefix, start...)) 174 keys = make([]string, 0, len(db.db)) 175 values = make([][]byte, 0, len(db.db)) 176 ) 177 // Collect the keys from the memory database corresponding to the given prefix 178 // and start 179 for key := range db.db { 180 if !strings.HasPrefix(key, pr) { 181 continue 182 } 183 if key >= st { 184 keys = append(keys, key) 185 } 186 } 187 // Sort the items and retrieve the associated values 188 sort.Strings(keys) 189 for _, key := range keys { 190 values = append(values, db.db[key]) 191 } 192 return &iterator{ 193 index: -1, 194 keys: keys, 195 values: values, 196 } 197 } 198 199 // Stat returns the statistic data of the database. 200 func (db *Database) Stat() (string, error) { 201 return "", nil 202 } 203 204 // Compact is not supported on a memory database, but there's no need either as 205 // a memory database doesn't waste space anyway. 206 func (db *Database) Compact(start []byte, limit []byte) error { 207 return nil 208 } 209 210 // SyncKeyValue ensures that all pending writes are flushed to disk, 211 // guaranteeing data durability up to the point. 212 func (db *Database) SyncKeyValue() error { 213 return nil 214 } 215 216 // Len returns the number of entries currently present in the memory database. 217 // 218 // Note, this method is only used for testing (i.e. not public in general) and 219 // does not have explicit checks for closed-ness to allow simpler testing code. 220 func (db *Database) Len() int { 221 db.lock.RLock() 222 defer db.lock.RUnlock() 223 224 return len(db.db) 225 } 226 227 // keyvalue is a key-value tuple tagged with a deletion field to allow creating 228 // memory-database write batches. 229 type keyvalue struct { 230 key string 231 value []byte 232 delete bool 233 234 rangeFrom []byte 235 rangeTo []byte 236 } 237 238 // batch is a write-only memory batch that commits changes to its host 239 // database when Write is called. A batch cannot be used concurrently. 240 type batch struct { 241 db *Database 242 writes []keyvalue 243 size int 244 } 245 246 // Put inserts the given value into the batch for later committing. 247 func (b *batch) Put(key, value []byte) error { 248 b.writes = append(b.writes, keyvalue{key: string(key), value: common.CopyBytes(value)}) 249 b.size += len(key) + len(value) 250 return nil 251 } 252 253 // Delete inserts the key removal into the batch for later committing. 254 func (b *batch) Delete(key []byte) error { 255 b.writes = append(b.writes, keyvalue{key: string(key), delete: true}) 256 b.size += len(key) 257 return nil 258 } 259 260 // DeleteRange removes all keys in the range [start, end) from the batch for later committing. 261 func (b *batch) DeleteRange(start, end []byte) error { 262 b.writes = append(b.writes, keyvalue{ 263 rangeFrom: bytes.Clone(start), 264 rangeTo: bytes.Clone(end), 265 delete: true, 266 }) 267 b.size += len(start) + len(end) 268 return nil 269 } 270 271 // ValueSize retrieves the amount of data queued up for writing. 272 func (b *batch) ValueSize() int { 273 return b.size 274 } 275 276 // Write flushes any accumulated data to the memory database. 277 func (b *batch) Write() error { 278 b.db.lock.Lock() 279 defer b.db.lock.Unlock() 280 281 if b.db.db == nil { 282 return errMemorydbClosed 283 } 284 for _, entry := range b.writes { 285 if entry.delete { 286 if entry.key != "" { 287 // Single key deletion 288 delete(b.db.db, entry.key) 289 } else { 290 // Range deletion (inclusive of start, exclusive of end) 291 for key := range b.db.db { 292 if entry.rangeFrom != nil && key < string(entry.rangeFrom) { 293 continue 294 } 295 if entry.rangeTo != nil && key >= string(entry.rangeTo) { 296 continue 297 } 298 delete(b.db.db, key) 299 } 300 } 301 continue 302 } 303 b.db.db[entry.key] = entry.value 304 } 305 return nil 306 } 307 308 // Reset resets the batch for reuse. 309 func (b *batch) Reset() { 310 b.writes = b.writes[:0] 311 b.size = 0 312 } 313 314 // Replay replays the batch contents. 315 func (b *batch) Replay(w ethdb.KeyValueWriter) error { 316 for _, entry := range b.writes { 317 if entry.delete { 318 if entry.key != "" { 319 // Single key deletion 320 if err := w.Delete([]byte(entry.key)); err != nil { 321 return err 322 } 323 } else { 324 // Range deletion 325 if rangeDeleter, ok := w.(ethdb.KeyValueRangeDeleter); ok { 326 if err := rangeDeleter.DeleteRange(entry.rangeFrom, entry.rangeTo); err != nil { 327 return err 328 } 329 } else { 330 return fmt.Errorf("ethdb.KeyValueWriter does not implement DeleteRange") 331 } 332 } 333 continue 334 } 335 if err := w.Put([]byte(entry.key), entry.value); err != nil { 336 return err 337 } 338 } 339 return nil 340 } 341 342 // iterator can walk over the (potentially partial) keyspace of a memory key 343 // value store. Internally it is a deep copy of the entire iterated state, 344 // sorted by keys. 345 type iterator struct { 346 index int 347 keys []string 348 values [][]byte 349 } 350 351 // Next moves the iterator to the next key/value pair. It returns whether the 352 // iterator is exhausted. 353 func (it *iterator) Next() bool { 354 // Short circuit if iterator is already exhausted in the forward direction. 355 if it.index >= len(it.keys) { 356 return false 357 } 358 it.index += 1 359 return it.index < len(it.keys) 360 } 361 362 // Error returns any accumulated error. Exhausting all the key/value pairs 363 // is not considered to be an error. A memory iterator cannot encounter errors. 364 func (it *iterator) Error() error { 365 return nil 366 } 367 368 // Key returns the key of the current key/value pair, or nil if done. The caller 369 // should not modify the contents of the returned slice, and its contents may 370 // change on the next call to Next. 371 func (it *iterator) Key() []byte { 372 // Short circuit if iterator is not in a valid position 373 if it.index < 0 || it.index >= len(it.keys) { 374 return nil 375 } 376 return []byte(it.keys[it.index]) 377 } 378 379 // Value returns the value of the current key/value pair, or nil if done. The 380 // caller should not modify the contents of the returned slice, and its contents 381 // may change on the next call to Next. 382 func (it *iterator) Value() []byte { 383 // Short circuit if iterator is not in a valid position 384 if it.index < 0 || it.index >= len(it.keys) { 385 return nil 386 } 387 return it.values[it.index] 388 } 389 390 // Release releases associated resources. Release should always succeed and can 391 // be called multiple times without causing error. 392 func (it *iterator) Release() { 393 it.index, it.keys, it.values = -1, nil, nil 394 }