forked from TrueCloudLab/frostfs-node
137 lines
3.9 KiB
Go
137 lines
3.9 KiB
Go
|
package implementations
|
||
|
|
||
|
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"
|
||
|
"github.com/nspcc-dev/neofs-node/internal"
|
||
|
"github.com/pkg/errors"
|
||
|
"go.uber.org/zap"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
// StorageGroupInfoReceiverParams groups the parameters of
|
||
|
// storage group information receiver.
|
||
|
StorageGroupInfoReceiverParams struct {
|
||
|
SelectiveContainerExecutor SelectiveContainerExecutor
|
||
|
Logger *zap.Logger
|
||
|
}
|
||
|
|
||
|
sgInfoRecv struct {
|
||
|
executor 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.
|
||
|
const ErrIncompleteSGInfo = internal.Error("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"
|
||
|
|
||
|
func (s *sgInfoRecv) GetSGInfo(ctx context.Context, cid CID, group []ObjectID) (*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
|
||
|
}
|
||
|
|
||
|
if err = s.executor.Head(ctx, &HeadParams{
|
||
|
GetParams: GetParams{
|
||
|
SelectiveParams: SelectiveParams{
|
||
|
CID: cid,
|
||
|
TTL: service.SingleForwardingTTL,
|
||
|
IDList: group,
|
||
|
Breaker: func(addr refs.Address) (cFlag ProgressControlFlag) {
|
||
|
if len(m) == 0 {
|
||
|
cFlag = BreakProgress
|
||
|
} else if _, ok := m[addr.ObjectID.String()]; !ok {
|
||
|
cFlag = 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:
|
||
|
return nil, errors.Wrap(errEmptyLogger, locationFinderInstanceFailMsg)
|
||
|
case p.SelectiveContainerExecutor == nil:
|
||
|
return nil, errors.Wrap(errEmptyObjectsContainerHandler, locationFinderInstanceFailMsg)
|
||
|
}
|
||
|
|
||
|
return &sgInfoRecv{
|
||
|
executor: p.SelectiveContainerExecutor,
|
||
|
log: p.Logger,
|
||
|
}, nil
|
||
|
}
|