Skip to content

Commit

Permalink
feat: Add a cli cmd to prune old states according to current settings…
Browse files Browse the repository at this point in the history
… (backport cosmos#12742) (cosmos#13119)

* feat: Add a cli cmd to prune old states according to current settings (cosmos#12742)

* add PruningCmd and change PruneStores signature

* the mimimum default pruning interval is 10

Co-authored-by: Marko <[email protected]>
(cherry picked from commit d874ace)

* fix backport error

Co-authored-by: adu-crypto <[email protected]>
Co-authored-by: adu <[email protected]>
  • Loading branch information
3 people authored and JeancarloBarrios committed Sep 28, 2024
1 parent 5dac560 commit d7795e9
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 24 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features

* (x/authz) [#13047](https://github.com/cosmos/cosmos-sdk/pull/13047) Add a GetAuthorization function to the keeper.
* (cli) [#12742](https://github.com/cosmos/cosmos-sdk/pull/12742) Add the `prune` CLI cmd to manually prune app store history versions based on the pruning options.

### Improvements

Expand Down
22 changes: 9 additions & 13 deletions client/pruning/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import (
"github.com/spf13/viper"

"github.com/cosmos/cosmos-sdk/client/flags"
pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types"
"github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
)
Expand All @@ -39,8 +38,7 @@ func PruningCmd(appCreator servertypes.AppCreator) *cobra.Command {
'--home' and '--app-db-backend'.
valid app-db-backend type includes 'goleveldb', 'cleveldb', 'rocksdb', 'boltdb', and 'badgerdb'.
`,
Example: `prune --home './' --app-db-backend 'goleveldb' --pruning 'custom' --pruning-keep-recent 100 --
pruning-keep-every 10, --pruning-interval 10`,
Example: "prune --home './' --app-db-backend 'goleveldb' --pruning 'custom' --pruning-keep-recent 100",
RunE: func(cmd *cobra.Command, _ []string) error {
vp := viper.New()

Expand All @@ -52,12 +50,13 @@ func PruningCmd(appCreator servertypes.AppCreator) *cobra.Command {
if err != nil {
return err
}
fmt.Printf("get pruning options from command flags, keep-recent: %v\n",
fmt.Printf("get pruning options from command flags, strategy: %v, keep-recent: %v\n",
pruningOptions.Strategy,
pruningOptions.KeepRecent,
)

home := vp.GetString(flags.FlagHome)
db, err := openDB(home)
db, err := openDB(home, server.GetAppDBBackend(vp))
if err != nil {
return err
}
Expand Down Expand Up @@ -92,7 +91,7 @@ func PruningCmd(appCreator servertypes.AppCreator) *cobra.Command {
pruningHeights[len(pruningHeights)-1],
)

rootMultiStore.PruneStores(false, pruningHeights)
err = rootMultiStore.PruneStores(false, pruningHeights)
if err != nil {
return err
}
Expand All @@ -103,19 +102,16 @@ func PruningCmd(appCreator servertypes.AppCreator) *cobra.Command {

cmd.Flags().String(flags.FlagHome, "", "The database home directory")
cmd.Flags().String(FlagAppDBBackend, "", "The type of database for application and snapshots databases")
cmd.Flags().String(server.FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
cmd.Flags().String(server.FlagPruning, pruningtypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
cmd.Flags().Uint64(server.FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
cmd.Flags().Uint64(server.FlagPruningKeepEvery, 0,
`Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom'),
this is not used by this command but kept for compatibility with the complete pruning options`)
cmd.Flags().Uint64(server.FlagPruningInterval, 10,
`Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom'),
this is not used by this command but kept for compatibility with the complete pruning options`)

return cmd
}

func openDB(rootDir string) (dbm.DB, error) {
func openDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) {
dataDir := filepath.Join(rootDir, "data")
return sdk.NewLevelDB("application", dataDir)
return dbm.NewDB("application", backendType, dataDir)
}
68 changes: 57 additions & 11 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,62 @@ func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore {
return store
}

// GetStoreByName performs a lookup of a StoreKey given a store name typically
func (rs *Store) handlePruning(version int64) error {
rs.pruningManager.HandleHeight(version - 1) // we should never prune the current version.
if !rs.pruningManager.ShouldPruneAtHeight(version) {
return nil
}
rs.logger.Info("prune start", "height", version)
defer rs.logger.Info("prune end", "height", version)
return rs.PruneStores(true, nil)
}

// PruneStores prunes the specific heights of the multi store.
// If clearPruningManager is true, the pruning manager will return the pruning heights,
// and they are appended to the pruningHeights to be pruned.
func (rs *Store) PruneStores(clearPruningManager bool, pruningHeights []int64) (err error) {
if clearPruningManager {
heights, err := rs.pruningManager.GetFlushAndResetPruningHeights()
if err != nil {
return err
}

if len(heights) == 0 {
rs.logger.Debug("no heights to be pruned from pruning manager")
}

pruningHeights = append(pruningHeights, heights...)
}

if len(pruningHeights) == 0 {
rs.logger.Debug("no heights need to be pruned")
return nil
}

rs.logger.Debug("pruning heights", "heights", pruningHeights)

for key, store := range rs.stores {
// If the store is wrapped with an inter-block cache, we must first unwrap
// it to get the underlying IAVL store.
if store.GetStoreType() != types.StoreTypeIAVL {
continue
}

store = rs.GetCommitKVStore(key)

err := store.(*iavl.Store).DeleteVersions(pruningHeights...)
if err == nil {
continue
}

if errCause := errors.Cause(err); errCause != nil && errCause != iavltree.ErrVersionDoesNotExist {
return err
}
}
return nil
}

// getStoreByName performs a lookup of a StoreKey given a store name typically
// provided in a path. The StoreKey is then used to perform a lookup and return
// a Store. If the Store is wrapped in an inter-block cache, it will be unwrapped
// prior to being returned. If the StoreKey does not exist, nil is returned.
Expand Down Expand Up @@ -756,7 +811,7 @@ func (rs *Store) Snapshot(height uint64, protoWriter protoio.Writer) error {
if height == 0 {
return sdkerrors.Wrap(sdkerrors.ErrLogic, "cannot snapshot height 0")
}
if height > uint64(rs.LastCommitID().Version) {
if height > uint64(GetLatestVersion(rs.db)) {
return sdkerrors.Wrapf(sdkerrors.ErrLogic, "cannot snapshot future height %v", height)
}

Expand Down Expand Up @@ -1048,15 +1103,6 @@ type storeParams struct {
initialVersion uint64
}

func newStoreParams(key types.StoreKey, db dbm.DB, typ types.StoreType, initialVersion uint64) storeParams {
return storeParams{
key: key,
db: db,
typ: typ,
initialVersion: initialVersion,
}
}

func GetLatestVersion(db dbm.DB) int64 {
bz, err := db.Get([]byte(latestVersionKey))
if err != nil {
Expand Down

0 comments on commit d7795e9

Please sign in to comment.