From 89c9320d8000845ee144f12adee958a5ab2303ef Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Fri, 5 Jun 2015 23:01:54 -0400 Subject: [PATCH 1/5] Allow exporting subset of chain --- core/chain_manager.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/chain_manager.go b/core/chain_manager.go index 86d1c1454..1d1b6554e 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -341,13 +341,25 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) { // Export writes the active chain to the given writer. func (self *ChainManager) Export(w io.Writer) error { + if err := self.ExportN(w, uint64(1), self.currentBlock.NumberU64()); err != nil { + return err + } + return nil +} + +// ExportN writes a subset of the active chain to the given writer. +func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error { self.mu.RLock() defer self.mu.RUnlock() glog.V(logger.Info).Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) - last := self.currentBlock.NumberU64() + if first > last { + return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last) + } - for nr := uint64(1); nr <= last; nr++ { + glog.V(logger.Info).Infof("exporting %d blocks...\n", last-first) + + for nr := first; nr <= last; nr++ { block := self.GetBlockByNumber(nr) if block == nil { return fmt.Errorf("export failed on #%d: not found", nr) From d65b64c8846636d3e58c1857eaff149d2f82a283 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sat, 6 Jun 2015 00:02:32 -0400 Subject: [PATCH 2/5] Allow export command to take first and last args --- cmd/geth/chaincmd.go | 22 +++++++++++++++++++++- cmd/utils/cmd.go | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 947532f40..509356a90 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -26,6 +26,12 @@ var ( Action: exportChain, Name: "export", Usage: `export blockchain into file`, + Description: ` +Requires a first argument of the file to write to. +Optional second and third arguments control the first and +last block to write. In this mode, the file will be appended +if already existing. + `, } upgradedbCommand = cli.Command{ Action: upgradeDB, @@ -68,7 +74,21 @@ func exportChain(ctx *cli.Context) { } chain, _, _, _ := utils.MakeChain(ctx) start := time.Now() - if err := utils.ExportChain(chain, ctx.Args().First()); err != nil { + + var err error + if len(ctx.Args()) < 3 { + err = utils.ExportChain(chain, ctx.Args().First()) + } else { + // This can be improved to allow for numbers larger than 9223372036854775807 + first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64) + last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64) + if ferr != nil || lerr != nil { + utils.Fatalf("Export error in parsing parameters\n") + } + err = utils.ExportAppendChain(chain, ctx.Args().First(), uint64(first), uint64(last)) + } + + if err != nil { utils.Fatalf("Export error: %v\n", err) } fmt.Printf("Export done in %v", time.Since(start)) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index e5413973d..f7520a8e4 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -268,3 +268,18 @@ func ExportChain(chainmgr *core.ChainManager, fn string) error { glog.Infoln("Exported blockchain to", fn) return nil } + +func ExportAppendChain(chainmgr *core.ChainManager, fn string, first uint64, last uint64) error { + glog.Infoln("Exporting blockchain to", fn) + // TODO verify mode perms + fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm) + if err != nil { + return err + } + defer fh.Close() + if err := chainmgr.ExportN(fh, first, last); err != nil { + return err + } + glog.Infoln("Exported blockchain to", fn) + return nil +} From ed621aae333ac183acc29c396c708ae57301838a Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sat, 6 Jun 2015 09:50:23 -0400 Subject: [PATCH 3/5] Cleanup --- cmd/geth/chaincmd.go | 2 +- core/chain_manager.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 509356a90..2e90001af 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -69,7 +69,7 @@ func importChain(ctx *cli.Context) { } func exportChain(ctx *cli.Context) { - if len(ctx.Args()) != 1 { + if len(ctx.Args()) < 1 { utils.Fatalf("This command requires an argument.") } chain, _, _, _ := utils.MakeChain(ctx) diff --git a/core/chain_manager.go b/core/chain_manager.go index 1d1b6554e..ae25ff6b1 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -351,13 +351,12 @@ func (self *ChainManager) Export(w io.Writer) error { func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error { self.mu.RLock() defer self.mu.RUnlock() - glog.V(logger.Info).Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) if first > last { return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last) } - glog.V(logger.Info).Infof("exporting %d blocks...\n", last-first) + glog.V(logger.Info).Infof("exporting %d blocks...\n", last-first+1) for nr := first; nr <= last; nr++ { block := self.GetBlockByNumber(nr) From 2729e6294a22c5f1adb547078a7391ca0537ccc9 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sat, 6 Jun 2015 10:04:13 -0400 Subject: [PATCH 4/5] Improved error checking --- cmd/geth/chaincmd.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 2e90001af..8586e3b81 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -76,16 +76,20 @@ func exportChain(ctx *cli.Context) { start := time.Now() var err error + fp := ctx.Args().First() if len(ctx.Args()) < 3 { - err = utils.ExportChain(chain, ctx.Args().First()) + err = utils.ExportChain(chain, fp) } else { // This can be improved to allow for numbers larger than 9223372036854775807 first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64) last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64) if ferr != nil || lerr != nil { - utils.Fatalf("Export error in parsing parameters\n") + utils.Fatalf("Export error in parsing parameters: block number not an integer\n") } - err = utils.ExportAppendChain(chain, ctx.Args().First(), uint64(first), uint64(last)) + if first < 0 || last < 0 { + utils.Fatalf("Export error: block number must be greater than 0\n") + } + err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last)) } if err != nil { From 4ab0cedf42abea8becc5177e566c070730f13a07 Mon Sep 17 00:00:00 2001 From: Taylor Gerring Date: Sat, 6 Jun 2015 10:59:56 -0400 Subject: [PATCH 5/5] Export should start with block 0 --- core/chain_manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/chain_manager.go b/core/chain_manager.go index ae25ff6b1..a00fd288d 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -341,7 +341,7 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) { // Export writes the active chain to the given writer. func (self *ChainManager) Export(w io.Writer) error { - if err := self.ExportN(w, uint64(1), self.currentBlock.NumberU64()); err != nil { + if err := self.ExportN(w, uint64(0), self.currentBlock.NumberU64()); err != nil { return err } return nil