frostfs-node/pkg/services/object_manager/transport/storagegroup/sg.go

139 lines
4.2 KiB
Go
Raw Normal View History

2020-07-24 13:54:03 +00:00
package storagegroup
import (
"context"
"github.com/multiformats/go-multiaddr"
"github.com/nspcc-dev/neofs-api-go/hash"
"github.com/nspcc-dev/neofs-api-go/object"
"github.com/nspcc-dev/neofs-api-go/refs"
"github.com/nspcc-dev/neofs-api-go/service"
"github.com/nspcc-dev/neofs-api-go/storagegroup"
2020-07-24 13:54:03 +00:00
"github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/transport"
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
"github.com/pkg/errors"
"go.uber.org/zap"
)
type (
// StorageGroupInfoReceiverParams groups the parameters of
// storage group information receiver.
StorageGroupInfoReceiverParams struct {
2020-07-24 13:54:03 +00:00
SelectiveContainerExecutor transport.SelectiveContainerExecutor
Logger *zap.Logger
}
sgInfoRecv struct {
2020-07-24 13:54:03 +00:00
executor transport.SelectiveContainerExecutor
log *zap.Logger
}
)
const locationFinderInstanceFailMsg = "could not create object location finder"
// ErrIncompleteSGInfo is returned by storage group information receiver
// that could not receive full information.
2020-07-24 13:54:03 +00:00
var ErrIncompleteSGInfo = errors.New("could not receive full storage group info")
// PublicSessionToken is a context key for SessionToken.
// FIXME: temp solution for cycle import fix.
// Unify with same const from transformer pkg.
const PublicSessionToken = "public token"
// BearerToken is a context key for BearerToken.
const BearerToken = "bearer token"
// ExtendedHeaders is a context key for X-headers.
const ExtendedHeaders = "extended headers"
2020-07-24 13:54:03 +00:00
func (s *sgInfoRecv) GetSGInfo(ctx context.Context, cid container.ID, group []object.ID) (*storagegroup.StorageGroup, error) {
var (
err error
res = new(storagegroup.StorageGroup)
hashList = make([]hash.Hash, 0, len(group))
)
m := make(map[string]struct{}, len(group))
for i := range group {
m[group[i].String()] = struct{}{}
}
// FIXME: hardcoded for simplicity.
// Function is called in next cases:
// - SG transformation on trusted node side (only in this case session token is needed);
// - SG info check on container nodes (token is not needed since system group has extra access);
// - data audit on inner ring nodes (same as previous).
var token service.SessionToken
if v, ok := ctx.Value(PublicSessionToken).(service.SessionToken); ok {
token = v
}
var bearer service.BearerToken
if v, ok := ctx.Value(BearerToken).(service.BearerToken); ok {
bearer = v
}
var extHdrs []service.ExtendedHeader
if v, ok := ctx.Value(ExtendedHeaders).([]service.ExtendedHeader); ok {
extHdrs = v
}
2020-07-24 13:54:03 +00:00
if err = s.executor.Head(ctx, &transport.HeadParams{
GetParams: transport.GetParams{
SelectiveParams: transport.SelectiveParams{
CID: cid,
TTL: service.SingleForwardingTTL,
IDList: group,
2020-07-24 13:54:03 +00:00
Breaker: func(addr refs.Address) (cFlag transport.ProgressControlFlag) {
if len(m) == 0 {
2020-07-24 13:54:03 +00:00
cFlag = transport.BreakProgress
} else if _, ok := m[addr.ObjectID.String()]; !ok {
2020-07-24 13:54:03 +00:00
cFlag = transport.NextAddress
}
return
},
Token: token,
Bearer: bearer,
ExtendedHeaders: extHdrs,
},
Handler: func(_ multiaddr.Multiaddr, obj *object.Object) {
_, hashHeader := obj.LastHeader(object.HeaderType(object.HomoHashHdr))
if hashHeader == nil {
return
}
hashList = append(hashList, hashHeader.Value.(*object.Header_HomoHash).HomoHash)
res.ValidationDataSize += obj.SystemHeader.PayloadLength
delete(m, obj.SystemHeader.ID.String())
},
},
FullHeaders: true,
}); err != nil {
return nil, err
} else if len(m) > 0 {
return nil, ErrIncompleteSGInfo
}
res.ValidationHash, err = hash.Concat(hashList)
return res, err
}
// NewStorageGroupInfoReceiver constructs storagegroup.InfoReceiver from SelectiveContainerExecutor.
func NewStorageGroupInfoReceiver(p StorageGroupInfoReceiverParams) (storagegroup.InfoReceiver, error) {
switch {
case p.Logger == nil:
2020-07-24 13:54:03 +00:00
return nil, errors.Wrap(logger.ErrNilLogger, locationFinderInstanceFailMsg)
case p.SelectiveContainerExecutor == nil:
2020-07-24 13:54:03 +00:00
return nil, errors.Wrap(errors.New("empty container handler"), locationFinderInstanceFailMsg)
}
return &sgInfoRecv{
executor: p.SelectiveContainerExecutor,
log: p.Logger,
}, nil
}