Merge PR #5500: Regen network/multistore upgrades

This commit is contained in:
Anil Kumar Kammari
2020-02-27 22:26:04 -08:00
committed by GitHub
parent de0f1a9e40
commit 0b7449129a
19 changed files with 351 additions and 130 deletions
-60
View File
@@ -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 {
-50
View File
@@ -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) {