github.com/btcsuite/btcd@v0.24.0/cmd/addblock/addblock.go (about)

     1  // Copyright (c) 2013-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  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/btcsuite/btcd/blockchain"
    12  	"github.com/btcsuite/btcd/blockchain/indexers"
    13  	"github.com/btcsuite/btcd/database"
    14  	"github.com/btcsuite/btcd/limits"
    15  	"github.com/btcsuite/btclog"
    16  )
    17  
    18  const (
    19  	// blockDbNamePrefix is the prefix for the btcd block database.
    20  	blockDbNamePrefix = "blocks"
    21  )
    22  
    23  var (
    24  	cfg *config
    25  	log btclog.Logger
    26  )
    27  
    28  // loadBlockDB opens the block database and returns a handle to it.
    29  func loadBlockDB() (database.DB, error) {
    30  	// The database name is based on the database type.
    31  	dbName := blockDbNamePrefix + "_" + cfg.DbType
    32  	dbPath := filepath.Join(cfg.DataDir, dbName)
    33  
    34  	log.Infof("Loading block database from '%s'", dbPath)
    35  	db, err := database.Open(cfg.DbType, dbPath, activeNetParams.Net)
    36  	if err != nil {
    37  		// Return the error if it's not because the database doesn't
    38  		// exist.
    39  		if dbErr, ok := err.(database.Error); !ok || dbErr.ErrorCode !=
    40  			database.ErrDbDoesNotExist {
    41  
    42  			return nil, err
    43  		}
    44  
    45  		// Create the db if it does not exist.
    46  		err = os.MkdirAll(cfg.DataDir, 0700)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  		db, err = database.Create(cfg.DbType, dbPath, activeNetParams.Net)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  	}
    55  
    56  	log.Info("Block database loaded")
    57  	return db, nil
    58  }
    59  
    60  // realMain is the real main function for the utility.  It is necessary to work
    61  // around the fact that deferred functions do not run when os.Exit() is called.
    62  func realMain() error {
    63  	// Load configuration and parse command line.
    64  	tcfg, _, err := loadConfig()
    65  	if err != nil {
    66  		return err
    67  	}
    68  	cfg = tcfg
    69  
    70  	// Setup logging.
    71  	backendLogger := btclog.NewBackend(os.Stdout)
    72  	defer os.Stdout.Sync()
    73  	log = backendLogger.Logger("MAIN")
    74  	database.UseLogger(backendLogger.Logger("BCDB"))
    75  	blockchain.UseLogger(backendLogger.Logger("CHAN"))
    76  	indexers.UseLogger(backendLogger.Logger("INDX"))
    77  
    78  	// Load the block database.
    79  	db, err := loadBlockDB()
    80  	if err != nil {
    81  		log.Errorf("Failed to load database: %v", err)
    82  		return err
    83  	}
    84  	defer db.Close()
    85  
    86  	fi, err := os.Open(cfg.InFile)
    87  	if err != nil {
    88  		log.Errorf("Failed to open file %v: %v", cfg.InFile, err)
    89  		return err
    90  	}
    91  	defer fi.Close()
    92  
    93  	// Create a block importer for the database and input file and start it.
    94  	// The done channel returned from start will contain an error if
    95  	// anything went wrong.
    96  	importer, err := newBlockImporter(db, fi)
    97  	if err != nil {
    98  		log.Errorf("Failed create block importer: %v", err)
    99  		return err
   100  	}
   101  
   102  	// Perform the import asynchronously.  This allows blocks to be
   103  	// processed and read in parallel.  The results channel returned from
   104  	// Import contains the statistics about the import including an error
   105  	// if something went wrong.
   106  	log.Info("Starting import")
   107  	resultsChan := importer.Import()
   108  	results := <-resultsChan
   109  	if results.err != nil {
   110  		log.Errorf("%v", results.err)
   111  		return results.err
   112  	}
   113  
   114  	log.Infof("Processed a total of %d blocks (%d imported, %d already "+
   115  		"known)", results.blocksProcessed, results.blocksImported,
   116  		results.blocksProcessed-results.blocksImported)
   117  	return nil
   118  }
   119  
   120  func main() {
   121  	// up some limits.
   122  	if err := limits.SetLimits(); err != nil {
   123  		os.Exit(1)
   124  	}
   125  
   126  	// Work around defer not working after os.Exit()
   127  	if err := realMain(); err != nil {
   128  		os.Exit(1)
   129  	}
   130  }