2020-12-10 12:26:40 +00:00
|
|
|
package searchsvc
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/pkg/client"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
|
|
|
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
|
|
|
|
"github.com/nspcc-dev/neofs-node/pkg/network/cache"
|
|
|
|
"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 clientCacheWrapper struct {
|
|
|
|
cache *cache.ClientCache
|
|
|
|
|
|
|
|
opts []client.Option
|
|
|
|
}
|
|
|
|
|
|
|
|
type clientWrapper struct {
|
|
|
|
client *client.Client
|
|
|
|
}
|
|
|
|
|
|
|
|
type storageEngineWrapper engine.StorageEngine
|
|
|
|
|
|
|
|
type traverseGeneratorWrapper util.TraverserGenerator
|
|
|
|
|
|
|
|
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 *clientCacheWrapper) get(key *ecdsa.PrivateKey, addr string) (searchClient, error) {
|
|
|
|
clt, err := c.cache.Get(key, addr, c.opts...)
|
|
|
|
|
|
|
|
return &clientWrapper{
|
|
|
|
client: clt,
|
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *clientWrapper) searchObjects(exec *execCtx) ([]*objectSDK.ID, error) {
|
|
|
|
return c.client.SearchObject(exec.context(),
|
|
|
|
exec.remotePrm(),
|
|
|
|
exec.callOptions()...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *storageEngineWrapper) search(exec *execCtx) ([]*objectSDK.ID, error) {
|
|
|
|
r, err := (*engine.StorageEngine)(e).Select(new(engine.SelectPrm).
|
2020-12-10 14:38:45 +00:00
|
|
|
WithFilters(exec.searchFilters()).
|
|
|
|
WithContainerID(exec.containerID()),
|
2020-12-10 12:26:40 +00:00
|
|
|
)
|
|
|
|
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 *container.ID) (*placement.Traverser, error) {
|
|
|
|
a := objectSDK.NewAddress()
|
|
|
|
a.SetContainerID(cid)
|
|
|
|
|
|
|
|
return (*util.TraverserGenerator)(e).GenerateTraverser(a)
|
|
|
|
}
|