syntax = "proto3";
package raft_cmdpb;

import "metapb.proto";
import "errorpb.proto";
import "eraftpb.proto";

message GetRequest {
    string cf = 1;
    bytes key = 2;
}

message GetResponse {
    bytes value = 1;
}

message PutRequest {
    string cf = 1;
    bytes key = 2;
    bytes value = 3;
}

message PutResponse {}

message DeleteRequest {
    string cf = 1;
    bytes key = 2;
}

message DeleteResponse {}

message SnapRequest {}

message SnapResponse {
    metapb.Region region = 1;
}

enum CmdType {
    Invalid = 0;
    Get = 1;
    Put = 3;
    Delete = 4;
    Snap = 5;
}

message Request {
    CmdType cmd_type = 1;
    GetRequest get = 2;
    PutRequest put = 4;
    DeleteRequest delete = 5;
    SnapRequest snap = 6;
}

message Response {
    CmdType cmd_type = 1;
    GetResponse get = 2;
    PutResponse put = 4;
    DeleteResponse delete = 5;
    SnapResponse snap = 6;
}

message ChangePeerRequest {
    // This can be only called in internal Raftstore now.
    eraftpb.ConfChangeType change_type = 1;
    metapb.Peer peer = 2;
}

message ChangePeerResponse {
    metapb.Region region = 1;
}

message SplitRequest {
    // This can be only called in internal Raftstore now.
    // The split_key has to exist in the splitting region.
    bytes split_key = 1;
    // We split the region into two. The first uses the origin 
    // parent region id, and the second uses the new_region_id.
    // We must guarantee that the new_region_id is global unique.
    uint64 new_region_id = 2;
    // The peer ids for the new split region.
    repeated uint64 new_peer_ids = 3;
}

message SplitResponse {
    // SplitResponse contains the region where specific keys have split into.
    repeated metapb.Region regions = 1;
}

message CompactLogRequest {
    uint64 compact_index = 1;
    uint64 compact_term = 2;
}

message CompactLogResponse {}

message TransferLeaderRequest {
    metapb.Peer peer = 1;
}

message TransferLeaderResponse {}

enum AdminCmdType {
    InvalidAdmin = 0;
    ChangePeer = 1;
    CompactLog = 3;
    TransferLeader = 4;
    Split = 10;
}

message AdminRequest {
    AdminCmdType cmd_type = 1;
    ChangePeerRequest change_peer = 2;
    CompactLogRequest compact_log = 4;
    TransferLeaderRequest transfer_leader = 5;
    SplitRequest split = 10;
}

message AdminResponse {
    AdminCmdType cmd_type = 1;
    ChangePeerResponse change_peer = 2;
    CompactLogResponse compact_log = 4;
    TransferLeaderResponse transfer_leader = 5;
    SplitResponse split = 10;
}

message RaftRequestHeader {
    uint64 region_id = 1;
    metapb.Peer peer = 2;
    metapb.RegionEpoch region_epoch = 4;
    uint64 term = 5;
}

message RaftResponseHeader {
    errorpb.Error error = 1;
    bytes uuid = 2;
    uint64 current_term = 3;
}

message RaftCmdRequest {
    RaftRequestHeader header = 1;
    // We can't enclose normal requests and administrator request
    // at same time. 
    repeated Request requests = 2;
    AdminRequest admin_request = 3;
}

message RaftCmdResponse {
    RaftResponseHeader header = 1;
    repeated Response responses = 2;
    AdminResponse admin_response = 3;
}
