mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-20 05:20:49 +02:00
* ec: add EC bitrot checksum protobuf EcBitrotProtection/EcShardChecksums/ChecksumAlgorithm sidecar messages, copy_ecsum_file and unsafe_ignore_sidecar fields, and a CHECKSUM scrub mode. * ec: bitrot checksum sidecar format, validation, and per-volume load Per-shard CRC32C block checksums in an optional <base>.ecsum sidecar with a self-integrity header; validation, rolling builder, backfill primitive, and EcVolume load on mount + removal on destroy. * ec: capture per-shard checksums at encode; verify-and-exclude on rebuild WriteEcFilesWithContext returns the protection computed inline during encoding. generateMissingEcFiles verifies present inputs against the sidecar, excludes corrupt ones, regenerates in place, and re-verifies; fail-closed unless unsafe_ignore_sidecar, removing all generated outputs on failure. * ec: read-only checksum scrub with Reed-Solomon arbiter ChecksumScrub verifies each local shard against the sidecar and reconstructs flagged shards from the clean shards so stale-sidecar false positives are not reported. Wired to the gRPC CHECKSUM mode and ec.scrub -mode checksum. * ec: server-side bitrot sidecar write, copy, cleanup, and opportunistic backfill Write .ecsum at fresh encode; propagate it with copy_ecsum_file (tolerant); remove it on full delete and decode; rebuild honors unsafe_ignore_sidecar and opportunistically backfills a sidecar when all shards are reachable. * ec: volume server bitrot config flags -ec.bitrotChecksum (default on) and -ec.bitrotBlockSizeMB (default 16). * fix(ec_bitrot): bound -ec.bitrotBlockSizeMB before the int64 multiply Validate the MiB value is in [1, 1024] before multiplying by 1 MiB, so a huge flag value cannot overflow int64 and slip past the power-of-two check, and a block size cannot collapse a sidecar to a few oversized blocks. * fix(ec_bitrot): distribute the .ecsum sidecar from the worker encode path The worker EC encode wrote the generation-0 sidecar locally but never added it to shardFiles, so DistributeEcShards never shipped it and the distributed holders came up unprotected. Append it to shardFiles and map the ecsum shard type to its extension in the sender so it travels with the shards. * fix(ec_bitrot): remove orphaned sidecars when the generation is gone Gate sidecar removal on existingShardCount==0 alone rather than also requiring a stray .ecx. A sidecar whose shards have all been deleted is orphaned and must be removed even when no .ecx remains, or it leaks. .ecx/.ecj/.vif removal stays gated on hasEcxFile as before. * fix(ec_bitrot): do not fold checksum blocks scanned into TotalFiles ChecksumScrub's first return is blocks scanned, not files. Discard it so the scrub response's TotalFiles (a needle/file count) is not inflated by the block count for CHECKSUM mode. * test(ec_bitrot): clean up generated .ecsum sidecars in removeGeneratedFiles * fix(ec_bitrot): reject an oversized sidecar payload before the uint32 cast The header stores payload_len as a uint32; bound the payload before the conversion so a pathological manifest cannot truncate the length field and corrupt the sidecar. A real manifest is a few KB, so this never trips. * fix(ec_bitrot): cap -ec.bitrotBlockSizeMB at 64 MiB The block size becomes the per-shard scratch buffer the scrub/backfill path allocates, so an over-large value (e.g. 1 GiB) is a memory hazard per concurrent scrub worker. Lower the upper bound from 1024 to 64 MiB. * fix(ec_bitrot): add -ecUnsafeIgnoreSidecar to weed tool fix -ecx The -ecx recovery path reconstructs missing shards via RebuildEcFilesWithContext, which fails closed on a malformed/stale .ecsum. Without an override flag an operator could not complete the rebuild without manually deleting the sidecar. Expose -ecUnsafeIgnoreSidecar (default false) and thread it through. * fix(ec_bitrot): bound sidecar payload with a direct int constant; drop readFull Guard len(payload) against a plain int constant (1 GiB) before the allocation instead of a uint64 MaxUint32 compare, so the allocation-size value is provably bounded (clears the CodeQL overflow alert) and the math import is no longer needed. Inline os.File.ReadAt with io.EOF handling in verifyShardFileBlocks and remove the now-redundant readFull helper (os.File.ReadAt fills the slice or errors). * test(ec_bitrot): use slices.Contains instead of a hand-rolled containsU32 * refactor(ec): fold the EcFiles WithContext variants into the base functions RebuildEcFiles now takes the *ECContext directly (nil => derive from .vif as before) and WriteEcFiles takes it too (nil => default), removing the parallel RebuildEcFilesWithContext / WriteEcFilesWithContext names. Callers that had an explicit context drop the WithContext suffix; the default-context callers pass nil. No behavior change. * refactor(ec): pass BackgroundECContext instead of nil to Write/RebuildEcFiles Add a non-nil BackgroundECContext placeholder (analogous to context.Background()) and have callers with no specific layout pass it instead of a nil *ECContext. WriteEcFiles resolves a zero/background context to the default ratio and RebuildEcFiles resolves it from the .vif, so behavior is unchanged. * fix(ec_bitrot): make BackgroundECContext a func; RebuildEcFiles fails closed on bad .vif - BackgroundECContext is now a function returning a fresh *ECContext, so callers cannot mutate a shared singleton or race on it (and it mirrors context.Background, which is also a function). - RebuildEcFiles now propagates the MaybeLoadVolumeInfo error: a present-but- unreadable .vif fails closed instead of silently rebuilding with the default ratio (which would corrupt a custom-ratio volume). Pass an explicit ctx to override.
793 lines
22 KiB
Protocol Buffer
793 lines
22 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
package volume_server_pb;
|
|
option go_package = "github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb";
|
|
|
|
import "remote.proto";
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
// Persistent state for volume servers.
|
|
message VolumeServerState {
|
|
// whether the server is in maintenance (i.e. read-only) mode.
|
|
bool maintenance = 1;
|
|
// incremental version counter
|
|
uint32 version = 2;
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
service VolumeServer {
|
|
//Experts only: takes multiple fid parameters. This function does not propagate deletes to replicas.
|
|
rpc BatchDelete (BatchDeleteRequest) returns (BatchDeleteResponse) {
|
|
}
|
|
|
|
rpc VacuumVolumeCheck (VacuumVolumeCheckRequest) returns (VacuumVolumeCheckResponse) {
|
|
}
|
|
rpc VacuumVolumeCompact (VacuumVolumeCompactRequest) returns (stream VacuumVolumeCompactResponse) {
|
|
}
|
|
rpc VacuumVolumeCommit (VacuumVolumeCommitRequest) returns (VacuumVolumeCommitResponse) {
|
|
}
|
|
rpc VacuumVolumeCleanup (VacuumVolumeCleanupRequest) returns (VacuumVolumeCleanupResponse) {
|
|
}
|
|
|
|
rpc DeleteCollection (DeleteCollectionRequest) returns (DeleteCollectionResponse) {
|
|
}
|
|
rpc AllocateVolume (AllocateVolumeRequest) returns (AllocateVolumeResponse) {
|
|
}
|
|
|
|
rpc VolumeSyncStatus (VolumeSyncStatusRequest) returns (VolumeSyncStatusResponse) {
|
|
}
|
|
rpc VolumeIncrementalCopy (VolumeIncrementalCopyRequest) returns (stream VolumeIncrementalCopyResponse) {
|
|
}
|
|
|
|
rpc VolumeMount (VolumeMountRequest) returns (VolumeMountResponse) {
|
|
}
|
|
rpc VolumeUnmount (VolumeUnmountRequest) returns (VolumeUnmountResponse) {
|
|
}
|
|
rpc VolumeDelete (VolumeDeleteRequest) returns (VolumeDeleteResponse) {
|
|
}
|
|
rpc VolumeMarkReadonly (VolumeMarkReadonlyRequest) returns (VolumeMarkReadonlyResponse) {
|
|
}
|
|
rpc VolumeMarkWritable (VolumeMarkWritableRequest) returns (VolumeMarkWritableResponse) {
|
|
}
|
|
rpc VolumeConfigure (VolumeConfigureRequest) returns (VolumeConfigureResponse) {
|
|
}
|
|
rpc VolumeStatus (VolumeStatusRequest) returns (VolumeStatusResponse) {
|
|
}
|
|
|
|
rpc GetState (GetStateRequest) returns (GetStateResponse) {
|
|
}
|
|
rpc SetState (SetStateRequest) returns (SetStateResponse) {
|
|
}
|
|
|
|
// copy the .idx .dat files, and mount this volume
|
|
rpc VolumeCopy (VolumeCopyRequest) returns (stream VolumeCopyResponse) {
|
|
}
|
|
rpc ReadVolumeFileStatus (ReadVolumeFileStatusRequest) returns (ReadVolumeFileStatusResponse) {
|
|
}
|
|
rpc CopyFile (CopyFileRequest) returns (stream CopyFileResponse) {
|
|
}
|
|
rpc ReceiveFile (stream ReceiveFileRequest) returns (ReceiveFileResponse) {
|
|
}
|
|
|
|
rpc ReadNeedleBlob (ReadNeedleBlobRequest) returns (ReadNeedleBlobResponse) {
|
|
}
|
|
rpc ReadNeedleMeta (ReadNeedleMetaRequest) returns (ReadNeedleMetaResponse) {
|
|
}
|
|
rpc WriteNeedleBlob (WriteNeedleBlobRequest) returns (WriteNeedleBlobResponse) {
|
|
}
|
|
rpc ReadAllNeedles (ReadAllNeedlesRequest) returns (stream ReadAllNeedlesResponse) {
|
|
}
|
|
|
|
rpc VolumeTailSender (VolumeTailSenderRequest) returns (stream VolumeTailSenderResponse) {
|
|
}
|
|
rpc VolumeTailReceiver (VolumeTailReceiverRequest) returns (VolumeTailReceiverResponse) {
|
|
}
|
|
|
|
// erasure coding
|
|
rpc VolumeEcShardsGenerate (VolumeEcShardsGenerateRequest) returns (VolumeEcShardsGenerateResponse) {
|
|
}
|
|
rpc VolumeEcShardsRebuild (VolumeEcShardsRebuildRequest) returns (VolumeEcShardsRebuildResponse) {
|
|
}
|
|
rpc VolumeEcShardsCopy (VolumeEcShardsCopyRequest) returns (VolumeEcShardsCopyResponse) {
|
|
}
|
|
rpc VolumeEcShardsDelete (VolumeEcShardsDeleteRequest) returns (VolumeEcShardsDeleteResponse) {
|
|
}
|
|
rpc VolumeEcShardsMount (VolumeEcShardsMountRequest) returns (VolumeEcShardsMountResponse) {
|
|
}
|
|
rpc VolumeEcShardsUnmount (VolumeEcShardsUnmountRequest) returns (VolumeEcShardsUnmountResponse) {
|
|
}
|
|
rpc VolumeEcShardRead (VolumeEcShardReadRequest) returns (stream VolumeEcShardReadResponse) {
|
|
}
|
|
rpc VolumeEcBlobDelete (VolumeEcBlobDeleteRequest) returns (VolumeEcBlobDeleteResponse) {
|
|
}
|
|
rpc VolumeEcShardsToVolume (VolumeEcShardsToVolumeRequest) returns (VolumeEcShardsToVolumeResponse) {
|
|
}
|
|
rpc VolumeEcShardsInfo (VolumeEcShardsInfoRequest) returns (VolumeEcShardsInfoResponse) {
|
|
}
|
|
|
|
// tiered storage
|
|
rpc VolumeTierMoveDatToRemote (VolumeTierMoveDatToRemoteRequest) returns (stream VolumeTierMoveDatToRemoteResponse) {
|
|
}
|
|
rpc VolumeTierMoveDatFromRemote (VolumeTierMoveDatFromRemoteRequest) returns (stream VolumeTierMoveDatFromRemoteResponse) {
|
|
}
|
|
|
|
rpc VolumeServerStatus (VolumeServerStatusRequest) returns (VolumeServerStatusResponse) {
|
|
}
|
|
rpc VolumeServerLeave (VolumeServerLeaveRequest) returns (VolumeServerLeaveResponse) {
|
|
}
|
|
|
|
// remote storage
|
|
rpc FetchAndWriteNeedle (FetchAndWriteNeedleRequest) returns (FetchAndWriteNeedleResponse) {
|
|
}
|
|
|
|
// scrubbing
|
|
rpc ScrubVolume (ScrubVolumeRequest) returns (ScrubVolumeResponse) {
|
|
}
|
|
rpc ScrubEcVolume (ScrubEcVolumeRequest) returns (ScrubEcVolumeResponse) {
|
|
}
|
|
|
|
// <experimental> query
|
|
rpc Query (QueryRequest) returns (stream QueriedStripe) {
|
|
}
|
|
|
|
rpc VolumeNeedleStatus (VolumeNeedleStatusRequest) returns (VolumeNeedleStatusResponse) {
|
|
}
|
|
|
|
rpc Ping (PingRequest) returns (PingResponse) {
|
|
}
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
message BatchDeleteRequest {
|
|
repeated string file_ids = 1;
|
|
bool skip_cookie_check = 2;
|
|
}
|
|
|
|
message BatchDeleteResponse {
|
|
repeated DeleteResult results = 1;
|
|
}
|
|
message DeleteResult {
|
|
string file_id = 1;
|
|
int32 status = 2;
|
|
string error = 3;
|
|
uint32 size = 4;
|
|
uint32 version = 5;
|
|
}
|
|
|
|
message Empty {
|
|
}
|
|
|
|
message VacuumVolumeCheckRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VacuumVolumeCheckResponse {
|
|
double garbage_ratio = 1;
|
|
}
|
|
|
|
message VacuumVolumeCompactRequest {
|
|
uint32 volume_id = 1;
|
|
int64 preallocate = 2;
|
|
}
|
|
message VacuumVolumeCompactResponse {
|
|
int64 processed_bytes = 1;
|
|
float load_avg_1m = 2;
|
|
}
|
|
|
|
message VacuumVolumeCommitRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VacuumVolumeCommitResponse {
|
|
bool is_read_only = 1;
|
|
uint64 volume_size = 2;
|
|
}
|
|
|
|
message VacuumVolumeCleanupRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VacuumVolumeCleanupResponse {
|
|
}
|
|
|
|
message DeleteCollectionRequest {
|
|
string collection = 1;
|
|
}
|
|
message DeleteCollectionResponse {
|
|
}
|
|
|
|
message AllocateVolumeRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
int64 preallocate = 3;
|
|
string replication = 4;
|
|
string ttl = 5;
|
|
uint32 memory_map_max_size_mb = 6;
|
|
string disk_type = 7;
|
|
uint32 version = 8;
|
|
}
|
|
message AllocateVolumeResponse {
|
|
}
|
|
|
|
message VolumeSyncStatusRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VolumeSyncStatusResponse {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
string replication = 4;
|
|
string ttl = 5;
|
|
uint64 tail_offset = 6;
|
|
uint32 compact_revision = 7;
|
|
uint64 idx_file_size = 8;
|
|
uint32 version = 9;
|
|
}
|
|
|
|
message VolumeIncrementalCopyRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 since_ns = 2;
|
|
}
|
|
message VolumeIncrementalCopyResponse {
|
|
bytes file_content = 1;
|
|
}
|
|
|
|
message VolumeMountRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VolumeMountResponse {
|
|
}
|
|
|
|
message VolumeUnmountRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VolumeUnmountResponse {
|
|
}
|
|
|
|
message VolumeDeleteRequest {
|
|
uint32 volume_id = 1;
|
|
bool only_empty = 2;
|
|
// when true, do not remove the cloud-tier object backing the volume.
|
|
// used for moves where another server is taking over the same .vif.
|
|
bool keep_remote_data = 3;
|
|
}
|
|
message VolumeDeleteResponse {
|
|
}
|
|
|
|
message VolumeMarkReadonlyRequest {
|
|
uint32 volume_id = 1;
|
|
bool persist = 2;
|
|
}
|
|
message VolumeMarkReadonlyResponse {
|
|
}
|
|
|
|
message VolumeMarkWritableRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VolumeMarkWritableResponse {
|
|
}
|
|
|
|
message VolumeConfigureRequest {
|
|
uint32 volume_id = 1;
|
|
string replication = 2;
|
|
}
|
|
message VolumeConfigureResponse {
|
|
string error = 1;
|
|
}
|
|
|
|
message VolumeStatusRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VolumeStatusResponse {
|
|
bool is_read_only = 1;
|
|
uint64 volume_size = 2;
|
|
uint64 file_count = 3;
|
|
uint64 file_deleted_count = 4;
|
|
}
|
|
|
|
message GetStateRequest {
|
|
}
|
|
message GetStateResponse {
|
|
VolumeServerState state = 1;
|
|
}
|
|
|
|
message SetStateRequest {
|
|
// SetState updates *all* volume server flags at once. Retrieve state with GetState(),
|
|
// modify individual flags as required, then call this RPC to update.
|
|
VolumeServerState state = 1;
|
|
}
|
|
message SetStateResponse {
|
|
VolumeServerState state = 1;
|
|
}
|
|
|
|
message VolumeCopyRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
string replication = 3;
|
|
string ttl = 4;
|
|
string source_data_node = 5;
|
|
string disk_type = 6;
|
|
int64 io_byte_per_second = 7;
|
|
}
|
|
message VolumeCopyResponse {
|
|
uint64 last_append_at_ns = 1;
|
|
int64 processed_bytes = 2;
|
|
}
|
|
|
|
message CopyFileRequest {
|
|
uint32 volume_id = 1;
|
|
string ext = 2;
|
|
uint32 compaction_revision = 3;
|
|
uint64 stop_offset = 4;
|
|
string collection = 5;
|
|
bool is_ec_volume = 6;
|
|
bool ignore_source_file_not_found = 7;
|
|
}
|
|
message CopyFileResponse {
|
|
bytes file_content = 1;
|
|
int64 modified_ts_ns = 2;
|
|
}
|
|
|
|
message ReceiveFileRequest {
|
|
oneof data {
|
|
ReceiveFileInfo info = 1;
|
|
bytes file_content = 2;
|
|
}
|
|
}
|
|
|
|
message ReceiveFileInfo {
|
|
uint32 volume_id = 1;
|
|
string ext = 2;
|
|
string collection = 3;
|
|
bool is_ec_volume = 4;
|
|
uint32 shard_id = 5;
|
|
uint64 file_size = 6;
|
|
uint32 disk_id = 7; // EC shard disk; 0 = auto-select (see VolumeEcShardsCopyRequest.disk_id)
|
|
}
|
|
|
|
message ReceiveFileResponse {
|
|
uint64 bytes_written = 1;
|
|
string error = 2;
|
|
}
|
|
|
|
message ReadNeedleBlobRequest {
|
|
uint32 volume_id = 1;
|
|
int64 offset = 3; // actual offset
|
|
int32 size = 4;
|
|
}
|
|
message ReadNeedleBlobResponse {
|
|
bytes needle_blob = 1;
|
|
}
|
|
|
|
message ReadNeedleMetaRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 needle_id = 2;
|
|
int64 offset = 3; // actual offset
|
|
int32 size = 4;
|
|
}
|
|
message ReadNeedleMetaResponse {
|
|
uint32 cookie = 1;
|
|
uint64 last_modified = 2;
|
|
uint32 crc = 3;
|
|
string ttl = 4;
|
|
uint64 append_at_ns = 5;
|
|
}
|
|
|
|
message WriteNeedleBlobRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 needle_id = 2;
|
|
int32 size = 3;
|
|
bytes needle_blob = 4;
|
|
}
|
|
message WriteNeedleBlobResponse {
|
|
}
|
|
|
|
message ReadAllNeedlesRequest {
|
|
repeated uint32 volume_ids = 1;
|
|
}
|
|
message ReadAllNeedlesResponse {
|
|
uint32 volume_id = 1;
|
|
uint64 needle_id = 2;
|
|
uint32 cookie = 3;
|
|
bytes needle_blob = 5;
|
|
bool needle_blob_compressed = 6;
|
|
uint64 last_modified = 7;
|
|
uint32 crc = 8;
|
|
bytes name = 9;
|
|
bytes mime = 10;
|
|
}
|
|
|
|
message VolumeTailSenderRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 since_ns = 2;
|
|
uint32 idle_timeout_seconds = 3;
|
|
}
|
|
message VolumeTailSenderResponse {
|
|
bytes needle_header = 1;
|
|
bytes needle_body = 2;
|
|
bool is_last_chunk = 3;
|
|
uint32 version = 4;
|
|
}
|
|
|
|
message VolumeTailReceiverRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 since_ns = 2;
|
|
uint32 idle_timeout_seconds = 3;
|
|
string source_volume_server = 4;
|
|
}
|
|
message VolumeTailReceiverResponse {
|
|
}
|
|
|
|
message VolumeEcShardsGenerateRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
}
|
|
message VolumeEcShardsGenerateResponse {
|
|
}
|
|
|
|
message VolumeEcShardsRebuildRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
bool unsafe_ignore_sidecar = 3; // bypass the bitrot-sidecar fail-closed guard (operator override; distinct from ec.rebuild -force)
|
|
}
|
|
message VolumeEcShardsRebuildResponse {
|
|
repeated uint32 rebuilt_shard_ids = 1;
|
|
}
|
|
|
|
message VolumeEcShardsCopyRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
repeated uint32 shard_ids = 3;
|
|
bool copy_ecx_file = 4;
|
|
string source_data_node = 5;
|
|
bool copy_ecj_file = 6;
|
|
bool copy_vif_file = 7;
|
|
uint32 disk_id = 8; // Target disk ID for storing EC shards
|
|
bool copy_ecsum_file = 9; // copy the bitrot checksum sidecar (.ecsum) when present; tolerant of a missing source (no-op), since this non-2PC path has no Prepare backstop
|
|
}
|
|
message VolumeEcShardsCopyResponse {
|
|
}
|
|
|
|
message VolumeEcShardsDeleteRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
repeated uint32 shard_ids = 3;
|
|
}
|
|
message VolumeEcShardsDeleteResponse {
|
|
}
|
|
|
|
message VolumeEcShardsMountRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
repeated uint32 shard_ids = 3;
|
|
string source_disk_type = 4; // disk type of the source volume, applied to the in-memory EC volume so heartbeats report under it (#9423)
|
|
}
|
|
message VolumeEcShardsMountResponse {
|
|
}
|
|
|
|
message VolumeEcShardsUnmountRequest {
|
|
uint32 volume_id = 1;
|
|
repeated uint32 shard_ids = 3;
|
|
}
|
|
message VolumeEcShardsUnmountResponse {
|
|
}
|
|
|
|
message VolumeEcShardReadRequest {
|
|
uint32 volume_id = 1;
|
|
uint32 shard_id = 2;
|
|
int64 offset = 3;
|
|
int64 size = 4;
|
|
uint64 file_key = 5;
|
|
}
|
|
message VolumeEcShardReadResponse {
|
|
bytes data = 1;
|
|
bool is_deleted = 2;
|
|
}
|
|
|
|
message VolumeEcBlobDeleteRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
uint64 file_key = 3;
|
|
uint32 version = 4;
|
|
}
|
|
message VolumeEcBlobDeleteResponse {
|
|
}
|
|
|
|
message VolumeEcShardsToVolumeRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
}
|
|
message VolumeEcShardsToVolumeResponse {
|
|
}
|
|
|
|
message VolumeEcShardsInfoRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message VolumeEcShardsInfoResponse {
|
|
repeated EcShardInfo ec_shard_infos = 1;
|
|
uint64 volume_size = 2;
|
|
uint64 file_count = 3;
|
|
uint64 file_deleted_count = 4;
|
|
}
|
|
|
|
message EcShardInfo {
|
|
uint32 shard_id = 1;
|
|
int64 size = 2;
|
|
string collection = 3;
|
|
uint32 volume_id = 4;
|
|
}
|
|
|
|
message ReadVolumeFileStatusRequest {
|
|
uint32 volume_id = 1;
|
|
}
|
|
message ReadVolumeFileStatusResponse {
|
|
uint32 volume_id = 1;
|
|
uint64 idx_file_timestamp_seconds = 2;
|
|
uint64 idx_file_size = 3;
|
|
uint64 dat_file_timestamp_seconds = 4;
|
|
uint64 dat_file_size = 5;
|
|
uint64 file_count = 6;
|
|
uint32 compaction_revision = 7;
|
|
string collection = 8;
|
|
string disk_type = 9;
|
|
VolumeInfo volume_info = 10;
|
|
uint32 version = 11;
|
|
}
|
|
|
|
message DiskStatus {
|
|
string dir = 1;
|
|
uint64 all = 2;
|
|
uint64 used = 3;
|
|
uint64 free = 4;
|
|
float percent_free = 5;
|
|
float percent_used = 6;
|
|
string disk_type = 7;
|
|
}
|
|
|
|
message MemStatus {
|
|
int32 goroutines = 1;
|
|
uint64 all = 2;
|
|
uint64 used = 3;
|
|
uint64 free = 4;
|
|
uint64 self = 5;
|
|
uint64 heap = 6;
|
|
uint64 stack = 7;
|
|
}
|
|
|
|
// tired storage on volume servers
|
|
message RemoteFile {
|
|
string backend_type = 1;
|
|
string backend_id = 2;
|
|
string key = 3;
|
|
uint64 offset = 4;
|
|
uint64 file_size = 5;
|
|
uint64 modified_time = 6;
|
|
string extension = 7;
|
|
}
|
|
message VolumeInfo {
|
|
repeated RemoteFile files = 1;
|
|
uint32 version = 2;
|
|
string replication = 3;
|
|
uint32 bytes_offset = 4;
|
|
int64 dat_file_size = 5; // store the original dat file size
|
|
uint64 expire_at_sec = 6; // expiration time of ec volume
|
|
bool read_only = 7;
|
|
EcShardConfig ec_shard_config = 8; // EC shard configuration (optional, null = use default 10+4)
|
|
}
|
|
|
|
// EcShardConfig specifies erasure coding shard configuration
|
|
message EcShardConfig {
|
|
uint32 data_shards = 1; // Number of data shards (e.g., 10)
|
|
uint32 parity_shards = 2; // Number of parity shards (e.g., 4)
|
|
}
|
|
|
|
// EcBitrotProtection is the entire content of a bitrot checksum sidecar
|
|
// (<base>.ecsum for the legacy generation, <base>.ecsum.v<N> for vacuum
|
|
// generation N). On disk it is wrapped in a fixed header carrying a CRC32C
|
|
// over this serialized payload (see weed/storage/erasure_coding/ec_bitrot.go).
|
|
message EcBitrotProtection {
|
|
ChecksumAlgorithm algorithm = 1; // CRC32C (Castagnoli)
|
|
uint32 block_size = 2; // bytes per checksum block; default 16777216 (16 MiB), a power-of-two multiple of 1 MiB
|
|
uint32 generation = 3; // EC vacuum generation these checksums describe (0 = legacy/fresh); must match the sidecar filename version
|
|
EcShardConfig ec_shard_config = 4; // data/parity shard counts at encode time
|
|
repeated EcShardChecksums shards = 5; // one entry per shard id in the active layout
|
|
bytes encode_uuid = 6; // random per-encode identity, for stale-sidecar detection across in-place re-encodes
|
|
}
|
|
|
|
message EcShardChecksums {
|
|
uint32 shard_id = 1; // 0..MaxShardCount-1 (custom EC ratios go up to 32)
|
|
int64 covered_size = 2; // shard byte length these checksums cover (must equal the on-disk shard length)
|
|
bytes block_crc32c = 3; // packed little-endian uint32[] = ceil(covered_size/block_size) entries
|
|
}
|
|
|
|
enum ChecksumAlgorithm {
|
|
CHECKSUM_NONE = 0;
|
|
CHECKSUM_CRC32C = 1;
|
|
}
|
|
message OldVersionVolumeInfo {
|
|
repeated RemoteFile files = 1;
|
|
uint32 version = 2;
|
|
string replication = 3;
|
|
uint32 BytesOffset = 4;
|
|
int64 dat_file_size = 5; // store the original dat file size
|
|
uint64 DestroyTime = 6; // expiration time of ec volume
|
|
bool read_only = 7;
|
|
}
|
|
|
|
// tiered storage
|
|
message VolumeTierMoveDatToRemoteRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
string destination_backend_name = 3;
|
|
bool keep_local_dat_file = 4;
|
|
}
|
|
message VolumeTierMoveDatToRemoteResponse {
|
|
int64 processed = 1;
|
|
float processedPercentage = 2;
|
|
}
|
|
|
|
message VolumeTierMoveDatFromRemoteRequest {
|
|
uint32 volume_id = 1;
|
|
string collection = 2;
|
|
bool keep_remote_dat_file = 3;
|
|
}
|
|
message VolumeTierMoveDatFromRemoteResponse {
|
|
int64 processed = 1;
|
|
float processedPercentage = 2;
|
|
}
|
|
|
|
message VolumeServerStatusRequest {
|
|
|
|
}
|
|
message VolumeServerStatusResponse {
|
|
repeated DiskStatus disk_statuses = 1;
|
|
MemStatus memory_status = 2;
|
|
string version = 3;
|
|
string data_center = 4;
|
|
string rack = 5;
|
|
VolumeServerState state = 6;
|
|
}
|
|
|
|
message VolumeServerLeaveRequest {
|
|
}
|
|
message VolumeServerLeaveResponse {
|
|
}
|
|
|
|
// remote storage
|
|
message FetchAndWriteNeedleRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 needle_id = 2;
|
|
uint32 cookie = 3;
|
|
int64 offset = 4;
|
|
int64 size = 5;
|
|
message Replica {
|
|
string url = 1;
|
|
string public_url = 2;
|
|
int32 grpc_port = 3;
|
|
}
|
|
repeated Replica replicas = 6;
|
|
string auth = 7;
|
|
int32 download_concurrency = 8; // multipart download concurrency if supported by the remote storage client; for S3, 0 = default (5)
|
|
// remote conf
|
|
remote_pb.RemoteConf remote_conf = 15;
|
|
remote_pb.RemoteStorageLocation remote_location = 16;
|
|
}
|
|
message FetchAndWriteNeedleResponse {
|
|
string e_tag = 1;
|
|
}
|
|
|
|
enum VolumeScrubMode {
|
|
UNKNOWN = 0;
|
|
INDEX = 1;
|
|
FULL = 2;
|
|
LOCAL = 3;
|
|
CHECKSUM = 4; // EC only: verify each local shard's raw bytes against the bitrot checksum sidecar
|
|
}
|
|
|
|
message ScrubVolumeRequest {
|
|
VolumeScrubMode mode = 1;
|
|
// optional list of volume IDs to scrub. if empty, all volumes for the server are scrubbed.
|
|
repeated uint32 volume_ids = 2;
|
|
bool mark_broken_volumes_readonly = 3;
|
|
}
|
|
message ScrubVolumeResponse {
|
|
uint64 total_volumes = 1;
|
|
uint64 total_files = 2;
|
|
repeated uint32 broken_volume_ids = 3;
|
|
repeated string details = 4;
|
|
}
|
|
|
|
message ScrubEcVolumeRequest {
|
|
VolumeScrubMode mode = 1;
|
|
// optional list of volume IDs to scrub. if empty, all EC volumes for the server are scrubbed.
|
|
repeated uint32 volume_ids = 2;
|
|
}
|
|
message ScrubEcVolumeResponse {
|
|
uint64 total_volumes = 1;
|
|
uint64 total_files = 2;
|
|
repeated uint32 broken_volume_ids = 3;
|
|
repeated EcShardInfo broken_shard_infos = 4;
|
|
repeated string details = 5;
|
|
}
|
|
|
|
// select on volume servers
|
|
message QueryRequest {
|
|
repeated string selections = 1;
|
|
repeated string from_file_ids = 2;
|
|
message Filter {
|
|
string field = 1;
|
|
string operand = 2;
|
|
string value = 3;
|
|
}
|
|
Filter filter = 3;
|
|
|
|
message InputSerialization {
|
|
// NONE | GZIP | BZIP2
|
|
string compression_type = 1;
|
|
message CSVInput {
|
|
string file_header_info = 1; // Valid values: NONE | USE | IGNORE
|
|
string record_delimiter = 2; // Default: \n
|
|
string field_delimiter = 3; // Default: ,
|
|
string quote_character = 4; // Default: "
|
|
string quote_escape_character = 5; // Default: "
|
|
string comments = 6; // Default: #
|
|
// If true, records might contain record delimiters within quote characters
|
|
bool allow_quoted_record_delimiter = 7; // default False.
|
|
}
|
|
message JSONInput {
|
|
string type = 1; // Valid values: DOCUMENT | LINES
|
|
}
|
|
message ParquetInput {
|
|
}
|
|
|
|
CSVInput csv_input = 2;
|
|
JSONInput json_input = 3;
|
|
ParquetInput parquet_input = 4;
|
|
}
|
|
InputSerialization input_serialization = 4;
|
|
|
|
message OutputSerialization {
|
|
message CSVOutput {
|
|
string quote_fields = 1; // Valid values: ALWAYS | ASNEEDED
|
|
string record_delimiter = 2; // Default: \n
|
|
string field_delimiter = 3; // Default: ,
|
|
string quote_character = 4; // Default: "
|
|
string quote_escape_character = 5; // Default: "
|
|
}
|
|
message JSONOutput {
|
|
string record_delimiter = 1;
|
|
}
|
|
|
|
CSVOutput csv_output = 2;
|
|
JSONOutput json_output = 3;
|
|
}
|
|
|
|
OutputSerialization output_serialization = 5;
|
|
}
|
|
message QueriedStripe {
|
|
bytes records = 1;
|
|
}
|
|
|
|
message VolumeNeedleStatusRequest {
|
|
uint32 volume_id = 1;
|
|
uint64 needle_id = 2;
|
|
}
|
|
message VolumeNeedleStatusResponse {
|
|
uint64 needle_id = 1;
|
|
uint32 cookie = 2;
|
|
uint32 size = 3;
|
|
uint64 last_modified = 4;
|
|
uint32 crc = 5;
|
|
string ttl = 6;
|
|
}
|
|
|
|
message PingRequest {
|
|
string target = 1; // default to ping itself
|
|
string target_type = 2;
|
|
}
|
|
message PingResponse {
|
|
int64 start_time_ns = 1;
|
|
int64 remote_time_ns = 2;
|
|
int64 stop_time_ns = 3;
|
|
}
|