Skip to content

Commit

Permalink
Problem: versiondb migration don't support iavl v1
Browse files Browse the repository at this point in the history
fixes: #1389

Solution:
- fix changeset dump command
- restore-app-db still restore iavl v0 db, but since iavl v1 is backward
  compatible, so it's fine.

Update versiondb/client/dump.go

Signed-off-by: yihuang <[email protected]>
  • Loading branch information
yihuang committed Apr 16, 2024
1 parent 90fc8be commit b8f43e8
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 17 deletions.
2 changes: 0 additions & 2 deletions integration_tests/test_versiondb.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import shutil
import tempfile

import pytest
import tomlkit
from pystarport import ports

from .network import Cronos
from .utils import ADDRS, send_transaction, wait_for_port


@pytest.mark.skip(reason="versiondb migration don't support iavl v1 yet, TODO: #1389")
def test_versiondb_migration(cronos: Cronos):
"""
test versiondb migration commands.
Expand Down
54 changes: 41 additions & 13 deletions versiondb/client/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"compress/zlib"
"context"
"encoding/binary"
"fmt"
"io"
"math"
Expand Down Expand Up @@ -75,6 +76,10 @@ func DumpChangeSetCmd(opts Options) *cobra.Command {
if err := os.MkdirAll(outDir, os.ModePerm); err != nil {
return err
}
iavlVersion, err := cmd.Flags().GetInt(flagIAVLVersion)
if err != nil {
return err

Check warning on line 81 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L79-L81

Added lines #L79 - L81 were not covered by tests
}

if endVersion == 0 {
// use the latest version of the first store for all stores
Expand All @@ -98,7 +103,7 @@ func DumpChangeSetCmd(opts Options) *cobra.Command {

// find the first version in the db, reading raw db because no public api for it.
prefix := []byte(fmt.Sprintf(tsrocksdb.StorePrefixTpl, store))
storeStartVersion, err := getNextVersion(dbm.NewPrefixDB(db, prefix), 0)
storeStartVersion, err := getFirstVersion(dbm.NewPrefixDB(db, prefix), iavlVersion)

Check warning on line 106 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L106

Added line #L106 was not covered by tests
if err != nil {
return err
}
Expand Down Expand Up @@ -166,9 +171,11 @@ func DumpChangeSetCmd(opts Options) *cobra.Command {
cmd.Flags().Int(flagChunkSize, DefaultChunkSize, "size of the block chunk")
cmd.Flags().Int(flagZlibLevel, 6, "level of zlib compression, 0: plain data, 1: fast, 9: best, default: 6, if not 0 the output file name will have .zz extension")
cmd.Flags().String(flagStores, "", "list of store names, default to the current store list in application")
cmd.Flags().Int(flagIAVLVersion, IAVLV1, "IAVL version, 0: v0, 1: v1")

Check warning on line 174 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L174

Added line #L174 was not covered by tests
return cmd
}

// Range represents a range `[start, end)`
type Range struct {
Start, End int64
}
Expand Down Expand Up @@ -199,7 +206,8 @@ func dumpRangeBlocks(outputFile string, tree *iavl.ImmutableTree, blockRange Ran

writer := snappy.NewBufferedWriter(fp)

if err := tree.TraverseStateChanges(blockRange.Start, blockRange.End, func(version int64, changeSet *iavl.ChangeSet) error {
// TraverseStateChanges becomes inclusive on end since iavl `v1.x.x`, while the blockRange is exclusive on end
if err := tree.TraverseStateChanges(blockRange.Start, blockRange.End-1, func(version int64, changeSet *iavl.ChangeSet) error {

Check warning on line 210 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L210

Added line #L210 was not covered by tests
return WriteChangeSet(writer, version, changeSet)
}); err != nil {
return err
Expand Down Expand Up @@ -289,25 +297,45 @@ func createFile(name string) (*os.File, error) {
return os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
}

func getNextVersion(db dbm.DB, version int64) (int64, error) {
func getFirstVersion(db dbm.DB, iavlVersion int) (int64, error) {
if iavlVersion == IAVLV0 {
itr, err := db.Iterator(
rootKeyFormat.Key(uint64(1)),
rootKeyFormat.Key(uint64(math.MaxInt64)),
)
if err != nil {
return 0, err

Check warning on line 307 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L300-L307

Added lines #L300 - L307 were not covered by tests
}
defer itr.Close()

Check warning on line 309 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L309

Added line #L309 was not covered by tests

var version int64
for ; itr.Valid(); itr.Next() {

Check warning

Code scanning / CodeQL

Unreachable statement Warning

This statement is unreachable.
rootKeyFormat.Scan(itr.Key(), &version)
return version, nil

Check warning on line 314 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L311-L314

Added lines #L311 - L314 were not covered by tests
}

return 0, itr.Error()

Check warning on line 317 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L317

Added line #L317 was not covered by tests
}

itr, err := db.Iterator(
rootKeyFormat.Key(uint64(version+1)),
rootKeyFormat.Key(uint64(math.MaxInt64)),
nodeKeyV1Format.KeyInt64(1),
nodeKeyV1Format.KeyInt64(math.MaxInt64),

Check warning on line 322 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L321-L322

Added lines #L321 - L322 were not covered by tests
)
if err != nil {
return 0, err
}
defer itr.Close()

var nversion int64
for ; itr.Valid(); itr.Next() {
rootKeyFormat.Scan(itr.Key(), &nversion)
return nversion, nil
}

if err := itr.Error(); err != nil {
return 0, err
var nk []byte
nodeKeyV1Format.Scan(itr.Key(), &nk)
version := int64(binary.BigEndian.Uint64(nk))
nonce := binary.BigEndian.Uint32(nk[8:])
if nonce == 1 {

Check warning on line 334 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L330-L334

Added lines #L330 - L334 were not covered by tests
// root key is normal node key with nonce 1
return version, nil

Check warning on line 336 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L336

Added line #L336 was not covered by tests
}
}

return 0, nil
return 0, itr.Error()

Check warning on line 340 in versiondb/client/dump.go

View check run for this annotation

Codecov / codecov/patch

versiondb/client/dump.go#L340

Added line #L340 was not covered by tests
}
6 changes: 6 additions & 0 deletions versiondb/client/flags.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package client

const (
IAVLV0 = iota
IAVLV1
)

const (
flagStartVersion = "start-version"
flagEndVersion = "end-version"
Expand All @@ -21,4 +26,5 @@ const (
flagSorterChunkSize = "sorter-chunk-size"
flagInitialVersion = "initial-version"
flagSDK64Compact = "sdk64-compact"
flagIAVLVersion = "iavl-version"
)
6 changes: 4 additions & 2 deletions versiondb/client/restore_app_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

const (
int64Size = 8
int32Size = 4

storeKeyPrefix = "s/k:%s/"
latestVersionKey = "s/latest"
Expand All @@ -41,8 +42,9 @@ const (
)

var (
nodeKeyFormat = keyformat.NewKeyFormat('n', memiavl.SizeHash) // n<hash>
rootKeyFormat = keyformat.NewKeyFormat('r', int64Size) // r<version>
nodeKeyFormat = keyformat.NewKeyFormat('n', memiavl.SizeHash) // n<hash>
rootKeyFormat = keyformat.NewKeyFormat('r', int64Size) // r<version>
nodeKeyV1Format = keyformat.NewFastPrefixFormatter('s', int64Size+int32Size) // s<version><nonce>
)

func RestoreAppDBCmd(opts Options) *cobra.Command {
Expand Down

0 comments on commit b8f43e8

Please sign in to comment.