Tracing for get object #135
95 changed files with 824 additions and 268 deletions
|
@ -15,6 +15,7 @@ Changelog for FrostFS Node
|
|||
- Multiple configs support (#44)
|
||||
- Parameters `nns-name` and `nns-zone` for command `frostfs-cli container create` (#37)
|
||||
- Tree service now saves the last synchronization height which persists across restarts (#82)
|
||||
- Add tracing support (#135)
|
||||
|
||||
### Changed
|
||||
- Change `frostfs_node_engine_container_size` to counting sizes of logical objects
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree"
|
||||
|
@ -22,8 +23,15 @@ func _client(ctx context.Context) (tree.TreeServiceClient, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
opts := make([]grpc.DialOption, 1, 2)
|
||||
opts[0] = grpc.WithBlock()
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithChainUnaryInterceptor(
|
||||
tracing.NewGRPCUnaryClientInteceptor(),
|
||||
),
|
||||
grpc.WithChainStreamInterceptor(
|
||||
tracing.NewGRPCStreamClientInterceptor(),
|
||||
),
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(netAddr.URIAddr(), "grpcs:") {
|
||||
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
|
|
|
@ -33,7 +33,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) {
|
|||
var prm blobovnicza.GetPrm
|
||||
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))
|
||||
|
||||
data := res.Object()
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"time"
|
||||
|
||||
netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||
apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient"
|
||||
contractsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/contracts"
|
||||
|
@ -27,6 +28,7 @@ import (
|
|||
nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node"
|
||||
objectconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object"
|
||||
replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator"
|
||||
tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||
netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor"
|
||||
|
@ -1055,6 +1057,13 @@ func (c *cfg) reloadConfig(ctx context.Context) {
|
|||
}
|
||||
|
||||
components = append(components, dCmp{"logger", logPrm.Reload})
|
||||
components = append(components, dCmp{"tracing", func() error {
|
||||
updated, err := tracing.Setup(ctx, *tracingconfig.ToTracingConfig(c.appCfg))
|
||||
if updated {
|
||||
c.log.Info("tracing configation updated")
|
||||
}
|
||||
return err
|
||||
}})
|
||||
if cmp, updated := metricsComponent(c); updated {
|
||||
if cmp.enabled {
|
||||
cmp.preReload = enableMetricsSvc
|
||||
|
|
31
cmd/frostfs-node/config/tracing/config.go
Normal file
31
cmd/frostfs-node/config/tracing/config.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package tracing
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
||||
)
|
||||
|
||||
const (
|
||||
subsection = "tracing"
|
||||
)
|
||||
|
||||
// ToTracingConfig extracts tracing config.
|
||||
func ToTracingConfig(c *config.Config) *tracing.Config {
|
||||
return &tracing.Config{
|
||||
Enabled: config.BoolSafe(c.Sub(subsection), "enabled"),
|
||||
Exporter: tracing.Exporter(config.StringSafe(c.Sub(subsection), "exporter")),
|
||||
Endpoint: config.StringSafe(c.Sub(subsection), "endpoint"),
|
||||
Service: "frostfs-node",
|
||||
InstanceID: getInstanceIDOrDefault(c),
|
||||
Version: misc.Version,
|
||||
}
|
||||
}
|
||||
|
||||
func getInstanceIDOrDefault(c *config.Config) string {
|
||||
s := config.StringSlice(c.Sub("node"), "addresses")
|
||||
if len(s) > 0 {
|
||||
return s[0]
|
||||
}
|
||||
return ""
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
grpcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||
"go.uber.org/zap"
|
||||
|
@ -19,6 +20,12 @@ func initGRPC(c *cfg) {
|
|||
grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) {
|
||||
serverOpts := []grpc.ServerOption{
|
||||
grpc.MaxSendMsgSize(maxMsgSize),
|
||||
grpc.ChainUnaryInterceptor(
|
||||
tracing.NewGRPCUnaryServerInterceptor(),
|
||||
),
|
||||
grpc.ChainStreamInterceptor(
|
||||
tracing.NewGRPCStreamServerInterceptor(),
|
||||
),
|
||||
}
|
||||
|
||||
tlsCfg := sc.TLS()
|
||||
|
|
|
@ -87,6 +87,8 @@ func initApp(ctx context.Context, c *cfg) {
|
|||
initAndLog(c, pprof.name, pprof.init)
|
||||
initAndLog(c, metrics.name, metrics.init)
|
||||
|
||||
initAndLog(c, "tracing", func(c *cfg) { initTracing(ctx, c) })
|
||||
|
||||
initLocalStorage(c)
|
||||
|
||||
initAndLog(c, "storage engine", func(c *cfg) {
|
||||
|
@ -100,7 +102,7 @@ func initApp(ctx context.Context, c *cfg) {
|
|||
initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) })
|
||||
initAndLog(c, "session", initSessionService)
|
||||
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, "tree", initTreeService)
|
||||
initAndLog(c, "control", initControlService)
|
||||
|
|
|
@ -23,7 +23,7 @@ type notificationSource struct {
|
|||
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))
|
||||
|
||||
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() {
|
||||
err = n.processAddress(a, handler)
|
||||
err = n.processAddress(ctx, a, handler)
|
||||
if err != nil {
|
||||
log.Error("notificator: could not process object",
|
||||
zap.Stringer("address", a),
|
||||
|
@ -66,13 +66,14 @@ func (n *notificationSource) Iterate(epoch uint64, handler func(topic string, ad
|
|||
}
|
||||
|
||||
func (n *notificationSource) processAddress(
|
||||
ctx context.Context,
|
||||
a oid.Address,
|
||||
h func(topic string, addr oid.Address),
|
||||
) error {
|
||||
var prm engine.HeadPrm
|
||||
prm.WithAddress(a)
|
||||
|
||||
res, err := n.e.Head(prm)
|
||||
res, err := n.e.Head(ctx, prm)
|
||||
if err != nil {
|
||||
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() {
|
||||
topic := nodeconfig.Notification(c.appCfg).DefaultTopic()
|
||||
pubKey := hex.EncodeToString(c.cfgNodeInfo.localInfo.PublicKey())
|
||||
|
@ -151,7 +152,7 @@ func initNotifications(c *cfg) {
|
|||
addNewEpochAsyncNotificationHandler(c, func(e event.Event) {
|
||||
ev := e.(netmap.NewEpoch)
|
||||
|
||||
n.ProcessEpoch(ev.EpochNumber())
|
||||
n.ProcessEpoch(ctx, ev.EpochNumber())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
31
cmd/frostfs-node/tracing.go
Normal file
31
cmd/frostfs-node/tracing.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func initTracing(ctx context.Context, c *cfg) {
|
||||
conf := tracingconfig.ToTracingConfig(c.appCfg)
|
||||
|
||||
_, err := tracing.Setup(ctx, *conf)
|
||||
if err != nil {
|
||||
c.log.Error("failed init tracing", zap.Error(err))
|
||||
}
|
||||
|
||||
c.closers = append(c.closers, closer{
|
||||
name: "tracing",
|
||||
fn: func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
err := tracing.Shutdown(ctx) //cfg context cancels before close
|
||||
if err != nil {
|
||||
c.log.Error("failed shutdown tracing", zap.Error(err))
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
|
@ -184,3 +184,7 @@ FROSTFS_STORAGE_SHARD_1_PILORAMA_MAX_BATCH_SIZE=100
|
|||
FROSTFS_STORAGE_SHARD_1_GC_REMOVER_BATCH_SIZE=200
|
||||
#### Sleep interval between data remover tacts
|
||||
FROSTFS_STORAGE_SHARD_1_GC_REMOVER_SLEEP_INTERVAL=5m
|
||||
|
||||
FROSTFS_TRACING_ENABLED=true
|
||||
FROSTFS_TRACING_ENDPOINT="localhost"
|
||||
FROSTFS_TRACING_EXPORTER="otlp_grpc"
|
|
@ -243,5 +243,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tracing": {
|
||||
"enabled": true,
|
||||
"endpoint": "localhost:9090",
|
||||
"exporter": "otlp_grpc"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,3 +214,9 @@ storage:
|
|||
path: tmp/1/blob/pilorama.db
|
||||
no_sync: true # USE WITH CAUTION. Return to user before pages have been persisted.
|
||||
perm: 0644 # permission to use for the database file and intermediate directories
|
||||
|
||||
tracing:
|
||||
enabled: true
|
||||
exporter: "otlp_grpc"
|
||||
endpoint: "localhost"
|
||||
|
28
go.mod
28
go.mod
|
@ -3,7 +3,7 @@ module git.frostfs.info/TrueCloudLab/frostfs-node
|
|||
go 1.18
|
||||
|
||||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.11.2-0.20230315095236-9dc375346703
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.0
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230316081442-bec77f280a85
|
||||
git.frostfs.info/TrueCloudLab/hrw v1.2.0
|
||||
|
@ -20,7 +20,6 @@ require (
|
|||
github.com/multiformats/go-multiaddr v0.8.0
|
||||
github.com/nats-io/nats.go v1.22.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/panjf2000/ants/v2 v2.4.0
|
||||
github.com/paulmach/orb v0.2.2
|
||||
|
@ -29,14 +28,16 @@ require (
|
|||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/stretchr/testify v1.8.2
|
||||
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/zap v1.24.0
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/term v0.3.0
|
||||
google.golang.org/grpc v1.52.0
|
||||
golang.org/x/term v0.5.0
|
||||
google.golang.org/grpc v1.53.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
@ -47,15 +48,19 @@ require (
|
|||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect
|
||||
github.com/benbjohnson/clock v1.1.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/holiman/uint256 v1.2.0 // indirect
|
||||
|
@ -76,6 +81,7 @@ require (
|
|||
github.com/nats-io/nkeys v0.3.0 // 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/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb // indirect
|
||||
github.com/nspcc-dev/rfc6979 v0.2.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
|
@ -90,12 +96,18 @@ require (
|
|||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
|
||||
github.com/twmb/murmur3 v1.1.5 // indirect
|
||||
github.com/urfave/cli v1.22.5 // 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/otlptracegrpc 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/proto/otlp v0.19.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
)
|
||||
|
|
71
go.sum
71
go.sum
|
@ -36,8 +36,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
|||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.11.2-0.20230315095236-9dc375346703 h1:lxe0DtZq/uFZVZu9apx6OcIXCJskQBMd/GVeYGKA3wA=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.11.2-0.20230315095236-9dc375346703/go.mod h1:gRd5iE5A84viily6AcNBsSlTx2XgoWrwRDz7z0MayDQ=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.0 h1:oZ0/KiaFeveXRLi5VVEpuLSHczeFyWx4HDl9wTJUtsE=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.0/go.mod h1:sPyITTmQT662ZI38ud2aoE1SUCAr1mO5xV8P4nzLkKI=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb h1:S/TrbOOu9qEXZRZ9/Ddw7crnxbBUQLo68PSzQWYrc9M=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230307110621-19a8ef2d02fb/go.mod h1:nkR5gaGeez3Zv2SE7aceP0YwxG2FzIB5cGKpQO2vV2o=
|
||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk=
|
||||
|
@ -56,6 +56,7 @@ github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1
|
|||
github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig=
|
||||
github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I=
|
||||
github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
|
||||
github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs=
|
||||
|
@ -90,11 +91,15 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
|
|||
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo=
|
||||
github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
|
@ -110,7 +115,11 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
|
@ -129,6 +138,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
|
|||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
|
@ -156,12 +166,19 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
|
||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -239,6 +256,8 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8
|
|||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
|
@ -445,6 +464,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
|
|||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
|
||||
|
@ -470,8 +490,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
|
@ -500,14 +521,30 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 h1:/fXHZHGvro6MVqV34fJzDhi7sHGpX3Ej/Qjmfn003ho=
|
||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0/go.mod h1:UFG7EBMRdXyFstOwH028U0sVf+AvukSGhF0g8+dmNG8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 h1:TKf2uAs2ueguzLaxOCBXNpHxfO/aC7PAdDsSH0IbeRQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0/go.mod h1:HrbCVv40OOLTABmOn1ZWty6CHXkU8DK/Urc43tHug70=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 h1:ap+y8RXX3Mu9apKVtOkM6WSFESLM8K3wNQyOU8sWHcc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0/go.mod h1:5w41DY6S9gZrbjuq6Y+753e96WfPha5IcsOSZTtullM=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 h1:sEL90JjOO/4yhquXl5zTAkLLsZ5+MycAgX99SDsxGc8=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0/go.mod h1:oCslUcizYdpKYyS9e8srZEqM6BB8fq41VJBjLAE6z1w=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
|
||||
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
|
@ -607,13 +644,14 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -624,6 +662,7 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ
|
|||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -692,8 +731,10 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -708,14 +749,15 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
|
@ -846,8 +888,9 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
|
|||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY=
|
||||
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
|
@ -866,9 +909,11 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
|
|||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
|
||||
google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
|
||||
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobovnicza
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
@ -39,7 +40,7 @@ func testGet(t *testing.T, blz *Blobovnicza, addr oid.Address, expObj []byte, as
|
|||
pGet.SetAddress(addr)
|
||||
|
||||
// try to read object from Blobovnicza
|
||||
res, err := blz.Get(pGet)
|
||||
res, err := blz.Get(context.Background(), pGet)
|
||||
if assertErr != nil {
|
||||
require.True(t, assertErr(err))
|
||||
} else {
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package blobovnicza
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util/slice"
|
||||
"go.etcd.io/bbolt"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// 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
|
||||
// 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 (
|
||||
data []byte
|
||||
addrKey = addressKey(prm.addr)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobovnicza
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -56,7 +57,7 @@ func TestBlobovnicza_Get(t *testing.T) {
|
|||
prmGet.SetAddress(addr)
|
||||
|
||||
checkObj := func() {
|
||||
res, err := blz.Get(prmGet)
|
||||
res, err := blz.Get(context.Background(), prmGet)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, obj, res.Object())
|
||||
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
package blobovniczatree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"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/blobstor/common"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
id := blobovnicza.NewIDFromBytes(prm.StorageID)
|
||||
blz, err := b.openBlobovnicza(id.String())
|
||||
|
@ -32,7 +44,7 @@ func (b *Blobovniczas) Exists(prm common.ExistsPrm) (common.ExistsRes, error) {
|
|||
|
||||
_, ok := activeCache[dirPath]
|
||||
|
||||
_, err := b.getObjectFromLevel(gPrm, p, !ok)
|
||||
_, err := b.getObjectFromLevel(ctx, gPrm, p, !ok)
|
||||
if err != nil {
|
||||
if !blobovnicza.IsErrNotFound(err) {
|
||||
b.log.Debug("could not get object from level",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobovniczatree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -44,7 +45,7 @@ func TestExistsInvalidStorageID(t *testing.T) {
|
|||
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.False(t, res.Exists)
|
||||
})
|
||||
|
@ -57,7 +58,7 @@ func TestExistsInvalidStorageID(t *testing.T) {
|
|||
require.NoError(t, os.Chmod(badDir, 0))
|
||||
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.False(t, res.Exists)
|
||||
})
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package blobovniczatree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"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/blobstor/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -16,7 +21,15 @@ import (
|
|||
//
|
||||
// If blobocvnicza ID is specified, only this blobovnicza is processed.
|
||||
// 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
|
||||
bPrm.SetAddress(prm.Address)
|
||||
|
||||
|
@ -27,7 +40,7 @@ func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) {
|
|||
return res, err
|
||||
}
|
||||
|
||||
return b.getObject(blz, bPrm)
|
||||
return b.getObject(ctx, blz, bPrm)
|
||||
}
|
||||
|
||||
activeCache := make(map[string]struct{})
|
||||
|
@ -37,7 +50,7 @@ func (b *Blobovniczas) Get(prm common.GetPrm) (res common.GetRes, err error) {
|
|||
|
||||
_, ok := activeCache[dirPath]
|
||||
|
||||
res, err = b.getObjectFromLevel(bPrm, p, !ok)
|
||||
res, err = b.getObjectFromLevel(ctx, bPrm, p, !ok)
|
||||
if err != nil {
|
||||
if !blobovnicza.IsErrNotFound(err) {
|
||||
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.
|
||||
//
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
b.lruMtx.Unlock()
|
||||
if ok {
|
||||
if res, err := b.getObject(v, prm); err == nil {
|
||||
if res, err := b.getObject(ctx, v, prm); err == nil {
|
||||
return res, err
|
||||
} else if !blobovnicza.IsErrNotFound(err) {
|
||||
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()
|
||||
|
||||
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
|
||||
} else if !blobovnicza.IsErrNotFound(err) {
|
||||
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 b.getObject(blz, prm)
|
||||
return b.getObject(ctx, blz, prm)
|
||||
}
|
||||
|
||||
// reads object from blobovnicza and returns GetSmallRes.
|
||||
func (b *Blobovniczas) getObject(blz *blobovnicza.Blobovnicza, prm blobovnicza.GetPrm) (common.GetRes, error) {
|
||||
res, err := blz.Get(prm)
|
||||
func (b *Blobovniczas) getObject(ctx context.Context, blz *blobovnicza.Blobovnicza, prm blobovnicza.GetPrm) (common.GetRes, error) {
|
||||
res, err := blz.Get(ctx, prm)
|
||||
if err != nil {
|
||||
return common.GetRes{}, err
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
package blobovniczatree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"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/blobstor/common"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -16,7 +22,16 @@ import (
|
|||
//
|
||||
// If blobocvnicza ID is specified, only this blobovnicza is processed.
|
||||
// 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 {
|
||||
id := blobovnicza.NewIDFromBytes(prm.StorageID)
|
||||
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 b.getObjectRange(blz, prm)
|
||||
return b.getObjectRange(ctx, blz, prm)
|
||||
}
|
||||
|
||||
activeCache := make(map[string]struct{})
|
||||
|
@ -35,7 +50,7 @@ func (b *Blobovniczas) GetRange(prm common.GetRangePrm) (res common.GetRangeRes,
|
|||
|
||||
_, ok := activeCache[dirPath]
|
||||
|
||||
res, err = b.getRangeFromLevel(prm, p, !ok)
|
||||
res, err = b.getRangeFromLevel(ctx, prm, p, !ok)
|
||||
if err != nil {
|
||||
outOfBounds := isErrOutOfRange(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.
|
||||
//
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
b.lruMtx.Unlock()
|
||||
if ok {
|
||||
res, err := b.getObjectRange(v, prm)
|
||||
res, err := b.getObjectRange(ctx, v, prm)
|
||||
switch {
|
||||
case err == nil,
|
||||
isErrOutOfRange(err):
|
||||
|
@ -101,7 +116,7 @@ func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string,
|
|||
b.activeMtx.RUnlock()
|
||||
|
||||
if ok && tryActive {
|
||||
res, err := b.getObjectRange(active.blz, prm)
|
||||
res, err := b.getObjectRange(ctx, active.blz, prm)
|
||||
switch {
|
||||
case err == nil,
|
||||
isErrOutOfRange(err):
|
||||
|
@ -131,11 +146,11 @@ func (b *Blobovniczas) getRangeFromLevel(prm common.GetRangePrm, blzPath string,
|
|||
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.
|
||||
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
|
||||
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.
|
||||
// If blobovnicza learns to do the compression itself,
|
||||
// we can start using GetRange.
|
||||
res, err := blz.Get(gPrm)
|
||||
res, err := blz.Get(ctx, gPrm)
|
||||
if err != nil {
|
||||
return common.GetRangeRes{}, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
@ -62,11 +63,11 @@ func TestCompression(t *testing.T) {
|
|||
}
|
||||
|
||||
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.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.Equal(t, bigObj[i], res2.Object)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
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.
|
||||
// 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.
|
||||
SetReportErrorFunc(f func(string, error))
|
||||
|
||||
Get(GetPrm) (GetRes, error)
|
||||
GetRange(GetRangePrm) (GetRangeRes, error)
|
||||
Exists(ExistsPrm) (ExistsRes, error)
|
||||
Get(context.Context, GetPrm) (GetRes, error)
|
||||
GetRange(context.Context, GetRangePrm) (GetRangeRes, error)
|
||||
Exists(context.Context, ExistsPrm) (ExistsRes, error)
|
||||
Put(PutPrm) (PutRes, error)
|
||||
Delete(DeletePrm) (DeleteRes, error)
|
||||
Iterate(IteratePrm) (IterateRes, error)
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package blobstor
|
||||
|
||||
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"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -9,15 +15,22 @@ import (
|
|||
//
|
||||
// Returns any error encountered that did not allow
|
||||
// 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()
|
||||
defer b.modeMtx.RUnlock()
|
||||
|
||||
if prm.StorageID != nil {
|
||||
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,
|
||||
|
@ -31,7 +44,7 @@ func (b *BlobStor) Exists(prm common.ExistsPrm) (common.ExistsRes, error) {
|
|||
// error | error | log the first error, return the second
|
||||
var errors []error
|
||||
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 {
|
||||
return res, nil
|
||||
} else if err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
|
@ -43,13 +44,13 @@ func TestExists(t *testing.T) {
|
|||
for i := range objects {
|
||||
prm.Address = objectCore.AddressOf(objects[i])
|
||||
|
||||
res, err := b.Exists(prm)
|
||||
res, err := b.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.True(t, res.Exists)
|
||||
}
|
||||
|
||||
prm.Address = oidtest.Address()
|
||||
res, err := b.Exists(prm)
|
||||
res, err := b.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.False(t, res.Exists)
|
||||
|
||||
|
@ -60,13 +61,13 @@ func TestExists(t *testing.T) {
|
|||
|
||||
// Object exists, first error is logged.
|
||||
prm.Address = objectCore.AddressOf(objects[0])
|
||||
res, err := b.Exists(prm)
|
||||
res, err := b.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.True(t, res.Exists)
|
||||
|
||||
// Object doesn't exist, first error is returned.
|
||||
prm.Address = objectCore.AddressOf(objects[1])
|
||||
_, err = b.Exists(prm)
|
||||
_, err = b.Exists(context.Background(), prm)
|
||||
require.Error(t, err)
|
||||
require.ErrorIs(t, err, teststore.ErrDiskExploded)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fstree
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -11,6 +12,7 @@ import (
|
|||
"strings"
|
||||
"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/compression"
|
||||
"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"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
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.
|
||||
|
@ -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
|
||||
// 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)
|
||||
|
||||
_, 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.
|
||||
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)
|
||||
|
||||
if _, err := os.Stat(p); os.IsNotExist(err) {
|
||||
return common.GetRes{}, logicerr.Wrap(apistatus.ObjectNotFound{})
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return common.GetRes{}, err
|
||||
var data []byte
|
||||
var err error
|
||||
{
|
||||
_, 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)
|
||||
|
@ -362,8 +386,16 @@ func (t *FSTree) Get(prm common.GetPrm) (common.GetRes, error) {
|
|||
}
|
||||
|
||||
// GetRange implements common.Storage.
|
||||
func (t *FSTree) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error) {
|
||||
res, err := t.Get(common.GetPrm{Address: prm.Address})
|
||||
func (t *FSTree) GetRange(ctx context.Context, prm common.GetRangePrm) (common.GetRangeRes, error) {
|
||||
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 {
|
||||
return common.GetRangeRes{}, err
|
||||
}
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
package blobstor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"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/util/logicerr"
|
||||
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.
|
||||
// If the descriptor is present, only one sub-storage is tried,
|
||||
// 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()
|
||||
defer b.modeMtx.RUnlock()
|
||||
|
||||
if prm.StorageID == nil {
|
||||
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)) {
|
||||
return res, err
|
||||
}
|
||||
|
@ -26,7 +39,7 @@ func (b *BlobStor) Get(prm common.GetPrm) (common.GetRes, error) {
|
|||
return common.GetRes{}, logicerr.Wrap(apistatus.ObjectNotFound{})
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -1,23 +1,38 @@
|
|||
package blobstor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"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/util/logicerr"
|
||||
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.
|
||||
// If the descriptor is present, only one sub-storage is tried,
|
||||
// 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()
|
||||
defer b.modeMtx.RUnlock()
|
||||
|
||||
if prm.StorageID == nil {
|
||||
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)) {
|
||||
return res, err
|
||||
}
|
||||
|
@ -26,7 +41,7 @@ func (b *BlobStor) GetRange(prm common.GetRangePrm) (common.GetRangeRes, error)
|
|||
return common.GetRangeRes{}, logicerr.Wrap(apistatus.ObjectNotFound{})
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstortest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
|
@ -26,7 +27,7 @@ func TestControl(t *testing.T, cons Constructor, min, max uint64) {
|
|||
prm.StorageID = objects[i].storageID
|
||||
prm.Raw = true
|
||||
|
||||
_, err := s.Get(prm)
|
||||
_, err := s.Get(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstortest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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) {
|
||||
prm := common.ExistsPrm{Address: oidtest.Address()}
|
||||
res, err := s.Exists(prm)
|
||||
res, err := s.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.False(t, res.Exists)
|
||||
})
|
||||
t.Run("get fail", func(t *testing.T) {
|
||||
prm := common.GetPrm{Address: oidtest.Address()}
|
||||
_, err := s.Get(prm)
|
||||
_, err := s.Get(context.Background(), prm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
})
|
||||
t.Run("getrange fail", func(t *testing.T) {
|
||||
prm := common.GetRangePrm{Address: oidtest.Address()}
|
||||
_, err := s.GetRange(prm)
|
||||
_, err := s.GetRange(context.Background(), prm)
|
||||
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.Raw = true
|
||||
|
||||
res, err := s.Get(prm)
|
||||
res, err := s.Get(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, objects[3].raw, res.RawData)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstortest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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) {
|
||||
prm := common.ExistsPrm{Address: oidtest.Address()}
|
||||
res, err := s.Exists(prm)
|
||||
res, err := s.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
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) {
|
||||
prm.StorageID = nil
|
||||
|
||||
res, err := s.Exists(prm)
|
||||
res, err := s.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
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) {
|
||||
prm.StorageID = objects[0].storageID
|
||||
|
||||
res, err := s.Exists(prm)
|
||||
res, err := s.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.True(t, res.Exists)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstortest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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) {
|
||||
gPrm := common.GetPrm{Address: oidtest.Address()}
|
||||
_, err := s.Get(gPrm)
|
||||
_, err := s.Get(context.Background(), gPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
})
|
||||
|
||||
|
@ -29,13 +30,13 @@ func TestGet(t *testing.T, cons Constructor, min, max uint64) {
|
|||
|
||||
// With storage ID.
|
||||
gPrm.StorageID = objects[i].storageID
|
||||
res, err := s.Get(gPrm)
|
||||
res, err := s.Get(context.Background(), gPrm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, objects[i].obj, res.Object)
|
||||
|
||||
// Without storage ID.
|
||||
gPrm.StorageID = nil
|
||||
res, err = s.Get(gPrm)
|
||||
res, err = s.Get(context.Background(), gPrm)
|
||||
require.NoError(t, err)
|
||||
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.Raw = true
|
||||
|
||||
res, err = s.Get(gPrm)
|
||||
res, err = s.Get(context.Background(), gPrm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, objects[i].raw, res.RawData)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstortest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
|
@ -20,7 +21,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) {
|
|||
|
||||
t.Run("missing object", func(t *testing.T) {
|
||||
gPrm := common.GetRangePrm{Address: oidtest.Address()}
|
||||
_, err := s.GetRange(gPrm)
|
||||
_, err := s.GetRange(context.Background(), gPrm)
|
||||
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) {
|
||||
// Without storage ID.
|
||||
res, err := s.GetRange(gPrm)
|
||||
res, err := s.GetRange(context.Background(), gPrm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, payload[start:stop], res.Data)
|
||||
})
|
||||
|
||||
t.Run("with storage ID", func(t *testing.T) {
|
||||
gPrm.StorageID = objects[0].storageID
|
||||
res, err := s.GetRange(gPrm)
|
||||
res, err := s.GetRange(context.Background(), gPrm)
|
||||
require.NoError(t, err)
|
||||
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.SetLength(10)
|
||||
|
||||
_, err := s.GetRange(gPrm)
|
||||
_, err := s.GetRange(context.Background(), gPrm)
|
||||
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.SetLength(uint64(len(payload)))
|
||||
|
||||
_, err := s.GetRange(gPrm)
|
||||
_, err := s.GetRange(context.Background(), gPrm)
|
||||
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.SetLength(1 << 63)
|
||||
|
||||
_, err := s.GetRange(gPrm)
|
||||
_, err := s.GetRange(context.Background(), gPrm)
|
||||
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.SetLength(math.MaxUint64 - 2)
|
||||
|
||||
_, err := s.GetRange(gPrm)
|
||||
_, err := s.GetRange(context.Background(), gPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectOutOfRange))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package memstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
|
@ -32,7 +33,7 @@ func New(opts ...Option) common.Storage {
|
|||
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()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (s *memstoreImpl) GetRange(req common.GetRangePrm) (common.GetRangeRes, error) {
|
||||
getResp, err := s.Get(common.GetPrm{
|
||||
func (s *memstoreImpl) GetRange(ctx context.Context, req common.GetRangePrm) (common.GetRangeRes, error) {
|
||||
getResp, err := s.Get(ctx, common.GetPrm{
|
||||
Address: req.Address,
|
||||
StorageID: req.StorageID,
|
||||
})
|
||||
|
@ -80,7 +81,7 @@ func (s *memstoreImpl) GetRange(req common.GetRangePrm) (common.GetRangeRes, err
|
|||
}, 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()
|
||||
|
||||
s.mu.RLock()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package memstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"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.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.Equal(t, obj.Payload(), resp.Object.Payload())
|
||||
}
|
||||
|
@ -47,7 +48,7 @@ func TestSimpleLifecycle(t *testing.T) {
|
|||
var objRange objectSDK.Range
|
||||
objRange.SetOffset(256)
|
||||
objRange.SetLength(512)
|
||||
resp, err := s.GetRange(common.GetRangePrm{
|
||||
resp, err := s.GetRange(context.Background(), common.GetRangePrm{
|
||||
Address: addr,
|
||||
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.False(t, resp.Exists)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package blobstor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
@ -119,7 +120,7 @@ func BenchmarkSubstorageReadPerf(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package teststore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"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 {
|
||||
case s.overrides.Get != nil:
|
||||
return s.overrides.Get(req)
|
||||
case s.st != nil:
|
||||
return s.st.Get(req)
|
||||
return s.st.Get(ctx, req)
|
||||
default:
|
||||
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()
|
||||
defer s.mu.RUnlock()
|
||||
switch {
|
||||
case s.overrides.GetRange != nil:
|
||||
return s.overrides.GetRange(req)
|
||||
case s.st != nil:
|
||||
return s.st.GetRange(req)
|
||||
return s.st.GetRange(ctx, req)
|
||||
default:
|
||||
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 {
|
||||
case s.overrides.Exists != nil:
|
||||
return s.overrides.Exists(req)
|
||||
case s.st != nil:
|
||||
return s.st.Exists(req)
|
||||
return s.st.Exists(ctx, req)
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected storage call: Exists(%+v)", req))
|
||||
}
|
||||
|
|
|
@ -212,20 +212,20 @@ func TestExecBlocks(t *testing.T) {
|
|||
require.NoError(t, e.BlockExecution(errBlock))
|
||||
|
||||
// try to exec some op
|
||||
_, err := Head(e, addr)
|
||||
_, err := Head(context.Background(), e, addr)
|
||||
require.ErrorIs(t, err, errBlock)
|
||||
|
||||
// resume executions
|
||||
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)
|
||||
|
||||
// close
|
||||
require.NoError(t, e.Close())
|
||||
|
||||
// try exec after close
|
||||
_, err = Head(e, addr)
|
||||
_, err = Head(context.Background(), e, addr)
|
||||
require.Error(t, err)
|
||||
|
||||
// try to resume
|
||||
|
|
|
@ -72,7 +72,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e
|
|||
var existsPrm shard.ExistsPrm
|
||||
existsPrm.SetAddress(prm.addr)
|
||||
|
||||
resExists, err := sh.Exists(existsPrm)
|
||||
resExists, err := sh.Exists(ctx, existsPrm)
|
||||
if err != nil {
|
||||
if shard.IsErrRemoved(err) || shard.IsErrObjectExpired(err) {
|
||||
return true
|
||||
|
|
|
@ -93,7 +93,7 @@ func checkGetError(t *testing.T, e *StorageEngine, addr oid.Address, expected an
|
|||
var getPrm GetPrm
|
||||
getPrm.WithAddress(addr)
|
||||
|
||||
_, err := e.Get(getPrm)
|
||||
_, err := e.Get(context.Background(), getPrm)
|
||||
if expected != nil {
|
||||
require.ErrorAs(t, err, expected)
|
||||
} else {
|
||||
|
|
|
@ -102,7 +102,7 @@ func TestErrorReporting(t *testing.T) {
|
|||
te.ng.mtx.RUnlock()
|
||||
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)
|
||||
|
||||
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++ {
|
||||
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)})
|
||||
_, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
|
||||
require.Error(t, err)
|
||||
checkShardState(t, te.ng, te.shards[0].id, i, 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()
|
||||
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)
|
||||
|
||||
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++ {
|
||||
_, err = te.ng.Get(GetPrm{addr: object.AddressOf(obj)})
|
||||
_, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)})
|
||||
require.Error(t, err)
|
||||
checkShardState(t, te.ng, te.shards[0].id, i, mode.ReadWrite)
|
||||
checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite)
|
||||
}
|
||||
|
||||
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)
|
||||
checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.DegradedReadOnly)
|
||||
checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite)
|
||||
|
@ -193,9 +193,9 @@ func TestBlobstorFailback(t *testing.T) {
|
|||
|
||||
for i := range objs {
|
||||
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)
|
||||
_, err = te.ng.GetRange(RngPrm{addr: addr})
|
||||
_, err = te.ng.GetRange(context.Background(), RngPrm{addr: addr})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
@ -213,15 +213,15 @@ func TestBlobstorFailback(t *testing.T) {
|
|||
|
||||
for i := range objs {
|
||||
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.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.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{})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"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.
|
||||
// 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))
|
||||
for i := range prm.shardID {
|
||||
shardIDs[i] = prm.shardID[i].String()
|
||||
|
@ -83,7 +84,7 @@ func (e *StorageEngine) Evacuate(prm EvacuateShardPrm) (EvacuateShardRes, error)
|
|||
var res EvacuateShardRes
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ func (e *StorageEngine) Evacuate(prm EvacuateShardPrm) (EvacuateShardRes, error)
|
|||
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 {
|
||||
var listPrm shard.ListWithCursorPrm
|
||||
listPrm.WithCount(defaultEvacuateBatchSize)
|
||||
|
@ -113,7 +114,7 @@ func (e *StorageEngine) evacuateShard(shardID string, prm EvacuateShardPrm, res
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -160,7 +161,7 @@ func (e *StorageEngine) getActualShards(shardIDs []string, handlerDefined bool)
|
|||
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 {
|
||||
for i := range toEvacuate {
|
||||
addr := toEvacuate[i].Address
|
||||
|
@ -168,7 +169,7 @@ func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.Add
|
|||
var getPrm shard.GetPrm
|
||||
getPrm.SetAddress(addr)
|
||||
|
||||
getRes, err := sh.Get(getPrm)
|
||||
getRes, err := sh.Get(ctx, getPrm)
|
||||
if err != nil {
|
||||
if prm.ignoreErrors {
|
||||
continue
|
||||
|
@ -176,7 +177,7 @@ func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.Add
|
|||
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
|
||||
}
|
||||
|
||||
|
@ -195,14 +196,14 @@ func (e *StorageEngine) evacuateObjects(sh *shard.Shard, toEvacuate []object.Add
|
|||
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 {
|
||||
hrw.SortHasherSliceByWeightValue(shards, weights, hrw.Hash([]byte(addr.EncodeToString())))
|
||||
for j := range shards {
|
||||
if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok {
|
||||
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 {
|
||||
e.log.Debug("object is moved to another shard",
|
||||
|
|
|
@ -91,7 +91,7 @@ func TestEvacuateShard(t *testing.T) {
|
|||
var prm GetPrm
|
||||
prm.WithAddress(objectCore.AddressOf(objects[i]))
|
||||
|
||||
_, err := e.Get(prm)
|
||||
_, err := e.Get(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
@ -102,14 +102,14 @@ func TestEvacuateShard(t *testing.T) {
|
|||
prm.WithShardIDList(ids[2:3])
|
||||
|
||||
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.Equal(t, 0, res.Count())
|
||||
})
|
||||
|
||||
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.Equal(t, objPerShard, res.count)
|
||||
|
||||
|
@ -120,7 +120,7 @@ func TestEvacuateShard(t *testing.T) {
|
|||
checkHasObjects(t)
|
||||
|
||||
// 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.Equal(t, 0, res.count)
|
||||
|
||||
|
@ -165,13 +165,13 @@ func TestEvacuateNetwork(t *testing.T) {
|
|||
var prm EvacuateShardPrm
|
||||
prm.shardID = ids[0:1]
|
||||
|
||||
res, err := e.Evacuate(prm)
|
||||
res, err := e.Evacuate(context.Background(), prm)
|
||||
require.ErrorIs(t, err, errMustHaveTwoShards)
|
||||
require.Equal(t, 0, res.Count())
|
||||
|
||||
prm.handler = acceptOneOf(objects, 2)
|
||||
|
||||
res, err = e.Evacuate(prm)
|
||||
res, err = e.Evacuate(context.Background(), prm)
|
||||
require.ErrorIs(t, err, errReplication)
|
||||
require.Equal(t, 2, res.Count())
|
||||
})
|
||||
|
@ -185,14 +185,14 @@ func TestEvacuateNetwork(t *testing.T) {
|
|||
prm.shardID = ids[1:2]
|
||||
prm.handler = acceptOneOf(objects, 2)
|
||||
|
||||
res, err := e.Evacuate(prm)
|
||||
res, err := e.Evacuate(context.Background(), prm)
|
||||
require.ErrorIs(t, err, errReplication)
|
||||
require.Equal(t, 2, res.Count())
|
||||
|
||||
t.Run("no errors", func(t *testing.T) {
|
||||
prm.handler = acceptOneOf(objects, 3)
|
||||
|
||||
res, err := e.Evacuate(prm)
|
||||
res, err := e.Evacuate(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 3, res.Count())
|
||||
})
|
||||
|
@ -217,14 +217,14 @@ func TestEvacuateNetwork(t *testing.T) {
|
|||
prm.shardID = evacuateIDs
|
||||
prm.handler = acceptOneOf(objects, totalCount-1)
|
||||
|
||||
res, err := e.Evacuate(prm)
|
||||
res, err := e.Evacuate(context.Background(), prm)
|
||||
require.ErrorIs(t, err, errReplication)
|
||||
require.Equal(t, totalCount-1, res.Count())
|
||||
|
||||
t.Run("no errors", func(t *testing.T) {
|
||||
prm.handler = acceptOneOf(objects, totalCount)
|
||||
|
||||
res, err := e.Evacuate(prm)
|
||||
res, err := e.Evacuate(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, totalCount, res.Count())
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"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
|
||||
|
||||
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 shard.IsErrRemoved(err) {
|
||||
alreadyRemoved = true
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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/util"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"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 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 {
|
||||
res, err = e.get(prm)
|
||||
res, err = e.get(ctx, prm)
|
||||
return err
|
||||
})
|
||||
|
||||
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 {
|
||||
defer elapsed(e.metrics.AddGetDuration)()
|
||||
}
|
||||
|
@ -69,7 +79,7 @@ func (e *StorageEngine) get(prm GetPrm) (GetRes, error) {
|
|||
Engine: e,
|
||||
}
|
||||
|
||||
it.tryGetWithMeta()
|
||||
it.tryGetWithMeta(ctx)
|
||||
|
||||
if it.SplitInfo != nil {
|
||||
return GetRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo))
|
||||
|
@ -84,7 +94,7 @@ func (e *StorageEngine) get(prm GetPrm) (GetRes, error) {
|
|||
return GetRes{}, it.OutError
|
||||
}
|
||||
|
||||
it.tryGetFromBlobstore()
|
||||
it.tryGetFromBlobstore(ctx)
|
||||
|
||||
if it.Object == nil {
|
||||
return GetRes{}, it.OutError
|
||||
|
@ -116,14 +126,14 @@ type getShardIterator struct {
|
|||
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) {
|
||||
noMeta := sh.GetMode().NoMetabase()
|
||||
i.ShardPrm.SetIgnoreMeta(noMeta)
|
||||
|
||||
i.HasDegraded = i.HasDegraded || noMeta
|
||||
|
||||
res, err := sh.Get(i.ShardPrm)
|
||||
res, err := sh.Get(ctx, i.ShardPrm)
|
||||
if err == nil {
|
||||
i.Object = res.Object()
|
||||
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,
|
||||
// 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.
|
||||
|
@ -174,18 +184,18 @@ func (i *getShardIterator) tryGetFromBlobstore() {
|
|||
return false
|
||||
}
|
||||
|
||||
res, err := sh.Get(i.ShardPrm)
|
||||
res, err := sh.Get(ctx, i.ShardPrm)
|
||||
i.Object = res.Object()
|
||||
return err == nil
|
||||
})
|
||||
}
|
||||
|
||||
// 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
|
||||
getPrm.WithAddress(addr)
|
||||
|
||||
res, err := storage.Get(getPrm)
|
||||
res, err := storage.Get(ctx, getPrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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/util"
|
||||
"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 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 {
|
||||
res, err = e.head(prm)
|
||||
res, err = e.head(ctx, prm)
|
||||
return err
|
||||
})
|
||||
|
||||
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 {
|
||||
defer elapsed(e.metrics.AddHeadDuration)()
|
||||
}
|
||||
|
@ -81,7 +86,7 @@ func (e *StorageEngine) head(prm HeadPrm) (HeadRes, error) {
|
|||
shPrm.SetRaw(prm.raw)
|
||||
|
||||
e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) {
|
||||
res, err := sh.Head(shPrm)
|
||||
res, err := sh.Head(ctx, shPrm)
|
||||
if err != nil {
|
||||
switch {
|
||||
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.
|
||||
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
|
||||
headPrm.WithAddress(addr)
|
||||
|
||||
res, err := storage.Head(headPrm)
|
||||
res, err := storage.Head(ctx, headPrm)
|
||||
if err != nil {
|
||||
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
|
||||
// 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
|
||||
headPrm.WithAddress(addr)
|
||||
headPrm.WithRaw(raw)
|
||||
|
||||
res, err := storage.Head(headPrm)
|
||||
res, err := storage.Head(ctx, headPrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
|
@ -66,7 +67,7 @@ func TestHeadRaw(t *testing.T) {
|
|||
headPrm.WithAddress(parentAddr)
|
||||
headPrm.WithRaw(true)
|
||||
|
||||
_, err = e.Head(headPrm)
|
||||
_, err = e.Head(context.Background(), headPrm)
|
||||
require.Error(t, err)
|
||||
|
||||
var si *object.SplitInfoError
|
||||
|
|
|
@ -134,7 +134,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh
|
|||
|
||||
if checkExists {
|
||||
existPrm.SetAddress(addr)
|
||||
exRes, err := sh.Exists(existPrm)
|
||||
exRes, err := sh.Exists(ctx, existPrm)
|
||||
if err != nil {
|
||||
if shard.IsErrRemoved(err) || shard.IsErrObjectExpired(err) {
|
||||
// inhumed once - no need to be inhumed again
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"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
|
||||
existsPrm.SetAddress(addrLocked)
|
||||
|
||||
exRes, err := sh.Exists(existsPrm)
|
||||
exRes, err := sh.Exists(context.TODO(), existsPrm)
|
||||
if err != nil {
|
||||
var siErr *objectSDK.SplitInfoError
|
||||
if !errors.As(err, &siErr) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
|
||||
|
@ -72,7 +73,7 @@ func (e *StorageEngine) put(prm PutPrm) (PutRes, error) {
|
|||
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
|
||||
return finished
|
||||
})
|
||||
|
@ -87,7 +88,7 @@ func (e *StorageEngine) put(prm PutPrm) (PutRes, error) {
|
|||
// putToShard puts object to sh.
|
||||
// First return value is true iff put has been successfully done.
|
||||
// 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
|
||||
|
||||
exitCh := make(chan struct{})
|
||||
|
@ -98,7 +99,7 @@ func (e *StorageEngine) putToShard(sh hashedShard, ind int, pool util.WorkerPool
|
|||
var existPrm shard.ExistsPrm
|
||||
existPrm.SetAddress(addr)
|
||||
|
||||
exists, err := sh.Exists(existPrm)
|
||||
exists, err := sh.Exists(ctx, existPrm)
|
||||
if err != nil {
|
||||
if shard.IsErrObjectExpired(err) {
|
||||
// object is already found but
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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/util"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"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 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 {
|
||||
res, err = e.getRange(prm)
|
||||
res, err = e.getRange(ctx, prm)
|
||||
return err
|
||||
})
|
||||
|
||||
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 {
|
||||
defer elapsed(e.metrics.AddRangeDuration)()
|
||||
}
|
||||
|
@ -83,7 +96,7 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
|
|||
Engine: e,
|
||||
}
|
||||
|
||||
it.tryGetWithMeta()
|
||||
it.tryGetWithMeta(ctx)
|
||||
|
||||
if it.SplitInfo != nil {
|
||||
return RngRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo))
|
||||
|
@ -96,7 +109,7 @@ func (e *StorageEngine) getRange(prm RngPrm) (RngRes, error) {
|
|||
return RngRes{}, it.OutError
|
||||
}
|
||||
|
||||
it.tryGetFromBlobstor()
|
||||
it.tryGetFromBlobstor(ctx)
|
||||
|
||||
if it.Object == nil {
|
||||
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.
|
||||
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
|
||||
rangePrm.WithAddress(addr)
|
||||
rangePrm.WithPayloadRange(rng)
|
||||
|
||||
res, err := storage.GetRange(rangePrm)
|
||||
res, err := storage.GetRange(ctx, rangePrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -141,13 +154,13 @@ type getRangeShardIterator struct {
|
|||
Engine *StorageEngine
|
||||
}
|
||||
|
||||
func (i *getRangeShardIterator) tryGetWithMeta() {
|
||||
func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) {
|
||||
i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) {
|
||||
noMeta := sh.GetMode().NoMetabase()
|
||||
i.HasDegraded = i.HasDegraded || noMeta
|
||||
i.ShardPrm.SetIgnoreMeta(noMeta)
|
||||
|
||||
res, err := sh.GetRange(i.ShardPrm)
|
||||
res, err := sh.GetRange(ctx, i.ShardPrm)
|
||||
if err == nil {
|
||||
i.Object = res.Object()
|
||||
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,
|
||||
// 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.
|
||||
|
@ -197,7 +210,7 @@ func (i *getRangeShardIterator) tryGetFromBlobstor() {
|
|||
return false
|
||||
}
|
||||
|
||||
res, err := sh.GetRange(i.ShardPrm)
|
||||
res, err := sh.GetRange(ctx, i.ShardPrm)
|
||||
if shard.IsErrOutOfRange(err) {
|
||||
var errOutOfRange apistatus.ObjectOutOfRange
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ func (e *StorageEngine) removeObjects(ctx context.Context, ch <-chan oid.Address
|
|||
var existsPrm shard.ExistsPrm
|
||||
existsPrm.SetAddress(addr)
|
||||
|
||||
res, err := shards[i].Exists(existsPrm)
|
||||
res, err := shards[i].Exists(ctx, existsPrm)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !res.Exists() {
|
||||
|
|
|
@ -63,6 +63,7 @@ func TestShardOpen(t *testing.T) {
|
|||
|
||||
newShard := func() *Shard {
|
||||
return New(
|
||||
WithID(NewIDFromBytes([]byte{})),
|
||||
WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}),
|
||||
WithBlobStorOptions(
|
||||
blobstor.WithStorages([]blobstor.SubStorage{
|
||||
|
@ -146,6 +147,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
sh = New(
|
||||
WithID(NewIDFromBytes([]byte{})),
|
||||
WithBlobStorOptions(blobOpts...),
|
||||
WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))),
|
||||
WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta_new")), meta.WithEpochState(epochState{})),
|
||||
|
@ -155,7 +157,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) {
|
|||
|
||||
var getPrm GetPrm
|
||||
getPrm.SetAddress(addr)
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
require.NoError(t, sh.Close())
|
||||
}
|
||||
|
@ -176,6 +178,7 @@ func TestRefillMetabase(t *testing.T) {
|
|||
}
|
||||
|
||||
sh := New(
|
||||
WithID(NewIDFromBytes([]byte{})),
|
||||
WithBlobStorOptions(blobOpts...),
|
||||
WithMetaBaseOptions(
|
||||
meta.WithPath(filepath.Join(p, "meta")),
|
||||
|
@ -277,7 +280,7 @@ func TestRefillMetabase(t *testing.T) {
|
|||
checkObj := func(addr oid.Address, expObj *objectSDK.Object) {
|
||||
headPrm.SetAddress(addr)
|
||||
|
||||
res, err := sh.Head(headPrm)
|
||||
res, err := sh.Head(context.Background(), headPrm)
|
||||
|
||||
if expObj == nil {
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
|
@ -302,7 +305,7 @@ func TestRefillMetabase(t *testing.T) {
|
|||
for _, member := range tombMembers {
|
||||
headPrm.SetAddress(member)
|
||||
|
||||
_, err := sh.Head(headPrm)
|
||||
_, err := sh.Head(context.Background(), headPrm)
|
||||
|
||||
if exists {
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
|
||||
|
@ -343,6 +346,7 @@ func TestRefillMetabase(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
sh = New(
|
||||
WithID(NewIDFromBytes([]byte{})),
|
||||
WithBlobStorOptions(blobOpts...),
|
||||
WithMetaBaseOptions(
|
||||
meta.WithPath(filepath.Join(p, "meta_restored")),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shard_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
|
||||
|
@ -51,7 +52,7 @@ func testShardDelete(t *testing.T, hasWriteCache bool) {
|
|||
_, err = sh.Delete(delPrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
})
|
||||
|
||||
|
@ -69,13 +70,13 @@ func testShardDelete(t *testing.T, hasWriteCache bool) {
|
|||
_, err := sh.Put(putPrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = sh.Delete(delPrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package shard_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
@ -276,7 +277,7 @@ func checkRestore(t *testing.T, sh *shard.Shard, prm shard.RestorePrm, objects [
|
|||
|
||||
for i := range objects {
|
||||
getPrm.SetAddress(object.AddressOf(objects[i]))
|
||||
res, err := sh.Get(getPrm)
|
||||
res, err := sh.Get(context.Background(), getPrm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, objects[i], res.Object())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package shard
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||
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 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 err error
|
||||
|
||||
|
@ -45,7 +47,7 @@ func (s *Shard) Exists(prm ExistsPrm) (ExistsRes, error) {
|
|||
p.Address = prm.addr
|
||||
|
||||
var res common.ExistsRes
|
||||
res, err = s.blobStor.Exists(p)
|
||||
res, err = s.blobStor.Exists(ctx, p)
|
||||
exists = res.Exists
|
||||
} else {
|
||||
var existsPrm meta.ExistsPrm
|
||||
|
|
|
@ -33,6 +33,7 @@ func Test_GCDropsLockedExpiredObject(t *testing.T) {
|
|||
|
||||
rootPath := t.TempDir()
|
||||
opts := []shard.Option{
|
||||
shard.WithID(shard.NewIDFromBytes([]byte{})),
|
||||
shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}),
|
||||
shard.WithBlobStorOptions(
|
||||
blobstor.WithStorages([]blobstor.SubStorage{
|
||||
|
@ -115,7 +116,7 @@ func Test_GCDropsLockedExpiredObject(t *testing.T) {
|
|||
var getPrm shard.GetPrm
|
||||
getPrm.SetAddress(objectCore.AddressOf(obj))
|
||||
require.Eventually(t, func() bool {
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
return shard.IsErrNotFound(err)
|
||||
}, 3*time.Second, 1*time.Second, "expired object must be deleted")
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package shard
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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/common"
|
||||
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"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"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.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
||||
// 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()
|
||||
defer s.m.RUnlock()
|
||||
|
||||
|
@ -70,7 +82,7 @@ func (s *Shard) Get(prm GetPrm) (GetRes, error) {
|
|||
getPrm.Address = prm.addr
|
||||
getPrm.StorageID = id
|
||||
|
||||
res, err := stor.Get(getPrm)
|
||||
res, err := stor.Get(ctx, getPrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -79,7 +91,7 @@ func (s *Shard) Get(prm GetPrm) (GetRes, 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()
|
||||
|
|
|
@ -2,6 +2,7 @@ package shard_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"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) {
|
||||
res, err := sh.Get(getPrm)
|
||||
res, err := sh.Get(context.Background(), getPrm)
|
||||
if hasWriteCache {
|
||||
require.Eventually(t, func() bool {
|
||||
if shard.IsErrNotFound(err) {
|
||||
res, err = sh.Get(getPrm)
|
||||
res, err = sh.Get(context.Background(), getPrm)
|
||||
}
|
||||
return !shard.IsErrNotFound(err)
|
||||
}, time.Second, time.Millisecond*100)
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package shard
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
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.
|
||||
|
@ -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.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
||||
// 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 err error
|
||||
if s.GetMode().NoMetabase() {
|
||||
|
@ -52,7 +65,7 @@ func (s *Shard) Head(prm HeadPrm) (HeadRes, error) {
|
|||
getPrm.SetIgnoreMeta(true)
|
||||
|
||||
var res GetRes
|
||||
res, err = s.Get(getPrm)
|
||||
res, err = s.Get(ctx, getPrm)
|
||||
obj = res.Object()
|
||||
} else {
|
||||
var headParams meta.GetPrm
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shard_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -75,18 +76,18 @@ func testShardHead(t *testing.T, hasWriteCache bool) {
|
|||
headPrm.SetAddress(object.AddressOf(parent))
|
||||
headPrm.SetRaw(false)
|
||||
|
||||
head, err := sh.Head(headPrm)
|
||||
head, err := sh.Head(context.Background(), headPrm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, parent.CutPayload(), head.Object())
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
require.Eventually(t, func() bool {
|
||||
if shard.IsErrNotFound(err) {
|
||||
res, err = sh.Head(headPrm)
|
||||
res, err = sh.Head(context.Background(), headPrm)
|
||||
}
|
||||
return !shard.IsErrNotFound(err)
|
||||
}, time.Second, time.Millisecond*100)
|
||||
|
|
|
@ -51,6 +51,6 @@ func testShardInhume(t *testing.T, hasWriteCache bool) {
|
|||
_, err = sh.Inhume(context.Background(), inhPrm)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ func TestShard_Lock(t *testing.T) {
|
|||
|
||||
rootPath := t.TempDir()
|
||||
opts := []shard.Option{
|
||||
shard.WithID(shard.NewIDFromBytes([]byte{})),
|
||||
shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}),
|
||||
shard.WithBlobStorOptions(
|
||||
blobstor.WithStorages([]blobstor.SubStorage{
|
||||
|
@ -137,7 +138,7 @@ func TestShard_Lock(t *testing.T) {
|
|||
var getPrm shard.GetPrm
|
||||
getPrm.SetAddress(objectcore.AddressOf(obj))
|
||||
|
||||
_, err = sh.Get(getPrm)
|
||||
_, err = sh.Get(context.Background(), getPrm)
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package shard
|
||||
|
||||
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/common"
|
||||
"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"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
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.
|
||||
|
@ -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.ObjectAlreadyRemoved if the requested object has been marked as removed in shard.
|
||||
// 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()
|
||||
defer s.m.RUnlock()
|
||||
|
||||
|
@ -77,7 +93,7 @@ func (s *Shard) GetRange(prm RngPrm) (RngRes, error) {
|
|||
getRngPrm.Range.SetLength(prm.ln)
|
||||
getRngPrm.StorageID = id
|
||||
|
||||
res, err := stor.GetRange(getRngPrm)
|
||||
res, err := stor.GetRange(ctx, getRngPrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -89,7 +105,7 @@ func (s *Shard) GetRange(prm RngPrm) (RngRes, 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 {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shard_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -105,7 +106,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) {
|
|||
rngPrm.SetAddress(addr)
|
||||
rngPrm.SetRange(tc.rng.GetOffset(), tc.rng.GetLength())
|
||||
|
||||
res, err := sh.GetRange(rngPrm)
|
||||
res, err := sh.GetRange(context.Background(), rngPrm)
|
||||
if tc.hasErr {
|
||||
require.ErrorAs(t, err, &apistatus.ObjectOutOfRange{})
|
||||
} else {
|
||||
|
|
|
@ -66,7 +66,7 @@ func TestShardReload(t *testing.T) {
|
|||
var prm ExistsPrm
|
||||
prm.SetAddress(objects[i].addr)
|
||||
|
||||
res, err := sh.Exists(prm)
|
||||
res, err := sh.Exists(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, exists, res.Exists(), "object #%d is missing", i)
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts
|
|||
}
|
||||
|
||||
opts := []shard.Option{
|
||||
shard.WithID(shard.NewIDFromBytes([]byte{})),
|
||||
shard.WithLogger(&logger.Logger{Logger: zap.L()}),
|
||||
shard.WithBlobStorOptions(bsOpts...),
|
||||
shard.WithMetaBaseOptions(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shard_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
|
@ -55,7 +56,7 @@ func TestWriteCacheObjectLoss(t *testing.T) {
|
|||
for i := range objects {
|
||||
getPrm.SetAddress(object.AddressOf(objects[i]))
|
||||
|
||||
_, err := sh.Get(getPrm)
|
||||
_, err := sh.Get(context.Background(), getPrm)
|
||||
require.NoError(t, err, i)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package writecache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
@ -95,7 +96,7 @@ func TestFlush(t *testing.T) {
|
|||
prm.Address = objects[i].addr
|
||||
prm.StorageID = mRes.StorageID()
|
||||
|
||||
res, err := bs.Get(prm)
|
||||
res, err := bs.Get(context.Background(), prm)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, objects[i].obj, res.Object)
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ func TestFlush(t *testing.T) {
|
|||
_, err := mb.Get(mPrm)
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -149,7 +150,7 @@ func TestFlush(t *testing.T) {
|
|||
_, err := mb.Get(mPrm)
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -266,7 +267,7 @@ func TestFlush(t *testing.T) {
|
|||
require.NoError(t, wc.Open(true))
|
||||
initWC(t, wc)
|
||||
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, wc.Close())
|
||||
|
@ -275,7 +276,7 @@ func TestFlush(t *testing.T) {
|
|||
require.NoError(t, wc.Open(false))
|
||||
initWC(t, wc)
|
||||
for i := range objects {
|
||||
_, err := wc.Get(objects[i].addr)
|
||||
_, err := wc.Get(context.Background(), objects[i].addr)
|
||||
if i < 2 {
|
||||
require.ErrorAs(t, err, new(apistatus.ObjectNotFound), i)
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package writecache
|
||||
|
||||
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/util/logicerr"
|
||||
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"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util/slice"
|
||||
"go.etcd.io/bbolt"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Get returns object from 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()
|
||||
|
||||
ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Get",
|
||||
trace.WithAttributes(
|
||||
attribute.String("address", saddr),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
value, err := Get(c.db, []byte(saddr))
|
||||
if err == nil {
|
||||
obj := objectSDK.New()
|
||||
|
@ -23,7 +34,7 @@ func (c *cache) Get(addr oid.Address) (*objectSDK.Object, error) {
|
|||
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 {
|
||||
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.
|
||||
//
|
||||
// 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) {
|
||||
obj, err := c.Get(addr)
|
||||
func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package writecache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
|
@ -177,6 +178,6 @@ func (c *cache) flushStatus(addr oid.Address) (bool, bool) {
|
|||
prm.SetAddress(addr)
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package writecache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
"os"
|
||||
"time"
|
||||
|
@ -27,7 +28,7 @@ type metabase interface {
|
|||
type blob interface {
|
||||
Put(common.PutPrm) (common.PutRes, error)
|
||||
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 {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package writecache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
|
@ -23,8 +24,8 @@ type Info struct {
|
|||
|
||||
// Cache represents write-cache for objects.
|
||||
type Cache interface {
|
||||
Get(address oid.Address) (*object.Object, error)
|
||||
Head(oid.Address) (*object.Object, error)
|
||||
Get(ctx context.Context, address oid.Address) (*object.Object, error)
|
||||
Head(context.Context, oid.Address) (*object.Object, error)
|
||||
// Delete removes object referenced by the given oid.Address from the
|
||||
// Cache. Returns any error encountered that prevented the object to be
|
||||
// removed.
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"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)
|
||||
if err != nil {
|
||||
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.WithFaultHandler(s.replicate)
|
||||
|
||||
res, err := s.s.Evacuate(prm)
|
||||
res, err := s.s.Evacuate(ctx, prm)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package notificator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
)
|
||||
|
||||
|
@ -8,7 +10,7 @@ import (
|
|||
type NotificationSource interface {
|
||||
// Iterate must iterate over all notifications for the
|
||||
// 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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package notificator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"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
|
||||
// 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.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",
|
||||
zap.String("topic", topic),
|
||||
zap.Stringer("address", addr),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"testing"
|
||||
|
@ -26,7 +27,7 @@ type testLocalStorage struct {
|
|||
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.Object().Equals(s.expAddr.Object()))
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
@ -27,7 +28,7 @@ type cfg struct {
|
|||
}
|
||||
|
||||
type ObjectStorage interface {
|
||||
Head(oid.Address) (*object.Object, error)
|
||||
Head(context.Context, oid.Address) (*object.Object, error)
|
||||
}
|
||||
|
||||
type Request interface {
|
||||
|
@ -207,7 +208,7 @@ func (h *cfg) localObjectHeaders(cnr cid.ID, idObj *oid.ID) ([]eaclSDK.Header, b
|
|||
addr.SetContainer(cnr)
|
||||
addr.SetObject(*idObj)
|
||||
|
||||
obj, err := h.storage.Head(addr)
|
||||
obj, err := h.storage.Head(context.TODO(), addr)
|
||||
if err == nil {
|
||||
return headersFromObject(obj, cnr, idObj), true
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
||||
|
@ -12,10 +13,10 @@ type localStorage struct {
|
|||
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 {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
return engine.Head(s.ls, addr)
|
||||
return engine.Head(ctx, s.ls, addr)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
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-node/pkg/core/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object"
|
||||
|
@ -111,6 +112,14 @@ func New(opts ...Option) Service {
|
|||
// Get implements ServiceServer interface, makes ACL checks and calls
|
||||
// next Get method in the ServiceServer pipeline.
|
||||
func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream) error {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(stream.Context(), "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
cnr, err := getContainerIDFromRequest(request)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -158,6 +167,9 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream
|
|||
return eACLErr(reqInfo, err)
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
return b.next.Get(request, &getStreamBasicChecker{
|
||||
GetObjectStream: stream,
|
||||
info: reqInfo,
|
||||
|
@ -177,6 +189,14 @@ func (b Service) Put() (object.PutObjectStream, error) {
|
|||
func (b Service) Head(
|
||||
ctx context.Context,
|
||||
request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(ctx, "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
cnr, err := getContainerIDFromRequest(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -224,6 +244,9 @@ func (b Service) Head(
|
|||
return nil, eACLErr(reqInfo, err)
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
resp, err := b.next.Head(ctx, request)
|
||||
if err == nil {
|
||||
if err = b.checker.CheckEACL(resp, reqInfo); err != nil {
|
||||
|
@ -235,6 +258,14 @@ func (b Service) Head(
|
|||
}
|
||||
|
||||
func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStream) error {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(stream.Context(), "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
id, err := getContainerIDFromRequest(request)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -275,6 +306,9 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr
|
|||
return eACLErr(reqInfo, err)
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
return b.next.Search(request, &searchStreamBasicChecker{
|
||||
checker: b.checker,
|
||||
SearchStream: stream,
|
||||
|
@ -285,6 +319,14 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr
|
|||
func (b Service) Delete(
|
||||
ctx context.Context,
|
||||
request *objectV2.DeleteRequest) (*objectV2.DeleteResponse, error) {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(ctx, "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
cnr, err := getContainerIDFromRequest(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -332,10 +374,21 @@ func (b Service) Delete(
|
|||
return nil, eACLErr(reqInfo, err)
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
return b.next.Delete(ctx, request)
|
||||
}
|
||||
|
||||
func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetObjectRangeStream) error {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(stream.Context(), "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
cnr, err := getContainerIDFromRequest(request)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -383,6 +436,9 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb
|
|||
return eACLErr(reqInfo, err)
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
return b.next.GetRange(request, &rangeStreamBasicChecker{
|
||||
checker: b.checker,
|
||||
GetObjectRangeStream: stream,
|
||||
|
@ -393,6 +449,14 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb
|
|||
func (b Service) GetRangeHash(
|
||||
ctx context.Context,
|
||||
request *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(ctx, "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
cnr, err := getContainerIDFromRequest(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -440,10 +504,21 @@ func (b Service) GetRangeHash(
|
|||
return nil, eACLErr(reqInfo, err)
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
return b.next.GetRangeHash(ctx, request)
|
||||
}
|
||||
|
||||
func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRequest) error {
|
||||
spanClosed := false
|
||||
_, span := tracing.StartSpanFromContext(ctx, "checkACL")
|
||||
defer func() {
|
||||
if !spanClosed {
|
||||
span.End()
|
||||
}
|
||||
}()
|
||||
|
||||
body := request.GetBody()
|
||||
if body == nil {
|
||||
return errEmptyBody
|
||||
|
@ -512,6 +587,9 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe
|
|||
}
|
||||
}
|
||||
|
||||
span.End()
|
||||
spanClosed = true
|
||||
|
||||
return p.next.Send(ctx, request)
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ func (c *testClient) addResult(addr oid.Address, obj *objectSDK.Object, err erro
|
|||
}{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 (
|
||||
ok bool
|
||||
obj *objectSDK.Object
|
||||
|
|
|
@ -4,15 +4,21 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (exec *execCtx) executeLocal(ctx context.Context) {
|
||||
ctx, span := tracing.StartSpanFromContext(ctx, "getService.executeLocal")
|
||||
defer func() {
|
||||
span.End()
|
||||
}()
|
||||
|
||||
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 errRemoved apistatus.ObjectAlreadyRemoved
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
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 {
|
||||
ctx, span := tracing.StartSpanFromContext(ctx, "getService.processNode")
|
||||
defer span.End()
|
||||
|
||||
exec.log.Debug("processing node...")
|
||||
|
||||
client, ok := exec.remoteClient(info)
|
||||
|
|
|
@ -31,7 +31,7 @@ type cfg struct {
|
|||
log *logger.Logger
|
||||
|
||||
localStorage interface {
|
||||
get(*execCtx) (*object.Object, error)
|
||||
get(context.Context, *execCtx) (*object.Object, error)
|
||||
}
|
||||
|
||||
clientCache interface {
|
||||
|
|
|
@ -200,13 +200,13 @@ func (c *clientWrapper) get(ctx context.Context, exec *execCtx, key *ecdsa.Priva
|
|||
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() {
|
||||
var headPrm engine.HeadPrm
|
||||
headPrm.WithAddress(exec.address())
|
||||
headPrm.WithRaw(exec.isRaw())
|
||||
|
||||
r, err := e.engine.Head(headPrm)
|
||||
r, err := e.engine.Head(ctx, headPrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) {
|
|||
getRange.WithAddress(exec.address())
|
||||
getRange.WithPayloadRange(rng)
|
||||
|
||||
r, err := e.engine.GetRange(getRange)
|
||||
r, err := e.engine.GetRange(ctx, getRange)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) {
|
|||
var getPrm engine.GetPrm
|
||||
getPrm.WithAddress(exec.address())
|
||||
|
||||
r, err := e.engine.Get(getPrm)
|
||||
r, err := e.engine.Get(ctx, getPrm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
|
||||
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"
|
||||
rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
|
@ -18,6 +19,8 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal"
|
||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
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) {
|
||||
ctx, span := tracing.StartSpanFromContext(ctx, "getRequestForwarder.forwardRequestToNode",
|
||||
trace.WithAttributes(attribute.String("address", addr.String())),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
|
||||
// once compose and resign forwarding request
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
|
||||
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"
|
||||
rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
|
@ -18,6 +19,8 @@ import (
|
|||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal"
|
||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
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) {
|
||||
ctx, span := tracing.StartSpanFromContext(ctx, "getRangeRequestForwarder.forwardRequestToNode",
|
||||
trace.WithAttributes(attribute.String("address", addr.String())),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
|
||||
// once compose and resign forwarding request
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"sync"
|
||||
|
||||
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/rpc"
|
||||
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"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
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) {
|
||||
ctx, span := tracing.StartSpanFromContext(ctx, "headRequestForwarder.forwardRequestToNode",
|
||||
trace.WithAttributes(attribute.String("address", addr.String())),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
|
||||
// once compose and resign forwarding request
|
||||
|
|
|
@ -96,7 +96,7 @@ func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV
|
|||
resp := new(objectV2.HeadResponse)
|
||||
resp.SetBody(new(objectV2.HeadResponseBody))
|
||||
|
||||
p, err := s.toHeadPrm(ctx, req, resp)
|
||||
p, err := s.toHeadPrm(req, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ func (w *headResponseWriter) WriteHeader(_ context.Context, hdr *object.Object)
|
|||
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()
|
||||
|
||||
addrV2 := body.GetAddress()
|
||||
|
|
|
@ -54,7 +54,7 @@ func (s *getStreamSigner) Send(resp *object.GetResponse) error {
|
|||
}
|
||||
|
||||
func (s *SignService) Get(req *object.GetRequest, stream GetObjectStream) error {
|
||||
return s.sigSvc.HandleServerStreamRequest(req,
|
||||
return s.sigSvc.HandleServerStreamRequest(stream.Context(), req,
|
||||
func(resp util.ResponseMessage) error {
|
||||
return stream.Send(resp.(*object.GetResponse))
|
||||
},
|
||||
|
@ -126,7 +126,7 @@ func (s *searchStreamSigner) Send(resp *object.SearchResponse) error {
|
|||
}
|
||||
|
||||
func (s *SignService) Search(req *object.SearchRequest, stream SearchStream) error {
|
||||
return s.sigSvc.HandleServerStreamRequest(req,
|
||||
return s.sigSvc.HandleServerStreamRequest(stream.Context(), req,
|
||||
func(resp util.ResponseMessage) error {
|
||||
return stream.Send(resp.(*object.SearchResponse))
|
||||
},
|
||||
|
@ -176,7 +176,7 @@ func (s *getRangeStreamSigner) Send(resp *object.GetRangeResponse) error {
|
|||
}
|
||||
|
||||
func (s *SignService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error {
|
||||
return s.sigSvc.HandleServerStreamRequest(req,
|
||||
return s.sigSvc.HandleServerStreamRequest(stream.Context(), req,
|
||||
func(resp util.ResponseMessage) error {
|
||||
return stream.Send(resp.(*object.GetRangeResponse))
|
||||
},
|
||||
|
|
|
@ -27,7 +27,7 @@ func (p *Replicator) HandleTask(ctx context.Context, task Task, res TaskResult)
|
|||
|
||||
if task.obj == nil {
|
||||
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 {
|
||||
p.log.Error("could not get object from local storage",
|
||||
zap.Stringer("object", task.addr),
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
|
||||
"github.com/hashicorp/golang-lru/v2/simplelru"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -84,8 +85,15 @@ func dialTreeService(ctx context.Context, netmapAddr string) (*grpc.ClientConn,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
opts := make([]grpc.DialOption, 1, 2)
|
||||
opts[0] = grpc.WithBlock()
|
||||
opts := []grpc.DialOption{
|
||||
grpc.WithBlock(),
|
||||
grpc.WithChainUnaryInterceptor(
|
||||
tracing.NewGRPCUnaryClientInteceptor(),
|
||||
),
|
||||
grpc.WithChainStreamInterceptor(
|
||||
tracing.NewGRPCStreamClientInterceptor(),
|
||||
),
|
||||
}
|
||||
|
||||
// FIXME(@fyrchik): ugly hack #1322
|
||||
if !strings.HasPrefix(netAddr.URIAddr(), "grpcs:") {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"math/rand"
|
||||
"sync"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
|
||||
|
@ -146,7 +147,14 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64,
|
|||
return false
|
||||
}
|
||||
|
||||
cc, err := grpc.DialContext(egCtx, a.URIAddr(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
cc, err := grpc.DialContext(egCtx, a.URIAddr(),
|
||||
grpc.WithChainUnaryInterceptor(
|
||||
tracing.NewGRPCUnaryClientInteceptor(),
|
||||
),
|
||||
grpc.WithChainStreamInterceptor(
|
||||
tracing.NewGRPCStreamClientInterceptor(),
|
||||
),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
// Failed to connect, try the next address.
|
||||
return false
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/pkg/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
|
||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
|
@ -67,8 +68,7 @@ func (s *RequestMessageStreamer) Send(ctx context.Context, req any) error {
|
|||
|
||||
var err error
|
||||
|
||||
// verify request signatures
|
||||
if err = signature.VerifyServiceMessage(req); err != nil {
|
||||
if err = verifyRequestSignature(ctx, req); err != nil {
|
||||
err = fmt.Errorf("could not verify request: %w", err)
|
||||
} else {
|
||||
err = s.send(ctx, req)
|
||||
|
@ -112,7 +112,7 @@ func (s *RequestMessageStreamer) CloseAndRecv(ctx context.Context) (ResponseMess
|
|||
setStatusV2(resp, err)
|
||||
}
|
||||
|
||||
if err = signResponse(s.key, resp, s.statusSupported); err != nil {
|
||||
if err = signResponse(ctx, s.key, resp, s.statusSupported); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ func (s *SignService) CreateRequestStreamer(sender RequestMessageWriter, closer
|
|||
}
|
||||
|
||||
func (s *SignService) HandleServerStreamRequest(
|
||||
ctx context.Context,
|
||||
req any,
|
||||
respWriter ResponseMessageWriter,
|
||||
blankResp ResponseConstructor,
|
||||
|
@ -142,12 +143,11 @@ func (s *SignService) HandleServerStreamRequest(
|
|||
|
||||
var err error
|
||||
|
||||
// verify request signatures
|
||||
if err = signature.VerifyServiceMessage(req); err != nil {
|
||||
if err = verifyRequestSignature(ctx, req); err != nil {
|
||||
err = fmt.Errorf("could not verify request: %w", err)
|
||||
} else {
|
||||
err = respWriterCaller(func(resp ResponseMessage) error {
|
||||
if err := signResponse(s.key, resp, statusSupported); err != nil {
|
||||
if err := signResponse(ctx, s.key, resp, statusSupported); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ func (s *SignService) HandleServerStreamRequest(
|
|||
|
||||
setStatusV2(resp, err)
|
||||
|
||||
_ = signResponse(s.key, resp, false) // panics or returns nil with false arg
|
||||
_ = signResponse(ctx, s.key, resp, false) // panics or returns nil with false arg
|
||||
|
||||
return respWriter(resp)
|
||||
}
|
||||
|
@ -183,8 +183,7 @@ func (s *SignService) HandleUnaryRequest(ctx context.Context, req any, handler U
|
|||
err error
|
||||
)
|
||||
|
||||
// verify request signatures
|
||||
if err = signature.VerifyServiceMessage(req); err != nil {
|
||||
if err = verifyRequestSignature(ctx, req); err != nil {
|
||||
var sigErr apistatus.SignatureVerification
|
||||
sigErr.SetMessage(err.Error())
|
||||
|
||||
|
@ -205,7 +204,7 @@ func (s *SignService) HandleUnaryRequest(ctx context.Context, req any, handler U
|
|||
}
|
||||
|
||||
// sign the response
|
||||
if err = signResponse(s.key, resp, statusSupported); err != nil {
|
||||
if err = signResponse(ctx, s.key, resp, statusSupported); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -233,7 +232,10 @@ func setStatusV2(resp ResponseMessage, err error) {
|
|||
// The signature error affects the result depending on the protocol version:
|
||||
// - if status return is supported, panics since we cannot return the failed status, because it will not be signed;
|
||||
// - otherwise, returns error in order to transport it directly.
|
||||
func signResponse(key *ecdsa.PrivateKey, resp any, statusSupported bool) error {
|
||||
func signResponse(ctx context.Context, key *ecdsa.PrivateKey, resp any, statusSupported bool) error {
|
||||
_, span := tracing.StartSpanFromContext(ctx, "signResponse")
|
||||
defer span.End()
|
||||
|
||||
err := signature.SignServiceMessage(key, resp)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not sign response: %w", err)
|
||||
|
@ -247,3 +249,10 @@ func signResponse(key *ecdsa.PrivateKey, resp any, statusSupported bool) error {
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func verifyRequestSignature(ctx context.Context, req any) error {
|
||||
_, span := tracing.StartSpanFromContext(ctx, "verifyRequestSignature")
|
||||
defer span.End()
|
||||
|
||||
return signature.VerifyServiceMessage(req)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue