104 lines
2.8 KiB
Protocol Buffer
104 lines
2.8 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
package musicfs;
|
|
|
|
// MusicFs service exposes a server-side music library to a remote musicfs
|
|
// FUSE mount.
|
|
service MusicFs {
|
|
// Hash-based reconciliation. Client sends the (inode, hash) pairs it
|
|
// currently has; server responds with the subset that changed (new or
|
|
// hash-different) plus the inodes the client has but the server no longer
|
|
// has. Cheap on the wire — no file metadata crosses until the client asks.
|
|
rpc Reconcile(ReconcileRequest) returns (ReconcileResponse);
|
|
|
|
// Fetch full metadata for a specific set of inodes. Called after Reconcile
|
|
// returns a non-empty `changed` list, for just those inodes.
|
|
rpc GetMetadata(GetMetadataRequest) returns (stream ManifestEntry);
|
|
|
|
// Stream every file entry in the library. Convenience RPC for first-run
|
|
// bootstrapping or full-refresh. The diff-based Reconcile path is the
|
|
// normal case.
|
|
rpc GetManifest(GetManifestRequest) returns (stream ManifestEntry);
|
|
|
|
// Stream the bytes of one file. If `start` and `length` are both zero the
|
|
// server streams the entire file; otherwise just the requested range. The
|
|
// first chunk carries `total_size` and `offset`; subsequent chunks continue
|
|
// from there.
|
|
rpc GetFile(GetFileRequest) returns (stream FileChunk);
|
|
|
|
// Long-lived stream of filesystem change events. The client uses these as
|
|
// wake-ups to refetch the manifest; correctness always rests on the hash
|
|
// diff, never on the event payload.
|
|
rpc SubscribeEvents(SubscribeEventsRequest) returns (stream ChangeEvent);
|
|
}
|
|
|
|
message ReconcileRequest {
|
|
repeated InodeHash entries = 1;
|
|
}
|
|
|
|
message ReconcileResponse {
|
|
repeated InodeHash changed = 1;
|
|
repeated uint64 deleted = 2;
|
|
}
|
|
|
|
message InodeHash {
|
|
uint64 inode = 1;
|
|
uint64 hash = 2;
|
|
}
|
|
|
|
message GetMetadataRequest {
|
|
repeated uint64 inodes = 1;
|
|
}
|
|
|
|
message GetManifestRequest {}
|
|
|
|
message GetFileRequest {
|
|
uint64 id = 1;
|
|
// When both are zero the server streams the entire file.
|
|
uint64 start = 2;
|
|
uint64 length = 3;
|
|
}
|
|
|
|
message SubscribeEventsRequest {}
|
|
|
|
message ManifestEntry {
|
|
uint64 id = 1;
|
|
string rel_path = 2;
|
|
uint64 size = 3;
|
|
uint64 mtime = 4;
|
|
uint64 ctime = 5;
|
|
uint64 crtime = 6;
|
|
MusicMetadata music_metadata = 7;
|
|
}
|
|
|
|
message MusicMetadata {
|
|
repeated string artist = 1;
|
|
optional string album_artist = 2;
|
|
string album = 3;
|
|
int32 track_number = 4;
|
|
string track_title = 5;
|
|
repeated string other_tags = 6;
|
|
bytes header = 7;
|
|
repeated bytes picture_block_headers = 8;
|
|
repeated PictureDataRange picture_data_ranges = 9;
|
|
uint64 real_audio_start = 10;
|
|
uint64 vorbis_comment_offset = 11;
|
|
uint64 vorbis_comment_length = 12;
|
|
}
|
|
|
|
message PictureDataRange {
|
|
uint64 offset = 1;
|
|
uint64 length = 2;
|
|
}
|
|
|
|
message FileChunk {
|
|
bytes data = 1;
|
|
uint64 offset = 2;
|
|
uint64 total_size = 3;
|
|
}
|
|
|
|
message ChangeEvent {
|
|
// "create", "modify", or "remove".
|
|
string kind = 1;
|
|
}
|