[#135] get-object: Add tracing spans

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2023-03-13 14:37:35 +03:00 committed by fyrchik
parent 5af9f58469
commit 0920d848d0
80 changed files with 523 additions and 231 deletions

View file

@ -33,7 +33,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) {
var prm blobovnicza.GetPrm var prm blobovnicza.GetPrm
prm.SetAddress(addr) prm.SetAddress(addr)
res, err := blz.Get(prm) res, err := blz.Get(cmd.Context(), prm)
common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err))
data := res.Object() data := res.Object()

View file

@ -102,7 +102,7 @@ func initApp(ctx context.Context, c *cfg) {
initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) }) initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) })
initAndLog(c, "session", initSessionService) initAndLog(c, "session", initSessionService)
initAndLog(c, "reputation", func(c *cfg) { initReputationService(ctx, c) }) initAndLog(c, "reputation", func(c *cfg) { initReputationService(ctx, c) })
initAndLog(c, "notification", initNotifications) initAndLog(c, "notification", func(c *cfg) { initNotifications(ctx, c) })
initAndLog(c, "object", initObjectService) initAndLog(c, "object", initObjectService)
initAndLog(c, "tree", initTreeService) initAndLog(c, "tree", initTreeService)
initAndLog(c, "control", initControlService) initAndLog(c, "control", initControlService)

View file

@ -23,7 +23,7 @@ type notificationSource struct {
defaultTopic string defaultTopic string
} }
func (n *notificationSource) Iterate(epoch uint64, handler func(topic string, addr oid.Address)) { func (n *notificationSource) Iterate(ctx context.Context, epoch uint64, handler func(topic string, addr oid.Address)) {
log := n.l.With(zap.Uint64("epoch", epoch)) log := n.l.With(zap.Uint64("epoch", epoch))
listRes, err := n.e.ListContainers(engine.ListContainersPrm{}) listRes, err := n.e.ListContainers(engine.ListContainersPrm{})
@ -51,7 +51,7 @@ func (n *notificationSource) Iterate(epoch uint64, handler func(topic string, ad
} }
for _, a := range selectRes.AddressList() { for _, a := range selectRes.AddressList() {
err = n.processAddress(a, handler) err = n.processAddress(ctx, a, handler)
if err != nil { if err != nil {
log.Error("notificator: could not process object", log.Error("notificator: could not process object",
zap.Stringer("address", a), zap.Stringer("address", a),
@ -66,13 +66,14 @@ func (n *notificationSource) Iterate(epoch uint64, handler func(topic string, ad
} }
func (n *notificationSource) processAddress( func (n *notificationSource) processAddress(
ctx context.Context,
a oid.Address, a oid.Address,
h func(topic string, addr oid.Address), h func(topic string, addr oid.Address),
) error { ) error {
var prm engine.HeadPrm var prm engine.HeadPrm
prm.WithAddress(a) prm.WithAddress(a)
res, err := n.e.Head(prm) res, err := n.e.Head(ctx, prm)
if err != nil { if err != nil {
return err return err
} }
@ -108,7 +109,7 @@ func (n notificationWriter) Notify(topic string, address oid.Address) {
} }
} }
func initNotifications(c *cfg) { func initNotifications(ctx context.Context, c *cfg) {
if nodeconfig.Notification(c.appCfg).Enabled() { if nodeconfig.Notification(c.appCfg).Enabled() {
topic := nodeconfig.Notification(c.appCfg).DefaultTopic() topic := nodeconfig.Notification(c.appCfg).DefaultTopic()
pubKey := hex.EncodeToString(c.cfgNodeInfo.localInfo.PublicKey()) pubKey := hex.EncodeToString(c.cfgNodeInfo.localInfo.PublicKey())
@ -151,7 +152,7 @@ func initNotifications(c *cfg) {
addNewEpochAsyncNotificationHandler(c, func(e event.Event) { addNewEpochAsyncNotificationHandler(c, func(e event.Event) {
ev := e.(netmap.NewEpoch) ev := e.(netmap.NewEpoch)
n.ProcessEpoch(ev.EpochNumber()) n.ProcessEpoch(ctx, ev.EpochNumber())
}) })
} }
} }

6
go.mod
View file

@ -20,7 +20,6 @@ require (
github.com/multiformats/go-multiaddr v0.8.0 github.com/multiformats/go-multiaddr v0.8.0
github.com/nats-io/nats.go v1.22.1 github.com/nats-io/nats.go v1.22.1
github.com/nspcc-dev/neo-go v0.100.1 github.com/nspcc-dev/neo-go v0.100.1
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb // indirect
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
github.com/panjf2000/ants/v2 v2.4.0 github.com/panjf2000/ants/v2 v2.4.0
github.com/paulmach/orb v0.2.2 github.com/paulmach/orb v0.2.2
@ -31,6 +30,8 @@ require (
github.com/spf13/viper v1.15.0 github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.2
go.etcd.io/bbolt v1.3.6 go.etcd.io/bbolt v1.3.6
go.opentelemetry.io/otel v1.14.0
go.opentelemetry.io/otel/trace v1.14.0
go.uber.org/atomic v1.10.0 go.uber.org/atomic v1.10.0
go.uber.org/zap v1.24.0 go.uber.org/zap v1.24.0
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2
@ -80,6 +81,7 @@ require (
github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nkeys v0.3.0 // indirect
github.com/nats-io/nuid v1.0.1 // indirect github.com/nats-io/nuid v1.0.1 // indirect
github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect
github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb // indirect
github.com/nspcc-dev/rfc6979 v0.2.0 // indirect github.com/nspcc-dev/rfc6979 v0.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
@ -94,13 +96,11 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
github.com/twmb/murmur3 v1.1.5 // indirect github.com/twmb/murmur3 v1.1.5 // indirect
github.com/urfave/cli v1.22.5 // indirect github.com/urfave/cli v1.22.5 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 // indirect
go.opentelemetry.io/otel/sdk v1.14.0 // indirect go.opentelemetry.io/otel/sdk v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.4.0 // indirect golang.org/x/crypto v0.4.0 // indirect

View file

@ -1,6 +1,7 @@
package blobovnicza package blobovnicza
import ( import (
"context"
"errors" "errors"
"math/rand" "math/rand"
"os" "os"
@ -39,7 +40,7 @@ func testGet(t *testing.T, blz *Blobovnicza, addr oid.Address, expObj []byte, as
pGet.SetAddress(addr) pGet.SetAddress(addr)
// try to read object from Blobovnicza // try to read object from Blobovnicza
res, err := blz.Get(pGet) res, err := blz.Get(context.Background(), pGet)
if assertErr != nil { if assertErr != nil {
require.True(t, assertErr(err)) require.True(t, assertErr(err))
} else { } else {

View file

@ -1,12 +1,16 @@
package blobovnicza package blobovnicza
import ( import (
"context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/nspcc-dev/neo-go/pkg/util/slice"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// GetPrm groups the parameters of Get operation. // GetPrm groups the parameters of Get operation.
@ -39,7 +43,13 @@ var errInterruptForEach = errors.New("interrupt for-each")
// //
// Returns an error of type apistatus.ObjectNotFound if the requested object is not // Returns an error of type apistatus.ObjectNotFound if the requested object is not
// presented in Blobovnicza. // presented in Blobovnicza.
func (b *Blobovnicza) Get(prm GetPrm) (GetRes, error) { func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) {
_, span := tracing.StartSpanFromContext(ctx, "Blobovnicza.Get",
trace.WithAttributes(
attribute.String("address", prm.addr.EncodeToString()),
))
defer span.End()
var ( var (
data []byte data []byte
addrKey = addressKey(prm.addr) addrKey = addressKey(prm.addr)

View file

@ -1,6 +1,7 @@
package blobovnicza package blobovnicza
import ( import (
"context"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -56,7 +57,7 @@ func TestBlobovnicza_Get(t *testing.T) {
prmGet.SetAddress(addr) prmGet.SetAddress(addr)
checkObj := func() { checkObj := func() {
res, err := blz.Get(prmGet) res, err := blz.Get(context.Background(), prmGet)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, obj, res.Object()) require.Equal(t, obj, res.Object())

View file

@ -1,15 +1,27 @@
package blobovniczatree package blobovniczatree
import ( import (
"context"
"encoding/hex"
"path/filepath" "path/filepath"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
// Exists implements common.Storage. // Exists implements common.Storage.
func (b *Blobovniczas) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common.ExistsRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "Blobovniczas.Exists",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.String("storage_id", hex.EncodeToString(prm.StorageID)),
))
defer span.End()
if prm.StorageID != nil { if prm.StorageID != nil {
id := blobovnicza.NewIDFromBytes(prm.StorageID) id := blobovnicza.NewIDFromBytes(prm.StorageID)
blz, err := b.openBlobovnicza(id.String()) blz, err := b.openBlobovnicza(id.String())
@ -32,7 +44,7 @@ func (b *Blobovniczas) Exists(prm common.ExistsPrm) (common.ExistsRes, error) {
_, ok := activeCache[dirPath] _, ok := activeCache[dirPath]
_, err := b.getObjectFromLevel(gPrm, p, !ok) _, err := b.getObjectFromLevel(ctx, gPrm, p, !ok)
if err != nil { if err != nil {
if !blobovnicza.IsErrNotFound(err) { if !blobovnicza.IsErrNotFound(err) {
b.log.Debug("could not get object from level", b.log.Debug("could not get object from level",

View file

@ -1,6 +1,7 @@
package blobovniczatree package blobovniczatree
import ( import (
"context"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -44,7 +45,7 @@ func TestExistsInvalidStorageID(t *testing.T) {
storageID[0]-- storageID[0]--
} }
res, err := b.Exists(common.ExistsPrm{Address: addr, StorageID: storageID}) res, err := b.Exists(context.Background(), common.ExistsPrm{Address: addr, StorageID: storageID})
require.NoError(t, err) require.NoError(t, err)
require.False(t, res.Exists) require.False(t, res.Exists)
}) })
@ -57,7 +58,7 @@ func TestExistsInvalidStorageID(t *testing.T) {
require.NoError(t, os.Chmod(badDir, 0)) require.NoError(t, os.Chmod(badDir, 0))
t.Cleanup(func() { _ = os.Chmod(filepath.Join(dir, "9"), os.ModePerm) }) t.Cleanup(func() { _ = os.Chmod(filepath.Join(dir, "9"), os.ModePerm) })
res, err := b.Exists(common.ExistsPrm{Address: addr, StorageID: storageID}) res, err := b.Exists(context.Background(), common.ExistsPrm{Address: addr, StorageID: storageID})
require.Error(t, err) require.Error(t, err)
require.False(t, res.Exists) require.False(t, res.Exists)
}) })

View file

@ -1,14 +1,19 @@
package blobovniczatree package blobovniczatree
import ( import (
"context"
"encoding/hex"
"fmt" "fmt"
"path/filepath" "path/filepath"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -16,7 +21,15 @@ import (
// //
// If blobocvnicza ID is specified, only this blobovnicza is processed. // If blobocvnicza ID is specified, only this blobovnicza is processed.
// Otherwise, all Blobovniczas are processed descending weight. // Otherwise, all Blobovniczas are processed descending weight.
func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) { func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.GetRes, err error) {
ctx, span := tracing.StartSpanFromContext(ctx, "Blobovniczas.Get",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.String("storage_id", hex.EncodeToString(prm.StorageID)),
attribute.Bool("raw", prm.Raw),
))
defer span.End()
var bPrm blobovnicza.GetPrm var bPrm blobovnicza.GetPrm
bPrm.SetAddress(prm.Address) bPrm.SetAddress(prm.Address)
@ -27,7 +40,7 @@ func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) {
return res, err return res, err
} }
return b.getObject(blz, bPrm) return b.getObject(ctx, blz, bPrm)
} }
activeCache := make(map[string]struct{}) activeCache := make(map[string]struct{})
@ -37,7 +50,7 @@ func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) {
_, ok := activeCache[dirPath] _, ok := activeCache[dirPath]
res, err = b.getObjectFromLevel(bPrm, p, !ok) res, err = b.getObjectFromLevel(ctx, bPrm, p, !ok)
if err != nil { if err != nil {
if !blobovnicza.IsErrNotFound(err) { if !blobovnicza.IsErrNotFound(err) {
b.log.Debug("could not get object from level", b.log.Debug("could not get object from level",
@ -64,7 +77,7 @@ func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) {
// tries to read object from particular blobovnicza. // tries to read object from particular blobovnicza.
// //
// returns error if object could not be read from any blobovnicza of the same level. // returns error if object could not be read from any blobovnicza of the same level.
func (b *Blobovniczas) getObjectFromLevel(prm blobovnicza.GetPrm, blzPath string, tryActive bool) (common.GetRes, error) { func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string, tryActive bool) (common.GetRes, error) {
lvlPath := filepath.Dir(blzPath) lvlPath := filepath.Dir(blzPath)
// try to read from blobovnicza if it is opened // try to read from blobovnicza if it is opened
@ -72,7 +85,7 @@ func (b *Blobovniczas) getObjectFromLevel(prm blobovnicza.GetPrm, blzPath string
v, ok := b.opened.Get(blzPath) v, ok := b.opened.Get(blzPath)
b.lruMtx.Unlock() b.lruMtx.Unlock()
if ok { if ok {
if res, err := b.getObject(v, prm); err == nil { if res, err := b.getObject(ctx, v, prm); err == nil {
return res, err return res, err
} else if !blobovnicza.IsErrNotFound(err) { } else if !blobovnicza.IsErrNotFound(err) {
b.log.Debug("could not read object from opened blobovnicza", b.log.Debug("could not read object from opened blobovnicza",
@ -92,7 +105,7 @@ func (b *Blobovniczas) getObjectFromLevel(prm blobovnicza.GetPrm, blzPath string
b.activeMtx.RUnlock() b.activeMtx.RUnlock()
if ok && tryActive { if ok && tryActive {
if res, err := b.getObject(active.blz, prm); err == nil { if res, err := b.getObject(ctx, active.blz, prm); err == nil {
return res, err return res, err
} else if !blobovnicza.IsErrNotFound(err) { } else if !blobovnicza.IsErrNotFound(err) {
b.log.Debug("could not get object from active blobovnicza", b.log.Debug("could not get object from active blobovnicza",
@ -117,12 +130,12 @@ func (b *Blobovniczas) getObjectFromLevel(prm blobovnicza.GetPrm, blzPath string
return common.GetRes{}, err return common.GetRes{}, err
} }
return b.getObject(blz, prm) return b.getObject(ctx, blz, prm)
} }
// reads object from blobovnicza and returns GetSmallRes. // reads object from blobovnicza and returns GetSmallRes.
func (b *Blobovniczas) getObject(blz *blobovnicza.Blobovnicza, prm blobovnicza.GetPrm) (common.GetRes, error) { func (b *Blobovniczas) getObject(ctx context.Context, blz *blobovnicza.Blobovnicza, prm blobovnicza.GetPrm) (common.GetRes, error) {
res, err := blz.Get(prm) res, err := blz.Get(ctx, prm)
if err != nil { if err != nil {
return common.GetRes{}, err return common.GetRes{}, err
} }

View file

@ -1,14 +1,20 @@
package blobovniczatree package blobovniczatree
import ( import (
"context"
"encoding/hex"
"fmt" "fmt"
"path/filepath" "path/filepath"
"strconv"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -16,7 +22,16 @@ import (
// //
// If blobocvnicza ID is specified, only this blobovnicza is processed. // If blobocvnicza ID is specified, only this blobovnicza is processed.
// Otherwise, all Blobovniczas are processed descending weight. // Otherwise, all Blobovniczas are processed descending weight.
func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes, err error) { func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (res common.GetRangeRes, err error) {
ctx, span := tracing.StartSpanFromContext(ctx, "Blobovniczas.GetRange",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.String("storage_id", hex.EncodeToString(prm.StorageID)),
attribute.String("offset", strconv.FormatUint(prm.Range.GetOffset(), 10)),
attribute.String("length", strconv.FormatUint(prm.Range.GetLength(), 10)),
))
defer span.End()
if prm.StorageID != nil { if prm.StorageID != nil {
id := blobovnicza.NewIDFromBytes(prm.StorageID) id := blobovnicza.NewIDFromBytes(prm.StorageID)
blz, err := b.openBlobovnicza(id.String()) blz, err := b.openBlobovnicza(id.String())
@ -24,7 +39,7 @@ func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes,
return common.GetRangeRes{}, err return common.GetRangeRes{}, err
} }
return b.getObjectRange(blz, prm) return b.getObjectRange(ctx, blz, prm)
} }
activeCache := make(map[string]struct{}) activeCache := make(map[string]struct{})
@ -35,7 +50,7 @@ func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes,
_, ok := activeCache[dirPath] _, ok := activeCache[dirPath]
res, err = b.getRangeFromLevel(prm, p, !ok) res, err = b.getRangeFromLevel(ctx, prm, p, !ok)
if err != nil { if err != nil {
outOfBounds := isErrOutOfRange(err) outOfBounds := isErrOutOfRange(err)
if !outOfBounds && !blobovnicza.IsErrNotFound(err) { if !outOfBounds && !blobovnicza.IsErrNotFound(err) {
@ -68,7 +83,7 @@ func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes,
// tries to read range of object payload data from particular blobovnicza. // tries to read range of object payload data from particular blobovnicza.
// //
// returns error if object could not be read from any blobovnicza of the same level. // returns error if object could not be read from any blobovnicza of the same level.
func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string, tryActive bool) (common.GetRangeRes, error) { func (b *Blobovniczas) getRangeFromLevel(ctx context.Context, prm common.GetRangePrm, blzPath string, tryActive bool) (common.GetRangeRes, error) {
lvlPath := filepath.Dir(blzPath) lvlPath := filepath.Dir(blzPath)
// try to read from blobovnicza if it is opened // try to read from blobovnicza if it is opened
@ -76,7 +91,7 @@ func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string,
v, ok := b.opened.Get(blzPath) v, ok := b.opened.Get(blzPath)
b.lruMtx.Unlock() b.lruMtx.Unlock()
if ok { if ok {
res, err := b.getObjectRange(v, prm) res, err := b.getObjectRange(ctx, v, prm)
switch { switch {
case err == nil, case err == nil,
isErrOutOfRange(err): isErrOutOfRange(err):
@ -101,7 +116,7 @@ func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string,
b.activeMtx.RUnlock() b.activeMtx.RUnlock()
if ok && tryActive { if ok && tryActive {
res, err := b.getObjectRange(active.blz, prm) res, err := b.getObjectRange(ctx, active.blz, prm)
switch { switch {
case err == nil, case err == nil,
isErrOutOfRange(err): isErrOutOfRange(err):
@ -131,11 +146,11 @@ func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string,
return common.GetRangeRes{}, err return common.GetRangeRes{}, err
} }
return b.getObjectRange(blz, prm) return b.getObjectRange(ctx, blz, prm)
} }
// reads range of object payload data from blobovnicza and returns GetRangeSmallRes. // reads range of object payload data from blobovnicza and returns GetRangeSmallRes.
func (b *Blobovniczas) getObjectRange(blz *blobovnicza.Blobovnicza, prm common.GetRangePrm) (common.GetRangeRes, error) { func (b *Blobovniczas) getObjectRange(ctx context.Context, blz *blobovnicza.Blobovnicza, prm common.GetRangePrm) (common.GetRangeRes, error) {
var gPrm blobovnicza.GetPrm var gPrm blobovnicza.GetPrm
gPrm.SetAddress(prm.Address) gPrm.SetAddress(prm.Address)
@ -143,7 +158,7 @@ func (b *Blobovniczas) getObjectRange(blz *blobovnicza.Blobovnicza, prm common.G
// stores data that is compressed on BlobStor side. // stores data that is compressed on BlobStor side.
// If blobovnicza learns to do the compression itself, // If blobovnicza learns to do the compression itself,
// we can start using GetRange. // we can start using GetRange.
res, err := blz.Get(gPrm) res, err := blz.Get(ctx, gPrm)
if err != nil { if err != nil {
return common.GetRangeRes{}, err return common.GetRangeRes{}, err
} }

View file

@ -1,6 +1,7 @@
package blobstor package blobstor
import ( import (
"context"
"path/filepath" "path/filepath"
"testing" "testing"
@ -62,11 +63,11 @@ func TestCompression(t *testing.T) {
} }
testGet := func(t *testing.T, b *BlobStor, i int) { testGet := func(t *testing.T, b *BlobStor, i int) {
res1, err := b.Get(common.GetPrm{Address: object.AddressOf(smallObj[i])}) res1, err := b.Get(context.Background(), common.GetPrm{Address: object.AddressOf(smallObj[i])})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, smallObj[i], res1.Object) require.Equal(t, smallObj[i], res1.Object)
res2, err := b.Get(common.GetPrm{Address: object.AddressOf(bigObj[i])}) res2, err := b.Get(context.Background(), common.GetPrm{Address: object.AddressOf(bigObj[i])})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, bigObj[i], res2.Object) require.Equal(t, bigObj[i], res2.Object)
} }

View file

@ -1,6 +1,10 @@
package common package common
import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression"
)
// Storage represents key-value object storage. // Storage represents key-value object storage.
// It is used as a building block for a blobstor of a shard. // It is used as a building block for a blobstor of a shard.
@ -16,9 +20,9 @@ type Storage interface {
// This function MUST be called before Open. // This function MUST be called before Open.
SetReportErrorFunc(f func(string, error)) SetReportErrorFunc(f func(string, error))
Get(GetPrm) (GetRes, error) Get(context.Context, GetPrm) (GetRes, error)
GetRange(GetRangePrm) (GetRangeRes, error) GetRange(context.Context, GetRangePrm) (GetRangeRes, error)
Exists(ExistsPrm) (ExistsRes, error) Exists(context.Context, ExistsPrm) (ExistsRes, error)
Put(PutPrm) (PutRes, error) Put(PutPrm) (PutRes, error)
Delete(DeletePrm) (DeleteRes, error) Delete(DeletePrm) (DeleteRes, error)
Iterate(IteratePrm) (IterateRes, error) Iterate(IteratePrm) (IterateRes, error)

View file

@ -1,7 +1,13 @@
package blobstor package blobstor
import ( import (
"context"
"encoding/hex"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -9,15 +15,22 @@ import (
// //
// Returns any error encountered that did not allow // Returns any error encountered that did not allow
// to completely check object existence. // to completely check object existence.
func (b *BlobStor) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.ExistsRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Exists",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.String("storage_id", hex.EncodeToString(prm.StorageID)),
))
defer span.End()
b.modeMtx.RLock() b.modeMtx.RLock()
defer b.modeMtx.RUnlock() defer b.modeMtx.RUnlock()
if prm.StorageID != nil { if prm.StorageID != nil {
if len(prm.StorageID) == 0 { if len(prm.StorageID) == 0 {
return b.storage[len(b.storage)-1].Storage.Exists(prm) return b.storage[len(b.storage)-1].Storage.Exists(ctx, prm)
} }
return b.storage[0].Storage.Exists(prm) return b.storage[0].Storage.Exists(ctx, prm)
} }
// If there was an error during existence check below, // If there was an error during existence check below,
@ -31,7 +44,7 @@ func (b *BlobStor) Exists(prm common.ExistsPrm) (common.ExistsRes, error) {
// error | error | log the first error, return the second // error | error | log the first error, return the second
var errors []error var errors []error
for i := range b.storage { for i := range b.storage {
res, err := b.storage[i].Storage.Exists(prm) res, err := b.storage[i].Storage.Exists(ctx, prm)
if err == nil && res.Exists { if err == nil && res.Exists {
return res, nil return res, nil
} else if err != nil { } else if err != nil {

View file

@ -1,6 +1,7 @@
package blobstor package blobstor
import ( import (
"context"
"os" "os"
"testing" "testing"
@ -43,13 +44,13 @@ func TestExists(t *testing.T) {
for i := range objects { for i := range objects {
prm.Address = objectCore.AddressOf(objects[i]) prm.Address = objectCore.AddressOf(objects[i])
res, err := b.Exists(prm) res, err := b.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Exists) require.True(t, res.Exists)
} }
prm.Address = oidtest.Address() prm.Address = oidtest.Address()
res, err := b.Exists(prm) res, err := b.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.False(t, res.Exists) require.False(t, res.Exists)
@ -60,13 +61,13 @@ func TestExists(t *testing.T) {
// Object exists, first error is logged. // Object exists, first error is logged.
prm.Address = objectCore.AddressOf(objects[0]) prm.Address = objectCore.AddressOf(objects[0])
res, err := b.Exists(prm) res, err := b.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Exists) require.True(t, res.Exists)
// Object doesn't exist, first error is returned. // Object doesn't exist, first error is returned.
prm.Address = objectCore.AddressOf(objects[1]) prm.Address = objectCore.AddressOf(objects[1])
_, err = b.Exists(prm) _, err = b.Exists(context.Background(), prm)
require.Error(t, err) require.Error(t, err)
require.ErrorIs(t, err, teststore.ErrDiskExploded) require.ErrorIs(t, err, teststore.ErrDiskExploded)
}) })

View file

@ -1,6 +1,7 @@
package fstree package fstree
import ( import (
"context"
"crypto/sha256" "crypto/sha256"
"errors" "errors"
"fmt" "fmt"
@ -11,6 +12,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
@ -19,6 +21,8 @@ import (
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// FSTree represents an object storage as a filesystem tree. // FSTree represents an object storage as a filesystem tree.
@ -208,7 +212,13 @@ func (t *FSTree) Delete(prm common.DeletePrm) (common.DeleteRes, error) {
// Exists returns the path to the file with object contents if it exists in the storage // Exists returns the path to the file with object contents if it exists in the storage
// and an error otherwise. // and an error otherwise.
func (t *FSTree) Exists(prm common.ExistsPrm) (common.ExistsRes, error) { func (t *FSTree) Exists(ctx context.Context, prm common.ExistsPrm) (common.ExistsRes, error) {
_, span := tracing.StartSpanFromContext(ctx, "FSTree.Exists",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
))
defer span.End()
p := t.treePath(prm.Address) p := t.treePath(prm.Address)
_, err := os.Stat(p) _, err := os.Stat(p)
@ -336,16 +346,30 @@ func (t *FSTree) PutStream(addr oid.Address, handler func(*os.File) error) error
} }
// Get returns an object from the storage by address. // Get returns an object from the storage by address.
func (t *FSTree) Get(prm common.GetPrm) (common.GetRes, error) { func (t *FSTree) Get(ctx context.Context, prm common.GetPrm) (common.GetRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "FSTree.Get",
trace.WithAttributes(
attribute.Bool("raw", prm.Raw),
attribute.String("address", prm.Address.EncodeToString()),
))
defer span.End()
p := t.treePath(prm.Address) p := t.treePath(prm.Address)
if _, err := os.Stat(p); os.IsNotExist(err) { if _, err := os.Stat(p); os.IsNotExist(err) {
return common.GetRes{}, logicerr.Wrap(apistatus.ObjectNotFound{}) return common.GetRes{}, logicerr.Wrap(apistatus.ObjectNotFound{})
} }
data, err := os.ReadFile(p) var data []byte
if err != nil { var err error
return common.GetRes{}, err {
_, span := tracing.StartSpanFromContext(ctx, "FSTree.Get.ReadFile")
defer span.End()
data, err = os.ReadFile(p)
if err != nil {
return common.GetRes{}, err
}
} }
data, err = t.Decompress(data) data, err = t.Decompress(data)
@ -362,8 +386,16 @@ func (t *FSTree) Get(prm common.GetPrm) (common.GetRes, error) {
} }
// GetRange implements common.Storage. // GetRange implements common.Storage.
func (t *FSTree) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error) { func (t *FSTree) GetRange(ctx context.Context, prm common.GetRangePrm) (common.GetRangeRes, error) {
res, err := t.Get(common.GetPrm{Address: prm.Address}) ctx, span := tracing.StartSpanFromContext(ctx, "FSTree.GetRange",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.String("offset", strconv.FormatUint(prm.Range.GetOffset(), 10)),
attribute.String("length", strconv.FormatUint(prm.Range.GetLength(), 10)),
))
defer span.End()
res, err := t.Get(ctx, common.GetPrm{Address: prm.Address})
if err != nil { if err != nil {
return common.GetRangeRes{}, err return common.GetRangeRes{}, err
} }

View file

@ -1,23 +1,36 @@
package blobstor package blobstor
import ( import (
"context"
"encoding/hex"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// Get reads the object from b. // Get reads the object from b.
// If the descriptor is present, only one sub-storage is tried, // If the descriptor is present, only one sub-storage is tried,
// Otherwise, each sub-storage is tried in order. // Otherwise, each sub-storage is tried in order.
func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) { func (b *BlobStor) Get(ctx context.Context, prm common.GetPrm) (common.GetRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.Get",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.Bool("raw", prm.Raw),
attribute.String("storage_id", hex.EncodeToString(prm.StorageID)),
))
defer span.End()
b.modeMtx.RLock() b.modeMtx.RLock()
defer b.modeMtx.RUnlock() defer b.modeMtx.RUnlock()
if prm.StorageID == nil { if prm.StorageID == nil {
for i := range b.storage { for i := range b.storage {
res, err := b.storage[i].Storage.Get(prm) res, err := b.storage[i].Storage.Get(ctx, prm)
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) { if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
return res, err return res, err
} }
@ -26,7 +39,7 @@ func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) {
return common.GetRes{}, logicerr.Wrap(apistatus.ObjectNotFound{}) return common.GetRes{}, logicerr.Wrap(apistatus.ObjectNotFound{})
} }
if len(prm.StorageID) == 0 { if len(prm.StorageID) == 0 {
return b.storage[len(b.storage)-1].Storage.Get(prm) return b.storage[len(b.storage)-1].Storage.Get(ctx, prm)
} }
return b.storage[0].Storage.Get(prm) return b.storage[0].Storage.Get(ctx, prm)
} }

View file

@ -1,23 +1,38 @@
package blobstor package blobstor
import ( import (
"context"
"encoding/hex"
"errors" "errors"
"strconv"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// GetRange reads object payload data from b. // GetRange reads object payload data from b.
// If the descriptor is present, only one sub-storage is tried, // If the descriptor is present, only one sub-storage is tried,
// Otherwise, each sub-storage is tried in order. // Otherwise, each sub-storage is tried in order.
func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error) { func (b *BlobStor) GetRange(ctx context.Context, prm common.GetRangePrm) (common.GetRangeRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.GetRange",
trace.WithAttributes(
attribute.String("address", prm.Address.EncodeToString()),
attribute.String("storage_id", hex.EncodeToString(prm.StorageID)),
attribute.String("offset", strconv.FormatUint(prm.Range.GetOffset(), 10)),
attribute.String("length", strconv.FormatUint(prm.Range.GetLength(), 10)),
))
defer span.End()
b.modeMtx.RLock() b.modeMtx.RLock()
defer b.modeMtx.RUnlock() defer b.modeMtx.RUnlock()
if prm.StorageID == nil { if prm.StorageID == nil {
for i := range b.storage { for i := range b.storage {
res, err := b.storage[i].Storage.GetRange(prm) res, err := b.storage[i].Storage.GetRange(ctx, prm)
if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) { if err == nil || !errors.As(err, new(apistatus.ObjectNotFound)) {
return res, err return res, err
} }
@ -26,7 +41,7 @@ func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error)
return common.GetRangeRes{}, logicerr.Wrap(apistatus.ObjectNotFound{}) return common.GetRangeRes{}, logicerr.Wrap(apistatus.ObjectNotFound{})
} }
if len(prm.StorageID) == 0 { if len(prm.StorageID) == 0 {
return b.storage[len(b.storage)-1].Storage.GetRange(prm) return b.storage[len(b.storage)-1].Storage.GetRange(ctx, prm)
} }
return b.storage[0].Storage.GetRange(prm) return b.storage[0].Storage.GetRange(ctx, prm)
} }

View file

@ -1,6 +1,7 @@
package blobstortest package blobstortest
import ( import (
"context"
"math/rand" "math/rand"
"testing" "testing"
@ -26,7 +27,7 @@ func TestControl(t *testing.T, cons Constructor, min, max uint64) {
prm.StorageID = objects[i].storageID prm.StorageID = objects[i].storageID
prm.Raw = true prm.Raw = true
_, err := s.Get(prm) _, err := s.Get(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
} }

View file

@ -1,6 +1,7 @@
package blobstortest package blobstortest
import ( import (
"context"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
@ -35,18 +36,18 @@ func TestDelete(t *testing.T, cons Constructor, min, max uint64) {
t.Run("exists fail", func(t *testing.T) { t.Run("exists fail", func(t *testing.T) {
prm := common.ExistsPrm{Address: oidtest.Address()} prm := common.ExistsPrm{Address: oidtest.Address()}
res, err := s.Exists(prm) res, err := s.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.False(t, res.Exists) require.False(t, res.Exists)
}) })
t.Run("get fail", func(t *testing.T) { t.Run("get fail", func(t *testing.T) {
prm := common.GetPrm{Address: oidtest.Address()} prm := common.GetPrm{Address: oidtest.Address()}
_, err := s.Get(prm) _, err := s.Get(context.Background(), prm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("getrange fail", func(t *testing.T) { t.Run("getrange fail", func(t *testing.T) {
prm := common.GetRangePrm{Address: oidtest.Address()} prm := common.GetRangePrm{Address: oidtest.Address()}
_, err := s.GetRange(prm) _, err := s.GetRange(context.Background(), prm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
}) })
@ -75,7 +76,7 @@ func TestDelete(t *testing.T, cons Constructor, min, max uint64) {
prm.Address = objects[3].addr prm.Address = objects[3].addr
prm.Raw = true prm.Raw = true
res, err := s.Get(prm) res, err := s.Get(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objects[3].raw, res.RawData) require.Equal(t, objects[3].raw, res.RawData)
}) })

View file

@ -1,6 +1,7 @@
package blobstortest package blobstortest
import ( import (
"context"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
@ -18,7 +19,7 @@ func TestExists(t *testing.T, cons Constructor, min, max uint64) {
t.Run("missing object", func(t *testing.T) { t.Run("missing object", func(t *testing.T) {
prm := common.ExistsPrm{Address: oidtest.Address()} prm := common.ExistsPrm{Address: oidtest.Address()}
res, err := s.Exists(prm) res, err := s.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.False(t, res.Exists) require.False(t, res.Exists)
}) })
@ -29,7 +30,7 @@ func TestExists(t *testing.T, cons Constructor, min, max uint64) {
t.Run("without storage ID", func(t *testing.T) { t.Run("without storage ID", func(t *testing.T) {
prm.StorageID = nil prm.StorageID = nil
res, err := s.Exists(prm) res, err := s.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Exists) require.True(t, res.Exists)
}) })
@ -37,7 +38,7 @@ func TestExists(t *testing.T, cons Constructor, min, max uint64) {
t.Run("with storage ID", func(t *testing.T) { t.Run("with storage ID", func(t *testing.T) {
prm.StorageID = objects[0].storageID prm.StorageID = objects[0].storageID
res, err := s.Exists(prm) res, err := s.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Exists) require.True(t, res.Exists)
}) })

View file

@ -1,6 +1,7 @@
package blobstortest package blobstortest
import ( import (
"context"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
@ -19,7 +20,7 @@ func TestGet(t *testing.T, cons Constructor, min, max uint64) {
t.Run("missing object", func(t *testing.T) { t.Run("missing object", func(t *testing.T) {
gPrm := common.GetPrm{Address: oidtest.Address()} gPrm := common.GetPrm{Address: oidtest.Address()}
_, err := s.Get(gPrm) _, err := s.Get(context.Background(), gPrm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
@ -29,13 +30,13 @@ func TestGet(t *testing.T, cons Constructor, min, max uint64) {
// With storage ID. // With storage ID.
gPrm.StorageID = objects[i].storageID gPrm.StorageID = objects[i].storageID
res, err := s.Get(gPrm) res, err := s.Get(context.Background(), gPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objects[i].obj, res.Object) require.Equal(t, objects[i].obj, res.Object)
// Without storage ID. // Without storage ID.
gPrm.StorageID = nil gPrm.StorageID = nil
res, err = s.Get(gPrm) res, err = s.Get(context.Background(), gPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objects[i].obj, res.Object) require.Equal(t, objects[i].obj, res.Object)
@ -43,7 +44,7 @@ func TestGet(t *testing.T, cons Constructor, min, max uint64) {
gPrm.StorageID = objects[i].storageID gPrm.StorageID = objects[i].storageID
gPrm.Raw = true gPrm.Raw = true
res, err = s.Get(gPrm) res, err = s.Get(context.Background(), gPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objects[i].raw, res.RawData) require.Equal(t, objects[i].raw, res.RawData)
} }

View file

@ -1,6 +1,7 @@
package blobstortest package blobstortest
import ( import (
"context"
"math" "math"
"testing" "testing"
@ -20,7 +21,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
t.Run("missing object", func(t *testing.T) { t.Run("missing object", func(t *testing.T) {
gPrm := common.GetRangePrm{Address: oidtest.Address()} gPrm := common.GetRangePrm{Address: oidtest.Address()}
_, err := s.GetRange(gPrm) _, err := s.GetRange(context.Background(), gPrm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
@ -38,14 +39,14 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
t.Run("without storage ID", func(t *testing.T) { t.Run("without storage ID", func(t *testing.T) {
// Without storage ID. // Without storage ID.
res, err := s.GetRange(gPrm) res, err := s.GetRange(context.Background(), gPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, payload[start:stop], res.Data) require.Equal(t, payload[start:stop], res.Data)
}) })
t.Run("with storage ID", func(t *testing.T) { t.Run("with storage ID", func(t *testing.T) {
gPrm.StorageID = objects[0].storageID gPrm.StorageID = objects[0].storageID
res, err := s.GetRange(gPrm) res, err := s.GetRange(context.Background(), gPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, payload[start:stop], res.Data) require.Equal(t, payload[start:stop], res.Data)
}) })
@ -54,7 +55,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
gPrm.Range.SetOffset(uint64(len(payload) + 10)) gPrm.Range.SetOffset(uint64(len(payload) + 10))
gPrm.Range.SetLength(10) gPrm.Range.SetLength(10)
_, err := s.GetRange(gPrm) _, err := s.GetRange(context.Background(), gPrm)
require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange)) require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange))
}) })
@ -62,7 +63,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
gPrm.Range.SetOffset(10) gPrm.Range.SetOffset(10)
gPrm.Range.SetLength(uint64(len(payload))) gPrm.Range.SetLength(uint64(len(payload)))
_, err := s.GetRange(gPrm) _, err := s.GetRange(context.Background(), gPrm)
require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange)) require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange))
}) })
@ -70,7 +71,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
gPrm.Range.SetOffset(0) gPrm.Range.SetOffset(0)
gPrm.Range.SetLength(1 << 63) gPrm.Range.SetLength(1 << 63)
_, err := s.GetRange(gPrm) _, err := s.GetRange(context.Background(), gPrm)
require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange)) require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange))
}) })
@ -78,7 +79,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
gPrm.Range.SetOffset(10) gPrm.Range.SetOffset(10)
gPrm.Range.SetLength(math.MaxUint64 - 2) gPrm.Range.SetLength(math.MaxUint64 - 2)
_, err := s.GetRange(gPrm) _, err := s.GetRange(context.Background(), gPrm)
require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange)) require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange))
}) })
} }

View file

@ -2,6 +2,7 @@
package memstore package memstore
import ( import (
"context"
"fmt" "fmt"
"sync" "sync"
@ -32,7 +33,7 @@ func New(opts ...Option) common.Storage {
return st return st
} }
func (s *memstoreImpl) Get(req common.GetPrm) (common.GetRes, error) { func (s *memstoreImpl) Get(_ context.Context, req common.GetPrm) (common.GetRes, error) {
key := req.Address.EncodeToString() key := req.Address.EncodeToString()
s.mu.RLock() s.mu.RLock()
@ -58,8 +59,8 @@ func (s *memstoreImpl) Get(req common.GetPrm) (common.GetRes, error) {
return common.GetRes{Object: obj, RawData: data}, nil return common.GetRes{Object: obj, RawData: data}, nil
} }
func (s *memstoreImpl) GetRange(req common.GetRangePrm) (common.GetRangeRes, error) { func (s *memstoreImpl) GetRange(ctx context.Context, req common.GetRangePrm) (common.GetRangeRes, error) {
getResp, err := s.Get(common.GetPrm{ getResp, err := s.Get(ctx, common.GetPrm{
Address: req.Address, Address: req.Address,
StorageID: req.StorageID, StorageID: req.StorageID,
}) })
@ -80,7 +81,7 @@ func (s *memstoreImpl) GetRange(req common.GetRangePrm) (common.GetRangeRes, err
}, nil }, nil
} }
func (s *memstoreImpl) Exists(req common.ExistsPrm) (common.ExistsRes, error) { func (s *memstoreImpl) Exists(_ context.Context, req common.ExistsPrm) (common.ExistsRes, error) {
key := req.Address.EncodeToString() key := req.Address.EncodeToString()
s.mu.RLock() s.mu.RLock()

View file

@ -1,6 +1,7 @@
package memstore package memstore
import ( import (
"context"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
@ -32,13 +33,13 @@ func TestSimpleLifecycle(t *testing.T) {
} }
{ {
resp, err := s.Exists(common.ExistsPrm{Address: addr}) resp, err := s.Exists(context.Background(), common.ExistsPrm{Address: addr})
require.NoError(t, err) require.NoError(t, err)
require.True(t, resp.Exists) require.True(t, resp.Exists)
} }
{ {
resp, err := s.Get(common.GetPrm{Address: addr}) resp, err := s.Get(context.Background(), common.GetPrm{Address: addr})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, obj.Payload(), resp.Object.Payload()) require.Equal(t, obj.Payload(), resp.Object.Payload())
} }
@ -47,7 +48,7 @@ func TestSimpleLifecycle(t *testing.T) {
var objRange objectSDK.Range var objRange objectSDK.Range
objRange.SetOffset(256) objRange.SetOffset(256)
objRange.SetLength(512) objRange.SetLength(512)
resp, err := s.GetRange(common.GetRangePrm{ resp, err := s.GetRange(context.Background(), common.GetRangePrm{
Address: addr, Address: addr,
Range: objRange, Range: objRange,
}) })
@ -61,7 +62,7 @@ func TestSimpleLifecycle(t *testing.T) {
} }
{ {
resp, err := s.Exists(common.ExistsPrm{Address: addr}) resp, err := s.Exists(context.Background(), common.ExistsPrm{Address: addr})
require.NoError(t, err) require.NoError(t, err)
require.False(t, resp.Exists) require.False(t, resp.Exists)
} }

View file

@ -1,6 +1,7 @@
package blobstor package blobstor
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"testing" "testing"
@ -127,7 +128,7 @@ func BenchmarkSubstorageReadPerf(b *testing.B) {
b.ResetTimer() b.ResetTimer()
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
_, err := st.Get(common.GetPrm{Address: addrGen.Next()}) _, err := st.Get(context.Background(), common.GetPrm{Address: addrGen.Next()})
require.NoError(b, err) require.NoError(b, err)
} }
}) })

View file

@ -13,6 +13,7 @@
package teststore package teststore
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
@ -140,36 +141,36 @@ func (s *TestStore) SetReportErrorFunc(f func(string, error)) {
} }
} }
func (s *TestStore) Get(req common.GetPrm) (common.GetRes, error) { func (s *TestStore) Get(ctx context.Context, req common.GetPrm) (common.GetRes, error) {
switch { switch {
case s.overrides.Get != nil: case s.overrides.Get != nil:
return s.overrides.Get(req) return s.overrides.Get(req)
case s.st != nil: case s.st != nil:
return s.st.Get(req) return s.st.Get(ctx, req)
default: default:
panic(fmt.Sprintf("unexpected storage call: Get(%+v)", req)) panic(fmt.Sprintf("unexpected storage call: Get(%+v)", req))
} }
} }
func (s *TestStore) GetRange(req common.GetRangePrm) (common.GetRangeRes, error) { func (s *TestStore) GetRange(ctx context.Context, req common.GetRangePrm) (common.GetRangeRes, error) {
s.mu.RLock() s.mu.RLock()
defer s.mu.RUnlock() defer s.mu.RUnlock()
switch { switch {
case s.overrides.GetRange != nil: case s.overrides.GetRange != nil:
return s.overrides.GetRange(req) return s.overrides.GetRange(req)
case s.st != nil: case s.st != nil:
return s.st.GetRange(req) return s.st.GetRange(ctx, req)
default: default:
panic(fmt.Sprintf("unexpected storage call: GetRange(%+v)", req)) panic(fmt.Sprintf("unexpected storage call: GetRange(%+v)", req))
} }
} }
func (s *TestStore) Exists(req common.ExistsPrm) (common.ExistsRes, error) { func (s *TestStore) Exists(ctx context.Context, req common.ExistsPrm) (common.ExistsRes, error) {
switch { switch {
case s.overrides.Exists != nil: case s.overrides.Exists != nil:
return s.overrides.Exists(req) return s.overrides.Exists(req)
case s.st != nil: case s.st != nil:
return s.st.Exists(req) return s.st.Exists(ctx, req)
default: default:
panic(fmt.Sprintf("unexpected storage call: Exists(%+v)", req)) panic(fmt.Sprintf("unexpected storage call: Exists(%+v)", req))
} }

View file

@ -212,20 +212,20 @@ func TestExecBlocks(t *testing.T) {
require.NoError(t, e.BlockExecution(errBlock)) require.NoError(t, e.BlockExecution(errBlock))
// try to exec some op // try to exec some op
_, err := Head(e, addr) _, err := Head(context.Background(), e, addr)
require.ErrorIs(t, err, errBlock) require.ErrorIs(t, err, errBlock)
// resume executions // resume executions
require.NoError(t, e.ResumeExecution()) require.NoError(t, e.ResumeExecution())
_, err = Head(e, addr) // can be any data-related op _, err = Head(context.Background(), e, addr) // can be any data-related op
require.NoError(t, err) require.NoError(t, err)
// close // close
require.NoError(t, e.Close()) require.NoError(t, e.Close())
// try exec after close // try exec after close
_, err = Head(e, addr) _, err = Head(context.Background(), e, addr)
require.Error(t, err) require.Error(t, err)
// try to resume // try to resume

View file

@ -72,7 +72,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e
var existsPrm shard.ExistsPrm var existsPrm shard.ExistsPrm
existsPrm.SetAddress(prm.addr) existsPrm.SetAddress(prm.addr)
resExists, err := sh.Exists(existsPrm) resExists, err := sh.Exists(ctx, existsPrm)
if err != nil { if err != nil {
if shard.IsErrRemoved(err) || shard.IsErrObjectExpired(err) { if shard.IsErrRemoved(err) || shard.IsErrObjectExpired(err) {
return true return true

View file

@ -93,7 +93,7 @@ func checkGetError(t *testing.T, e *StorageEngine, addr oid.Address, expected an
var getPrm GetPrm var getPrm GetPrm
getPrm.WithAddress(addr) getPrm.WithAddress(addr)
_, err := e.Get(getPrm) _, err := e.Get(context.Background(), getPrm)
if expected != nil { if expected != nil {
require.ErrorAs(t, err, expected) require.ErrorAs(t, err, expected)
} else { } else {

View file

@ -102,7 +102,7 @@ func TestErrorReporting(t *testing.T) {
te.ng.mtx.RUnlock() te.ng.mtx.RUnlock()
require.NoError(t, err) require.NoError(t, err)
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)}) _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
require.NoError(t, err) require.NoError(t, err)
checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite)
@ -115,7 +115,7 @@ func TestErrorReporting(t *testing.T) {
} }
for i := uint32(1); i < 3; i++ { for i := uint32(1); i < 3; i++ {
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)}) _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
require.Error(t, err) require.Error(t, err)
checkShardState(t, te.ng, te.shards[0].id, i, mode.ReadWrite) checkShardState(t, te.ng, te.shards[0].id, i, mode.ReadWrite)
checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite)
@ -136,7 +136,7 @@ func TestErrorReporting(t *testing.T) {
te.ng.mtx.RUnlock() te.ng.mtx.RUnlock()
require.NoError(t, err) require.NoError(t, err)
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)}) _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
require.NoError(t, err) require.NoError(t, err)
checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite)
@ -149,14 +149,14 @@ func TestErrorReporting(t *testing.T) {
} }
for i := uint32(1); i < errThreshold; i++ { for i := uint32(1); i < errThreshold; i++ {
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)}) _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
require.Error(t, err) require.Error(t, err)
checkShardState(t, te.ng, te.shards[0].id, i, mode.ReadWrite) checkShardState(t, te.ng, te.shards[0].id, i, mode.ReadWrite)
checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite)
} }
for i := uint32(0); i < 2; i++ { for i := uint32(0); i < 2; i++ {
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)}) _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
require.Error(t, err) require.Error(t, err)
checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.DegradedReadOnly) checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.DegradedReadOnly)
checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite)
@ -193,9 +193,9 @@ func TestBlobstorFailback(t *testing.T) {
for i := range objs { for i := range objs {
addr := object.AddressOf(objs[i]) addr := object.AddressOf(objs[i])
_, err = te.ng.Get(GetPrm{addr: addr}) _, err = te.ng.Get(context.Background(), GetPrm{addr: addr})
require.NoError(t, err) require.NoError(t, err)
_, err = te.ng.GetRange(RngPrm{addr: addr}) _, err = te.ng.GetRange(context.Background(), RngPrm{addr: addr})
require.NoError(t, err) require.NoError(t, err)
} }
@ -213,15 +213,15 @@ func TestBlobstorFailback(t *testing.T) {
for i := range objs { for i := range objs {
addr := object.AddressOf(objs[i]) addr := object.AddressOf(objs[i])
getRes, err := te.ng.Get(GetPrm{addr: addr}) getRes, err := te.ng.Get(context.Background(), GetPrm{addr: addr})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objs[i], getRes.Object()) require.Equal(t, objs[i], getRes.Object())
rngRes, err := te.ng.GetRange(RngPrm{addr: addr, off: 1, ln: 10}) rngRes, err := te.ng.GetRange(context.Background(), RngPrm{addr: addr, off: 1, ln: 10})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objs[i].Payload()[1:11], rngRes.Object().Payload()) require.Equal(t, objs[i].Payload()[1:11], rngRes.Object().Payload())
_, err = te.ng.GetRange(RngPrm{addr: addr, off: errSmallSize + 10, ln: 1}) _, err = te.ng.GetRange(context.Background(), RngPrm{addr: addr, off: errSmallSize + 10, ln: 1})
require.ErrorAs(t, err, &apistatus.ObjectOutOfRange{}) require.ErrorAs(t, err, &apistatus.ObjectOutOfRange{})
} }

View file

@ -1,6 +1,7 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
@ -58,7 +59,7 @@ var errMustHaveTwoShards = errors.New("must have at least 1 spare shard")
// Evacuate moves data from one shard to the others. // Evacuate moves data from one shard to the others.
// The shard being moved must be in read-only mode. // The shard being moved must be in read-only mode.
func (e *StorageEngine) Evacuate(prm EvacuateShardPrm) (EvacuateShardRes, error) { func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (EvacuateShardRes, error) {
shardIDs := make([]string, len(prm.shardID)) shardIDs := make([]string, len(prm.shardID))
for i := range prm.shardID { for i := range prm.shardID {
shardIDs[i] = prm.shardID[i].String() shardIDs[i] = prm.shardID[i].String()
@ -83,7 +84,7 @@ func (e *StorageEngine) Evacuate(prm EvacuateShardPrm) (EvacuateShardRes, error)
var res EvacuateShardRes var res EvacuateShardRes
for _, shardID := range shardIDs { for _, shardID := range shardIDs {
if err = e.evacuateShard(shardID, prm, &res, shards, weights, shardsToEvacuate); err != nil { if err = e.evacuateShard(ctx, shardID, prm, &res, shards, weights, shardsToEvacuate); err != nil {
return res, err return res, err
} }
} }
@ -92,7 +93,7 @@ func (e *StorageEngine) Evacuate(prm EvacuateShardPrm) (EvacuateShardRes, error)
return res, nil return res, nil
} }
func (e *StorageEngine) evacuateShard(shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes,
shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error { shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error {
var listPrm shard.ListWithCursorPrm var listPrm shard.ListWithCursorPrm
listPrm.WithCount(defaultEvacuateBatchSize) listPrm.WithCount(defaultEvacuateBatchSize)
@ -113,7 +114,7 @@ func (e *StorageEngine) evacuateShard(shardID string, prm EvacuateShardPrm, res
return err return err
} }
if err = e.evacuateObjects(sh, listRes.AddressList(), prm, res, shards, weights, shardsToEvacuate); err != nil { if err = e.evacuateObjects(ctx, sh, listRes.AddressList(), prm, res, shards, weights, shardsToEvacuate); err != nil {
return err return err
} }
@ -160,7 +161,7 @@ func (e *StorageEngine) getActualShards(shardIDs []string, handlerDefined bool)
return shards, weights, nil return shards, weights, nil
} }
func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.AddressWithType, prm EvacuateShardPrm, res *EvacuateShardRes, func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, toEvacuate []object.AddressWithType, prm EvacuateShardPrm, res *EvacuateShardRes,
shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error { shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error {
for i := range toEvacuate { for i := range toEvacuate {
addr := toEvacuate[i].Address addr := toEvacuate[i].Address
@ -168,7 +169,7 @@ func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.Add
var getPrm shard.GetPrm var getPrm shard.GetPrm
getPrm.SetAddress(addr) getPrm.SetAddress(addr)
getRes, err := sh.Get(getPrm) getRes, err := sh.Get(ctx, getPrm)
if err != nil { if err != nil {
if prm.ignoreErrors { if prm.ignoreErrors {
continue continue
@ -176,7 +177,7 @@ func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.Add
return err return err
} }
if e.tryEvacuateObject(addr, getRes.Object(), sh, res, shards, weights, shardsToEvacuate) { if e.tryEvacuateObject(ctx, addr, getRes.Object(), sh, res, shards, weights, shardsToEvacuate) {
continue continue
} }
@ -195,14 +196,14 @@ func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.Add
return nil return nil
} }
func (e *StorageEngine) tryEvacuateObject(addr oid.Address, object *objectSDK.Object, sh *shard.Shard, res *EvacuateShardRes, func (e *StorageEngine) tryEvacuateObject(ctx context.Context, addr oid.Address, object *objectSDK.Object, sh *shard.Shard, res *EvacuateShardRes,
shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) bool { shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) bool {
hrw.SortHasherSliceByWeightValue(shards, weights, hrw.Hash([]byte(addr.EncodeToString()))) hrw.SortHasherSliceByWeightValue(shards, weights, hrw.Hash([]byte(addr.EncodeToString())))
for j := range shards { for j := range shards {
if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok { if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok {
continue continue
} }
putDone, exists := e.putToShard(shards[j].hashedShard, j, shards[j].pool, addr, object) putDone, exists := e.putToShard(ctx, shards[j].hashedShard, j, shards[j].pool, addr, object)
if putDone || exists { if putDone || exists {
if putDone { if putDone {
e.log.Debug("object is moved to another shard", e.log.Debug("object is moved to another shard",

View file

@ -91,7 +91,7 @@ func TestEvacuateShard(t *testing.T) {
var prm GetPrm var prm GetPrm
prm.WithAddress(objectCore.AddressOf(objects[i])) prm.WithAddress(objectCore.AddressOf(objects[i]))
_, err := e.Get(prm) _, err := e.Get(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -102,14 +102,14 @@ func TestEvacuateShard(t *testing.T) {
prm.WithShardIDList(ids[2:3]) prm.WithShardIDList(ids[2:3])
t.Run("must be read-only", func(t *testing.T) { t.Run("must be read-only", func(t *testing.T) {
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.ErrorIs(t, err, shard.ErrMustBeReadOnly) require.ErrorIs(t, err, shard.ErrMustBeReadOnly)
require.Equal(t, 0, res.Count()) require.Equal(t, 0, res.Count())
}) })
require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly)) require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly))
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objPerShard, res.count) require.Equal(t, objPerShard, res.count)
@ -120,7 +120,7 @@ func TestEvacuateShard(t *testing.T) {
checkHasObjects(t) checkHasObjects(t)
// Calling it again is OK, but all objects are already moved, so no new PUTs should be done. // Calling it again is OK, but all objects are already moved, so no new PUTs should be done.
res, err = e.Evacuate(prm) res, err = e.Evacuate(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 0, res.count) require.Equal(t, 0, res.count)
@ -165,13 +165,13 @@ func TestEvacuateNetwork(t *testing.T) {
var prm EvacuateShardPrm var prm EvacuateShardPrm
prm.shardID = ids[0:1] prm.shardID = ids[0:1]
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.ErrorIs(t, err, errMustHaveTwoShards) require.ErrorIs(t, err, errMustHaveTwoShards)
require.Equal(t, 0, res.Count()) require.Equal(t, 0, res.Count())
prm.handler = acceptOneOf(objects, 2) prm.handler = acceptOneOf(objects, 2)
res, err = e.Evacuate(prm) res, err = e.Evacuate(context.Background(), prm)
require.ErrorIs(t, err, errReplication) require.ErrorIs(t, err, errReplication)
require.Equal(t, 2, res.Count()) require.Equal(t, 2, res.Count())
}) })
@ -185,14 +185,14 @@ func TestEvacuateNetwork(t *testing.T) {
prm.shardID = ids[1:2] prm.shardID = ids[1:2]
prm.handler = acceptOneOf(objects, 2) prm.handler = acceptOneOf(objects, 2)
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.ErrorIs(t, err, errReplication) require.ErrorIs(t, err, errReplication)
require.Equal(t, 2, res.Count()) require.Equal(t, 2, res.Count())
t.Run("no errors", func(t *testing.T) { t.Run("no errors", func(t *testing.T) {
prm.handler = acceptOneOf(objects, 3) prm.handler = acceptOneOf(objects, 3)
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 3, res.Count()) require.Equal(t, 3, res.Count())
}) })
@ -217,14 +217,14 @@ func TestEvacuateNetwork(t *testing.T) {
prm.shardID = evacuateIDs prm.shardID = evacuateIDs
prm.handler = acceptOneOf(objects, totalCount-1) prm.handler = acceptOneOf(objects, totalCount-1)
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.ErrorIs(t, err, errReplication) require.ErrorIs(t, err, errReplication)
require.Equal(t, totalCount-1, res.Count()) require.Equal(t, totalCount-1, res.Count())
t.Run("no errors", func(t *testing.T) { t.Run("no errors", func(t *testing.T) {
prm.handler = acceptOneOf(objects, totalCount) prm.handler = acceptOneOf(objects, totalCount)
res, err := e.Evacuate(prm) res, err := e.Evacuate(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, totalCount, res.Count()) require.Equal(t, totalCount, res.Count())
}) })

View file

@ -1,6 +1,7 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
@ -16,7 +17,7 @@ func (e *StorageEngine) exists(addr oid.Address) (bool, error) {
exists := false exists := false
e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) {
res, err := sh.Exists(shPrm) res, err := sh.Exists(context.TODO(), shPrm)
if err != nil { if err != nil {
if shard.IsErrRemoved(err) { if shard.IsErrRemoved(err) {
alreadyRemoved = true alreadyRemoved = true

View file

@ -1,14 +1,18 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -43,16 +47,22 @@ func (r GetRes) Object() *objectSDK.Object {
// Returns an error of type apistatus.ObjectAlreadyRemoved if the object has been marked as removed. // Returns an error of type apistatus.ObjectAlreadyRemoved if the object has been marked as removed.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
func (e *StorageEngine) Get(prm GetPrm) (res GetRes, err error) { func (e *StorageEngine) Get(ctx context.Context, prm GetPrm) (res GetRes, err error) {
err = e.execIfNotBlocked(func() error { err = e.execIfNotBlocked(func() error {
res, err = e.get(prm) res, err = e.get(ctx, prm)
return err return err
}) })
return return
} }
func (e *StorageEngine) get(prm GetPrm) (GetRes, error) { func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.get",
trace.WithAttributes(
attribute.String("address", prm.addr.EncodeToString()),
))
defer span.End()
if e.metrics != nil { if e.metrics != nil {
defer elapsed(e.metrics.AddGetDuration)() defer elapsed(e.metrics.AddGetDuration)()
} }
@ -69,7 +79,7 @@ func (e *StorageEngine) get(prm GetPrm) (GetRes, error) {
Engine: e, Engine: e,
} }
it.tryGetWithMeta() it.tryGetWithMeta(ctx)
if it.SplitInfo != nil { if it.SplitInfo != nil {
return GetRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo)) return GetRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo))
@ -84,7 +94,7 @@ func (e *StorageEngine) get(prm GetPrm) (GetRes, error) {
return GetRes{}, it.OutError return GetRes{}, it.OutError
} }
it.tryGetFromBlobstore() it.tryGetFromBlobstore(ctx)
if it.Object == nil { if it.Object == nil {
return GetRes{}, it.OutError return GetRes{}, it.OutError
@ -116,14 +126,14 @@ type getShardIterator struct {
splitInfoErr *objectSDK.SplitInfoError splitInfoErr *objectSDK.SplitInfoError
} }
func (i *getShardIterator) tryGetWithMeta() { func (i *getShardIterator) tryGetWithMeta(ctx context.Context) {
i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) { i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) {
noMeta := sh.GetMode().NoMetabase() noMeta := sh.GetMode().NoMetabase()
i.ShardPrm.SetIgnoreMeta(noMeta) i.ShardPrm.SetIgnoreMeta(noMeta)
i.HasDegraded = i.HasDegraded || noMeta i.HasDegraded = i.HasDegraded || noMeta
res, err := sh.Get(i.ShardPrm) res, err := sh.Get(ctx, i.ShardPrm)
if err == nil { if err == nil {
i.Object = res.Object() i.Object = res.Object()
return true return true
@ -162,7 +172,7 @@ func (i *getShardIterator) tryGetWithMeta() {
}) })
} }
func (i *getShardIterator) tryGetFromBlobstore() { func (i *getShardIterator) tryGetFromBlobstore(ctx context.Context) {
// If the object is not found but is present in metabase, // If the object is not found but is present in metabase,
// try to fetch it from blobstor directly. If it is found in any // try to fetch it from blobstor directly. If it is found in any
// blobstor, increase the error counter for the shard which contains the meta. // blobstor, increase the error counter for the shard which contains the meta.
@ -174,18 +184,18 @@ func (i *getShardIterator) tryGetFromBlobstore() {
return false return false
} }
res, err := sh.Get(i.ShardPrm) res, err := sh.Get(ctx, i.ShardPrm)
i.Object = res.Object() i.Object = res.Object()
return err == nil return err == nil
}) })
} }
// Get reads object from local storage by provided address. // Get reads object from local storage by provided address.
func Get(storage *StorageEngine, addr oid.Address) (*objectSDK.Object, error) { func Get(ctx context.Context, storage *StorageEngine, addr oid.Address) (*objectSDK.Object, error) {
var getPrm GetPrm var getPrm GetPrm
getPrm.WithAddress(addr) getPrm.WithAddress(addr)
res, err := storage.Get(getPrm) res, err := storage.Get(ctx, getPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,8 +1,10 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
@ -52,16 +54,19 @@ func (r HeadRes) Header() *objectSDK.Object {
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object was inhumed. // Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object was inhumed.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
func (e *StorageEngine) Head(prm HeadPrm) (res HeadRes, err error) { func (e *StorageEngine) Head(ctx context.Context, prm HeadPrm) (res HeadRes, err error) {
err = e.execIfNotBlocked(func() error { err = e.execIfNotBlocked(func() error {
res, err = e.head(prm) res, err = e.head(ctx, prm)
return err return err
}) })
return return
} }
func (e *StorageEngine) head(prm HeadPrm) (HeadRes, error) { func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.head")
defer span.End()
if e.metrics != nil { if e.metrics != nil {
defer elapsed(e.metrics.AddHeadDuration)() defer elapsed(e.metrics.AddHeadDuration)()
} }
@ -81,7 +86,7 @@ func (e *StorageEngine) head(prm HeadPrm) (HeadRes, error) {
shPrm.SetRaw(prm.raw) shPrm.SetRaw(prm.raw)
e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) { e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) {
res, err := sh.Head(shPrm) res, err := sh.Head(ctx, shPrm)
if err != nil { if err != nil {
switch { switch {
case shard.IsErrNotFound(err): case shard.IsErrNotFound(err):
@ -139,11 +144,11 @@ func (e *StorageEngine) head(prm HeadPrm) (HeadRes, error) {
} }
// Head reads object header from local storage by provided address. // Head reads object header from local storage by provided address.
func Head(storage *StorageEngine, addr oid.Address) (*objectSDK.Object, error) { func Head(ctx context.Context, storage *StorageEngine, addr oid.Address) (*objectSDK.Object, error) {
var headPrm HeadPrm var headPrm HeadPrm
headPrm.WithAddress(addr) headPrm.WithAddress(addr)
res, err := storage.Head(headPrm) res, err := storage.Head(ctx, headPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -153,12 +158,12 @@ func Head(storage *StorageEngine, addr oid.Address) (*objectSDK.Object, error) {
// HeadRaw reads object header from local storage by provided address and raw // HeadRaw reads object header from local storage by provided address and raw
// flag. // flag.
func HeadRaw(storage *StorageEngine, addr oid.Address, raw bool) (*objectSDK.Object, error) { func HeadRaw(ctx context.Context, storage *StorageEngine, addr oid.Address, raw bool) (*objectSDK.Object, error) {
var headPrm HeadPrm var headPrm HeadPrm
headPrm.WithAddress(addr) headPrm.WithAddress(addr)
headPrm.WithRaw(raw) headPrm.WithRaw(raw)
res, err := storage.Head(headPrm) res, err := storage.Head(ctx, headPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,6 +1,7 @@
package engine package engine
import ( import (
"context"
"os" "os"
"testing" "testing"
@ -66,7 +67,7 @@ func TestHeadRaw(t *testing.T) {
headPrm.WithAddress(parentAddr) headPrm.WithAddress(parentAddr)
headPrm.WithRaw(true) headPrm.WithRaw(true)
_, err = e.Head(headPrm) _, err = e.Head(context.Background(), headPrm)
require.Error(t, err) require.Error(t, err)
var si *object.SplitInfoError var si *object.SplitInfoError

View file

@ -134,7 +134,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh
if checkExists { if checkExists {
existPrm.SetAddress(addr) existPrm.SetAddress(addr)
exRes, err := sh.Exists(existPrm) exRes, err := sh.Exists(ctx, existPrm)
if err != nil { if err != nil {
if shard.IsErrRemoved(err) || shard.IsErrObjectExpired(err) { if shard.IsErrRemoved(err) || shard.IsErrObjectExpired(err) {
// inhumed once - no need to be inhumed again // inhumed once - no need to be inhumed again

View file

@ -1,6 +1,7 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
@ -69,7 +70,7 @@ func (e *StorageEngine) lockSingle(idCnr cid.ID, locker, locked oid.ID, checkExi
var existsPrm shard.ExistsPrm var existsPrm shard.ExistsPrm
existsPrm.SetAddress(addrLocked) existsPrm.SetAddress(addrLocked)
exRes, err := sh.Exists(existsPrm) exRes, err := sh.Exists(context.TODO(), existsPrm)
if err != nil { if err != nil {
var siErr *objectSDK.SplitInfoError var siErr *objectSDK.SplitInfoError
if !errors.As(err, &siErr) { if !errors.As(err, &siErr) {

View file

@ -1,6 +1,7 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
@ -72,7 +73,7 @@ func (e *StorageEngine) put(prm PutPrm) (PutRes, error) {
return false return false
} }
putDone, exists := e.putToShard(sh, ind, pool, addr, prm.obj) putDone, exists := e.putToShard(context.TODO(), sh, ind, pool, addr, prm.obj)
finished = putDone || exists finished = putDone || exists
return finished return finished
}) })
@ -87,7 +88,7 @@ func (e *StorageEngine) put(prm PutPrm) (PutRes, error) {
// putToShard puts object to sh. // putToShard puts object to sh.
// First return value is true iff put has been successfully done. // First return value is true iff put has been successfully done.
// Second return value is true iff object already exists. // Second return value is true iff object already exists.
func (e *StorageEngine) putToShard(sh hashedShard, ind int, pool util.WorkerPool, addr oid.Address, obj *objectSDK.Object) (bool, bool) { func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, pool util.WorkerPool, addr oid.Address, obj *objectSDK.Object) (bool, bool) {
var putSuccess, alreadyExists bool var putSuccess, alreadyExists bool
exitCh := make(chan struct{}) exitCh := make(chan struct{})
@ -98,7 +99,7 @@ func (e *StorageEngine) putToShard(sh hashedShard, ind int, pool util.WorkerPool
var existPrm shard.ExistsPrm var existPrm shard.ExistsPrm
existPrm.SetAddress(addr) existPrm.SetAddress(addr)
exists, err := sh.Exists(existPrm) exists, err := sh.Exists(ctx, existPrm)
if err != nil { if err != nil {
if shard.IsErrObjectExpired(err) { if shard.IsErrObjectExpired(err) {
// object is already found but // object is already found but

View file

@ -1,14 +1,19 @@
package engine package engine
import ( import (
"context"
"errors" "errors"
"strconv"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -56,16 +61,24 @@ func (r RngRes) Object() *objectSDK.Object {
// Returns ErrRangeOutOfBounds if the requested object range is out of bounds. // Returns ErrRangeOutOfBounds if the requested object range is out of bounds.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
func (e *StorageEngine) GetRange(prm RngPrm) (res RngRes, err error) { func (e *StorageEngine) GetRange(ctx context.Context, prm RngPrm) (res RngRes, err error) {
err = e.execIfNotBlocked(func() error { err = e.execIfNotBlocked(func() error {
res, err = e.getRange(prm) res, err = e.getRange(ctx, prm)
return err return err
}) })
return return
} }
func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) { func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.getRange",
trace.WithAttributes(
attribute.String("address", prm.addr.EncodeToString()),
attribute.String("offset", strconv.FormatUint(prm.off, 10)),
attribute.String("length", strconv.FormatUint(prm.ln, 10)),
))
defer span.End()
if e.metrics != nil { if e.metrics != nil {
defer elapsed(e.metrics.AddRangeDuration)() defer elapsed(e.metrics.AddRangeDuration)()
} }
@ -83,7 +96,7 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
Engine: e, Engine: e,
} }
it.tryGetWithMeta() it.tryGetWithMeta(ctx)
if it.SplitInfo != nil { if it.SplitInfo != nil {
return RngRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo)) return RngRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo))
@ -96,7 +109,7 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
return RngRes{}, it.OutError return RngRes{}, it.OutError
} }
it.tryGetFromBlobstor() it.tryGetFromBlobstor(ctx)
if it.Object == nil { if it.Object == nil {
return RngRes{}, it.OutError return RngRes{}, it.OutError
@ -114,12 +127,12 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
} }
// GetRange reads object payload range from local storage by provided address. // GetRange reads object payload range from local storage by provided address.
func GetRange(storage *StorageEngine, addr oid.Address, rng *objectSDK.Range) ([]byte, error) { func GetRange(ctx context.Context, storage *StorageEngine, addr oid.Address, rng *objectSDK.Range) ([]byte, error) {
var rangePrm RngPrm var rangePrm RngPrm
rangePrm.WithAddress(addr) rangePrm.WithAddress(addr)
rangePrm.WithPayloadRange(rng) rangePrm.WithPayloadRange(rng)
res, err := storage.GetRange(rangePrm) res, err := storage.GetRange(ctx, rangePrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -141,13 +154,13 @@ type getRangeShardIterator struct {
Engine *StorageEngine Engine *StorageEngine
} }
func (i *getRangeShardIterator) tryGetWithMeta() { func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) {
i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) { i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) {
noMeta := sh.GetMode().NoMetabase() noMeta := sh.GetMode().NoMetabase()
i.HasDegraded = i.HasDegraded || noMeta i.HasDegraded = i.HasDegraded || noMeta
i.ShardPrm.SetIgnoreMeta(noMeta) i.ShardPrm.SetIgnoreMeta(noMeta)
res, err := sh.GetRange(i.ShardPrm) res, err := sh.GetRange(ctx, i.ShardPrm)
if err == nil { if err == nil {
i.Object = res.Object() i.Object = res.Object()
return true return true
@ -185,7 +198,7 @@ func (i *getRangeShardIterator) tryGetWithMeta() {
}) })
} }
func (i *getRangeShardIterator) tryGetFromBlobstor() { func (i *getRangeShardIterator) tryGetFromBlobstor(ctx context.Context) {
// If the object is not found but is present in metabase, // If the object is not found but is present in metabase,
// try to fetch it from blobstor directly. If it is found in any // try to fetch it from blobstor directly. If it is found in any
// blobstor, increase the error counter for the shard which contains the meta. // blobstor, increase the error counter for the shard which contains the meta.
@ -197,7 +210,7 @@ func (i *getRangeShardIterator) tryGetFromBlobstor() {
return false return false
} }
res, err := sh.GetRange(i.ShardPrm) res, err := sh.GetRange(ctx, i.ShardPrm)
if shard.IsErrOutOfRange(err) { if shard.IsErrOutOfRange(err) {
var errOutOfRange apistatus.ObjectOutOfRange var errOutOfRange apistatus.ObjectOutOfRange

View file

@ -116,7 +116,7 @@ func (e *StorageEngine) removeObjects(ctx context.Context, ch <-chan oid.Address
var existsPrm shard.ExistsPrm var existsPrm shard.ExistsPrm
existsPrm.SetAddress(addr) existsPrm.SetAddress(addr)
res, err := shards[i].Exists(existsPrm) res, err := shards[i].Exists(ctx, existsPrm)
if err != nil { if err != nil {
return err return err
} else if !res.Exists() { } else if !res.Exists() {

View file

@ -63,6 +63,7 @@ func TestShardOpen(t *testing.T) {
newShard := func() *Shard { newShard := func() *Shard {
return New( return New(
WithID(NewIDFromBytes([]byte{})),
WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
WithBlobStorOptions( WithBlobStorOptions(
blobstor.WithStorages([]blobstor.SubStorage{ blobstor.WithStorages([]blobstor.SubStorage{
@ -146,6 +147,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
sh = New( sh = New(
WithID(NewIDFromBytes([]byte{})),
WithBlobStorOptions(blobOpts...), WithBlobStorOptions(blobOpts...),
WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))), WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))),
WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta_new")), meta.WithEpochState(epochState{})), WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta_new")), meta.WithEpochState(epochState{})),
@ -155,7 +157,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) {
var getPrm GetPrm var getPrm GetPrm
getPrm.SetAddress(addr) getPrm.SetAddress(addr)
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
require.NoError(t, sh.Close()) require.NoError(t, sh.Close())
} }
@ -176,6 +178,7 @@ func TestRefillMetabase(t *testing.T) {
} }
sh := New( sh := New(
WithID(NewIDFromBytes([]byte{})),
WithBlobStorOptions(blobOpts...), WithBlobStorOptions(blobOpts...),
WithMetaBaseOptions( WithMetaBaseOptions(
meta.WithPath(filepath.Join(p, "meta")), meta.WithPath(filepath.Join(p, "meta")),
@ -277,7 +280,7 @@ func TestRefillMetabase(t *testing.T) {
checkObj := func(addr oid.Address, expObj *objectSDK.Object) { checkObj := func(addr oid.Address, expObj *objectSDK.Object) {
headPrm.SetAddress(addr) headPrm.SetAddress(addr)
res, err := sh.Head(headPrm) res, err := sh.Head(context.Background(), headPrm)
if expObj == nil { if expObj == nil {
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
@ -302,7 +305,7 @@ func TestRefillMetabase(t *testing.T) {
for _, member := range tombMembers { for _, member := range tombMembers {
headPrm.SetAddress(member) headPrm.SetAddress(member)
_, err := sh.Head(headPrm) _, err := sh.Head(context.Background(), headPrm)
if exists { if exists {
require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
@ -343,6 +346,7 @@ func TestRefillMetabase(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
sh = New( sh = New(
WithID(NewIDFromBytes([]byte{})),
WithBlobStorOptions(blobOpts...), WithBlobStorOptions(blobOpts...),
WithMetaBaseOptions( WithMetaBaseOptions(
meta.WithPath(filepath.Join(p, "meta_restored")), meta.WithPath(filepath.Join(p, "meta_restored")),

View file

@ -1,6 +1,7 @@
package shard_test package shard_test
import ( import (
"context"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
@ -51,7 +52,7 @@ func testShardDelete(t *testing.T, hasWriteCache bool) {
_, err = sh.Delete(delPrm) _, err = sh.Delete(delPrm)
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
@ -69,13 +70,13 @@ func testShardDelete(t *testing.T, hasWriteCache bool) {
_, err := sh.Put(putPrm) _, err := sh.Put(putPrm)
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Delete(delPrm) _, err = sh.Delete(delPrm)
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
} }

View file

@ -2,6 +2,7 @@ package shard_test
import ( import (
"bytes" "bytes"
"context"
"io" "io"
"math/rand" "math/rand"
"os" "os"
@ -276,7 +277,7 @@ func checkRestore(t *testing.T, sh *shard.Shard, prm shard.RestorePrm, objects [
for i := range objects { for i := range objects {
getPrm.SetAddress(object.AddressOf(objects[i])) getPrm.SetAddress(object.AddressOf(objects[i]))
res, err := sh.Get(getPrm) res, err := sh.Get(context.Background(), getPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objects[i], res.Object()) require.Equal(t, objects[i], res.Object())
} }

View file

@ -1,6 +1,8 @@
package shard package shard
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
@ -33,7 +35,7 @@ func (p ExistsRes) Exists() bool {
// //
// Returns an error of type apistatus.ObjectAlreadyRemoved if object has been marked as removed. // Returns an error of type apistatus.ObjectAlreadyRemoved if object has been marked as removed.
// Returns the object.ErrObjectIsExpired if the object is presented but already expired. // Returns the object.ErrObjectIsExpired if the object is presented but already expired.
func (s *Shard) Exists(prm ExistsPrm) (ExistsRes, error) { func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) {
var exists bool var exists bool
var err error var err error
@ -45,7 +47,7 @@ func (s *Shard) Exists(prm ExistsPrm) (ExistsRes, error) {
p.Address = prm.addr p.Address = prm.addr
var res common.ExistsRes var res common.ExistsRes
res, err = s.blobStor.Exists(p) res, err = s.blobStor.Exists(ctx, p)
exists = res.Exists exists = res.Exists
} else { } else {
var existsPrm meta.ExistsPrm var existsPrm meta.ExistsPrm

View file

@ -33,6 +33,7 @@ func Test_GCDropsLockedExpiredObject(t *testing.T) {
rootPath := t.TempDir() rootPath := t.TempDir()
opts := []shard.Option{ opts := []shard.Option{
shard.WithID(shard.NewIDFromBytes([]byte{})),
shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}), shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}),
shard.WithBlobStorOptions( shard.WithBlobStorOptions(
blobstor.WithStorages([]blobstor.SubStorage{ blobstor.WithStorages([]blobstor.SubStorage{
@ -115,7 +116,7 @@ func Test_GCDropsLockedExpiredObject(t *testing.T) {
var getPrm shard.GetPrm var getPrm shard.GetPrm
getPrm.SetAddress(objectCore.AddressOf(obj)) getPrm.SetAddress(objectCore.AddressOf(obj))
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
return shard.IsErrNotFound(err) return shard.IsErrNotFound(err)
}, 3*time.Second, 1*time.Second, "expired object must be deleted") }, 3*time.Second, 1*time.Second, "expired object must be deleted")
} }

View file

@ -1,8 +1,10 @@
package shard package shard
import ( import (
"context"
"fmt" "fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "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/blobstor/common"
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
@ -11,6 +13,8 @@ import (
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -61,7 +65,15 @@ func (r GetRes) HasMeta() bool {
// Returns an error of type apistatus.ObjectNotFound if the requested object is missing in shard. // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in shard.
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard. // Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
// Returns the object.ErrObjectIsExpired if the object is presented but already expired. // Returns the object.ErrObjectIsExpired if the object is presented but already expired.
func (s *Shard) Get(prm GetPrm) (GetRes, error) { func (s *Shard) Get(ctx context.Context, prm GetPrm) (GetRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "Shard.Get",
trace.WithAttributes(
attribute.String("shard_id", s.ID().String()),
attribute.String("address", prm.addr.EncodeToString()),
attribute.Bool("skip_meta", prm.skipMeta),
))
defer span.End()
s.m.RLock() s.m.RLock()
defer s.m.RUnlock() defer s.m.RUnlock()
@ -70,7 +82,7 @@ func (s *Shard) Get(prm GetPrm) (GetRes, error) {
getPrm.Address = prm.addr getPrm.Address = prm.addr
getPrm.StorageID = id getPrm.StorageID = id
res, err := stor.Get(getPrm) res, err := stor.Get(ctx, getPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -79,7 +91,7 @@ func (s *Shard) Get(prm GetPrm) (GetRes, error) {
} }
wc := func(c writecache.Cache) (*objectSDK.Object, error) { wc := func(c writecache.Cache) (*objectSDK.Object, error) {
return c.Get(prm.addr) return c.Get(ctx, prm.addr)
} }
skipMeta := prm.skipMeta || s.info.Mode.NoMetabase() skipMeta := prm.skipMeta || s.info.Mode.NoMetabase()

View file

@ -2,6 +2,7 @@ package shard_test
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"testing" "testing"
"time" "time"
@ -111,11 +112,11 @@ func testShardGet(t *testing.T, hasWriteCache bool) {
} }
func testGet(t *testing.T, sh *shard.Shard, getPrm shard.GetPrm, hasWriteCache bool) (shard.GetRes, error) { func testGet(t *testing.T, sh *shard.Shard, getPrm shard.GetPrm, hasWriteCache bool) (shard.GetRes, error) {
res, err := sh.Get(getPrm) res, err := sh.Get(context.Background(), getPrm)
if hasWriteCache { if hasWriteCache {
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
if shard.IsErrNotFound(err) { if shard.IsErrNotFound(err) {
res, err = sh.Get(getPrm) res, err = sh.Get(context.Background(), getPrm)
} }
return !shard.IsErrNotFound(err) return !shard.IsErrNotFound(err)
}, time.Second, time.Millisecond*100) }, time.Second, time.Millisecond*100)

View file

@ -1,9 +1,14 @@
package shard package shard
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// HeadPrm groups the parameters of Head operation. // HeadPrm groups the parameters of Head operation.
@ -43,7 +48,15 @@ func (r HeadRes) Object() *objectSDK.Object {
// Returns an error of type apistatus.ObjectNotFound if object is missing in Shard. // Returns an error of type apistatus.ObjectNotFound if object is missing in Shard.
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard. // Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
// Returns the object.ErrObjectIsExpired if the object is presented but already expired. // Returns the object.ErrObjectIsExpired if the object is presented but already expired.
func (s *Shard) Head(prm HeadPrm) (HeadRes, error) { func (s *Shard) Head(ctx context.Context, prm HeadPrm) (HeadRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "Shard.Head",
trace.WithAttributes(
attribute.String("shard_id", s.ID().String()),
attribute.String("address", prm.addr.EncodeToString()),
attribute.Bool("raw", prm.raw),
))
defer span.End()
var obj *objectSDK.Object var obj *objectSDK.Object
var err error var err error
if s.GetMode().NoMetabase() { if s.GetMode().NoMetabase() {
@ -52,7 +65,7 @@ func (s *Shard) Head(prm HeadPrm) (HeadRes, error) {
getPrm.SetIgnoreMeta(true) getPrm.SetIgnoreMeta(true)
var res GetRes var res GetRes
res, err = s.Get(getPrm) res, err = s.Get(ctx, getPrm)
obj = res.Object() obj = res.Object()
} else { } else {
var headParams meta.GetPrm var headParams meta.GetPrm

View file

@ -1,6 +1,7 @@
package shard_test package shard_test
import ( import (
"context"
"errors" "errors"
"testing" "testing"
"time" "time"
@ -75,18 +76,18 @@ func testShardHead(t *testing.T, hasWriteCache bool) {
headPrm.SetAddress(object.AddressOf(parent)) headPrm.SetAddress(object.AddressOf(parent))
headPrm.SetRaw(false) headPrm.SetRaw(false)
head, err := sh.Head(headPrm) head, err := sh.Head(context.Background(), headPrm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, parent.CutPayload(), head.Object()) require.Equal(t, parent.CutPayload(), head.Object())
}) })
} }
func testHead(t *testing.T, sh *shard.Shard, headPrm shard.HeadPrm, hasWriteCache bool) (shard.HeadRes, error) { func testHead(t *testing.T, sh *shard.Shard, headPrm shard.HeadPrm, hasWriteCache bool) (shard.HeadRes, error) {
res, err := sh.Head(headPrm) res, err := sh.Head(context.Background(), headPrm)
if hasWriteCache { if hasWriteCache {
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
if shard.IsErrNotFound(err) { if shard.IsErrNotFound(err) {
res, err = sh.Head(headPrm) res, err = sh.Head(context.Background(), headPrm)
} }
return !shard.IsErrNotFound(err) return !shard.IsErrNotFound(err)
}, time.Second, time.Millisecond*100) }, time.Second, time.Millisecond*100)

View file

@ -51,6 +51,6 @@ func testShardInhume(t *testing.T, hasWriteCache bool) {
_, err = sh.Inhume(context.Background(), inhPrm) _, err = sh.Inhume(context.Background(), inhPrm)
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
} }

View file

@ -27,6 +27,7 @@ func TestShard_Lock(t *testing.T) {
rootPath := t.TempDir() rootPath := t.TempDir()
opts := []shard.Option{ opts := []shard.Option{
shard.WithID(shard.NewIDFromBytes([]byte{})),
shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}), shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}),
shard.WithBlobStorOptions( shard.WithBlobStorOptions(
blobstor.WithStorages([]blobstor.SubStorage{ blobstor.WithStorages([]blobstor.SubStorage{
@ -137,7 +138,7 @@ func TestShard_Lock(t *testing.T) {
var getPrm shard.GetPrm var getPrm shard.GetPrm
getPrm.SetAddress(objectcore.AddressOf(obj)) getPrm.SetAddress(objectcore.AddressOf(obj))
_, err = sh.Get(getPrm) _, err = sh.Get(context.Background(), getPrm)
require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
} }

View file

@ -1,6 +1,10 @@
package shard package shard
import ( import (
"context"
"strconv"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "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/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
@ -8,6 +12,8 @@ import (
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// RngPrm groups the parameters of GetRange operation. // RngPrm groups the parameters of GetRange operation.
@ -66,7 +72,17 @@ func (r RngRes) HasMeta() bool {
// Returns an error of type apistatus.ObjectNotFound if the requested object is missing. // Returns an error of type apistatus.ObjectNotFound if the requested object is missing.
// Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard. // Returns an error of type apistatus.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
// Returns the object.ErrObjectIsExpired if the object is presented but already expired. // Returns the object.ErrObjectIsExpired if the object is presented but already expired.
func (s *Shard) GetRange(prm RngPrm) (RngRes, error) { func (s *Shard) GetRange(ctx context.Context, prm RngPrm) (RngRes, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "Shard.GetRange",
trace.WithAttributes(
attribute.String("shard_id", s.ID().String()),
attribute.String("address", prm.addr.EncodeToString()),
attribute.Bool("skip_meta", prm.skipMeta),
attribute.String("offset", strconv.FormatUint(prm.off, 10)),
attribute.String("length", strconv.FormatUint(prm.ln, 10)),
))
defer span.End()
s.m.RLock() s.m.RLock()
defer s.m.RUnlock() defer s.m.RUnlock()
@ -77,7 +93,7 @@ func (s *Shard) GetRange(prm RngPrm) (RngRes, error) {
getRngPrm.Range.SetLength(prm.ln) getRngPrm.Range.SetLength(prm.ln)
getRngPrm.StorageID = id getRngPrm.StorageID = id
res, err := stor.GetRange(getRngPrm) res, err := stor.GetRange(ctx, getRngPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -89,7 +105,7 @@ func (s *Shard) GetRange(prm RngPrm) (RngRes, error) {
} }
wc := func(c writecache.Cache) (*object.Object, error) { wc := func(c writecache.Cache) (*object.Object, error) {
res, err := c.Get(prm.addr) res, err := c.Get(ctx, prm.addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,6 +1,7 @@
package shard_test package shard_test
import ( import (
"context"
"math" "math"
"path/filepath" "path/filepath"
"testing" "testing"
@ -105,7 +106,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) {
rngPrm.SetAddress(addr) rngPrm.SetAddress(addr)
rngPrm.SetRange(tc.rng.GetOffset(), tc.rng.GetLength()) rngPrm.SetRange(tc.rng.GetOffset(), tc.rng.GetLength())
res, err := sh.GetRange(rngPrm) res, err := sh.GetRange(context.Background(), rngPrm)
if tc.hasErr { if tc.hasErr {
require.ErrorAs(t, err, &apistatus.ObjectOutOfRange{}) require.ErrorAs(t, err, &apistatus.ObjectOutOfRange{})
} else { } else {

View file

@ -66,7 +66,7 @@ func TestShardReload(t *testing.T) {
var prm ExistsPrm var prm ExistsPrm
prm.SetAddress(objects[i].addr) prm.SetAddress(objects[i].addr)
res, err := sh.Exists(prm) res, err := sh.Exists(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, exists, res.Exists(), "object #%d is missing", i) require.Equal(t, exists, res.Exists(), "object #%d is missing", i)
} }

View file

@ -63,6 +63,7 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts
} }
opts := []shard.Option{ opts := []shard.Option{
shard.WithID(shard.NewIDFromBytes([]byte{})),
shard.WithLogger(&logger.Logger{Logger: zap.L()}), shard.WithLogger(&logger.Logger{Logger: zap.L()}),
shard.WithBlobStorOptions(bsOpts...), shard.WithBlobStorOptions(bsOpts...),
shard.WithMetaBaseOptions( shard.WithMetaBaseOptions(

View file

@ -1,6 +1,7 @@
package shard_test package shard_test
import ( import (
"context"
"math/rand" "math/rand"
"testing" "testing"
@ -55,7 +56,7 @@ func TestWriteCacheObjectLoss(t *testing.T) {
for i := range objects { for i := range objects {
getPrm.SetAddress(object.AddressOf(objects[i])) getPrm.SetAddress(object.AddressOf(objects[i]))
_, err := sh.Get(getPrm) _, err := sh.Get(context.Background(), getPrm)
require.NoError(t, err, i) require.NoError(t, err, i)
} }
} }

View file

@ -1,6 +1,7 @@
package writecache package writecache
import ( import (
"context"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -95,7 +96,7 @@ func TestFlush(t *testing.T) {
prm.Address = objects[i].addr prm.Address = objects[i].addr
prm.StorageID = mRes.StorageID() prm.StorageID = mRes.StorageID()
res, err := bs.Get(prm) res, err := bs.Get(context.Background(), prm)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, objects[i].obj, res.Object) require.Equal(t, objects[i].obj, res.Object)
} }
@ -119,7 +120,7 @@ func TestFlush(t *testing.T) {
_, err := mb.Get(mPrm) _, err := mb.Get(mPrm)
require.Error(t, err) require.Error(t, err)
_, err = bs.Get(common.GetPrm{Address: objects[i].addr}) _, err = bs.Get(context.Background(), common.GetPrm{Address: objects[i].addr})
require.Error(t, err) require.Error(t, err)
} }
@ -149,7 +150,7 @@ func TestFlush(t *testing.T) {
_, err := mb.Get(mPrm) _, err := mb.Get(mPrm)
require.Error(t, err) require.Error(t, err)
_, err = bs.Get(common.GetPrm{Address: objects[i].addr}) _, err = bs.Get(context.Background(), common.GetPrm{Address: objects[i].addr})
require.Error(t, err) require.Error(t, err)
} }
@ -266,7 +267,7 @@ func TestFlush(t *testing.T) {
require.NoError(t, wc.Open(true)) require.NoError(t, wc.Open(true))
initWC(t, wc) initWC(t, wc)
for i := range objects { for i := range objects {
_, err := wc.Get(objects[i].addr) _, err := wc.Get(context.Background(), objects[i].addr)
require.NoError(t, err, i) require.NoError(t, err, i)
} }
require.NoError(t, wc.Close()) require.NoError(t, wc.Close())
@ -275,7 +276,7 @@ func TestFlush(t *testing.T) {
require.NoError(t, wc.Open(false)) require.NoError(t, wc.Open(false))
initWC(t, wc) initWC(t, wc)
for i := range objects { for i := range objects {
_, err := wc.Get(objects[i].addr) _, err := wc.Get(context.Background(), objects[i].addr)
if i < 2 { if i < 2 {
require.ErrorAs(t, err, new(apistatus.ObjectNotFound), i) require.ErrorAs(t, err, new(apistatus.ObjectNotFound), i)
} else { } else {

View file

@ -1,6 +1,9 @@
package writecache package writecache
import ( import (
"context"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
@ -8,14 +11,22 @@ import (
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/nspcc-dev/neo-go/pkg/util/slice"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
// Get returns object from write-cache. // Get returns object from write-cache.
// //
// Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache. // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache.
func (c *cache) Get(addr oid.Address) (*objectSDK.Object, error) { func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) {
saddr := addr.EncodeToString() saddr := addr.EncodeToString()
ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Get",
trace.WithAttributes(
attribute.String("address", saddr),
))
defer span.End()
value, err := Get(c.db, []byte(saddr)) value, err := Get(c.db, []byte(saddr))
if err == nil { if err == nil {
obj := objectSDK.New() obj := objectSDK.New()
@ -23,7 +34,7 @@ func (c *cache) Get(addr oid.Address) (*objectSDK.Object, error) {
return obj, obj.Unmarshal(value) return obj, obj.Unmarshal(value)
} }
res, err := c.fsTree.Get(common.GetPrm{Address: addr}) res, err := c.fsTree.Get(ctx, common.GetPrm{Address: addr})
if err != nil { if err != nil {
return nil, logicerr.Wrap(apistatus.ObjectNotFound{}) return nil, logicerr.Wrap(apistatus.ObjectNotFound{})
} }
@ -35,8 +46,14 @@ func (c *cache) Get(addr oid.Address) (*objectSDK.Object, error) {
// Head returns object header from write-cache. // Head returns object header from write-cache.
// //
// Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache. // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache.
func (c *cache) Head(addr oid.Address) (*objectSDK.Object, error) { func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) {
obj, err := c.Get(addr) ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Head",
trace.WithAttributes(
attribute.String("address", addr.EncodeToString()),
))
defer span.End()
obj, err := c.Get(ctx, addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1,6 +1,7 @@
package writecache package writecache
import ( import (
"context"
"errors" "errors"
"sync" "sync"
@ -177,6 +178,6 @@ func (c *cache) flushStatus(addr oid.Address) (bool, bool) {
prm.SetAddress(addr) prm.SetAddress(addr)
mRes, _ := c.metabase.StorageID(prm) mRes, _ := c.metabase.StorageID(prm)
res, err := c.blobstor.Exists(common.ExistsPrm{Address: addr, StorageID: mRes.StorageID()}) res, err := c.blobstor.Exists(context.TODO(), common.ExistsPrm{Address: addr, StorageID: mRes.StorageID()})
return err == nil && res.Exists, false return err == nil && res.Exists, false
} }

View file

@ -1,6 +1,7 @@
package writecache package writecache
import ( import (
"context"
"io/fs" "io/fs"
"os" "os"
"time" "time"
@ -27,7 +28,7 @@ type metabase interface {
type blob interface { type blob interface {
Put(common.PutPrm) (common.PutRes, error) Put(common.PutPrm) (common.PutRes, error)
NeedsCompression(obj *objectSDK.Object) bool NeedsCompression(obj *objectSDK.Object) bool
Exists(res common.ExistsPrm) (common.ExistsRes, error) Exists(ctx context.Context, res common.ExistsPrm) (common.ExistsRes, error)
} }
type options struct { type options struct {

View file

@ -1,6 +1,7 @@
package writecache package writecache
import ( import (
"context"
"os" "os"
"sync" "sync"
@ -23,8 +24,8 @@ type Info struct {
// Cache represents write-cache for objects. // Cache represents write-cache for objects.
type Cache interface { type Cache interface {
Get(address oid.Address) (*object.Object, error) Get(ctx context.Context, address oid.Address) (*object.Object, error)
Head(oid.Address) (*object.Object, error) Head(context.Context, oid.Address) (*object.Object, error)
// Delete removes object referenced by the given oid.Address from the // Delete removes object referenced by the given oid.Address from the
// Cache. Returns any error encountered that prevented the object to be // Cache. Returns any error encountered that prevented the object to be
// removed. // removed.

View file

@ -19,7 +19,7 @@ import (
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
) )
func (s *Server) EvacuateShard(_ context.Context, req *control.EvacuateShardRequest) (*control.EvacuateShardResponse, error) { func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRequest) (*control.EvacuateShardResponse, error) {
err := s.isValidRequest(req) err := s.isValidRequest(req)
if err != nil { if err != nil {
return nil, status.Error(codes.PermissionDenied, err.Error()) return nil, status.Error(codes.PermissionDenied, err.Error())
@ -30,7 +30,7 @@ func (s *Server) EvacuateShard(_ context.Context, req *control.EvacuateShardRequ
prm.WithIgnoreErrors(req.GetBody().GetIgnoreErrors()) prm.WithIgnoreErrors(req.GetBody().GetIgnoreErrors())
prm.WithFaultHandler(s.replicate) prm.WithFaultHandler(s.replicate)
res, err := s.s.Evacuate(prm) res, err := s.s.Evacuate(ctx, prm)
if err != nil { if err != nil {
return nil, status.Error(codes.Internal, err.Error()) return nil, status.Error(codes.Internal, err.Error())
} }

View file

@ -1,6 +1,8 @@
package notificator package notificator
import ( import (
"context"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
) )
@ -8,7 +10,7 @@ import (
type NotificationSource interface { type NotificationSource interface {
// Iterate must iterate over all notifications for the // Iterate must iterate over all notifications for the
// provided epoch and call handler for all of them. // provided epoch and call handler for all of them.
Iterate(epoch uint64, handler func(topic string, addr oid.Address)) Iterate(ctx context.Context, epoch uint64, handler func(topic string, addr oid.Address))
} }
// NotificationWriter notifies all the subscribers // NotificationWriter notifies all the subscribers

View file

@ -1,6 +1,7 @@
package notificator package notificator
import ( import (
"context"
"fmt" "fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
@ -71,11 +72,11 @@ func New(prm *Prm) *Notificator {
// ProcessEpoch looks for all objects with defined epoch in the storage // ProcessEpoch looks for all objects with defined epoch in the storage
// and passes their addresses to the NotificationWriter. // and passes their addresses to the NotificationWriter.
func (n *Notificator) ProcessEpoch(epoch uint64) { func (n *Notificator) ProcessEpoch(ctx context.Context, epoch uint64) {
logger := n.l.With(zap.Uint64("epoch", epoch)) logger := n.l.With(zap.Uint64("epoch", epoch))
logger.Debug("notificator: start processing object notifications") logger.Debug("notificator: start processing object notifications")
n.ns.Iterate(epoch, func(topic string, addr oid.Address) { n.ns.Iterate(ctx, epoch, func(topic string, addr oid.Address) {
n.l.Debug("notificator: processing object notification", n.l.Debug("notificator: processing object notification",
zap.String("topic", topic), zap.String("topic", topic),
zap.Stringer("address", addr), zap.Stringer("address", addr),

View file

@ -1,6 +1,7 @@
package v2 package v2
import ( import (
"context"
"crypto/ecdsa" "crypto/ecdsa"
"errors" "errors"
"testing" "testing"
@ -26,7 +27,7 @@ type testLocalStorage struct {
err error err error
} }
func (s *testLocalStorage) Head(addr oid.Address) (*object.Object, error) { func (s *testLocalStorage) Head(ctx context.Context, addr oid.Address) (*object.Object, error) {
require.True(s.t, addr.Container().Equals(s.expAddr.Container())) require.True(s.t, addr.Container().Equals(s.expAddr.Container()))
require.True(s.t, addr.Object().Equals(s.expAddr.Object())) require.True(s.t, addr.Object().Equals(s.expAddr.Object()))

View file

@ -1,6 +1,7 @@
package v2 package v2
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
@ -27,7 +28,7 @@ type cfg struct {
} }
type ObjectStorage interface { type ObjectStorage interface {
Head(oid.Address) (*object.Object, error) Head(context.Context, oid.Address) (*object.Object, error)
} }
type Request interface { type Request interface {
@ -207,7 +208,7 @@ func (h *cfg) localObjectHeaders(cnr cid.ID, idObj *oid.ID) ([]eaclSDK.Header, b
addr.SetContainer(cnr) addr.SetContainer(cnr)
addr.SetObject(*idObj) addr.SetObject(*idObj)
obj, err := h.storage.Head(addr) obj, err := h.storage.Head(context.TODO(), addr)
if err == nil { if err == nil {
return headersFromObject(obj, cnr, idObj), true return headersFromObject(obj, cnr, idObj), true
} }

View file

@ -1,6 +1,7 @@
package v2 package v2
import ( import (
"context"
"io" "io"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
@ -12,10 +13,10 @@ type localStorage struct {
ls *engine.StorageEngine ls *engine.StorageEngine
} }
func (s *localStorage) Head(addr oid.Address) (*objectSDK.Object, error) { func (s *localStorage) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) {
if s.ls == nil { if s.ls == nil {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
return engine.Head(s.ls, addr) return engine.Head(ctx, s.ls, addr)
} }

View file

@ -139,7 +139,7 @@ func (c *testClient) addResult(addr oid.Address, obj *objectSDK.Object, err erro
}{obj: obj, err: err} }{obj: obj, err: err}
} }
func (s *testStorage) get(exec *execCtx) (*objectSDK.Object, error) { func (s *testStorage) get(_ context.Context, exec *execCtx) (*objectSDK.Object, error) {
var ( var (
ok bool ok bool
obj *objectSDK.Object obj *objectSDK.Object

View file

@ -4,15 +4,21 @@ import (
"context" "context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
"go.uber.org/zap" "go.uber.org/zap"
) )
func (exec *execCtx) executeLocal(ctx context.Context) { func (exec *execCtx) executeLocal(ctx context.Context) {
ctx, span := tracing.StartSpanFromContext(ctx, "getService.executeLocal")
defer func() {
span.End()
}()
var err error var err error
exec.collectedObject, err = exec.svc.localStorage.get(exec) exec.collectedObject, err = exec.svc.localStorage.get(ctx, exec)
var errSplitInfo *objectSDK.SplitInfoError var errSplitInfo *objectSDK.SplitInfoError
var errRemoved apistatus.ObjectAlreadyRemoved var errRemoved apistatus.ObjectAlreadyRemoved

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
@ -11,6 +12,9 @@ import (
) )
func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool { func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool {
ctx, span := tracing.StartSpanFromContext(ctx, "getService.processNode")
defer span.End()
exec.log.Debug("processing node...") exec.log.Debug("processing node...")
client, ok := exec.remoteClient(info) client, ok := exec.remoteClient(info)

View file

@ -31,7 +31,7 @@ type cfg struct {
log *logger.Logger log *logger.Logger
localStorage interface { localStorage interface {
get(*execCtx) (*object.Object, error) get(context.Context, *execCtx) (*object.Object, error)
} }
clientCache interface { clientCache interface {

View file

@ -200,13 +200,13 @@ func (c *clientWrapper) get(ctx context.Context, exec *execCtx, key *ecdsa.Priva
return res.Object(), nil return res.Object(), nil
} }
func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { func (e *storageEngineWrapper) get(ctx context.Context, exec *execCtx) (*object.Object, error) {
if exec.headOnly() { if exec.headOnly() {
var headPrm engine.HeadPrm var headPrm engine.HeadPrm
headPrm.WithAddress(exec.address()) headPrm.WithAddress(exec.address())
headPrm.WithRaw(exec.isRaw()) headPrm.WithRaw(exec.isRaw())
r, err := e.engine.Head(headPrm) r, err := e.engine.Head(ctx, headPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -217,7 +217,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) {
getRange.WithAddress(exec.address()) getRange.WithAddress(exec.address())
getRange.WithPayloadRange(rng) getRange.WithPayloadRange(rng)
r, err := e.engine.GetRange(getRange) r, err := e.engine.GetRange(ctx, getRange)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -227,7 +227,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) {
var getPrm engine.GetPrm var getPrm engine.GetPrm
getPrm.WithAddress(exec.address()) getPrm.WithAddress(exec.address())
r, err := e.engine.Get(getPrm) r, err := e.engine.Get(ctx, getPrm)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -9,6 +9,7 @@ import (
"sync" "sync"
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
@ -18,6 +19,8 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal"
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
type getRequestForwarder struct { type getRequestForwarder struct {
@ -30,6 +33,11 @@ type getRequestForwarder struct {
} }
func (f *getRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*object.Object, error) { func (f *getRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*object.Object, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "getRequestForwarder.forwardRequestToNode",
trace.WithAttributes(attribute.String("address", addr.String())),
)
defer span.End()
var err error var err error
// once compose and resign forwarding request // once compose and resign forwarding request

View file

@ -9,6 +9,7 @@ import (
"sync" "sync"
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
@ -18,6 +19,8 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal"
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
type getRangeRequestForwarder struct { type getRangeRequestForwarder struct {
@ -29,6 +32,11 @@ type getRangeRequestForwarder struct {
} }
func (f *getRangeRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*object.Object, error) { func (f *getRangeRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*object.Object, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "getRangeRequestForwarder.forwardRequestToNode",
trace.WithAttributes(attribute.String("address", addr.String())),
)
defer span.End()
var err error var err error
// once compose and resign forwarding request // once compose and resign forwarding request

View file

@ -8,6 +8,7 @@ import (
"sync" "sync"
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
@ -19,6 +20,8 @@ import (
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
) )
type headRequestForwarder struct { type headRequestForwarder struct {
@ -30,6 +33,11 @@ type headRequestForwarder struct {
} }
func (f *headRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*object.Object, error) { func (f *headRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*object.Object, error) {
ctx, span := tracing.StartSpanFromContext(ctx, "headRequestForwarder.forwardRequestToNode",
trace.WithAttributes(attribute.String("address", addr.String())),
)
defer span.End()
var err error var err error
// once compose and resign forwarding request // once compose and resign forwarding request

View file

@ -96,7 +96,7 @@ func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV
resp := new(objectV2.HeadResponse) resp := new(objectV2.HeadResponse)
resp.SetBody(new(objectV2.HeadResponseBody)) resp.SetBody(new(objectV2.HeadResponseBody))
p, err := s.toHeadPrm(ctx, req, resp) p, err := s.toHeadPrm(req, resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -215,7 +215,7 @@ func (w *headResponseWriter) WriteHeader(_ context.Context, hdr *object.Object)
return nil return nil
} }
func (s *Service) toHeadPrm(ctx context.Context, req *objectV2.HeadRequest, resp *objectV2.HeadResponse) (*getsvc.HeadPrm, error) { func (s *Service) toHeadPrm(req *objectV2.HeadRequest, resp *objectV2.HeadResponse) (*getsvc.HeadPrm, error) {
body := req.GetBody() body := req.GetBody()
addrV2 := body.GetAddress() addrV2 := body.GetAddress()

View file

@ -27,7 +27,7 @@ func (p *Replicator) HandleTask(ctx context.Context, task Task, res TaskResult)
if task.obj == nil { if task.obj == nil {
var err error var err error
task.obj, err = engine.Get(p.localStorage, task.addr) task.obj, err = engine.Get(ctx, p.localStorage, task.addr)
if err != nil { if err != nil {
p.log.Error("could not get object from local storage", p.log.Error("could not get object from local storage",
zap.Stringer("object", task.addr), zap.Stringer("object", task.addr),