frostfs-node/pkg/services/object/util/prm.go
Leonard Lyubich 1e170c3812 [#234] services/object: Support netmap epoch and lookup dead in read ops
Support processing of NetmapEpoch and NetmapLookupDepth X-headers when
processing object read operations. Placement for operations
Get/Head/GetRange/GetRangeHash/Search is built for the epoch specified in
NetmapEpoch X-header (by default latest). Also the specified operations are
processed until success is achieved for network maps from the past up to
NetmapLookupDepth value. Behavior for default values (zero or missing) left
unchanged.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2021-01-12 19:19:11 +03:00

211 lines
3.9 KiB
Go

package util
import (
"crypto/ecdsa"
"strconv"
"github.com/nspcc-dev/neofs-api-go/pkg"
"github.com/nspcc-dev/neofs-api-go/pkg/client"
"github.com/nspcc-dev/neofs-api-go/pkg/token"
"github.com/nspcc-dev/neofs-api-go/v2/session"
)
type CommonPrm struct {
local bool
netmapEpoch, netmapLookupDepth uint64
token *token.SessionToken
bearer *token.BearerToken
key *ecdsa.PrivateKey
callOpts []client.CallOption
}
type remoteCallOpts struct {
opts []client.CallOption
}
type DynamicCallOption func(*remoteCallOpts)
func (p *CommonPrm) WithLocalOnly(v bool) *CommonPrm {
if p != nil {
p.local = v
}
return p
}
func (p *CommonPrm) LocalOnly() bool {
if p != nil {
return p.local
}
return false
}
func (p *CommonPrm) WithSessionToken(token *token.SessionToken) *CommonPrm {
if p != nil {
p.token = token
}
return p
}
func (p *CommonPrm) WithBearerToken(token *token.BearerToken) *CommonPrm {
if p != nil {
p.bearer = token
}
return p
}
// WithPrivateKey sets private key to use during execution.
func (p *CommonPrm) WithPrivateKey(key *ecdsa.PrivateKey) *CommonPrm {
if p != nil {
p.key = key
}
return p
}
// PrivateKey returns private key to use during execution.
func (p *CommonPrm) PrivateKey() *ecdsa.PrivateKey {
if p != nil {
return p.key
}
return nil
}
// WithRemoteCallOptions sets call options remote remote client calls.
func (p *CommonPrm) WithRemoteCallOptions(opts ...client.CallOption) *CommonPrm {
if p != nil {
p.callOpts = opts
}
return p
}
// RemoteCallOptions return call options for remote client calls.
func (p *CommonPrm) RemoteCallOptions(dynamic ...DynamicCallOption) []client.CallOption {
if p != nil {
o := &remoteCallOpts{
opts: p.callOpts,
}
for _, applier := range dynamic {
applier(o)
}
return o.opts
}
return nil
}
func WithNetmapEpoch(v uint64) DynamicCallOption {
return func(o *remoteCallOpts) {
xHdr := pkg.NewXHeader()
xHdr.SetKey(session.XHeaderNetmapEpoch)
xHdr.SetValue(strconv.FormatUint(v, 10))
o.opts = append(o.opts, client.WithXHeader(xHdr))
}
}
func (p *CommonPrm) SessionToken() *token.SessionToken {
if p != nil {
return p.token
}
return nil
}
func (p *CommonPrm) BearerToken() *token.BearerToken {
if p != nil {
return p.bearer
}
return nil
}
func (p *CommonPrm) NetmapEpoch() uint64 {
if p != nil {
return p.netmapEpoch
}
return 0
}
func (p *CommonPrm) NetmapLookupDepth() uint64 {
if p != nil {
return p.netmapLookupDepth
}
return 0
}
func (p *CommonPrm) SetNetmapLookupDepth(v uint64) {
if p != nil {
p.netmapLookupDepth = v
}
}
func CommonPrmFromV2(req interface {
GetMetaHeader() *session.RequestMetaHeader
}) (*CommonPrm, error) {
meta := req.GetMetaHeader()
xHdrs := meta.GetXHeaders()
const staticOptNum = 3
prm := &CommonPrm{
local: meta.GetTTL() <= 1, // FIXME: use constant
token: nil,
bearer: nil,
callOpts: make([]client.CallOption, 0, staticOptNum+len(xHdrs)),
}
prm.callOpts = append(prm.callOpts, client.WithTTL(meta.GetTTL()-1))
if tok := meta.GetSessionToken(); tok != nil {
prm.token = token.NewSessionTokenFromV2(tok)
prm.callOpts = append(prm.callOpts, client.WithSession(prm.token))
}
if tok := meta.GetBearerToken(); tok != nil {
prm.bearer = token.NewBearerTokenFromV2(tok)
prm.callOpts = append(prm.callOpts, client.WithBearer(prm.bearer))
}
for i := range xHdrs {
switch xHdrs[i].GetKey() {
case session.XHeaderNetmapEpoch:
var err error
prm.netmapEpoch, err = strconv.ParseUint(xHdrs[i].GetValue(), 10, 64)
if err != nil {
return nil, err
}
case session.XHeaderNetmapLookupDepth:
var err error
prm.netmapLookupDepth, err = strconv.ParseUint(xHdrs[i].GetValue(), 10, 64)
if err != nil {
return nil, err
}
default:
prm.callOpts = append(prm.callOpts,
client.WithXHeader(
pkg.NewXHeaderFromV2(xHdrs[i]),
),
)
}
}
return prm, nil
}