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  }