2015-08-26 06:03:18 +02:00
|
|
|
// Copyright (c) 2013-2016 The btcsuite developers
|
2013-10-04 17:09:15 +02:00
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
2013-08-20 18:11:59 +02:00
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2014-07-02 15:50:08 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
2015-01-30 23:25:42 +01:00
|
|
|
"github.com/btcsuite/btcd/blockchain"
|
2016-06-04 00:06:16 +02:00
|
|
|
"github.com/btcsuite/btcd/blockchain/indexers"
|
2015-08-26 11:54:55 +02:00
|
|
|
"github.com/btcsuite/btcd/database"
|
2015-01-17 07:48:13 +01:00
|
|
|
"github.com/btcsuite/btcd/limits"
|
2015-01-16 18:42:25 +01:00
|
|
|
"github.com/btcsuite/btclog"
|
2013-08-20 18:11:59 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2014-01-12 19:05:05 +01:00
|
|
|
// blockDbNamePrefix is the prefix for the btcd block database.
|
|
|
|
blockDbNamePrefix = "blocks"
|
2013-08-20 18:11:59 +02:00
|
|
|
)
|
|
|
|
|
2013-11-11 17:48:21 +01:00
|
|
|
var (
|
2014-01-12 19:05:05 +01:00
|
|
|
cfg *config
|
|
|
|
log btclog.Logger
|
2013-11-11 17:48:21 +01:00
|
|
|
)
|
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
// loadBlockDB opens the block database and returns a handle to it.
|
2015-08-26 06:03:18 +02:00
|
|
|
func loadBlockDB() (database.DB, error) {
|
2014-01-12 19:05:05 +01:00
|
|
|
// The database name is based on the database type.
|
|
|
|
dbName := blockDbNamePrefix + "_" + cfg.DbType
|
|
|
|
dbPath := filepath.Join(cfg.DataDir, dbName)
|
|
|
|
|
|
|
|
log.Infof("Loading block database from '%s'", dbPath)
|
2015-08-26 06:03:18 +02:00
|
|
|
db, err := database.Open(cfg.DbType, dbPath, activeNetParams.Net)
|
2013-10-10 20:05:54 +02:00
|
|
|
if err != nil {
|
2014-01-12 19:05:05 +01:00
|
|
|
// Return the error if it's not because the database doesn't
|
|
|
|
// exist.
|
2015-08-26 06:03:18 +02:00
|
|
|
if dbErr, ok := err.(database.Error); !ok || dbErr.ErrorCode !=
|
|
|
|
database.ErrDbDoesNotExist {
|
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
return nil, err
|
2013-10-10 20:05:54 +02:00
|
|
|
}
|
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
// Create the db if it does not exist.
|
|
|
|
err = os.MkdirAll(cfg.DataDir, 0700)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-08-26 06:03:18 +02:00
|
|
|
db, err = database.Create(cfg.DbType, dbPath, activeNetParams.Net)
|
2014-01-12 19:05:05 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2014-01-07 22:30:25 +01:00
|
|
|
}
|
|
|
|
|
2015-08-26 06:03:18 +02:00
|
|
|
log.Info("Block database loaded")
|
2014-01-12 19:05:05 +01:00
|
|
|
return db, nil
|
|
|
|
}
|
2013-08-20 18:11:59 +02:00
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
// 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()
|
2013-08-20 18:11:59 +02:00
|
|
|
if err != nil {
|
2014-01-12 19:05:05 +01:00
|
|
|
return err
|
2013-08-20 18:11:59 +02:00
|
|
|
}
|
2014-01-12 19:05:05 +01:00
|
|
|
cfg = tcfg
|
2013-08-20 18:11:59 +02:00
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
// Setup logging.
|
2017-05-24 23:24:06 +02:00
|
|
|
backendLogger := btclog.NewBackend(os.Stdout)
|
|
|
|
defer os.Stdout.Sync()
|
|
|
|
log = backendLogger.Logger("MAIN")
|
|
|
|
database.UseLogger(backendLogger.Logger("BCDB"))
|
|
|
|
blockchain.UseLogger(backendLogger.Logger("CHAN"))
|
|
|
|
indexers.UseLogger(backendLogger.Logger("INDX"))
|
2013-08-20 18:11:59 +02:00
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
// Load the block database.
|
|
|
|
db, err := loadBlockDB()
|
2013-08-20 18:11:59 +02:00
|
|
|
if err != nil {
|
2014-01-12 19:05:05 +01:00
|
|
|
log.Errorf("Failed to load database: %v", err)
|
|
|
|
return err
|
2013-08-20 18:11:59 +02:00
|
|
|
}
|
|
|
|
defer db.Close()
|
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
fi, err := os.Open(cfg.InFile)
|
2013-08-20 18:11:59 +02:00
|
|
|
if err != nil {
|
2014-01-12 19:05:05 +01:00
|
|
|
log.Errorf("Failed to open file %v: %v", cfg.InFile, err)
|
|
|
|
return err
|
2013-08-20 18:11:59 +02:00
|
|
|
}
|
2014-01-12 19:05:05 +01:00
|
|
|
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.
|
2015-08-26 06:03:18 +02:00
|
|
|
importer, err := newBlockImporter(db, fi)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Failed create block importer: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
2014-01-12 19:05:05 +01:00
|
|
|
|
|
|
|
// 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
|
2013-08-20 18:11:59 +02:00
|
|
|
}
|
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
log.Infof("Processed a total of %d blocks (%d imported, %d already "+
|
|
|
|
"known)", results.blocksProcessed, results.blocksImported,
|
|
|
|
results.blocksProcessed-results.blocksImported)
|
|
|
|
return nil
|
2013-08-20 18:11:59 +02:00
|
|
|
}
|
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
func main() {
|
2020-09-07 18:14:21 +02:00
|
|
|
// up some limits.
|
2014-01-12 19:05:05 +01:00
|
|
|
if err := limits.SetLimits(); err != nil {
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2013-08-20 18:11:59 +02:00
|
|
|
|
2014-01-12 19:05:05 +01:00
|
|
|
// Work around defer not working after os.Exit()
|
|
|
|
if err := realMain(); err != nil {
|
|
|
|
os.Exit(1)
|
2013-08-20 18:11:59 +02:00
|
|
|
}
|
|
|
|
}
|