Skip to content

Commit

Permalink
feat: speed up rollback command (backport #636) (#648)
Browse files Browse the repository at this point in the history
Co-authored-by: yihuang <[email protected]>
Co-authored-by: Marko Baricevic <[email protected]>
  • Loading branch information
3 people authored Dec 26, 2022
1 parent 21ea96e commit 007cd55
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 36 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## Unreleased

- [#640](https://github.com/cosmos/iavl/pull/640) commit `NodeDB` batch in `LoadVersionForOverwriting`.
- [#636](https://github.com/cosmos/iavl/pull/636) Speed up rollback method: `LoadVersionForOverwriting`.

## 0.19.4 (October 28, 2022)

Expand Down
19 changes: 7 additions & 12 deletions mutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -630,17 +630,18 @@ func (tree *MutableTree) LoadVersionForOverwriting(targetVersion int64) (int64,
return latestVersion, err
}

tree.mtx.Lock()
defer tree.mtx.Unlock()

tree.ndb.resetLatestVersion(latestVersion)

if !tree.skipFastStorageUpgrade {
if err := tree.enableFastStorageAndCommitLocked(); err != nil {
// it'll repopulates the fast node index because of version mismatch.
if _, err := tree.enableFastStorageAndCommitIfNotEnabled(); err != nil {
return latestVersion, err
}
}

tree.ndb.resetLatestVersion(latestVersion)

tree.mtx.Lock()
defer tree.mtx.Unlock()

for v := range tree.versions {
if v > targetVersion {
delete(tree.versions, v)
Expand Down Expand Up @@ -706,12 +707,6 @@ func (tree *MutableTree) enableFastStorageAndCommitIfNotEnabled() (bool, error)
return true, nil
}

func (tree *MutableTree) enableFastStorageAndCommitLocked() error {
tree.mtx.Lock()
defer tree.mtx.Unlock()
return tree.enableFastStorageAndCommit()
}

func (tree *MutableTree) enableFastStorageAndCommit() error {
var err error

Expand Down
36 changes: 12 additions & 24 deletions nodedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const (
defaultStorageVersionValue = "1.0.0"
fastStorageVersionValue = "1.1.0"
fastNodeCacheSize = 100000
maxVersion = int64(math.MaxInt64)
)

var (
Expand Down Expand Up @@ -458,7 +459,7 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64) error {
// Next, delete orphans:
// - Delete orphan entries *and referred nodes* with fromVersion >= version
// - Delete orphan entries with toVersion >= version-1 (since orphans at latest are not orphans)
err = ndb.traverseOrphans(func(key, hash []byte) error {
err = ndb.traverseRange(orphanKeyFormat.Key(version-1), orphanKeyFormat.Key(maxVersion), func(key, hash []byte) error {
var fromVersion, toVersion int64
orphanKeyFormat.Scan(key, &toVersion, &fromVersion)

Expand All @@ -483,7 +484,7 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64) error {
}

// Delete the version root entries
err = ndb.traverseRange(rootKeyFormat.Key(version), rootKeyFormat.Key(int64(math.MaxInt64)), func(k, v []byte) error {
err = ndb.traverseRange(rootKeyFormat.Key(version), rootKeyFormat.Key(maxVersion), func(k, v []byte) error {
if err = ndb.batch.Delete(k); err != nil {
return err
}
Expand All @@ -494,27 +495,7 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64) error {
return err
}

// Delete fast node entries
err = ndb.traverseFastNodes(func(keyWithPrefix, v []byte) error {
key := keyWithPrefix[1:]
fastNode, err := DeserializeFastNode(key, v)

if err != nil {
return err
}

if version <= fastNode.versionLastUpdatedAt {
if err = ndb.batch.Delete(keyWithPrefix); err != nil {
return err
}
ndb.fastNodeCache.Remove(key)
}
return nil
})

if err != nil {
return err
}
// NOTICE: we don't touch fast node indexes here, because it'll be rebuilt later because of version mismatch.

return nil
}
Expand Down Expand Up @@ -612,6 +593,11 @@ func (ndb *nodeDB) deleteNodesFrom(version int64, hash []byte) error {
return err
}

if node.version < version {
// We can skip the whole sub-tree since children.version <= parent.version.
return nil
}

if node.leftHash != nil {
if err := ndb.deleteNodesFrom(version, node.leftHash); err != nil {
return err
Expand Down Expand Up @@ -729,7 +715,7 @@ func (ndb *nodeDB) rootKey(version int64) []byte {
func (ndb *nodeDB) getLatestVersion() (int64, error) {
if ndb.latestVersion == 0 {
var err error
ndb.latestVersion, err = ndb.getPreviousVersion(1<<63 - 1)
ndb.latestVersion, err = ndb.getPreviousVersion(maxVersion)
if err != nil {
return 0, err
}
Expand Down Expand Up @@ -793,6 +779,7 @@ func (ndb *nodeDB) traverseOrphans(fn func(keyWithPrefix, v []byte) error) error
}

// Traverse fast nodes and return error if any, nil otherwise
// nolint: unused
func (ndb *nodeDB) traverseFastNodes(fn func(k, v []byte) error) error {
return ndb.traversePrefix(fastKeyFormat.Key(), fn)
}
Expand Down Expand Up @@ -1015,6 +1002,7 @@ func (ndb *nodeDB) orphans() ([][]byte, error) {
// Not efficient.
// NOTE: DB cannot implement Size() because
// mutations are not always synchronous.
//
//nolint:unused
func (ndb *nodeDB) size() int {
size := 0
Expand Down

0 comments on commit 007cd55

Please sign in to comment.