walletdb

数据库模块

  • Key/value store
  • Namespace support (说的就是NestedBucket)
  • Allows multiple packages to have their own area in the database without
    worrying about conflicts (说的就是NestedBucket)
  • Read-only and read-write transactions with both manual and managed modes
  • Nested buckets
  • Supports registration of backend databases
  • Comprehensive test coverage
    主要interface
    go type ReadTx interface type ReadWriteTx interface type ReadBucket interface type ReadWriteBucket interface type ReadCursor interface type ReadWriteCursor interface type DB interface

关于这些interface的使用

1. 入口


// DB represents an ACID database.  All database access is performed through
// read or read+write transactions.
type DB interface {
	// BeginReadTx opens a database read transaction.
	BeginReadTx() (ReadTx, error)

	// BeginReadWriteTx opens a database read+write transaction.
	BeginReadWriteTx() (ReadWriteTx, error)

	// Copy writes a copy of the database to the provided writer.  This
	// call will start a read-only transaction to perform all operations.
	Copy(w io.Writer) error

	// Close cleanly shuts down the database and syncs all data.
	Close() error
}

通过Driver的Create和Open来创建DB,然后可以通过BeginReadTx和BeginReadWriteTx来获取读写数据库的方法

2. 操作Bucket

type ReadTx interface {
	// ReadBucket opens the root bucket for read only access.  If the bucket
	// described by the key does not exist, nil is returned.
	ReadBucket(key []byte) ReadBucket

	// Rollback closes the transaction, discarding changes (if any) if the
	// database was modified by a write transaction.
	Rollback() error
}
// ReadWriteTx represents a database transaction that can be used for both reads
// and writes.  When only reads are necessary, consider using a ReadTx instead.
type ReadWriteTx interface {
	ReadTx

	// ReadWriteBucket opens the root bucket for read/write access.  If the
	// bucket described by the key does not exist, nil is returned.
	ReadWriteBucket(key []byte) ReadWriteBucket

	// CreateTopLevelBucket creates th top level bucket for a key if it
	// does not exist.  The newly-created bucket it returned.
	CreateTopLevelBucket(key []byte) (ReadWriteBucket, error)

	// DeleteTopLevelBucket deletes the top level bucket for a key.  This
	// errors if the bucket can not be found or the key keys a single value
	// instead of a bucket.
	DeleteTopLevelBucket(key []byte) error

	// Commit commits all changes that have been on the transaction's root
	// buckets and all of their sub-buckets to persistent storage.
	Commit() error

	// OnCommit takes a function closure that will be executed when the
	// transaction successfully gets committed.
	OnCommit(func())
}

通过接口可以看出ReadTx和ReadWriteTx主要是获取Bucket以及对Bucket进行管理.

3. 读写数据

// ReadBucket represents a bucket (a hierarchical structure within the database)
// that is only allowed to perform read operations.
type ReadBucket interface {
	// NestedReadBucket retrieves a nested bucket with the given key.
	// Returns nil if the bucket does not exist.
	NestedReadBucket(key []byte) ReadBucket

	// ForEach invokes the passed function with every key/value pair in
	// the bucket.  This includes nested buckets, in which case the value
	// is nil, but it does not include the key/value pairs within those
	// nested buckets.
	//
	// NOTE: The values returned by this function are only valid during a
	// transaction.  Attempting to access them after a transaction has ended
	// results in undefined behavior.  This constraint prevents additional
	// data copies and allows support for memory-mapped database
	// implementations.
	ForEach(func(k, v []byte) error) error

	// Get returns the value for the given key.  Returns nil if the key does
	// not exist in this bucket (or nested buckets).
	//
	// NOTE: The value returned by this function is only valid during a
	// transaction.  Attempting to access it after a transaction has ended
	// results in undefined behavior.  This constraint prevents additional
	// data copies and allows support for memory-mapped database
	// implementations.
	Get(key []byte) []byte
	//这个接口和forEach有啥关系,如何使用呢?
	ReadCursor() ReadCursor
}
// ReadWriteBucket represents a bucket (a hierarchical structure within the
// database) that is allowed to perform both read and write operations.
type ReadWriteBucket interface {
	ReadBucket

	// NestedReadWriteBucket retrieves a nested bucket with the given key.
	// Returns nil if the bucket does not exist.
	NestedReadWriteBucket(key []byte) ReadWriteBucket

	// CreateBucket creates and returns a new nested bucket with the given
	// key.  Returns ErrBucketExists if the bucket already exists,
	// ErrBucketNameRequired if the key is empty, or ErrIncompatibleValue
	// if the key value is otherwise invalid for the particular database
	// implementation.  Other errors are possible depending on the
	// implementation.
	CreateBucket(key []byte) (ReadWriteBucket, error)

	// CreateBucketIfNotExists creates and returns a new nested bucket with
	// the given key if it does not already exist.  Returns
	// ErrBucketNameRequired if the key is empty or ErrIncompatibleValue
	// if the key value is otherwise invalid for the particular database
	// backend.  Other errors are possible depending on the implementation.
	CreateBucketIfNotExists(key []byte) (ReadWriteBucket, error)

	// DeleteNestedBucket removes a nested bucket with the given key.
	// Returns ErrTxNotWritable if attempted against a read-only transaction
	// and ErrBucketNotFound if the specified bucket does not exist.
	DeleteNestedBucket(key []byte) error

	// Put saves the specified key/value pair to the bucket.  Keys that do
	// not already exist are added and keys that already exist are
	// overwritten.  Returns ErrTxNotWritable if attempted against a
	// read-only transaction.
	Put(key, value []byte) error

	// Delete removes the specified key from the bucket.  Deleting a key
	// that does not exist does not return an error.  Returns
	// ErrTxNotWritable if attempted against a read-only transaction.
	Delete(key []byte) error

	// Cursor returns a new cursor, allowing for iteration over the bucket's
	// key/value pairs and nested buckets in forward or backward order.
	ReadWriteCursor() ReadWriteCursor

	// Tx returns the bucket's transaction.
	Tx() ReadWriteTx
}

真正的读写数据就是Get和Put两个,还有Delete会删除数据.

Tx是在Bucket层面进行管理,而ReadWriteBucket主要是对Bucket的内容管理,同时也会管理在当前Bucket中的NestedBucket. 因此Bucket和Tx是互相嵌套的.

manage和unmanage接口的区别

直接使用上述接口通过DB.BeginReadTx和BeginReadWriteTx进行数据库操作都是unmanage的,
通过walletdb.View和walletdb.Update接口操作数据库则是manage的方式

接口的实现

实现反而比较简单,基本上是BoltDB的接口的简单封装. 不过这种抽象也有好处,就是后续可以方便的替换为其他数据库来实现.