Skip to content

Commit

Permalink
fix: Prevent newExporter crash if tree.ndb is nil (backport cosmos#622)…
Browse files Browse the repository at this point in the history
… (cosmos#631)

Co-authored-by: Chill Validation <[email protected]>
Co-authored-by: Marko Baricevic <[email protected]>
  • Loading branch information
3 people authored Dec 8, 2022
1 parent 43560dc commit 2af006a
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 15 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### Breaking Changes

- [#622](https://github.com/cosmos/iavl/pull/622) `export/newExporter()` and `ImmutableTree.Export()` returns error for nil arguements

## Unreleased

- [#640](https://github.com/cosmos/iavl/pull/640) commit `NodeDB` batch in `LoadVersionForOverwriting`.
Expand Down
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ all: lint test install
install:
ifeq ($(COLORS_ON),)
go install ./cmd/iaviewer
go install ./cmd/iavlserver
else
go install $(CMDFLAGS) ./cmd/iaviewer
go install $(CMDFLAGS) ./cmd/iavlserver
endif
.PHONY: install

Expand Down
5 changes: 4 additions & 1 deletion benchmarks/cosmos-exim/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ func runExport(dbPath string) (int64, map[string][]*iavl.ExportNode, error) {
return 0, nil, err
}
start := time.Now().UTC()
exporter := itree.Export()
exporter, err := itree.Export()
if err != nil {
return 0, nil, err
}
defer exporter.Close()
for {
node, err := exporter.Next()
Expand Down
19 changes: 15 additions & 4 deletions export.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package iavl

import (
"context"

"github.com/pkg/errors"
"errors"
"fmt"
)

// exportBufferSize is the number of nodes to buffer in the exporter. It improves throughput by
Expand All @@ -15,6 +15,9 @@ const exportBufferSize = 32
// nolint:revive
var ExportDone = errors.New("export is complete") // nolint:golint

// ErrNotInitalizedTree when chains introduce a store without initializing data
var ErrNotInitalizedTree = errors.New("iavl/export newExporter failed to create")

// ExportNode contains exported node data.
type ExportNode struct {
Key []byte
Expand All @@ -35,7 +38,15 @@ type Exporter struct {
}

// NewExporter creates a new Exporter. Callers must call Close() when done.
func newExporter(tree *ImmutableTree) *Exporter {
func newExporter(tree *ImmutableTree) (*Exporter, error) {
if tree == nil {
return nil, fmt.Errorf("tree is nil: %w", ErrNotInitalizedTree)
}
// CV Prevent crash on incrVersionReaders if tree.ndb == nil
if tree.ndb == nil {
return nil, fmt.Errorf("tree.ndb is nil: %w", ErrNotInitalizedTree)
}

ctx, cancel := context.WithCancel(context.Background())
exporter := &Exporter{
tree: tree,
Expand All @@ -46,7 +57,7 @@ func newExporter(tree *ImmutableTree) *Exporter {
tree.ndb.incrVersionReaders(tree.version)
go exporter.export(ctx)

return exporter
return exporter, nil
}

// export exports nodes
Expand Down
15 changes: 10 additions & 5 deletions export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ func TestExporter(t *testing.T) {
}

actual := make([]*ExportNode, 0, len(expect))
exporter := tree.Export()
exporter, err := tree.Export()
require.NoError(t, err)
defer exporter.Close()
for {
node, err := exporter.Next()
Expand Down Expand Up @@ -189,7 +190,8 @@ func TestExporter_Import(t *testing.T) {
t.Run(desc, func(t *testing.T) {
t.Parallel()

exporter := tree.Export()
exporter, err := tree.Export()
require.NoError(t, err)
defer exporter.Close()

newTree, err := NewMutableTree(db.NewMemDB(), 0, false)
Expand Down Expand Up @@ -234,7 +236,8 @@ func TestExporter_Import(t *testing.T) {

func TestExporter_Close(t *testing.T) {
tree := setupExportTreeSized(t, 4096)
exporter := tree.Export()
exporter, err := tree.Export()
require.NoError(t, err)

node, err := exporter.Next()
require.NoError(t, err)
Expand Down Expand Up @@ -273,7 +276,8 @@ func TestExporter_DeleteVersionErrors(t *testing.T) {

itree, err := tree.GetImmutable(2)
require.NoError(t, err)
exporter := itree.Export()
exporter, err := itree.Export()
require.NoError(t, err)
defer exporter.Close()

err = tree.DeleteVersion(2)
Expand All @@ -291,7 +295,8 @@ func BenchmarkExport(b *testing.B) {
tree := setupExportTreeSized(b, 4096)
b.StartTimer()
for n := 0; n < b.N; n++ {
exporter := tree.Export()
exporter, err := tree.Export()
require.NoError(b, err)
for {
_, err := exporter.Next()
if err == ExportDone {
Expand Down
2 changes: 1 addition & 1 deletion immutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (t *ImmutableTree) Hash() ([]byte, error) {

// Export returns an iterator that exports tree nodes as ExportNodes. These nodes can be
// imported with MutableTree.Import() to recreate an identical tree.
func (t *ImmutableTree) Export() *Exporter {
func (t *ImmutableTree) Export() (*Exporter, error) {
return newExporter(t)
}

Expand Down
5 changes: 3 additions & 2 deletions import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func ExampleImporter() {
if err != nil {
// handle err
}
exporter := itree.Export()
exporter, err := itree.Export()
defer exporter.Close()
exported := []*ExportNode{}
for {
Expand Down Expand Up @@ -218,7 +218,8 @@ func BenchmarkImport(b *testing.B) {
b.StopTimer()
tree := setupExportTreeSized(b, 4096)
exported := make([]*ExportNode, 0, 4096)
exporter := tree.Export()
exporter, err := tree.Export()
require.NoError(b, err)
for {
item, err := exporter.Next()
if err == ExportDone {
Expand Down

0 comments on commit 2af006a

Please sign in to comment.