From dc90e0b84bc30baedbf5000e33f9037525144592 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 12 Nov 2022 09:19:09 +0800 Subject: [PATCH 01/13] add LoadVersionForOverwritingWithMode to * skip deleteNodesFrom * lazyLoad latest version --- mutable_tree.go | 14 ++++++++++++-- nodedb.go | 10 ++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/mutable_tree.go b/mutable_tree.go index 5793b63c0..6cb8cec34 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -616,12 +616,22 @@ func (tree *MutableTree) LoadVersion(targetVersion int64) (int64, error) { // LoadVersionForOverwriting attempts to load a tree at a previously committed // version, or the latest version below it. Any versions greater than targetVersion will be deleted. func (tree *MutableTree) LoadVersionForOverwriting(targetVersion int64) (int64, error) { - latestVersion, err := tree.LoadVersion(targetVersion) + return tree.LoadVersionForOverwritingWithMode(targetVersion, false) +} + +func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, fastMode bool) (int64, error) { + var latestVersion int64 + var err error + if !fastMode { + latestVersion, err = tree.LoadVersion(targetVersion) + } else { + latestVersion, err = tree.LazyLoadVersion(targetVersion) + } if err != nil { return latestVersion, err } - if err = tree.ndb.DeleteVersionsFrom(targetVersion + 1); err != nil { + if err = tree.ndb.DeleteVersionsFrom(targetVersion+1, fastMode); err != nil { return latestVersion, err } diff --git a/nodedb.go b/nodedb.go index 2d00d01ac..831030c2e 100644 --- a/nodedb.go +++ b/nodedb.go @@ -420,7 +420,7 @@ func (ndb *nodeDB) DeleteVersion(version int64, checkLatestVersion bool) error { } // DeleteVersionsFrom permanently deletes all tree versions from the given version upwards. -func (ndb *nodeDB) DeleteVersionsFrom(version int64) error { +func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { latest, err := ndb.getLatestVersion() if err != nil { return err @@ -444,9 +444,11 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64) error { // First, delete all active nodes in the current (latest) version whose node version is after // the given version. - err = ndb.deleteNodesFrom(version, root) - if err != nil { - return err + if !fastMode { + err = ndb.deleteNodesFrom(version, root) + if err != nil { + return err + } } // Next, delete orphans: From a9d704d5bbd033d9c8bb49639d6af0694fd25207 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Sat, 12 Nov 2022 09:20:03 +0800 Subject: [PATCH 02/13] allow single iteration to traverse orphans target version with prefix --- nodedb.go | 63 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/nodedb.go b/nodedb.go index 831030c2e..97ae06412 100644 --- a/nodedb.go +++ b/nodedb.go @@ -449,31 +449,48 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { if err != nil { return err } - } - - // 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 { - var fromVersion, toVersion int64 - orphanKeyFormat.Scan(key, &toVersion, &fromVersion) - - if fromVersion >= version { - if err = ndb.batch.Delete(key); err != nil { - return err - } - if err = ndb.batch.Delete(ndb.nodeKey(hash)); err != nil { - return err + // 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 { + var fromVersion, toVersion int64 + orphanKeyFormat.Scan(key, &toVersion, &fromVersion) + + if fromVersion >= version { + if err = ndb.batch.Delete(key); err != nil { + return err + } + if err = ndb.batch.Delete(ndb.nodeKey(hash)); err != nil { + return err + } + ndb.nodeCache.Remove(hash) + } else if toVersion >= version-1 { + if err = ndb.batch.Delete(key); err != nil { + return err + } } - ndb.nodeCache.Remove(hash) - } else if toVersion >= version-1 { - if err = ndb.batch.Delete(key); err != nil { - return err + return nil + }) + } else { + err = ndb.traverseOrphansVersion(version-1, func(key, hash []byte) error { + var fromVersion, toVersion int64 + orphanKeyFormat.Scan(key, &toVersion, &fromVersion) + if fromVersion >= version { + if err = ndb.batch.Delete(key); err != nil { + return err + } + if err = ndb.batch.Delete(ndb.nodeKey(hash)); err != nil { + return err + } + ndb.nodeCache.Remove(hash) + } else if toVersion >= version-1 { + if err = ndb.batch.Delete(key); err != nil { + return err + } } - } - return nil - }) - + return nil + }) + } if err != nil { return err } From 325405d159eb9392a1edef3006b645730beff12e Mon Sep 17 00:00:00 2001 From: mmsqe Date: Mon, 14 Nov 2022 23:10:07 +0800 Subject: [PATCH 03/13] add missing commit on rollback when disable fastnode --- mutable_tree.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mutable_tree.go b/mutable_tree.go index 6cb8cec34..28c4c4160 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -639,6 +639,8 @@ func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, if err := tree.enableFastStorageAndCommitLocked(); err != nil { return latestVersion, err } + } else if err = tree.ndb.Commit(); err != nil { + return latestVersion, err } tree.ndb.resetLatestVersion(latestVersion) From 76c0d19e7d5a51acda4ad0c10dbbea84f30a15c3 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Wed, 16 Nov 2022 14:12:55 +0800 Subject: [PATCH 04/13] allow skip delete fast node entries --- nodedb.go | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/nodedb.go b/nodedb.go index 97ae06412..ed72b0470 100644 --- a/nodedb.go +++ b/nodedb.go @@ -508,24 +508,29 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { } // Delete fast node entries - err = ndb.traverseFastNodes(func(keyWithPrefix, v []byte) error { - key := keyWithPrefix[1:] - fastNode, err := fastnode.DeserializeNode(key, v) - if err != nil { - return err - } - - if version <= fastNode.GetVersionLastUpdatedAt() { - if err = ndb.batch.Delete(keyWithPrefix); err != nil { + // Delete step will be skipped with enable fastMode + // with the assumption that the rollback happens offline + // since fast nodes will be reinforced when next start up + if !fastMode { + err = ndb.traverseFastNodes(func(keyWithPrefix, v []byte) error { + key := keyWithPrefix[1:] + fastNode, err := fastnode.DeserializeNode(key, v) + if err != nil { return err } - ndb.fastNodeCache.Remove(key) - } - return nil - }) - if err != nil { - return err + if version <= fastNode.GetVersionLastUpdatedAt() { + if err = ndb.batch.Delete(keyWithPrefix); err != nil { + return err + } + ndb.fastNodeCache.Remove(key) + } + return nil + }) + + if err != nil { + return err + } } return nil From 1493ae5c745e737bc7beb93ff385126005582c53 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Mon, 14 Nov 2022 09:44:08 +0800 Subject: [PATCH 05/13] add del version test --- nodedb_test.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/nodedb_test.go b/nodedb_test.go index 0f2beecd1..deaade5bf 100644 --- a/nodedb_test.go +++ b/nodedb_test.go @@ -293,3 +293,66 @@ func makeAndPopulateMutableTree(tb testing.TB) *MutableTree { require.Nil(tb, err, "Expected .SaveVersion to succeed") return tree } + +func TestDeleteVersion(t *testing.T) { + v := []byte("value") + + var version int64 = 100 + testCases := []struct { + name string + v int64 + fastMode bool + }{ + { + "delete from version without fast mode", + version, + false, + }, + { + "delete from version -1 without fast mode", + version - 1, + false, + }, + { + "enable fast mode", + version, + true, + }, + } + for _, tc := range testCases { + db := db.NewMemDB() + ndb := newNodeDB(db, 0, nil) + leftNode := NewNode([]byte("left_key"), v, version-1) + rightNode := NewNode([]byte("right_key"), v, version-1) + node := NewNode([]byte("key"), v, version) + node.leftNode = leftNode + node.rightNode = rightNode + node.subtreeHeight = 1 + node.size = 2 + hash, err := ndb.SaveBranch(node) + require.NoError(t, err) + err = ndb.Commit() + require.NoError(t, err) + key := ndb.rootKey(version) + err = ndb.db.Set(key, hash) + require.NoError(t, err) + err = ndb.DeleteVersionsFrom(tc.v, tc.fastMode) + require.NoError(t, err) + err = ndb.Commit() + require.NoError(t, err) + bz, err := ndb.db.Get(ndb.nodeKey(hash)) + require.NoError(t, err) + leftBz, err := ndb.db.Get(ndb.nodeKey(leftNode.hash)) + require.NoError(t, err) + if !tc.fastMode { + if tc.v <= version { + require.Empty(t, bz) + } + if tc.v < version { + require.Empty(t, leftBz) + } else { + require.NotEmpty(t, leftBz) + } + } + } +} From e0cfa4279fa59d18071a001b96bc2aea951638db Mon Sep 17 00:00:00 2001 From: mmsqe Date: Wed, 16 Nov 2022 22:19:01 +0800 Subject: [PATCH 06/13] add change doc --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11d12bd60..2198de29f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - [#586](https://github.com/cosmos/iavl/pull/586) Remove the `RangeProof` and refactor the ics23_proof to use the internal methods. +- [#620](https://github.com/cosmos/iavl/pull/620) Add fast mode to rollback chain state in quick and dirty way, may leave some orphan nodes in db, not a big deal. ## 0.19.4 (October 28, 2022) From 36f3727ad0df649d2185435119d39fc614380148 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 17 Nov 2022 20:21:23 +0800 Subject: [PATCH 07/13] reuse with traverseInnerFunc --- nodedb.go | 57 +++++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/nodedb.go b/nodedb.go index ed72b0470..76ad9aa44 100644 --- a/nodedb.go +++ b/nodedb.go @@ -444,6 +444,24 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { // First, delete all active nodes in the current (latest) version whose node version is after // the given version. + traverseInnerFunc := func(key, hash []byte) error { + var fromVersion, toVersion int64 + orphanKeyFormat.Scan(key, &toVersion, &fromVersion) + if fromVersion >= version { + if err = ndb.batch.Delete(key); err != nil { + return err + } + if err = ndb.batch.Delete(ndb.nodeKey(hash)); err != nil { + return err + } + ndb.nodeCache.Remove(hash) + } else if toVersion >= version-1 { + if err = ndb.batch.Delete(key); err != nil { + return err + } + } + return nil + } if !fastMode { err = ndb.deleteNodesFrom(version, root) if err != nil { @@ -452,44 +470,9 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) 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 { - var fromVersion, toVersion int64 - orphanKeyFormat.Scan(key, &toVersion, &fromVersion) - - if fromVersion >= version { - if err = ndb.batch.Delete(key); err != nil { - return err - } - if err = ndb.batch.Delete(ndb.nodeKey(hash)); err != nil { - return err - } - ndb.nodeCache.Remove(hash) - } else if toVersion >= version-1 { - if err = ndb.batch.Delete(key); err != nil { - return err - } - } - return nil - }) + err = ndb.traverseOrphans(traverseInnerFunc) } else { - err = ndb.traverseOrphansVersion(version-1, func(key, hash []byte) error { - var fromVersion, toVersion int64 - orphanKeyFormat.Scan(key, &toVersion, &fromVersion) - if fromVersion >= version { - if err = ndb.batch.Delete(key); err != nil { - return err - } - if err = ndb.batch.Delete(ndb.nodeKey(hash)); err != nil { - return err - } - ndb.nodeCache.Remove(hash) - } else if toVersion >= version-1 { - if err = ndb.batch.Delete(key); err != nil { - return err - } - } - return nil - }) + err = ndb.traverseOrphansVersion(version-1, traverseInnerFunc) } if err != nil { return err From 2e9db23d31859e443a6c0ceda499edfcf7bb4353 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Thu, 17 Nov 2022 20:21:32 +0800 Subject: [PATCH 08/13] Apply suggestions from code review --- CHANGELOG.md | 2 +- mutable_tree.go | 8 +++++--- nodedb.go | 10 +++++----- nodedb_test.go | 16 ++++++++-------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2198de29f..9bdd8ce94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## Unreleased - [#586](https://github.com/cosmos/iavl/pull/586) Remove the `RangeProof` and refactor the ics23_proof to use the internal methods. -- [#620](https://github.com/cosmos/iavl/pull/620) Add fast mode to rollback chain state in quick and dirty way, may leave some orphan nodes in db, not a big deal. +- [#620](https://github.com/cosmos/iavl/pull/620) Add `fastRollback` flag to rollback chain state in quick and dirty way, may leave some orphan nodes in db, not a big deal. ## 0.19.4 (October 28, 2022) diff --git a/mutable_tree.go b/mutable_tree.go index 28c4c4160..eae63faf4 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -619,10 +619,12 @@ func (tree *MutableTree) LoadVersionForOverwriting(targetVersion int64) (int64, return tree.LoadVersionForOverwritingWithMode(targetVersion, false) } -func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, fastMode bool) (int64, error) { +// LoadVersionForOverwritingWithMode call LoadVersionForOverwriting with fastRollback +// to allow rollback in a quick and dirty way. +func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, fastRollback bool) (int64, error) { var latestVersion int64 var err error - if !fastMode { + if !fastRollback { latestVersion, err = tree.LoadVersion(targetVersion) } else { latestVersion, err = tree.LazyLoadVersion(targetVersion) @@ -631,7 +633,7 @@ func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, return latestVersion, err } - if err = tree.ndb.DeleteVersionsFrom(targetVersion+1, fastMode); err != nil { + if err = tree.ndb.DeleteVersionsFrom(targetVersion+1, fastRollback); err != nil { return latestVersion, err } diff --git a/nodedb.go b/nodedb.go index 76ad9aa44..0dc5cdf12 100644 --- a/nodedb.go +++ b/nodedb.go @@ -419,8 +419,8 @@ func (ndb *nodeDB) DeleteVersion(version int64, checkLatestVersion bool) error { return err } -// DeleteVersionsFrom permanently deletes all tree versions from the given version upwards. -func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { +// DeleteVersionsFrom permanently deletes all tree versions from the given version upwards with fastRollback. +func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastRollback bool) error { latest, err := ndb.getLatestVersion() if err != nil { return err @@ -462,7 +462,7 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { } return nil } - if !fastMode { + if !fastRollback { err = ndb.deleteNodesFrom(version, root) if err != nil { return err @@ -491,10 +491,10 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastMode bool) error { } // Delete fast node entries - // Delete step will be skipped with enable fastMode + // Delete step will be skipped with enable fastRollback // with the assumption that the rollback happens offline // since fast nodes will be reinforced when next start up - if !fastMode { + if !fastRollback { err = ndb.traverseFastNodes(func(keyWithPrefix, v []byte) error { key := keyWithPrefix[1:] fastNode, err := fastnode.DeserializeNode(key, v) diff --git a/nodedb_test.go b/nodedb_test.go index deaade5bf..9f9c0be58 100644 --- a/nodedb_test.go +++ b/nodedb_test.go @@ -299,22 +299,22 @@ func TestDeleteVersion(t *testing.T) { var version int64 = 100 testCases := []struct { - name string - v int64 - fastMode bool + name string + v int64 + fastRollback bool }{ { - "delete from version without fast mode", + "delete from version without fast rollback", version, false, }, { - "delete from version -1 without fast mode", + "delete from version -1 without fast rollback", version - 1, false, }, { - "enable fast mode", + "enable fast rollback", version, true, }, @@ -336,7 +336,7 @@ func TestDeleteVersion(t *testing.T) { key := ndb.rootKey(version) err = ndb.db.Set(key, hash) require.NoError(t, err) - err = ndb.DeleteVersionsFrom(tc.v, tc.fastMode) + err = ndb.DeleteVersionsFrom(tc.v, tc.fastRollback) require.NoError(t, err) err = ndb.Commit() require.NoError(t, err) @@ -344,7 +344,7 @@ func TestDeleteVersion(t *testing.T) { require.NoError(t, err) leftBz, err := ndb.db.Get(ndb.nodeKey(leftNode.hash)) require.NoError(t, err) - if !tc.fastMode { + if !tc.fastRollback { if tc.v <= version { require.Empty(t, bz) } From e3f445f4eab12e483797b7937de8d01f5936b8d3 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 18 Nov 2022 09:21:07 +0800 Subject: [PATCH 09/13] test del count --- nodedb_test.go | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/nodedb_test.go b/nodedb_test.go index 9f9c0be58..33a630c5a 100644 --- a/nodedb_test.go +++ b/nodedb_test.go @@ -294,6 +294,30 @@ func makeAndPopulateMutableTree(tb testing.TB) *MutableTree { return tree } +type customBatch struct { + db.Batch + DeleteCount int +} + +func (b *customBatch) Delete(key []byte) error { + b.DeleteCount += 1 + return b.Batch.Delete(key) +} + +type customMemDB struct { + *db.MemDB + LastBatch *customBatch +} + +func (db *customMemDB) NewBatch() db.Batch { + if db.LastBatch != nil { + db.LastBatch.Batch = db.MemDB.NewBatch() + } else { + db.LastBatch = &customBatch{db.MemDB.NewBatch(), 0} + } + return db.LastBatch +} + func TestDeleteVersion(t *testing.T) { v := []byte("value") @@ -302,25 +326,32 @@ func TestDeleteVersion(t *testing.T) { name string v int64 fastRollback bool + delCount int }{ { "delete from version without fast rollback", version, false, + 2, }, { "delete from version -1 without fast rollback", version - 1, false, + 4, }, { "enable fast rollback", - version, + version - 1, true, + 1, }, } for _, tc := range testCases { - db := db.NewMemDB() + db := &customMemDB{ + MemDB: db.NewMemDB(), + LastBatch: nil, + } ndb := newNodeDB(db, 0, nil) leftNode := NewNode([]byte("left_key"), v, version-1) rightNode := NewNode([]byte("right_key"), v, version-1) @@ -353,6 +384,10 @@ func TestDeleteVersion(t *testing.T) { } else { require.NotEmpty(t, leftBz) } + } else { + require.NotEmpty(t, bz) + require.NotEmpty(t, leftBz) } + require.Equal(t, tc.delCount, db.LastBatch.DeleteCount, "Delete call count mismatch") } } From 06baf1fe31d0f507c25f403d974651b7177addff Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 18 Nov 2022 09:25:43 +0800 Subject: [PATCH 10/13] rename to offline rollback --- mutable_tree.go | 8 ++++---- nodedb.go | 10 +++++----- nodedb_test.go | 18 +++++++++--------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/mutable_tree.go b/mutable_tree.go index eae63faf4..c98d58c7f 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -619,12 +619,12 @@ func (tree *MutableTree) LoadVersionForOverwriting(targetVersion int64) (int64, return tree.LoadVersionForOverwritingWithMode(targetVersion, false) } -// LoadVersionForOverwritingWithMode call LoadVersionForOverwriting with fastRollback +// LoadVersionForOverwritingWithMode call LoadVersionForOverwriting with offlineRollback // to allow rollback in a quick and dirty way. -func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, fastRollback bool) (int64, error) { +func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, offlineRollback bool) (int64, error) { var latestVersion int64 var err error - if !fastRollback { + if !offlineRollback { latestVersion, err = tree.LoadVersion(targetVersion) } else { latestVersion, err = tree.LazyLoadVersion(targetVersion) @@ -633,7 +633,7 @@ func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, return latestVersion, err } - if err = tree.ndb.DeleteVersionsFrom(targetVersion+1, fastRollback); err != nil { + if err = tree.ndb.DeleteVersionsFrom(targetVersion+1, offlineRollback); err != nil { return latestVersion, err } diff --git a/nodedb.go b/nodedb.go index 0dc5cdf12..4f3577aae 100644 --- a/nodedb.go +++ b/nodedb.go @@ -419,8 +419,8 @@ func (ndb *nodeDB) DeleteVersion(version int64, checkLatestVersion bool) error { return err } -// DeleteVersionsFrom permanently deletes all tree versions from the given version upwards with fastRollback. -func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastRollback bool) error { +// DeleteVersionsFrom permanently deletes all tree versions from the given version upwards with offlineRollback. +func (ndb *nodeDB) DeleteVersionsFrom(version int64, offlineRollback bool) error { latest, err := ndb.getLatestVersion() if err != nil { return err @@ -462,7 +462,7 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastRollback bool) error { } return nil } - if !fastRollback { + if !offlineRollback { err = ndb.deleteNodesFrom(version, root) if err != nil { return err @@ -491,10 +491,10 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, fastRollback bool) error { } // Delete fast node entries - // Delete step will be skipped with enable fastRollback + // Delete step will be skipped with enable offlineRollback // with the assumption that the rollback happens offline // since fast nodes will be reinforced when next start up - if !fastRollback { + if !offlineRollback { err = ndb.traverseFastNodes(func(keyWithPrefix, v []byte) error { key := keyWithPrefix[1:] fastNode, err := fastnode.DeserializeNode(key, v) diff --git a/nodedb_test.go b/nodedb_test.go index 33a630c5a..484682f21 100644 --- a/nodedb_test.go +++ b/nodedb_test.go @@ -323,25 +323,25 @@ func TestDeleteVersion(t *testing.T) { var version int64 = 100 testCases := []struct { - name string - v int64 - fastRollback bool - delCount int + name string + v int64 + offlineRollback bool + delCount int }{ { - "delete from version without fast rollback", + "delete from version without offline rollback", version, false, 2, }, { - "delete from version -1 without fast rollback", + "delete from version -1 without offline rollback", version - 1, false, 4, }, { - "enable fast rollback", + "enable offline rollback", version - 1, true, 1, @@ -367,7 +367,7 @@ func TestDeleteVersion(t *testing.T) { key := ndb.rootKey(version) err = ndb.db.Set(key, hash) require.NoError(t, err) - err = ndb.DeleteVersionsFrom(tc.v, tc.fastRollback) + err = ndb.DeleteVersionsFrom(tc.v, tc.offlineRollback) require.NoError(t, err) err = ndb.Commit() require.NoError(t, err) @@ -375,7 +375,7 @@ func TestDeleteVersion(t *testing.T) { require.NoError(t, err) leftBz, err := ndb.db.Get(ndb.nodeKey(leftNode.hash)) require.NoError(t, err) - if !tc.fastRollback { + if !tc.offlineRollback { if tc.v <= version { require.Empty(t, bz) } From 7e88c5cecc703e1e0bad0ed05c1d827726ab62c3 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 18 Nov 2022 09:25:47 +0800 Subject: [PATCH 11/13] Apply suggestions from code review --- nodedb.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nodedb.go b/nodedb.go index 4f3577aae..b2cf5f9b3 100644 --- a/nodedb.go +++ b/nodedb.go @@ -472,6 +472,7 @@ func (ndb *nodeDB) DeleteVersionsFrom(version int64, offlineRollback bool) error // - Delete orphan entries with toVersion >= version-1 (since orphans at latest are not orphans) err = ndb.traverseOrphans(traverseInnerFunc) } else { + // toVersion in orphan records is current version-1 err = ndb.traverseOrphansVersion(version-1, traverseInnerFunc) } if err != nil { From 9b36a27fef07b17935fd98ed3a77689d04e52184 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 18 Nov 2022 09:28:14 +0800 Subject: [PATCH 12/13] update change doc --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bdd8ce94..da87b04ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## Unreleased - [#586](https://github.com/cosmos/iavl/pull/586) Remove the `RangeProof` and refactor the ics23_proof to use the internal methods. -- [#620](https://github.com/cosmos/iavl/pull/620) Add `fastRollback` flag to rollback chain state in quick and dirty way, may leave some orphan nodes in db, not a big deal. +- [#620](https://github.com/cosmos/iavl/pull/620) Add `offlineRollback` flag to rollback chain state in quick and dirty way, may leave some orphan nodes in db, not a big deal. ## 0.19.4 (October 28, 2022) From d64ee0597adebef3554309dbe5abe24580d26760 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Tue, 22 Nov 2022 10:53:27 +0800 Subject: [PATCH 13/13] no extra disableIAVLFastNode when rollback offline --- mutable_tree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mutable_tree.go b/mutable_tree.go index c98d58c7f..f9235fb9f 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -637,7 +637,7 @@ func (tree *MutableTree) LoadVersionForOverwritingWithMode(targetVersion int64, return latestVersion, err } - if !tree.skipFastStorageUpgrade { + if !tree.skipFastStorageUpgrade && !offlineRollback { if err := tree.enableFastStorageAndCommitLocked(); err != nil { return latestVersion, err }