forked from TrueCloudLab/frostfs-node
c30aa20b04
`CommonPrm` structure has private key for remote operations. It obtained in the beginning of request processing. However, not every operation triggers remote calls. Therefore, key might not be used. It is important to avoid early key fetching because `TokenStore` now returns error if session token does not exist. This is valid case when container nodes receive request with session token (for ACL pass) and they should process request locally. Signed-off-by: Alex Vanin <alexey@nspcc.ru>
130 lines
3 KiB
Go
130 lines
3 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"
|
|
"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.prm.common.KeyStorage().GetKey(exec.prm.common.SessionToken())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return c.client.SearchObject(exec.context(),
|
|
&exec.prm.SearchObjectParams,
|
|
exec.prm.common.RemoteCallOptions(
|
|
util.WithNetmapEpoch(exec.curProcEpoch),
|
|
util.WithKey(key),
|
|
)...)
|
|
}
|
|
|
|
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()
|
|
}
|