refactor!: remove 'keep-every' from pruning (#11152)
This commit is contained in:
parent
94e6a379a2
commit
774e333ccb
@ -65,6 +65,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
* (store)[\#11152](https://github.com/cosmos/cosmos-sdk/pull/11152) Remove `keep-every` from pruning options.
|
||||
* [\#10950](https://github.com/cosmos/cosmos-sdk/pull/10950) Add `envPrefix` parameter to `cmd.Execute`.
|
||||
* (x/mint) [\#10441](https://github.com/cosmos/cosmos-sdk/pull/10441) The `NewAppModule` function now accepts an inflation calculation function as an argument.
|
||||
* [\#10295](https://github.com/cosmos/cosmos-sdk/pull/10295) Remove store type aliases from /types
|
||||
|
||||
@ -709,22 +709,6 @@ func (app *BaseApp) GetBlockRetentionHeight(commitHeight int64) int64 {
|
||||
retentionHeight = commitHeight - cp.Evidence.MaxAgeNumBlocks
|
||||
}
|
||||
|
||||
// Define the state pruning offset, i.e. the block offset at which the
|
||||
// underlying logical database is persisted to disk.
|
||||
statePruningOffset := int64(app.cms.GetPruning().KeepEvery)
|
||||
if statePruningOffset > 0 {
|
||||
if commitHeight > statePruningOffset {
|
||||
v := commitHeight - (commitHeight % statePruningOffset)
|
||||
retentionHeight = minNonZero(retentionHeight, v)
|
||||
} else {
|
||||
// Hitting this case means we have persisting enabled but have yet to reach
|
||||
// a height in which we persist state, so we return zero regardless of other
|
||||
// conditions. Otherwise, we could end up pruning blocks without having
|
||||
// any state committed to disk.
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
if app.snapshotInterval > 0 && app.snapshotKeepRecent > 0 {
|
||||
v := commitHeight - int64((app.snapshotInterval * uint64(app.snapshotKeepRecent)))
|
||||
retentionHeight = minNonZero(retentionHeight, v)
|
||||
|
||||
@ -39,12 +39,11 @@ func TestGetBlockRentionHeight(t *testing.T) {
|
||||
"pruning iavl snapshot only": {
|
||||
bapp: baseapp.NewBaseApp(
|
||||
name, logger, db,
|
||||
baseapp.SetPruning(sdk.PruningOptions{KeepEvery: 10000}),
|
||||
baseapp.SetMinRetainBlocks(1),
|
||||
),
|
||||
maxAgeBlocks: 0,
|
||||
commitHeight: 499000,
|
||||
expected: 490000,
|
||||
expected: 498999,
|
||||
},
|
||||
"pruning state sync snapshot only": {
|
||||
bapp: baseapp.NewBaseApp(
|
||||
@ -69,7 +68,6 @@ func TestGetBlockRentionHeight(t *testing.T) {
|
||||
"pruning all conditions": {
|
||||
bapp: baseapp.NewBaseApp(
|
||||
name, logger, db,
|
||||
baseapp.SetPruning(sdk.PruningOptions{KeepEvery: 10000}),
|
||||
baseapp.SetMinRetainBlocks(400000),
|
||||
baseapp.SetSnapshotInterval(50000), baseapp.SetSnapshotKeepRecent(3),
|
||||
),
|
||||
@ -80,7 +78,6 @@ func TestGetBlockRentionHeight(t *testing.T) {
|
||||
"no pruning due to no persisted state": {
|
||||
bapp: baseapp.NewBaseApp(
|
||||
name, logger, db,
|
||||
baseapp.SetPruning(sdk.PruningOptions{KeepEvery: 10000}),
|
||||
baseapp.SetMinRetainBlocks(400000),
|
||||
baseapp.SetSnapshotInterval(50000), baseapp.SetSnapshotKeepRecent(3),
|
||||
),
|
||||
@ -91,7 +88,6 @@ func TestGetBlockRentionHeight(t *testing.T) {
|
||||
"disable pruning": {
|
||||
bapp: baseapp.NewBaseApp(
|
||||
name, logger, db,
|
||||
baseapp.SetPruning(sdk.PruningOptions{KeepEvery: 10000}),
|
||||
baseapp.SetMinRetainBlocks(0),
|
||||
baseapp.SetSnapshotInterval(50000), baseapp.SetSnapshotKeepRecent(3),
|
||||
),
|
||||
|
||||
@ -292,16 +292,9 @@ func (app *BaseApp) init() error {
|
||||
|
||||
// make sure the snapshot interval is a multiple of the pruning KeepEvery interval
|
||||
if app.snapshotManager != nil && app.snapshotInterval > 0 {
|
||||
rms, ok := app.cms.(*rootmulti.Store)
|
||||
if !ok {
|
||||
if _, ok := app.cms.(*rootmulti.Store); !ok {
|
||||
return errors.New("state sync snapshots require a rootmulti store")
|
||||
}
|
||||
pruningOpts := rms.GetPruning()
|
||||
if pruningOpts.KeepEvery > 0 && app.snapshotInterval%pruningOpts.KeepEvery != 0 {
|
||||
return fmt.Errorf(
|
||||
"state sync snapshot interval %v must be a multiple of pruning keep every interval %v",
|
||||
app.snapshotInterval, pruningOpts.KeepEvery)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -184,7 +184,6 @@ func setupBaseAppWithSnapshots(t *testing.T, blocks uint, blockTxs int, options
|
||||
app := setupBaseApp(t, append(options,
|
||||
baseapp.SetSnapshotStore(snapshotStore),
|
||||
baseapp.SetSnapshotInterval(snapshotInterval),
|
||||
baseapp.SetPruning(sdk.PruningOptions{KeepEvery: 1}),
|
||||
routerOpt)...)
|
||||
|
||||
app.InitChain(abci.RequestInitChain{})
|
||||
@ -480,7 +479,6 @@ func TestLoadVersionPruning(t *testing.T) {
|
||||
logger := log.NewNopLogger()
|
||||
pruningOptions := storetypes.PruningOptions{
|
||||
KeepRecent: 2,
|
||||
KeepEvery: 3,
|
||||
Interval: 1,
|
||||
}
|
||||
pruningOpt := baseapp.SetPruning(pruningOptions)
|
||||
|
||||
5
go.sum
5
go.sum
@ -288,7 +288,6 @@ github.com/cosmos/cosmos-sdk/errors v1.0.0-beta.2/go.mod h1:Gi7pzVRnvZ1N16JAXpLA
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
|
||||
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
|
||||
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
|
||||
github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y=
|
||||
github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w=
|
||||
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU=
|
||||
@ -324,7 +323,6 @@ github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFM
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M=
|
||||
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI=
|
||||
@ -537,8 +535,6 @@ github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9
|
||||
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
|
||||
github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs=
|
||||
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@ -1657,7 +1653,6 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@ -31,7 +31,6 @@ type BaseConfig struct {
|
||||
|
||||
Pruning string `mapstructure:"pruning"`
|
||||
PruningKeepRecent string `mapstructure:"pruning-keep-recent"`
|
||||
PruningKeepEvery string `mapstructure:"pruning-keep-every"`
|
||||
PruningInterval string `mapstructure:"pruning-interval"`
|
||||
|
||||
// HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
@ -207,7 +206,6 @@ func DefaultConfig() *Config {
|
||||
InterBlockCache: true,
|
||||
Pruning: storetypes.PruningOptionDefault,
|
||||
PruningKeepRecent: "0",
|
||||
PruningKeepEvery: "0",
|
||||
PruningInterval: "0",
|
||||
MinRetainBlocks: 0,
|
||||
IndexEvents: make([]string, 0),
|
||||
@ -265,7 +263,6 @@ func GetConfig(v *viper.Viper) Config {
|
||||
InterBlockCache: v.GetBool("inter-block-cache"),
|
||||
Pruning: v.GetString("pruning"),
|
||||
PruningKeepRecent: v.GetString("pruning-keep-recent"),
|
||||
PruningKeepEvery: v.GetString("pruning-keep-every"),
|
||||
PruningInterval: v.GetString("pruning-interval"),
|
||||
HaltHeight: v.GetUint64("halt-height"),
|
||||
HaltTime: v.GetUint64("halt-time"),
|
||||
|
||||
@ -22,15 +22,14 @@ const DefaultConfigTemplate = `# This is a TOML config file.
|
||||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "{{ .BaseConfig.MinGasPrices }}"
|
||||
|
||||
# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
|
||||
# default: the last 362880 states are kept, pruning at 10 block intervals
|
||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
# everything: all saved states will be deleted, storing only the current state; pruning at 10 block intervals
|
||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
|
||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent' and 'pruning-interval'
|
||||
pruning = "{{ .BaseConfig.Pruning }}"
|
||||
|
||||
# These are applied if and only if the pruning strategy is custom.
|
||||
pruning-keep-recent = "{{ .BaseConfig.PruningKeepRecent }}"
|
||||
pruning-keep-every = "{{ .BaseConfig.PruningKeepEvery }}"
|
||||
pruning-interval = "{{ .BaseConfig.PruningInterval }}"
|
||||
|
||||
# HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
@ -202,7 +201,7 @@ enable-unsafe-cors = {{ .GRPCWeb.EnableUnsafeCORS }}
|
||||
[state-sync]
|
||||
|
||||
# snapshot-interval specifies the block interval at which local state sync snapshots are
|
||||
# taken (0 to disable). Must be a multiple of pruning-keep-every.
|
||||
# taken (0 to disable).
|
||||
snapshot-interval = {{ .StateSync.SnapshotInterval }}
|
||||
|
||||
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
|
||||
|
||||
@ -24,7 +24,6 @@ func GetPruningOptionsFromFlags(appOpts types.AppOptions) (storetypes.PruningOpt
|
||||
case storetypes.PruningOptionCustom:
|
||||
opts := storetypes.NewPruningOptions(
|
||||
cast.ToUint64(appOpts.Get(FlagPruningKeepRecent)),
|
||||
cast.ToUint64(appOpts.Get(FlagPruningKeepEvery)),
|
||||
cast.ToUint64(appOpts.Get(FlagPruningInterval)),
|
||||
)
|
||||
|
||||
|
||||
@ -31,14 +31,12 @@ func TestGetPruningOptionsFromFlags(t *testing.T) {
|
||||
v := viper.New()
|
||||
v.Set(FlagPruning, types.PruningOptionCustom)
|
||||
v.Set(FlagPruningKeepRecent, 1234)
|
||||
v.Set(FlagPruningKeepEvery, 4321)
|
||||
v.Set(FlagPruningInterval, 10)
|
||||
|
||||
return v
|
||||
},
|
||||
expectedOptions: types.PruningOptions{
|
||||
KeepRecent: 1234,
|
||||
KeepEvery: 4321,
|
||||
Interval: 10,
|
||||
},
|
||||
},
|
||||
|
||||
@ -48,7 +48,6 @@ const (
|
||||
|
||||
FlagPruning = "pruning"
|
||||
FlagPruningKeepRecent = "pruning-keep-recent"
|
||||
FlagPruningKeepEvery = "pruning-keep-every"
|
||||
FlagPruningInterval = "pruning-interval"
|
||||
FlagIndexEvents = "index-events"
|
||||
FlagMinRetainBlocks = "min-retain-blocks"
|
||||
@ -77,15 +76,15 @@ func StartCmd(appCreator types.AppCreator, defaultNodeHome string) *cobra.Comman
|
||||
Long: `Run the full node application with Tendermint in or out of process. By
|
||||
default, the application will run with Tendermint in process.
|
||||
|
||||
Pruning options can be provided via the '--pruning' flag or alternatively with '--pruning-keep-recent',
|
||||
'pruning-keep-every', and 'pruning-interval' together.
|
||||
Pruning options can be provided via the '--pruning' flag or alternatively with '--pruning-keep-recent'
|
||||
and 'pruning-interval' together.
|
||||
|
||||
For '--pruning' the options are as follows:
|
||||
|
||||
default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
|
||||
default: the last 362880 states are kept, pruning at 10 block intervals
|
||||
nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
everything: all saved states will be deleted, storing only the current state; pruning at 10 block intervals
|
||||
custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
|
||||
custom: allow pruning options to be manually specified through 'pruning-keep-recent' and 'pruning-interval'
|
||||
|
||||
Node halting configurations exist in the form of two flags: '--halt-height' and '--halt-time'. During
|
||||
the ABCI Commit phase, the node will check if the current block height is greater than or equal to
|
||||
@ -147,7 +146,6 @@ which accepts a path for the resulting pprof file.
|
||||
cmd.Flags().Bool(FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
|
||||
cmd.Flags().String(FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
|
||||
cmd.Flags().Uint64(FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint64(FlagPruningKeepEvery, 0, "Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint64(FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
|
||||
cmd.Flags().Uint(FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
|
||||
cmd.Flags().Uint64(FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
|
||||
|
||||
@ -28,9 +28,7 @@ filesystem under `<node_home>/data/snapshots/`, with metadata in a LevelDB datab
|
||||
|
||||
Snapshots are taken asynchronously, i.e. new blocks will be applied concurrently
|
||||
with snapshots being taken. This is possible because IAVL supports querying
|
||||
immutable historical heights. However, this requires `state-sync.snapshot-interval`
|
||||
to be a multiple of `pruning-keep-every`, to prevent a height from being removed
|
||||
while it is being snapshotted.
|
||||
immutable historical heights.
|
||||
|
||||
When a remote node is state syncing, Tendermint calls the ABCI method
|
||||
`ListSnapshots` to list available local snapshots and `LoadSnapshotChunk` to
|
||||
|
||||
@ -428,14 +428,7 @@ func (rs *Store) Commit() types.CommitID {
|
||||
// be pruned, where pruneHeight = (commitHeight - 1) - KeepRecent.
|
||||
if int64(rs.pruningOpts.KeepRecent) < previousHeight {
|
||||
pruneHeight := previousHeight - int64(rs.pruningOpts.KeepRecent)
|
||||
// We consider this height to be pruned iff:
|
||||
//
|
||||
// - KeepEvery is zero as that means that all heights should be pruned.
|
||||
// - KeepEvery % (height - KeepRecent) != 0 as that means the height is not
|
||||
// a 'snapshot' height.
|
||||
if rs.pruningOpts.KeepEvery == 0 || pruneHeight%int64(rs.pruningOpts.KeepEvery) != 0 {
|
||||
rs.pruneHeights = append(rs.pruneHeights, pruneHeight)
|
||||
}
|
||||
rs.pruneHeights = append(rs.pruneHeights, pruneHeight)
|
||||
}
|
||||
|
||||
// batch prune if the current height is a pruning interval height
|
||||
|
||||
@ -329,7 +329,6 @@ func TestMultiStoreRestart(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
pruning := types.PruningOptions{
|
||||
KeepRecent: 2,
|
||||
KeepEvery: 3,
|
||||
Interval: 1,
|
||||
}
|
||||
multi := newMultiStoreWithMounts(db, pruning)
|
||||
@ -488,9 +487,9 @@ func TestMultiStore_Pruning(t *testing.T) {
|
||||
}{
|
||||
{"prune nothing", 10, types.PruneNothing, nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
|
||||
{"prune everything", 10, types.PruneEverything, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9}, []int64{10}},
|
||||
{"prune some; no batch", 10, types.NewPruningOptions(2, 3, 1), []int64{1, 2, 4, 5, 7}, []int64{3, 6, 8, 9, 10}},
|
||||
{"prune some; small batch", 10, types.NewPruningOptions(2, 3, 3), []int64{1, 2, 4, 5}, []int64{3, 6, 7, 8, 9, 10}},
|
||||
{"prune some; large batch", 10, types.NewPruningOptions(2, 3, 11), nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
|
||||
{"prune some; no batch", 10, types.NewPruningOptions(2, 1), []int64{1, 2, 4, 5, 7}, []int64{3, 6, 8, 9, 10}},
|
||||
{"prune some; small batch", 10, types.NewPruningOptions(2, 3), []int64{1, 2, 4, 5}, []int64{3, 6, 7, 8, 9, 10}},
|
||||
{"prune some; large batch", 10, types.NewPruningOptions(2, 11), nil, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@ -520,7 +519,7 @@ func TestMultiStore_Pruning(t *testing.T) {
|
||||
|
||||
func TestMultiStore_PruningRestart(t *testing.T) {
|
||||
db := dbm.NewMemDB()
|
||||
ms := newMultiStoreWithMounts(db, types.NewPruningOptions(2, 3, 11))
|
||||
ms := newMultiStoreWithMounts(db, types.NewPruningOptions(2, 11))
|
||||
require.NoError(t, ms.LoadLatestVersion())
|
||||
|
||||
// Commit enough to build up heights to prune, where on the next block we should
|
||||
@ -534,13 +533,13 @@ func TestMultiStore_PruningRestart(t *testing.T) {
|
||||
// ensure we've persisted the current batch of heights to prune to the store's DB
|
||||
ph, err := getPruningHeights(ms.db)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, pruneHeights, ph)
|
||||
require.Equal(t, []int64{1, 2, 3, 4, 5, 6, 7}, ph)
|
||||
|
||||
// "restart"
|
||||
ms = newMultiStoreWithMounts(db, types.NewPruningOptions(2, 3, 11))
|
||||
ms = newMultiStoreWithMounts(db, types.NewPruningOptions(2, 11))
|
||||
err = ms.LoadLatestVersion()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, pruneHeights, ms.pruneHeights)
|
||||
require.Equal(t, []int64{1, 2, 3, 4, 5, 6, 7}, ms.pruneHeights)
|
||||
|
||||
// commit one more block and ensure the heights have been pruned
|
||||
ms.Commit()
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package types
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Pruning option string constants
|
||||
const (
|
||||
@ -16,15 +18,15 @@ var (
|
||||
// at every 10th height. The last 362880 heights are kept assuming the typical
|
||||
// block time is 5s and typical unbonding period is 21 days. If these values
|
||||
// do not match the applications' requirements, use the "custom" option.
|
||||
PruneDefault = NewPruningOptions(362880, 100, 10)
|
||||
PruneDefault = NewPruningOptions(362880, 10)
|
||||
|
||||
// PruneEverything defines a pruning strategy where all committed heights are
|
||||
// deleted, storing only the current height and where to-be pruned heights are
|
||||
// pruned at every 10th height.
|
||||
PruneEverything = NewPruningOptions(0, 0, 10)
|
||||
PruneEverything = NewPruningOptions(0, 10)
|
||||
|
||||
// PruneNothing defines a pruning strategy where all heights are kept on disk.
|
||||
PruneNothing = NewPruningOptions(0, 1, 0)
|
||||
PruneNothing = NewPruningOptions(0, 0)
|
||||
)
|
||||
|
||||
// PruningOptions defines the pruning strategy used when determining which
|
||||
@ -33,30 +35,20 @@ type PruningOptions struct {
|
||||
// KeepRecent defines how many recent heights to keep on disk.
|
||||
KeepRecent uint64
|
||||
|
||||
// KeepEvery defines how many offset heights are kept on disk past KeepRecent.
|
||||
KeepEvery uint64
|
||||
|
||||
// Interval defines when the pruned heights are removed from disk.
|
||||
Interval uint64
|
||||
}
|
||||
|
||||
func NewPruningOptions(keepRecent, keepEvery, interval uint64) PruningOptions {
|
||||
func NewPruningOptions(keepRecent, interval uint64) PruningOptions {
|
||||
return PruningOptions{
|
||||
KeepRecent: keepRecent,
|
||||
KeepEvery: keepEvery,
|
||||
Interval: interval,
|
||||
}
|
||||
}
|
||||
|
||||
func (po PruningOptions) Validate() error {
|
||||
if po.KeepEvery == 0 && po.Interval == 0 {
|
||||
return fmt.Errorf("invalid 'Interval' when pruning everything: %d", po.Interval)
|
||||
}
|
||||
if po.KeepEvery == 1 && po.Interval != 0 { // prune nothing
|
||||
return fmt.Errorf("invalid 'Interval' when pruning nothing: %d", po.Interval)
|
||||
}
|
||||
if po.KeepEvery > 1 && po.Interval == 0 {
|
||||
return fmt.Errorf("invalid 'Interval' when pruning: %d", po.Interval)
|
||||
if po.KeepRecent > 0 && po.Interval == 0 {
|
||||
return fmt.Errorf("invalid 'Interval' when pruning recent heights: %d", po.Interval)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -9,20 +9,17 @@ import (
|
||||
func TestPruningOptions_Validate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
keepRecent uint64
|
||||
keepEvery uint64
|
||||
interval uint64
|
||||
expectErr bool
|
||||
}{
|
||||
{100, 500, 10, false}, // default
|
||||
{0, 0, 10, false}, // everything
|
||||
{0, 1, 0, false}, // nothing
|
||||
{0, 10, 10, false},
|
||||
{100, 0, 0, true}, // invalid interval
|
||||
{0, 1, 5, true}, // invalid interval
|
||||
{100, 10, false}, // default
|
||||
{0, 10, false}, // everything
|
||||
{0, 0, false}, // nothing
|
||||
{100, 0, true}, // invalid interval
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
po := NewPruningOptions(tc.keepRecent, tc.keepEvery, tc.interval)
|
||||
po := NewPruningOptions(tc.keepRecent, tc.interval)
|
||||
err := po.Validate()
|
||||
require.Equal(t, tc.expectErr, err != nil, "options: %v, err: %s", po, err)
|
||||
}
|
||||
|
||||
@ -521,35 +521,40 @@ func (s *Store) Commit() types.CommitID {
|
||||
// Substores read-lock this mutex; lock to prevent racey invalidation of underlying txns
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
// Determine the target version
|
||||
versions, err := s.stateDB.Versions()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
target := versions.Last() + 1
|
||||
if target > math.MaxInt64 {
|
||||
panic(ErrMaximumHeight)
|
||||
}
|
||||
|
||||
// Fast forward to initial version if needed
|
||||
if s.InitialVersion != 0 && target < s.InitialVersion {
|
||||
target = s.InitialVersion
|
||||
}
|
||||
|
||||
cid, err := s.commit(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Prune if necessary
|
||||
previous := cid.Version - 1
|
||||
if s.Pruning.KeepEvery != 1 && s.Pruning.Interval != 0 && cid.Version%int64(s.Pruning.Interval) == 0 {
|
||||
if s.Pruning.Interval != 0 && cid.Version%int64(s.Pruning.Interval) == 0 {
|
||||
// The range of newly prunable versions
|
||||
lastPrunable := previous - int64(s.Pruning.KeepRecent)
|
||||
firstPrunable := lastPrunable - int64(s.Pruning.Interval)
|
||||
|
||||
for version := firstPrunable; version <= lastPrunable; version++ {
|
||||
if s.Pruning.KeepEvery == 0 || version%int64(s.Pruning.KeepEvery) != 0 {
|
||||
s.stateDB.DeleteVersion(uint64(version))
|
||||
if s.StateCommitmentDB != nil {
|
||||
s.StateCommitmentDB.DeleteVersion(uint64(version))
|
||||
}
|
||||
s.stateDB.DeleteVersion(uint64(version))
|
||||
|
||||
if s.StateCommitmentDB != nil {
|
||||
s.StateCommitmentDB.DeleteVersion(uint64(version))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,8 +398,8 @@ func TestPruning(t *testing.T) {
|
||||
types.PruningOptions
|
||||
kept []uint64
|
||||
}{
|
||||
{types.PruningOptions{2, 4, 10}, []uint64{4, 8, 9, 10}},
|
||||
{types.PruningOptions{0, 4, 10}, []uint64{4, 8, 10}},
|
||||
{types.PruningOptions{2, 10}, []uint64{8, 9, 10}},
|
||||
{types.PruningOptions{0, 10}, []uint64{10}},
|
||||
{types.PruneEverything, []uint64{10}},
|
||||
{types.PruneNothing, []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
|
||||
}
|
||||
@ -423,6 +423,7 @@ func TestPruning(t *testing.T) {
|
||||
for _, db := range dbs {
|
||||
versions, err := db.Versions()
|
||||
require.NoError(t, err)
|
||||
|
||||
kept := sliceToSet(tc.kept)
|
||||
for v := uint64(1); v <= 10; v++ {
|
||||
_, has := kept[v]
|
||||
@ -434,19 +435,21 @@ func TestPruning(t *testing.T) {
|
||||
// Test pruning interval
|
||||
// Save up to 20th version while checking history at specific version checkpoints
|
||||
testCheckPoints := map[uint64][]uint64{
|
||||
5: []uint64{1, 2, 3, 4, 5},
|
||||
10: []uint64{5, 10},
|
||||
15: []uint64{5, 10, 11, 12, 13, 14, 15},
|
||||
20: []uint64{5, 10, 15, 20},
|
||||
5: {1, 2, 3, 4, 5},
|
||||
10: {10},
|
||||
15: {10, 11, 12, 13, 14, 15},
|
||||
20: {20},
|
||||
}
|
||||
|
||||
db := memdb.NewDB()
|
||||
opts := simpleStoreConfig(t)
|
||||
opts.Pruning = types.PruningOptions{0, 5, 10}
|
||||
opts.Pruning = types.PruningOptions{0, 10}
|
||||
store, err := NewStore(db, opts)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := byte(1); i <= 20; i++ {
|
||||
store.GetKVStore(skey_1).Set([]byte{i}, []byte{i})
|
||||
|
||||
cid := store.Commit()
|
||||
latest := uint64(i)
|
||||
require.Equal(t, latest, uint64(cid.Version))
|
||||
@ -455,8 +458,10 @@ func TestPruning(t *testing.T) {
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
||||
versions, err := db.Versions()
|
||||
require.NoError(t, err)
|
||||
|
||||
keptMap := sliceToSet(kept)
|
||||
for v := uint64(1); v <= latest; v++ {
|
||||
_, has := keptMap[v]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user