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 }