[#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:
Alex Vanin 2020-12-01 11:08:06 +03:00
parent 31371771e8
commit 73505fe582

View file

@ -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
} }