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