github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/database/ffldb/dbcache.go (about)

     1  // Copyright (c) 2015-2016 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package ffldb
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/btcsuite/goleveldb/leveldb"
    15  	"github.com/btcsuite/goleveldb/leveldb/iterator"
    16  	"github.com/btcsuite/goleveldb/leveldb/util"
    17  	"github.com/BlockABC/godash/database/internal/treap"
    18  )
    19  
    20  const (
    21  	// defaultCacheSize is the default size for the database cache.
    22  	defaultCacheSize = 100 * 1024 * 1024 // 100 MB
    23  
    24  	// defaultFlushSecs is the default number of seconds to use as a
    25  	// threshold in between database cache flushes when the cache size has
    26  	// not been exceeded.
    27  	defaultFlushSecs = 300 // 5 minutes
    28  
    29  	// ldbBatchHeaderSize is the size of a leveldb batch header which
    30  	// includes the sequence header and record counter.
    31  	//
    32  	// ldbRecordIKeySize is the size of the ikey used internally by leveldb
    33  	// when appending a record to a batch.
    34  	//
    35  	// These are used to help preallocate space needed for a batch in one
    36  	// allocation instead of letting leveldb itself constantly grow it.
    37  	// This results in far less pressure on the GC and consequently helps
    38  	// prevent the GC from allocating a lot of extra unneeded space.
    39  	ldbBatchHeaderSize = 12
    40  	ldbRecordIKeySize  = 8
    41  )
    42  
    43  // ldbCacheIter wraps a treap iterator to provide the additional functionality
    44  // needed to satisfy the leveldb iterator.Iterator interface.
    45  type ldbCacheIter struct {
    46  	*treap.Iterator
    47  }
    48  
    49  // Enforce ldbCacheIterator implements the leveldb iterator.Iterator interface.
    50  var _ iterator.Iterator = (*ldbCacheIter)(nil)
    51  
    52  // Error is only provided to satisfy the iterator interface as there are no
    53  // errors for this memory-only structure.
    54  //
    55  // This is part of the leveldb iterator.Iterator interface implementation.
    56  func (iter *ldbCacheIter) Error() error {
    57  	return nil
    58  }
    59  
    60  // SetReleaser is only provided to satisfy the iterator interface as there is no
    61  // need to override it.
    62  //
    63  // This is part of the leveldb iterator.Iterator interface implementation.
    64  func (iter *ldbCacheIter) SetReleaser(releaser util.Releaser) {
    65  }
    66  
    67  // Release is only provided to satisfy the iterator interface.
    68  //
    69  // This is part of the leveldb iterator.Iterator interface implementation.
    70  func (iter *ldbCacheIter) Release() {
    71  }
    72  
    73  // newLdbCacheIter creates a new treap iterator for the given slice against the
    74  // pending keys for the passed cache snapshot and returns it wrapped in an
    75  // ldbCacheIter so it can be used as a leveldb iterator.
    76  func newLdbCacheIter(snap *dbCacheSnapshot, slice *util.Range) *ldbCacheIter {
    77  	iter := snap.pendingKeys.Iterator(slice.Start, slice.Limit)
    78  	return &ldbCacheIter{Iterator: iter}
    79  }
    80  
    81  // dbCacheIterator defines an iterator over the key/value pairs in the database
    82  // cache and underlying database.
    83  type dbCacheIterator struct {
    84  	cacheSnapshot *dbCacheSnapshot
    85  	dbIter        iterator.Iterator
    86  	cacheIter     iterator.Iterator
    87  	currentIter   iterator.Iterator
    88  	released      bool
    89  }
    90  
    91  // Enforce dbCacheIterator implements the leveldb iterator.Iterator interface.
    92  var _ iterator.Iterator = (*dbCacheIterator)(nil)
    93  
    94  // skipPendingUpdates skips any keys at the current database iterator position
    95  // that are being updated by the cache.  The forwards flag indicates the
    96  // direction the iterator is moving.
    97  func (iter *dbCacheIterator) skipPendingUpdates(forwards bool) {
    98  	for iter.dbIter.Valid() {
    99  		var skip bool
   100  		key := iter.dbIter.Key()
   101  		if iter.cacheSnapshot.pendingRemove.Has(key) {
   102  			skip = true
   103  		} else if iter.cacheSnapshot.pendingKeys.Has(key) {
   104  			skip = true
   105  		}
   106  		if !skip {
   107  			break
   108  		}
   109  
   110  		if forwards {
   111  			iter.dbIter.Next()
   112  		} else {
   113  			iter.dbIter.Prev()
   114  		}
   115  	}
   116  }
   117  
   118  // chooseIterator first skips any entries in the database iterator that are
   119  // being updated by the cache and sets the current iterator to the appropriate
   120  // iterator depending on their validity and the order they compare in while taking
   121  // into account the direction flag.  When the iterator is being moved forwards
   122  // and both iterators are valid, the iterator with the smaller key is chosen and
   123  // vice versa when the iterator is being moved backwards.
   124  func (iter *dbCacheIterator) chooseIterator(forwards bool) bool {
   125  	// Skip any keys at the current database iterator position that are
   126  	// being updated by the cache.
   127  	iter.skipPendingUpdates(forwards)
   128  
   129  	// When both iterators are exhausted, the iterator is exhausted too.
   130  	if !iter.dbIter.Valid() && !iter.cacheIter.Valid() {
   131  		iter.currentIter = nil
   132  		return false
   133  	}
   134  
   135  	// Choose the database iterator when the cache iterator is exhausted.
   136  	if !iter.cacheIter.Valid() {
   137  		iter.currentIter = iter.dbIter
   138  		return true
   139  	}
   140  
   141  	// Choose the cache iterator when the database iterator is exhausted.
   142  	if !iter.dbIter.Valid() {
   143  		iter.currentIter = iter.cacheIter
   144  		return true
   145  	}
   146  
   147  	// Both iterators are valid, so choose the iterator with either the
   148  	// smaller or larger key depending on the forwards flag.
   149  	compare := bytes.Compare(iter.dbIter.Key(), iter.cacheIter.Key())
   150  	if (forwards && compare > 0) || (!forwards && compare < 0) {
   151  		iter.currentIter = iter.cacheIter
   152  	} else {
   153  		iter.currentIter = iter.dbIter
   154  	}
   155  	return true
   156  }
   157  
   158  // First positions the iterator at the first key/value pair and returns whether
   159  // or not the pair exists.
   160  //
   161  // This is part of the leveldb iterator.Iterator interface implementation.
   162  func (iter *dbCacheIterator) First() bool {
   163  	// Seek to the first key in both the database and cache iterators and
   164  	// choose the iterator that is both valid and has the smaller key.
   165  	iter.dbIter.First()
   166  	iter.cacheIter.First()
   167  	return iter.chooseIterator(true)
   168  }
   169  
   170  // Last positions the iterator at the last key/value pair and returns whether or
   171  // not the pair exists.
   172  //
   173  // This is part of the leveldb iterator.Iterator interface implementation.
   174  func (iter *dbCacheIterator) Last() bool {
   175  	// Seek to the last key in both the database and cache iterators and
   176  	// choose the iterator that is both valid and has the larger key.
   177  	iter.dbIter.Last()
   178  	iter.cacheIter.Last()
   179  	return iter.chooseIterator(false)
   180  }
   181  
   182  // Next moves the iterator one key/value pair forward and returns whether or not
   183  // the pair exists.
   184  //
   185  // This is part of the leveldb iterator.Iterator interface implementation.
   186  func (iter *dbCacheIterator) Next() bool {
   187  	// Nothing to return if cursor is exhausted.
   188  	if iter.currentIter == nil {
   189  		return false
   190  	}
   191  
   192  	// Move the current iterator to the next entry and choose the iterator
   193  	// that is both valid and has the smaller key.
   194  	iter.currentIter.Next()
   195  	return iter.chooseIterator(true)
   196  }
   197  
   198  // Prev moves the iterator one key/value pair backward and returns whether or
   199  // not the pair exists.
   200  //
   201  // This is part of the leveldb iterator.Iterator interface implementation.
   202  func (iter *dbCacheIterator) Prev() bool {
   203  	// Nothing to return if cursor is exhausted.
   204  	if iter.currentIter == nil {
   205  		return false
   206  	}
   207  
   208  	// Move the current iterator to the previous entry and choose the
   209  	// iterator that is both valid and has the larger key.
   210  	iter.currentIter.Prev()
   211  	return iter.chooseIterator(false)
   212  }
   213  
   214  // Seek positions the iterator at the first key/value pair that is greater than
   215  // or equal to the passed seek key.  Returns false if no suitable key was found.
   216  //
   217  // This is part of the leveldb iterator.Iterator interface implementation.
   218  func (iter *dbCacheIterator) Seek(key []byte) bool {
   219  	// Seek to the provided key in both the database and cache iterators
   220  	// then choose the iterator that is both valid and has the larger key.
   221  	iter.dbIter.Seek(key)
   222  	iter.cacheIter.Seek(key)
   223  	return iter.chooseIterator(true)
   224  }
   225  
   226  // Valid indicates whether the iterator is positioned at a valid key/value pair.
   227  // It will be considered invalid when the iterator is newly created or exhausted.
   228  //
   229  // This is part of the leveldb iterator.Iterator interface implementation.
   230  func (iter *dbCacheIterator) Valid() bool {
   231  	return iter.currentIter != nil
   232  }
   233  
   234  // Key returns the current key the iterator is pointing to.
   235  //
   236  // This is part of the leveldb iterator.Iterator interface implementation.
   237  func (iter *dbCacheIterator) Key() []byte {
   238  	// Nothing to return if iterator is exhausted.
   239  	if iter.currentIter == nil {
   240  		return nil
   241  	}
   242  
   243  	return iter.currentIter.Key()
   244  }
   245  
   246  // Value returns the current value the iterator is pointing to.
   247  //
   248  // This is part of the leveldb iterator.Iterator interface implementation.
   249  func (iter *dbCacheIterator) Value() []byte {
   250  	// Nothing to return if iterator is exhausted.
   251  	if iter.currentIter == nil {
   252  		return nil
   253  	}
   254  
   255  	return iter.currentIter.Value()
   256  }
   257  
   258  // SetReleaser is only provided to satisfy the iterator interface as there is no
   259  // need to override it.
   260  //
   261  // This is part of the leveldb iterator.Iterator interface implementation.
   262  func (iter *dbCacheIterator) SetReleaser(releaser util.Releaser) {
   263  }
   264  
   265  // Release releases the iterator by removing the underlying treap iterator from
   266  // the list of active iterators against the pending keys treap.
   267  //
   268  // This is part of the leveldb iterator.Iterator interface implementation.
   269  func (iter *dbCacheIterator) Release() {
   270  	if !iter.released {
   271  		iter.dbIter.Release()
   272  		iter.cacheIter.Release()
   273  		iter.currentIter = nil
   274  		iter.released = true
   275  	}
   276  }
   277  
   278  // Error is only provided to satisfy the iterator interface as there are no
   279  // errors for this memory-only structure.
   280  //
   281  // This is part of the leveldb iterator.Iterator interface implementation.
   282  func (iter *dbCacheIterator) Error() error {
   283  	return nil
   284  }
   285  
   286  // dbCacheSnapshot defines a snapshot of the database cache and underlying
   287  // database at a particular point in time.
   288  type dbCacheSnapshot struct {
   289  	dbSnapshot    *leveldb.Snapshot
   290  	pendingKeys   *treap.Immutable
   291  	pendingRemove *treap.Immutable
   292  }
   293  
   294  // Has returns whether or not the passed key exists.
   295  func (snap *dbCacheSnapshot) Has(key []byte) bool {
   296  	// Check the cached entries first.
   297  	if snap.pendingRemove.Has(key) {
   298  		return false
   299  	}
   300  	if snap.pendingKeys.Has(key) {
   301  		return true
   302  	}
   303  
   304  	// Consult the database.
   305  	hasKey, _ := snap.dbSnapshot.Has(key, nil)
   306  	return hasKey
   307  }
   308  
   309  // Get returns the value for the passed key.  The function will return nil when
   310  // the key does not exist.
   311  func (snap *dbCacheSnapshot) Get(key []byte) []byte {
   312  	// Check the cached entries first.
   313  	if snap.pendingRemove.Has(key) {
   314  		return nil
   315  	}
   316  	if value := snap.pendingKeys.Get(key); value != nil {
   317  		return value
   318  	}
   319  
   320  	// Consult the database.
   321  	value, err := snap.dbSnapshot.Get(key, nil)
   322  	if err != nil {
   323  		return nil
   324  	}
   325  	return value
   326  }
   327  
   328  // Release releases the snapshot.
   329  func (snap *dbCacheSnapshot) Release() {
   330  	snap.dbSnapshot.Release()
   331  	snap.pendingKeys = nil
   332  	snap.pendingRemove = nil
   333  }
   334  
   335  // NewIterator returns a new iterator for the snapshot.  The newly returned
   336  // iterator is not pointing to a valid item until a call to one of the methods
   337  // to position it is made.
   338  //
   339  // The slice parameter allows the iterator to be limited to a range of keys.
   340  // The start key is inclusive and the limit key is exclusive.  Either or both
   341  // can be nil if the functionality is not desired.
   342  func (snap *dbCacheSnapshot) NewIterator(slice *util.Range) *dbCacheIterator {
   343  	return &dbCacheIterator{
   344  		dbIter:        snap.dbSnapshot.NewIterator(slice, nil),
   345  		cacheIter:     newLdbCacheIter(snap, slice),
   346  		cacheSnapshot: snap,
   347  	}
   348  }
   349  
   350  // dbCache provides a database cache layer backed by an underlying database.  It
   351  // allows a maximum cache size and flush interval to be specified such that the
   352  // cache is flushed to the database when the cache size exceeds the maximum
   353  // configured value or it has been longer than the configured interval since the
   354  // last flush.  This effectively provides transaction batching so that callers
   355  // can commit transactions at will without incurring large performance hits due
   356  // to frequent disk syncs.
   357  type dbCache struct {
   358  	// ldb is the underlying leveldb DB for metadata.
   359  	ldb *leveldb.DB
   360  
   361  	// store is used to sync blocks to flat files.
   362  	store *blockStore
   363  
   364  	// The following fields are related to flushing the cache to persistent
   365  	// storage.  Note that all flushing is performed in an opportunistic
   366  	// fashion.  This means that it is only flushed during a transaction or
   367  	// when the database cache is closed.
   368  	//
   369  	// maxSize is the maximum size threshold the cache can grow to before
   370  	// it is flushed.
   371  	//
   372  	// flushInterval is the threshold interval of time that is allowed to
   373  	// pass before the cache is flushed.
   374  	//
   375  	// lastFlush is the time the cache was last flushed.  It is used in
   376  	// conjunction with the current time and the flush interval.
   377  	//
   378  	// NOTE: These flush related fields are protected by the database write
   379  	// lock.
   380  	maxSize       uint64
   381  	flushInterval time.Duration
   382  	lastFlush     time.Time
   383  
   384  	// The following fields hold the keys that need to be stored or deleted
   385  	// from the underlying database once the cache is full, enough time has
   386  	// passed, or when the database is shutting down.  Note that these are
   387  	// stored using immutable treaps to support O(1) MVCC snapshots against
   388  	// the cached data.  The cacheLock is used to protect concurrent access
   389  	// for cache updates and snapshots.
   390  	cacheLock    sync.RWMutex
   391  	cachedKeys   *treap.Immutable
   392  	cachedRemove *treap.Immutable
   393  }
   394  
   395  // Snapshot returns a snapshot of the database cache and underlying database at
   396  // a particular point in time.
   397  //
   398  // The snapshot must be released after use by calling Release.
   399  func (c *dbCache) Snapshot() (*dbCacheSnapshot, error) {
   400  	dbSnapshot, err := c.ldb.GetSnapshot()
   401  	if err != nil {
   402  		str := "failed to open transaction"
   403  		return nil, convertErr(str, err)
   404  	}
   405  
   406  	// Since the cached keys to be added and removed use an immutable treap,
   407  	// a snapshot is simply obtaining the root of the tree under the lock
   408  	// which is used to atomically swap the root.
   409  	c.cacheLock.RLock()
   410  	cacheSnapshot := &dbCacheSnapshot{
   411  		dbSnapshot:    dbSnapshot,
   412  		pendingKeys:   c.cachedKeys,
   413  		pendingRemove: c.cachedRemove,
   414  	}
   415  	c.cacheLock.RUnlock()
   416  	return cacheSnapshot, nil
   417  }
   418  
   419  // updateDB invokes the passed function in the context of a managed leveldb
   420  // transaction.  Any errors returned from the user-supplied function will cause
   421  // the transaction to be rolled back and are returned from this function.
   422  // Otherwise, the transaction is committed when the user-supplied function
   423  // returns a nil error.
   424  func (c *dbCache) updateDB(fn func(ldbTx *leveldb.Transaction) error) error {
   425  	// Start a leveldb transaction.
   426  	ldbTx, err := c.ldb.OpenTransaction()
   427  	if err != nil {
   428  		return convertErr("failed to open ldb transaction", err)
   429  	}
   430  
   431  	if err := fn(ldbTx); err != nil {
   432  		ldbTx.Discard()
   433  		return err
   434  	}
   435  
   436  	// Commit the leveldb transaction and convert any errors as needed.
   437  	if err := ldbTx.Commit(); err != nil {
   438  		return convertErr("failed to commit leveldb transaction", err)
   439  	}
   440  	return nil
   441  }
   442  
   443  // TreapForEacher is an interface which allows iteration of a treap in ascending
   444  // order using a user-supplied callback for each key/value pair.  It mainly
   445  // exists so both mutable and immutable treaps can be atomically committed to
   446  // the database with the same function.
   447  type TreapForEacher interface {
   448  	ForEach(func(k, v []byte) bool)
   449  }
   450  
   451  // commitTreaps atomically commits all of the passed pending add/update/remove
   452  // updates to the underlying database.
   453  func (c *dbCache) commitTreaps(pendingKeys, pendingRemove TreapForEacher) error {
   454  	// Perform all leveldb updates using an atomic transaction.
   455  	return c.updateDB(func(ldbTx *leveldb.Transaction) error {
   456  		var innerErr error
   457  		pendingKeys.ForEach(func(k, v []byte) bool {
   458  			if dbErr := ldbTx.Put(k, v, nil); dbErr != nil {
   459  				str := fmt.Sprintf("failed to put key %q to "+
   460  					"ldb transaction", k)
   461  				innerErr = convertErr(str, dbErr)
   462  				return false
   463  			}
   464  			return true
   465  		})
   466  		if innerErr != nil {
   467  			return innerErr
   468  		}
   469  
   470  		pendingRemove.ForEach(func(k, v []byte) bool {
   471  			if dbErr := ldbTx.Delete(k, nil); dbErr != nil {
   472  				str := fmt.Sprintf("failed to delete "+
   473  					"key %q from ldb transaction",
   474  					k)
   475  				innerErr = convertErr(str, dbErr)
   476  				return false
   477  			}
   478  			return true
   479  		})
   480  		return innerErr
   481  	})
   482  }
   483  
   484  // flush flushes the database cache to persistent storage.  This involes syncing
   485  // the block store and replaying all transactions that have been applied to the
   486  // cache to the underlying database.
   487  //
   488  // This function MUST be called with the database write lock held.
   489  func (c *dbCache) flush() error {
   490  	c.lastFlush = time.Now()
   491  
   492  	// Sync the current write file associated with the block store.  This is
   493  	// necessary before writing the metadata to prevent the case where the
   494  	// metadata contains information about a block which actually hasn't
   495  	// been written yet in unexpected shutdown scenarios.
   496  	if err := c.store.syncBlocks(); err != nil {
   497  		return err
   498  	}
   499  
   500  	// Since the cached keys to be added and removed use an immutable treap,
   501  	// a snapshot is simply obtaining the root of the tree under the lock
   502  	// which is used to atomically swap the root.
   503  	c.cacheLock.RLock()
   504  	cachedKeys := c.cachedKeys
   505  	cachedRemove := c.cachedRemove
   506  	c.cacheLock.RUnlock()
   507  
   508  	// Nothing to do if there is no data to flush.
   509  	if cachedKeys.Len() == 0 && cachedRemove.Len() == 0 {
   510  		return nil
   511  	}
   512  
   513  	// Perform all leveldb updates using an atomic transaction.
   514  	if err := c.commitTreaps(cachedKeys, cachedRemove); err != nil {
   515  		return err
   516  	}
   517  
   518  	// Clear the cache since it has been flushed.
   519  	c.cacheLock.Lock()
   520  	c.cachedKeys = treap.NewImmutable()
   521  	c.cachedRemove = treap.NewImmutable()
   522  	c.cacheLock.Unlock()
   523  
   524  	return nil
   525  }
   526  
   527  // needsFlush returns whether or not the database cache needs to be flushed to
   528  // persistent storage based on its current size, whether or not adding all of
   529  // the entries in the passed database transaction would cause it to exceed the
   530  // configured limit, and how much time has elapsed since the last time the cache
   531  // was flushed.
   532  //
   533  // This function MUST be called with the database write lock held.
   534  func (c *dbCache) needsFlush(tx *transaction) bool {
   535  	// A flush is needed when more time has elapsed than the configured
   536  	// flush interval.
   537  	if time.Now().Sub(c.lastFlush) > c.flushInterval {
   538  		return true
   539  	}
   540  
   541  	// A flush is needed when the size of the database cache exceeds the
   542  	// specified max cache size.  The total calculated size is multiplied by
   543  	// 1.5 here to account for additional memory consumption that will be
   544  	// needed during the flush as well as old nodes in the cache that are
   545  	// referenced by the snapshot used by the transaction.
   546  	snap := tx.snapshot
   547  	totalSize := snap.pendingKeys.Size() + snap.pendingRemove.Size()
   548  	totalSize = uint64(float64(totalSize) * 1.5)
   549  	if totalSize > c.maxSize {
   550  		return true
   551  	}
   552  
   553  	return false
   554  }
   555  
   556  // commitTx atomically adds all of the pending keys to add and remove into the
   557  // database cache.  When adding the pending keys would cause the size of the
   558  // cache to exceed the max cache size, or the time since the last flush exceeds
   559  // the configured flush interval, the cache will be flushed to the underlying
   560  // persistent database.
   561  //
   562  // This is an atomic operation with respect to the cache in that either all of
   563  // the pending keys to add and remove in the transaction will be applied or none
   564  // of them will.
   565  //
   566  // The database cache itself might be flushed to the underlying persistent
   567  // database even if the transaction fails to apply, but it will only be the
   568  // state of the cache without the transaction applied.
   569  //
   570  // This function MUST be called during a database write transaction which in
   571  // turn implies the database write lock will be held.
   572  func (c *dbCache) commitTx(tx *transaction) error {
   573  	// Flush the cache and write the current transaction directly to the
   574  	// database if a flush is needed.
   575  	if c.needsFlush(tx) {
   576  		if err := c.flush(); err != nil {
   577  			return err
   578  		}
   579  
   580  		// Perform all leveldb updates using an atomic transaction.
   581  		err := c.commitTreaps(tx.pendingKeys, tx.pendingRemove)
   582  		if err != nil {
   583  			return err
   584  		}
   585  
   586  		// Clear the transaction entries since they have been committed.
   587  		tx.pendingKeys = nil
   588  		tx.pendingRemove = nil
   589  		return nil
   590  	}
   591  
   592  	// At this point a database flush is not needed, so atomically commit
   593  	// the transaction to the cache.
   594  
   595  	// Since the cached keys to be added and removed use an immutable treap,
   596  	// a snapshot is simply obtaining the root of the tree under the lock
   597  	// which is used to atomically swap the root.
   598  	c.cacheLock.RLock()
   599  	newCachedKeys := c.cachedKeys
   600  	newCachedRemove := c.cachedRemove
   601  	c.cacheLock.RUnlock()
   602  
   603  	// Apply every key to add in the database transaction to the cache.
   604  	tx.pendingKeys.ForEach(func(k, v []byte) bool {
   605  		newCachedRemove = newCachedRemove.Delete(k)
   606  		newCachedKeys = newCachedKeys.Put(k, v)
   607  		return true
   608  	})
   609  	tx.pendingKeys = nil
   610  
   611  	// Apply every key to remove in the database transaction to the cache.
   612  	tx.pendingRemove.ForEach(func(k, v []byte) bool {
   613  		newCachedKeys = newCachedKeys.Delete(k)
   614  		newCachedRemove = newCachedRemove.Put(k, nil)
   615  		return true
   616  	})
   617  	tx.pendingRemove = nil
   618  
   619  	// Atomically replace the immutable treaps which hold the cached keys to
   620  	// add and delete.
   621  	c.cacheLock.Lock()
   622  	c.cachedKeys = newCachedKeys
   623  	c.cachedRemove = newCachedRemove
   624  	c.cacheLock.Unlock()
   625  	return nil
   626  }
   627  
   628  // Close cleanly shuts down the database cache by syncing all data and closing
   629  // the underlying leveldb database.
   630  //
   631  // This function MUST be called with the database write lock held.
   632  func (c *dbCache) Close() error {
   633  	// Flush any outstanding cached entries to disk.
   634  	if err := c.flush(); err != nil {
   635  		// Even if there is an error while flushing, attempt to close
   636  		// the underlying database.  The error is ignored since it would
   637  		// mask the flush error.
   638  		_ = c.ldb.Close()
   639  		return err
   640  	}
   641  
   642  	// Close the underlying leveldb database.
   643  	if err := c.ldb.Close(); err != nil {
   644  		str := "failed to close underlying leveldb database"
   645  		return convertErr(str, err)
   646  	}
   647  
   648  	return nil
   649  }
   650  
   651  // newDbCache returns a new database cache instance backed by the provided
   652  // leveldb instance.  The cache will be flushed to leveldb when the max size
   653  // exceeds the provided value or it has been longer than the provided interval
   654  // since the last flush.
   655  func newDbCache(ldb *leveldb.DB, store *blockStore, maxSize uint64, flushIntervalSecs uint32) *dbCache {
   656  	return &dbCache{
   657  		ldb:           ldb,
   658  		store:         store,
   659  		maxSize:       maxSize,
   660  		flushInterval: time.Second * time.Duration(flushIntervalSecs),
   661  		lastFlush:     time.Now(),
   662  		cachedKeys:    treap.NewImmutable(),
   663  		cachedRemove:  treap.NewImmutable(),
   664  	}
   665  }