forked from TrueCloudLab/frostfs-node
[#222] Update Get method in shard
Now `Get`, `Head` and `GetRange` will be separate methods on shard. Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
31371771e8
commit
73505fe582
1 changed files with 69 additions and 65 deletions
|
@ -1,17 +1,20 @@
|
||||||
package shard
|
package shard
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
|
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
"github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// storFetcher is a type to unify object fetching mechanism in `fetchObjectData`
|
||||||
|
// method. It represents generalization of `getSmall` and `getBig` methods.
|
||||||
|
type storFetcher = func(stor *blobstor.BlobStor, id *blobovnicza.ID) (*object.Object, error)
|
||||||
|
|
||||||
// GetPrm groups the parameters of Get operation.
|
// GetPrm groups the parameters of Get operation.
|
||||||
type GetPrm struct {
|
type GetPrm struct {
|
||||||
ln int64 // negative value for full range
|
|
||||||
|
|
||||||
off uint64
|
|
||||||
|
|
||||||
addr *objectSDK.Address
|
addr *objectSDK.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,93 +34,94 @@ func (p *GetPrm) WithAddress(addr *objectSDK.Address) *GetPrm {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithFullRange is a Get option to receive full object payload.
|
// Object returns the requested object.
|
||||||
func (p *GetPrm) WithFullRange() *GetPrm {
|
|
||||||
if p != nil {
|
|
||||||
p.ln = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRange is a Get option to set range of requested payload data.
|
|
||||||
//
|
|
||||||
// Calling with negative length is equivalent
|
|
||||||
// to getting the full payload range.
|
|
||||||
//
|
|
||||||
// Calling with zero length is equivalent
|
|
||||||
// to getting the object header.
|
|
||||||
func (p *GetPrm) WithRange(off uint64, ln int64) *GetPrm {
|
|
||||||
if p != nil {
|
|
||||||
p.off, p.ln = off, ln
|
|
||||||
}
|
|
||||||
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Object returns the requested object part.
|
|
||||||
//
|
|
||||||
// Instance payload contains the requested range of the original object.
|
|
||||||
func (r *GetRes) Object() *object.Object {
|
func (r *GetRes) Object() *object.Object {
|
||||||
return r.obj
|
return r.obj
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reads part of an object from shard.
|
// Get reads an object from shard.
|
||||||
//
|
//
|
||||||
// Returns any error encountered that
|
// Returns any error encountered that
|
||||||
// did not allow to completely read the object part.
|
// did not allow to completely read the object part.
|
||||||
//
|
//
|
||||||
// Returns ErrNotFound if requested object is missing in shard.
|
// Returns object.ErrNotFound if requested object is missing in shard.
|
||||||
func (s *Shard) Get(prm *GetPrm) (*GetRes, error) {
|
func (s *Shard) Get(prm *GetPrm) (*GetRes, error) {
|
||||||
if prm.ln < 0 {
|
var big, small storFetcher
|
||||||
// try to read from WriteCache
|
|
||||||
// TODO: implement
|
|
||||||
|
|
||||||
// form GetBig parameters
|
big = func(stor *blobstor.BlobStor, _ *blobovnicza.ID) (*object.Object, error) {
|
||||||
getBigPrm := new(blobstor.GetBigPrm)
|
getBigPrm := new(blobstor.GetBigPrm)
|
||||||
getBigPrm.SetAddress(prm.addr)
|
getBigPrm.SetAddress(prm.addr)
|
||||||
|
|
||||||
res, err := s.blobStor.GetBig(getBigPrm)
|
res, err := stor.GetBig(getBigPrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &GetRes{
|
return res.Object(), nil
|
||||||
obj: res.Object(),
|
}
|
||||||
}, nil
|
|
||||||
} else if prm.ln == 0 {
|
small = func(stor *blobstor.BlobStor, id *blobovnicza.ID) (*object.Object, error) {
|
||||||
head, err := s.metaBase.Get(prm.addr)
|
getSmallPrm := new(blobstor.GetSmallPrm)
|
||||||
|
getSmallPrm.SetAddress(prm.addr)
|
||||||
|
getSmallPrm.SetBlobovniczaID(id)
|
||||||
|
|
||||||
|
res, err := stor.GetSmall(getSmallPrm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &GetRes{
|
return res.Object(), nil
|
||||||
obj: head,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to read from WriteCache
|
obj, err := s.fetchObjectData(prm.addr, big, small)
|
||||||
// TODO: implement
|
|
||||||
|
|
||||||
// form GetRangeBig parameters
|
|
||||||
getRngBigPrm := new(blobstor.GetRangeBigPrm)
|
|
||||||
getRngBigPrm.SetAddress(prm.addr)
|
|
||||||
|
|
||||||
rng := objectSDK.NewRange()
|
|
||||||
rng.SetOffset(prm.off)
|
|
||||||
rng.SetLength(uint64(prm.ln))
|
|
||||||
|
|
||||||
getRngBigPrm.SetRange(rng)
|
|
||||||
|
|
||||||
res, err := s.blobStor.GetRangeBig(getRngBigPrm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
obj := object.NewRaw()
|
|
||||||
obj.SetPayload(res.RangeData())
|
|
||||||
|
|
||||||
return &GetRes{
|
return &GetRes{
|
||||||
obj: obj.Object(),
|
obj: obj,
|
||||||
}, nil
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchObjectData looks through writeCache and blobStor to find object.
|
||||||
|
func (s *Shard) fetchObjectData(addr *objectSDK.Address, big, small storFetcher) (*object.Object, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
res *object.Object
|
||||||
|
)
|
||||||
|
|
||||||
|
if s.hasWriteCache() {
|
||||||
|
res, err = small(s.writeCache, nil)
|
||||||
|
if err == nil {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s.log.Debug("miss in writeCache blobovnicza")
|
||||||
|
|
||||||
|
res, err = big(s.writeCache, nil)
|
||||||
|
if err == nil {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
s.log.Debug("miss in writeCache shallow dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
exists, err := s.metaBase.Exists(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return nil, object.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
blobovniczaID, err := s.metaBase.IsSmall(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't fetch blobovnicza id from metabase: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if blobovniczaID != nil {
|
||||||
|
res, err = small(s.blobStor, blobovniczaID)
|
||||||
|
} else {
|
||||||
|
res, err = big(s.blobStor, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue