[#299] pool: Do not use pointers to the resulting values

In previous implementation `pool` package provided access to resulting
values as pointers to them. This caused clients to handle nil
cases even when the field presence in the response is required.

Avoid returning pointers to values in result getters. This also reduces
reference counter load and allows values from `client.Client` to be
forwarded directly without additional assignment.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-08-08 13:15:10 +04:00 committed by LeL
parent f8148c954b
commit 737e690482
3 changed files with 149 additions and 158 deletions

View file

@ -65,16 +65,16 @@ func newToken(key ecdsa.PrivateKey) *session.Object {
return &tok return &tok
} }
func (m *mockClient) balanceGet(context.Context, PrmBalanceGet) (*accounting.Decimal, error) { func (m *mockClient) balanceGet(context.Context, PrmBalanceGet) (accounting.Decimal, error) {
return nil, nil return accounting.Decimal{}, nil
} }
func (m *mockClient) containerPut(context.Context, PrmContainerPut) (*cid.ID, error) { func (m *mockClient) containerPut(context.Context, PrmContainerPut) (cid.ID, error) {
return nil, nil return cid.ID{}, nil
} }
func (m *mockClient) containerGet(context.Context, PrmContainerGet) (*container.Container, error) { func (m *mockClient) containerGet(context.Context, PrmContainerGet) (container.Container, error) {
return nil, nil return container.Container{}, nil
} }
func (m *mockClient) containerList(context.Context, PrmContainerList) ([]cid.ID, error) { func (m *mockClient) containerList(context.Context, PrmContainerList) ([]cid.ID, error) {
@ -85,65 +85,69 @@ func (m *mockClient) containerDelete(context.Context, PrmContainerDelete) error
return nil return nil
} }
func (m *mockClient) containerEACL(context.Context, PrmContainerEACL) (*eacl.Table, error) { func (m *mockClient) containerEACL(context.Context, PrmContainerEACL) (eacl.Table, error) {
return nil, nil return eacl.Table{}, nil
} }
func (m *mockClient) containerSetEACL(context.Context, PrmContainerSetEACL) error { func (m *mockClient) containerSetEACL(context.Context, PrmContainerSetEACL) error {
return nil return nil
} }
func (m *mockClient) endpointInfo(context.Context, prmEndpointInfo) (*netmap.NodeInfo, error) { func (m *mockClient) endpointInfo(context.Context, prmEndpointInfo) (netmap.NodeInfo, error) {
if m.errorOnEndpointInfo {
return nil, m.handleError(nil, errors.New("error"))
}
var ni netmap.NodeInfo var ni netmap.NodeInfo
if m.errorOnEndpointInfo {
return ni, m.handleError(nil, errors.New("error"))
}
ni.SetNetworkEndpoints(m.addr) ni.SetNetworkEndpoints(m.addr)
return &ni, nil return ni, nil
}
func (m *mockClient) networkInfo(context.Context, prmNetworkInfo) (*netmap.NetworkInfo, error) {
if m.errorOnNetworkInfo {
return nil, m.handleError(nil, errors.New("error"))
} }
func (m *mockClient) networkInfo(context.Context, prmNetworkInfo) (netmap.NetworkInfo, error) {
var ni netmap.NetworkInfo var ni netmap.NetworkInfo
return &ni, nil
if m.errorOnNetworkInfo {
return ni, m.handleError(nil, errors.New("error"))
} }
func (m *mockClient) objectPut(context.Context, PrmObjectPut) (*oid.ID, error) { return ni, nil
return nil, nil }
func (m *mockClient) objectPut(context.Context, PrmObjectPut) (oid.ID, error) {
return oid.ID{}, nil
} }
func (m *mockClient) objectDelete(context.Context, PrmObjectDelete) error { func (m *mockClient) objectDelete(context.Context, PrmObjectDelete) error {
return nil return nil
} }
func (m *mockClient) objectGet(context.Context, PrmObjectGet) (*ResGetObject, error) { func (m *mockClient) objectGet(context.Context, PrmObjectGet) (ResGetObject, error) {
var res ResGetObject
if m.stOnGetObject == nil { if m.stOnGetObject == nil {
return &ResGetObject{}, nil return res, nil
} }
status := apistatus.ErrFromStatus(m.stOnGetObject) status := apistatus.ErrFromStatus(m.stOnGetObject)
return &ResGetObject{}, m.handleError(status, nil) return res, m.handleError(status, nil)
} }
func (m *mockClient) objectHead(context.Context, PrmObjectHead) (*object.Object, error) { func (m *mockClient) objectHead(context.Context, PrmObjectHead) (object.Object, error) {
return nil, nil return object.Object{}, nil
} }
func (m *mockClient) objectRange(context.Context, PrmObjectRange) (*ResObjectRange, error) { func (m *mockClient) objectRange(context.Context, PrmObjectRange) (ResObjectRange, error) {
return nil, nil return ResObjectRange{}, nil
} }
func (m *mockClient) objectSearch(context.Context, PrmObjectSearch) (*ResObjectSearch, error) { func (m *mockClient) objectSearch(context.Context, PrmObjectSearch) (ResObjectSearch, error) {
return nil, nil return ResObjectSearch{}, nil
} }
func (m *mockClient) sessionCreate(context.Context, prmCreateSession) (*resCreateSession, error) { func (m *mockClient) sessionCreate(context.Context, prmCreateSession) (resCreateSession, error) {
if m.errorOnCreateSession { if m.errorOnCreateSession {
return nil, m.handleError(nil, errors.New("error")) return resCreateSession{}, m.handleError(nil, errors.New("error"))
} }
tok := newToken(m.key) tok := newToken(m.key)
@ -151,7 +155,7 @@ func (m *mockClient) sessionCreate(context.Context, prmCreateSession) (*resCreat
var v2tok sessionv2.Token var v2tok sessionv2.Token
tok.WriteToV2(&v2tok) tok.WriteToV2(&v2tok)
return &resCreateSession{ return resCreateSession{
id: v2tok.GetBody().GetID(), id: v2tok.GetBody().GetID(),
sessionKey: v2tok.GetBody().GetSessionKey(), sessionKey: v2tok.GetBody().GetSessionKey(),
}, nil }, nil

View file

@ -37,37 +37,37 @@ import (
// Others are expected to be for test purposes only. // Others are expected to be for test purposes only.
type client interface { type client interface {
// see clientWrapper.balanceGet. // see clientWrapper.balanceGet.
balanceGet(context.Context, PrmBalanceGet) (*accounting.Decimal, error) balanceGet(context.Context, PrmBalanceGet) (accounting.Decimal, error)
// see clientWrapper.containerPut. // see clientWrapper.containerPut.
containerPut(context.Context, PrmContainerPut) (*cid.ID, error) containerPut(context.Context, PrmContainerPut) (cid.ID, error)
// see clientWrapper.containerGet. // see clientWrapper.containerGet.
containerGet(context.Context, PrmContainerGet) (*container.Container, error) containerGet(context.Context, PrmContainerGet) (container.Container, error)
// see clientWrapper.containerList. // see clientWrapper.containerList.
containerList(context.Context, PrmContainerList) ([]cid.ID, error) containerList(context.Context, PrmContainerList) ([]cid.ID, error)
// see clientWrapper.containerDelete. // see clientWrapper.containerDelete.
containerDelete(context.Context, PrmContainerDelete) error containerDelete(context.Context, PrmContainerDelete) error
// see clientWrapper.containerEACL. // see clientWrapper.containerEACL.
containerEACL(context.Context, PrmContainerEACL) (*eacl.Table, error) containerEACL(context.Context, PrmContainerEACL) (eacl.Table, error)
// see clientWrapper.containerSetEACL. // see clientWrapper.containerSetEACL.
containerSetEACL(context.Context, PrmContainerSetEACL) error containerSetEACL(context.Context, PrmContainerSetEACL) error
// see clientWrapper.endpointInfo. // see clientWrapper.endpointInfo.
endpointInfo(context.Context, prmEndpointInfo) (*netmap.NodeInfo, error) endpointInfo(context.Context, prmEndpointInfo) (netmap.NodeInfo, error)
// see clientWrapper.networkInfo. // see clientWrapper.networkInfo.
networkInfo(context.Context, prmNetworkInfo) (*netmap.NetworkInfo, error) networkInfo(context.Context, prmNetworkInfo) (netmap.NetworkInfo, error)
// see clientWrapper.objectPut. // see clientWrapper.objectPut.
objectPut(context.Context, PrmObjectPut) (*oid.ID, error) objectPut(context.Context, PrmObjectPut) (oid.ID, error)
// see clientWrapper.objectDelete. // see clientWrapper.objectDelete.
objectDelete(context.Context, PrmObjectDelete) error objectDelete(context.Context, PrmObjectDelete) error
// see clientWrapper.objectGet. // see clientWrapper.objectGet.
objectGet(context.Context, PrmObjectGet) (*ResGetObject, error) objectGet(context.Context, PrmObjectGet) (ResGetObject, error)
// see clientWrapper.objectHead. // see clientWrapper.objectHead.
objectHead(context.Context, PrmObjectHead) (*object.Object, error) objectHead(context.Context, PrmObjectHead) (object.Object, error)
// see clientWrapper.objectRange. // see clientWrapper.objectRange.
objectRange(context.Context, PrmObjectRange) (*ResObjectRange, error) objectRange(context.Context, PrmObjectRange) (ResObjectRange, error)
// see clientWrapper.objectSearch. // see clientWrapper.objectSearch.
objectSearch(context.Context, PrmObjectSearch) (*ResObjectSearch, error) objectSearch(context.Context, PrmObjectSearch) (ResObjectSearch, error)
// see clientWrapper.sessionCreate. // see clientWrapper.sessionCreate.
sessionCreate(context.Context, prmCreateSession) (*resCreateSession, error) sessionCreate(context.Context, prmCreateSession) (resCreateSession, error)
clientStatus clientStatus
} }
@ -273,8 +273,7 @@ func newWrapper(prm wrapperPrm) (*clientWrapper, error) {
} }
// balanceGet invokes sdkClient.BalanceGet parse response status to error and return result as is. // balanceGet invokes sdkClient.BalanceGet parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (accounting.Decimal, error) {
func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (*accounting.Decimal, error) {
var cliPrm sdkClient.PrmBalanceGet var cliPrm sdkClient.PrmBalanceGet
cliPrm.SetAccount(prm.account) cliPrm.SetAccount(prm.account)
@ -286,17 +285,15 @@ func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (*acc
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("balance get on client: %w", err) return accounting.Decimal{}, fmt.Errorf("balance get on client: %w", err)
} }
bal := res.Amount() return res.Amount(), nil
return &bal, nil
} }
// containerPut invokes sdkClient.ContainerPut parse response status to error and return result as is. // containerPut invokes sdkClient.ContainerPut parse response status to error and return result as is.
// It also waits for the container to appear on the network. // It also waits for the container to appear on the network.
func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (*cid.ID, error) { func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (cid.ID, error) {
start := time.Now() start := time.Now()
res, err := c.client.ContainerPut(ctx, prm.prmClient) res, err := c.client.ContainerPut(ctx, prm.prmClient)
c.incRequests(time.Since(start), methodContainerPut) c.incRequests(time.Since(start), methodContainerPut)
@ -305,7 +302,7 @@ func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("container put on client: %w", err) return cid.ID{}, fmt.Errorf("container put on client: %w", err)
} }
if !prm.waitParamsSet { if !prm.waitParamsSet {
@ -316,15 +313,14 @@ func (c *clientWrapper) containerPut(ctx context.Context, prm PrmContainerPut) (
err = waitForContainerPresence(ctx, c, idCnr, &prm.waitParams) err = waitForContainerPresence(ctx, c, idCnr, &prm.waitParams)
if err = c.handleError(nil, err); err != nil { if err = c.handleError(nil, err); err != nil {
return nil, fmt.Errorf("wait container presence on client: %w", err) return cid.ID{}, fmt.Errorf("wait container presence on client: %w", err)
} }
return &idCnr, nil return idCnr, nil
} }
// containerGet invokes sdkClient.ContainerGet parse response status to error and return result as is. // containerGet invokes sdkClient.ContainerGet parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) containerGet(ctx context.Context, prm PrmContainerGet) (container.Container, error) {
func (c *clientWrapper) containerGet(ctx context.Context, prm PrmContainerGet) (*container.Container, error) {
var cliPrm sdkClient.PrmContainerGet var cliPrm sdkClient.PrmContainerGet
cliPrm.SetContainer(prm.cnrID) cliPrm.SetContainer(prm.cnrID)
@ -336,11 +332,10 @@ func (c *clientWrapper) containerGet(ctx context.Context, prm PrmContainerGet) (
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("container get on client: %w", err) return container.Container{}, fmt.Errorf("container get on client: %w", err)
} }
cnr := res.Container() return res.Container(), nil
return &cnr, nil
} }
// containerList invokes sdkClient.ContainerList parse response status to error and return result as is. // containerList invokes sdkClient.ContainerList parse response status to error and return result as is.
@ -389,8 +384,7 @@ func (c *clientWrapper) containerDelete(ctx context.Context, prm PrmContainerDel
} }
// containerEACL invokes sdkClient.ContainerEACL parse response status to error and return result as is. // containerEACL invokes sdkClient.ContainerEACL parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) containerEACL(ctx context.Context, prm PrmContainerEACL) (eacl.Table, error) {
func (c *clientWrapper) containerEACL(ctx context.Context, prm PrmContainerEACL) (*eacl.Table, error) {
var cliPrm sdkClient.PrmContainerEACL var cliPrm sdkClient.PrmContainerEACL
cliPrm.SetContainer(prm.cnrID) cliPrm.SetContainer(prm.cnrID)
@ -402,12 +396,10 @@ func (c *clientWrapper) containerEACL(ctx context.Context, prm PrmContainerEACL)
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("get eacl on client: %w", err) return eacl.Table{}, fmt.Errorf("get eacl on client: %w", err)
} }
eACL := res.Table() return res.Table(), nil
return &eACL, nil
} }
// containerSetEACL invokes sdkClient.ContainerSetEACL parse response status to error. // containerSetEACL invokes sdkClient.ContainerSetEACL parse response status to error.
@ -449,8 +441,7 @@ func (c *clientWrapper) containerSetEACL(ctx context.Context, prm PrmContainerSe
} }
// endpointInfo invokes sdkClient.EndpointInfo parse response status to error and return result as is. // endpointInfo invokes sdkClient.EndpointInfo parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) endpointInfo(ctx context.Context, _ prmEndpointInfo) (netmap.NodeInfo, error) {
func (c *clientWrapper) endpointInfo(ctx context.Context, _ prmEndpointInfo) (*netmap.NodeInfo, error) {
start := time.Now() start := time.Now()
res, err := c.client.EndpointInfo(ctx, sdkClient.PrmEndpointInfo{}) res, err := c.client.EndpointInfo(ctx, sdkClient.PrmEndpointInfo{})
c.incRequests(time.Since(start), methodEndpointInfo) c.incRequests(time.Since(start), methodEndpointInfo)
@ -459,17 +450,14 @@ func (c *clientWrapper) endpointInfo(ctx context.Context, _ prmEndpointInfo) (*n
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("endpoint info on client: %w", err) return netmap.NodeInfo{}, fmt.Errorf("endpoint info on client: %w", err)
} }
nodeInfo := res.NodeInfo() return res.NodeInfo(), nil
return &nodeInfo, nil
} }
// networkInfo invokes sdkClient.NetworkInfo parse response status to error and return result as is. // networkInfo invokes sdkClient.NetworkInfo parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) networkInfo(ctx context.Context, _ prmNetworkInfo) (netmap.NetworkInfo, error) {
func (c *clientWrapper) networkInfo(ctx context.Context, _ prmNetworkInfo) (*netmap.NetworkInfo, error) {
start := time.Now() start := time.Now()
res, err := c.client.NetworkInfo(ctx, sdkClient.PrmNetworkInfo{}) res, err := c.client.NetworkInfo(ctx, sdkClient.PrmNetworkInfo{})
c.incRequests(time.Since(start), methodNetworkInfo) c.incRequests(time.Since(start), methodNetworkInfo)
@ -478,17 +466,14 @@ func (c *clientWrapper) networkInfo(ctx context.Context, _ prmNetworkInfo) (*net
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("network info on client: %w", err) return netmap.NetworkInfo{}, fmt.Errorf("network info on client: %w", err)
} }
netInfo := res.Info() return res.Info(), nil
return &netInfo, nil
} }
// objectPut writes object to NeoFS. // objectPut writes object to NeoFS.
// Exactly one return value is non-nil. func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (oid.ID, error) {
func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (*oid.ID, error) {
var cliPrm sdkClient.PrmObjectPutInit var cliPrm sdkClient.PrmObjectPutInit
cliPrm.SetCopiesNumber(prm.copiesNumber) cliPrm.SetCopiesNumber(prm.copiesNumber)
@ -496,7 +481,7 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (*oid.I
wObj, err := c.client.ObjectPutInit(ctx, cliPrm) wObj, err := c.client.ObjectPutInit(ctx, cliPrm)
c.incRequests(time.Since(start), methodObjectPut) c.incRequests(time.Since(start), methodObjectPut)
if err = c.handleError(nil, err); err != nil { if err = c.handleError(nil, err); err != nil {
return nil, fmt.Errorf("init writing on API client: %w", err) return oid.ID{}, fmt.Errorf("init writing on API client: %w", err)
} }
if prm.stoken != nil { if prm.stoken != nil {
@ -550,7 +535,7 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (*oid.I
break break
} }
return nil, fmt.Errorf("read payload: %w", c.handleError(nil, err)) return oid.ID{}, fmt.Errorf("read payload: %w", c.handleError(nil, err))
} }
} }
} }
@ -561,12 +546,10 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (*oid.I
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { // here err already carries both status and client errors if err = c.handleError(st, err); err != nil { // here err already carries both status and client errors
return nil, fmt.Errorf("client failure: %w", err) return oid.ID{}, fmt.Errorf("client failure: %w", err)
} }
id := res.StoredObjectID() return res.StoredObjectID(), nil
return &id, nil
} }
// objectDelete invokes sdkClient.ObjectDelete parse response status to error. // objectDelete invokes sdkClient.ObjectDelete parse response status to error.
@ -601,8 +584,7 @@ func (c *clientWrapper) objectDelete(ctx context.Context, prm PrmObjectDelete) e
} }
// objectGet returns reader for object. // objectGet returns reader for object.
// Exactly one return value is non-nil. func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (ResGetObject, error) {
func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (*ResGetObject, error) {
var cliPrm sdkClient.PrmObjectGet var cliPrm sdkClient.PrmObjectGet
cliPrm.FromContainer(prm.addr.Container()) cliPrm.FromContainer(prm.addr.Container())
cliPrm.ByID(prm.addr.Object()) cliPrm.ByID(prm.addr.Object())
@ -619,7 +601,7 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (*ResGe
rObj, err := c.client.ObjectGetInit(ctx, cliPrm) rObj, err := c.client.ObjectGetInit(ctx, cliPrm)
if err = c.handleError(nil, err); err != nil { if err = c.handleError(nil, err); err != nil {
return nil, fmt.Errorf("init object reading on client: %w", err) return ResGetObject{}, fmt.Errorf("init object reading on client: %w", err)
} }
if prm.key != nil { if prm.key != nil {
@ -636,7 +618,7 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (*ResGe
st = rObjRes.Status() st = rObjRes.Status()
} }
err = c.handleError(st, err) err = c.handleError(st, err)
return nil, fmt.Errorf("read header: %w", err) return res, fmt.Errorf("read header: %w", err)
} }
res.Payload = &objectReadCloser{ res.Payload = &objectReadCloser{
@ -646,12 +628,11 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (*ResGe
}, },
} }
return &res, nil return res, nil
} }
// objectHead invokes sdkClient.ObjectHead parse response status to error and return result as is. // objectHead invokes sdkClient.ObjectHead parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (object.Object, error) {
func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (*object.Object, error) {
var cliPrm sdkClient.PrmObjectHead var cliPrm sdkClient.PrmObjectHead
cliPrm.FromContainer(prm.addr.Container()) cliPrm.FromContainer(prm.addr.Container())
cliPrm.ByID(prm.addr.Object()) cliPrm.ByID(prm.addr.Object())
@ -678,18 +659,17 @@ func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (*obj
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("read object header via client: %w", err) return obj, fmt.Errorf("read object header via client: %w", err)
} }
if !res.ReadHeader(&obj) { if !res.ReadHeader(&obj) {
return nil, errors.New("missing object header in response") return obj, errors.New("missing object header in response")
} }
return &obj, nil return obj, nil
} }
// objectRange returns object range reader. // objectRange returns object range reader.
// Exactly one return value is non-nil. func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (ResObjectRange, error) {
func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (*ResObjectRange, error) {
var cliPrm sdkClient.PrmObjectRange var cliPrm sdkClient.PrmObjectRange
cliPrm.FromContainer(prm.addr.Container()) cliPrm.FromContainer(prm.addr.Container())
cliPrm.ByID(prm.addr.Object()) cliPrm.ByID(prm.addr.Object())
@ -708,13 +688,13 @@ func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (*R
res, err := c.client.ObjectRangeInit(ctx, cliPrm) res, err := c.client.ObjectRangeInit(ctx, cliPrm)
c.incRequests(time.Since(start), methodObjectRange) c.incRequests(time.Since(start), methodObjectRange)
if err = c.handleError(nil, err); err != nil { if err = c.handleError(nil, err); err != nil {
return nil, fmt.Errorf("init payload range reading on client: %w", err) return ResObjectRange{}, fmt.Errorf("init payload range reading on client: %w", err)
} }
if prm.key != nil { if prm.key != nil {
res.UseKey(*prm.key) res.UseKey(*prm.key)
} }
return &ResObjectRange{ return ResObjectRange{
payload: res, payload: res,
elapsedTimeCallback: func(elapsed time.Duration) { elapsedTimeCallback: func(elapsed time.Duration) {
c.incRequests(elapsed, methodObjectRange) c.incRequests(elapsed, methodObjectRange)
@ -723,8 +703,7 @@ func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (*R
} }
// objectSearch invokes sdkClient.ObjectSearchInit parse response status to error and return result as is. // objectSearch invokes sdkClient.ObjectSearchInit parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) objectSearch(ctx context.Context, prm PrmObjectSearch) (ResObjectSearch, error) {
func (c *clientWrapper) objectSearch(ctx context.Context, prm PrmObjectSearch) (*ResObjectSearch, error) {
var cliPrm sdkClient.PrmObjectSearch var cliPrm sdkClient.PrmObjectSearch
cliPrm.InContainer(prm.cnrID) cliPrm.InContainer(prm.cnrID)
@ -740,18 +719,17 @@ func (c *clientWrapper) objectSearch(ctx context.Context, prm PrmObjectSearch) (
res, err := c.client.ObjectSearchInit(ctx, cliPrm) res, err := c.client.ObjectSearchInit(ctx, cliPrm)
if err = c.handleError(nil, err); err != nil { if err = c.handleError(nil, err); err != nil {
return nil, fmt.Errorf("init object searching on client: %w", err) return ResObjectSearch{}, fmt.Errorf("init object searching on client: %w", err)
} }
if prm.key != nil { if prm.key != nil {
res.UseKey(*prm.key) res.UseKey(*prm.key)
} }
return &ResObjectSearch{r: res}, nil return ResObjectSearch{r: res}, nil
} }
// sessionCreate invokes sdkClient.SessionCreate parse response status to error and return result as is. // sessionCreate invokes sdkClient.SessionCreate parse response status to error and return result as is.
// Exactly one return value is non-nil. func (c *clientWrapper) sessionCreate(ctx context.Context, prm prmCreateSession) (resCreateSession, error) {
func (c *clientWrapper) sessionCreate(ctx context.Context, prm prmCreateSession) (*resCreateSession, error) {
var cliPrm sdkClient.PrmSessionCreate var cliPrm sdkClient.PrmSessionCreate
cliPrm.SetExp(prm.exp) cliPrm.SetExp(prm.exp)
cliPrm.UseKey(prm.key) cliPrm.UseKey(prm.key)
@ -764,10 +742,10 @@ func (c *clientWrapper) sessionCreate(ctx context.Context, prm prmCreateSession)
st = res.Status() st = res.Status()
} }
if err = c.handleError(st, err); err != nil { if err = c.handleError(st, err); err != nil {
return nil, fmt.Errorf("session creation on client: %w", err) return resCreateSession{}, fmt.Errorf("session creation on client: %w", err)
} }
return &resCreateSession{ return resCreateSession{
id: res.ID(), id: res.ID(),
sessionKey: res.PublicKey(), sessionKey: res.PublicKey(),
}, nil }, nil
@ -1797,7 +1775,9 @@ func (p *Pool) fillAppropriateKey(prm *prmCommon) {
} }
// PutObject writes an object through a remote server using NeoFS API protocol. // PutObject writes an object through a remote server using NeoFS API protocol.
func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (*oid.ID, error) { //
// Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (oid.ID, error) {
cnr, _ := prm.hdr.ContainerID() cnr, _ := prm.hdr.ContainerID()
var prmCtx prmContext var prmCtx prmContext
@ -1812,13 +1792,13 @@ func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (*oid.ID, error)
ctxCall.Context = ctx ctxCall.Context = ctx
if err := p.initCallContext(&ctxCall, prm.prmCommon, prmCtx); err != nil { if err := p.initCallContext(&ctxCall, prm.prmCommon, prmCtx); err != nil {
return nil, fmt.Errorf("init call context: %w", err) return oid.ID{}, fmt.Errorf("init call context: %w", err)
} }
if ctxCall.sessionDefault { if ctxCall.sessionDefault {
ctxCall.sessionTarget = prm.UseSession ctxCall.sessionTarget = prm.UseSession
if err := p.openDefaultSession(&ctxCall); err != nil { if err := p.openDefaultSession(&ctxCall); err != nil {
return nil, fmt.Errorf("open default session: %w", err) return oid.ID{}, fmt.Errorf("open default session: %w", err)
} }
} }
@ -1826,7 +1806,7 @@ func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (*oid.ID, error)
if err != nil { if err != nil {
// removes session token from cache in case of token error // removes session token from cache in case of token error
p.checkSessionTokenErr(err, ctxCall.endpoint) p.checkSessionTokenErr(err, ctxCall.endpoint)
return nil, fmt.Errorf("init writing on API client: %w", err) return id, fmt.Errorf("init writing on API client: %w", err)
} }
return id, nil return id, nil
@ -1890,8 +1870,9 @@ type ResGetObject struct {
} }
// GetObject reads object header and initiates reading an object payload through a remote server using NeoFS API protocol. // GetObject reads object header and initiates reading an object payload through a remote server using NeoFS API protocol.
// Exactly one return value is non-nil. //
func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (*ResGetObject, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (ResGetObject, error) {
var prmCtx prmContext var prmCtx prmContext
prmCtx.useDefaultSession() prmCtx.useDefaultSession()
prmCtx.useVerb(session.VerbObjectGet) prmCtx.useVerb(session.VerbObjectGet)
@ -1903,12 +1884,13 @@ func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (*ResGetObject,
cc.Context = ctx cc.Context = ctx
cc.sessionTarget = prm.UseSession cc.sessionTarget = prm.UseSession
var res ResGetObject
err := p.initCallContext(&cc, prm.prmCommon, prmCtx) err := p.initCallContext(&cc, prm.prmCommon, prmCtx)
if err != nil { if err != nil {
return nil, err return res, err
} }
var res *ResGetObject
return res, p.call(&cc, func() error { return res, p.call(&cc, func() error {
res, err = cc.client.objectGet(ctx, prm) res, err = cc.client.objectGet(ctx, prm)
return err return err
@ -1916,8 +1898,9 @@ func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (*ResGetObject,
} }
// HeadObject reads object header through a remote server using NeoFS API protocol. // HeadObject reads object header through a remote server using NeoFS API protocol.
// Exactly one return value is non-nil. //
func (p *Pool) HeadObject(ctx context.Context, prm PrmObjectHead) (*object.Object, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) HeadObject(ctx context.Context, prm PrmObjectHead) (object.Object, error) {
var prmCtx prmContext var prmCtx prmContext
prmCtx.useDefaultSession() prmCtx.useDefaultSession()
prmCtx.useVerb(session.VerbObjectHead) prmCtx.useVerb(session.VerbObjectHead)
@ -1930,12 +1913,13 @@ func (p *Pool) HeadObject(ctx context.Context, prm PrmObjectHead) (*object.Objec
cc.Context = ctx cc.Context = ctx
cc.sessionTarget = prm.UseSession cc.sessionTarget = prm.UseSession
var obj object.Object
err := p.initCallContext(&cc, prm.prmCommon, prmCtx) err := p.initCallContext(&cc, prm.prmCommon, prmCtx)
if err != nil { if err != nil {
return nil, err return obj, err
} }
var obj *object.Object
return obj, p.call(&cc, func() error { return obj, p.call(&cc, func() error {
obj, err = cc.client.objectHead(ctx, prm) obj, err = cc.client.objectHead(ctx, prm)
return err return err
@ -1969,8 +1953,9 @@ func (x *ResObjectRange) Close() error {
// ObjectRange initiates reading an object's payload range through a remote // ObjectRange initiates reading an object's payload range through a remote
// server using NeoFS API protocol. // server using NeoFS API protocol.
// Exactly one return value is non-nil. //
func (p *Pool) ObjectRange(ctx context.Context, prm PrmObjectRange) (*ResObjectRange, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) ObjectRange(ctx context.Context, prm PrmObjectRange) (ResObjectRange, error) {
var prmCtx prmContext var prmCtx prmContext
prmCtx.useDefaultSession() prmCtx.useDefaultSession()
prmCtx.useVerb(session.VerbObjectRange) prmCtx.useVerb(session.VerbObjectRange)
@ -1982,13 +1967,13 @@ func (p *Pool) ObjectRange(ctx context.Context, prm PrmObjectRange) (*ResObjectR
cc.Context = ctx cc.Context = ctx
cc.sessionTarget = prm.UseSession cc.sessionTarget = prm.UseSession
var res ResObjectRange
err := p.initCallContext(&cc, prm.prmCommon, prmCtx) err := p.initCallContext(&cc, prm.prmCommon, prmCtx)
if err != nil { if err != nil {
return nil, err return res, err
} }
var res *ResObjectRange
return res, p.call(&cc, func() error { return res, p.call(&cc, func() error {
res, err = cc.client.objectRange(ctx, prm) res, err = cc.client.objectRange(ctx, prm)
return err return err
@ -2034,10 +2019,10 @@ func (x *ResObjectSearch) Close() {
// SearchObjects initiates object selection through a remote server using NeoFS API protocol. // SearchObjects initiates object selection through a remote server using NeoFS API protocol.
// //
// The call only opens the transmission channel, explicit fetching of matched objects // The call only opens the transmission channel, explicit fetching of matched objects
// is done using the ResObjectSearch. Exactly one return value is non-nil. // is done using the ResObjectSearch. Resulting reader must be finally closed.
// Resulting reader must be finally closed. //
// Exactly one return value is non-nil. // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (*ResObjectSearch, error) { func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (ResObjectSearch, error) {
var prmCtx prmContext var prmCtx prmContext
prmCtx.useDefaultSession() prmCtx.useDefaultSession()
prmCtx.useVerb(session.VerbObjectSearch) prmCtx.useVerb(session.VerbObjectSearch)
@ -2050,13 +2035,13 @@ func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (*ResObje
cc.Context = ctx cc.Context = ctx
cc.sessionTarget = prm.UseSession cc.sessionTarget = prm.UseSession
var res ResObjectSearch
err := p.initCallContext(&cc, prm.prmCommon, prmCtx) err := p.initCallContext(&cc, prm.prmCommon, prmCtx)
if err != nil { if err != nil {
return nil, err return res, err
} }
var res *ResObjectSearch
return res, p.call(&cc, func() error { return res, p.call(&cc, func() error {
res, err = cc.client.objectSearch(ctx, prm) res, err = cc.client.objectSearch(ctx, prm)
return err return err
@ -2070,21 +2055,24 @@ func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (*ResObje
// waiting timeout: 120s // waiting timeout: 120s
// //
// Success can be verified by reading by identifier (see GetContainer). // Success can be verified by reading by identifier (see GetContainer).
func (p *Pool) PutContainer(ctx context.Context, prm PrmContainerPut) (*cid.ID, error) { //
// Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) PutContainer(ctx context.Context, prm PrmContainerPut) (cid.ID, error) {
cp, err := p.connection() cp, err := p.connection()
if err != nil { if err != nil {
return nil, err return cid.ID{}, err
} }
return cp.containerPut(ctx, prm) return cp.containerPut(ctx, prm)
} }
// GetContainer reads NeoFS container by ID. // GetContainer reads NeoFS container by ID.
// Exactly one return value is non-nil. //
func (p *Pool) GetContainer(ctx context.Context, prm PrmContainerGet) (*container.Container, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) GetContainer(ctx context.Context, prm PrmContainerGet) (container.Container, error) {
cp, err := p.connection() cp, err := p.connection()
if err != nil { if err != nil {
return nil, err return container.Container{}, err
} }
return cp.containerGet(ctx, prm) return cp.containerGet(ctx, prm)
@ -2117,11 +2105,12 @@ func (p *Pool) DeleteContainer(ctx context.Context, prm PrmContainerDelete) erro
} }
// GetEACL reads eACL table of the NeoFS container. // GetEACL reads eACL table of the NeoFS container.
// Exactly one return value is non-nil. //
func (p *Pool) GetEACL(ctx context.Context, prm PrmContainerEACL) (*eacl.Table, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) GetEACL(ctx context.Context, prm PrmContainerEACL) (eacl.Table, error) {
cp, err := p.connection() cp, err := p.connection()
if err != nil { if err != nil {
return nil, err return eacl.Table{}, err
} }
return cp.containerEACL(ctx, prm) return cp.containerEACL(ctx, prm)
@ -2144,11 +2133,12 @@ func (p *Pool) SetEACL(ctx context.Context, prm PrmContainerSetEACL) error {
} }
// Balance requests current balance of the NeoFS account. // Balance requests current balance of the NeoFS account.
// Exactly one return value is non-nil. //
func (p *Pool) Balance(ctx context.Context, prm PrmBalanceGet) (*accounting.Decimal, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) Balance(ctx context.Context, prm PrmBalanceGet) (accounting.Decimal, error) {
cp, err := p.connection() cp, err := p.connection()
if err != nil { if err != nil {
return nil, err return accounting.Decimal{}, err
} }
return cp.balanceGet(ctx, prm) return cp.balanceGet(ctx, prm)
@ -2196,7 +2186,7 @@ func waitForEACLPresence(ctx context.Context, cli client, cnrID *cid.ID, table *
return waitFor(ctx, waitParams, func(ctx context.Context) bool { return waitFor(ctx, waitParams, func(ctx context.Context) bool {
eaclTable, err := cli.containerEACL(ctx, prm) eaclTable, err := cli.containerEACL(ctx, prm)
if err == nil { if err == nil {
return eacl.EqualTables(*table, *eaclTable) return eacl.EqualTables(*table, eaclTable)
} }
return false return false
}) })
@ -2239,11 +2229,12 @@ func waitFor(ctx context.Context, params *WaitParams, condition func(context.Con
} }
// NetworkInfo requests information about the NeoFS network of which the remote server is a part. // NetworkInfo requests information about the NeoFS network of which the remote server is a part.
// Exactly one return value is non-nil. //
func (p *Pool) NetworkInfo(ctx context.Context) (*netmap.NetworkInfo, error) { // Main return value MUST NOT be processed on an erroneous return.
func (p *Pool) NetworkInfo(ctx context.Context) (netmap.NetworkInfo, error) {
cp, err := p.connection() cp, err := p.connection()
if err != nil { if err != nil {
return nil, err return netmap.NetworkInfo{}, err
} }
return cp.networkInfo(ctx, prmNetworkInfo{}) return cp.networkInfo(ctx, prmNetworkInfo{})
@ -2269,11 +2260,7 @@ func SyncContainerWithNetwork(ctx context.Context, cnr *container.Container, p *
return fmt.Errorf("network info: %w", err) return fmt.Errorf("network info: %w", err)
} }
if ni == nil { container.ApplyNetworkConfig(cnr, ni)
return errors.New("empty network info")
}
container.ApplyNetworkConfig(cnr, *ni)
return nil return nil
} }

View file

@ -48,12 +48,12 @@ type clientMock struct {
err error err error
} }
func (c *clientMock) endpointInfo(context.Context, prmEndpointInfo) (*netmap.NodeInfo, error) { func (c *clientMock) endpointInfo(context.Context, prmEndpointInfo) (netmap.NodeInfo, error) {
return nil, nil return netmap.NodeInfo{}, nil
} }
func (c *clientMock) networkInfo(context.Context, prmNetworkInfo) (*netmap.NetworkInfo, error) { func (c *clientMock) networkInfo(context.Context, prmNetworkInfo) (netmap.NetworkInfo, error) {
return nil, nil return netmap.NetworkInfo{}, nil
} }
func newNetmapMock(name string, needErr bool) *clientMock { func newNetmapMock(name string, needErr bool) *clientMock {