/**
 * Communication protocol between FUSE client and the server.
 * @author Krzysztof Trzepla
 * @copyright (C) 2015 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in
 * 'LICENSE.txt'
 */

syntax = "proto2";
package one.clproto;

import "common_messages.proto";

enum FileType {
    REG = 1; // regular file
    DIR = 2; // directory
    LNK = 3; // hard link
    SYMLNK = 4; // symbolic link
}

enum HelperMode {
    AUTO         = 1; // automatic helper mode detection
    FORCE_PROXY  = 2; // return proxy io helper or error
    FORCE_DIRECT = 3; // return direct io helper or error
}

// Generic FUSE client request
message FuseRequest {
    oneof fuse_request { // list of all FUSE client requests
        ResolveGuid resolve_guid = 1;
        GetHelperParams get_helper_params = 2;
        CreateStorageTestFile create_storage_test_file = 3;
        VerifyStorageTestFile verify_storage_test_file = 4;
        FileRequest file_request = 5;
        GetFSStats get_fs_stats = 6;
        MultipartUploadRequest multipart_upload_request = 7;
    }
}

message MultipartUploadRequest {
    oneof multipart_request {
        CreateMultipartUpload create_multipart_upload = 1;
        UploadMultipartPart upload_multipart_part = 2;
        ListMultipartParts list_multipart_parts = 3;
        AbortMultipartUpload abort_multipart_upload = 4;
        CompleteMultipartUpload complete_multipart_upload = 5;
        ListMultipartUploads list_multipart_uploads = 6;
    }
}

message MultipartUpload {
    required bytes multipart_upload_id = 1;
    required bytes path = 2;
    required uint64 creation_time = 3;
}

message MultipartUploads {
    repeated MultipartUpload uploads = 1;
    optional bool is_last = 2;
    optional bytes next_page_token = 3;
}

// Sender: Oneclient
// Response: MultipartUploads
// Returns the list of ongoing multipart uploads of current user in specific space.
// The results must be paged and ordered by key path and then creation time (multiple uploads can exist for
// the same path).
// This does not include uploads which are already aborted or completed.
message ListMultipartUploads {
    required bytes space_id = 1;
    optional uint32 limit = 2; // default 1000
    optional bytes index_token = 3;
}

// Sender: Oneclient
// Response: MultipartUpload
// Creates a record in the database representing a new multipart upload for specific space and path.
// Multiple multipart uploads can exist for the same path.
message CreateMultipartUpload {
    required bytes space_id = 1;
    required bytes path = 2;
}

message MultipartPart {
    required uint32 number = 1;
    required uint64 size = 2;
    required bytes etag = 3;
    required uint64 last_modified = 4;
}

message MultipartParts {
    repeated MultipartPart parts = 1;
    optional bool is_last = 2;
}

// Sender: Oneclient
// Response: Status[ok]
// Registers a new multipart upload part in the database. If the part with the same number is already registered
// under the same multipart upload id, it must be overriden by this message.
// Returns EINVAL if the multipart_upload_id is invalid or multipart upload is already completed or canceled.
message UploadMultipartPart {
    required bytes multipart_upload_id = 1;
    required MultipartPart part = 2;
}

// Sender: Oneclient
// Response: MultipartParts
// Returns EINVAL if the multipart_upload_id is invalid or multipart upload is already completed or canceled.
message ListMultipartParts {
    required bytes multipart_upload_id = 1;
    optional int32 limit = 2; // default 1000
    optional int64 part_marker = 3;
}

// Sender: Oneclient
// Response: Status
// Returns EINVAL if the multipart_upload_id is invalid or multipart upload is already completed or canceled.
message CompleteMultipartUpload {
    required bytes multipart_upload_id = 1;
}

// Sender: Oneclient
// Response: Status
// Returns EINVAL if the multipart_upload_id is invalid or multipart upload is already completed or canceled.
message AbortMultipartUpload {
    required bytes multipart_upload_id = 1;
}

message ResolveGuid {
    required bytes path = 1;
}

message GetFSStats {
    required bytes file_id = 1;
}

message GetHelperParams {
    required bytes storage_id       = 1;
    required bytes space_id         = 2;
    optional HelperMode helper_mode = 3;
}

message CreateStorageTestFile {
    required bytes storage_id = 1;
    required bytes file_uuid  = 2;
}

message VerifyStorageTestFile {
    required bytes storage_id   = 1;
    required bytes space_id     = 2;
    required bytes file_id      = 3;
    required bytes file_content = 4;
}

// Generic FUSE client file request
message FileRequest {
    required bytes context_guid = 1;

    oneof file_request { // list of all FUSE client file requests
        GetFileAttr get_file_attr = 2;
        GetChildAttr get_child_attr = 3;
        GetFileChildren get_file_children = 4;
        CreateDir create_dir = 5;
        DeleteFile delete_file = 6;
        UpdateTimes update_times = 7;
        ChangeMode change_mode = 8;
        Rename rename = 9;
        CreateFile create_file = 10;
        MakeFile make_file = 11;
        OpenFile open_file = 12;
        GetFileLocation get_file_location = 13;
        Release release = 14;
        Truncate truncate = 15;
        SynchronizeBlock synchronize_block = 16;
        SynchronizeBlockAndComputeChecksum synchronize_block_and_compute_checksum = 17;
        GetXattr get_xattr = 18;
        SetXattr set_xattr = 19;
        RemoveXattr remove_xattr = 20;
        ListXattr list_xattr = 21;
        FSync fsync = 22;
        GetFileChildrenAttrs get_file_children_attrs = 23;
        StorageFileCreated storage_file_created = 24;
        OpenFileWithExtendedInfo open_file_with_extended_info = 25;
        BlockSynchronizationRequest block_synchronization_request = 26;
        MakeLink make_link = 27;
        MakeSymlink make_symlink = 28;
        ReadSymlink read_symlink = 29;
        GetFileAttrByPath get_file_attr_by_path = 30;
        CreatePath create_path = 31;
        ReportFileWritten file_written_range = 32;
        ReportFileRead file_read_range = 33;
        ListFilesRecursively list_files_recursively = 34;
    }
}

message GetFileAttr {
    optional bool include_replication_status = 1;
    optional bool include_link_count = 2;
    repeated bytes xattrs = 3;
}

message GetChildAttr {
    required bytes name = 1;
    optional bool include_replication_status = 2;
    optional bool include_link_count = 3;
    repeated bytes xattrs = 4;
}

message GetFileChildren {
    required int32 offset = 1;
    required int32 size = 2;
    optional bytes index_token = 3;
    optional bytes index_startid = 4;
}

message GetFileChildrenAttrs {
    required int32 offset = 1;
    required int32 size = 2;
    optional bytes index_token = 3;
    optional bool include_replication_status = 4;
    optional bool include_link_count = 5;
    repeated bytes xattrs = 6;
}

message CreateDir {
    required bytes name = 1;
    required uint32 mode = 2;
}

message DeleteFile {
    optional bool  silent = 1;
}

message UpdateTimes {
    optional uint64 atime = 1;
    optional uint64 mtime = 2;
    optional uint64 ctime = 3;
}

message ChangeMode {
    required uint32 mode = 1;
}

message Rename {
    required bytes target_parent_uuid = 1;
    required bytes target_name = 2;
}

message CreateFile {
    required bytes name = 1;
    required uint32 mode = 2;
    required OpenFlag flag = 3;
}

message MakeFile {
    required bytes name = 1;
    required uint32 mode = 2;
}

message OpenFile {
    required OpenFlag flag = 1;
}

message OpenFileWithExtendedInfo {
    required OpenFlag flag = 1;
}

message GetFileLocation {
}

message Release {
    required bytes handle_id = 1;
}

message Truncate {
    required uint64 size = 1;
}

message SynchronizeBlock {
    required FileBlock block    = 1;
    optional bool      prefetch = 2;
    optional int32     priority = 3;
}

message SynchronizeBlockAndComputeChecksum {
    required FileBlock block = 1;
    optional bool      prefetch = 2;
    optional int32     priority = 3;
}

message BlockSynchronizationRequest {
    required FileBlock block    = 1;
    optional bool      prefetch = 2;
    optional int32     priority = 3;
}

message Xattr {
    required bytes name = 1;
    required bytes value = 2;
}

message GetXattr {
    required bytes name = 1;
    optional bool inherited = 2;
}

message SetXattr {
    required Xattr xattr = 1;
    optional bool create = 2;
    optional bool replace = 3;
}

message RemoveXattr {
    required bytes name = 1;
}

message ListXattr {
    optional bool inherited = 1;
    optional bool show_internal = 2;
}

message FSync {
    optional bool data_only = 1;
    optional bytes handle_id = 2;
}

message StorageFileCreated {
}

message MakeLink {
    required bytes target_parent_uuid = 1;
    required bytes target_name = 2;
}

message MakeSymlink {
    required bytes target_name = 1;
    required bytes link = 2;
}

message ReadSymlink {
}

// Generic FUSE client response
message FuseResponse {
    required Status status = 1;

    oneof fuse_response { // list of all FUSE client responses
        FileAttr file_attr = 2;
        FileChildren file_children = 3;
        FileLocation file_location = 4;
        HelperParams helper_params = 5;
        StorageTestFile storage_test_file = 6;
        Dir dir = 7;
        SyncResponse sync_response = 8;
        FileRenamed file_renamed = 9;
        FileCreated file_created = 10;
        FileOpened file_opened = 11;
        Uuid uuid = 12;
        Xattr xattr = 13;
        XattrList xattr_list = 14;
        FileChildrenAttrs file_children_attrs = 15;
        FileLocationChanged file_location_changed = 16;
        FileOpenedExtended file_opened_extended = 17;
        FSStats fs_stats = 18;
        Symlink symlink = 19;
        MultipartParts multipart_parts = 20;
        MultipartUpload multipart_upload = 21;
        MultipartUploads multipart_uploads = 22;
        FileList files_list = 23;
    }
}

message FileAttr {
    required bytes uuid = 1;
    required bytes name = 2;
    required uint32 mode = 3;
    required uint32 uid = 4;
    required uint32 gid = 5;
    required uint64 atime = 6;
    required uint64 mtime = 7;
    required uint64 ctime = 8;
    required FileType type = 9;
    optional uint64 size = 10;
    repeated bytes shares = 11;
    required bytes provider_id = 12;
    required bytes owner_id = 13;
    optional bytes parent_uuid = 14;
    optional bool fully_replicated = 15;
    optional uint32 nlink = 16;
    required bytes index = 17;
    repeated Xattr xattrs = 18;
}

message FileChildren {
    repeated ChildLink child_links = 1;
    optional bytes index_token = 2;
    optional bool is_last = 3;
}

message FileChildrenAttrs {
    repeated FileAttr child_attrs = 1;
    optional bytes index_token = 2;
    optional bool is_last = 3;
}

message FileLocationChanged {
    required FileLocation file_location = 1;
    optional uint64 change_beg_offset = 2;
    optional uint64 change_end_offset = 3;
}

message FileLocation {
    required bytes uuid = 1;
    required bytes provider_id = 2;
    required bytes space_id = 3;
    required bytes storage_id = 4;
    required bytes file_id = 5;
    repeated FileBlock blocks = 6;
    required uint64 version = 7;
}

message FileCreated {
    required bytes handle_id = 1;
    required FileAttr file_attr = 2;
    required FileLocation file_location = 3;
}

message FileOpened {
    required bytes handle_id = 1;
}

message FileOpenedExtended {
    required bytes handle_id = 1;
    required bytes provider_id = 2;
    required bytes file_id = 3;
    required bytes storage_id = 4;
}

message HelperArg {
    required string key = 1;
    required string value = 2;
}

message HelperParams {
    required bytes helper_name = 1;
    repeated HelperArg helper_args = 2;
}

message StorageTestFile {
    required HelperParams helper_params = 1;
    required bytes        space_id      = 2;
    required bytes        file_id       = 3;
    required bytes        file_content  = 4;
}

message SyncResponse {
    required bytes checksum = 1;
    required FileLocationChanged file_location_changed = 2;
}

message FileRenamed {
    required bytes new_uuid = 1;
    repeated FileRenamedEntry child_entries = 2; // entries for children of
                                                 // renamed file
}

message Uuid {
    required bytes uuid = 1;
}

message XattrList {
    repeated bytes names = 1;
}

message StorageStats {
    required bytes storage_id = 1;
    required uint64 size = 2;
    required uint64 occupied = 3;
}

message FSStats {
    required bytes space_id = 1;
    repeated StorageStats storage_stats = 2;
}

message Symlink {
    required bytes link = 1;
}

// Sender: Oneclient
// Response: FileAttr
// Returns attr of the file pointed by the path relative to space or directory determined by context_guid
// or error if path does not exist
message GetFileAttrByPath {
    required bytes path = 1;
    repeated bytes xattrs = 2;
}

// Sender: Oneclient
// Response: FileAttr
// If path already exists, it returns the FileAttr of the last directory on the path
// If path already exists and points to a file, returns ENOTDIR
// If path doesn't exist, it creates all directories necessary and returns new FileAttr
message CreatePath {
    required bytes path = 1;
}

// Sender: Oneclient
// Response: Status[ok]
// Updates the file location - if necessary - of a file identified by context_guid
message ReportFileWritten {
    required uint64 offset = 1;
    required uint64 size = 2;
}

// Sender: Oneclient
// Response: Status[ok]
// Updates the read map of a file identified by context_guid
message ReportFileRead {
    required uint64 offset = 1;
    required uint64 size = 2;
}

message FileList {
    repeated FileAttr files = 1;
    optional bool is_last = 2;
    optional bytes next_page_token = 3;
}

// Sender: Oneclient
// Response: FileList
// Recursively lists non-directory files (i.e regular files, symbolic links and hardlinks) in directory specified by context_guid (listing root).
// Files are listed in lexicographical order by their paths, which are relative to the listing root directory (context_guid).
message ListFilesRecursively {
    optional bytes token = 1;
    optional bytes start_after = 2;
    optional bytes prefix = 3;
    optional uint32 limit = 4;
    optional bool include_dirs = 5;
    repeated bytes xattrs = 6;
}

