// realMain is the real main function for the utility. It is necessary to work // around the fact that deferred functions do not run when os.Exit() is called. func realMain() error { // Load configuration and parse command line. tcfg, _, err := loadConfig() if err != nil { return err } cfg = tcfg // Setup logging. backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") database.UseLogger(btclog.NewSubsystemLogger(backendLogger, "BCDB: ")) blockchain.UseLogger(btclog.NewSubsystemLogger(backendLogger, "CHAN: ")) indexers.UseLogger(btclog.NewSubsystemLogger(backendLogger, "INDX: ")) // Load the block database. db, err := loadBlockDB() if err != nil { log.Errorf("Failed to load database: %v", err) return err } defer db.Close() fi, err := os.Open(cfg.InFile) if err != nil { log.Errorf("Failed to open file %v: %v", cfg.InFile, err) return err } defer fi.Close() // Create a block importer for the database and input file and start it. // The done channel returned from start will contain an error if // anything went wrong. importer, err := newBlockImporter(db, fi) if err != nil { log.Errorf("Failed create block importer: %v", err) return err } // Perform the import asynchronously. This allows blocks to be // processed and read in parallel. The results channel returned from // Import contains the statistics about the import including an error // if something went wrong. log.Info("Starting import") resultsChan := importer.Import() results := <-resultsChan if results.err != nil { log.Errorf("%v", results.err) return results.err } log.Infof("Processed a total of %d blocks (%d imported, %d already "+ "known) in %v", results.blocksProcessed, results.blocksImported, results.blocksProcessed-results.blocksImported, results.duration) return nil }
// realMain is the real main function for the utility. It is necessary to work // around the fact that deferred functions do not run when os.Exit() is called. func realMain() error { // Setup logging. backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") dbLog := btclog.NewSubsystemLogger(backendLogger, "BCDB: ") dbLog.SetLevel(btclog.DebugLvl) database.UseLogger(dbLog) // Setup the parser options and commands. appName := filepath.Base(os.Args[0]) appName = strings.TrimSuffix(appName, filepath.Ext(appName)) parserFlags := flags.Options(flags.HelpFlag | flags.PassDoubleDash) parser := flags.NewNamedParser(appName, parserFlags) parser.AddGroup("Global Options", "", cfg) parser.AddCommand("insecureimport", "Insecurely import bulk block data from bootstrap.dat", "Insecurely import bulk block data from bootstrap.dat. "+ "WARNING: This is NOT secure because it does NOT "+ "verify chain rules. It is only provided for testing "+ "purposes.", &importCfg) parser.AddCommand("loadheaders", "Time how long to load headers for all blocks in the database", "", &headersCfg) parser.AddCommand("fetchblock", "Fetch the specific block hash from the database", "", &fetchBlockCfg) parser.AddCommand("fetchblockregion", "Fetch the specified block region from the database", "", &blockRegionCfg) // Parse command line and invoke the Execute function for the specified // command. if _, err := parser.Parse(); err != nil { if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp { parser.WriteHelp(os.Stderr) } else { log.Error(err) } return err } return nil }
func main() { cfg := config{ DbType: "leveldb", DataDir: defaultDataDir, } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") database.UseLogger(log) // Multiple networks can't be selected simultaneously. funcName := "main" numNets := 0 // Count number of network flags passed; assign active network params // while we're at it if cfg.TestNet3 { numNets++ activeNetParams = &chaincfg.TestNet3Params } if cfg.RegressionTest { numNets++ activeNetParams = &chaincfg.RegressionNetParams } if cfg.SimNet { numNets++ activeNetParams = &chaincfg.SimNetParams } if numNets > 1 { str := "%s: The testnet, regtest, and simnet params can't be " + "used together -- choose one of the three" err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) parser.WriteHelp(os.Stderr) return } cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams)) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db") db, err := database.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer db.Close() log.Infof("db load complete") _, height, err := db.NewestSha() log.Infof("loaded block height %v", height) sha, err := getSha(db, cfg.ShaString) if err != nil { log.Infof("Invalid block hash %v", cfg.ShaString) return } err = db.DropAfterBlockBySha(&sha) if err != nil { log.Warnf("failed %v", err) } }
func main() { end := int64(-1) cfg := config{ DbType: "leveldb", DataDir: defaultDataDir, } parser := flags.NewParser(&cfg, flags.Default) _, err := parser.Parse() if err != nil { if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp { parser.WriteHelp(os.Stderr) } return } backendLogger := btclog.NewDefaultBackendLogger() defer backendLogger.Flush() log = btclog.NewSubsystemLogger(backendLogger, "") database.UseLogger(log) // Multiple networks can't be selected simultaneously. funcName := "main" numNets := 0 // Count number of network flags passed; assign active network params // while we're at it if cfg.TestNet { numNets++ activeNetParams = &chaincfg.TestNetParams } if cfg.SimNet { numNets++ activeNetParams = &chaincfg.SimNetParams } if numNets > 1 { str := "%s: The testnet, regtest, and simnet params can't be " + "used together -- choose one of the three" err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) parser.WriteHelp(os.Stderr) return } cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams)) blockDbNamePrefix := "blocks" dbName := blockDbNamePrefix + "_" + cfg.DbType if cfg.DbType == "sqlite" { dbName = dbName + ".db" } dbPath := filepath.Join(cfg.DataDir, dbName) log.Infof("loading db %v", cfg.DbType) database, err := database.OpenDB(cfg.DbType, dbPath) if err != nil { log.Warnf("db open failed: %v", err) return } defer database.Close() log.Infof("db load complete") height, err := getHeight(database, cfg.ShaString) if err != nil { log.Infof("Invalid block %v", cfg.ShaString) return } if cfg.EShaString != "" { end, err = getHeight(database, cfg.EShaString) if err != nil { log.Infof("Invalid end block %v", cfg.EShaString) return } } else { end = height + 1 } log.Infof("height %v end %v", height, end) var fo io.WriteCloser if cfg.OutFile != "" { fo, err = os.Create(cfg.OutFile) if err != nil { log.Warnf("failed to open file %v, err %v", cfg.OutFile, err) } defer func() { if err := fo.Close(); err != nil { log.Warn("failed to close file %v %v", cfg.OutFile, err) } }() } for ; height < end; height++ { if cfg.Progress && height%int64(1) == 0 { log.Infof("Processing block %v", height) } err = DumpBlock(database, height, fo, cfg.RawBlock, cfg.FmtBlock, cfg.ShowTx) if err != nil { break } } if cfg.Progress { height-- log.Infof("Processing block %v", height) } }