syntax = "proto3"; package import_sstpb; import "metapb.proto"; import "errorpb.proto"; import "kvrpcpb.proto"; import "raft_serverpb.proto"; import "gogoproto/gogo.proto"; import "rustproto.proto"; import "brpb.proto"; option (gogoproto.sizer_all) = true; option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; option (rustproto.lite_runtime_all) = true; option java_package = "org.tikv.kvproto"; // ImportSST provides a service to import a generated SST file to a region in TiKV. // // In order to import an SST file to a region, the user should: // 1. Retrieve the meta of the region according to the SST file's range. // 2. Upload the SST file to the servers where the region's peers locate in. // 3. Issue an ingest request to the region's leader with the SST file's metadata. // // It's the user's responsibility to make sure that the SST file is uploaded to // the servers where the region's peers locate in, before issue the ingest // request to the region's leader. However, the region can be scheduled (so the // location of the region's peers will be changed) or split/merged (so the range // of the region will be changed), after the SST file is uploaded, but before // the SST file is ingested. So, the region's epoch is provided in the SST // file's metadata, to guarantee that the region's epoch must be the same // between the SST file is uploaded and ingested later. service ImportSST { // Switch to normal/import mode. rpc SwitchMode(SwitchModeRequest) returns (SwitchModeResponse) {} // Upload an SST file to a server. rpc Upload(stream UploadRequest) returns (UploadResponse) {} // Ingest an uploaded SST file to a region. rpc Ingest(IngestRequest) returns (IngestResponse) {} // Compact the specific range for better performance. rpc Compact(CompactRequest) returns (CompactResponse) {} rpc SetDownloadSpeedLimit(SetDownloadSpeedLimitRequest) returns (SetDownloadSpeedLimitResponse) {} // Download an SST file from an external storage, and performs key-rewrite // after downloading. rpc Download(DownloadRequest) returns (DownloadResponse) {} // Open a write stream to generate sst files rpc Write(stream WriteRequest) returns (WriteResponse) {} rpc RawWrite(stream RawWriteRequest) returns (RawWriteResponse) {} // Ingest Multiple files in one request rpc MultiIngest(MultiIngestRequest) returns (IngestResponse) {} // Collect duplicate data from TiKV. rpc DuplicateDetect(DuplicateDetectRequest) returns (stream DuplicateDetectResponse) {} } enum SwitchMode { Normal = 0; Import = 1; } message SwitchModeRequest { SwitchMode mode = 1; } message SwitchModeResponse { } message Range { bytes start = 1; bytes end = 2; } message SSTMeta { bytes uuid = 1; Range range = 2; uint32 crc32 = 3; uint64 length = 4; string cf_name = 5; uint64 region_id = 6; metapb.RegionEpoch region_epoch = 7; bool end_key_exclusive = 8; // total_kvs and total_bytes is equivalent to PD's approximate_keys and approximate_size // set these values can save time from tikv upload keys and size to PD through Heartbeat. uint64 total_kvs = 9; uint64 total_bytes = 10; // API version implies the encode of the key and value. kvrpcpb.APIVersion api_version = 11; // cipher_iv is used to encrypt/decrypt sst bytes cipher_iv = 12; } // A rewrite rule is applied on the *encoded* keys (the internal storage // representation). message RewriteRule { bytes old_key_prefix = 1; bytes new_key_prefix = 2; uint64 new_timestamp = 3; } message UploadRequest { oneof chunk { SSTMeta meta = 1; bytes data = 2; } } message UploadResponse { } message IngestRequest { kvrpcpb.Context context = 1; SSTMeta sst = 2; } message MultiIngestRequest { kvrpcpb.Context context = 1; repeated SSTMeta ssts = 2; } message IngestResponse { errorpb.Error error = 1; } message CompactRequest { // Compact files in the range and above the output level. // Compact all files if the range is not specified. // Compact all files to the bottommost level if the output level is -1. Range range = 1; int32 output_level = 2; } message CompactResponse { } message DownloadRequest { // The SST meta used to identify the downloaded file. // Must be the same among all nodes in the same Raft group. // Note: the "crc32" and "cf_name" fields are ignored in this request, // and the "range" field represents the closed key range after rewrite // (as origin keys in encoded representation). SSTMeta sst = 2 [(gogoproto.nullable) = false]; // The url field is deprecated, use storage_backend instead reserved 8; reserved "url"; // The file name of the SST file. string name = 9; // Performs a key prefix rewrite after downloading the SST file. // All keys in the SST will be rewritten as: // // new_key = new_key_prefix + old_key[len(old_key_prefix)..] // // When used for TiDB, rewriting the prefix changes the table ID. Please // note that key-rewrite is applied on the origin keys in encoded // representation (the SST itself should still use data keys in encoded // representation). // // You need to ensure that the keys before and after rewriting are in the // same order, otherwise the RPC request will fail. RewriteRule rewrite_rule = 13 [(gogoproto.nullable) = false]; backup.StorageBackend storage_backend = 14; bool is_raw_kv = 15; // cipher_info is used to decrypt sst when download sst backup.CipherInfo cipher_info = 16; } // For now it is just used for distinguishing the error of the request with the error // of gRPC, add more concrete types if it is necessary later. message Error { string message = 1; } message DownloadResponse { // The actual key range (after rewrite) of the downloaded SST. The range is // inclusive in both ends. Range range = 1 [(gogoproto.nullable) = false]; // Whether the SST is empty. An empty SST is prohibited in TiKV, do not // ingest if this field is true. // (Deprecated, should be replaced by checking `length == 0` in the future) bool is_empty = 2; Error error = 3; // The CRC32 checksum of the rewritten SST file (implementation can return // zero, indicating the CRC32 was not calculated). uint32 crc32 = 4; // The actual length of the rewritten SST file. uint64 length = 5; } message SetDownloadSpeedLimitRequest { // The download speed limit (bytes/second). Set to 0 for unlimited speed. uint64 speed_limit = 1; } message SetDownloadSpeedLimitResponse { } message Pair { bytes key = 1; bytes value = 2; enum OP { Put = 0; Delete = 1; } OP op = 3; } message WriteBatch { uint64 commit_ts = 1; repeated Pair pairs = 2; } message WriteRequest { oneof chunk { SSTMeta meta = 1; WriteBatch batch = 2; } } message WriteResponse { Error error = 1; repeated SSTMeta metas = 2; } message RawWriteBatch { uint64 ttl = 1; repeated Pair pairs = 2; } message RawWriteRequest { oneof chunk { SSTMeta meta = 1; RawWriteBatch batch = 2; } } message RawWriteResponse { Error error = 1; repeated SSTMeta metas = 2; } message DuplicateDetectRequest { kvrpcpb.Context context = 1; bytes start_key = 2; bytes end_key = 3; // Return only the keys found by scanning, not their values. bool key_only = 4; // We only check the data whose timestamp is larger than `min_commit_ts`. `min_commit_ts` is exclueded. uint64 min_commit_ts = 5; } message KvPair { bytes key = 1; bytes value = 2; uint64 commit_ts = 3; } message DuplicateDetectResponse { errorpb.Error region_error = 1; Error key_error = 2; // The these keys will be in asc order (but commit time is in desc order), // and the content is just like following: // [ // {key: "key1", value: "value11", commit_ts: 1005}, // {key: "key1", value: "value12", commit_ts: 1004}, // {key: "key1", value: "value13", commit_ts: 1001}, // {key: "key2", value: "value21", commit_ts: 1004}, // {key: "key2", value: "value22", commit_ts: 1002}, // ... // ] repeated KvPair pairs = 3; }