Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Configurable pruning #3195

Merged
merged 2 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ BREAKING CHANGES
* [stake] \#2513 Validator power type from Dec -> Int
* [stake] \#3233 key and value now contain duplicate fields to simplify code
* [\#3064](https://github.com/cosmos/cosmos-sdk/issues/3064) Sanitize `sdk.Coin` denom. Coins denoms are now case insensitive, i.e. 100fooToken equals to 100FOOTOKEN.
* [\#3195](https://github.com/cosmos/cosmos-sdk/issues/3195) Allows custom configuration for syncable strategy
* [\#3242](https://github.com/cosmos/cosmos-sdk/issues/3242) Fix infinite gas
meter utilization during aborted ante handler executions.

* Tendermint


Expand Down
8 changes: 5 additions & 3 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"github.com/cosmos/cosmos-sdk/store"
"os"
"testing"

Expand Down Expand Up @@ -85,9 +86,10 @@ func TestMountStores(t *testing.T) {
// Test that LoadLatestVersion actually does.
func TestLoadVersion(t *testing.T) {
logger := defaultLogger()
pruningOpt := SetPruning(store.PruneSyncable)
db := dbm.NewMemDB()
name := t.Name()
app := NewBaseApp(name, logger, db, nil)
app := NewBaseApp(name, logger, db, nil, pruningOpt)

// make a cap key and mount the store
capKey := sdk.NewKVStoreKey(MainStoreKey)
Expand Down Expand Up @@ -116,15 +118,15 @@ func TestLoadVersion(t *testing.T) {
commitID2 := sdk.CommitID{2, res.Data}

// reload with LoadLatestVersion
app = NewBaseApp(name, logger, db, nil)
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadLatestVersion(capKey)
require.Nil(t, err)
testLoadVersionHelper(t, app, int64(2), commitID2)

// reload with LoadVersion, see if you can commit the same block and get
// the same result
app = NewBaseApp(name, logger, db, nil)
app = NewBaseApp(name, logger, db, nil, pruningOpt)
app.MountStores(capKey)
err = app.LoadVersion(1, capKey)
require.Nil(t, err)
Expand Down
17 changes: 2 additions & 15 deletions baseapp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,8 @@ import (
// for options that need access to non-exported fields of the BaseApp

// SetPruning sets a pruning option on the multistore associated with the app
func SetPruning(pruning string) func(*BaseApp) {
var pruningEnum sdk.PruningStrategy
switch pruning {
case "nothing":
pruningEnum = sdk.PruneNothing
case "everything":
pruningEnum = sdk.PruneEverything
case "syncable":
pruningEnum = sdk.PruneSyncable
default:
panic(fmt.Sprintf("invalid pruning strategy: %s", pruning))
}
return func(bap *BaseApp) {
bap.cms.SetPruning(pruningEnum)
}
func SetPruning(opts sdk.PruningOptions) func(*BaseApp) {
return func(bap *BaseApp) { bap.cms.SetPruning(opts) }
}

// SetMinimumFees returns an option that sets the minimum fees on the app.
Expand Down
3 changes: 2 additions & 1 deletion cmd/gaia/cmd/gaiad/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"encoding/json"
"github.com/cosmos/cosmos-sdk/store"
"io"

"github.com/cosmos/cosmos-sdk/baseapp"
Expand Down Expand Up @@ -56,7 +57,7 @@ func main() {

func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application {
return app.NewGaiaApp(logger, db, traceStore, true,
baseapp.SetPruning(viper.GetString("pruning")),
baseapp.SetPruning(store.NewPruningOptions(viper.GetString("pruning"))),
baseapp.SetMinimumFees(viper.GetString("minimum_fees")),
)
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/gaia/cmd/gaiadebug/hack.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"github.com/cosmos/cosmos-sdk/store"
"os"
"path"

Expand Down Expand Up @@ -48,7 +49,7 @@ func runHackCmd(cmd *cobra.Command, args []string) error {
fmt.Println(err)
os.Exit(1)
}
app := NewGaiaApp(logger, db, baseapp.SetPruning(viper.GetString("pruning")))
app := NewGaiaApp(logger, db, baseapp.SetPruning(store.NewPruningOptions(viper.GetString("pruning"))))

// print some info
id := app.LastCommitID()
Expand Down
3 changes: 2 additions & 1 deletion cmd/gaia/cmd/gaiareplay/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"github.com/cosmos/cosmos-sdk/store"
"io"
"os"
"path/filepath"
Expand Down Expand Up @@ -106,7 +107,7 @@ func run(rootDir string) {
fmt.Println("Creating application")
myapp := app.NewGaiaApp(
ctx.Logger, appDB, traceStoreWriter, true,
baseapp.SetPruning("everything"), // nothing
baseapp.SetPruning(store.PruneEverything), // nothing
)

// Genesis
Expand Down
3 changes: 2 additions & 1 deletion docs/examples/basecoin/cmd/basecoind/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"fmt"
"github.com/cosmos/cosmos-sdk/store"
"io"
"os"

Expand Down Expand Up @@ -122,7 +123,7 @@ func InitCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
}

func newApp(logger log.Logger, db dbm.DB, storeTracer io.Writer) abci.Application {
return app.NewBasecoinApp(logger, db, baseapp.SetPruning(viper.GetString("pruning")))
return app.NewBasecoinApp(logger, db, baseapp.SetPruning(store.NewPruningOptions(viper.GetString("pruning"))))
}

func exportAppStateAndTMValidators(logger log.Logger, db dbm.DB, storeTracer io.Writer, _ int64, _ bool) (
Expand Down
2 changes: 1 addition & 1 deletion server/mock/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (ms multiStore) LastCommitID() sdk.CommitID {
panic("not implemented")
}

func (ms multiStore) SetPruning(s sdk.PruningStrategy) {
func (ms multiStore) SetPruning(opts sdk.PruningOptions) {
panic("not implemented")
}

Expand Down
2 changes: 1 addition & 1 deletion store/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
// Import cosmos-sdk/types/store.go for convenience.
// nolint
type (
PruningStrategy = types.PruningStrategy
PruningOptions = types.PruningOptions
Store = types.Store
Committer = types.Committer
CommitStore = types.CommitStore
Expand Down
2 changes: 1 addition & 1 deletion store/dbstoreadapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ func (cdsa commitDBStoreAdapter) LastCommitID() CommitID {
}
}

func (cdsa commitDBStoreAdapter) SetPruning(_ PruningStrategy) {}
func (cdsa commitDBStoreAdapter) SetPruning(_ PruningOptions) {}
17 changes: 4 additions & 13 deletions store/iavlstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const (
)

// load the iavl store
func LoadIAVLStore(db dbm.DB, id CommitID, pruning sdk.PruningStrategy) (CommitStore, error) {
func LoadIAVLStore(db dbm.DB, id CommitID, pruning sdk.PruningOptions) (CommitStore, error) {
tree := iavl.NewMutableTree(db, defaultIAVLCacheSize)
_, err := tree.LoadVersion(id.Version)
if err != nil {
Expand All @@ -38,7 +38,6 @@ var _ Queryable = (*iavlStore)(nil)

// iavlStore Implements KVStore and CommitStore.
type iavlStore struct {

// The underlying tree.
tree *iavl.MutableTree

Expand Down Expand Up @@ -102,17 +101,9 @@ func (st *iavlStore) LastCommitID() CommitID {
}

// Implements Committer.
func (st *iavlStore) SetPruning(pruning sdk.PruningStrategy) {
switch pruning {
case sdk.PruneEverything:
st.numRecent = 0
st.storeEvery = 0
case sdk.PruneNothing:
st.storeEvery = 1
case sdk.PruneSyncable:
st.numRecent = 100
st.storeEvery = 10000
}
func (st *iavlStore) SetPruning(opt sdk.PruningOptions) {
st.numRecent = opt.KeepRecent()
st.storeEvery = opt.KeepEvery()
}

// VersionExists returns whether or not a given version is stored.
Expand Down
2 changes: 1 addition & 1 deletion store/multistoreproof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func TestVerifyIAVLStoreQueryProof(t *testing.T) {
// Create main tree for testing.
db := dbm.NewMemDB()
iStore, err := LoadIAVLStore(db, CommitID{}, sdk.PruneNothing)
iStore, err := LoadIAVLStore(db, CommitID{}, PruneNothing)
store := iStore.(*iavlStore)
require.Nil(t, err)
store.Set([]byte("MYKEY"), []byte("MYVALUE"))
Expand Down
29 changes: 29 additions & 0 deletions store/pruning.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package store

import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// default pruning strategies
var (
// PruneEverything means all saved states will be deleted, storing only the current state
PruneEverything = sdk.NewPruningOptions(0, 0)
// PruneNothing means all historic states will be saved, nothing will be deleted
PruneNothing = sdk.NewPruningOptions(0, 1)
// PruneSyncable means only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th)
PruneSyncable = sdk.NewPruningOptions(100, 10000)
)

func NewPruningOptions(strategy string) (opt PruningOptions) {
switch strategy {
case "nothing":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be constants defined in this file and used everywhere NewPruningOptions is called imho.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need this method to parse viper flag value. To be able to change default pruning options, baseapp should take not just strategy, but options itself. So we can't just pass strategy to ** baseapp**. Maybe I miss something?
Btw, I open PruneEverything, PruneNothing, PruneSyncable and change tests to use them, instead of this method.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is OK for now.

opt = PruneNothing
case "everything":
opt = PruneEverything
case "syncable":
opt = PruneSyncable
default:
opt = PruneSyncable
}
return
}
10 changes: 5 additions & 5 deletions store/rootmultistore.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (
type rootMultiStore struct {
db dbm.DB
lastCommitID CommitID
pruning sdk.PruningStrategy
pruningOpts sdk.PruningOptions
storesParams map[StoreKey]storeParams
stores map[StoreKey]CommitStore
keysByName map[string]StoreKey
Expand All @@ -47,10 +47,10 @@ func NewCommitMultiStore(db dbm.DB) *rootMultiStore {
}

// Implements CommitMultiStore
func (rs *rootMultiStore) SetPruning(pruning sdk.PruningStrategy) {
rs.pruning = pruning
func (rs *rootMultiStore) SetPruning(pruningOpts sdk.PruningOptions) {
rs.pruningOpts = pruningOpts
for _, substore := range rs.stores {
substore.SetPruning(pruning)
substore.SetPruning(pruningOpts)
}
}

Expand Down Expand Up @@ -355,7 +355,7 @@ func (rs *rootMultiStore) loadCommitStoreFromParams(key sdk.StoreKey, id CommitI
// TODO: id?
// return NewCommitMultiStore(db, id)
case sdk.StoreTypeIAVL:
store, err = LoadIAVLStore(db, id, rs.pruning)
store, err = LoadIAVLStore(db, id, rs.pruningOpts)
return
case sdk.StoreTypeDB:
store = commitDBStoreAdapter{dbStoreAdapter{db}}
Expand Down
1 change: 1 addition & 0 deletions store/rootmultistore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ func TestMultiStoreQuery(t *testing.T) {

func newMultiStoreWithMounts(db dbm.DB) *rootMultiStore {
store := NewCommitMultiStore(db)
store.pruningOpts = PruneSyncable
store.MountStoreWithDB(
sdk.NewKVStoreKey("store1"), sdk.StoreTypeIAVL, nil)
store.MountStoreWithDB(
Expand Down
2 changes: 1 addition & 1 deletion store/transientstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (ts *transientStore) Commit() (id CommitID) {
}

// Implements CommitStore
func (ts *transientStore) SetPruning(pruning PruningStrategy) {
func (ts *transientStore) SetPruning(opts PruningOptions) {
}

// Implements CommitStore
Expand Down
32 changes: 21 additions & 11 deletions types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,29 @@ import (

// NOTE: These are implemented in cosmos-sdk/store.

// PruningStrategy specfies how old states will be deleted over time
type PruningStrategy uint8
// PruningStrategy specifies how old states will be deleted over time where
// keepRecent can be used with keepEvery to create a pruning "strategy".
type PruningOptions struct {
keepRecent int64
keepEvery int64
}

const (
// PruneSyncable means only those states not needed for state syncing will be deleted (keeps last 100 + every 10000th)
PruneSyncable PruningStrategy = iota
func NewPruningOptions(keepRecent, keepEvery int64) PruningOptions {
return PruningOptions{
keepRecent: keepRecent,
keepEvery: keepEvery,
}
}

// PruneEverything means all saved states will be deleted, storing only the current state
PruneEverything PruningStrategy = iota
// How much recent state will be kept. Older state will be deleted.
func (po PruningOptions) KeepRecent() int64 {
return po.keepRecent
}

// PruneNothing means all historic states will be saved, nothing will be deleted
PruneNothing PruningStrategy = iota
)
// Keeps every N stated, deleting others.
func (po PruningOptions) KeepEvery() int64 {
return po.keepEvery
}

type Store interface { //nolint
GetStoreType() StoreType
Expand All @@ -35,7 +45,7 @@ type Store interface { //nolint
type Committer interface {
Commit() CommitID
LastCommitID() CommitID
SetPruning(PruningStrategy)
SetPruning(PruningOptions)
}

// Stores of MultiStore must implement CommitStore.
Expand Down