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