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

  // Gets status of the storage node in FrostFS network map.
  rpc GetNetmapStatus(GetNetmapStatusRequest) returns (GetNetmapStatusResponse);

  // 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);

  // ResetShardEvacuationStatus resets evacuation status if there is no running
  // evacuation process.
  rpc ResetShardEvacuationStatus(ResetShardEvacuationStatusRequest)
      returns (ResetShardEvacuationStatusResponse);

  // 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);

  // Add local access policy engine overrides to a node.
  rpc AddChainLocalOverride(AddChainLocalOverrideRequest)
      returns (AddChainLocalOverrideResponse);

  // Get local access policy engine overrides stored in the node by chain id.
  rpc GetChainLocalOverride(GetChainLocalOverrideRequest)
      returns (GetChainLocalOverrideResponse);

  // List local access policy engine overrides stored in the node by container
  // id.
  rpc ListChainLocalOverrides(ListChainLocalOverridesRequest)
      returns (ListChainLocalOverridesResponse);

  // Remove local access policy engine overrides stored in the node by chaind
  // id.
  rpc RemoveChainLocalOverride(RemoveChainLocalOverrideRequest)
      returns (RemoveChainLocalOverrideResponse);

  // Remove local access policy engine overrides stored in the node by chaind
  // id.
  rpc RemoveChainLocalOverridesByTarget(
      RemoveChainLocalOverridesByTargetRequest)
      returns (RemoveChainLocalOverridesByTargetResponse);

  // List targets of the local APE overrides stored in the node.
  rpc ListTargetsLocalOverrides(ListTargetsLocalOverridesRequest)
      returns (ListTargetsLocalOverridesResponse);

  // Flush objects from write-cache and move it to degraded read only mode.
  rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse);

  // DetachShards detaches and closes shards.
  rpc DetachShards(DetachShardsRequest) returns (DetachShardsResponse);
}

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

// Get netmap status request.
message GetNetmapStatusRequest {
  message Body {}

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

  // Body signature.
  Signature signature = 2;
}

// Get netmap status response.
message GetNetmapStatusResponse {
  message Body {
    // Storage node status in FrostFS network map.
    NetmapStatus status = 1;

    // Network map epoch.
    uint64 epoch = 2;
  }

  // Body of get 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;
    // If true, then writecache will be left in read-only mode after flush
    // completed.
    bool seal = 2;
  }

  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 {
    enum Scope {
      NONE = 0;
      OBJECTS = 1;
      TREES = 2;
    }

    // IDs of the shards.
    repeated bytes shard_ID = 1;
    // Flag indicating whether object read errors should be ignored.
    bool ignore_errors = 2;
    // Evacuation scope.
    uint32 scope = 3;
  }

  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 + skipped == total is not guaranteed after completion.
    uint64 total_objects = 1;
    // Evacuated objects count.
    uint64 evacuated_objects = 2;
    // Failed objects count.
    uint64 failed_objects = 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;

    // Skipped objects count.
    uint64 skipped_objects = 9;

    // Total trees to evacuate count.
    uint64 total_trees = 10;
    // Evacuated trees count.
    uint64 evacuated_trees = 11;
    // Failed trees count.
    uint64 failed_trees = 12;
  }

  Body body = 1;
  Signature signature = 2;
}

// ResetShardEvacuationStatus request.
message ResetShardEvacuationStatusRequest {
  message Body {}

  Body body = 1;
  Signature signature = 2;
}

// ResetShardEvacuationStatus response.
message ResetShardEvacuationStatusResponse {
  message Body {}

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

// AddChainLocalOverride request.
message AddChainLocalOverrideRequest {
  message Body {
    // Target for which the overrides are applied.
    ChainTarget target = 1;

    // Serialized rule chain. If chain ID is left empty
    // in the chain, then it will be generated and returned
    // in the response.
    bytes chain = 2;
  }

  Body body = 1;

  Signature signature = 2;
}

// AddChainLocalOverride response.
message AddChainLocalOverrideResponse {
  message Body {
    // Chain ID assigned for the added rule chain.
    // If chain ID is left empty in the request, then
    // it will be generated.
    bytes chain_id = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

// GetChainLocalOverride request.
message GetChainLocalOverrideRequest {
  message Body {
    // Target for which the overrides are applied.
    ChainTarget target = 1;

    // Chain ID assigned for the added rule chain.
    bytes chain_id = 2;
  }

  Body body = 1;

  Signature signature = 2;
}

// GetChainLocalOverride response.
message GetChainLocalOverrideResponse {
  message Body {
    // Serialized rule chain.
    bytes chain = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

// ListChainLocalOverrides request.
message ListChainLocalOverridesRequest {
  message Body {
    // Target for which the overrides are applied.
    ChainTarget target = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

// ListChainLocalOverrides response.
message ListChainLocalOverridesResponse {
  message Body {
    // The list of serialized rule chain.
    repeated bytes chains = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

// ListTargetsLocalOverrides request.
message ListTargetsLocalOverridesRequest {
  message Body {
    // Target for which the overrides are applied.
    string chainName = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

// ListTargetsLocalOverrides response.
message ListTargetsLocalOverridesResponse {
  message Body {
    // The list of chain targets.
    repeated ChainTarget targets = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

message RemoveChainLocalOverrideRequest {
  message Body {
    // Target for which the overrides are applied.
    ChainTarget target = 1;

    // Chain ID assigned for the added rule chain.
    bytes chain_id = 2;
  }

  Body body = 1;

  Signature signature = 2;
}

message RemoveChainLocalOverrideResponse {
  message Body {}

  Body body = 1;

  Signature signature = 2;
}

message RemoveChainLocalOverridesByTargetRequest {
  message Body {
    // Target for which the overrides are applied.
    ChainTarget target = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

message RemoveChainLocalOverridesByTargetResponse {
  message Body {}

  Body body = 1;

  Signature signature = 2;
}

message SealWriteCacheRequest {
  // 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;
}

message SealWriteCacheResponse {
  message Body {
    message Status {
      bytes shard_ID = 1;
      bool success = 2;
      string error = 3;
    }
    repeated Status results = 1;
  }

  Body body = 1;

  Signature signature = 2;
}

message DetachShardsRequest {
  message Body { repeated bytes shard_ID = 1; }

  Body body = 1;
  Signature signature = 2;
}

message DetachShardsResponse {
  message Body {}

  Body body = 1;

  Signature signature = 2;
}