github.com/theQRL/go-zond@v0.1.1/zonddb/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 "errors" 22 "sort" 23 "strings" 24 "sync" 25 26 "github.com/theQRL/go-zond/common" 27 "github.com/theQRL/go-zond/zonddb" 28 ) 29 30 var ( 31 // errMemorydbClosed is returned if a memory database was already closed at the 32 // invocation of a data access operation. 33 errMemorydbClosed = errors.New("database closed") 34 35 // errMemorydbNotFound is returned if a key is requested that is not found in 36 // the provided memory database. 37 errMemorydbNotFound = errors.New("not found") 38 39 // errSnapshotReleased is returned if callers want to retrieve data from a 40 // released snapshot. 41 errSnapshotReleased = errors.New("snapshot released") 42 ) 43 44 // Database is an ephemeral key-value store. Apart from basic data storage 45 // functionality it also supports batch writes and iterating over the keyspace in 46 // binary-alphabetical order. 47 type Database struct { 48 db map[string][]byte 49 lock sync.RWMutex 50 } 51 52 // New returns a wrapped map with all the required database interface methods 53 // implemented. 54 func New() *Database { 55 return &Database{ 56 db: make(map[string][]byte), 57 } 58 } 59 60 // NewWithCap returns a wrapped map pre-allocated to the provided capacity with 61 // all the required database interface methods implemented. 62 func NewWithCap(size int) *Database { 63 return &Database{ 64 db: make(map[string][]byte, size), 65 } 66 } 67 68 // Close deallocates the internal map and ensures any consecutive data access op 69 // fails with an error. 70 func (db *Database) Close() error { 71 db.lock.Lock() 72 defer db.lock.Unlock() 73 74 db.db = nil 75 return nil 76 } 77 78 // Has retrieves if a key is present in the key-value store. 79 func (db *Database) Has(key []byte) (bool, error) { 80 db.lock.RLock() 81 defer db.lock.RUnlock() 82 83 if db.db == nil { 84 return false, errMemorydbClosed 85 } 86 _, ok := db.db[string(key)] 87 return ok, nil 88 } 89 90 // Get retrieves the given key if it's present in the key-value store. 91 func (db *Database) Get(key []byte) ([]byte, error) { 92 db.lock.RLock() 93 defer db.lock.RUnlock() 94 95 if db.db == nil { 96 return nil, errMemorydbClosed 97 } 98 if entry, ok := db.db[string(key)]; ok { 99 return common.CopyBytes(entry), nil 100 } 101 return nil, errMemorydbNotFound 102 } 103 104 // Put inserts the given value into the key-value store. 105 func (db *Database) Put(key []byte, value []byte) error { 106 db.lock.Lock() 107 defer db.lock.Unlock() 108 109 if db.db == nil { 110 return errMemorydbClosed 111 } 112 db.db[string(key)] = common.CopyBytes(value) 113 return nil 114 } 115 116 // Delete removes the key from the key-value store. 117 func (db *Database) Delete(key []byte) error { 118 db.lock.Lock() 119 defer db.lock.Unlock() 120 121 if db.db == nil { 122 return errMemorydbClosed 123 } 124 delete(db.db, string(key)) 125 return nil 126 } 127 128 // NewBatch creates a write-only key-value store that buffers changes to its host 129 // database until a final write is called. 130 func (db *Database) NewBatch() zonddb.Batch { 131 return &batch{ 132 db: db, 133 } 134 } 135 136 // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. 137 func (db *Database) NewBatchWithSize(size int) zonddb.Batch { 138 return &batch{ 139 db: db, 140 } 141 } 142 143 // NewIterator creates a binary-alphabetical iterator over a subset 144 // of database content with a particular key prefix, starting at a particular 145 // initial key (or after, if it does not exist). 146 func (db *Database) NewIterator(prefix []byte, start []byte) zonddb.Iterator { 147 db.lock.RLock() 148 defer db.lock.RUnlock() 149 150 var ( 151 pr = string(prefix) 152 st = string(append(prefix, start...)) 153 keys = make([]string, 0, len(db.db)) 154 values = make([][]byte, 0, len(db.db)) 155 ) 156 // Collect the keys from the memory database corresponding to the given prefix 157 // and start 158 for key := range db.db { 159 if !strings.HasPrefix(key, pr) { 160 continue 161 } 162 if key >= st { 163 keys = append(keys, key) 164 } 165 } 166 // Sort the items and retrieve the associated values 167 sort.Strings(keys) 168 for _, key := range keys { 169 values = append(values, db.db[key]) 170 } 171 return &iterator{ 172 index: -1, 173 keys: keys, 174 values: values, 175 } 176 } 177 178 // NewSnapshot creates a database snapshot based on the current state. 179 // The created snapshot will not be affected by all following mutations 180 // happened on the database. 181 func (db *Database) NewSnapshot() (zonddb.Snapshot, error) { 182 return newSnapshot(db), nil 183 } 184 185 // Stat returns a particular internal stat of the database. 186 func (db *Database) Stat(property string) (string, error) { 187 return "", errors.New("unknown property") 188 } 189 190 // Compact is not supported on a memory database, but there's no need either as 191 // a memory database doesn't waste space anyway. 192 func (db *Database) Compact(start []byte, limit []byte) error { 193 return nil 194 } 195 196 // Len returns the number of entries currently present in the memory database. 197 // 198 // Note, this method is only used for testing (i.e. not public in general) and 199 // does not have explicit checks for closed-ness to allow simpler testing code. 200 func (db *Database) Len() int { 201 db.lock.RLock() 202 defer db.lock.RUnlock() 203 204 return len(db.db) 205 } 206 207 // keyvalue is a key-value tuple tagged with a deletion field to allow creating 208 // memory-database write batches. 209 type keyvalue struct { 210 key []byte 211 value []byte 212 delete bool 213 } 214 215 // batch is a write-only memory batch that commits changes to its host 216 // database when Write is called. A batch cannot be used concurrently. 217 type batch struct { 218 db *Database 219 writes []keyvalue 220 size int 221 } 222 223 // Put inserts the given value into the batch for later committing. 224 func (b *batch) Put(key, value []byte) error { 225 b.writes = append(b.writes, keyvalue{common.CopyBytes(key), common.CopyBytes(value), false}) 226 b.size += len(key) + len(value) 227 return nil 228 } 229 230 // Delete inserts the a key removal into the batch for later committing. 231 func (b *batch) Delete(key []byte) error { 232 b.writes = append(b.writes, keyvalue{common.CopyBytes(key), nil, true}) 233 b.size += len(key) 234 return nil 235 } 236 237 // ValueSize retrieves the amount of data queued up for writing. 238 func (b *batch) ValueSize() int { 239 return b.size 240 } 241 242 // Write flushes any accumulated data to the memory database. 243 func (b *batch) Write() error { 244 b.db.lock.Lock() 245 defer b.db.lock.Unlock() 246 247 if b.db.db == nil { 248 return errMemorydbClosed 249 } 250 for _, keyvalue := range b.writes { 251 if keyvalue.delete { 252 delete(b.db.db, string(keyvalue.key)) 253 continue 254 } 255 b.db.db[string(keyvalue.key)] = keyvalue.value 256 } 257 return nil 258 } 259 260 // Reset resets the batch for reuse. 261 func (b *batch) Reset() { 262 b.writes = b.writes[:0] 263 b.size = 0 264 } 265 266 // Replay replays the batch contents. 267 func (b *batch) Replay(w zonddb.KeyValueWriter) error { 268 for _, keyvalue := range b.writes { 269 if keyvalue.delete { 270 if err := w.Delete(keyvalue.key); err != nil { 271 return err 272 } 273 continue 274 } 275 if err := w.Put(keyvalue.key, keyvalue.value); err != nil { 276 return err 277 } 278 } 279 return nil 280 } 281 282 // iterator can walk over the (potentially partial) keyspace of a memory key 283 // value store. Internally it is a deep copy of the entire iterated state, 284 // sorted by keys. 285 type iterator struct { 286 index int 287 keys []string 288 values [][]byte 289 } 290 291 // Next moves the iterator to the next key/value pair. It returns whether the 292 // iterator is exhausted. 293 func (it *iterator) Next() bool { 294 // Short circuit if iterator is already exhausted in the forward direction. 295 if it.index >= len(it.keys) { 296 return false 297 } 298 it.index += 1 299 return it.index < len(it.keys) 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 // Short circuit if iterator is not in a valid position 313 if it.index < 0 || it.index >= len(it.keys) { 314 return nil 315 } 316 return []byte(it.keys[it.index]) 317 } 318 319 // Value returns the value of the current key/value pair, or nil if done. The 320 // caller should not modify the contents of the returned slice, and its contents 321 // may change on the next call to Next. 322 func (it *iterator) Value() []byte { 323 // Short circuit if iterator is not in a valid position 324 if it.index < 0 || it.index >= len(it.keys) { 325 return nil 326 } 327 return it.values[it.index] 328 } 329 330 // Release releases associated resources. Release should always succeed and can 331 // be called multiple times without causing error. 332 func (it *iterator) Release() { 333 it.index, it.keys, it.values = -1, nil, nil 334 } 335 336 // snapshot wraps a batch of key-value entries deep copied from the in-memory 337 // database for implementing the Snapshot interface. 338 type snapshot struct { 339 db map[string][]byte 340 lock sync.RWMutex 341 } 342 343 // newSnapshot initializes the snapshot with the given database instance. 344 func newSnapshot(db *Database) *snapshot { 345 db.lock.RLock() 346 defer db.lock.RUnlock() 347 348 copied := make(map[string][]byte, len(db.db)) 349 for key, val := range db.db { 350 copied[key] = common.CopyBytes(val) 351 } 352 return &snapshot{db: copied} 353 } 354 355 // Has retrieves if a key is present in the snapshot backing by a key-value 356 // data store. 357 func (snap *snapshot) Has(key []byte) (bool, error) { 358 snap.lock.RLock() 359 defer snap.lock.RUnlock() 360 361 if snap.db == nil { 362 return false, errSnapshotReleased 363 } 364 _, ok := snap.db[string(key)] 365 return ok, nil 366 } 367 368 // Get retrieves the given key if it's present in the snapshot backing by 369 // key-value data store. 370 func (snap *snapshot) Get(key []byte) ([]byte, error) { 371 snap.lock.RLock() 372 defer snap.lock.RUnlock() 373 374 if snap.db == nil { 375 return nil, errSnapshotReleased 376 } 377 if entry, ok := snap.db[string(key)]; ok { 378 return common.CopyBytes(entry), nil 379 } 380 return nil, errMemorydbNotFound 381 } 382 383 // Release releases associated resources. Release should always succeed and can 384 // be called multiple times without causing error. 385 func (snap *snapshot) Release() { 386 snap.lock.Lock() 387 defer snap.lock.Unlock() 388 389 snap.db = nil 390 }