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

Problem: memiavl more efficient snapshot setup is not used #1067

Merged
merged 13 commits into from
Jun 19, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
- [#1035](https://github.com/crypto-org-chain/cronos/pull/1035) Support caching in memiavl directly, ignore inter-block cache silently.
- [#1050](https://github.com/crypto-org-chain/cronos/pull/1050) nativebyteorder mode will check endianness on startup, binaries are built with nativebyteorder by default.
- [#1064](https://github.com/crypto-org-chain/cronos/pull/1064) Simplify memiavl snapshot switching.
- [#]() memiavl: only export state-sync snapshots on an exist snapshot
yihuang marked this conversation as resolved.
Show resolved Hide resolved

*April 13, 2023*

Expand Down
24 changes: 15 additions & 9 deletions app/memiavl.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/cosmos/cosmos-sdk/baseapp"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
storetypes "github.com/cosmos/cosmos-sdk/store/types"

"github.com/crypto-org-chain/cronos/memiavl"
"github.com/crypto-org-chain/cronos/store/rootmulti"
Expand All @@ -25,22 +24,29 @@ const (

func SetupMemIAVL(logger log.Logger, homePath string, appOpts servertypes.AppOptions, baseAppOptions []func(*baseapp.BaseApp)) []func(*baseapp.BaseApp) {
if cast.ToBool(appOpts.Get(FlagMemIAVL)) {
// cms must be overridden before the other options, because they may use the cms,
// make sure the cms aren't be overridden by the other options later on.
cms := rootmulti.NewStore(filepath.Join(homePath, "data", "memiavl.db"), logger)
cms.SetMemIAVLOptions(memiavl.Options{
opts := memiavl.Options{
AsyncCommitBuffer: cast.ToInt(appOpts.Get(FlagAsyncCommitBuffer)),
ZeroCopy: cast.ToBool(appOpts.Get(FlagZeroCopy)),
SnapshotKeepRecent: cast.ToUint32(appOpts.Get(FlagSnapshotKeepRecent)),
SnapshotInterval: cast.ToUint32(appOpts.Get(FlagSnapshotInterval)),
CacheSize: cast.ToInt(appOpts.Get(FlagCacheSize)),
})
baseAppOptions = append([]func(*baseapp.BaseApp){setCMS(cms)}, baseAppOptions...)
}
// cms must be overridden before the other options, because they may use the cms,
// make sure the cms aren't be overridden by the other options later on.
baseAppOptions = append([]func(*baseapp.BaseApp){setMemIAVL(homePath, logger, opts)}, baseAppOptions...)
}

return baseAppOptions
}

func setCMS(cms storetypes.CommitMultiStore) func(*baseapp.BaseApp) {
return func(bapp *baseapp.BaseApp) { bapp.SetCMS(cms) }
func setMemIAVL(homePath string, logger log.Logger, opts memiavl.Options) func(*baseapp.BaseApp) {
return func(bapp *baseapp.BaseApp) {
// trigger state-sync snapshot creation by memiavl
opts.TriggerStateSyncExport = func(height int64) {
go bapp.SnapshotManager().SnapshotIfApplicable(height)
}
cms := rootmulti.NewStore(filepath.Join(homePath, "data", "memiavl.db"), logger)
cms.SetMemIAVLOptions(opts)
bapp.SetCMS(cms)
}
}
31 changes: 24 additions & 7 deletions memiavl/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ type DB struct {
snapshotInterval uint32
// make sure only one snapshot rewrite is running
pruneSnapshotLock sync.Mutex
// it's more efficient to export snapshot versions, so we only support that by default
supportExportNonSnapshotVersion bool
triggerStateSyncExport func(height int64)

// invariant: the LastIndex always match the current version of MultiTree
wal *wal.Log
Expand Down Expand Up @@ -73,6 +76,9 @@ type Options struct {
InitialStores []string
SnapshotKeepRecent uint32
SnapshotInterval uint32
// it's more efficient to export snapshot versions, we can filter out the non-snapshot versions
SupportExportNonSnapshotVersion bool
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
TriggerStateSyncExport func(height int64)
// load the target version instead of latest version
TargetVersion uint32
// Buffer size for the asynchronous commit queue, -1 means synchronous commit,
Expand Down Expand Up @@ -135,13 +141,15 @@ func Load(dir string, opts Options) (*DB, error) {
}

db := &DB{
MultiTree: *mtree,
logger: opts.Logger,
dir: dir,
wal: wal,
walChanSize: opts.AsyncCommitBuffer,
snapshotKeepRecent: opts.SnapshotKeepRecent,
snapshotInterval: opts.SnapshotInterval,
MultiTree: *mtree,
logger: opts.Logger,
dir: dir,
wal: wal,
walChanSize: opts.AsyncCommitBuffer,
snapshotKeepRecent: opts.SnapshotKeepRecent,
snapshotInterval: opts.SnapshotInterval,
supportExportNonSnapshotVersion: opts.SupportExportNonSnapshotVersion,
triggerStateSyncExport: opts.TriggerStateSyncExport,
}

if db.logger == nil {
Expand Down Expand Up @@ -242,6 +250,11 @@ func (db *DB) checkBackgroundSnapshotRewrite() error {
db.logger.Info("switched to new snapshot", "version", db.MultiTree.Version())

db.pruneSnapshots()

// trigger state-sync snapshot export
if db.triggerStateSyncExport != nil {
db.triggerStateSyncExport(db.SnapshotVersion())
}
default:
}

Expand Down Expand Up @@ -609,6 +622,10 @@ func currentPath(root string) string {
return filepath.Join(root, "current")
}

func snapshotPath(root string, version uint32) string {
return filepath.Join(root, snapshotName(version))
}

func currentTmpPath(root string) string {
return filepath.Join(root, "current-tmp")
}
Expand Down
26 changes: 20 additions & 6 deletions memiavl/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,27 @@ func (db *DB) Snapshot(height uint64, protoWriter protoio.Writer) error {
if height > math.MaxUint32 {
return fmt.Errorf("height overflows uint32: %d", height)
}
version := uint32(height)
Fixed Show fixed Hide fixed

Check failure

Code scanning / gosec

Potential integer overflow by integer type conversion

Potential integer overflow by integer type conversion

mtree, err := Load(db.dir, Options{
TargetVersion: uint32(height),
ZeroCopy: true,
})
if err != nil {
return errors.Wrapf(err, "invalid snapshot height: %d", height)
var (
mtree *MultiTree
err error
)
if db.supportExportNonSnapshotVersion {
db, err := Load(db.dir, Options{
TargetVersion: version,
ZeroCopy: true,
})
if err != nil {
return errors.Wrapf(err, "invalid height: %d", height)
}

mtree = &db.MultiTree
} else {
mtree, err = LoadMultiTree(snapshotPath(db.dir, version), true, 0)
if err != nil {
return errors.Wrapf(err, "invalid snapshot height: %d", height)
}
}

for _, tree := range mtree.trees {
Expand Down