syntax = "proto3";

package control;

import "pkg/services/control/types.proto";

option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control";

// `ControlService` provides an interface for internal work with the storage node.
service ControlService {
    // Performs health check of the storage node.
    rpc HealthCheck (HealthCheckRequest) returns (HealthCheckResponse);

    // Sets status of the storage node in FrostFS network map.
    rpc SetNetmapStatus (SetNetmapStatusRequest) returns (SetNetmapStatusResponse);

    // Mark objects to be removed from node's local object storage.
    rpc DropObjects (DropObjectsRequest) returns (DropObjectsResponse);

    // Returns list that contains information about all shards of a node.
    rpc ListShards (ListShardsRequest) returns (ListShardsResponse);

    // Sets mode of the shard.
    rpc SetShardMode (SetShardModeRequest) returns (SetShardModeResponse);

    // Synchronizes all log operations for the specified tree.
    rpc SynchronizeTree (SynchronizeTreeRequest) returns (SynchronizeTreeResponse);

    // EvacuateShard moves all data from one shard to the others.
    // Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation
    rpc EvacuateShard (EvacuateShardRequest) returns (EvacuateShardResponse);

    // StartShardEvacuation starts moving all data from one shard to the others.
    rpc StartShardEvacuation (StartShardEvacuationRequest) returns (StartShardEvacuationResponse);

    // GetShardEvacuationStatus returns evacuation status.
    rpc GetShardEvacuationStatus (GetShardEvacuationStatusRequest) returns (GetShardEvacuationStatusResponse);

    // StopShardEvacuation stops moving all data from one shard to the others.
    rpc StopShardEvacuation (StopShardEvacuationRequest) returns (StopShardEvacuationResponse);

    // 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.
message HealthCheckRequest {
    // Health check request body.
    message Body {
    }

    // Body of health check request message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Health check request.
message HealthCheckResponse {
    // Health check response body
    message Body {
        // Status of the storage node in FrostFS network map.
        NetmapStatus netmap_status = 1;

        // Health status of storage node application.
        HealthStatus health_status = 2;
    }

    // Body of health check response message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Set netmap status request.
message SetNetmapStatusRequest {
    // Set netmap status request body.
    message Body {
        // New storage node status in FrostFS network map.
        // If status is MAINTENANCE, the node checks whether maintenance is
        // allowed in the network settings. In case of prohibition, the request
        // is denied. Otherwise, node switches to local maintenance state. To
        // force local maintenance, use `force_maintenance` flag.
        NetmapStatus status = 1;

        // MAINTENANCE status validation skip flag. If set, node starts local
        // maintenance regardless of network settings. The flag MUST NOT be
        // set for any other status.
        bool force_maintenance = 2;
    }

    // Body of set netmap status request message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Set netmap status response.
message SetNetmapStatusResponse {
    // Set netmap status response body
    message Body {
    }

    // Body of set netmap status response message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Request to drop the objects.
message DropObjectsRequest {
    // Request body structure.
    message Body {
        // List of object addresses to be removed.
        // in FrostFS API binary format.
        repeated bytes address_list = 1;
    }

    // Body of the request message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Response to request to drop the objects.
message DropObjectsResponse {
    // Response body structure.
    message Body {
    }

    // Body of the response message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Request to list all shards of the node.
message ListShardsRequest {
    // Request body structure.
    message Body {
    }

    // Body of the request message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// ListShards response.
message ListShardsResponse {
    // Response body structure.
    message Body {
        // List of the node's shards.
        repeated ShardInfo shards = 1;
    }

    // Body of the response message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// Request to set mode of the shard.
message SetShardModeRequest {
    // Request body structure.
    message Body {
        // ID of the shard.
        repeated bytes shard_ID = 1;

        // Mode that requested to be set.
        ShardMode mode = 2;

        // Flag signifying whether error counter should be set to 0.
        bool resetErrorCounter = 3;
    }

    // Body of set shard mode request message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// SetShardMode response.
message SetShardModeResponse {
    // Response body structure.
    message Body {
    }

    // Body of set shard mode response message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// SynchronizeTree request.
message SynchronizeTreeRequest {
    // Request body structure.
    message Body {
        bytes container_id = 1;
        string tree_id = 2;
        // Starting height for the synchronization. Can be omitted.
        uint64 height = 3;
    }

    // Body of restore shard request message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}

// SynchronizeTree response.
message SynchronizeTreeResponse {
    // Response body structure.
    message Body {
    }

    // Body of restore shard response message.
    Body body = 1;

    // Body signature.
    Signature signature = 2;
}


// EvacuateShard request.
message EvacuateShardRequest {
    // Request body structure.
    message Body {
        // ID of the shard.
        repeated bytes shard_ID = 1;

        // Flag indicating whether object read errors should be ignored.
        bool ignore_errors = 2;
    }

    Body body = 1;
    Signature signature = 2;
}

// EvacuateShard response.
message EvacuateShardResponse {
    // Response body structure.
    message Body {
        uint32 count = 1;
    }

    Body body = 1;
    Signature signature = 2;
}

// FlushCache request.
message FlushCacheRequest {
    // Request body structure.
    message Body {
        // ID of the shard.
        repeated bytes shard_ID = 1;
    }

    Body body = 1;
    Signature signature = 2;
}

// FlushCache response.
message FlushCacheResponse {
    // Response body structure.
    message Body {
    }

    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;
}

// StartShardEvacuation request.
message StartShardEvacuationRequest {
    // Request body structure.
    message Body {
        // IDs of the shards.
        repeated bytes shard_ID = 1;
        // Flag indicating whether object read errors should be ignored.
        bool ignore_errors = 2;
    }

    Body body = 1;
    Signature signature = 2;
}

// StartShardEvacuation response.
message StartShardEvacuationResponse {
    // Response body structure.
    message Body {}

    Body body = 1;
    Signature signature = 2;
}

// GetShardEvacuationStatus request.
message GetShardEvacuationStatusRequest {
    // Request body structure.
    message Body {}

    Body body = 1;
    Signature signature = 2;
}

// GetShardEvacuationStatus response.
message GetShardEvacuationStatusResponse {
    // Response body structure.
    message Body {
        // Evacuate status enum.
        enum Status {
            EVACUATE_SHARD_STATUS_UNDEFINED = 0;
            RUNNING = 1;
            COMPLETED = 2;
        }

        // Unix timestamp value.
        message UnixTimestamp {
            int64 value = 1;
        }

        // Duration in seconds.
        message Duration {
            int64 seconds = 1;
        }

        // Total objects to evacuate count. The value is approximate, so evacuated + failed == total is not guaranteed after completion.
        uint64 total = 1;
        // Evacuated objects count.
        uint64 evacuated = 2;
        // Failed objects count.
        uint64 failed = 3;

        // Shard IDs.
        repeated bytes shard_ID = 4;
        // Evacuation process status.
        Status status = 5;
        // Evacuation process duration.
        Duration duration = 6;
        // Evacuation process started at timestamp.
        UnixTimestamp started_at = 7;
        // Error message if evacuation failed.
        string error_message = 8;
    }

    Body body = 1;
    Signature signature = 2;
}

// StopShardEvacuation request.
message StopShardEvacuationRequest {
    // Request body structure.
    message Body {}

    Body body = 1;
    Signature signature = 2;
}

// StopShardEvacuation response.
message StopShardEvacuationResponse {
    // Response body structure.
    message Body {}

    Body body = 1;
    Signature signature = 2;
}