forked from TrueCloudLab/frostfs-node
[#947] engine: Evacuate trees to remote nodes
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
728150d1d2
commit
db67c21d55
8 changed files with 283 additions and 95 deletions
|
@ -4,13 +4,17 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
|
@ -28,7 +32,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe
|
|||
prm := engine.EvacuateShardPrm{
|
||||
ShardID: s.getShardIDList(req.GetBody().GetShard_ID()),
|
||||
IgnoreErrors: req.GetBody().GetIgnoreErrors(),
|
||||
ObjectsHandler: s.replicate,
|
||||
ObjectsHandler: s.replicateObject,
|
||||
Scope: engine.EvacuateScopeObjects,
|
||||
}
|
||||
|
||||
|
@ -50,7 +54,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *Server) replicate(ctx context.Context, addr oid.Address, obj *objectSDK.Object) error {
|
||||
func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *objectSDK.Object) error {
|
||||
cid, ok := obj.ContainerID()
|
||||
if !ok {
|
||||
// Return nil to prevent situations where a shard can't be evacuated
|
||||
|
@ -58,33 +62,11 @@ func (s *Server) replicate(ctx context.Context, addr oid.Address, obj *objectSDK
|
|||
return nil
|
||||
}
|
||||
|
||||
nm, err := s.netMapSrc.GetNetMap(0)
|
||||
nodes, err := s.getContainerNodes(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := s.cnrSrc.Get(cid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
binCnr := make([]byte, sha256.Size)
|
||||
cid.Encode(binCnr)
|
||||
|
||||
ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't build a list of container nodes")
|
||||
}
|
||||
|
||||
nodes := placement.FlattenNodes(ns)
|
||||
bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes()
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
if bytes.Equal(nodes[i].PublicKey(), bs) {
|
||||
copy(nodes[i:], nodes[i+1:])
|
||||
nodes = nodes[:len(nodes)-1]
|
||||
}
|
||||
}
|
||||
|
||||
var res replicatorResult
|
||||
task := replicator.Task{
|
||||
NumCopies: 1,
|
||||
|
@ -100,6 +82,95 @@ func (s *Server) replicate(ctx context.Context, addr oid.Address, obj *objectSDK
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (string, error) {
|
||||
nodes, err := s.getContainerNodes(contID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
return "", fmt.Errorf("no remote nodes available to replicate tree '%s' of container %s", treeID, contID)
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
err = s.replicateTreeToNode(ctx, forest, contID, treeID, node)
|
||||
if err == nil {
|
||||
return hex.EncodeToString(node.PublicKey()), nil
|
||||
}
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest, contID cid.ID, treeID string, node netmap.NodeInfo) error {
|
||||
rawCID := make([]byte, sha256.Size)
|
||||
contID.Encode(rawCID)
|
||||
|
||||
var height uint64
|
||||
for {
|
||||
op, err := forest.TreeGetOpLog(ctx, contID, treeID, height)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if op.Time == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
req := &tree.ApplyRequest{
|
||||
Body: &tree.ApplyRequest_Body{
|
||||
ContainerId: rawCID,
|
||||
TreeId: treeID,
|
||||
Operation: &tree.LogMove{
|
||||
ParentId: op.Parent,
|
||||
Meta: op.Meta.Bytes(),
|
||||
ChildId: op.Child,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err = tree.SignMessage(req, s.key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't sign apply request: %w", err)
|
||||
}
|
||||
|
||||
err = s.treeService.ReplicateTreeOp(ctx, node, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
height = op.Time + 1
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) {
|
||||
nm, err := s.netMapSrc.GetNetMap(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := s.cnrSrc.Get(contID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
binCnr := make([]byte, sha256.Size)
|
||||
contID.Encode(binCnr)
|
||||
|
||||
ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't build a list of container nodes")
|
||||
}
|
||||
|
||||
nodes := placement.FlattenNodes(ns)
|
||||
bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes()
|
||||
for i := 0; i < len(nodes); i++ {
|
||||
if bytes.Equal(nodes[i].PublicKey(), bs) {
|
||||
copy(nodes[i:], nodes[i+1:])
|
||||
nodes = nodes[:len(nodes)-1]
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
type replicatorResult struct {
|
||||
count int
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue