forked from TrueCloudLab/frostfs-node
[#643] objsvc/put: Unify placement iterators
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
3fcf56f2fb
commit
facd3b2c4b
4 changed files with 132 additions and 199 deletions
|
@ -8,7 +8,6 @@ import (
|
|||
"fmt"
|
||||
"hash"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
objectAPI "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
|
||||
|
@ -150,18 +149,19 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
traversal := &traversal{
|
||||
opts: placementOptions,
|
||||
extraBroadcastEnabled: len(obj.Children()) > 0 ||
|
||||
(!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock)),
|
||||
mExclude: make(map[string]*bool),
|
||||
}
|
||||
|
||||
iter := s.cfg.newNodeIterator(placementOptions)
|
||||
iter.extraBroadcastEnabled = len(obj.Children()) > 0 || (!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock))
|
||||
|
||||
signer := &putSingleRequestSigner{
|
||||
req: req,
|
||||
keyStorage: s.keyStorage,
|
||||
signer: &sync.Once{},
|
||||
}
|
||||
return s.saveAccordingToPlacement(ctx, obj, signer, traversal, meta)
|
||||
|
||||
return iter.forEachNode(ctx, func(ctx context.Context, nd nodeDesc) error {
|
||||
return s.saveToPlacementNode(ctx, &nd, obj, signer, meta)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) ([]placement.Option, error) {
|
||||
|
@ -199,97 +199,6 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (s *Service) saveAccordingToPlacement(ctx context.Context, obj *objectSDK.Object, signer *putSingleRequestSigner,
|
||||
traversal *traversal, meta object.ContentMeta) error {
|
||||
traverser, err := placement.NewTraverser(traversal.opts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create object placement traverser: %w", err)
|
||||
}
|
||||
|
||||
var resultError atomic.Value
|
||||
for {
|
||||
addrs := traverser.Next()
|
||||
if len(addrs) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if stop := s.saveToPlacementNodes(ctx, obj, signer, traversal, traverser, addrs, meta, &resultError); stop {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !traverser.Success() {
|
||||
var err errIncompletePut
|
||||
err.singleErr, _ = resultError.Load().(error)
|
||||
return err
|
||||
}
|
||||
|
||||
if traversal.submitPrimaryPlacementFinish() {
|
||||
err = s.saveAccordingToPlacement(ctx, obj, signer, traversal, meta)
|
||||
if err != nil {
|
||||
s.log.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) saveToPlacementNodes(ctx context.Context,
|
||||
obj *objectSDK.Object,
|
||||
signer *putSingleRequestSigner,
|
||||
traversal *traversal,
|
||||
traverser *placement.Traverser,
|
||||
nodeAddresses []placement.Node,
|
||||
meta object.ContentMeta,
|
||||
resultError *atomic.Value,
|
||||
) bool {
|
||||
wg := sync.WaitGroup{}
|
||||
|
||||
for _, nodeAddress := range nodeAddresses {
|
||||
nodeAddress := nodeAddress
|
||||
if ok := traversal.mExclude[string(nodeAddress.PublicKey())]; ok != nil {
|
||||
if *ok {
|
||||
traverser.SubmitSuccess()
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
local := false
|
||||
workerPool := s.remotePool
|
||||
if s.netmapKeys.IsLocalKey(nodeAddress.PublicKey()) {
|
||||
local = true
|
||||
workerPool = s.localPool
|
||||
}
|
||||
|
||||
item := new(bool)
|
||||
wg.Add(1)
|
||||
if err := workerPool.Submit(func() {
|
||||
defer wg.Done()
|
||||
|
||||
err := s.saveToPlacementNode(ctx, &nodeDesc{local: local, info: nodeAddress}, obj, signer, meta)
|
||||
|
||||
if err != nil {
|
||||
resultError.Store(err)
|
||||
svcutil.LogServiceError(s.log, "PUT", nodeAddress.Addresses(), err)
|
||||
return
|
||||
}
|
||||
|
||||
traverser.SubmitSuccess()
|
||||
*item = true
|
||||
}); err != nil {
|
||||
wg.Done()
|
||||
svcutil.LogWorkerPoolError(s.log, "PUT", err)
|
||||
return true
|
||||
}
|
||||
|
||||
traversal.submitProcessed(nodeAddress, item)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *nodeDesc, obj *objectSDK.Object,
|
||||
signer *putSingleRequestSigner, meta object.ContentMeta) error {
|
||||
if nodeDesc.local {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue