2023-04-20 10:57:45 +00:00
|
|
|
package getsvc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client"
|
|
|
|
"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"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement"
|
2023-04-21 15:21:46 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
2023-04-20 10:57:45 +00:00
|
|
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
|
|
|
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"
|
2023-04-21 15:21:46 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
2023-04-20 10:57:45 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type epochSource interface {
|
|
|
|
Epoch() (uint64, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type traverserGenerator interface {
|
|
|
|
GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type keyStorage interface {
|
|
|
|
GetKey(info *util.SessionInfo) (*ecdsa.PrivateKey, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type localStorageEngine interface {
|
|
|
|
Head(ctx context.Context, p engine.HeadPrm) (engine.HeadRes, error)
|
|
|
|
GetRange(ctx context.Context, p engine.RngPrm) (engine.RngRes, error)
|
|
|
|
Get(ctx context.Context, p engine.GetPrm) (engine.GetRes, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type clientConstructor interface {
|
2023-04-21 15:21:46 +00:00
|
|
|
Get(coreclient.NodeInfo) (coreclient.MultiAddressClient, error)
|
2023-04-20 10:57:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type remoteStorageConstructor interface {
|
2023-04-21 15:21:46 +00:00
|
|
|
Get(coreclient.NodeInfo) (remoteStorage, error)
|
2023-04-20 10:57:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type multiclientRemoteStorageConstructor struct {
|
|
|
|
clientConstructor clientConstructor
|
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
func (c *multiclientRemoteStorageConstructor) Get(info coreclient.NodeInfo) (remoteStorage, error) {
|
2023-04-20 10:57:45 +00:00
|
|
|
clt, err := c.clientConstructor.Get(info)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &multiaddressRemoteStorage{
|
|
|
|
client: clt,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type localStorage interface {
|
|
|
|
Head(ctx context.Context, address oid.Address, isRaw bool) (*objectSDK.Object, error)
|
|
|
|
Range(ctx context.Context, address oid.Address, rng *objectSDK.Range) (*objectSDK.Object, error)
|
|
|
|
Get(ctx context.Context, address oid.Address) (*objectSDK.Object, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
type engineLocalStorage struct {
|
|
|
|
engine localStorageEngine
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *engineLocalStorage) Head(ctx context.Context, address oid.Address, isRaw bool) (*objectSDK.Object, error) {
|
|
|
|
var headPrm engine.HeadPrm
|
|
|
|
headPrm.WithAddress(address)
|
|
|
|
headPrm.WithRaw(isRaw)
|
|
|
|
|
|
|
|
r, err := s.engine.Head(ctx, headPrm)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Header(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *engineLocalStorage) Range(ctx context.Context, address oid.Address, rng *objectSDK.Range) (*objectSDK.Object, error) {
|
|
|
|
var getRange engine.RngPrm
|
|
|
|
getRange.WithAddress(address)
|
|
|
|
getRange.WithPayloadRange(rng)
|
|
|
|
|
|
|
|
r, err := s.engine.GetRange(ctx, getRange)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Object(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *engineLocalStorage) Get(ctx context.Context, address oid.Address) (*objectSDK.Object, error) {
|
|
|
|
var getPrm engine.GetPrm
|
|
|
|
getPrm.WithAddress(address)
|
|
|
|
|
|
|
|
r, err := s.engine.Get(ctx, getPrm)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Object(), nil
|
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
type RemoteRequestParams struct {
|
|
|
|
Epoch uint64
|
|
|
|
TTL uint32
|
|
|
|
PrivateKey *ecdsa.PrivateKey
|
|
|
|
SessionToken *session.Object
|
|
|
|
BearerToken *bearer.Token
|
|
|
|
XHeaders []string
|
|
|
|
IsRaw bool
|
2023-04-20 10:57:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
type remoteStorage interface {
|
|
|
|
Get(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error)
|
|
|
|
Head(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error)
|
|
|
|
Range(ctx context.Context, address oid.Address, rng *objectSDK.Range, requestParams RemoteRequestParams) (*objectSDK.Object, error)
|
2023-04-20 10:57:45 +00:00
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
ForwardRequest(ctx context.Context, info coreclient.NodeInfo, forwarder RequestForwarder) (*objectSDK.Object, error)
|
|
|
|
}
|
2023-04-20 10:57:45 +00:00
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
type multiaddressRemoteStorage struct {
|
|
|
|
client coreclient.MultiAddressClient
|
|
|
|
}
|
2023-04-20 10:57:45 +00:00
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
func (s *multiaddressRemoteStorage) ForwardRequest(ctx context.Context, info coreclient.NodeInfo, forwarder RequestForwarder) (*objectSDK.Object, error) {
|
|
|
|
return forwarder(ctx, info, s.client)
|
2023-04-20 10:57:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
func (s *multiaddressRemoteStorage) Range(ctx context.Context, address oid.Address, rng *objectSDK.Range, requestParams RemoteRequestParams) (*objectSDK.Object, error) {
|
2023-04-20 10:57:45 +00:00
|
|
|
var prm internalclient.PayloadRangePrm
|
|
|
|
|
|
|
|
prm.SetClient(s.client)
|
2023-04-21 15:21:46 +00:00
|
|
|
prm.SetTTL(requestParams.TTL)
|
|
|
|
prm.SetNetmapEpoch(requestParams.Epoch)
|
|
|
|
prm.SetAddress(address)
|
|
|
|
prm.SetPrivateKey(requestParams.PrivateKey)
|
|
|
|
prm.SetSessionToken(requestParams.SessionToken)
|
|
|
|
prm.SetBearerToken(requestParams.BearerToken)
|
|
|
|
prm.SetXHeaders(requestParams.XHeaders)
|
2023-04-20 10:57:45 +00:00
|
|
|
prm.SetRange(rng)
|
2023-04-21 15:21:46 +00:00
|
|
|
if requestParams.IsRaw {
|
2023-04-20 10:57:45 +00:00
|
|
|
prm.SetRawFlag()
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := internalclient.PayloadRange(ctx, prm)
|
|
|
|
if err != nil {
|
|
|
|
var errAccessDenied *apistatus.ObjectAccessDenied
|
|
|
|
if errors.As(err, &errAccessDenied) {
|
2023-04-21 15:21:46 +00:00
|
|
|
obj, err := s.Get(ctx, address, requestParams)
|
2023-04-20 10:57:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
payload := obj.Payload()
|
|
|
|
from := rng.GetOffset()
|
|
|
|
to := from + rng.GetLength()
|
|
|
|
|
|
|
|
if pLen := uint64(len(payload)); to < from || pLen < from || pLen < to {
|
|
|
|
return nil, new(apistatus.ObjectOutOfRange)
|
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
return s.payloadOnlyObject(payload[from:to]), nil
|
2023-04-20 10:57:45 +00:00
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
return s.payloadOnlyObject(res.PayloadRange()), nil
|
2023-04-20 10:57:45 +00:00
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
func (s *multiaddressRemoteStorage) Head(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error) {
|
2023-04-20 10:57:45 +00:00
|
|
|
var prm internalclient.HeadObjectPrm
|
|
|
|
|
|
|
|
prm.SetClient(s.client)
|
2023-04-21 15:21:46 +00:00
|
|
|
prm.SetTTL(requestParams.TTL)
|
|
|
|
prm.SetNetmapEpoch(requestParams.Epoch)
|
|
|
|
prm.SetAddress(address)
|
|
|
|
prm.SetPrivateKey(requestParams.PrivateKey)
|
|
|
|
prm.SetSessionToken(requestParams.SessionToken)
|
|
|
|
prm.SetBearerToken(requestParams.BearerToken)
|
|
|
|
prm.SetXHeaders(requestParams.XHeaders)
|
|
|
|
|
|
|
|
if requestParams.IsRaw {
|
2023-04-20 10:57:45 +00:00
|
|
|
prm.SetRawFlag()
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := internalclient.HeadObject(ctx, prm)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return res.Header(), nil
|
|
|
|
}
|
|
|
|
|
2023-04-21 15:21:46 +00:00
|
|
|
func (s *multiaddressRemoteStorage) Get(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error) {
|
2023-04-20 10:57:45 +00:00
|
|
|
var prm internalclient.GetObjectPrm
|
|
|
|
|
|
|
|
prm.SetClient(s.client)
|
2023-04-21 15:21:46 +00:00
|
|
|
prm.SetTTL(requestParams.TTL)
|
|
|
|
prm.SetNetmapEpoch(requestParams.Epoch)
|
|
|
|
prm.SetAddress(address)
|
|
|
|
prm.SetPrivateKey(requestParams.PrivateKey)
|
|
|
|
prm.SetSessionToken(requestParams.SessionToken)
|
|
|
|
prm.SetBearerToken(requestParams.BearerToken)
|
|
|
|
prm.SetXHeaders(requestParams.XHeaders)
|
|
|
|
|
|
|
|
if requestParams.IsRaw {
|
2023-04-20 10:57:45 +00:00
|
|
|
prm.SetRawFlag()
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := internalclient.GetObject(ctx, prm)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return res.Object(), nil
|
|
|
|
}
|
2023-04-21 15:21:46 +00:00
|
|
|
|
|
|
|
func (s *multiaddressRemoteStorage) payloadOnlyObject(payload []byte) *objectSDK.Object {
|
|
|
|
obj := objectSDK.New()
|
|
|
|
obj.SetPayload(payload)
|
|
|
|
|
|
|
|
return obj
|
|
|
|
}
|
2023-04-24 09:09:43 +00:00
|
|
|
|
|
|
|
type RangeHashRes struct {
|
|
|
|
hashes [][]byte
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *RangeHashRes) Hashes() [][]byte {
|
|
|
|
return r.hashes
|
|
|
|
}
|