frostfs-node/pkg/services/policer/check.go
Evgenii Stratonikov 7cb3d0cb4a [#885] policer: remove objects for removed container
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2021-10-18 12:14:14 +03:00

131 lines
3 KiB
Go

package policer
import (
"context"
"errors"
"strings"
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
"github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-node/pkg/core/container"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
headsvc "github.com/nspcc-dev/neofs-node/pkg/services/object/head"
"github.com/nspcc-dev/neofs-node/pkg/services/replicator"
"go.uber.org/zap"
)
func (p *Policer) processObject(ctx context.Context, addr *object.Address) {
cnr, err := p.cnrSrc.Get(addr.ContainerID())
if err != nil {
p.log.Error("could not get container",
zap.Stringer("cid", addr.ContainerID()),
zap.String("error", err.Error()),
)
if errors.Is(err, container.ErrNotFound) {
prm := new(engine.InhumePrm)
prm.MarkAsGarbage(addr)
_, err := p.jobQueue.localStorage.Inhume(prm)
if err != nil {
p.log.Error("could not inhume object with missing container",
zap.Stringer("cid", addr.ContainerID()),
zap.Stringer("oid", addr.ObjectID()),
zap.String("error", err.Error()))
}
}
return
}
policy := cnr.PlacementPolicy()
nn, err := p.placementBuilder.BuildPlacement(addr, policy)
if err != nil {
p.log.Error("could not build placement vector for object",
zap.String("error", err.Error()),
)
return
}
replicas := policy.Replicas()
for i := range nn {
select {
case <-ctx.Done():
return
default:
}
p.processNodes(ctx, addr, nn[i], replicas[i].Count())
}
}
func (p *Policer) processNodes(ctx context.Context, addr *object.Address, nodes netmap.Nodes, shortage uint32) {
log := p.log.With(
zap.Stringer("object", addr),
)
prm := new(headsvc.RemoteHeadPrm).WithObjectAddress(addr)
redundantLocalCopy := false
for i := 0; i < len(nodes); i++ {
select {
case <-ctx.Done():
return
default:
}
if p.netmapKeys.IsLocalKey(nodes[i].PublicKey()) {
if shortage == 0 {
// we can call the redundant copy callback
// here to slightly improve the performance
// instead of readability.
redundantLocalCopy = true
break
} else {
shortage--
}
} else if shortage > 0 {
callCtx, cancel := context.WithTimeout(ctx, p.headTimeout)
_, err := p.remoteHeader.Head(callCtx, prm.WithNodeInfo(nodes[i].NodeInfo))
cancel()
if err != nil {
// FIXME: this is a temporary solution to resolve 404 response from remote node
// We need to distinguish problem nodes from nodes without an object.
if strings.Contains(err.Error(), headsvc.ErrNotFound.Error()) {
continue
} else {
log.Error("could not receive object header",
zap.String("error", err.Error()),
)
continue
}
} else {
shortage--
}
}
nodes = append(nodes[:i], nodes[i+1:]...)
i--
}
if shortage > 0 {
log.Info("shortage of object copies detected",
zap.Uint32("shortage", shortage),
)
p.replicator.AddTask(new(replicator.Task).
WithObjectAddress(addr).
WithNodes(nodes).
WithCopiesNumber(shortage),
)
} else if redundantLocalCopy {
log.Info("redundant local object copy detected")
p.cbRedundantCopy(addr)
}
}