Skip to content

Commit 0f1cdfa

Browse files
committed
Merge pull request #1193 from tgerring/hotbackup
Improve export command
2 parents 81ceac1 + 4ab0ced commit 0f1cdfa

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

cmd/geth/chaincmd.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ var (
2626
Action: exportChain,
2727
Name: "export",
2828
Usage: `export blockchain into file`,
29+
Description: `
30+
Requires a first argument of the file to write to.
31+
Optional second and third arguments control the first and
32+
last block to write. In this mode, the file will be appended
33+
if already existing.
34+
`,
2935
}
3036
upgradedbCommand = cli.Command{
3137
Action: upgradeDB,
@@ -63,12 +69,30 @@ func importChain(ctx *cli.Context) {
6369
}
6470

6571
func exportChain(ctx *cli.Context) {
66-
if len(ctx.Args()) != 1 {
72+
if len(ctx.Args()) < 1 {
6773
utils.Fatalf("This command requires an argument.")
6874
}
6975
chain, _, _, _ := utils.MakeChain(ctx)
7076
start := time.Now()
71-
if err := utils.ExportChain(chain, ctx.Args().First()); err != nil {
77+
78+
var err error
79+
fp := ctx.Args().First()
80+
if len(ctx.Args()) < 3 {
81+
err = utils.ExportChain(chain, fp)
82+
} else {
83+
// This can be improved to allow for numbers larger than 9223372036854775807
84+
first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64)
85+
last, lerr := strconv.ParseInt(ctx.Args().Get(2), 10, 64)
86+
if ferr != nil || lerr != nil {
87+
utils.Fatalf("Export error in parsing parameters: block number not an integer\n")
88+
}
89+
if first < 0 || last < 0 {
90+
utils.Fatalf("Export error: block number must be greater than 0\n")
91+
}
92+
err = utils.ExportAppendChain(chain, fp, uint64(first), uint64(last))
93+
}
94+
95+
if err != nil {
7296
utils.Fatalf("Export error: %v\n", err)
7397
}
7498
fmt.Printf("Export done in %v", time.Since(start))

cmd/utils/cmd.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,18 @@ func ExportChain(chainmgr *core.ChainManager, fn string) error {
268268
glog.Infoln("Exported blockchain to", fn)
269269
return nil
270270
}
271+
272+
func ExportAppendChain(chainmgr *core.ChainManager, fn string, first uint64, last uint64) error {
273+
glog.Infoln("Exporting blockchain to", fn)
274+
// TODO verify mode perms
275+
fh, err := os.OpenFile(fn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModePerm)
276+
if err != nil {
277+
return err
278+
}
279+
defer fh.Close()
280+
if err := chainmgr.ExportN(fh, first, last); err != nil {
281+
return err
282+
}
283+
glog.Infoln("Exported blockchain to", fn)
284+
return nil
285+
}

core/chain_manager.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,24 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
347347

348348
// Export writes the active chain to the given writer.
349349
func (self *ChainManager) Export(w io.Writer) error {
350+
if err := self.ExportN(w, uint64(0), self.currentBlock.NumberU64()); err != nil {
351+
return err
352+
}
353+
return nil
354+
}
355+
356+
// ExportN writes a subset of the active chain to the given writer.
357+
func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error {
350358
self.mu.RLock()
351359
defer self.mu.RUnlock()
352-
glog.V(logger.Info).Infof("exporting %v blocks...\n", self.currentBlock.Header().Number)
353360

354-
last := self.currentBlock.NumberU64()
361+
if first > last {
362+
return fmt.Errorf("export failed: first (%d) is greater than last (%d)", first, last)
363+
}
364+
365+
glog.V(logger.Info).Infof("exporting %d blocks...\n", last-first+1)
355366

356-
for nr := uint64(1); nr <= last; nr++ {
367+
for nr := first; nr <= last; nr++ {
357368
block := self.GetBlockByNumber(nr)
358369
if block == nil {
359370
return fmt.Errorf("export failed on #%d: not found", nr)

0 commit comments

Comments
 (0)