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