From 17afb0b370bb3e5e4c0188a18acf3fdf3ab9b5d5 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 22 Apr 2022 10:07:04 -0500 Subject: [PATCH] Move forceprune logic into functions, make db open/closes all in a single scope (backport #1321) (#1323) * Move forceprune logic into functions, make db open/closes all in a single scope (#1321) --- CHANGELOG.md | 4 + cmd/osmosisd/cmd/forceprune.go | 169 ++++++++++++++++++++------------- 2 files changed, 106 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0549f26bfca..1587e0bf65a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased]() + +* [#1262](https://github.com/osmosis-labs/osmosis/pull/1262) Add a `forceprune` command to the binaries, that prunes golevelDB data better. + ## [v7.2.0](https://github.com/osmosis-labs/osmosis/releases/tag/v7.2.0) * [#1241](https://github.com/osmosis-labs/osmosis/pull/1241/files) chore: upgrade sdk to v0.45.0x-osmo-v7.7 diff --git a/cmd/osmosisd/cmd/forceprune.go b/cmd/osmosisd/cmd/forceprune.go index fcc35682e48..0add006e94e 100644 --- a/cmd/osmosisd/cmd/forceprune.go +++ b/cmd/osmosisd/cmd/forceprune.go @@ -37,19 +37,19 @@ func forceprune() *cobra.Command { Short: "Example osmosisd forceprune -f 188000 -m 1000, which would keep blockchain and state data of last 188000 blocks (approximately 2 weeks) and ABCI responses of last 1000 blocks.", Long: "Forceprune options prunes and compacts blockstore.db and state.db. One needs to shut down chain before running forceprune. By default it keeps last 188000 blocks (approximately 2 weeks of data) blockstore and state db (validator and consensus information) and 1000 blocks of abci responses from state.db. Everything beyond these heights in blockstore and state.db is pruned. ABCI Responses are stored in index db and so redundant especially if one is running pruned nodes. As a result we are removing ABCI data from state.db aggressively by default. One can override height for blockstore.db and state.db by using -f option and for abci response by using -m option. Example osmosisd forceprune -f 188000 -m 1000.", RunE: func(cmd *cobra.Command, args []string) error { - full_height_flag, err := cmd.Flags().GetString(fullHeight) + fullHeightFlag, err := cmd.Flags().GetString(fullHeight) if err != nil { return err } - min_height_flag, err := cmd.Flags().GetString(minHeight) + minHeightFlag, err := cmd.Flags().GetString(minHeight) if err != nil { return err } clientCtx := client.GetClientContextFromCmd(cmd) conf := config.DefaultConfig() - db_path := clientCtx.HomeDir + "/" + conf.DBPath + dbPath := clientCtx.HomeDir + "/" + conf.DBPath cmdr := exec.Command("osmosisd", "status") err = cmdr.Run() @@ -59,102 +59,137 @@ func forceprune() *cobra.Command { return nil } - full_height, err := strconv.ParseInt(full_height_flag, 10, 64) + fullHeight, err := strconv.ParseInt(fullHeightFlag, 10, 64) if err != nil { return err } - min_height, err := strconv.ParseInt(min_height_flag, 10, 64) + minHeight, err := strconv.ParseInt(minHeightFlag, 10, 64) if err != nil { return err } - opts := opt.Options{ - DisableSeeksCompaction: true, - } - - db_bs, err := tmdb.NewGoLevelDBWithOpts("blockstore", db_path, &opts) + startHeight, currentHeight, err := pruneBlockStoreAndGetHeights(dbPath, fullHeight) if err != nil { return err } - bs := tmstore.NewBlockStore(db_bs) - start_height := bs.Base() - current_height := bs.Height() - - fmt.Println("Pruning Block Store ...") - prunedBlocks, err := bs.PruneBlocks(current_height - full_height) - defer db_bs.Close() + err = compactBlockStore(dbPath) if err != nil { return err } - fmt.Println("Pruned Block Store ...", prunedBlocks) - db_bs.Close() - - fmt.Println("Compacting Block Store ...") - db, err := leveldb.OpenFile(db_path+"/blockstore.db", &opts) - defer db.Close() + err = forcepruneStateStore(dbPath, startHeight, currentHeight, minHeight, fullHeight) if err != nil { return err } - if err = db.CompactRange(*util.BytesPrefix([]byte{})); err != nil { - return err - } + fmt.Println("Done ...") - db, err = leveldb.OpenFile(db_path+"/state.db", &opts) - if err != nil { - return err - } - stateDBKeys := []string{kValidators, kConsensusParams, kABCIResponses} - fmt.Println("Pruning State Store ...") - for i, s := range stateDBKeys { - fmt.Println(i, s) - - retain_height := int64(0) - if s == kABCIResponses { - retain_height = current_height - min_height - } else { - retain_height = current_height - full_height - } + return nil + }, + } + + cmd.Flags().StringP(fullHeight, "f", defaultFullHeight, "Full height to chop to") + cmd.Flags().StringP(minHeight, "m", defaultMinHeight, "Min height for ABCI to chop to") + return cmd +} - batch := new(leveldb.Batch) - curBatchSize := uint64(0) +func pruneBlockStoreAndGetHeights(dbPath string, fullHeight int64) ( + startHeight int64, currentHeight int64, err error, +) { + opts := opt.Options{ + DisableSeeksCompaction: true, + } - fmt.Println(start_height, current_height, retain_height) + db_bs, err := tmdb.NewGoLevelDBWithOpts("blockstore", dbPath, &opts) + if err != nil { + return 0, 0, err + } + defer db_bs.Close() - for c := start_height; c < retain_height; c++ { - batch.Delete([]byte(s + strconv.FormatInt(c, 10))) - curBatchSize++ + bs := tmstore.NewBlockStore(db_bs) + startHeight = bs.Base() + currentHeight = bs.Height() - if curBatchSize%batchMaxSize == 0 && curBatchSize > 0 { - err := db.Write(batch, nil) - if err != nil { - return err - } - batch.Reset() - batch = new(leveldb.Batch) - } - } + fmt.Println("Pruning Block Store ...") + prunedBlocks, err := bs.PruneBlocks(currentHeight - fullHeight) + if err != nil { + return 0, 0, err + } + fmt.Println("Pruned Block Store ...", prunedBlocks) + return startHeight, currentHeight, nil +} + +func compactBlockStore(dbPath string) error { + compactOpts := opt.Options{ + DisableSeeksCompaction: true, + } + + fmt.Println("Compacting Block Store ...") + + db, err := leveldb.OpenFile(dbPath+"/blockstore.db", &compactOpts) + defer db.Close() + if err != nil { + return err + } + if err = db.CompactRange(*util.BytesPrefix([]byte{})); err != nil { + return err + } + return nil +} + +func forcepruneStateStore(dbPath string, startHeight, currentHeight, minHeight, fullHeight int64) error { + opts := opt.Options{ + DisableSeeksCompaction: true, + } + + db, err := leveldb.OpenFile(dbPath+"/state.db", &opts) + if err != nil { + return err + } + defer db.Close() + + stateDBKeys := []string{kValidators, kConsensusParams, kABCIResponses} + fmt.Println("Pruning State Store ...") + for i, s := range stateDBKeys { + fmt.Println(i, s) + + retain_height := int64(0) + if s == kABCIResponses { + retain_height = currentHeight - minHeight + } else { + retain_height = currentHeight - fullHeight + } + + batch := new(leveldb.Batch) + curBatchSize := uint64(0) + fmt.Println(startHeight, currentHeight, retain_height) + + for c := startHeight; c < retain_height; c++ { + batch.Delete([]byte(s + strconv.FormatInt(c, 10))) + curBatchSize++ + + if curBatchSize%batchMaxSize == 0 && curBatchSize > 0 { err := db.Write(batch, nil) if err != nil { return err } batch.Reset() + batch = new(leveldb.Batch) } + } - fmt.Println("Compacting State Store ...") - if err = db.CompactRange(*util.BytesPrefix([]byte{})); err != nil { - return err - } - fmt.Println("Done ...") - - return nil - }, + err := db.Write(batch, nil) + if err != nil { + return err + } + batch.Reset() } - cmd.Flags().StringP(fullHeight, "f", defaultFullHeight, "Full height to chop to") - cmd.Flags().StringP(minHeight, "m", defaultMinHeight, "Min height for ABCI to chop to") - return cmd + fmt.Println("Compacting State Store ...") + if err = db.CompactRange(*util.BytesPrefix([]byte{})); err != nil { + return err + } + return nil }