diff --git a/pkg/services/control/convert.go b/pkg/services/control/convert.go index 833288bb7..f7582dd68 100644 --- a/pkg/services/control/convert.go +++ b/pkg/services/control/convert.go @@ -200,3 +200,21 @@ func (w *flushCacheResponseWrapper) FromGRPCMessage(m grpc.Message) error { w.FlushCacheResponse = r return nil } + +type doctorResponseWrapper struct { + *DoctorResponse +} + +func (w *doctorResponseWrapper) ToGRPCMessage() grpc.Message { + return w.DoctorResponse +} + +func (w *doctorResponseWrapper) FromGRPCMessage(m grpc.Message) error { + r, ok := m.(*DoctorResponse) + if !ok { + return message.NewUnexpectedMessageType(m, (*DoctorResponse)(nil)) + } + + w.DoctorResponse = r + return nil +} diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 0779e177b..2676ea7a5 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -18,6 +18,7 @@ const ( rpcSynchronizeTree = "SynchronizeTree" rpcEvacuateShard = "EvacuateShard" rpcFlushCache = "FlushCache" + rpcDoctor = "Doctor" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -191,3 +192,16 @@ func FlushCache(cli *client.Client, req *FlushCacheRequest, opts ...client.CallO return wResp.FlushCacheResponse, nil } + +// Doctor executes ControlService.Doctor RPC. +func Doctor(cli *client.Client, req *DoctorRequest, opts ...client.CallOption) (*DoctorResponse, error) { + wResp := &doctorResponseWrapper{new(DoctorResponse)} + wReq := &requestWrapper{m: req} + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcDoctor), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.DoctorResponse, nil +} diff --git a/pkg/services/control/server/doctor.go b/pkg/services/control/server/doctor.go new file mode 100644 index 000000000..2c91d4c2b --- /dev/null +++ b/pkg/services/control/server/doctor.go @@ -0,0 +1,37 @@ +package control + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Server) Doctor(ctx context.Context, req *control.DoctorRequest) (*control.DoctorResponse, error) { + err := s.isValidRequest(req) + if err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + if !req.Body.RemoveDuplicates { + return nil, status.Error(codes.InvalidArgument, "operation not specified") + } + + var prm engine.RemoveDuplicatesPrm + prm.Concurrency = int(req.Body.Concurrency) + + err = s.s.RemoveDuplicates(ctx, prm) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + resp := &control.DoctorResponse{Body: &control.DoctorResponse_Body{}} + + err = SignMessage(s.key, resp) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return resp, nil +} diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 78e7b0598..ca3e2770e 100644 Binary files a/pkg/services/control/service.pb.go and b/pkg/services/control/service.pb.go differ diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 5a09a74a5..7c661e661 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -37,6 +37,9 @@ service ControlService { // FlushCache moves all data from one shard to the others. rpc FlushCache (FlushCacheRequest) returns (FlushCacheResponse); + + // Doctor performs storage restructuring operations on engine. + rpc Doctor (DoctorRequest) returns (DoctorResponse); } // Health check request. @@ -345,3 +348,28 @@ message FlushCacheResponse { Body body = 1; Signature signature = 2; } + + +// Doctor request. +message DoctorRequest { + // Request body structure. + message Body { + // Number of threads to use for the operation. + uint32 concurrency = 1; + // Flag to search engine for duplicate objects and leave only one copy. + bool remove_duplicates = 2; + } + + Body body = 1; + Signature signature = 2; +} + +// Doctor response. +message DoctorResponse { + // Response body structure. + message Body { + } + + Body body = 1; + Signature signature = 2; +} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 5bb119090..0f50d5893 100644 Binary files a/pkg/services/control/service_frostfs.pb.go and b/pkg/services/control/service_frostfs.pb.go differ diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 2cfddd7f5..4a4fbeac1 100644 Binary files a/pkg/services/control/service_grpc.pb.go and b/pkg/services/control/service_grpc.pb.go differ