github.com/decred/dcrlnd@v0.7.6/kvdb/interface.go (about)

     1  package kvdb
     2  
     3  import (
     4  	"github.com/btcsuite/btcwallet/walletdb"
     5  )
     6  
     7  // Update opens a database read/write transaction and executes the function f
     8  // with the transaction passed as a parameter. After f exits, if f did not
     9  // error, the transaction is committed. Otherwise, if f did error, the
    10  // transaction is rolled back. If the rollback fails, the original error
    11  // returned by f is still returned. If the commit fails, the commit error is
    12  // returned. As callers may expect retries of the f closure (depending on the
    13  // database backend used), the reset function will be called before each retry
    14  // respectively.
    15  func Update(db Backend, f func(tx RwTx) error, reset func()) error {
    16  	return db.Update(f, reset)
    17  }
    18  
    19  // View opens a database read transaction and executes the function f with the
    20  // transaction passed as a parameter. After f exits, the transaction is rolled
    21  // back. If f errors, its error is returned, not a rollback error (if any
    22  // occur). The passed reset function is called before the start of the
    23  // transaction and can be used to reset intermediate state. As callers may
    24  // expect retries of the f closure (depending on the database backend used), the
    25  // reset function will be called before each retry respectively.
    26  func View(db Backend, f func(tx RTx) error, reset func()) error {
    27  	return db.View(f, reset)
    28  }
    29  
    30  // Batch is identical to the Update call, but it attempts to combine several
    31  // individual Update transactions into a single write database transaction on
    32  // an optimistic basis. This only has benefits if multiple goroutines call
    33  // Batch. For etcd Batch simply does an Update since combination is more complex
    34  // in that case due to STM retries.
    35  func Batch(db Backend, f func(tx RwTx) error) error {
    36  	// Fall back to the normal Update method if the backend doesn't support
    37  	// batching.
    38  	if _, ok := db.(walletdb.BatchDB); !ok {
    39  		// Since Batch calls handle external state reset, we can safely
    40  		// pass in an empty reset closure.
    41  		return db.Update(f, func() {})
    42  	}
    43  
    44  	return walletdb.Batch(db, f)
    45  }
    46  
    47  // Create initializes and opens a database for the specified type. The
    48  // arguments are specific to the database type driver. See the documentation
    49  // for the database driver for further details.
    50  //
    51  // ErrDbUnknownType will be returned if the database type is not registered.
    52  var Create = walletdb.Create
    53  
    54  // Backend represents an ACID database. All database access is performed
    55  // through read or read+write transactions.
    56  type Backend = walletdb.DB
    57  
    58  // Open opens an existing database for the specified type. The arguments are
    59  // specific to the database type driver. See the documentation for the database
    60  // driver for further details.
    61  //
    62  // ErrDbUnknownType will be returned if the database type is not registered.
    63  var Open = walletdb.Open
    64  
    65  // Driver defines a structure for backend drivers to use when they registered
    66  // themselves as a backend which implements the Backend interface.
    67  type Driver = walletdb.Driver
    68  
    69  // RBucket represents a bucket (a hierarchical structure within the
    70  // database) that is only allowed to perform read operations.
    71  type RBucket = walletdb.ReadBucket
    72  
    73  // RCursor represents a bucket cursor that can be positioned at the start or
    74  // end of the bucket's key/value pairs and iterate over pairs in the bucket.
    75  // This type is only allowed to perform database read operations.
    76  type RCursor = walletdb.ReadCursor
    77  
    78  // RTx represents a database transaction that can only be used for reads. If
    79  // a database update must occur, use a RwTx.
    80  type RTx = walletdb.ReadTx
    81  
    82  // RwBucket represents a bucket (a hierarchical structure within the database)
    83  // that is allowed to perform both read and write operations.
    84  type RwBucket = walletdb.ReadWriteBucket
    85  
    86  // RwCursor represents a bucket cursor that can be positioned at the start or
    87  // end of the bucket's key/value pairs and iterate over pairs in the bucket.
    88  // This abstraction is allowed to perform both database read and write
    89  // operations.
    90  type RwCursor = walletdb.ReadWriteCursor
    91  
    92  // RwTx represents a database transaction that can be used for both reads and
    93  // writes. When only reads are necessary, consider using a RTx instead.
    94  type RwTx = walletdb.ReadWriteTx
    95  
    96  // ExtendedRTx is an extension to walletdb.ReadTx to allow prefetching of keys.
    97  type ExtendedRTx interface {
    98  	RTx
    99  
   100  	// RootBucket returns the "root bucket" which is pseudo bucket used
   101  	// when prefetching (keys from) top level buckets.
   102  	RootBucket() RBucket
   103  }
   104  
   105  // ExtendedRBucket is an extension to walletdb.ReadBucket to allow prefetching
   106  // of all values inside buckets.
   107  type ExtendedRBucket interface {
   108  	RBucket
   109  
   110  	// Prefetch will attempt to prefetch all values under a path.
   111  	Prefetch(paths ...[]string)
   112  
   113  	// ForAll is an optimized version of ForEach.
   114  	//
   115  	// NOTE: ForAll differs from ForEach in that no additional queries can
   116  	// be executed within the callback.
   117  	ForAll(func(k, v []byte) error) error
   118  }
   119  
   120  // Prefetch will attempt to prefetch all values under a path from the passed
   121  // bucket.
   122  func Prefetch(b RBucket, paths ...[]string) {
   123  	if bucket, ok := b.(ExtendedRBucket); ok {
   124  		bucket.Prefetch(paths...)
   125  	}
   126  }
   127  
   128  // ForAll is an optimized version of ForEach with the limitation that no
   129  // additional queries can be executed within the callback.
   130  func ForAll(b RBucket, cb func(k, v []byte) error) error {
   131  	if bucket, ok := b.(ExtendedRBucket); ok {
   132  		return bucket.ForAll(cb)
   133  	}
   134  
   135  	return b.ForEach(cb)
   136  }
   137  
   138  // RootBucket is a wrapper to ExtendedRTx.RootBucket which does nothing if
   139  // the implementation doesn't have ExtendedRTx.
   140  func RootBucket(t RTx) RBucket {
   141  	if tx, ok := t.(ExtendedRTx); ok {
   142  		return tx.RootBucket()
   143  	}
   144  
   145  	return nil
   146  }
   147  
   148  var (
   149  	// ErrBucketNotFound is returned when trying to access a bucket that
   150  	// has not been created yet.
   151  	ErrBucketNotFound = walletdb.ErrBucketNotFound
   152  
   153  	// ErrBucketExists is returned when creating a bucket that already
   154  	// exists.
   155  	ErrBucketExists = walletdb.ErrBucketExists
   156  
   157  	// ErrDatabaseNotOpen is returned when a database instance is accessed
   158  	// before it is opened or after it is closed.
   159  	ErrDatabaseNotOpen = walletdb.ErrDbNotOpen
   160  )