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.
12 "github.com/btcsuite/btcd/blockchain"
13 "github.com/btcsuite/btcd/blockchain/indexers"
14 "github.com/btcsuite/btcd/database"
15 "github.com/btcsuite/btcd/limits"
16 "github.com/btcsuite/btclog"
20 // blockDbNamePrefix is the prefix for the btcd block database.
21 blockDbNamePrefix = "blocks"
29 // loadBlockDB opens the block database and returns a handle to it.
30 func loadBlockDB() (database.DB, error) {
31 // The database name is based on the database type.
32 dbName := blockDbNamePrefix + "_" + cfg.DbType
33 dbPath := filepath.Join(cfg.DataDir, dbName)
35 log.Infof("Loading block database from '%s'", dbPath)
36 db, err := database.Open(cfg.DbType, dbPath, activeNetParams.Net)
38 // Return the error if it's not because the database doesn't
40 if dbErr, ok := err.(database.Error); !ok || dbErr.ErrorCode !=
41 database.ErrDbDoesNotExist {
46 // Create the db if it does not exist.
47 err = os.MkdirAll(cfg.DataDir, 0700)
51 db, err = database.Create(cfg.DbType, dbPath, activeNetParams.Net)
57 log.Info("Block database loaded")
61 // realMain is the real main function for the utility. It is necessary to work
62 // around the fact that deferred functions do not run when os.Exit() is called.
63 func realMain() error {
64 // Load configuration and parse command line.
65 tcfg, _, err := loadConfig()
72 backendLogger := btclog.NewBackend(os.Stdout)
73 defer os.Stdout.Sync()
74 log = backendLogger.Logger("MAIN")
75 database.UseLogger(backendLogger.Logger("BCDB"))
76 blockchain.UseLogger(backendLogger.Logger("CHAN"))
77 indexers.UseLogger(backendLogger.Logger("INDX"))
79 // Load the block database.
80 db, err := loadBlockDB()
82 log.Errorf("Failed to load database: %v", err)
87 fi, err := os.Open(cfg.InFile)
89 log.Errorf("Failed to open file %v: %v", cfg.InFile, err)
94 // Create a block importer for the database and input file and start it.
95 // The done channel returned from start will contain an error if
96 // anything went wrong.
97 importer, err := newBlockImporter(db, fi)
99 log.Errorf("Failed create block importer: %v", err)
103 // Perform the import asynchronously. This allows blocks to be
104 // processed and read in parallel. The results channel returned from
105 // Import contains the statistics about the import including an error
106 // if something went wrong.
107 log.Info("Starting import")
108 resultsChan := importer.Import()
109 results := <-resultsChan
110 if results.err != nil {
111 log.Errorf("%v", results.err)
115 log.Infof("Processed a total of %d blocks (%d imported, %d already "+
116 "known)", results.blocksProcessed, results.blocksImported,
117 results.blocksProcessed-results.blocksImported)
122 // Use all processor cores and up some limits.
123 runtime.GOMAXPROCS(runtime.NumCPU())
124 if err := limits.SetLimits(); err != nil {
128 // Work around defer not working after os.Exit()
129 if err := realMain(); err != nil {