btcd中database代码详解
在btcd.go文件中,函数loadBlockDB根据配置初始化了相应的数据库
func loadBlockDB() (database.DB, error) {
// The memdb backend does not have a file path associated with it, so
// handle it uniquely. We also don't want to worry about the multiple
// database type warnings when running with the memory database.
if cfg.DbType == "memdb" {
btcdLog.Infof("Creating block database in memory.")
db, err := database.Create(cfg.DbType)
if err != nil {
return nil, err
}
return db, nil
}
warnMultipleDBs()
// The database name is based on the database type.
dbPath := blockDbPath(cfg.DbType)
// The regression test is special in that it needs a clean database for
// each run, so remove it now if it already exists.
removeRegressionDB(dbPath)
btcdLog.Infof("Loading block database from '%s'", dbPath)
db, err := database.Open(cfg.DbType, dbPath, activeNetParams.Net)
if err != nil {
// Return the error if it's not because the database doesn't
// exist.
if dbErr, ok := err.(database.Error); !ok || dbErr.ErrorCode !=
database.ErrDbDoesNotExist {
return nil, err
}
// Create the db if it does not exist.
err = os.MkdirAll(cfg.DataDir, 0700)
if err != nil {
return nil, err
}
db, err = database.Create(cfg.DbType, dbPath, activeNetParams.Net)
if err != nil {
return nil, err
}
}
btcdLog.Info("Block database loaded")
return db, nil
}
在btcdMain函数中,调用loadBlockDB()获得数据库的句柄,通过newservre配置blockchain对象
server, err := newServer(cfg.Listeners, db, activeNetParams.Params,interrupt)
loadBlockDB()返回的是btcd中定义的数据库的接口,接口的定义如下:
// DB provides a generic interface that is used to store bitcoin blocks and
// related metadata. This interface is intended to be agnostic to the actual
// mechanism used for backend data storage. The RegisterDriver function can be
// used to add a new backend data storage method.
//
// This interface is divided into two distinct categories of functionality.
//
// The first category is atomic metadata storage with bucket support. This is
// accomplished through the use of database transactions.
//
// The second category is generic block storage. This functionality is
// intentionally separate because the mechanism used for block storage may or
// may not be the same mechanism used for metadata storage. For example, it is
// often more efficient to store the block data as flat files while the metadata
// is kept in a database. However, this interface aims to be generic enough to
// support blocks in the database too, if needed by a particular backend.
type DB interface {
// Type returns the database driver type the current database instance
// was created with.
Type() string
// Begin starts a transaction which is either read-only or read-write
// depending on the specified flag. Multiple read-only transactions
// can be started simultaneously while only a single read-write
// transaction can be started at a time. The call will block when
// starting a read-write transaction when one is already open.
//
// NOTE: The transaction must be closed by calling Rollback or Commit on
// it when it is no longer needed. Failure to do so can result in
// unclaimed memory and/or inablity to close the database due to locks
// depending on the specific database implementation.
Begin(writable bool) (Tx, error)
// View invokes the passed function in the context of a managed
// read-only transaction. Any errors returned from the user-supplied
// function are returned from this function.
//
// Calling Rollback or Commit on the transaction passed to the
// user-supplied function will result in a panic.
View(fn func(tx Tx) error) error
// Update invokes the passed function in the context of a managed
// read-write transaction. Any errors returned from the user-supplied
// function will cause the transaction to be rolled back and are
// returned from this function. Otherwise, the transaction is committed
// when the user-supplied function returns a nil error.
//
// Calling Rollback or Commit on the transaction passed to the
// user-supplied function will result in a panic.
Update(fn func(tx Tx) error) error
// Close cleanly shuts down the database and syncs all data. It will
// block until all database transactions have been finalized (rolled
// back or committed).
Close() error
}
函数处理收到的block
func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bool, bool, error)
该函数会检查block的合法性,并且确认该block和该block之前的block是否也存在在数据库中。如果都满足要求则写入到数据库,写入数据库的代码函数如下:
func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) (bool, error)

函数dbStoreBlock把block信息放入pendingBlockData数组,


在transaction的commit方法中,把block信息写进数据库,一个transaction可以存放多个block,然后一次写入文件。
在transcation的writePendingAndCommit()方法中,把数据写入数据库
在这个函数中打开leveldb数据库
func openDB(dbPath string, network wire.BitcoinNet, create bool) (database.DB, error) {

transcation 的commit方法

在writePendingAndCommit()中有写数据库

最后调用到这个函数
浙公网安备 33010602011771号