[#1969] local_object_storage: Add a type for logical errors

All logic errors are wrapped in `logicerr.Logical` type and do not
affect shard error counter.

Signed-off-by: Evgenii Stratonikov <evgeniy@morphbits.ru>
This commit is contained in:
Evgenii Stratonikov 2022-10-26 15:23:12 +03:00 committed by fyrchik
parent 98034005f1
commit fcdbf5e509
42 changed files with 206 additions and 139 deletions

View file

@ -1,8 +1,6 @@
package engine
import (
"errors"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"go.uber.org/zap"
@ -77,10 +75,9 @@ func (e *StorageEngine) containerSize(prm ContainerSizePrm) (res ContainerSizeRe
csPrm.SetContainerID(prm.cnr)
csRes, err := sh.Shard.ContainerSize(csPrm)
if err != nil && !errors.Is(err, shard.ErrDegradedMode) {
if err != nil {
e.reportShardError(sh, "can't get container size", err,
zap.Stringer("container_id", prm.cnr),
)
zap.Stringer("container_id", prm.cnr))
return false
}
@ -126,9 +123,7 @@ func (e *StorageEngine) listContainers() (ListContainersRes, error) {
e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) {
res, err := sh.Shard.ListContainers(shard.ListContainersPrm{})
if err != nil {
if !errors.Is(err, shard.ErrDegradedMode) {
e.reportShardError(sh, "can't get list of containers", err)
}
e.reportShardError(sh, "can't get list of containers", err)
return false
}

View file

@ -77,8 +77,8 @@ func (e *StorageEngine) delete(prm DeletePrm) (DeleteRes, error) {
return true
}
splitErr, ok := err.(*objectSDK.SplitInfoError)
if !ok {
var splitErr *objectSDK.SplitInfoError
if !errors.As(err, &splitErr) {
if !shard.IsErrNotFound(err) {
e.reportShardError(sh, "could not check object existence", err)
}
@ -97,13 +97,7 @@ func (e *StorageEngine) delete(prm DeletePrm) (DeleteRes, error) {
_, err = sh.Inhume(shPrm)
if err != nil {
if errors.Is(err, shard.ErrReadOnlyMode) || errors.Is(err, shard.ErrDegradedMode) {
e.log.Warn("could not inhume object in shard",
zap.Stringer("shard_id", sh.ID()),
zap.String("error", err.Error()))
} else {
e.reportShardError(sh, "could not inhume object in shard", err)
}
e.reportShardError(sh, "could not inhume object in shard", err)
locked.is = errors.As(err, &locked.err)

View file

@ -1,10 +1,12 @@
package engine
import (
"errors"
"sync"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util/logicerr"
"github.com/nspcc-dev/neofs-node/pkg/util"
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
"go.uber.org/atomic"
@ -40,6 +42,13 @@ func (e *StorageEngine) reportShardError(
msg string,
err error,
fields ...zap.Field) {
if isLogical(err) {
e.log.Warn(msg,
zap.Stringer("shard_id", sh.ID()),
zap.String("error", err.Error()))
return
}
sid := sh.ID()
errCount := sh.errorCount.Inc()
e.log.Warn(msg, append([]zap.Field{
@ -77,6 +86,10 @@ func (e *StorageEngine) reportShardError(
}
}
func isLogical(err error) bool {
return errors.As(err, &logicerr.Logical{})
}
// Option represents StorageEngine's constructor option.
type Option func(*cfg)

View file

@ -1,6 +1,8 @@
package engine
import (
"errors"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
@ -22,8 +24,8 @@ func (e *StorageEngine) exists(addr oid.Address) (bool, error) {
return true
}
_, ok := err.(*objectSDK.SplitInfoError)
if ok {
var siErr *objectSDK.SplitInfoError
if errors.As(err, &siErr) {
return true
}

View file

@ -5,6 +5,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util/logicerr"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
@ -90,8 +91,6 @@ func (e *StorageEngine) get(prm GetPrm) (GetRes, error) {
case shard.IsErrNotFound(err):
return false // ignore, go to next shard
case errors.As(err, &siErr):
siErr = err.(*objectSDK.SplitInfoError)
if outSI == nil {
outSI = objectSDK.NewSplitInfo()
}
@ -128,7 +127,7 @@ func (e *StorageEngine) get(prm GetPrm) (GetRes, error) {
})
if outSI != nil {
return GetRes{}, objectSDK.NewSplitInfoError(outSI)
return GetRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(outSI))
}
if obj == nil {

View file

@ -5,6 +5,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util/logicerr"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
@ -86,8 +87,6 @@ func (e *StorageEngine) head(prm HeadPrm) (HeadRes, error) {
case shard.IsErrNotFound(err):
return false // ignore, go to next shard
case errors.As(err, &siErr):
siErr = err.(*objectSDK.SplitInfoError)
if outSI == nil {
outSI = objectSDK.NewSplitInfo()
}
@ -127,7 +126,7 @@ func (e *StorageEngine) head(prm HeadPrm) (HeadRes, error) {
})
if outSI != nil {
return HeadRes{}, objectSDK.NewSplitInfoError(outSI)
return HeadRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(outSI))
}
if head == nil {

View file

@ -68,8 +68,8 @@ func TestHeadRaw(t *testing.T) {
_, err = e.Head(headPrm)
require.Error(t, err)
si, ok := err.(*object.SplitInfoError)
require.True(t, ok)
var si *object.SplitInfoError
require.ErrorAs(t, err, &si)
// SplitInfoError should contain info from both shards
require.Equal(t, splitID, si.SplitInfo().SplitID())

View file

@ -4,6 +4,7 @@ import (
"errors"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util/logicerr"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
@ -28,13 +29,13 @@ func (e *StorageEngine) lock(idCnr cid.ID, locker oid.ID, locked []oid.ID) error
for i := range locked {
switch e.lockSingle(idCnr, locker, locked[i], true) {
case 1:
return apistatus.LockNonRegularObject{}
return logicerr.Wrap(apistatus.LockNonRegularObject{})
case 0:
switch e.lockSingle(idCnr, locker, locked[i], false) {
case 1:
return apistatus.LockNonRegularObject{}
return logicerr.Wrap(apistatus.LockNonRegularObject{})
case 0:
return errLockFailed
return logicerr.Wrap(errLockFailed)
}
}
}

View file

@ -5,6 +5,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util/logicerr"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
@ -103,8 +104,6 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
case shard.IsErrNotFound(err):
return false // ignore, go to next shard
case errors.As(err, &siErr):
siErr = err.(*objectSDK.SplitInfoError)
if outSI == nil {
outSI = objectSDK.NewSplitInfo()
}
@ -138,7 +137,7 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
})
if outSI != nil {
return RngRes{}, objectSDK.NewSplitInfoError(outSI)
return RngRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(outSI))
}
if obj == nil {

View file

@ -1,8 +1,6 @@
package engine
import (
"errors"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/object"
@ -111,9 +109,7 @@ func (e *StorageEngine) list(limit uint64) (SelectRes, error) {
e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) {
res, err := sh.List() // consider limit result of shard iterator
if err != nil {
if !errors.Is(err, shard.ErrDegradedMode) {
e.reportShardError(sh, "could not select objects from shard", err)
}
e.reportShardError(sh, "could not select objects from shard", err)
} else {
for _, addr := range res.AddressList() { // save only unique values
if _, ok := uniqueMap[addr.EncodeToString()]; !ok {

View file

@ -8,13 +8,14 @@ import (
"github.com/nspcc-dev/hrw"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util/logicerr"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/panjf2000/ants/v2"
"go.uber.org/atomic"
"go.uber.org/zap"
)
var errShardNotFound = errors.New("shard not found")
var errShardNotFound = logicerr.Wrap(errors.New("shard not found"))
type hashedShard shardWrapper