From fe0178181171cff0bf00e7b24943d15dedacb77b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 15 Jun 2023 13:19:36 +0300 Subject: [PATCH] [#446] los: Wrap SSD errors in a separate type Signed-off-by: Evgenii Stratonikov --- .../internal/metaerr/error.go | 33 +++++++++ .../internal/metaerr/error_test.go | 67 +++++++++++++++++++ pkg/local_object_storage/metabase/children.go | 3 +- .../metabase/containers.go | 5 +- pkg/local_object_storage/metabase/control.go | 15 +++-- pkg/local_object_storage/metabase/counter.go | 3 +- pkg/local_object_storage/metabase/delete.go | 3 +- pkg/local_object_storage/metabase/exists.go | 3 +- pkg/local_object_storage/metabase/expired.go | 3 +- pkg/local_object_storage/metabase/get.go | 3 +- .../metabase/graveyard.go | 9 +-- pkg/local_object_storage/metabase/inhume.go | 3 +- .../metabase/iterators.go | 5 +- pkg/local_object_storage/metabase/list.go | 3 +- pkg/local_object_storage/metabase/lock.go | 11 +-- pkg/local_object_storage/metabase/movable.go | 11 +-- pkg/local_object_storage/metabase/put.go | 3 +- pkg/local_object_storage/metabase/select.go | 5 +- pkg/local_object_storage/metabase/shard_id.go | 7 +- .../metabase/storage_id.go | 5 +- pkg/local_object_storage/pilorama/boltdb.go | 45 +++++++------ pkg/local_object_storage/writecache/delete.go | 3 +- pkg/local_object_storage/writecache/flush.go | 9 +-- pkg/local_object_storage/writecache/get.go | 8 ++- .../writecache/iterate.go | 5 +- pkg/local_object_storage/writecache/put.go | 3 +- .../writecache/writecache.go | 5 +- 27 files changed, 202 insertions(+), 76 deletions(-) create mode 100644 pkg/local_object_storage/internal/metaerr/error.go create mode 100644 pkg/local_object_storage/internal/metaerr/error_test.go diff --git a/pkg/local_object_storage/internal/metaerr/error.go b/pkg/local_object_storage/internal/metaerr/error.go new file mode 100644 index 000000000..41b8504bc --- /dev/null +++ b/pkg/local_object_storage/internal/metaerr/error.go @@ -0,0 +1,33 @@ +package metaerr + +import "errors" + +// Error is a wrapper for SSD-related errors. +// In our model it unites metabase, pilorama and write-cache errors. +type Error struct { + err error +} + +// New returns simple error with a provided error message. +func New(msg string) Error { + return Error{err: errors.New(msg)} +} + +// Error implements the error interface. +func (e Error) Error() string { + return e.err.Error() +} + +// Wrap wraps arbitrary error. +// Returns nil if err == nil. +func Wrap(err error) error { + if err != nil { + return Error{err: err} + } + return nil +} + +// Unwrap returns underlying error. +func (e Error) Unwrap() error { + return e.err +} diff --git a/pkg/local_object_storage/internal/metaerr/error_test.go b/pkg/local_object_storage/internal/metaerr/error_test.go new file mode 100644 index 000000000..5a16aa501 --- /dev/null +++ b/pkg/local_object_storage/internal/metaerr/error_test.go @@ -0,0 +1,67 @@ +package metaerr + +import ( + "errors" + "fmt" + "strconv" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestError(t *testing.T) { + t.Run("errors.Is", func(t *testing.T) { + e1 := errors.New("some error") + ee := Wrap(e1) + require.ErrorIs(t, ee, e1) + + e2 := fmt.Errorf("wrap: %w", e1) + ee = Wrap(e2) + require.ErrorIs(t, ee, e1) + require.ErrorIs(t, ee, e2) + + require.Equal(t, errors.Unwrap(ee), e2) + }) + + t.Run("errors.As", func(t *testing.T) { + e1 := testError{42} + ee := Wrap(e1) + + { + var actual testError + require.ErrorAs(t, ee, &actual) + require.Equal(t, e1.data, actual.data) + } + { + var actual Error + require.ErrorAs(t, ee, &actual) + require.Equal(t, e1, actual.err) + } + + e2 := fmt.Errorf("wrap: %w", e1) + ee = Wrap(e2) + + { + var actual testError + require.ErrorAs(t, ee, &actual) + require.Equal(t, e1.data, actual.data) + } + }) +} +func TestNilWrap(t *testing.T) { + require.NoError(t, Wrap(nil)) +} + +func TestErrorMessage(t *testing.T) { + msg := "sth to report" + err := New(msg) + require.Contains(t, err.Error(), msg) +} + +type testError struct { + data uint64 +} + +func (e testError) Error() string { + return strconv.FormatUint(e.data, 10) +} diff --git a/pkg/local_object_storage/metabase/children.go b/pkg/local_object_storage/metabase/children.go index f0591b43c..500e83e7a 100644 --- a/pkg/local_object_storage/metabase/children.go +++ b/pkg/local_object_storage/metabase/children.go @@ -1,6 +1,7 @@ package meta import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) @@ -50,7 +51,7 @@ func (db *DB) GetChildren(addresses []oid.Address) (map[oid.Address][]oid.Addres }) if err != nil { - return nil, err + return nil, metaerr.Wrap(err) } return result, nil diff --git a/pkg/local_object_storage/metabase/containers.go b/pkg/local_object_storage/metabase/containers.go index 3d69649a9..fe38e0b6d 100644 --- a/pkg/local_object_storage/metabase/containers.go +++ b/pkg/local_object_storage/metabase/containers.go @@ -3,6 +3,7 @@ package meta import ( "encoding/binary" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.etcd.io/bbolt" ) @@ -21,7 +22,7 @@ func (db *DB) Containers() (list []cid.ID, err error) { return err }) - return list, err + return list, metaerr.Wrap(err) } func (db *DB) containers(tx *bbolt.Tx) ([]cid.ID, error) { @@ -55,7 +56,7 @@ func (db *DB) ContainerSize(id cid.ID) (size uint64, err error) { return err }) - return size, err + return size, metaerr.Wrap(err) } func (db *DB) containerSize(tx *bbolt.Tx, id cid.ID) (uint64, error) { diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 4ae802aaa..370fddda1 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -6,6 +6,7 @@ import ( "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" @@ -34,7 +35,7 @@ func (db *DB) Open(readOnly bool) error { } db.boltOptions.ReadOnly = readOnly - return db.openBolt() + return metaerr.Wrap(db.openBolt()) } func (db *DB) openBolt() error { @@ -79,7 +80,7 @@ func (db *DB) openBolt() error { // Does nothing if metabase has already been initialized and filled. To roll back the database to its initial state, // use Reset. func (db *DB) Init() error { - return db.init(false) + return metaerr.Wrap(db.init(false)) } // Reset resets metabase. Works similar to Init but cleans up all static buckets and @@ -92,7 +93,7 @@ func (db *DB) Reset() error { return ErrDegradedMode } - return db.init(true) + return metaerr.Wrap(db.init(true)) } func (db *DB) init(reset bool) error { @@ -167,15 +168,15 @@ func (db *DB) SyncCounters() error { return ErrReadOnlyMode } - return db.boltDB.Update(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.Update(func(tx *bbolt.Tx) error { return syncCounter(tx, true) - }) + })) } // Close closes boltDB instance. func (db *DB) Close() error { if db.boltDB != nil { - return db.boltDB.Close() + return metaerr.Wrap(db.boltDB.Close()) } return nil } @@ -203,7 +204,7 @@ func (db *DB) Reload(opts ...Option) (bool, error) { db.mode = mode.Degraded db.info.Path = c.info.Path if err := db.openBolt(); err != nil { - return false, fmt.Errorf("%w: %v", ErrDegradedMode, err) + return false, metaerr.Wrap(fmt.Errorf("%w: %v", ErrDegradedMode, err)) } db.mode = mode.ReadWrite diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index a07328026..c0dc7886e 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -67,7 +68,7 @@ func (db *DB) ObjectCounters() (cc ObjectCounters, err error) { return nil }) - return + return cc, metaerr.Wrap(err) } // updateCounter updates the object counter. Tx MUST be writable. diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 6ddf96593..7e8e0e5dd 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -108,7 +109,7 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { availableRemoved: availableRemoved, sizes: sizes, availableSizes: availableSizes, - }, err + }, metaerr.Wrap(err) } // deleteGroup deletes object from the metabase. Handles removal of the diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 74faf1634..f9c563bdd 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -5,6 +5,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -65,7 +66,7 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err return err }) - return + return res, metaerr.Wrap(err) } func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (exists bool, err error) { diff --git a/pkg/local_object_storage/metabase/expired.go b/pkg/local_object_storage/metabase/expired.go index d20fdbfa9..aac158ba4 100644 --- a/pkg/local_object_storage/metabase/expired.go +++ b/pkg/local_object_storage/metabase/expired.go @@ -7,6 +7,7 @@ import ( "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -65,7 +66,7 @@ func (db *DB) FilterExpired(ctx context.Context, epoch uint64, addresses []oid.A }) if err != nil { - return nil, err + return nil, metaerr.Wrap(err) } return result, nil } diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 2f94c72d0..2ce82bcee 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -74,7 +75,7 @@ func (db *DB) Get(ctx context.Context, prm GetPrm) (res GetRes, err error) { return err }) - return + return res, metaerr.Wrap(err) } func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw bool, currEpoch uint64) (*objectSDK.Object, error) { diff --git a/pkg/local_object_storage/metabase/graveyard.go b/pkg/local_object_storage/metabase/graveyard.go index 393c9f4d0..e2530bd31 100644 --- a/pkg/local_object_storage/metabase/graveyard.go +++ b/pkg/local_object_storage/metabase/graveyard.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) @@ -65,9 +66,9 @@ func (db *DB) IterateOverGarbage(p GarbageIterationPrm) error { return ErrDegradedMode } - return db.boltDB.View(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { return db.iterateDeletedObj(tx, gcHandler{p.h}, p.offset) - }) + })) } // TombstonedObject represents descriptor of the @@ -132,9 +133,9 @@ func (db *DB) IterateOverGraveyard(p GraveyardIterationPrm) error { return ErrDegradedMode } - return db.boltDB.View(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { return db.iterateDeletedObj(tx, graveyardHandler{p.h}, p.offset) - }) + })) } type kvHandler interface { diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index e4af1d1b9..7865a8771 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -138,7 +139,7 @@ func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRes, err err return db.inhumeTx(tx, currEpoch, prm, &res) }) - return + return res, metaerr.Wrap(err) } func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes) error { diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index ba22566a3..dfa048621 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -6,6 +6,7 @@ import ( "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -51,9 +52,9 @@ func (db *DB) IterateExpired(epoch uint64, h ExpiredObjectHandler) error { return ErrDegradedMode } - return db.boltDB.View(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { return db.iterateExpired(tx, epoch, h) - }) + })) } func (db *DB) iterateExpired(tx *bbolt.Tx, epoch uint64, h ExpiredObjectHandler) error { diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 7fe1040bb..7c77cd703 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -2,6 +2,7 @@ package meta import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -75,7 +76,7 @@ func (db *DB) ListWithCursor(prm ListPrm) (res ListRes, err error) { return err }) - return res, err + return res, metaerr.Wrap(err) } func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.AddressWithType, count int, cursor *Cursor) ([]objectcore.AddressWithType, *Cursor, error) { diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index 2b5fcd775..b84e0bf46 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -5,6 +5,7 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -63,7 +64,7 @@ func (db *DB) Lock(ctx context.Context, cnr cid.ID, locker oid.ID, locked []oid. } key := make([]byte, cidSize) - return db.boltDB.Update(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.Update(func(tx *bbolt.Tx) error { if firstIrregularObjectType(tx, cnr, bucketKeysLocked...) != object.TypeRegular { return logicerr.Wrap(apistatus.LockNonRegularObject{}) } @@ -109,7 +110,7 @@ func (db *DB) Lock(ctx context.Context, cnr cid.ID, locker oid.ID, locked []oid. } return nil - }) + })) } // FreeLockedBy unlocks all objects in DB which are locked by lockers. @@ -135,7 +136,7 @@ func (db *DB) FreeLockedBy(lockers []oid.Address) ([]oid.Address, error) { return nil }); err != nil { - return nil, err + return nil, metaerr.Wrap(err) } return unlockedObjects, nil } @@ -292,8 +293,8 @@ func (db *DB) IsLocked(ctx context.Context, prm IsLockedPrm) (res IsLockedRes, e return res, ErrDegradedMode } - return res, db.boltDB.View(func(tx *bbolt.Tx) error { + return res, metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { res.locked = objectLocked(tx, prm.addr.Container(), prm.addr.Object()) return nil - }) + })) } diff --git a/pkg/local_object_storage/metabase/movable.go b/pkg/local_object_storage/metabase/movable.go index 033b9c718..763e49a5d 100644 --- a/pkg/local_object_storage/metabase/movable.go +++ b/pkg/local_object_storage/metabase/movable.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -76,7 +77,7 @@ func (db *DB) ToMoveIt(ctx context.Context, prm ToMoveItPrm) (res ToMoveItRes, e return toMoveIt.Put(key, zeroValue) }) - return + return res, metaerr.Wrap(err) } // DoNotMove removes `MoveIt` mark from the object. @@ -98,7 +99,7 @@ func (db *DB) DoNotMove(prm DoNotMovePrm) (res DoNotMoveRes, err error) { return toMoveIt.Delete(key) }) - return + return res, metaerr.Wrap(err) } // Movable returns list of marked objects to move into other shard. @@ -121,7 +122,7 @@ func (db *DB) Movable(_ MovablePrm) (MovableRes, error) { }) }) if err != nil { - return MovableRes{}, err + return MovableRes{}, metaerr.Wrap(err) } // we can parse strings to structures in-place, but probably it seems @@ -132,8 +133,8 @@ func (db *DB) Movable(_ MovablePrm) (MovableRes, error) { for i := range strAddrs { err = decodeAddressFromKey(&addrs[i], []byte(strAddrs[i])) if err != nil { - return MovableRes{}, fmt.Errorf("can't parse object address %v: %w", - strAddrs[i], err) + return MovableRes{}, metaerr.Wrap(fmt.Errorf("can't parse object address %v: %w", + strAddrs[i], err)) } } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 86830f7da..b7cff68dc 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -9,6 +9,7 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -83,7 +84,7 @@ func (db *DB) Put(ctx context.Context, prm PutPrm) (res PutRes, err error) { storagelog.OpField("metabase PUT")) } - return + return res, metaerr.Wrap(err) } func (db *DB) put(tx *bbolt.Tx, diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index b6b8f5b10..466476d4e 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -9,6 +9,7 @@ import ( v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -80,11 +81,11 @@ func (db *DB) Select(ctx context.Context, prm SelectPrm) (res SelectRes, err err currEpoch := db.epochState.CurrentEpoch() - return res, db.boltDB.View(func(tx *bbolt.Tx) error { + return res, metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { res.addrList, err = db.selectObjects(tx, prm.cnr, prm.filters, currEpoch) return err - }) + })) } func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs object.SearchFilters, currEpoch uint64) ([]oid.Address, error) { diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index fac8a079f..f60a4724d 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -1,6 +1,7 @@ package meta import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" ) @@ -28,7 +29,7 @@ func (db *DB) ReadShardID() ([]byte, error) { } return nil }) - return id, err + return id, metaerr.Wrap(err) } // WriteShardID writes shard it to db. @@ -42,11 +43,11 @@ func (db *DB) WriteShardID(id []byte) error { return ErrReadOnlyMode } - return db.boltDB.Update(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.Update(func(tx *bbolt.Tx) error { b, err := tx.CreateBucketIfNotExists(shardInfoBucket) if err != nil { return err } return b.Put(shardIDKey, id) - }) + })) } diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index b53010a1e..6ba5a60cb 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/nspcc-dev/neo-go/pkg/util/slice" @@ -54,7 +55,7 @@ func (db *DB) StorageID(ctx context.Context, prm StorageIDPrm) (res StorageIDRes return err }) - return + return res, metaerr.Wrap(err) } func (db *DB) storageID(tx *bbolt.Tx, addr oid.Address) ([]byte, error) { @@ -113,5 +114,5 @@ func (db *DB) UpdateStorageID(prm UpdateStorageIDPrm) (res UpdateStorageIDRes, e return err }) - return + return res, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 5b2c97f10..e7bcb110b 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" @@ -105,7 +106,7 @@ func (t *boltForest) SetMode(m mode.Mode) error { func (t *boltForest) Open(readOnly bool) error { err := util.MkdirAllX(filepath.Dir(t.path), t.perm) if err != nil { - return fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err) + return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err)) } opts := *bbolt.DefaultOptions @@ -116,7 +117,7 @@ func (t *boltForest) Open(readOnly bool) error { t.db, err = bbolt.Open(t.path, t.perm, &opts) if err != nil { - return fmt.Errorf("can't open the pilorama DB: %w", err) + return metaerr.Wrap(fmt.Errorf("can't open the pilorama DB: %w", err)) } t.db.MaxBatchSize = t.maxBatchSize @@ -174,7 +175,7 @@ func (t *boltForest) TreeMove(ctx context.Context, d CIDDescriptor, treeID strin lm := *m fullID := bucketName(d.CID, treeID) - return &lm, t.db.Batch(func(tx *bbolt.Tx) error { + return &lm, metaerr.Wrap(t.db.Batch(func(tx *bbolt.Tx) error { bLog, bTree, err := t.getTreeBuckets(tx, fullID) if err != nil { return err @@ -185,7 +186,7 @@ func (t *boltForest) TreeMove(ctx context.Context, d CIDDescriptor, treeID strin lm.Child = t.findSpareID(bTree) } return t.do(bLog, bTree, make([]byte, 17), &lm) - }) + })) } func (t *boltForest) TreeHeight(ctx context.Context, cid cidSDK.ID, treeID string) (uint64, error) { @@ -219,7 +220,7 @@ func (t *boltForest) TreeHeight(ctx context.Context, cid cidSDK.ID, treeID strin if err == nil { err = retErr } - return height, err + return height, metaerr.Wrap(err) } // TreeExists implements the Forest interface. @@ -247,7 +248,7 @@ func (t *boltForest) TreeExists(ctx context.Context, cid cidSDK.ID, treeID strin return nil }) - return exists, err + return exists, metaerr.Wrap(err) } var syncHeightKey = []byte{'h'} @@ -267,7 +268,7 @@ func (t *boltForest) TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK.ID binary.LittleEndian.PutUint64(rawHeight, height) buck := bucketName(cid, treeID) - return t.db.Batch(func(tx *bbolt.Tx) error { + return metaerr.Wrap(t.db.Batch(func(tx *bbolt.Tx) error { treeRoot := tx.Bucket(buck) if treeRoot == nil { return ErrTreeNotFound @@ -275,7 +276,7 @@ func (t *boltForest) TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK.ID b := treeRoot.Bucket(dataBucket) return b.Put(syncHeightKey, rawHeight) - }) + })) } // TreeLastSyncHeight implements the pilorama.Forest interface. @@ -304,7 +305,7 @@ func (t *boltForest) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, tree } return nil }) - return height, err + return height, metaerr.Wrap(err) } // TreeAddByPath implements the Forest interface. @@ -384,7 +385,7 @@ func (t *boltForest) TreeAddByPath(ctx context.Context, d CIDDescriptor, treeID } return t.do(bLog, bTree, key[:], &lm[len(lm)-1]) }) - return lm, err + return lm, metaerr.Wrap(err) } // getLatestTimestamp returns timestamp for a new operation which is guaranteed to be bigger than @@ -450,13 +451,13 @@ func (t *boltForest) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string return nil }) if err != nil || seen { - return err + return metaerr.Wrap(err) } } if t.db.MaxBatchSize == 1 { fullID := bucketName(cnr, treeID) - return t.db.Update(func(tx *bbolt.Tx) error { + return metaerr.Wrap(t.db.Update(func(tx *bbolt.Tx) error { bLog, bTree, err := t.getTreeBuckets(tx, fullID) if err != nil { return err @@ -464,12 +465,12 @@ func (t *boltForest) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string var lm Move return t.applyOperation(bLog, bTree, []*Move{m}, &lm) - }) + })) } ch := make(chan error, 1) t.addBatch(cnr, treeID, m, ch) - return <-ch + return metaerr.Wrap(<-ch) } func (t *boltForest) addBatch(cnr cidSDK.ID, treeID string, m *Move, ch chan error) { @@ -751,7 +752,7 @@ func (t *boltForest) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID st var nodes []Node - return nodes, t.db.View(func(tx *bbolt.Tx) error { + return nodes, metaerr.Wrap(t.db.View(func(tx *bbolt.Tx) error { treeRoot := tx.Bucket(bucketName(cid, treeID)) if treeRoot == nil { return ErrTreeNotFound @@ -788,7 +789,7 @@ func (t *boltForest) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID st childKey, _ = c.Next() } return nil - }) + })) } // TreeGetMeta implements the forest interface. @@ -828,7 +829,7 @@ func (t *boltForest) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID stri return m.FromBytes(meta) }) - return m, parentID, err + return m, parentID, metaerr.Wrap(err) } // TreeGetChildren implements the Forest interface. @@ -869,7 +870,7 @@ func (t *boltForest) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID return nil }) - return children, err + return children, metaerr.Wrap(err) } // TreeList implements the Forest interface. @@ -907,7 +908,7 @@ func (t *boltForest) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, err return nil }) if err != nil { - return nil, fmt.Errorf("could not list trees: %w", err) + return nil, metaerr.Wrap(fmt.Errorf("could not list trees: %w", err)) } return ids, nil @@ -949,7 +950,7 @@ func (t *boltForest) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID str return nil }) - return lm, err + return lm, metaerr.Wrap(err) } // TreeDrop implements the pilorama.Forest interface. @@ -971,7 +972,7 @@ func (t *boltForest) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID string) return ErrReadOnlyMode } - return t.db.Batch(func(tx *bbolt.Tx) error { + return metaerr.Wrap(t.db.Batch(func(tx *bbolt.Tx) error { if treeID == "" { c := tx.Cursor() prefix := make([]byte, 32) @@ -989,7 +990,7 @@ func (t *boltForest) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID string) return ErrTreeNotFound } return err - }) + })) } func (t *boltForest) getPathPrefix(bTree *bbolt.Bucket, attr string, path []string) (int, Node, error) { diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index 796fda623..aeab88b0b 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -77,5 +78,5 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { deleted = true } - return err + return metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index da8b3a0fa..21f968b04 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -10,6 +10,7 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -193,7 +194,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { data, err := f() if err != nil { - c.reportFlushError("can't read a file", sAddr, err) + c.reportFlushError("can't read a file", sAddr, metaerr.Wrap(err)) if ignoreErrors { return nil } @@ -203,7 +204,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { var obj object.Object err = obj.Unmarshal(data) if err != nil { - c.reportFlushError("can't unmarshal an object", sAddr, err) + c.reportFlushError("can't unmarshal an object", sAddr, metaerr.Wrap(err)) if ignoreErrors { return nil } @@ -314,7 +315,7 @@ func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { for k, data := cs.Seek(nil); k != nil; k, data = cs.Next() { sa := string(k) if err := addr.DecodeString(sa); err != nil { - c.reportFlushError("can't decode object address from the DB", sa, err) + c.reportFlushError("can't decode object address from the DB", sa, metaerr.Wrap(err)) if ignoreErrors { continue } @@ -323,7 +324,7 @@ func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { var obj object.Object if err := obj.Unmarshal(data); err != nil { - c.reportFlushError("can't unmarshal an object from the DB", sa, err) + c.reportFlushError("can't unmarshal an object from the DB", sa, metaerr.Wrap(err)) if ignoreErrors { continue } diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go index aac5759ae..2546bada9 100644 --- a/pkg/local_object_storage/writecache/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -5,6 +5,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -28,7 +29,8 @@ func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, e )) defer span.End() - return c.getInternal(ctx, saddr, addr) + obj, err := c.getInternal(ctx, saddr, addr) + return obj, metaerr.Wrap(err) } func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) (*objectSDK.Object, error) { @@ -71,7 +73,7 @@ func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, obj, err := c.getInternal(ctx, saddr, addr) if err != nil { - return nil, err + return nil, metaerr.Wrap(err) } return obj.CutPayload(), nil @@ -95,5 +97,5 @@ func Get(db *bbolt.DB, key []byte) ([]byte, error) { value = slice.Copy(value) return nil }) - return value, err + return value, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/writecache/iterate.go b/pkg/local_object_storage/writecache/iterate.go index 59ace93bd..5349c069c 100644 --- a/pkg/local_object_storage/writecache/iterate.go +++ b/pkg/local_object_storage/writecache/iterate.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) @@ -18,7 +19,7 @@ var ErrNoDefaultBucket = errors.New("no default bucket") // // DB must not be nil and should be opened. func IterateDB(db *bbolt.DB, f func(oid.Address) error) error { - return db.View(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.View(func(tx *bbolt.Tx) error { b := tx.Bucket(defaultBucket) if b == nil { return ErrNoDefaultBucket @@ -34,5 +35,5 @@ func IterateDB(db *bbolt.DB, f func(oid.Address) error) error { return f(addr) }) - }) + })) } diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index 61e81ec30..619b2bd26 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" @@ -72,7 +73,7 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro if err == nil { added = true } - return common.PutRes{}, err + return common.PutRes{}, metaerr.Wrap(err) } // putSmall persists small objects to the write-cache database and diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 6fa0e36de..962c9c39a 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -129,14 +130,14 @@ func (c *cache) DumpInfo() Info { func (c *cache) Open(readOnly bool) error { err := c.openStore(readOnly) if err != nil { - return err + return metaerr.Wrap(err) } // Opening after Close is done during maintenance mode, // thus we need to create a channel here. c.closeCh = make(chan struct{}) - return c.initCounters() + return metaerr.Wrap(c.initCounters()) } // Init runs necessary services.