From e53ad2f4687afe4a4964a3484cda11522f97cd19 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Jan 2022 18:39:16 +0300 Subject: [PATCH] [#1085] blobovnicza: allow to ignore errors during iteration Signed-off-by: Evgenii Stratonikov --- .../blobovnicza/iterate.go | 10 ++++ .../blobovnicza/iterate_test.go | 57 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 pkg/local_object_storage/blobovnicza/iterate_test.go diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index 6ac3c6af..f7ab27ad 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -84,6 +84,8 @@ type IteratePrm struct { withoutData bool handler IterationHandler + + ignoreErrors bool } // DecodeAddresses sets flag to unmarshal object addresses. @@ -101,6 +103,11 @@ func (x *IteratePrm) SetHandler(h IterationHandler) { x.handler = h } +// IgnoreErrors makes all errors to be ignored. +func (x *IteratePrm) IgnoreErrors() { + x.ignoreErrors = true +} + // IterateRes groups resulting values of Iterate operation. type IterateRes struct { } @@ -124,6 +131,9 @@ func (b *Blobovnicza) Iterate(prm IteratePrm) (*IterateRes, error) { } if err := addressFromKey(elem.addr, k); err != nil { + if prm.ignoreErrors { + return nil + } return fmt.Errorf("could not decode address key: %w", err) } } diff --git a/pkg/local_object_storage/blobovnicza/iterate_test.go b/pkg/local_object_storage/blobovnicza/iterate_test.go new file mode 100644 index 00000000..0ea8668c --- /dev/null +++ b/pkg/local_object_storage/blobovnicza/iterate_test.go @@ -0,0 +1,57 @@ +package blobovnicza + +import ( + "errors" + "path/filepath" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/util/slice" + objecttest "github.com/nspcc-dev/neofs-sdk-go/object/test" + "github.com/stretchr/testify/require" + "go.etcd.io/bbolt" +) + +func TestBlobovniczaIterate(t *testing.T) { + filename := filepath.Join(t.TempDir(), "blob") + b := New(WithPath(filename)) + require.NoError(t, b.Open()) + require.NoError(t, b.Init()) + + data := [][]byte{{0, 1, 2, 3}, {5, 6, 7, 8}} + addr := objecttest.Address() + _, err := b.Put(&PutPrm{addr: addr, objData: data[0]}) + require.NoError(t, err) + + require.NoError(t, b.boltDB.Update(func(tx *bbolt.Tx) error { + buck := tx.Bucket(bucketKeyFromBounds(firstBucketBound)) + return buck.Put([]byte("invalid address"), data[1]) + })) + + seen := make([][]byte, 0, 2) + inc := func(e IterationElement) error { + seen = append(seen, slice.Copy(e.data)) + return nil + } + + _, err = b.Iterate(IteratePrm{handler: inc}) + require.NoError(t, err) + require.ElementsMatch(t, seen, data) + + seen = seen[:0] + _, err = b.Iterate(IteratePrm{handler: inc, decodeAddresses: true}) + require.Error(t, err) + + seen = seen[:0] + _, err = b.Iterate(IteratePrm{handler: inc, decodeAddresses: true, ignoreErrors: true}) + require.NoError(t, err) + require.ElementsMatch(t, seen, data[:1]) + + seen = seen[:0] + expectedErr := errors.New("stop iteration") + _, err = b.Iterate(IteratePrm{ + decodeAddresses: true, + handler: func(IterationElement) error { return expectedErr }, + ignoreErrors: true, + }) + require.True(t, errors.Is(err, expectedErr), "got: %v") +}