github.com/palcoin-project/palcd@v1.0.0/database/cmd/dbtool/loadheaders.go (about)

     1  // Copyright (c) 2015-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"time"
     9  
    10  	"github.com/palcoin-project/palcd/chaincfg/chainhash"
    11  	"github.com/palcoin-project/palcd/database"
    12  )
    13  
    14  // headersCmd defines the configuration options for the loadheaders command.
    15  type headersCmd struct {
    16  	Bulk bool `long:"bulk" description:"Use bulk loading of headers instead of one at a time"`
    17  }
    18  
    19  var (
    20  	// headersCfg defines the configuration options for the command.
    21  	headersCfg = headersCmd{
    22  		Bulk: false,
    23  	}
    24  )
    25  
    26  // Execute is the main entry point for the command.  It's invoked by the parser.
    27  func (cmd *headersCmd) Execute(args []string) error {
    28  	// Setup the global config options and ensure they are valid.
    29  	if err := setupGlobalConfig(); err != nil {
    30  		return err
    31  	}
    32  
    33  	// Load the block database.
    34  	db, err := loadBlockDB()
    35  	if err != nil {
    36  		return err
    37  	}
    38  	defer db.Close()
    39  
    40  	// NOTE: This code will only work for ffldb.  Ideally the package using
    41  	// the database would keep a metadata index of its own.
    42  	blockIdxName := []byte("ffldb-blockidx")
    43  	if !headersCfg.Bulk {
    44  		err = db.View(func(tx database.Tx) error {
    45  			totalHdrs := 0
    46  			blockIdxBucket := tx.Metadata().Bucket(blockIdxName)
    47  			blockIdxBucket.ForEach(func(k, v []byte) error {
    48  				totalHdrs++
    49  				return nil
    50  			})
    51  			log.Infof("Loading headers for %d blocks...", totalHdrs)
    52  			numLoaded := 0
    53  			startTime := time.Now()
    54  			blockIdxBucket.ForEach(func(k, v []byte) error {
    55  				var hash chainhash.Hash
    56  				copy(hash[:], k)
    57  				_, err := tx.FetchBlockHeader(&hash)
    58  				if err != nil {
    59  					return err
    60  				}
    61  				numLoaded++
    62  				return nil
    63  			})
    64  			log.Infof("Loaded %d headers in %v", numLoaded,
    65  				time.Since(startTime))
    66  			return nil
    67  		})
    68  		return err
    69  	}
    70  
    71  	// Bulk load headers.
    72  	err = db.View(func(tx database.Tx) error {
    73  		blockIdxBucket := tx.Metadata().Bucket(blockIdxName)
    74  		hashes := make([]chainhash.Hash, 0, 500000)
    75  		blockIdxBucket.ForEach(func(k, v []byte) error {
    76  			var hash chainhash.Hash
    77  			copy(hash[:], k)
    78  			hashes = append(hashes, hash)
    79  			return nil
    80  		})
    81  
    82  		log.Infof("Loading headers for %d blocks...", len(hashes))
    83  		startTime := time.Now()
    84  		hdrs, err := tx.FetchBlockHeaders(hashes)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		log.Infof("Loaded %d headers in %v", len(hdrs),
    89  			time.Since(startTime))
    90  		return nil
    91  	})
    92  	return err
    93  }