namespace generated; union RequestType {ReadRequest, ReadRawRequest, GetattrRequest, MkdirRequest, ReaddirRequest, RenameRequest, UtimensRequest, ChmodRequest, HardlinkRequest, TruncateRequest, UnlinkRequest, LookupRequest, WriteRequest, FilesystemChecksumRequest, FilesystemCheckRequest, RaftRequest, LatestCommitRequest, FilesystemReadyRequest, RmdirRequest, ChownRequest, CreateRequest, FsyncRequest, GetXattrRequest, ListXattrsRequest, SetXattrRequest, RemoveXattrRequest, FilesystemInformationRequest, HardlinkIncrementRequest, HardlinkRollbackRequest, CreateInodeRequest, CreateLinkRequest, DecrementInodeRequest, LockRequest, UnlockRequest, RemoveLinkRequest, ReplaceLinkRequest, UpdateParentRequest, UpdateMetadataChangedTimeRequest, RaftGroupLeaderRequest} enum FileKind: ubyte { DefaultValueNotAType, File, Directory, Symlink } struct UserContext { uid: uint; gid: uint; } table GenericRequest { request: RequestType; } // TODO: maybe support multiple messages in a single request table RaftRequest { raft_group: ushort; message: [ubyte] (required); } table LatestCommitRequest { raft_group: ushort; } table RaftGroupLeaderRequest { raft_group: ushort; } table FilesystemInformationRequest { } table FilesystemReadyRequest { } table FilesystemChecksumRequest { } table FilesystemCheckRequest { } table ListXattrsRequest { inode: ulong; } table GetXattrRequest { inode: ulong; key: string (required); } table SetXattrRequest { inode: ulong; key: string (required); value: [ubyte] (required); } table RemoveXattrRequest { inode: ulong; key: string (required); } struct CommitId { term: ulong; index: ulong; } // Reads only the blocks of data on this node table ReadRawRequest { required_commit: CommitId (required); inode: ulong; offset: ulong; read_size: uint; } table ReadRequest { inode: ulong; offset: ulong; read_size: uint; } table GetattrRequest { inode: ulong; } table MkdirRequest { parent: ulong; name: string (required); uid: uint; gid: uint; mode: ushort; } table WriteRequest { inode: ulong; offset: ulong; data: [ubyte] (required); } table FsyncRequest { inode: ulong; } table UnlinkRequest { parent: ulong; name: string (required); context: UserContext (required); } table RmdirRequest { parent: ulong; name: string (required); context: UserContext (required); } table TruncateRequest { inode: ulong; new_length: ulong; context: UserContext (required); } table ReaddirRequest { inode: ulong; } struct OptionalUInt { value: uint; } struct OptionalULong { value: ulong; } table ChownRequest { inode: ulong; uid: OptionalUInt; gid: OptionalUInt; context: UserContext (required); } table ChmodRequest { inode: ulong; mode: uint; context: UserContext (required); } table UtimensRequest { inode: ulong; atime: Timestamp; mtime: Timestamp; context: UserContext (required); } table HardlinkRequest { inode: ulong; new_parent: ulong; new_name: string (required); context: UserContext (required); } // Used internally to remove a link entry from a directory. Does *not* decrement the hard link count of the target inode table RemoveLinkRequest { parent: ulong; name: string (required); link_inode: OptionalULong; link_uid: OptionalUInt; lock_id: OptionalULong; context: UserContext (required); } // Used internally for stage0 of hardlink transactions table HardlinkIncrementRequest { inode: ulong; } // Used internally to rollback hardlink transactions table HardlinkRollbackRequest { inode: ulong; last_modified_time: Timestamp (required); } table RenameRequest { parent: ulong; name: string (required); new_parent: ulong; new_name: string (required); context: UserContext (required); } table LookupRequest { parent: ulong; name: string (required); context: UserContext (required); } table CreateRequest { parent: ulong; name: string (required); uid: uint; gid: uint; mode: ushort; kind: FileKind; } // Internal request to lock an inode table LockRequest { inode: ulong; } // Internal request to lock an inode table UnlockRequest { inode: ulong; lock_id: ulong; } // Internal request to update the parent link of a directory inode table UpdateParentRequest { inode: ulong; new_parent: ulong; lock_id: OptionalULong; } // Internal request to update the metadata changed time an inode table UpdateMetadataChangedTimeRequest { inode: ulong; lock_id: OptionalULong; } // Internal request to create an inode as part of a create() or mkdir() transaction table CreateInodeRequest { raft_group: ushort; parent: ulong; uid: uint; gid: uint; mode: ushort; kind: FileKind; } // Internal request to create directory link as part of a transaction. Does not increment the inode's link count. table CreateLinkRequest { parent: ulong; name: string (required); inode: ulong; kind: FileKind; lock_id: OptionalULong; context: UserContext (required); } // Internal request to atomically replace a directory link, so that it points to a different inode, // as part of a transaction. Does not change either inode's link count. It is the callers responsibility to ensure // that replacing the existing link is safe (i.e. it doesn't point to a non-empty directory) table ReplaceLinkRequest { parent: ulong; name: string (required); new_inode: ulong; kind: FileKind; lock_id: OptionalULong; context: UserContext (required); } // TODO: raft messages have to be idempotent. This one is not. // Internal request to decrement inode link count. Will delete the inode if its count reaches zero. table DecrementInodeRequest { inode: ulong; // The number of times to decrement the link count decrement_count: uint; lock_id: OptionalULong; } root_type GenericRequest; enum ErrorCode: byte { DefaultValueNotAnError = 0, DoesNotExist, InodeDoesNotExist, FileTooLarge, AccessDenied, OperationNotPermitted, AlreadyExists, NameTooLong, NotEmpty, MissingXattrKey, BadResponse, BadRequest, Corrupted, RaftFailure, Uncategorized } table ErrorResponse { error_code: ErrorCode; } table ReadResponse { data: [ubyte] (required); } table EmptyResponse { } struct Timestamp { seconds: long; nanos: int; } table DirectoryEntry { inode: ulong; name: string (required); kind: FileKind; } table DirectoryListingResponse { entries: [DirectoryEntry] (required); } table WrittenResponse { bytes_written: uint; } table FileMetadataResponse { inode: ulong; size_bytes: ulong; size_blocks: ulong; last_access_time: Timestamp (required); last_modified_time: Timestamp (required); last_metadata_modified_time: Timestamp (required); kind: FileKind; mode: ushort; hard_links: uint; user_id: uint; group_id: uint; device_id: uint; block_size: uint; // The number of directory entries in the directory. Only meaningful if kind == Directory directory_entries: uint; } table LatestCommitResponse { term: ulong; index: ulong; } table InodeResponse { inode: ulong; } table RemoveLinkResponse { inode: ulong; processing_complete: bool; } table LockResponse { lock_id: ulong; } table NodeIdResponse { node_id: ulong; } table HardlinkTransactionResponse { last_modified_time: Timestamp (required); kind: FileKind; attr_response: FileMetadataResponse (required); } table XattrsResponse { xattrs: [string] (required); } table GroupChecksum { raft_group: ushort; checksum: [ubyte] (required); } table ChecksumResponse { checksums: [GroupChecksum] (required); } table FilesystemInformationResponse { block_size: uint; max_name_length: uint; } union ResponseType { EmptyResponse, ErrorResponse, ReadResponse, FileMetadataResponse, DirectoryListingResponse, WrittenResponse, LatestCommitResponse, XattrsResponse, InodeResponse, HardlinkTransactionResponse, LockResponse, RemoveLinkResponse, ChecksumResponse, NodeIdResponse, FilesystemInformationResponse } table GenericResponse { response: ResponseType; }