From 7abbdca0641f1526c347da60012f437be57254e8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 28 Aug 2024 13:56:45 +0300 Subject: [PATCH] [#1340] getSvc: Fix access denied error handling Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/get.go | 8 +++++++ pkg/services/object/get/remote.go | 7 +++++- pkg/services/object/get/v2/get_forwarder.go | 26 ++++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 07a2f3a7..03b7f8bf 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -2,9 +2,11 @@ package getsvc import ( "context" + "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) @@ -120,6 +122,12 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { exec.log.Debug(logs.OperationFinishedWithError, zap.Error(exec.err), ) + var errAccessDenied *apistatus.ObjectAccessDenied + if execCnr && errors.As(exec.err, &errAccessDenied) { + // Local get can't return access denied error, so this error was returned by + // write to the output stream. So there is no need to try to find object on other nodes. + return + } if execCnr { exec.executeOnContainer(ctx) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index ce9abfe1..163767c4 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -31,6 +31,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { var errECInfo *objectSDK.ECInfoError var errRemoved *apistatus.ObjectAlreadyRemoved var errOutOfRange *apistatus.ObjectOutOfRange + var errAccessDenied *apistatus.ObjectAccessDenied switch { default: @@ -38,7 +39,11 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { if r.status != statusEC { // for raw requests, continue to collect other parts r.status = statusUndefined - r.err = new(apistatus.ObjectNotFound) + if errors.As(err, &errAccessDenied) { + r.err = err + } else { + r.err = new(apistatus.ObjectNotFound) + } } return false case err == nil: diff --git a/pkg/services/object/get/v2/get_forwarder.go b/pkg/services/object/get/v2/get_forwarder.go index 774f9864..18194c74 100644 --- a/pkg/services/object/get/v2/get_forwarder.go +++ b/pkg/services/object/get/v2/get_forwarder.go @@ -23,12 +23,14 @@ import ( ) type getRequestForwarder struct { - OnceResign sync.Once - OnceHeaderSending sync.Once - GlobalProgress int - Key *ecdsa.PrivateKey - Request *objectV2.GetRequest - Stream *streamObjectWriter + OnceResign sync.Once + GlobalProgress int + Key *ecdsa.PrivateKey + Request *objectV2.GetRequest + Stream *streamObjectWriter + + headerSent bool + headerSentGuard sync.Mutex } func (f *getRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*objectSDK.Object, error) { @@ -83,13 +85,15 @@ func (f *getRequestForwarder) writeHeader(ctx context.Context, v *objectV2.GetOb obj.SetSignature(v.GetSignature()) obj.SetHeader(v.GetHeader()) - var err error - f.OnceHeaderSending.Do(func() { - err = f.Stream.WriteHeader(ctx, objectSDK.NewFromV2(obj)) - }) - if err != nil { + f.headerSentGuard.Lock() + defer f.headerSentGuard.Unlock() + if f.headerSent { + return nil + } + if err := f.Stream.WriteHeader(ctx, objectSDK.NewFromV2(obj)); err != nil { return errCouldNotWriteObjHeader(err) } + f.headerSent = true return nil }