OSDN Git Service

Thanos did someting
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / database / cmd / dbtool / insecureimport.go
diff --git a/vendor/github.com/btcsuite/btcd/database/cmd/dbtool/insecureimport.go b/vendor/github.com/btcsuite/btcd/database/cmd/dbtool/insecureimport.go
deleted file mode 100644 (file)
index 7564eb6..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright (c) 2015-2016 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-       "encoding/binary"
-       "fmt"
-       "io"
-       "os"
-       "sync"
-       "time"
-
-       "github.com/btcsuite/btcd/chaincfg/chainhash"
-       "github.com/btcsuite/btcd/database"
-       "github.com/btcsuite/btcd/wire"
-       "github.com/btcsuite/btcutil"
-)
-
-// importCmd defines the configuration options for the insecureimport command.
-type importCmd struct {
-       InFile   string `short:"i" long:"infile" description:"File containing the block(s)"`
-       Progress int    `short:"p" long:"progress" description:"Show a progress message each time this number of seconds have passed -- Use 0 to disable progress announcements"`
-}
-
-var (
-       // importCfg defines the configuration options for the command.
-       importCfg = importCmd{
-               InFile:   "bootstrap.dat",
-               Progress: 10,
-       }
-
-       // zeroHash is a simply a hash with all zeros.  It is defined here to
-       // avoid creating it multiple times.
-       zeroHash = chainhash.Hash{}
-)
-
-// importResults houses the stats and result as an import operation.
-type importResults struct {
-       blocksProcessed int64
-       blocksImported  int64
-       err             error
-}
-
-// blockImporter houses information about an ongoing import from a block data
-// file to the block database.
-type blockImporter struct {
-       db                database.DB
-       r                 io.ReadSeeker
-       processQueue      chan []byte
-       doneChan          chan bool
-       errChan           chan error
-       quit              chan struct{}
-       wg                sync.WaitGroup
-       blocksProcessed   int64
-       blocksImported    int64
-       receivedLogBlocks int64
-       receivedLogTx     int64
-       lastHeight        int64
-       lastBlockTime     time.Time
-       lastLogTime       time.Time
-}
-
-// readBlock reads the next block from the input file.
-func (bi *blockImporter) readBlock() ([]byte, error) {
-       // The block file format is:
-       //  <network> <block length> <serialized block>
-       var net uint32
-       err := binary.Read(bi.r, binary.LittleEndian, &net)
-       if err != nil {
-               if err != io.EOF {
-                       return nil, err
-               }
-
-               // No block and no error means there are no more blocks to read.
-               return nil, nil
-       }
-       if net != uint32(activeNetParams.Net) {
-               return nil, fmt.Errorf("network mismatch -- got %x, want %x",
-                       net, uint32(activeNetParams.Net))
-       }
-
-       // Read the block length and ensure it is sane.
-       var blockLen uint32
-       if err := binary.Read(bi.r, binary.LittleEndian, &blockLen); err != nil {
-               return nil, err
-       }
-       if blockLen > wire.MaxBlockPayload {
-               return nil, fmt.Errorf("block payload of %d bytes is larger "+
-                       "than the max allowed %d bytes", blockLen,
-                       wire.MaxBlockPayload)
-       }
-
-       serializedBlock := make([]byte, blockLen)
-       if _, err := io.ReadFull(bi.r, serializedBlock); err != nil {
-               return nil, err
-       }
-
-       return serializedBlock, nil
-}
-
-// processBlock potentially imports the block into the database.  It first
-// deserializes the raw block while checking for errors.  Already known blocks
-// are skipped and orphan blocks are considered errors.  Returns whether the
-// block was imported along with any potential errors.
-//
-// NOTE: This is not a safe import as it does not verify chain rules.
-func (bi *blockImporter) processBlock(serializedBlock []byte) (bool, error) {
-       // Deserialize the block which includes checks for malformed blocks.
-       block, err := btcutil.NewBlockFromBytes(serializedBlock)
-       if err != nil {
-               return false, err
-       }
-
-       // update progress statistics
-       bi.lastBlockTime = block.MsgBlock().Header.Timestamp
-       bi.receivedLogTx += int64(len(block.MsgBlock().Transactions))
-
-       // Skip blocks that already exist.
-       var exists bool
-       err = bi.db.View(func(tx database.Tx) error {
-               exists, err = tx.HasBlock(block.Hash())
-               return err
-       })
-       if err != nil {
-               return false, err
-       }
-       if exists {
-               return false, nil
-       }
-
-       // Don't bother trying to process orphans.
-       prevHash := &block.MsgBlock().Header.PrevBlock
-       if !prevHash.IsEqual(&zeroHash) {
-               var exists bool
-               err := bi.db.View(func(tx database.Tx) error {
-                       exists, err = tx.HasBlock(prevHash)
-                       return err
-               })
-               if err != nil {
-                       return false, err
-               }
-               if !exists {
-                       return false, fmt.Errorf("import file contains block "+
-                               "%v which does not link to the available "+
-                               "block chain", prevHash)
-               }
-       }
-
-       // Put the blocks into the database with no checking of chain rules.
-       err = bi.db.Update(func(tx database.Tx) error {
-               return tx.StoreBlock(block)
-       })
-       if err != nil {
-               return false, err
-       }
-
-       return true, nil
-}
-
-// readHandler is the main handler for reading blocks from the import file.
-// This allows block processing to take place in parallel with block reads.
-// It must be run as a goroutine.
-func (bi *blockImporter) readHandler() {
-out:
-       for {
-               // Read the next block from the file and if anything goes wrong
-               // notify the status handler with the error and bail.
-               serializedBlock, err := bi.readBlock()
-               if err != nil {
-                       bi.errChan <- fmt.Errorf("Error reading from input "+
-                               "file: %v", err.Error())
-                       break out
-               }
-
-               // A nil block with no error means we're done.
-               if serializedBlock == nil {
-                       break out
-               }
-
-               // Send the block or quit if we've been signalled to exit by
-               // the status handler due to an error elsewhere.
-               select {
-               case bi.processQueue <- serializedBlock:
-               case <-bi.quit:
-                       break out
-               }
-       }
-
-       // Close the processing channel to signal no more blocks are coming.
-       close(bi.processQueue)
-       bi.wg.Done()
-}
-
-// logProgress logs block progress as an information message.  In order to
-// prevent spam, it limits logging to one message every importCfg.Progress
-// seconds with duration and totals included.
-func (bi *blockImporter) logProgress() {
-       bi.receivedLogBlocks++
-
-       now := time.Now()
-       duration := now.Sub(bi.lastLogTime)
-       if duration < time.Second*time.Duration(importCfg.Progress) {
-               return
-       }
-
-       // Truncate the duration to 10s of milliseconds.
-       durationMillis := int64(duration / time.Millisecond)
-       tDuration := 10 * time.Millisecond * time.Duration(durationMillis/10)
-
-       // Log information about new block height.
-       blockStr := "blocks"
-       if bi.receivedLogBlocks == 1 {
-               blockStr = "block"
-       }
-       txStr := "transactions"
-       if bi.receivedLogTx == 1 {
-               txStr = "transaction"
-       }
-       log.Infof("Processed %d %s in the last %s (%d %s, height %d, %s)",
-               bi.receivedLogBlocks, blockStr, tDuration, bi.receivedLogTx,
-               txStr, bi.lastHeight, bi.lastBlockTime)
-
-       bi.receivedLogBlocks = 0
-       bi.receivedLogTx = 0
-       bi.lastLogTime = now
-}
-
-// processHandler is the main handler for processing blocks.  This allows block
-// processing to take place in parallel with block reads from the import file.
-// It must be run as a goroutine.
-func (bi *blockImporter) processHandler() {
-out:
-       for {
-               select {
-               case serializedBlock, ok := <-bi.processQueue:
-                       // We're done when the channel is closed.
-                       if !ok {
-                               break out
-                       }
-
-                       bi.blocksProcessed++
-                       bi.lastHeight++
-                       imported, err := bi.processBlock(serializedBlock)
-                       if err != nil {
-                               bi.errChan <- err
-                               break out
-                       }
-
-                       if imported {
-                               bi.blocksImported++
-                       }
-
-                       bi.logProgress()
-
-               case <-bi.quit:
-                       break out
-               }
-       }
-       bi.wg.Done()
-}
-
-// statusHandler waits for updates from the import operation and notifies
-// the passed doneChan with the results of the import.  It also causes all
-// goroutines to exit if an error is reported from any of them.
-func (bi *blockImporter) statusHandler(resultsChan chan *importResults) {
-       select {
-       // An error from either of the goroutines means we're done so signal
-       // caller with the error and signal all goroutines to quit.
-       case err := <-bi.errChan:
-               resultsChan <- &importResults{
-                       blocksProcessed: bi.blocksProcessed,
-                       blocksImported:  bi.blocksImported,
-                       err:             err,
-               }
-               close(bi.quit)
-
-       // The import finished normally.
-       case <-bi.doneChan:
-               resultsChan <- &importResults{
-                       blocksProcessed: bi.blocksProcessed,
-                       blocksImported:  bi.blocksImported,
-                       err:             nil,
-               }
-       }
-}
-
-// Import is the core function which handles importing the blocks from the file
-// associated with the block importer to the database.  It returns a channel
-// on which the results will be returned when the operation has completed.
-func (bi *blockImporter) Import() chan *importResults {
-       // Start up the read and process handling goroutines.  This setup allows
-       // blocks to be read from disk in parallel while being processed.
-       bi.wg.Add(2)
-       go bi.readHandler()
-       go bi.processHandler()
-
-       // Wait for the import to finish in a separate goroutine and signal
-       // the status handler when done.
-       go func() {
-               bi.wg.Wait()
-               bi.doneChan <- true
-       }()
-
-       // Start the status handler and return the result channel that it will
-       // send the results on when the import is done.
-       resultChan := make(chan *importResults)
-       go bi.statusHandler(resultChan)
-       return resultChan
-}
-
-// newBlockImporter returns a new importer for the provided file reader seeker
-// and database.
-func newBlockImporter(db database.DB, r io.ReadSeeker) *blockImporter {
-       return &blockImporter{
-               db:           db,
-               r:            r,
-               processQueue: make(chan []byte, 2),
-               doneChan:     make(chan bool),
-               errChan:      make(chan error),
-               quit:         make(chan struct{}),
-               lastLogTime:  time.Now(),
-       }
-}
-
-// Execute is the main entry point for the command.  It's invoked by the parser.
-func (cmd *importCmd) Execute(args []string) error {
-       // Setup the global config options and ensure they are valid.
-       if err := setupGlobalConfig(); err != nil {
-               return err
-       }
-
-       // Ensure the specified block file exists.
-       if !fileExists(cmd.InFile) {
-               str := "The specified block file [%v] does not exist"
-               return fmt.Errorf(str, cmd.InFile)
-       }
-
-       // Load the block database.
-       db, err := loadBlockDB()
-       if err != nil {
-               return err
-       }
-       defer db.Close()
-
-       // Ensure the database is sync'd and closed on Ctrl+C.
-       addInterruptHandler(func() {
-               log.Infof("Gracefully shutting down the database...")
-               db.Close()
-       })
-
-       fi, err := os.Open(importCfg.InFile)
-       if err != nil {
-               return err
-       }
-       defer fi.Close()
-
-       // Create a block importer for the database and input file and start it.
-       // The results channel returned from start will contain an error if
-       // anything went wrong.
-       importer := newBlockImporter(db, fi)
-
-       // Perform the import asynchronously and signal the main goroutine when
-       // done.  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.  This is done
-       // in a separate goroutine rather than waiting directly so the main
-       // goroutine can be signaled for shutdown by either completion, error,
-       // or from the main interrupt handler.  This is necessary since the main
-       // goroutine must be kept running long enough for the interrupt handler
-       // goroutine to finish.
-       go func() {
-               log.Info("Starting import")
-               resultsChan := importer.Import()
-               results := <-resultsChan
-               if results.err != nil {
-                       dbErr, ok := results.err.(database.Error)
-                       if !ok || ok && dbErr.ErrorCode != database.ErrDbNotOpen {
-                               shutdownChannel <- results.err
-                               return
-                       }
-               }
-
-               log.Infof("Processed a total of %d blocks (%d imported, %d "+
-                       "already known)", results.blocksProcessed,
-                       results.blocksImported,
-                       results.blocksProcessed-results.blocksImported)
-               shutdownChannel <- nil
-       }()
-
-       // Wait for shutdown signal from either a normal completion or from the
-       // interrupt handler.
-       err = <-shutdownChannel
-       return err
-}