frostfs-node/pkg/services/object/search/util.go
Leonard Lyubich b3708fc530 [#957] services/object: Refactor usage of NeoFS API client
The client needs of the Object service are limited and change not often.
Interface changes of the client library should not affect the operation of
various service packages, if they do not change their requirements for
the provided functionality. To localize the use of the base client and
facilitate further support, an auxiliary package is implemented that will
only be used by the Object service.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2021-11-03 18:30:09 +03:00

144 lines
3.4 KiB
Go

package searchsvc
import (
"sync"
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-node/pkg/core/client"
"github.com/nspcc-dev/neofs-node/pkg/core/netmap"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
internalclient "github.com/nspcc-dev/neofs-node/pkg/services/object/internal/client"
"github.com/nspcc-dev/neofs-node/pkg/services/object/util"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
)
type uniqueIDWriter struct {
mtx sync.Mutex
written map[string]struct{}
writer IDListWriter
}
type clientConstructorWrapper struct {
constructor ClientConstructor
}
type clientWrapper struct {
client client.Client
}
type storageEngineWrapper engine.StorageEngine
type traverseGeneratorWrapper util.TraverserGenerator
type nmSrcWrapper struct {
nmSrc netmap.Source
}
func newUniqueAddressWriter(w IDListWriter) IDListWriter {
return &uniqueIDWriter{
written: make(map[string]struct{}),
writer: w,
}
}
func (w *uniqueIDWriter) WriteIDs(list []*objectSDK.ID) error {
w.mtx.Lock()
for i := 0; i < len(list); i++ { // don't use range, slice mutates in body
s := list[i].String()
// standard stringer is quite costly, it is better
// to facilitate the calculation of the key
if _, ok := w.written[s]; !ok {
// mark address as processed
w.written[s] = struct{}{}
continue
}
// exclude processed address
list = append(list[:i], list[i+1:]...)
i--
}
w.mtx.Unlock()
return w.writer.WriteIDs(list)
}
func (c *clientConstructorWrapper) get(info client.NodeInfo) (searchClient, error) {
clt, err := c.constructor.Get(info)
if err != nil {
return nil, err
}
return &clientWrapper{
client: clt,
}, nil
}
func (c *clientWrapper) searchObjects(exec *execCtx, info client.NodeInfo) ([]*objectSDK.ID, error) {
if exec.prm.forwarder != nil {
return exec.prm.forwarder(info, c.client)
}
key, err := exec.svc.keyStore.GetKey(exec.prm.common.SessionToken())
if err != nil {
return nil, err
}
var prm internalclient.SearchObjectsPrm
prm.SetContext(exec.context())
prm.SetClient(c.client)
prm.SetPrivateKey(key)
prm.SetSessionToken(exec.prm.common.SessionToken())
prm.SetBearerToken(exec.prm.common.BearerToken())
prm.SetTTL(exec.prm.common.TTL())
prm.SetXHeaders(exec.prm.common.XHeaders())
prm.SetNetmapEpoch(exec.curProcEpoch)
prm.SetContainerID(exec.containerID())
prm.SetFilters(exec.searchFilters())
res, err := internalclient.SearchObjects(prm)
if err != nil {
return nil, err
}
return res.IDList(), nil
}
func (e *storageEngineWrapper) search(exec *execCtx) ([]*objectSDK.ID, error) {
r, err := (*engine.StorageEngine)(e).Select(new(engine.SelectPrm).
WithFilters(exec.searchFilters()).
WithContainerID(exec.containerID()),
)
if err != nil {
return nil, err
}
return idsFromAddresses(r.AddressList()), nil
}
func idsFromAddresses(addrs []*objectSDK.Address) []*objectSDK.ID {
ids := make([]*objectSDK.ID, len(addrs))
for i := range addrs {
ids[i] = addrs[i].ObjectID()
}
return ids
}
func (e *traverseGeneratorWrapper) generateTraverser(cid *cid.ID, epoch uint64) (*placement.Traverser, error) {
a := objectSDK.NewAddress()
a.SetContainerID(cid)
return (*util.TraverserGenerator)(e).GenerateTraverser(a, epoch)
}
func (n *nmSrcWrapper) currentEpoch() (uint64, error) {
return n.nmSrc.Epoch()
}