From 882d010870ce4e8d4bd6accfa2905fe9d567115b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 14:00:01 +0300 Subject: [PATCH 01/16] [#6] services/object: Remove useless helpers We have lots of small _private_ methods on `execCtx` whose sole purpose is to just return a struct field. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/delete/exec.go | 32 ++-------- pkg/services/object/delete/local.go | 2 +- pkg/services/object/delete/util.go | 16 ++--- pkg/services/object/get/assemble.go | 30 ++++----- pkg/services/object/get/container.go | 8 +-- pkg/services/object/get/exec.go | 75 +++++------------------ pkg/services/object/get/get.go | 2 +- pkg/services/object/get/get_test.go | 8 +-- pkg/services/object/get/local.go | 4 +- pkg/services/object/get/remote.go | 4 +- pkg/services/object/get/util.go | 36 +++++------ pkg/services/object/search/container.go | 8 +-- pkg/services/object/search/exec.go | 31 +--------- pkg/services/object/search/search_test.go | 4 +- pkg/services/object/search/util.go | 10 +-- 15 files changed, 88 insertions(+), 182 deletions(-) diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index 4da4c8083..44fc358b2 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -5,9 +5,7 @@ import ( "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" @@ -45,37 +43,17 @@ const ( func (exec *execCtx) setLogger(l *logger.Logger) { exec.log = &logger.Logger{Logger: l.With( zap.String("request", "DELETE"), - zap.Stringer("address", exec.address()), - zap.Bool("local", exec.isLocal()), + zap.Stringer("address", exec.prm.addr), + zap.Bool("local", exec.prm.common.LocalOnly()), zap.Bool("with session", exec.prm.common.SessionToken() != nil), zap.Bool("with bearer", exec.prm.common.BearerToken() != nil), )} } -func (exec execCtx) context() context.Context { - return exec.ctx -} - -func (exec execCtx) isLocal() bool { - return exec.prm.common.LocalOnly() -} - -func (exec *execCtx) address() oid.Address { - return exec.prm.addr -} - -func (exec *execCtx) containerID() cid.ID { - return exec.prm.addr.Container() -} - -func (exec *execCtx) commonParameters() *util.CommonPrm { - return exec.prm.common -} - func (exec *execCtx) newAddress(id oid.ID) oid.Address { var a oid.Address a.SetObject(id) - a.SetContainer(exec.containerID()) + a.SetContainer(exec.prm.addr.Container()) return a } @@ -241,11 +219,11 @@ func (exec *execCtx) initTombstoneObject() bool { } exec.tombstoneObj = object.New() - exec.tombstoneObj.SetContainerID(exec.containerID()) + exec.tombstoneObj.SetContainerID(exec.prm.addr.Container()) exec.tombstoneObj.SetType(object.TypeTombstone) exec.tombstoneObj.SetPayload(payload) - tokenSession := exec.commonParameters().SessionToken() + tokenSession := exec.prm.common.SessionToken() if tokenSession != nil { issuer := tokenSession.Issuer() exec.tombstoneObj.SetOwnerID(&issuer) diff --git a/pkg/services/object/delete/local.go b/pkg/services/object/delete/local.go index 36af96448..97b49e101 100644 --- a/pkg/services/object/delete/local.go +++ b/pkg/services/object/delete/local.go @@ -36,7 +36,7 @@ func (exec *execCtx) formTombstone() (ok bool) { exec.tombstone.SetExpirationEpoch( exec.svc.netInfo.CurrentEpoch() + tsLifetime, ) - exec.addMembers([]oid.ID{exec.address().Object()}) + exec.addMembers([]oid.ID{exec.prm.addr.Object()}) exec.log.Debug("forming split info...") diff --git a/pkg/services/object/delete/util.go b/pkg/services/object/delete/util.go index a8ebb3065..905b182dd 100644 --- a/pkg/services/object/delete/util.go +++ b/pkg/services/object/delete/util.go @@ -24,12 +24,12 @@ func (w *headSvcWrapper) headAddress(exec *execCtx, addr oid.Address) (*object.O wr := getsvc.NewSimpleObjectWriter() p := getsvc.HeadPrm{} - p.SetCommonParameters(exec.commonParameters()) + p.SetCommonParameters(exec.prm.common) p.SetHeaderWriter(wr) p.WithRawFlag(true) p.WithAddress(addr) - err := (*getsvc.Service)(w).Head(exec.context(), p) + err := (*getsvc.Service)(w).Head(exec.ctx, p) if err != nil { return nil, err } @@ -38,7 +38,7 @@ func (w *headSvcWrapper) headAddress(exec *execCtx, addr oid.Address) (*object.O } func (w *headSvcWrapper) splitInfo(exec *execCtx) (*object.SplitInfo, error) { - _, err := w.headAddress(exec, exec.address()) + _, err := w.headAddress(exec, exec.prm.addr) var errSplitInfo *object.SplitInfoError @@ -89,11 +89,11 @@ func (w *searchSvcWrapper) splitMembers(exec *execCtx) ([]oid.ID, error) { p := searchsvc.Prm{} p.SetWriter(wr) - p.SetCommonParameters(exec.commonParameters()) - p.WithContainerID(exec.containerID()) + p.SetCommonParameters(exec.prm.common) + p.WithContainerID(exec.prm.addr.Container()) p.WithSearchFilters(fs) - err := (*searchsvc.Service)(w).Search(exec.context(), p) + err := (*searchsvc.Service)(w).Search(exec.ctx, p) if err != nil { return nil, err } @@ -108,7 +108,7 @@ func (s *simpleIDWriter) WriteIDs(ids []oid.ID) error { } func (w *putSvcWrapper) put(exec *execCtx) (*oid.ID, error) { - streamer, err := (*putsvc.Service)(w).Put(exec.context()) + streamer, err := (*putsvc.Service)(w).Put(exec.ctx) if err != nil { return nil, err } @@ -116,7 +116,7 @@ func (w *putSvcWrapper) put(exec *execCtx) (*oid.ID, error) { payload := exec.tombstoneObj.Payload() initPrm := new(putsvc.PutInitPrm). - WithCommonPrm(exec.commonParameters()). + WithCommonPrm(exec.prm.common). WithObject(exec.tombstoneObj.CutPayload()) err = streamer.Init(initPrm) diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index ebae18eb5..149469e2a 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -36,26 +36,26 @@ func (exec *execCtx) assemble() { exec.log.Debug("trying to assemble the object...") - assembler := newAssembler(exec.address(), exec.splitInfo(), exec.ctxRange(), exec) + assembler := newAssembler(exec.prm.addr, exec.splitInfo, exec.prm.rng, exec) exec.log.Debug("assembling splitted object...", - zap.Stringer("address", exec.address()), - zap.Uint64("range_offset", exec.ctxRange().GetOffset()), - zap.Uint64("range_length", exec.ctxRange().GetLength()), + zap.Stringer("address", exec.prm.addr), + zap.Uint64("range_offset", exec.prm.rng.GetOffset()), + zap.Uint64("range_length", exec.prm.rng.GetLength()), ) defer exec.log.Debug("assembling splitted object completed", - zap.Stringer("address", exec.address()), - zap.Uint64("range_offset", exec.ctxRange().GetOffset()), - zap.Uint64("range_length", exec.ctxRange().GetLength()), + zap.Stringer("address", exec.prm.addr), + zap.Uint64("range_offset", exec.prm.rng.GetOffset()), + zap.Uint64("range_length", exec.prm.rng.GetLength()), ) - obj, err := assembler.Assemble(exec.context(), exec.prm.objWriter) + obj, err := assembler.Assemble(exec.ctx, exec.prm.objWriter) if err != nil { exec.log.Warn("failed to assemble splitted object", zap.Error(err), - zap.Stringer("address", exec.address()), - zap.Uint64("range_offset", exec.ctxRange().GetOffset()), - zap.Uint64("range_length", exec.ctxRange().GetLength()), + zap.Stringer("address", exec.prm.addr), + zap.Uint64("range_offset", exec.prm.rng.GetOffset()), + zap.Uint64("range_length", exec.prm.rng.GetLength()), ) } @@ -98,7 +98,7 @@ func equalAddresses(a, b oid.Address) bool { func (exec *execCtx) HeadObject(ctx context.Context, id oid.ID) (*objectSDK.Object, error) { p := exec.prm p.common = p.common.WithLocalOnly(false) - p.addr.SetContainer(exec.containerID()) + p.addr.SetContainer(exec.prm.addr.Container()) p.addr.SetObject(id) prm := HeadPrm{ @@ -108,7 +108,7 @@ func (exec *execCtx) HeadObject(ctx context.Context, id oid.ID) (*objectSDK.Obje w := NewSimpleObjectWriter() prm.SetHeaderWriter(w) //nolint: contextcheck - err := exec.svc.Head(exec.context(), prm) + err := exec.svc.Head(exec.ctx, prm) if err != nil { return nil, err @@ -125,11 +125,11 @@ func (exec *execCtx) GetObject(ctx context.Context, id oid.ID, rng *objectSDK.Ra p.objWriter = w p.SetRange(rng) - p.addr.SetContainer(exec.containerID()) + p.addr.SetContainer(exec.prm.addr.Container()) p.addr.SetObject(id) //nolint: contextcheck - statusError := exec.svc.get(exec.context(), p.commonPrm, withPayloadRange(rng)) + statusError := exec.svc.get(exec.ctx, p.commonPrm, withPayloadRange(rng)) if statusError.err != nil { return nil, statusError.err diff --git a/pkg/services/object/get/container.go b/pkg/services/object/get/container.go index 882861129..85ade334b 100644 --- a/pkg/services/object/get/container.go +++ b/pkg/services/object/get/container.go @@ -8,12 +8,12 @@ import ( ) func (exec *execCtx) executeOnContainer() { - if exec.isLocal() { + if exec.prm.common.LocalOnly() { exec.log.Debug("return result directly") return } - lookupDepth := exec.netmapLookupDepth() + lookupDepth := exec.prm.common.NetmapLookupDepth() exec.log.Debug("trying to execute in container...", zap.Uint64("netmap lookup depth", lookupDepth), @@ -47,12 +47,12 @@ func (exec *execCtx) processCurrentEpoch() bool { zap.Uint64("number", exec.curProcEpoch), ) - traverser, ok := exec.generateTraverser(exec.address()) + traverser, ok := exec.generateTraverser(exec.prm.addr) if !ok { return true } - ctx, cancel := context.WithCancel(exec.context()) + ctx, cancel := context.WithCancel(exec.ctx) defer cancel() exec.status = statusUndefined diff --git a/pkg/services/object/get/exec.go b/pkg/services/object/get/exec.go index 9858b32b2..2f4d98aca 100644 --- a/pkg/services/object/get/exec.go +++ b/pkg/services/object/get/exec.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - 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.uber.org/zap" @@ -29,13 +28,13 @@ type execCtx struct { statusError - infoSplit *objectSDK.SplitInfo + splitInfo *objectSDK.SplitInfo log *logger.Logger collectedObject *objectSDK.Object - head bool + headOnly bool curProcEpoch uint64 } @@ -52,7 +51,7 @@ const ( func headOnly() execOption { return func(c *execCtx) { - c.head = true + c.headOnly = true } } @@ -64,38 +63,22 @@ func withPayloadRange(r *objectSDK.Range) execOption { func (exec *execCtx) setLogger(l *logger.Logger) { req := "GET" - if exec.headOnly() { + if exec.headOnly { req = "HEAD" - } else if exec.ctxRange() != nil { + } else if exec.prm.rng != nil { req = "GET_RANGE" } exec.log = &logger.Logger{Logger: l.With( zap.String("request", req), - zap.Stringer("address", exec.address()), - zap.Bool("raw", exec.isRaw()), - zap.Bool("local", exec.isLocal()), + zap.Stringer("address", exec.prm.addr), + zap.Bool("raw", exec.prm.raw), + zap.Bool("local", exec.prm.common.LocalOnly()), zap.Bool("with session", exec.prm.common.SessionToken() != nil), zap.Bool("with bearer", exec.prm.common.BearerToken() != nil), )} } -func (exec execCtx) context() context.Context { - return exec.ctx -} - -func (exec execCtx) isLocal() bool { - return exec.prm.common.LocalOnly() -} - -func (exec execCtx) isRaw() bool { - return exec.prm.raw -} - -func (exec execCtx) address() oid.Address { - return exec.prm.addr -} - func (exec execCtx) key() (*ecdsa.PrivateKey, error) { if exec.prm.signerKey != nil { // the key has already been requested and @@ -116,35 +99,11 @@ func (exec execCtx) key() (*ecdsa.PrivateKey, error) { } func (exec *execCtx) canAssemble() bool { - return !exec.isRaw() && !exec.headOnly() -} - -func (exec *execCtx) splitInfo() *objectSDK.SplitInfo { - return exec.infoSplit -} - -func (exec *execCtx) containerID() cid.ID { - return exec.address().Container() -} - -func (exec *execCtx) ctxRange() *objectSDK.Range { - return exec.prm.rng -} - -func (exec *execCtx) headOnly() bool { - return exec.head -} - -func (exec *execCtx) netmapEpoch() uint64 { - return exec.prm.common.NetmapEpoch() -} - -func (exec *execCtx) netmapLookupDepth() uint64 { - return exec.prm.common.NetmapLookupDepth() + return !exec.prm.raw && !exec.headOnly } func (exec *execCtx) initEpoch() bool { - exec.curProcEpoch = exec.netmapEpoch() + exec.curProcEpoch = exec.prm.common.NetmapEpoch() if exec.curProcEpoch > 0 { return true } @@ -218,12 +177,12 @@ func mergeSplitInfo(dst, src *objectSDK.SplitInfo) { } func (exec *execCtx) writeCollectedHeader() bool { - if exec.ctxRange() != nil { + if exec.prm.rng != nil { return true } err := exec.prm.objWriter.WriteHeader( - exec.context(), + exec.ctx, exec.collectedObject.CutPayload(), ) @@ -244,11 +203,11 @@ func (exec *execCtx) writeCollectedHeader() bool { } func (exec *execCtx) writeObjectPayload(obj *objectSDK.Object) bool { - if exec.headOnly() { + if exec.headOnly { return true } - err := exec.prm.objWriter.WriteChunk(exec.context(), obj.Payload()) + err := exec.prm.objWriter.WriteChunk(exec.ctx, obj.Payload()) switch { default: @@ -272,12 +231,6 @@ func (exec *execCtx) writeCollectedObject() { } } -// isForwardingEnabled returns true if common execution -// parameters has request forwarding closure set. -func (exec execCtx) isForwardingEnabled() bool { - return exec.prm.forwarder != nil -} - // disableForwarding removes request forwarding closure from common // parameters, so it won't be inherited in new execution contexts. func (exec *execCtx) disableForwarding() { diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index cdb2d96fd..2502a93ca 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -69,7 +69,7 @@ func (s *Service) get(ctx context.Context, prm commonPrm, opts ...execOption) st prm: RangePrm{ commonPrm: prm, }, - infoSplit: object.NewSplitInfo(), + splitInfo: object.NewSplitInfo(), } for i := range opts { diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 09d0c38fa..b860491d8 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -118,7 +118,7 @@ func newTestClient() *testClient { } func (c *testClient) getObject(exec *execCtx, _ client.NodeInfo) (*objectSDK.Object, error) { - v, ok := c.results[exec.address().EncodeToString()] + v, ok := c.results[exec.prm.addr.EncodeToString()] if !ok { var errNotFound apistatus.ObjectNotFound @@ -129,7 +129,7 @@ func (c *testClient) getObject(exec *execCtx, _ client.NodeInfo) (*objectSDK.Obj return nil, v.err } - return cutToRange(v.obj, exec.ctxRange()), nil + return cutToRange(v.obj, exec.prm.rng), nil } func (c *testClient) addResult(addr oid.Address, obj *objectSDK.Object, err error) { @@ -143,7 +143,7 @@ func (s *testStorage) get(exec *execCtx) (*objectSDK.Object, error) { var ( ok bool obj *objectSDK.Object - sAddr = exec.address().EncodeToString() + sAddr = exec.prm.addr.EncodeToString() ) if _, ok = s.inhumed[sAddr]; ok { @@ -157,7 +157,7 @@ func (s *testStorage) get(exec *execCtx) (*objectSDK.Object, error) { } if obj, ok = s.phy[sAddr]; ok { - return cutToRange(obj, exec.ctxRange()), nil + return cutToRange(obj, exec.prm.rng), nil } var errNotFound apistatus.ObjectNotFound diff --git a/pkg/services/object/get/local.go b/pkg/services/object/get/local.go index f526af4e6..75de59a5c 100644 --- a/pkg/services/object/get/local.go +++ b/pkg/services/object/get/local.go @@ -34,8 +34,8 @@ func (exec *execCtx) executeLocal() { exec.err = errRemoved case errors.As(err, &errSplitInfo): exec.status = statusVIRTUAL - mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo()) - exec.err = objectSDK.NewSplitInfoError(exec.infoSplit) + mergeSplitInfo(exec.splitInfo, errSplitInfo.SplitInfo()) + exec.err = objectSDK.NewSplitInfoError(exec.splitInfo) case errors.As(err, &errOutOfRange): exec.status = statusOutOfRange exec.err = errOutOfRange diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index fbfb01bcd..946cc8d84 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -54,8 +54,8 @@ func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool exec.err = errOutOfRange case errors.As(err, &errSplitInfo): exec.status = statusVIRTUAL - mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo()) - exec.err = objectSDK.NewSplitInfoError(exec.infoSplit) + mergeSplitInfo(exec.splitInfo, errSplitInfo.SplitInfo()) + exec.err = objectSDK.NewSplitInfoError(exec.splitInfo) } return exec.status != statusUndefined diff --git a/pkg/services/object/get/util.go b/pkg/services/object/get/util.go index d647b07f6..7dfc6e662 100644 --- a/pkg/services/object/get/util.go +++ b/pkg/services/object/get/util.go @@ -89,7 +89,7 @@ func (c *clientCacheWrapper) get(info coreclient.NodeInfo) (getClient, error) { // nolint: funlen func (c *clientWrapper) getObject(exec *execCtx, info coreclient.NodeInfo) (*object.Object, error) { - if exec.isForwardingEnabled() { + if exec.prm.forwarder != nil { return exec.prm.forwarder(info, c.client) } @@ -98,20 +98,20 @@ func (c *clientWrapper) getObject(exec *execCtx, info coreclient.NodeInfo) (*obj return nil, err } - if exec.headOnly() { + if exec.headOnly { var prm internalclient.HeadObjectPrm - prm.SetContext(exec.context()) + prm.SetContext(exec.ctx) prm.SetClient(c.client) prm.SetTTL(exec.prm.common.TTL()) prm.SetNetmapEpoch(exec.curProcEpoch) - prm.SetAddress(exec.address()) + prm.SetAddress(exec.prm.addr) prm.SetPrivateKey(key) prm.SetSessionToken(exec.prm.common.SessionToken()) prm.SetBearerToken(exec.prm.common.BearerToken()) prm.SetXHeaders(exec.prm.common.XHeaders()) - if exec.isRaw() { + if exec.prm.raw { prm.SetRawFlag() } @@ -124,21 +124,21 @@ func (c *clientWrapper) getObject(exec *execCtx, info coreclient.NodeInfo) (*obj } // we don't specify payload writer because we accumulate // the object locally (even huge). - if rng := exec.ctxRange(); rng != nil { + if rng := exec.prm.rng; rng != nil { var prm internalclient.PayloadRangePrm - prm.SetContext(exec.context()) + prm.SetContext(exec.ctx) prm.SetClient(c.client) prm.SetTTL(exec.prm.common.TTL()) prm.SetNetmapEpoch(exec.curProcEpoch) - prm.SetAddress(exec.address()) + prm.SetAddress(exec.prm.addr) prm.SetPrivateKey(key) prm.SetSessionToken(exec.prm.common.SessionToken()) prm.SetBearerToken(exec.prm.common.BearerToken()) prm.SetXHeaders(exec.prm.common.XHeaders()) prm.SetRange(rng) - if exec.isRaw() { + if exec.prm.raw { prm.SetRawFlag() } @@ -175,17 +175,17 @@ func (c *clientWrapper) getObject(exec *execCtx, info coreclient.NodeInfo) (*obj func (c *clientWrapper) get(exec *execCtx, key *ecdsa.PrivateKey) (*object.Object, error) { var prm internalclient.GetObjectPrm - prm.SetContext(exec.context()) + prm.SetContext(exec.ctx) prm.SetClient(c.client) prm.SetTTL(exec.prm.common.TTL()) prm.SetNetmapEpoch(exec.curProcEpoch) - prm.SetAddress(exec.address()) + prm.SetAddress(exec.prm.addr) prm.SetPrivateKey(key) prm.SetSessionToken(exec.prm.common.SessionToken()) prm.SetBearerToken(exec.prm.common.BearerToken()) prm.SetXHeaders(exec.prm.common.XHeaders()) - if exec.isRaw() { + if exec.prm.raw { prm.SetRawFlag() } @@ -198,10 +198,10 @@ func (c *clientWrapper) get(exec *execCtx, key *ecdsa.PrivateKey) (*object.Objec } func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { - if exec.headOnly() { + if exec.headOnly { var headPrm engine.HeadPrm - headPrm.WithAddress(exec.address()) - headPrm.WithRaw(exec.isRaw()) + headPrm.WithAddress(exec.prm.addr) + headPrm.WithRaw(exec.prm.raw) r, err := e.engine.Head(headPrm) if err != nil { @@ -209,9 +209,9 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { } return r.Header(), nil - } else if rng := exec.ctxRange(); rng != nil { + } else if rng := exec.prm.rng; rng != nil { var getRange engine.RngPrm - getRange.WithAddress(exec.address()) + getRange.WithAddress(exec.prm.addr) getRange.WithPayloadRange(rng) r, err := e.engine.GetRange(getRange) @@ -222,7 +222,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { return r.Object(), nil } else { var getPrm engine.GetPrm - getPrm.WithAddress(exec.address()) + getPrm.WithAddress(exec.prm.addr) r, err := e.engine.Get(getPrm) if err != nil { diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index fffcba42a..ee59fffc7 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -10,12 +10,12 @@ import ( ) func (exec *execCtx) executeOnContainer() { - if exec.isLocal() { + if exec.prm.common.LocalOnly() { exec.log.Debug("return result directly") return } - lookupDepth := exec.netmapLookupDepth() + lookupDepth := exec.prm.common.NetmapLookupDepth() exec.log.Debug("trying to execute in container...", zap.Uint64("netmap lookup depth", lookupDepth), @@ -52,12 +52,12 @@ func (exec *execCtx) processCurrentEpoch() bool { zap.Uint64("number", exec.curProcEpoch), ) - traverser, ok := exec.generateTraverser(exec.containerID()) + traverser, ok := exec.generateTraverser(exec.prm.cnr) if !ok { return true } - ctx, cancel := context.WithCancel(exec.context()) + ctx, cancel := context.WithCancel(exec.ctx) defer cancel() for { diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index a1737b521..22d049e79 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) @@ -45,39 +44,15 @@ func (exec *execCtx) prepare() { func (exec *execCtx) setLogger(l *logger.Logger) { exec.log = &logger.Logger{Logger: l.With( zap.String("request", "SEARCH"), - zap.Stringer("container", exec.containerID()), - zap.Bool("local", exec.isLocal()), + zap.Stringer("container", exec.prm.cnr), + zap.Bool("local", exec.prm.common.LocalOnly()), zap.Bool("with session", exec.prm.common.SessionToken() != nil), zap.Bool("with bearer", exec.prm.common.BearerToken() != nil), )} } -func (exec execCtx) context() context.Context { - return exec.ctx -} - -func (exec execCtx) isLocal() bool { - return exec.prm.common.LocalOnly() -} - -func (exec *execCtx) containerID() cid.ID { - return exec.prm.cnr -} - -func (exec *execCtx) searchFilters() object.SearchFilters { - return exec.prm.filters -} - -func (exec *execCtx) netmapEpoch() uint64 { - return exec.prm.common.NetmapEpoch() -} - -func (exec *execCtx) netmapLookupDepth() uint64 { - return exec.prm.common.NetmapLookupDepth() -} - func (exec *execCtx) initEpoch() bool { - exec.curProcEpoch = exec.netmapEpoch() + exec.curProcEpoch = exec.prm.common.NetmapEpoch() if exec.curProcEpoch > 0 { return true } diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index bb3d422b3..a9c6d219d 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -103,7 +103,7 @@ func (c *testClientCache) get(info clientcore.NodeInfo) (searchClient, error) { } func (s *testStorage) search(exec *execCtx) ([]oid.ID, error) { - v, ok := s.items[exec.containerID().EncodeToString()] + v, ok := s.items[exec.prm.cnr.EncodeToString()] if !ok { return nil, nil } @@ -112,7 +112,7 @@ func (s *testStorage) search(exec *execCtx) ([]oid.ID, error) { } func (c *testStorage) searchObjects(exec *execCtx, _ clientcore.NodeInfo) ([]oid.ID, error) { - v, ok := c.items[exec.containerID().EncodeToString()] + v, ok := c.items[exec.prm.cnr.EncodeToString()] if !ok { return nil, nil } diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 741a224af..9477cb428 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -98,7 +98,7 @@ func (c *clientWrapper) searchObjects(exec *execCtx, info client.NodeInfo) ([]oi var prm internalclient.SearchObjectsPrm - prm.SetContext(exec.context()) + prm.SetContext(exec.ctx) prm.SetClient(c.client) prm.SetPrivateKey(key) prm.SetSessionToken(exec.prm.common.SessionToken()) @@ -106,8 +106,8 @@ func (c *clientWrapper) searchObjects(exec *execCtx, info client.NodeInfo) ([]oi prm.SetTTL(exec.prm.common.TTL()) prm.SetXHeaders(exec.prm.common.XHeaders()) prm.SetNetmapEpoch(exec.curProcEpoch) - prm.SetContainerID(exec.containerID()) - prm.SetFilters(exec.searchFilters()) + prm.SetContainerID(exec.prm.cnr) + prm.SetFilters(exec.prm.filters) res, err := internalclient.SearchObjects(prm) if err != nil { @@ -119,8 +119,8 @@ func (c *clientWrapper) searchObjects(exec *execCtx, info client.NodeInfo) ([]oi func (e *storageEngineWrapper) search(exec *execCtx) ([]oid.ID, error) { var selectPrm engine.SelectPrm - selectPrm.WithFilters(exec.searchFilters()) - selectPrm.WithContainerID(exec.containerID()) + selectPrm.WithFilters(exec.prm.filters) + selectPrm.WithContainerID(exec.prm.cnr) r, err := e.storage.Select(selectPrm) if err != nil { -- 2.45.3 From 9fbcc0e43cac2d62486698399c231a9996cbb23f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 14:06:47 +0300 Subject: [PATCH 02/16] [#6] services/object: Remove `nmSrc` wrapper It calls a single method from source without any processing. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/exec.go | 2 +- pkg/services/object/get/get_test.go | 6 +++--- pkg/services/object/get/service.go | 12 ++++++------ pkg/services/object/get/util.go | 9 --------- pkg/services/object/search/exec.go | 2 +- pkg/services/object/search/search_test.go | 6 +++--- pkg/services/object/search/service.go | 12 ++++++------ pkg/services/object/search/util.go | 9 --------- 8 files changed, 20 insertions(+), 38 deletions(-) diff --git a/pkg/services/object/get/exec.go b/pkg/services/object/get/exec.go index 2f4d98aca..d8347e812 100644 --- a/pkg/services/object/get/exec.go +++ b/pkg/services/object/get/exec.go @@ -108,7 +108,7 @@ func (exec *execCtx) initEpoch() bool { return true } - e, err := exec.svc.currentEpochReceiver.currentEpoch() + e, err := exec.svc.epochSource.Epoch() switch { default: diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index b860491d8..f6645bbd5 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -56,7 +56,7 @@ type testClient struct { type testEpochReceiver uint64 -func (e testEpochReceiver) currentEpoch() (uint64, error) { +func (e testEpochReceiver) Epoch() (uint64, error) { return uint64(e), nil } @@ -519,7 +519,7 @@ func TestGetRemoteSmall(t *testing.T) { }, } svc.clientCache = c - svc.currentEpochReceiver = testEpochReceiver(curEpoch) + svc.epochSource = testEpochReceiver(curEpoch) return svc } @@ -1670,7 +1670,7 @@ func TestGetFromPastEpoch(t *testing.T) { }, } - svc.currentEpochReceiver = testEpochReceiver(curEpoch) + svc.epochSource = testEpochReceiver(curEpoch) w := NewSimpleObjectWriter() diff --git a/pkg/services/object/get/service.go b/pkg/services/object/get/service.go index e69ab4f0f..fe4ba4c23 100644 --- a/pkg/services/object/get/service.go +++ b/pkg/services/object/get/service.go @@ -40,13 +40,15 @@ type cfg struct { GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, error) } - currentEpochReceiver interface { - currentEpoch() (uint64, error) - } + epochSource epochSource keyStore *util.KeyStorage } +type epochSource interface { + Epoch() (uint64, error) +} + func defaultCfg() *cfg { return &cfg{ log: &logger.Logger{Logger: zap.L()}, @@ -107,9 +109,7 @@ func WithTraverserGenerator(t *util.TraverserGenerator) Option { // map storage to receive current network state. func WithNetMapSource(nmSrc netmap.Source) Option { return func(c *cfg) { - c.currentEpochReceiver = &nmSrcWrapper{ - nmSrc: nmSrc, - } + c.epochSource = nmSrc } } diff --git a/pkg/services/object/get/util.go b/pkg/services/object/get/util.go index 7dfc6e662..c51fc678f 100644 --- a/pkg/services/object/get/util.go +++ b/pkg/services/object/get/util.go @@ -7,7 +7,6 @@ import ( "io" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internal "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" @@ -45,10 +44,6 @@ type hasherWrapper struct { hash io.Writer } -type nmSrcWrapper struct { - nmSrc netmap.Source -} - func NewSimpleObjectWriter() *SimpleObjectWriter { return &SimpleObjectWriter{ obj: object.New(), @@ -252,7 +247,3 @@ func (h *hasherWrapper) WriteChunk(_ context.Context, p []byte) error { _, err := h.hash.Write(p) return err } - -func (n *nmSrcWrapper) currentEpoch() (uint64, error) { - return n.nmSrc.Epoch() -} diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index 22d049e79..dd18b8f3e 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -57,7 +57,7 @@ func (exec *execCtx) initEpoch() bool { return true } - e, err := exec.svc.currentEpochReceiver.currentEpoch() + e, err := exec.svc.epochSource.Epoch() switch { default: diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index a9c6d219d..25e5838c5 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -51,7 +51,7 @@ type simpleIDWriter struct { type testEpochReceiver uint64 -func (e testEpochReceiver) currentEpoch() (uint64, error) { +func (e testEpochReceiver) Epoch() (uint64, error) { return uint64(e), nil } @@ -261,7 +261,7 @@ func TestGetRemoteSmall(t *testing.T) { }, } svc.clientConstructor = c - svc.currentEpochReceiver = testEpochReceiver(curEpoch) + svc.epochSource = testEpochReceiver(curEpoch) return svc } @@ -388,7 +388,7 @@ func TestGetFromPastEpoch(t *testing.T) { }, } - svc.currentEpochReceiver = testEpochReceiver(curEpoch) + svc.epochSource = testEpochReceiver(curEpoch) w := new(simpleIDWriter) diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index aebcfca0f..09b277b27 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -46,13 +46,15 @@ type cfg struct { generateTraverser(cid.ID, uint64) (*placement.Traverser, error) } - currentEpochReceiver interface { - currentEpoch() (uint64, error) - } + epochSource epochSource keyStore *util.KeyStorage } +type epochSource interface { + Epoch() (uint64, error) +} + func defaultCfg() *cfg { return &cfg{ log: &logger.Logger{Logger: zap.L()}, @@ -110,9 +112,7 @@ func WithTraverserGenerator(t *util.TraverserGenerator) Option { // map storage to receive current network state. func WithNetMapSource(nmSrc netmap.Source) Option { return func(c *cfg) { - c.currentEpochReceiver = &nmSrcWrapper{ - nmSrc: nmSrc, - } + c.epochSource = nmSrc } } diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 9477cb428..ffaf00793 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -4,7 +4,6 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -35,10 +34,6 @@ type storageEngineWrapper struct { type traverseGeneratorWrapper util.TraverserGenerator -type nmSrcWrapper struct { - nmSrc netmap.Source -} - func newUniqueAddressWriter(w IDListWriter) IDListWriter { return &uniqueIDWriter{ written: make(map[oid.ID]struct{}), @@ -143,7 +138,3 @@ func idsFromAddresses(addrs []oid.Address) []oid.ID { func (e *traverseGeneratorWrapper) generateTraverser(cnr cid.ID, epoch uint64) (*placement.Traverser, error) { return (*util.TraverserGenerator)(e).GenerateTraverser(cnr, nil, epoch) } - -func (n *nmSrcWrapper) currentEpoch() (uint64, error) { - return n.nmSrc.Epoch() -} -- 2.45.3 From c1cd32ecca4db7201970a96c17d83c6bb8ec19c5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Jan 2023 13:41:05 +0300 Subject: [PATCH 03/16] [#6] eacl/v2: Rename `cfg` receiver Signed-off-by: Evgenii Stratonikov --- pkg/services/object/acl/eacl/v2/headers.go | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 63e733cf6..ae3bc8568 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -102,20 +102,20 @@ func requestHeaders(msg xHeaderSource) []eaclSDK.Header { var errMissingOID = errors.New("object ID is missing") // nolint: funlen -func (h *cfg) readObjectHeaders(dst *headerSource) error { - switch m := h.msg.(type) { +func (c *cfg) readObjectHeaders(dst *headerSource) error { + switch m := c.msg.(type) { default: - panic(fmt.Sprintf("unexpected message type %T", h.msg)) + panic(fmt.Sprintf("unexpected message type %T", c.msg)) case requestXHeaderSource: switch req := m.req.(type) { case *objectV2.GetRequest, *objectV2.HeadRequest: - if h.obj == nil { + if c.obj == nil { return errMissingOID } - objHeaders, completed := h.localObjectHeaders(h.cnr, h.obj) + objHeaders, completed := c.localObjectHeaders(c.cnr, c.obj) dst.objectHeaders = objHeaders dst.incompleteObjectHeaders = !completed @@ -123,18 +123,18 @@ func (h *cfg) readObjectHeaders(dst *headerSource) error { *objectV2.GetRangeRequest, *objectV2.GetRangeHashRequest, *objectV2.DeleteRequest: - if h.obj == nil { + if c.obj == nil { return errMissingOID } - dst.objectHeaders = addressHeaders(h.cnr, h.obj) + dst.objectHeaders = addressHeaders(c.cnr, c.obj) case *objectV2.PutRequest: if v, ok := req.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { oV2 := new(objectV2.Object) oV2.SetObjectID(v.GetObjectID()) oV2.SetHeader(v.GetHeader()) - dst.objectHeaders = headersFromObject(object.NewFromV2(oV2), h.cnr, h.obj) + dst.objectHeaders = headersFromObject(object.NewFromV2(oV2), c.cnr, c.obj) } case *objectV2.SearchRequest: cnrV2 := req.GetBody().GetContainerID() @@ -151,7 +151,7 @@ func (h *cfg) readObjectHeaders(dst *headerSource) error { case responseXHeaderSource: switch resp := m.resp.(type) { default: - objectHeaders, completed := h.localObjectHeaders(h.cnr, h.obj) + objectHeaders, completed := c.localObjectHeaders(c.cnr, c.obj) dst.objectHeaders = objectHeaders dst.incompleteObjectHeaders = !completed @@ -161,7 +161,7 @@ func (h *cfg) readObjectHeaders(dst *headerSource) error { oV2.SetObjectID(v.GetObjectID()) oV2.SetHeader(v.GetHeader()) - dst.objectHeaders = headersFromObject(object.NewFromV2(oV2), h.cnr, h.obj) + dst.objectHeaders = headersFromObject(object.NewFromV2(oV2), c.cnr, c.obj) } case *objectV2.HeadResponse: oV2 := new(objectV2.Object) @@ -173,7 +173,7 @@ func (h *cfg) readObjectHeaders(dst *headerSource) error { hdr = new(objectV2.Header) var idV2 refsV2.ContainerID - h.cnr.WriteToV2(&idV2) + c.cnr.WriteToV2(&idV2) hdr.SetContainerID(&idV2) hdr.SetVersion(v.GetVersion()) @@ -187,20 +187,20 @@ func (h *cfg) readObjectHeaders(dst *headerSource) error { oV2.SetHeader(hdr) - dst.objectHeaders = headersFromObject(object.NewFromV2(oV2), h.cnr, h.obj) + dst.objectHeaders = headersFromObject(object.NewFromV2(oV2), c.cnr, c.obj) } } return nil } -func (h *cfg) localObjectHeaders(cnr cid.ID, idObj *oid.ID) ([]eaclSDK.Header, bool) { +func (c *cfg) localObjectHeaders(cnr cid.ID, idObj *oid.ID) ([]eaclSDK.Header, bool) { if idObj != nil { var addr oid.Address addr.SetContainer(cnr) addr.SetObject(*idObj) - obj, err := h.storage.Head(addr) + obj, err := c.storage.Head(addr) if err == nil { return headersFromObject(obj, cnr, idObj), true } -- 2.45.3 From 9ca20ad80fbb511b9be38c8e5135a824c89b12b8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 14:19:42 +0300 Subject: [PATCH 04/16] [#6] services/object: Remove pointer unneeded indirections All `Service` are accessed by pointer. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/acl/eacl/v2/headers.go | 17 +++++----- pkg/services/object/acl/v2/service.go | 37 ++++++++++------------ pkg/services/object/delete/service.go | 17 ++++------ pkg/services/object/delete/v2/service.go | 10 +++--- pkg/services/object/get/get_test.go | 6 ++-- pkg/services/object/get/service.go | 21 ++++++------ pkg/services/object/get/v2/service.go | 10 +++--- pkg/services/object/put/service.go | 25 +++++++-------- pkg/services/object/put/v2/service.go | 10 +++--- pkg/services/object/search/search_test.go | 6 ++-- pkg/services/object/search/service.go | 19 +++++------ pkg/services/object/search/v2/service.go | 10 +++--- 12 files changed, 82 insertions(+), 106 deletions(-) diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index ae3bc8568..3d09e84b0 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -45,31 +45,30 @@ type headerSource struct { incompleteObjectHeaders bool } -func defaultCfg() *cfg { - return &cfg{ - storage: new(localStorage), - } +func (c *cfg) initDefault() { + c.storage = new(localStorage) } func NewMessageHeaderSource(opts ...Option) (eaclSDK.TypedHeaderSource, error) { - cfg := defaultCfg() + var c cfg + c.initDefault() for i := range opts { - opts[i](cfg) + opts[i](&c) } - if cfg.msg == nil { + if c.msg == nil { return nil, errors.New("message is not provided") } var res headerSource - err := cfg.readObjectHeaders(&res) + err := c.readObjectHeaders(&res) if err != nil { return nil, err } - res.requestHeaders = requestHeaders(cfg.msg) + res.requestHeaders = requestHeaders(c.msg) return res, nil } diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 6bf8c4405..93acec224 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -21,7 +21,7 @@ import ( // Service checks basic ACL rules. type Service struct { - *cfg + cfg c senderClassifier } @@ -72,18 +72,17 @@ type cfg struct { next object.ServiceServer } -func defaultCfg() *cfg { - return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - } +func (c *cfg) initDefault() { + c.log = &logger.Logger{Logger: zap.L()} } // New is a constructor for object ACL checking service. -func New(opts ...Option) Service { - cfg := defaultCfg() +func New(opts ...Option) *Service { + var s Service + s.cfg.initDefault() for i := range opts { - opts[i](cfg) + opts[i](&s.cfg) } panicOnNil := func(v any, name string) { @@ -92,20 +91,18 @@ func New(opts ...Option) Service { } } - panicOnNil(cfg.next, "next Service") - panicOnNil(cfg.nm, "netmap client") - panicOnNil(cfg.irFetcher, "inner Ring fetcher") - panicOnNil(cfg.checker, "acl checker") - panicOnNil(cfg.containers, "container source") + panicOnNil(s.cfg.next, "next Service") + panicOnNil(s.cfg.nm, "netmap client") + panicOnNil(s.cfg.irFetcher, "inner Ring fetcher") + panicOnNil(s.cfg.checker, "acl checker") + panicOnNil(s.cfg.containers, "container source") - return Service{ - cfg: cfg, - c: senderClassifier{ - log: cfg.log, - innerRing: cfg.irFetcher, - netmap: cfg.nm, - }, + s.c = senderClassifier{ + log: s.cfg.log, + innerRing: s.cfg.irFetcher, + netmap: s.cfg.nm, } + return &s } // Get implements ServiceServer interface, makes ACL checks and calls diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index f2ea384de..6e490ce78 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -15,7 +15,7 @@ import ( // Service utility serving requests of Object.Get service. type Service struct { - *cfg + cfg } // Option is a Service's constructor option. @@ -60,24 +60,21 @@ type cfg struct { keyStorage *util.KeyStorage } -func defaultCfg() *cfg { - return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - } +func (c *cfg) initDefault() { + c.log = &logger.Logger{Logger: zap.L()} } // New creates, initializes and returns utility serving // Object.Get service requests. func New(opts ...Option) *Service { - c := defaultCfg() + var s Service + s.cfg.initDefault() for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // WithLogger returns option to specify Delete service's logger. diff --git a/pkg/services/object/delete/v2/service.go b/pkg/services/object/delete/v2/service.go index 51759c5df..bbb119f89 100644 --- a/pkg/services/object/delete/v2/service.go +++ b/pkg/services/object/delete/v2/service.go @@ -9,7 +9,7 @@ import ( // Service implements Delete operation of Object service v2. type Service struct { - *cfg + cfg } // Option represents Service constructor option. @@ -21,15 +21,13 @@ type cfg struct { // NewService constructs Service instance from provided options. func NewService(opts ...Option) *Service { - c := new(cfg) + var s Service for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // Delete calls internal service. diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index f6645bbd5..531dde58b 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -245,7 +245,7 @@ func TestGetLocalOnly(t *testing.T) { ctx := context.Background() newSvc := func(storage *testStorage) *Service { - svc := &Service{cfg: new(cfg)} + svc := &Service{} svc.log = test.NewLogger(false) svc.localStorage = storage @@ -506,7 +506,7 @@ func TestGetRemoteSmall(t *testing.T) { container.CalculateID(&idCnr, cnr) newSvc := func(b *testPlacementBuilder, c *testClientCache) *Service { - svc := &Service{cfg: new(cfg)} + svc := &Service{} svc.log = test.NewLogger(false) svc.localStorage = newTestStorage() @@ -1639,7 +1639,7 @@ func TestGetFromPastEpoch(t *testing.T) { c22 := newTestClient() c22.addResult(addr, obj, nil) - svc := &Service{cfg: new(cfg)} + svc := &Service{} svc.log = test.NewLogger(false) svc.localStorage = newTestStorage() diff --git a/pkg/services/object/get/service.go b/pkg/services/object/get/service.go index fe4ba4c23..b52c16384 100644 --- a/pkg/services/object/get/service.go +++ b/pkg/services/object/get/service.go @@ -15,7 +15,7 @@ import ( // Service utility serving requests of Object.Get service. type Service struct { - *cfg + cfg } // Option is a Service's constructor option. @@ -49,26 +49,23 @@ type epochSource interface { Epoch() (uint64, error) } -func defaultCfg() *cfg { - return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - localStorage: new(storageEngineWrapper), - clientCache: new(clientCacheWrapper), - } +func (c *cfg) initDefault() { + c.log = &logger.Logger{Logger: zap.L()} + c.localStorage = new(storageEngineWrapper) + c.clientCache = new(clientCacheWrapper) } // New creates, initializes and returns utility serving // Object.Get service requests. func New(opts ...Option) *Service { - c := defaultCfg() + var s Service + s.cfg.initDefault() for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // WithLogger returns option to specify Get service's logger. diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index 3fd8cd04a..771576818 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -13,7 +13,7 @@ import ( // Service implements Get operation of Object service v2. type Service struct { - *cfg + cfg } // Option represents Service constructor option. @@ -27,15 +27,13 @@ type cfg struct { // NewService constructs Service instance from provided options. func NewService(opts ...Option) *Service { - c := new(cfg) + var s Service for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // Get calls internal service and returns v2 object stream. diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index b74c97d49..cfc20ca28 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -22,7 +22,7 @@ type MaxSizeSource interface { } type Service struct { - *cfg + cfg } type Option func(*cfg) @@ -57,31 +57,28 @@ type cfg struct { log *logger.Logger } -func defaultCfg() *cfg { - return &cfg{ - remotePool: util.NewPseudoWorkerPool(), - localPool: util.NewPseudoWorkerPool(), - log: &logger.Logger{Logger: zap.L()}, - } +func (c *cfg) initDefault() { + c.remotePool = util.NewPseudoWorkerPool() + c.localPool = util.NewPseudoWorkerPool() + c.log = &logger.Logger{Logger: zap.L()} } func NewService(opts ...Option) *Service { - c := defaultCfg() + var s Service + s.cfg.initDefault() for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - c.fmtValidator = object.NewFormatValidator(c.fmtValidatorOpts...) + s.cfg.fmtValidator = object.NewFormatValidator(s.cfg.fmtValidatorOpts...) - return &Service{ - cfg: c, - } + return &s } func (p *Service) Put(ctx context.Context) (*Streamer, error) { return &Streamer{ - cfg: p.cfg, + cfg: &p.cfg, ctx: ctx, }, nil } diff --git a/pkg/services/object/put/v2/service.go b/pkg/services/object/put/v2/service.go index 7d0dfc613..254c9b99a 100644 --- a/pkg/services/object/put/v2/service.go +++ b/pkg/services/object/put/v2/service.go @@ -11,7 +11,7 @@ import ( // Service implements Put operation of Object service v2. type Service struct { - *cfg + cfg } // Option represents Service constructor option. @@ -24,15 +24,13 @@ type cfg struct { // NewService constructs Service instance from provided options. func NewService(opts ...Option) *Service { - c := new(cfg) + var s Service for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // Put calls internal service and returns v2 object streamer. diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 25e5838c5..fc84508b6 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -146,7 +146,7 @@ func TestGetLocalOnly(t *testing.T) { ctx := context.Background() newSvc := func(storage *testStorage) *Service { - svc := &Service{cfg: new(cfg)} + svc := &Service{} svc.log = test.NewLogger(false) svc.localStorage = storage @@ -248,7 +248,7 @@ func TestGetRemoteSmall(t *testing.T) { container.CalculateID(&id, cnr) newSvc := func(b *testPlacementBuilder, c *testClientCache) *Service { - svc := &Service{cfg: new(cfg)} + svc := &Service{} svc.log = test.NewLogger(false) svc.localStorage = newTestStorage() @@ -357,7 +357,7 @@ func TestGetFromPastEpoch(t *testing.T) { ids22 := generateIDs(10) c22.addResult(idCnr, ids22, nil) - svc := &Service{cfg: new(cfg)} + svc := &Service{} svc.log = test.NewLogger(false) svc.localStorage = newTestStorage() diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 09b277b27..79cf22503 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -15,7 +15,7 @@ import ( // Service is an utility serving requests // of Object.Search service. type Service struct { - *cfg + cfg } // Option is a Service's constructor option. @@ -55,25 +55,22 @@ type epochSource interface { Epoch() (uint64, error) } -func defaultCfg() *cfg { - return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - clientConstructor: new(clientConstructorWrapper), - } +func (c *cfg) initDefault() { + c.log = &logger.Logger{Logger: zap.L()} + c.clientConstructor = new(clientConstructorWrapper) } // New creates, initializes and returns utility serving // Object.Get service requests. func New(opts ...Option) *Service { - c := defaultCfg() + var s Service + s.cfg.initDefault() for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // WithLogger returns option to specify Get service's logger. diff --git a/pkg/services/object/search/v2/service.go b/pkg/services/object/search/v2/service.go index 17e1bc7e0..b6c25223c 100644 --- a/pkg/services/object/search/v2/service.go +++ b/pkg/services/object/search/v2/service.go @@ -9,7 +9,7 @@ import ( // Service implements Search operation of Object service v2. type Service struct { - *cfg + cfg } // Option represents Service constructor option. @@ -23,15 +23,13 @@ type cfg struct { // NewService constructs Service instance from provided options. func NewService(opts ...Option) *Service { - c := new(cfg) + var s Service for i := range opts { - opts[i](c) + opts[i](&s.cfg) } - return &Service{ - cfg: c, - } + return &s } // Search calls internal service and returns v2 object stream. -- 2.45.3 From 724346a7045f136dfae6b9443faf7aa35c037ef9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 14:29:29 +0300 Subject: [PATCH 05/16] [#6] services/object: Simplify storage wrappers Signed-off-by: Evgenii Stratonikov --- pkg/services/object/acl/eacl/v2/headers.go | 2 +- pkg/services/object/acl/eacl/v2/localstore.go | 8 +++----- pkg/services/object/acl/eacl/v2/opts.go | 4 +--- pkg/services/object/get/service.go | 3 +-- pkg/services/object/get/util.go | 13 ++++++------- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 3d09e84b0..5fda90559 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -46,7 +46,7 @@ type headerSource struct { } func (c *cfg) initDefault() { - c.storage = new(localStorage) + c.storage = (*localStorage)(nil) } func NewMessageHeaderSource(opts ...Option) (eaclSDK.TypedHeaderSource, error) { diff --git a/pkg/services/object/acl/eacl/v2/localstore.go b/pkg/services/object/acl/eacl/v2/localstore.go index 40271f1cd..3c6452e30 100644 --- a/pkg/services/object/acl/eacl/v2/localstore.go +++ b/pkg/services/object/acl/eacl/v2/localstore.go @@ -8,14 +8,12 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) -type localStorage struct { - ls *engine.StorageEngine -} +type localStorage engine.StorageEngine func (s *localStorage) Head(addr oid.Address) (*objectSDK.Object, error) { - if s.ls == nil { + if s == nil { return nil, io.ErrUnexpectedEOF } - return engine.Head(s.ls, addr) + return engine.Head((*engine.StorageEngine)(s), addr) } diff --git a/pkg/services/object/acl/eacl/v2/opts.go b/pkg/services/object/acl/eacl/v2/opts.go index 7657e8780..f715e3430 100644 --- a/pkg/services/object/acl/eacl/v2/opts.go +++ b/pkg/services/object/acl/eacl/v2/opts.go @@ -14,9 +14,7 @@ func WithObjectStorage(v ObjectStorage) Option { func WithLocalObjectStorage(v *engine.StorageEngine) Option { return func(c *cfg) { - c.storage = &localStorage{ - ls: v, - } + c.storage = (*localStorage)(v) } } diff --git a/pkg/services/object/get/service.go b/pkg/services/object/get/service.go index b52c16384..a1577b37e 100644 --- a/pkg/services/object/get/service.go +++ b/pkg/services/object/get/service.go @@ -51,7 +51,6 @@ type epochSource interface { func (c *cfg) initDefault() { c.log = &logger.Logger{Logger: zap.L()} - c.localStorage = new(storageEngineWrapper) c.clientCache = new(clientCacheWrapper) } @@ -79,7 +78,7 @@ func WithLogger(l *logger.Logger) Option { // instance. func WithLocalStorageEngine(e *engine.StorageEngine) Option { return func(c *cfg) { - c.localStorage.(*storageEngineWrapper).engine = e + c.localStorage = (*storageEngineWrapper)(e) } } diff --git a/pkg/services/object/get/util.go b/pkg/services/object/get/util.go index c51fc678f..6cc114a64 100644 --- a/pkg/services/object/get/util.go +++ b/pkg/services/object/get/util.go @@ -28,9 +28,7 @@ type clientWrapper struct { client coreclient.MultiAddressClient } -type storageEngineWrapper struct { - engine *engine.StorageEngine -} +type storageEngineWrapper engine.StorageEngine type partWriter struct { ObjectWriter @@ -192,13 +190,14 @@ func (c *clientWrapper) get(exec *execCtx, key *ecdsa.PrivateKey) (*object.Objec return res.Object(), nil } -func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { +func (w *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { + e := (*engine.StorageEngine)(w) if exec.headOnly { var headPrm engine.HeadPrm headPrm.WithAddress(exec.prm.addr) headPrm.WithRaw(exec.prm.raw) - r, err := e.engine.Head(headPrm) + r, err := e.Head(headPrm) if err != nil { return nil, err } @@ -209,7 +208,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { getRange.WithAddress(exec.prm.addr) getRange.WithPayloadRange(rng) - r, err := e.engine.GetRange(getRange) + r, err := e.GetRange(getRange) if err != nil { return nil, err } @@ -219,7 +218,7 @@ func (e *storageEngineWrapper) get(exec *execCtx) (*object.Object, error) { var getPrm engine.GetPrm getPrm.WithAddress(exec.prm.addr) - r, err := e.engine.Get(getPrm) + r, err := e.Get(getPrm) if err != nil { return nil, err } -- 2.45.3 From b8f8462f383d0400839cb3ae4279d242ab03aefb Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 14:29:51 +0300 Subject: [PATCH 06/16] [#6] services/policer: Reduce the amount of indirect pointers Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/policer.go | 37 ++++++++++++++------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index dba0c1cba..50610b5b6 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -51,11 +51,11 @@ func (oiw *objectsInWork) add(addr oid.Address) { // Policer represents the utility that verifies // compliance with the object storage policy. type Policer struct { - *cfg + cfg cache *lru.Cache[oid.Address, time.Time] - objsInWork *objectsInWork + objsInWork objectsInWork } // Option is an option for Policer constructor. @@ -95,38 +95,33 @@ type cfg struct { rebalanceFreq, evictDuration time.Duration } -func defaultCfg() *cfg { - return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - batchSize: 10, - cacheSize: 1024, // 1024 * address size = 1024 * 64 = 64 MiB - rebalanceFreq: 1 * time.Second, - evictDuration: 30 * time.Second, - } +func (c *cfg) initDefault() { + c.log = &logger.Logger{Logger: zap.L()} + c.batchSize = 10 + c.cacheSize = 1024 // 1024 * address size = 1024 * 64 = 64 MiB + c.rebalanceFreq = 1 * time.Second + c.evictDuration = 30 * time.Second } // New creates, initializes and returns Policer instance. func New(opts ...Option) *Policer { - c := defaultCfg() + var p Policer + p.cfg.initDefault() for i := range opts { - opts[i](c) + opts[i](&p.cfg) } - c.log = &logger.Logger{Logger: c.log.With(zap.String("component", "Object Policer"))} + p.log = &logger.Logger{Logger: p.cfg.log.With(zap.String("component", "Object Policer"))} - cache, err := lru.New[oid.Address, time.Time](int(c.cacheSize)) + cache, err := lru.New[oid.Address, time.Time](int(p.cacheSize)) if err != nil { panic(err) } - return &Policer{ - cfg: c, - cache: cache, - objsInWork: &objectsInWork{ - objs: make(map[oid.Address]struct{}, c.maxCapacity), - }, - } + p.cache = cache + p.objsInWork.objs = make(map[oid.Address]struct{}, p.maxCapacity) + return &p } // WithHeadTimeout returns option to set Head timeout of Policer. -- 2.45.3 From 41866dfcaa697742515901442f493894238db9b5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 14:40:34 +0300 Subject: [PATCH 07/16] [#6] services/object: Reduce `distibutedTarget` memory footprint Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/distributed.go | 15 ++------------- pkg/services/object/put/streamer.go | 15 ++++++++++----- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 47104b323..268303f9b 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -23,8 +23,6 @@ type preparedObjectTarget interface { type distributedTarget struct { traversal traversal - remotePool, localPool util.WorkerPool - obj *objectSDK.Object objMeta object.ContentMeta @@ -32,7 +30,7 @@ type distributedTarget struct { nodeTargetInitializer func(nodeDesc) preparedObjectTarget - isLocalKey func([]byte) bool + getWorkerPool func([]byte) (util.WorkerPool, bool) relay func(nodeDesc) error @@ -196,16 +194,7 @@ loop: addr := addrs[i] - isLocal := t.isLocalKey(addr.PublicKey()) - - var workerPool util.WorkerPool - - if isLocal { - workerPool = t.localPool - } else { - workerPool = t.remotePool - } - + workerPool, isLocal := t.getWorkerPool(addr.PublicKey()) if err := workerPool.Submit(func() { defer wg.Done() diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 915b718a3..53de626f5 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/transformer" + pkgutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -221,9 +222,8 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) transformer.ObjectTarget { extraBroadcastEnabled: withBroadcast, }, - payload: getPayload(), - remotePool: p.remotePool, - localPool: p.localPool, + payload: getPayload(), + getWorkerPool: p.getWorkerPool, nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { return &localTarget{ @@ -245,8 +245,6 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) transformer.ObjectTarget { relay: relay, fmt: p.fmtValidator, log: p.log, - - isLocalKey: p.netmapKeys.IsLocalKey, } } @@ -283,3 +281,10 @@ func (p *Streamer) Close() (*PutResponse, error) { id: ids.SelfID(), }, nil } + +func (p *Streamer) getWorkerPool(pub []byte) (pkgutil.WorkerPool, bool) { + if p.netmapKeys.IsLocalKey(pub) { + return p.localPool, true + } + return p.remotePool, false +} -- 2.45.3 From 4a080ecbb78b7fafc994a26895455eb2b1bc1470 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 17:48:50 +0300 Subject: [PATCH 08/16] [#6] services/util: Remove `HandleUnaryRequest` There is no need in a wrapper with many from-`interface{}` conversions. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/accounting.go | 6 +- cmd/frostfs-node/container.go | 19 ++-- cmd/frostfs-node/netmap.go | 20 ++-- cmd/frostfs-node/reputation.go | 19 ++-- cmd/frostfs-node/session.go | 5 +- pkg/services/accounting/executor.go | 10 +- pkg/services/accounting/response.go | 37 ------- pkg/services/container/executor.go | 14 ++- pkg/services/container/response.go | 115 -------------------- pkg/services/netmap/executor.go | 13 ++- pkg/services/netmap/response.go | 63 ----------- pkg/services/object/response.go | 27 ++--- pkg/services/reputation/rpc/response.go | 50 --------- pkg/services/session/executor.go | 11 +- pkg/services/session/response.go | 37 ------- pkg/services/util/response/client_stream.go | 6 +- pkg/services/util/response/server_stream.go | 6 +- pkg/services/util/response/service.go | 7 +- pkg/services/util/response/unary.go | 21 ---- 19 files changed, 86 insertions(+), 400 deletions(-) delete mode 100644 pkg/services/accounting/response.go delete mode 100644 pkg/services/container/response.go delete mode 100644 pkg/services/netmap/response.go delete mode 100644 pkg/services/reputation/rpc/response.go delete mode 100644 pkg/services/session/response.go delete mode 100644 pkg/services/util/response/unary.go diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index 26acc0437..fcc44fdce 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -19,10 +19,8 @@ func initAccountingService(c *cfg) { server := accountingTransportGRPC.New( accountingService.NewSignService( &c.key.PrivateKey, - accountingService.NewResponseService( - accountingService.NewExecutionService( - accounting.NewExecutor(balanceMorphWrapper), - ), + accountingService.NewExecutionService( + accounting.NewExecutor(balanceMorphWrapper), c.respSvc, ), ), diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index bcd9e3bef..2b2e7b783 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -197,16 +197,13 @@ func initContainerService(c *cfg) { server := containerTransportGRPC.New( containerService.NewSignService( &c.key.PrivateKey, - containerService.NewResponseService( - &usedSpaceService{ - Server: containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt)), - loadWriterProvider: loadRouter, - loadPlacementBuilder: loadPlacementBuilder, - routeBuilder: routeBuilder, - cfg: c, - }, - c.respSvc, - ), + &usedSpaceService{ + Server: containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), + loadWriterProvider: loadRouter, + loadPlacementBuilder: loadPlacementBuilder, + routeBuilder: routeBuilder, + cfg: c, + }, ), ) @@ -568,6 +565,8 @@ func (c *usedSpaceService) AnnounceUsedSpace(ctx context.Context, req *container resp := new(containerV2.AnnounceUsedSpaceResponse) resp.SetBody(respBody) + c.cfg.respSvc.SetMeta(resp) + return resp, nil } diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 00bbdbf5c..cbc85b7c2 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -153,17 +153,15 @@ func initNetmapService(c *cfg) { server := netmapTransportGRPC.New( netmapService.NewSignService( &c.key.PrivateKey, - netmapService.NewResponseService( - netmapService.NewExecutionService( - c, - c.apiVersion, - &netInfo{ - netState: c.cfgNetmap.state, - magic: c.cfgMorph.client, - morphClientNetMap: c.cfgNetmap.wrapper, - msPerBlockRdr: c.cfgMorph.client.MsPerBlock, - }, - ), + netmapService.NewExecutionService( + c, + c.apiVersion, + &netInfo{ + netState: c.cfgNetmap.state, + magic: c.cfgMorph.client, + morphClientNetMap: c.cfgNetmap.wrapper, + msPerBlockRdr: c.cfgMorph.client.MsPerBlock, + }, c.respSvc, ), ), diff --git a/cmd/frostfs-node/reputation.go b/cmd/frostfs-node/reputation.go index 8854b21cb..7ef16ad25 100644 --- a/cmd/frostfs-node/reputation.go +++ b/cmd/frostfs-node/reputation.go @@ -199,16 +199,13 @@ func initReputationService(c *cfg) { server := grpcreputation.New( reputationrpc.NewSignService( &c.key.PrivateKey, - reputationrpc.NewResponseService( - &reputationServer{ - cfg: c, - log: c.log, - localRouter: localTrustRouter, - intermediateRouter: intermediateTrustRouter, - routeBuilder: localRouteBuilder, - }, - c.respSvc, - ), + &reputationServer{ + cfg: c, + log: c.log, + localRouter: localTrustRouter, + intermediateRouter: intermediateTrustRouter, + routeBuilder: localRouteBuilder, + }, ), ) @@ -289,6 +286,7 @@ func (s *reputationServer) AnnounceLocalTrust(ctx context.Context, req *v2reputa resp := new(v2reputation.AnnounceLocalTrustResponse) resp.SetBody(new(v2reputation.AnnounceLocalTrustResponseBody)) + s.respSvc.SetMeta(resp) return resp, nil } @@ -317,6 +315,7 @@ func (s *reputationServer) AnnounceIntermediateResult(ctx context.Context, req * resp := new(v2reputation.AnnounceIntermediateResultResponse) resp.SetBody(new(v2reputation.AnnounceIntermediateResultResponseBody)) + s.respSvc.SetMeta(resp) return resp, nil } diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index 95e3b8205..f9c1811a1 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -53,10 +53,7 @@ func initSessionService(c *cfg) { server := sessionTransportGRPC.New( sessionSvc.NewSignService( &c.key.PrivateKey, - sessionSvc.NewResponseService( - sessionSvc.NewExecutionService(c.privateTokenStore, c.log), - c.respSvc, - ), + sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log), ), ) diff --git a/pkg/services/accounting/executor.go b/pkg/services/accounting/executor.go index 402845957..b0722cf8a 100644 --- a/pkg/services/accounting/executor.go +++ b/pkg/services/accounting/executor.go @@ -5,6 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" ) type ServiceExecutor interface { @@ -12,13 +13,15 @@ type ServiceExecutor interface { } type executorSvc struct { - exec ServiceExecutor + exec ServiceExecutor + respSvc *response.Service } // NewExecutionService wraps ServiceExecutor and returns Accounting Service interface. -func NewExecutionService(exec ServiceExecutor) Server { +func NewExecutionService(exec ServiceExecutor, respSvc *response.Service) Server { return &executorSvc{ - exec: exec, + exec: exec, + respSvc: respSvc, } } @@ -31,5 +34,6 @@ func (s *executorSvc) Balance(ctx context.Context, req *accounting.BalanceReques resp := new(accounting.BalanceResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } diff --git a/pkg/services/accounting/response.go b/pkg/services/accounting/response.go deleted file mode 100644 index a78ac6fd6..000000000 --- a/pkg/services/accounting/response.go +++ /dev/null @@ -1,37 +0,0 @@ -package accounting - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" -) - -type responseService struct { - respSvc *response.Service - - svc Server -} - -// NewResponseService returns accounting service instance that passes internal service -// call to response service. -func NewResponseService(accSvc Server, respSvc *response.Service) Server { - return &responseService{ - respSvc: respSvc, - svc: accSvc, - } -} - -func (s *responseService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Balance(ctx, req.(*accounting.BalanceRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*accounting.BalanceResponse), nil -} diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index b4705d258..d4ae11d62 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" ) type ServiceExecutor interface { @@ -21,12 +22,15 @@ type executorSvc struct { Server exec ServiceExecutor + + respSvc *response.Service } // NewExecutionService wraps ServiceExecutor and returns Container Service interface. -func NewExecutionService(exec ServiceExecutor) Server { +func NewExecutionService(exec ServiceExecutor, respSvc *response.Service) Server { return &executorSvc{ - exec: exec, + exec: exec, + respSvc: respSvc, } } @@ -44,6 +48,7 @@ func (s *executorSvc) Put(ctx context.Context, req *container.PutRequest) (*cont resp := new(container.PutResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } @@ -61,6 +66,7 @@ func (s *executorSvc) Delete(ctx context.Context, req *container.DeleteRequest) resp := new(container.DeleteResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } @@ -73,6 +79,7 @@ func (s *executorSvc) Get(ctx context.Context, req *container.GetRequest) (*cont resp := new(container.GetResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } @@ -85,6 +92,7 @@ func (s *executorSvc) List(ctx context.Context, req *container.ListRequest) (*co resp := new(container.ListResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } @@ -102,6 +110,7 @@ func (s *executorSvc) SetExtendedACL(ctx context.Context, req *container.SetExte resp := new(container.SetExtendedACLResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } @@ -114,5 +123,6 @@ func (s *executorSvc) GetExtendedACL(ctx context.Context, req *container.GetExte resp := new(container.GetExtendedACLResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } diff --git a/pkg/services/container/response.go b/pkg/services/container/response.go deleted file mode 100644 index 138974537..000000000 --- a/pkg/services/container/response.go +++ /dev/null @@ -1,115 +0,0 @@ -package container - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" -) - -type responseService struct { - respSvc *response.Service - - svc Server -} - -// NewResponseService returns container service instance that passes internal service -// call to response service. -func NewResponseService(cnrSvc Server, respSvc *response.Service) Server { - return &responseService{ - respSvc: respSvc, - svc: cnrSvc, - } -} - -func (s *responseService) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Put(ctx, req.(*container.PutRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.PutResponse), nil -} - -func (s *responseService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Delete(ctx, req.(*container.DeleteRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.DeleteResponse), nil -} - -func (s *responseService) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Get(ctx, req.(*container.GetRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.GetResponse), nil -} - -func (s *responseService) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.List(ctx, req.(*container.ListRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.ListResponse), nil -} - -func (s *responseService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.SetExtendedACL(ctx, req.(*container.SetExtendedACLRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.SetExtendedACLResponse), nil -} - -func (s *responseService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.GetExtendedACL(ctx, req.(*container.GetExtendedACLRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.GetExtendedACLResponse), nil -} - -func (s *responseService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.AnnounceUsedSpace(ctx, req.(*container.AnnounceUsedSpaceRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*container.AnnounceUsedSpaceResponse), nil -} diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index 9fa3d767f..d1e7a949e 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" versionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) @@ -18,6 +19,8 @@ type executorSvc struct { state NodeState netInfo NetworkInfo + + respSvc *response.Service } // NodeState encapsulates information @@ -42,8 +45,8 @@ type NetworkInfo interface { Dump(versionsdk.Version) (*netmapSDK.NetworkInfo, error) } -func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo) Server { - if s == nil || netInfo == nil || !version.IsValid(v) { +func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo, respSvc *response.Service) Server { + if s == nil || netInfo == nil || !version.IsValid(v) || respSvc == nil { // this should never happen, otherwise it programmers bug panic("can't create netmap execution service") } @@ -51,6 +54,7 @@ func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo) res := &executorSvc{ state: s, netInfo: netInfo, + respSvc: respSvc, } v.WriteToV2(&res.version) @@ -96,6 +100,7 @@ func (s *executorSvc) LocalNodeInfo( resp := new(netmap.LocalNodeInfoResponse) resp.SetBody(body) + s.respSvc.SetMeta(resp) return resp, nil } @@ -126,10 +131,11 @@ func (s *executorSvc) NetworkInfo( resp := new(netmap.NetworkInfoResponse) resp.SetBody(body) + s.respSvc.SetMeta(resp) return resp, nil } -func (s *executorSvc) Snapshot(_ context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { +func (s *executorSvc) Snapshot(_ context.Context, _ *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { var nm netmap.NetMap err := s.state.ReadCurrentNetMap(&nm) @@ -143,5 +149,6 @@ func (s *executorSvc) Snapshot(_ context.Context, req *netmap.SnapshotRequest) ( resp := new(netmap.SnapshotResponse) resp.SetBody(body) + s.respSvc.SetMeta(resp) return resp, nil } diff --git a/pkg/services/netmap/response.go b/pkg/services/netmap/response.go deleted file mode 100644 index 8b035e461..000000000 --- a/pkg/services/netmap/response.go +++ /dev/null @@ -1,63 +0,0 @@ -package netmap - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" -) - -type responseService struct { - respSvc *response.Service - - svc Server -} - -// NewResponseService returns netmap service instance that passes internal service -// call to response service. -func NewResponseService(nmSvc Server, respSvc *response.Service) Server { - return &responseService{ - respSvc: respSvc, - svc: nmSvc, - } -} - -func (s *responseService) LocalNodeInfo(ctx context.Context, req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.LocalNodeInfo(ctx, req.(*netmap.LocalNodeInfoRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*netmap.LocalNodeInfoResponse), nil -} - -func (s *responseService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.NetworkInfo(ctx, req.(*netmap.NetworkInfoRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*netmap.NetworkInfoResponse), nil -} - -func (s *responseService) Snapshot(ctx context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Snapshot(ctx, req.(*netmap.SnapshotRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*netmap.SnapshotResponse), nil -} diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index 4da2b23a7..305faa5c3 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -91,16 +91,13 @@ func (s *ResponseService) Put(ctx context.Context) (PutObjectStream, error) { } func (s *ResponseService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Head(ctx, req.(*object.HeadRequest)) - }, - ) + resp, err := s.svc.Head(ctx, req) if err != nil { return nil, err } - return resp.(*object.HeadResponse), nil + s.respSvc.SetMeta(resp) + return resp, nil } func (s *searchStreamResponser) Send(resp *object.SearchResponse) error { @@ -117,16 +114,13 @@ func (s *ResponseService) Search(req *object.SearchRequest, stream SearchStream) } func (s *ResponseService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Delete(ctx, req.(*object.DeleteRequest)) - }, - ) + resp, err := s.svc.Delete(ctx, req) if err != nil { return nil, err } - return resp.(*object.DeleteResponse), nil + s.respSvc.SetMeta(resp) + return resp, nil } func (s *getRangeStreamResponser) Send(resp *object.GetRangeResponse) error { @@ -143,14 +137,11 @@ func (s *ResponseService) GetRange(req *object.GetRangeRequest, stream GetObject } func (s *ResponseService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.GetRangeHash(ctx, req.(*object.GetRangeHashRequest)) - }, - ) + resp, err := s.svc.GetRangeHash(ctx, req) if err != nil { return nil, err } - return resp.(*object.GetRangeHashResponse), nil + s.respSvc.SetMeta(resp) + return resp, nil } diff --git a/pkg/services/reputation/rpc/response.go b/pkg/services/reputation/rpc/response.go deleted file mode 100644 index 808a0a476..000000000 --- a/pkg/services/reputation/rpc/response.go +++ /dev/null @@ -1,50 +0,0 @@ -package reputationrpc - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/reputation" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" -) - -type responseService struct { - respSvc *response.Service - - svc Server -} - -// NewResponseService returns reputation service server instance that passes -// internal service call to response service. -func NewResponseService(cnrSvc Server, respSvc *response.Service) Server { - return &responseService{ - respSvc: respSvc, - svc: cnrSvc, - } -} - -func (s *responseService) AnnounceLocalTrust(ctx context.Context, req *reputation.AnnounceLocalTrustRequest) (*reputation.AnnounceLocalTrustResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.AnnounceLocalTrust(ctx, req.(*reputation.AnnounceLocalTrustRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*reputation.AnnounceLocalTrustResponse), nil -} - -func (s *responseService) AnnounceIntermediateResult(ctx context.Context, req *reputation.AnnounceIntermediateResultRequest) (*reputation.AnnounceIntermediateResultResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.AnnounceIntermediateResult(ctx, req.(*reputation.AnnounceIntermediateResultRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*reputation.AnnounceIntermediateResultResponse), nil -} diff --git a/pkg/services/session/executor.go b/pkg/services/session/executor.go index 237a13962..3aa6d8ba0 100644 --- a/pkg/services/session/executor.go +++ b/pkg/services/session/executor.go @@ -5,6 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -16,14 +17,17 @@ type ServiceExecutor interface { type executorSvc struct { exec ServiceExecutor + respSvc *response.Service + log *logger.Logger } // NewExecutionService wraps ServiceExecutor and returns Session Service interface. -func NewExecutionService(exec ServiceExecutor, l *logger.Logger) Server { +func NewExecutionService(exec ServiceExecutor, respSvc *response.Service, l *logger.Logger) Server { return &executorSvc{ - exec: exec, - log: l, + exec: exec, + log: l, + respSvc: respSvc, } } @@ -41,5 +45,6 @@ func (s *executorSvc) Create(ctx context.Context, req *session.CreateRequest) (* resp := new(session.CreateResponse) resp.SetBody(respBody) + s.respSvc.SetMeta(resp) return resp, nil } diff --git a/pkg/services/session/response.go b/pkg/services/session/response.go deleted file mode 100644 index cbf93fb1f..000000000 --- a/pkg/services/session/response.go +++ /dev/null @@ -1,37 +0,0 @@ -package session - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" -) - -type responseService struct { - respSvc *response.Service - - svc Server -} - -// NewResponseService returns session service instance that passes internal service -// call to response service. -func NewResponseService(ssSvc Server, respSvc *response.Service) Server { - return &responseService{ - respSvc: respSvc, - svc: ssSvc, - } -} - -func (s *responseService) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { - resp, err := s.respSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Create(ctx, req.(*session.CreateRequest)) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*session.CreateResponse), nil -} diff --git a/pkg/services/util/response/client_stream.go b/pkg/services/util/response/client_stream.go index f167f005a..7984441d1 100644 --- a/pkg/services/util/response/client_stream.go +++ b/pkg/services/util/response/client_stream.go @@ -9,7 +9,7 @@ import ( // ClientMessageStreamer represents client-side message streamer // that sets meta values to the response. type ClientMessageStreamer struct { - cfg *cfg + srv *Service send util.RequestMessageWriter @@ -32,7 +32,7 @@ func (s *ClientMessageStreamer) CloseAndRecv() (util.ResponseMessage, error) { return nil, fmt.Errorf("(%T) could not close stream and receive response: %w", s, err) } - setMeta(resp, s.cfg) + s.srv.SetMeta(resp) return resp, nil } @@ -40,7 +40,7 @@ func (s *ClientMessageStreamer) CloseAndRecv() (util.ResponseMessage, error) { // CreateRequestStreamer wraps stream methods and returns ClientMessageStreamer instance. func (s *Service) CreateRequestStreamer(sender util.RequestMessageWriter, closer util.ClientStreamCloser) *ClientMessageStreamer { return &ClientMessageStreamer{ - cfg: s.cfg, + srv: s, send: sender, close: closer, } diff --git a/pkg/services/util/response/server_stream.go b/pkg/services/util/response/server_stream.go index 8a19fc4e7..df1c00177 100644 --- a/pkg/services/util/response/server_stream.go +++ b/pkg/services/util/response/server_stream.go @@ -9,7 +9,7 @@ import ( // ServerMessageStreamer represents server-side message streamer // that sets meta values to all response messages. type ServerMessageStreamer struct { - cfg *cfg + srv *Service recv util.ResponseMessageReader } @@ -22,7 +22,7 @@ func (s *ServerMessageStreamer) Recv() (util.ResponseMessage, error) { return nil, fmt.Errorf("could not receive response message for signing: %w", err) } - setMeta(m, s.cfg) + s.srv.SetMeta(m) return m, nil } @@ -30,7 +30,7 @@ func (s *ServerMessageStreamer) Recv() (util.ResponseMessage, error) { // HandleServerStreamRequest builds internal streamer via handlers, wraps it to ServerMessageStreamer and returns the result. func (s *Service) HandleServerStreamRequest(respWriter util.ResponseMessageWriter) util.ResponseMessageWriter { return func(resp util.ResponseMessage) error { - setMeta(resp, s.cfg) + s.SetMeta(resp) return respWriter(resp) } diff --git a/pkg/services/util/response/service.go b/pkg/services/util/response/service.go index 87cc8383d..a63d5343b 100644 --- a/pkg/services/util/response/service.go +++ b/pkg/services/util/response/service.go @@ -44,11 +44,12 @@ func NewService(opts ...Option) *Service { } } -func setMeta(resp util.ResponseMessage, cfg *cfg) { +// SetMeta sets adds meta-header to resp. +func (s *Service) SetMeta(resp util.ResponseMessage) { meta := new(session.ResponseMetaHeader) - meta.SetVersion(&cfg.version) + meta.SetVersion(&s.cfg.version) meta.SetTTL(1) // FIXME: #1160 TTL must be calculated - meta.SetEpoch(cfg.state.CurrentEpoch()) + meta.SetEpoch(s.cfg.state.CurrentEpoch()) if origin := resp.GetMetaHeader(); origin != nil { // FIXME: #1160 what if origin is set by local server? diff --git a/pkg/services/util/response/unary.go b/pkg/services/util/response/unary.go deleted file mode 100644 index 29cb95314..000000000 --- a/pkg/services/util/response/unary.go +++ /dev/null @@ -1,21 +0,0 @@ -package response - -import ( - "context" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" -) - -// HandleUnaryRequest call passes request to handler, sets response meta header values and returns it. -func (s *Service) HandleUnaryRequest(ctx context.Context, req any, handler util.UnaryHandler) (util.ResponseMessage, error) { - // process request - resp, err := handler(ctx, req) - if err != nil { - return nil, fmt.Errorf("could not handle request: %w", err) - } - - setMeta(resp, s.cfg) - - return resp, nil -} -- 2.45.3 From cb2c5790006c80c4457cfd75166995c93d03e338 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 17:55:03 +0300 Subject: [PATCH 09/16] [#6] services/util: Remove `HandleServerStreamRequest` There is no need in a wrapper with many from-`interface{}` conversions. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/response.go | 39 ++++++++++----------- pkg/services/util/response/server_stream.go | 37 ------------------- 2 files changed, 18 insertions(+), 58 deletions(-) delete mode 100644 pkg/services/util/response/server_stream.go diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index 305faa5c3..cfdadc845 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -16,21 +16,21 @@ type ResponseService struct { } type searchStreamResponser struct { - util.ServerStream + SearchStream - respWriter util.ResponseMessageWriter + respSvc *response.Service } type getStreamResponser struct { - util.ServerStream + GetObjectStream - respWriter util.ResponseMessageWriter + respSvc *response.Service } type getRangeStreamResponser struct { - util.ServerStream + GetObjectRangeStream - respWriter util.ResponseMessageWriter + respSvc *response.Service } type putStreamResponser struct { @@ -47,15 +47,14 @@ func NewResponseService(objSvc ServiceServer, respSvc *response.Service) *Respon } func (s *getStreamResponser) Send(resp *object.GetResponse) error { - return s.respWriter(resp) + s.respSvc.SetMeta(resp) + return s.GetObjectStream.Send(resp) } func (s *ResponseService) Get(req *object.GetRequest, stream GetObjectStream) error { return s.svc.Get(req, &getStreamResponser{ - ServerStream: stream, - respWriter: s.respSvc.HandleServerStreamRequest(func(resp util.ResponseMessage) error { - return stream.Send(resp.(*object.GetResponse)) - }), + GetObjectStream: stream, + respSvc: s.respSvc, }) } @@ -101,15 +100,14 @@ func (s *ResponseService) Head(ctx context.Context, req *object.HeadRequest) (*o } func (s *searchStreamResponser) Send(resp *object.SearchResponse) error { - return s.respWriter(resp) + s.respSvc.SetMeta(resp) + return s.SearchStream.Send(resp) } func (s *ResponseService) Search(req *object.SearchRequest, stream SearchStream) error { return s.svc.Search(req, &searchStreamResponser{ - ServerStream: stream, - respWriter: s.respSvc.HandleServerStreamRequest(func(resp util.ResponseMessage) error { - return stream.Send(resp.(*object.SearchResponse)) - }), + SearchStream: stream, + respSvc: s.respSvc, }) } @@ -124,15 +122,14 @@ func (s *ResponseService) Delete(ctx context.Context, req *object.DeleteRequest) } func (s *getRangeStreamResponser) Send(resp *object.GetRangeResponse) error { - return s.respWriter(resp) + s.respSvc.SetMeta(resp) + return s.GetObjectRangeStream.Send(resp) } func (s *ResponseService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error { return s.svc.GetRange(req, &getRangeStreamResponser{ - ServerStream: stream, - respWriter: s.respSvc.HandleServerStreamRequest(func(resp util.ResponseMessage) error { - return stream.Send(resp.(*object.GetRangeResponse)) - }), + GetObjectRangeStream: stream, + respSvc: s.respSvc, }) } diff --git a/pkg/services/util/response/server_stream.go b/pkg/services/util/response/server_stream.go deleted file mode 100644 index df1c00177..000000000 --- a/pkg/services/util/response/server_stream.go +++ /dev/null @@ -1,37 +0,0 @@ -package response - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" -) - -// ServerMessageStreamer represents server-side message streamer -// that sets meta values to all response messages. -type ServerMessageStreamer struct { - srv *Service - - recv util.ResponseMessageReader -} - -// Recv calls Recv method of internal streamer, sets response meta -// values and returns the response. -func (s *ServerMessageStreamer) Recv() (util.ResponseMessage, error) { - m, err := s.recv() - if err != nil { - return nil, fmt.Errorf("could not receive response message for signing: %w", err) - } - - s.srv.SetMeta(m) - - return m, nil -} - -// HandleServerStreamRequest builds internal streamer via handlers, wraps it to ServerMessageStreamer and returns the result. -func (s *Service) HandleServerStreamRequest(respWriter util.ResponseMessageWriter) util.ResponseMessageWriter { - return func(resp util.ResponseMessage) error { - s.SetMeta(resp) - - return respWriter(resp) - } -} -- 2.45.3 From 5d13f70cb0eb0b6466be8d265fc47b55ae80429f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 18:01:51 +0300 Subject: [PATCH 10/16] [#6] services/util: Remove `CreateRequestStreamer` There is no need in a wrapper with many from-`interface{}` conversions. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/response.go | 24 +++++------ pkg/services/util/response/client_stream.go | 47 --------------------- 2 files changed, 11 insertions(+), 60 deletions(-) delete mode 100644 pkg/services/util/response/client_stream.go diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index cfdadc845..e6a0b036c 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -5,7 +5,6 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" ) @@ -34,7 +33,8 @@ type getRangeStreamResponser struct { } type putStreamResponser struct { - stream *response.ClientMessageStreamer + stream PutObjectStream + respSvc *response.Service } // NewResponseService returns object service instance that passes internal service @@ -59,16 +59,20 @@ func (s *ResponseService) Get(req *object.GetRequest, stream GetObjectStream) er } func (s *putStreamResponser) Send(req *object.PutRequest) error { - return s.stream.Send(req) + if err := s.stream.Send(req); err != nil { + return fmt.Errorf("could not send the request: %w", err) + } + return nil } func (s *putStreamResponser) CloseAndRecv() (*object.PutResponse, error) { r, err := s.stream.CloseAndRecv() if err != nil { - return nil, fmt.Errorf("(%T) could not receive response: %w", s, err) + return nil, fmt.Errorf("could not close stream and receive response: %w", err) } - return r.(*object.PutResponse), nil + s.respSvc.SetMeta(r) + return r, nil } func (s *ResponseService) Put(ctx context.Context) (PutObjectStream, error) { @@ -78,14 +82,8 @@ func (s *ResponseService) Put(ctx context.Context) (PutObjectStream, error) { } return &putStreamResponser{ - stream: s.respSvc.CreateRequestStreamer( - func(req any) error { - return stream.Send(req.(*object.PutRequest)) - }, - func() (util.ResponseMessage, error) { - return stream.CloseAndRecv() - }, - ), + stream: stream, + respSvc: s.respSvc, }, nil } diff --git a/pkg/services/util/response/client_stream.go b/pkg/services/util/response/client_stream.go deleted file mode 100644 index 7984441d1..000000000 --- a/pkg/services/util/response/client_stream.go +++ /dev/null @@ -1,47 +0,0 @@ -package response - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" -) - -// ClientMessageStreamer represents client-side message streamer -// that sets meta values to the response. -type ClientMessageStreamer struct { - srv *Service - - send util.RequestMessageWriter - - close util.ClientStreamCloser -} - -// Send calls send method of internal streamer. -func (s *ClientMessageStreamer) Send(req any) error { - if err := s.send(req); err != nil { - return fmt.Errorf("(%T) could not send the request: %w", s, err) - } - return nil -} - -// CloseAndRecv closes internal stream, receivers the response, -// sets meta values and returns the result. -func (s *ClientMessageStreamer) CloseAndRecv() (util.ResponseMessage, error) { - resp, err := s.close() - if err != nil { - return nil, fmt.Errorf("(%T) could not close stream and receive response: %w", s, err) - } - - s.srv.SetMeta(resp) - - return resp, nil -} - -// CreateRequestStreamer wraps stream methods and returns ClientMessageStreamer instance. -func (s *Service) CreateRequestStreamer(sender util.RequestMessageWriter, closer util.ClientStreamCloser) *ClientMessageStreamer { - return &ClientMessageStreamer{ - srv: s, - send: sender, - close: closer, - } -} -- 2.45.3 From 761a0aaecc0d08c7a517d48cf83758f97d522fef Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 18:04:24 +0300 Subject: [PATCH 11/16] [#6] services/util: Simplify `response.Service` It has only 1 parameter. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 2 +- pkg/services/util/response/service.go | 40 ++++----------------------- 2 files changed, 7 insertions(+), 35 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 09f2c2087..e2361c9bb 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -590,7 +590,7 @@ func initCfg(appCfg *config.Config) *cfg { key: key, binPublicKey: key.PublicKey().Bytes(), localAddr: netAddr, - respSvc: response.NewService(response.WithNetworkState(netState)), + respSvc: response.NewService(netState), clientCache: cache.NewSDKClientCache(cacheOpts), bgClientCache: cache.NewSDKClientCache(cacheOpts), putClientCache: cache.NewSDKClientCache(cacheOpts), diff --git a/pkg/services/util/response/service.go b/pkg/services/util/response/service.go index a63d5343b..005a643e5 100644 --- a/pkg/services/util/response/service.go +++ b/pkg/services/util/response/service.go @@ -11,45 +11,24 @@ import ( // Service represents universal v2 service // that sets response meta header values. type Service struct { - cfg *cfg -} - -// Option is an option of Service constructor. -type Option func(*cfg) - -type cfg struct { version refs.Version state netmap.State } -func defaultCfg() *cfg { - var c cfg - - version.Current().WriteToV2(&c.version) - - return &c -} - // NewService creates, initializes and returns Service instance. -func NewService(opts ...Option) *Service { - c := defaultCfg() - - for i := range opts { - opts[i](c) - } - - return &Service{ - cfg: c, - } +func NewService(nmState netmap.State) *Service { + s := &Service{state: nmState} + version.Current().WriteToV2(&s.version) + return s } // SetMeta sets adds meta-header to resp. func (s *Service) SetMeta(resp util.ResponseMessage) { meta := new(session.ResponseMetaHeader) - meta.SetVersion(&s.cfg.version) + meta.SetVersion(&s.version) meta.SetTTL(1) // FIXME: #1160 TTL must be calculated - meta.SetEpoch(s.cfg.state.CurrentEpoch()) + meta.SetEpoch(s.state.CurrentEpoch()) if origin := resp.GetMetaHeader(); origin != nil { // FIXME: #1160 what if origin is set by local server? @@ -58,10 +37,3 @@ func (s *Service) SetMeta(resp util.ResponseMessage) { resp.SetMetaHeader(meta) } - -// WithNetworkState returns option to set network state of Service. -func WithNetworkState(v netmap.State) Option { - return func(c *cfg) { - c.state = v - } -} -- 2.45.3 From 0283071b6406653feef45a0bd3f756e0a050f146 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 18:26:43 +0300 Subject: [PATCH 12/16] [#6] services/util: Remove `SignService.HandleUnaryRequest` There is no need in a wrapper with many from-`interface{}` conversions. Signed-off-by: Evgenii Stratonikov --- pkg/services/accounting/sign.go | 15 +--- pkg/services/container/sign.go | 119 ++++++++-------------------- pkg/services/netmap/sign.go | 51 ++++-------- pkg/services/object/sign.go | 51 ++++-------- pkg/services/reputation/rpc/sign.go | 34 +++----- pkg/services/session/sign.go | 17 ++-- pkg/services/util/sign.go | 45 +++++------ 7 files changed, 102 insertions(+), 230 deletions(-) diff --git a/pkg/services/accounting/sign.go b/pkg/services/accounting/sign.go index e98d9b3af..896b88d5a 100644 --- a/pkg/services/accounting/sign.go +++ b/pkg/services/accounting/sign.go @@ -22,17 +22,6 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { } func (s *signService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Balance(ctx, req.(*accounting.BalanceRequest)) - }, - func() util.ResponseMessage { - return new(accounting.BalanceResponse) - }, - ) - if err != nil { - return nil, err - } - - return resp.(*accounting.BalanceResponse), nil + resp, err := util.WrapResponse(s.svc.Balance(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index 9e77e2e21..32256df2e 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -22,113 +22,64 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { } func (s *signService) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Put(ctx, req.(*container.PutRequest)) - }, - func() util.ResponseMessage { - return new(container.PutResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.PutResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.PutResponse), nil + resp, err := util.WrapResponse(s.svc.Put(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Delete(ctx, req.(*container.DeleteRequest)) - }, - func() util.ResponseMessage { - return new(container.DeleteResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.DeleteResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.DeleteResponse), nil + resp, err := util.WrapResponse(s.svc.Delete(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Get(ctx, req.(*container.GetRequest)) - }, - func() util.ResponseMessage { - return new(container.GetResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.GetResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.GetResponse), nil + resp, err := util.WrapResponse(s.svc.Get(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.List(ctx, req.(*container.ListRequest)) - }, - func() util.ResponseMessage { - return new(container.ListResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.ListResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.ListResponse), nil + resp, err := util.WrapResponse(s.svc.List(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.SetExtendedACL(ctx, req.(*container.SetExtendedACLRequest)) - }, - func() util.ResponseMessage { - return new(container.SetExtendedACLResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.SetExtendedACLResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.SetExtendedACLResponse), nil + resp, err := util.WrapResponse(s.svc.SetExtendedACL(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.GetExtendedACL(ctx, req.(*container.GetExtendedACLRequest)) - }, - func() util.ResponseMessage { - return new(container.GetExtendedACLResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.GetExtendedACLResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.GetExtendedACLResponse), nil + resp, err := util.WrapResponse(s.svc.GetExtendedACL(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.AnnounceUsedSpace(ctx, req.(*container.AnnounceUsedSpaceRequest)) - }, - func() util.ResponseMessage { - return new(container.AnnounceUsedSpaceResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.AnnounceUsedSpaceResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*container.AnnounceUsedSpaceResponse), nil + resp, err := util.WrapResponse(s.svc.AnnounceUsedSpace(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } diff --git a/pkg/services/netmap/sign.go b/pkg/services/netmap/sign.go index 85b19d862..1714c7f40 100644 --- a/pkg/services/netmap/sign.go +++ b/pkg/services/netmap/sign.go @@ -24,49 +24,28 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { func (s *signService) LocalNodeInfo( ctx context.Context, req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.LocalNodeInfo(ctx, req.(*netmap.LocalNodeInfoRequest)) - }, - func() util.ResponseMessage { - return new(netmap.LocalNodeInfoResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(netmap.LocalNodeInfoResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*netmap.LocalNodeInfoResponse), nil + resp, err := util.WrapResponse(s.svc.LocalNodeInfo(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.NetworkInfo(ctx, req.(*netmap.NetworkInfoRequest)) - }, - func() util.ResponseMessage { - return new(netmap.NetworkInfoResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(netmap.NetworkInfoResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*netmap.NetworkInfoResponse), nil + resp, err := util.WrapResponse(s.svc.NetworkInfo(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) Snapshot(ctx context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Snapshot(ctx, req.(*netmap.SnapshotRequest)) - }, - func() util.ResponseMessage { - return new(netmap.SnapshotResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(netmap.SnapshotResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*netmap.SnapshotResponse), nil + resp, err := util.WrapResponse(s.svc.Snapshot(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 585fc659a..1c8aa10c6 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -105,19 +105,12 @@ func (s *SignService) Put(ctx context.Context) (PutObjectStream, error) { } func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Head(ctx, req.(*object.HeadRequest)) - }, - func() util.ResponseMessage { - return new(object.HeadResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(object.HeadResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*object.HeadResponse), nil + resp, err := util.WrapResponse(s.svc.Head(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *searchStreamSigner) Send(resp *object.SearchResponse) error { @@ -156,19 +149,12 @@ func (s *SignService) Search(req *object.SearchRequest, stream SearchStream) err } func (s *SignService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Delete(ctx, req.(*object.DeleteRequest)) - }, - func() util.ResponseMessage { - return new(object.DeleteResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(object.DeleteResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*object.DeleteResponse), nil + resp, err := util.WrapResponse(s.svc.Delete(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *getRangeStreamSigner) Send(resp *object.GetRangeResponse) error { @@ -193,17 +179,10 @@ func (s *SignService) GetRange(req *object.GetRangeRequest, stream GetObjectRang } func (s *SignService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.GetRangeHash(ctx, req.(*object.GetRangeHashRequest)) - }, - func() util.ResponseMessage { - return new(object.GetRangeHashResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(object.GetRangeHashResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*object.GetRangeHashResponse), nil + resp, err := util.WrapResponse(s.svc.GetRangeHash(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } diff --git a/pkg/services/reputation/rpc/sign.go b/pkg/services/reputation/rpc/sign.go index 9db06ff1e..b7a94600d 100644 --- a/pkg/services/reputation/rpc/sign.go +++ b/pkg/services/reputation/rpc/sign.go @@ -22,33 +22,19 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { } func (s *signService) AnnounceLocalTrust(ctx context.Context, req *reputation.AnnounceLocalTrustRequest) (*reputation.AnnounceLocalTrustResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.AnnounceLocalTrust(ctx, req.(*reputation.AnnounceLocalTrustRequest)) - }, - func() util.ResponseMessage { - return new(reputation.AnnounceLocalTrustResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(reputation.AnnounceLocalTrustResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*reputation.AnnounceLocalTrustResponse), nil + resp, err := util.WrapResponse(s.svc.AnnounceLocalTrust(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } func (s *signService) AnnounceIntermediateResult(ctx context.Context, req *reputation.AnnounceIntermediateResultRequest) (*reputation.AnnounceIntermediateResultResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.AnnounceIntermediateResult(ctx, req.(*reputation.AnnounceIntermediateResultRequest)) - }, - func() util.ResponseMessage { - return new(reputation.AnnounceIntermediateResultResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(reputation.AnnounceIntermediateResultResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*reputation.AnnounceIntermediateResultResponse), nil + resp, err := util.WrapResponse(s.svc.AnnounceIntermediateResult(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } diff --git a/pkg/services/session/sign.go b/pkg/services/session/sign.go index 1156dc538..5f590caf1 100644 --- a/pkg/services/session/sign.go +++ b/pkg/services/session/sign.go @@ -22,17 +22,10 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { } func (s *signService) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { - resp, err := s.sigSvc.HandleUnaryRequest(ctx, req, - func(ctx context.Context, req any) (util.ResponseMessage, error) { - return s.svc.Create(ctx, req.(*session.CreateRequest)) - }, - func() util.ResponseMessage { - return new(session.CreateResponse) - }, - ) - if err != nil { - return nil, err + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(session.CreateResponse) + return resp, s.sigSvc.SignResponse(req, resp, err) } - - return resp.(*session.CreateResponse), nil + resp, err := util.WrapResponse(s.svc.Create(ctx, req)) + return resp, s.sigSvc.SignResponse(req, resp, err) } diff --git a/pkg/services/util/sign.go b/pkg/services/util/sign.go index 2478e6256..3f850ed52 100644 --- a/pkg/services/util/sign.go +++ b/pkg/services/util/sign.go @@ -172,44 +172,39 @@ func (s *SignService) HandleServerStreamRequest( return nil } -func (s *SignService) HandleUnaryRequest(ctx context.Context, req any, handler UnaryHandler, blankResp ResponseConstructor) (ResponseMessage, error) { +func (s *SignService) SignResponse(req RequestMessage, resp ResponseMessage, err error) error { // handle protocol versions <=2.10 (API statuses was introduced in 2.11 only) // req argument should be strengthen with type RequestMessage - statusSupported := isStatusSupported(req.(RequestMessage)) // panic is OK here for now - - var ( - resp ResponseMessage - err error - ) - - // verify request signatures - if err = signature.VerifyServiceMessage(req); err != nil { - var sigErr apistatus.SignatureVerification - sigErr.SetMessage(err.Error()) - - err = sigErr - } else { - // process request - resp, err = handler(ctx, req) - } + statusSupported := isStatusSupported(req) if err != nil { if !statusSupported { - return nil, err + return err } - resp = blankResp() - setStatusV2(resp, err) } // sign the response - if err = signResponse(s.key, resp, statusSupported); err != nil { - return nil, err - } + return signResponse(s.key, resp, statusSupported) +} - return resp, nil +func (s *SignService) VerifyRequest(req RequestMessage) error { + if err := signature.VerifyServiceMessage(req); err != nil { + var sigErr apistatus.SignatureVerification + sigErr.SetMessage(err.Error()) + return sigErr + } + return nil +} + +// WrapResponse creates an appropriate response struct if it is nil. +func WrapResponse[T any](resp *T, err error) (*T, error) { + if resp != nil { + return resp, err + } + return new(T), nil } func isStatusSupported(req RequestMessage) bool { -- 2.45.3 From cfd1b1d349931ea546b61da4a1e265cc15ec2446 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 30 Dec 2022 20:01:13 +0300 Subject: [PATCH 13/16] [#6] services/util: Remove remaining stream wrappers Signed-off-by: Evgenii Stratonikov --- pkg/services/accounting/sign.go | 2 +- pkg/services/container/sign.go | 28 ++--- pkg/services/netmap/sign.go | 12 +- pkg/services/object/sign.go | 187 +++++++++++++-------------- pkg/services/reputation/rpc/sign.go | 8 +- pkg/services/session/sign.go | 4 +- pkg/services/util/sign.go | 188 +++------------------------- 7 files changed, 142 insertions(+), 287 deletions(-) diff --git a/pkg/services/accounting/sign.go b/pkg/services/accounting/sign.go index 896b88d5a..036668cdd 100644 --- a/pkg/services/accounting/sign.go +++ b/pkg/services/accounting/sign.go @@ -23,5 +23,5 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { func (s *signService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) { resp, err := util.WrapResponse(s.svc.Balance(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index 32256df2e..0fc1b9601 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -24,62 +24,62 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { func (s *signService) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.PutResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Put(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.DeleteResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Delete(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.GetResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Get(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.ListResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.List(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.SetExtendedACLResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.SetExtendedACL(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.GetExtendedACLResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.GetExtendedACL(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.AnnounceUsedSpaceResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.AnnounceUsedSpace(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } diff --git a/pkg/services/netmap/sign.go b/pkg/services/netmap/sign.go index 1714c7f40..6c12b07f7 100644 --- a/pkg/services/netmap/sign.go +++ b/pkg/services/netmap/sign.go @@ -26,26 +26,26 @@ func (s *signService) LocalNodeInfo( req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(netmap.LocalNodeInfoResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.LocalNodeInfo(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(netmap.NetworkInfoResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.NetworkInfo(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) Snapshot(ctx context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(netmap.SnapshotResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Snapshot(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 1c8aa10c6..c42a8d2a7 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -18,27 +18,29 @@ type SignService struct { } type searchStreamSigner struct { - util.ServerStream - - respWriter util.ResponseMessageWriter - - nonEmptyResp bool // set on first Send call + SearchStream + statusSupported bool + sigSvc *util.SignService + nonEmptyResp bool // set on first Send call } type getStreamSigner struct { - util.ServerStream - - respWriter util.ResponseMessageWriter + GetObjectStream + statusSupported bool + sigSvc *util.SignService } type putStreamSigner struct { - stream *util.RequestMessageStreamer + sigSvc *util.SignService + stream PutObjectStream + statusSupported bool + err error } type getRangeStreamSigner struct { - util.ServerStream - - respWriter util.ResponseMessageWriter + GetObjectRangeStream + statusSupported bool + sigSvc *util.SignService } func NewSignService(key *ecdsa.PrivateKey, svc ServiceServer) *SignService { @@ -50,37 +52,50 @@ func NewSignService(key *ecdsa.PrivateKey, svc ServiceServer) *SignService { } func (s *getStreamSigner) Send(resp *object.GetResponse) error { - return s.respWriter(resp) + if err := s.sigSvc.SignResponse(s.statusSupported, resp, nil); err != nil { + return err + } + return s.GetObjectStream.Send(resp) } func (s *SignService) Get(req *object.GetRequest, stream GetObjectStream) error { - return s.sigSvc.HandleServerStreamRequest(req, - func(resp util.ResponseMessage) error { - return stream.Send(resp.(*object.GetResponse)) - }, - func() util.ResponseMessage { - return new(object.GetResponse) - }, - func(respWriter util.ResponseMessageWriter) error { - return s.svc.Get(req, &getStreamSigner{ - ServerStream: stream, - respWriter: respWriter, - }) - }, - ) + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(object.GetResponse) + _ = s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) + return stream.Send(resp) + } + + return s.svc.Get(req, &getStreamSigner{ + GetObjectStream: stream, + sigSvc: s.sigSvc, + statusSupported: util.IsStatusSupported(req), + }) } func (s *putStreamSigner) Send(req *object.PutRequest) error { - return s.stream.Send(req) + s.statusSupported = util.IsStatusSupported(req) + + if s.err = s.sigSvc.VerifyRequest(req); s.err != nil { + return util.ErrAbortStream + } + if s.err = s.stream.Send(req); s.err != nil { + return util.ErrAbortStream + } + return nil } -func (s *putStreamSigner) CloseAndRecv() (*object.PutResponse, error) { - r, err := s.stream.CloseAndRecv() - if err != nil { - return nil, fmt.Errorf("could not receive response: %w", err) +func (s *putStreamSigner) CloseAndRecv() (resp *object.PutResponse, err error) { + if s.err != nil { + err = s.err + resp = new(object.PutResponse) + } else { + resp, err = s.stream.CloseAndRecv() + if err != nil { + return nil, fmt.Errorf("could not close stream and receive response: %w", err) + } } - return r.(*object.PutResponse), nil + return resp, s.sigSvc.SignResponse(s.statusSupported, resp, err) } func (s *SignService) Put(ctx context.Context) (PutObjectStream, error) { @@ -90,99 +105,87 @@ func (s *SignService) Put(ctx context.Context) (PutObjectStream, error) { } return &putStreamSigner{ - stream: s.sigSvc.CreateRequestStreamer( - func(req any) error { - return stream.Send(req.(*object.PutRequest)) - }, - func() (util.ResponseMessage, error) { - return stream.CloseAndRecv() - }, - func() util.ResponseMessage { - return new(object.PutResponse) - }, - ), + stream: stream, + sigSvc: s.sigSvc, }, nil } func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(object.HeadResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Head(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *searchStreamSigner) Send(resp *object.SearchResponse) error { s.nonEmptyResp = true - return s.respWriter(resp) + if err := s.sigSvc.SignResponse(s.statusSupported, resp, nil); err != nil { + return err + } + return s.SearchStream.Send(resp) } func (s *SignService) Search(req *object.SearchRequest, stream SearchStream) error { - return s.sigSvc.HandleServerStreamRequest(req, - func(resp util.ResponseMessage) error { - return stream.Send(resp.(*object.SearchResponse)) - }, - func() util.ResponseMessage { - return new(object.SearchResponse) - }, - func(respWriter util.ResponseMessageWriter) error { - stream := &searchStreamSigner{ - ServerStream: stream, - respWriter: respWriter, - } + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(object.SearchResponse) + _ = s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) + return stream.Send(resp) + } - err := s.svc.Search(req, stream) - - if err == nil && !stream.nonEmptyResp { - // The higher component does not write any response in the case of an empty result (which is correct). - // With the introduction of status returns at least one answer must be signed and sent to the client. - // This approach is supported by clients who do not know how to work with statuses (one could make - // a switch according to the protocol version from the request, but the costs of sending an empty - // answer can be neglected due to the gradual refusal to use the "old" clients). - return stream.Send(new(object.SearchResponse)) - } - - return err - }, - ) + ss := &searchStreamSigner{ + SearchStream: stream, + sigSvc: s.sigSvc, + statusSupported: util.IsStatusSupported(req), + } + err := s.svc.Search(req, ss) + if err == nil && !ss.nonEmptyResp { + // The higher component does not write any response in the case of an empty result (which is correct). + // With the introduction of status returns at least one answer must be signed and sent to the client. + // This approach is supported by clients who do not know how to work with statuses (one could make + // a switch according to the protocol version from the request, but the costs of sending an empty + // answer can be neglected due to the gradual refusal to use the "old" clients). + return stream.Send(new(object.SearchResponse)) + } + return err } func (s *SignService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(object.DeleteResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Delete(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *getRangeStreamSigner) Send(resp *object.GetRangeResponse) error { - return s.respWriter(resp) + if err := s.sigSvc.SignResponse(s.statusSupported, resp, nil); err != nil { + return err + } + return s.GetObjectRangeStream.Send(resp) } func (s *SignService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error { - return s.sigSvc.HandleServerStreamRequest(req, - func(resp util.ResponseMessage) error { - return stream.Send(resp.(*object.GetRangeResponse)) - }, - func() util.ResponseMessage { - return new(object.GetRangeResponse) - }, - func(respWriter util.ResponseMessageWriter) error { - return s.svc.GetRange(req, &getRangeStreamSigner{ - ServerStream: stream, - respWriter: respWriter, - }) - }, - ) + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(object.GetRangeResponse) + _ = s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) + return stream.Send(resp) + } + + return s.svc.GetRange(req, &getRangeStreamSigner{ + GetObjectRangeStream: stream, + sigSvc: s.sigSvc, + statusSupported: util.IsStatusSupported(req), + }) } func (s *SignService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(object.GetRangeHashResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.GetRangeHash(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } diff --git a/pkg/services/reputation/rpc/sign.go b/pkg/services/reputation/rpc/sign.go index b7a94600d..1f2bc32d4 100644 --- a/pkg/services/reputation/rpc/sign.go +++ b/pkg/services/reputation/rpc/sign.go @@ -24,17 +24,17 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { func (s *signService) AnnounceLocalTrust(ctx context.Context, req *reputation.AnnounceLocalTrustRequest) (*reputation.AnnounceLocalTrustResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(reputation.AnnounceLocalTrustResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.AnnounceLocalTrust(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } func (s *signService) AnnounceIntermediateResult(ctx context.Context, req *reputation.AnnounceIntermediateResultRequest) (*reputation.AnnounceIntermediateResultResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(reputation.AnnounceIntermediateResultResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.AnnounceIntermediateResult(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } diff --git a/pkg/services/session/sign.go b/pkg/services/session/sign.go index 5f590caf1..383b9c7e4 100644 --- a/pkg/services/session/sign.go +++ b/pkg/services/session/sign.go @@ -24,8 +24,8 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { func (s *signService) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(session.CreateResponse) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } resp, err := util.WrapResponse(s.svc.Create(ctx, req)) - return resp, s.sigSvc.SignResponse(req, resp, err) + return resp, s.sigSvc.SignResponse(util.IsStatusSupported(req), resp, err) } diff --git a/pkg/services/util/sign.go b/pkg/services/util/sign.go index 3f850ed52..78f56607f 100644 --- a/pkg/services/util/sign.go +++ b/pkg/services/util/sign.go @@ -1,7 +1,6 @@ package util import ( - "context" "crypto/ecdsa" "errors" "fmt" @@ -21,163 +20,23 @@ type ResponseMessage interface { SetMetaHeader(*session.ResponseMetaHeader) } -type UnaryHandler func(context.Context, any) (ResponseMessage, error) - type SignService struct { key *ecdsa.PrivateKey } -type ResponseMessageWriter func(ResponseMessage) error - -type ServerStreamHandler func(context.Context, any) (ResponseMessageReader, error) - -type ResponseMessageReader func() (ResponseMessage, error) - var ErrAbortStream = errors.New("abort message stream") -type ResponseConstructor func() ResponseMessage - -type RequestMessageWriter func(any) error - -type ClientStreamCloser func() (ResponseMessage, error) - -type RequestMessageStreamer struct { - key *ecdsa.PrivateKey - - send RequestMessageWriter - - close ClientStreamCloser - - respCons ResponseConstructor - - statusSupported bool - - sendErr error -} - func NewUnarySignService(key *ecdsa.PrivateKey) *SignService { return &SignService{ key: key, } } -func (s *RequestMessageStreamer) Send(req any) error { - // req argument should be strengthen with type RequestMessage - s.statusSupported = isStatusSupported(req.(RequestMessage)) // panic is OK here for now - - var err error - - // verify request signatures - if err = signature.VerifyServiceMessage(req); err != nil { - err = fmt.Errorf("could not verify request: %w", err) - } else { - err = s.send(req) - } - - if err != nil { - if !s.statusSupported { - return err - } - - s.sendErr = err - - return ErrAbortStream - } - - return nil -} - -func (s *RequestMessageStreamer) CloseAndRecv() (ResponseMessage, error) { - var ( - resp ResponseMessage - err error - ) - - if s.sendErr != nil { - err = s.sendErr - } else { - resp, err = s.close() - if err != nil { - err = fmt.Errorf("could not close stream and receive response: %w", err) - } - } - - if err != nil { - if !s.statusSupported { - return nil, err - } - - resp = s.respCons() - - setStatusV2(resp, err) - } - - if err = signResponse(s.key, resp, s.statusSupported); err != nil { - return nil, err - } - - return resp, nil -} - -func (s *SignService) CreateRequestStreamer(sender RequestMessageWriter, closer ClientStreamCloser, blankResp ResponseConstructor) *RequestMessageStreamer { - return &RequestMessageStreamer{ - key: s.key, - send: sender, - close: closer, - - respCons: blankResp, - } -} - -func (s *SignService) HandleServerStreamRequest( - req any, - respWriter ResponseMessageWriter, - blankResp ResponseConstructor, - respWriterCaller func(ResponseMessageWriter) error, -) error { - // handle protocol versions <=2.10 (API statuses was introduced in 2.11 only) - - // req argument should be strengthen with type RequestMessage - statusSupported := isStatusSupported(req.(RequestMessage)) // panic is OK here for now - - var err error - - // verify request signatures - if err = signature.VerifyServiceMessage(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 { - return err - } - - return respWriter(resp) - }) - } - - if err != nil { - if !statusSupported { - return err - } - - resp := blankResp() - - setStatusV2(resp, err) - - _ = signResponse(s.key, resp, false) // panics or returns nil with false arg - - return respWriter(resp) - } - - return nil -} - -func (s *SignService) SignResponse(req RequestMessage, resp ResponseMessage, err error) error { - // handle protocol versions <=2.10 (API statuses was introduced in 2.11 only) - - // req argument should be strengthen with type RequestMessage - statusSupported := isStatusSupported(req) - +// SignResponse response with private key via signature.SignServiceMessage. +// 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 (s *SignService) SignResponse(statusSupported bool, resp ResponseMessage, err error) error { if err != nil { if !statusSupported { return err @@ -186,8 +45,18 @@ func (s *SignService) SignResponse(req RequestMessage, resp ResponseMessage, err setStatusV2(resp, err) } - // sign the response - return signResponse(s.key, resp, statusSupported) + err = signature.SignServiceMessage(s.key, resp) + if err != nil { + err = fmt.Errorf("could not sign response: %w", err) + + if statusSupported { + // We can't pass this error as status code since response will be unsigned. + // Isn't expected in practice, so panic is ok here. + panic(err) + } + } + + return err } func (s *SignService) VerifyRequest(req RequestMessage) error { @@ -207,7 +76,9 @@ func WrapResponse[T any](resp *T, err error) (*T, error) { return new(T), nil } -func isStatusSupported(req RequestMessage) bool { +// IsStatusSupported returns true iff request version implies expecting status return. +// This allows us to handle protocol versions <=2.10 (API statuses was introduced in 2.11 only). +func IsStatusSupported(req RequestMessage) bool { version := req.GetMetaHeader().GetVersion() mjr := version.GetMajor() @@ -223,22 +94,3 @@ func setStatusV2(resp ResponseMessage, err error) { session.SetStatus(resp, apistatus.ToStatusV2(apistatus.ErrToStatus(err))) } - -// signs response with private key via signature.SignServiceMessage. -// 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 { - err := signature.SignServiceMessage(key, resp) - if err != nil { - err = fmt.Errorf("could not sign response: %w", err) - - if statusSupported { - // We can't pass this error as status code since response will be unsigned. - // Isn't expected in practice, so panic is ok here. - panic(err) - } - } - - return err -} -- 2.45.3 From f161630cf63f5c5f1e0fc2ba47ffb104149db66b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 31 Dec 2022 09:43:13 +0300 Subject: [PATCH 14/16] [#6] services/util: Do not panic in sign function Signed-off-by: Evgenii Stratonikov --- pkg/services/util/sign.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pkg/services/util/sign.go b/pkg/services/util/sign.go index 78f56607f..2c2a5b83c 100644 --- a/pkg/services/util/sign.go +++ b/pkg/services/util/sign.go @@ -47,16 +47,10 @@ func (s *SignService) SignResponse(statusSupported bool, resp ResponseMessage, e err = signature.SignServiceMessage(s.key, resp) if err != nil { - err = fmt.Errorf("could not sign response: %w", err) - - if statusSupported { - // We can't pass this error as status code since response will be unsigned. - // Isn't expected in practice, so panic is ok here. - panic(err) - } + return fmt.Errorf("could not sign response: %w", err) } - return err + return nil } func (s *SignService) VerifyRequest(req RequestMessage) error { -- 2.45.3 From b3dd9bcb896a2b5b787fb5617c5279ff5c31547a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Jan 2023 15:10:54 +0300 Subject: [PATCH 15/16] [#6] services/object: Simplify local/remote targets Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/distributed.go | 6 ++--- pkg/services/object/put/local.go | 33 +++++++------------------- pkg/services/object/put/remote.go | 25 ++++++------------- pkg/services/object/put/streamer.go | 2 +- 4 files changed, 19 insertions(+), 47 deletions(-) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 268303f9b..9f7a9e81f 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -17,7 +17,6 @@ import ( type preparedObjectTarget interface { WriteObject(*objectSDK.Object, object.ContentMeta) error - Close() (*transformer.AccessIdentifiers, error) } type distributedTarget struct { @@ -154,10 +153,9 @@ func (t *distributedTarget) sendObject(node nodeDesc) error { target := t.nodeTargetInitializer(node) - if err := target.WriteObject(t.obj, t.objMeta); err != nil { + err := target.WriteObject(t.obj, t.objMeta) + if err != nil { return fmt.Errorf("could not write header: %w", err) - } else if _, err := target.Close(); err != nil { - return fmt.Errorf("could not close object stream: %w", err) } return nil } diff --git a/pkg/services/object/put/local.go b/pkg/services/object/put/local.go index f344f77e9..ba2a5aa0a 100644 --- a/pkg/services/object/put/local.go +++ b/pkg/services/object/put/local.go @@ -4,7 +4,6 @@ import ( "fmt" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/transformer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -26,40 +25,26 @@ type ObjectStorage interface { type localTarget struct { storage ObjectStorage - - obj *object.Object - meta objectCore.ContentMeta } -func (t *localTarget) WriteObject(obj *object.Object, meta objectCore.ContentMeta) error { - t.obj = obj - t.meta = meta - - return nil -} - -func (t *localTarget) Close() (*transformer.AccessIdentifiers, error) { - switch t.meta.Type() { +func (t localTarget) WriteObject(obj *object.Object, meta objectCore.ContentMeta) error { + switch meta.Type() { case object.TypeTombstone: - err := t.storage.Delete(objectCore.AddressOf(t.obj), t.meta.Objects()) + err := t.storage.Delete(objectCore.AddressOf(obj), meta.Objects()) if err != nil { - return nil, fmt.Errorf("could not delete objects from tombstone locally: %w", err) + return fmt.Errorf("could not delete objects from tombstone locally: %w", err) } case object.TypeLock: - err := t.storage.Lock(objectCore.AddressOf(t.obj), t.meta.Objects()) + err := t.storage.Lock(objectCore.AddressOf(obj), meta.Objects()) if err != nil { - return nil, fmt.Errorf("could not lock object from lock objects locally: %w", err) + return fmt.Errorf("could not lock object from lock objects locally: %w", err) } default: // objects that do not change meta storage } - if err := t.storage.Put(t.obj); err != nil { - return nil, fmt.Errorf("(%T) could not put object to local storage: %w", t, err) + if err := t.storage.Put(obj); err != nil { + return fmt.Errorf("(%T) could not put object to local storage: %w", t, err) } - - id, _ := t.obj.ID() - - return new(transformer.AccessIdentifiers). - WithSelfID(id), nil + return nil } diff --git a/pkg/services/object/put/remote.go b/pkg/services/object/put/remote.go index 760de7508..27df5b6cc 100644 --- a/pkg/services/object/put/remote.go +++ b/pkg/services/object/put/remote.go @@ -10,7 +10,6 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/transformer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) @@ -25,8 +24,6 @@ type remoteTarget struct { nodeInfo clientcore.NodeInfo - obj *object.Object - clientConstructor ClientConstructor } @@ -46,15 +43,9 @@ type RemotePutPrm struct { } func (t *remoteTarget) WriteObject(obj *object.Object, _ objectcore.ContentMeta) error { - t.obj = obj - - return nil -} - -func (t *remoteTarget) Close() (*transformer.AccessIdentifiers, error) { c, err := t.clientConstructor.Get(t.nodeInfo) if err != nil { - return nil, fmt.Errorf("(%T) could not create SDK client %s: %w", t, t.nodeInfo, err) + return fmt.Errorf("(%T) could not create SDK client %s: %w", t, t.nodeInfo, err) } var prm internalclient.PutObjectPrm @@ -65,15 +56,14 @@ func (t *remoteTarget) Close() (*transformer.AccessIdentifiers, error) { prm.SetSessionToken(t.commonPrm.SessionToken()) prm.SetBearerToken(t.commonPrm.BearerToken()) prm.SetXHeaders(t.commonPrm.XHeaders()) - prm.SetObject(t.obj) + prm.SetObject(obj) - res, err := internalclient.PutObject(prm) + _, err = internalclient.PutObject(prm) if err != nil { - return nil, fmt.Errorf("(%T) could not put object to %s: %w", t, t.nodeInfo.AddressGroup(), err) + return fmt.Errorf("(%T) could not put object to %s: %w", t, t.nodeInfo.AddressGroup(), err) } - return new(transformer.AccessIdentifiers). - WithSelfID(res.ID()), nil + return nil } // NewRemoteSender creates, initializes and returns new RemoteSender instance. @@ -120,9 +110,8 @@ func (s *RemoteSender) PutObject(ctx context.Context, p *RemotePutPrm) error { return fmt.Errorf("parse client node info: %w", err) } - if err := t.WriteObject(p.obj, objectcore.ContentMeta{}); err != nil { - return fmt.Errorf("(%T) could not send object header: %w", s, err) - } else if _, err := t.Close(); err != nil { + err = t.WriteObject(p.obj, objectcore.ContentMeta{}) + if err != nil { return fmt.Errorf("(%T) could not send object: %w", s, err) } diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 53de626f5..b8347f46e 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -226,7 +226,7 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) transformer.ObjectTarget { getWorkerPool: p.getWorkerPool, nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { - return &localTarget{ + return localTarget{ storage: p.localStore, } } -- 2.45.3 From 1d3d0b7cc15eacdee7de1ea26c7f953ea0bc9f9d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 10 Jan 2023 15:24:18 +0300 Subject: [PATCH 16/16] [#6] services/object: Remove mutex from `traversal` struct Make it being used from a single thread. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/distributed.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 9f7a9e81f..14daf5be2 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -45,9 +45,6 @@ type traversal struct { // need of additional broadcast after the object is saved extraBroadcastEnabled bool - // mtx protects mExclude map. - mtx sync.RWMutex - // container nodes which was processed during the primary object placement mExclude map[string]struct{} } @@ -73,21 +70,17 @@ func (x *traversal) submitProcessed(n placement.Node) { if x.extraBroadcastEnabled { key := string(n.PublicKey()) - x.mtx.Lock() if x.mExclude == nil { x.mExclude = make(map[string]struct{}, 1) } x.mExclude[key] = struct{}{} - x.mtx.Unlock() } } // checks if specified node was processed during the primary object placement. func (x *traversal) processed(n placement.Node) bool { - x.mtx.RLock() _, ok := x.mExclude[string(n.PublicKey())] - x.mtx.RUnlock() return ok } @@ -198,12 +191,6 @@ loop: err := f(nodeDesc{local: isLocal, info: addr}) - // mark the container node as processed in order to exclude it - // in subsequent container broadcast. Note that we don't - // process this node during broadcast if primary placement - // on it failed. - t.traversal.submitProcessed(addr) - if err != nil { resErr.Store(err) svcutil.LogServiceError(t.log, "PUT", addr.Addresses(), err) @@ -218,6 +205,12 @@ loop: break loop } + + // mark the container node as processed in order to exclude it + // in subsequent container broadcast. Note that we don't + // process this node during broadcast if primary placement + // on it failed. + t.traversal.submitProcessed(addrs[i]) } wg.Wait() -- 2.45.3