Merge PR #5500: Regen network/multistore upgrades
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
package baseapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
@@ -17,7 +14,6 @@ import (
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
@@ -226,62 +222,6 @@ func DefaultStoreLoader(ms sdk.CommitMultiStore) error {
|
||||
return ms.LoadLatestVersion()
|
||||
}
|
||||
|
||||
// StoreLoaderWithUpgrade is used to prepare baseapp with a fixed StoreLoader
|
||||
// pattern. This is useful in test cases, or with custom upgrade loading logic.
|
||||
func StoreLoaderWithUpgrade(upgrades *storetypes.StoreUpgrades) StoreLoader {
|
||||
return func(ms sdk.CommitMultiStore) error {
|
||||
return ms.LoadLatestVersionAndUpgrade(upgrades)
|
||||
}
|
||||
}
|
||||
|
||||
// UpgradeableStoreLoader can be configured by SetStoreLoader() to check for the
|
||||
// existence of a given upgrade file - json encoded StoreUpgrades data.
|
||||
//
|
||||
// If not file is present, it will peform the default load (no upgrades to store).
|
||||
//
|
||||
// If the file is present, it will parse the file and execute those upgrades
|
||||
// (rename or delete stores), while loading the data. It will also delete the
|
||||
// upgrade file upon successful load, so that the upgrade is only applied once,
|
||||
// and not re-applied on next restart
|
||||
//
|
||||
// This is useful for in place migrations when a store key is renamed between
|
||||
// two versions of the software. (TODO: this code will move to x/upgrades
|
||||
// when PR #4233 is merged, here mainly to help test the design)
|
||||
func UpgradeableStoreLoader(upgradeInfoPath string) StoreLoader {
|
||||
return func(ms sdk.CommitMultiStore) error {
|
||||
_, err := os.Stat(upgradeInfoPath)
|
||||
if os.IsNotExist(err) {
|
||||
return DefaultStoreLoader(ms)
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// there is a migration file, let's execute
|
||||
data, err := ioutil.ReadFile(upgradeInfoPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read upgrade file %s: %v", upgradeInfoPath, err)
|
||||
}
|
||||
|
||||
var upgrades storetypes.StoreUpgrades
|
||||
err = json.Unmarshal(data, &upgrades)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse upgrade file: %v", err)
|
||||
}
|
||||
|
||||
err = ms.LoadLatestVersionAndUpgrade(&upgrades)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load and upgrade database: %v", err)
|
||||
}
|
||||
|
||||
// if we have a successful load, we delete the file
|
||||
err = os.Remove(upgradeInfoPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("deleting upgrade file %s: %v", upgradeInfoPath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// LoadVersion loads the BaseApp application version. It will panic if called
|
||||
// more than once on a running baseapp.
|
||||
func (app *BaseApp) LoadVersion(version int64, baseKey *sdk.KVStoreKey) error {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -137,18 +136,6 @@ func useDefaultLoader(app *BaseApp) {
|
||||
app.SetStoreLoader(DefaultStoreLoader)
|
||||
}
|
||||
|
||||
func useUpgradeLoader(upgrades *store.StoreUpgrades) func(*BaseApp) {
|
||||
return func(app *BaseApp) {
|
||||
app.SetStoreLoader(StoreLoaderWithUpgrade(upgrades))
|
||||
}
|
||||
}
|
||||
|
||||
func useFileUpgradeLoader(upgradeInfoPath string) func(*BaseApp) {
|
||||
return func(app *BaseApp) {
|
||||
app.SetStoreLoader(UpgradeableStoreLoader(upgradeInfoPath))
|
||||
}
|
||||
}
|
||||
|
||||
func initStore(t *testing.T, db dbm.DB, storeKey string, k, v []byte) {
|
||||
rs := rootmulti.NewStore(db)
|
||||
rs.SetPruning(store.PruneNothing)
|
||||
@@ -184,19 +171,6 @@ func checkStore(t *testing.T, db dbm.DB, ver int64, storeKey string, k, v []byte
|
||||
// Test that we can make commits and then reload old versions.
|
||||
// Test that LoadLatestVersion actually does.
|
||||
func TestSetLoader(t *testing.T) {
|
||||
// write a renamer to a file
|
||||
f, err := ioutil.TempFile("", "upgrade-*.json")
|
||||
require.NoError(t, err)
|
||||
data := []byte(`{"renamed":[{"old_key": "bnk", "new_key": "banker"}]}`)
|
||||
_, err = f.Write(data)
|
||||
require.NoError(t, err)
|
||||
configName := f.Name()
|
||||
require.NoError(t, f.Close())
|
||||
|
||||
// make sure it exists before running everything
|
||||
_, err = os.Stat(configName)
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := map[string]struct {
|
||||
setLoader func(*BaseApp)
|
||||
origStoreKey string
|
||||
@@ -211,26 +185,6 @@ func TestSetLoader(t *testing.T) {
|
||||
origStoreKey: "foo",
|
||||
loadStoreKey: "foo",
|
||||
},
|
||||
"rename with inline opts": {
|
||||
setLoader: useUpgradeLoader(&store.StoreUpgrades{
|
||||
Renamed: []store.StoreRename{{
|
||||
OldKey: "foo",
|
||||
NewKey: "bar",
|
||||
}},
|
||||
}),
|
||||
origStoreKey: "foo",
|
||||
loadStoreKey: "bar",
|
||||
},
|
||||
"file loader with missing file": {
|
||||
setLoader: useFileUpgradeLoader(configName + "randomchars"),
|
||||
origStoreKey: "bnk",
|
||||
loadStoreKey: "bnk",
|
||||
},
|
||||
"file loader with existing file": {
|
||||
setLoader: useFileUpgradeLoader(configName),
|
||||
origStoreKey: "bnk",
|
||||
loadStoreKey: "banker",
|
||||
},
|
||||
}
|
||||
|
||||
k := []byte("key")
|
||||
@@ -265,10 +219,6 @@ func TestSetLoader(t *testing.T) {
|
||||
checkStore(t, db, 2, tc.loadStoreKey, []byte("foo"), nil)
|
||||
})
|
||||
}
|
||||
|
||||
// ensure config file was deleted
|
||||
_, err = os.Stat(configName)
|
||||
require.True(t, os.IsNotExist(err))
|
||||
}
|
||||
|
||||
func TestAppVersionSetterGetter(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user