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  }