diff options
author | Felix Lange <fjl@twurst.com> | 2015-05-27 22:02:08 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2015-05-28 07:09:26 +0800 |
commit | 67effb94b6fadac7b207cb5333c91f578326762e (patch) | |
tree | f95a40d3213a23b434845ed89a40a110379f6606 /cmd/utils | |
parent | 705beb4c25f976f6bce40818bd835e235c2babf4 (diff) | |
download | dexon-67effb94b6fadac7b207cb5333c91f578326762e.tar.gz dexon-67effb94b6fadac7b207cb5333c91f578326762e.tar.zst dexon-67effb94b6fadac7b207cb5333c91f578326762e.zip |
cmd/geth, cmd/utils: make chain importing interruptible
Interrupting import with Ctrl-C could cause database corruption
because the signal wasn't handled. utils.ImportChain now checks
for a queued interrupt on every batch.
Diffstat (limited to 'cmd/utils')
-rw-r--r-- | cmd/utils/cmd.go | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 06c240bd4..2e2b627df 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -173,22 +173,47 @@ func FormatTransactionData(data string) []byte { return d } -func ImportChain(chainmgr *core.ChainManager, fn string) error { +func ImportChain(chain *core.ChainManager, fn string) error { + // Watch for Ctrl-C while the import is running. + // If a signal is received, the import will stop at the next batch. + interrupt := make(chan os.Signal, 1) + stop := make(chan struct{}) + signal.Notify(interrupt, os.Interrupt) + defer signal.Stop(interrupt) + defer close(interrupt) + go func() { + if _, ok := <-interrupt; ok { + glog.Info("caught interrupt during import, will stop at next batch") + } + close(stop) + }() + checkInterrupt := func() bool { + select { + case <-stop: + return true + default: + return false + } + } + glog.Infoln("Importing blockchain", fn) - fh, err := os.OpenFile(fn, os.O_RDONLY, os.ModePerm) + fh, err := os.Open(fn) if err != nil { return err } defer fh.Close() - - chainmgr.Reset() stream := rlp.NewStream(fh, 0) + // Remove all existing blocks and start the import. + chain.Reset() batchSize := 2500 blocks := make(types.Blocks, batchSize) n := 0 for { // Load a batch of RLP blocks. + if checkInterrupt() { + return fmt.Errorf("interrupted") + } i := 0 for ; i < batchSize; i++ { var b types.Block @@ -204,7 +229,10 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error { break } // Import the batch. - if _, err := chainmgr.InsertChain(blocks[:i]); err != nil { + if checkInterrupt() { + return fmt.Errorf("interrupted") + } + if _, err := chain.InsertChain(blocks[:i]); err != nil { return fmt.Errorf("invalid block %d: %v", n, err) } } |