1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
use cyfs_base::*;

use async_trait::async_trait;
use int_enum::IntEnum;

#[derive(Debug, Clone)]
pub struct FileDirRef {
    pub dir_id: DirId,
    pub inner_path: String,
}

#[derive(Debug)]
pub struct FileCacheData {
    pub hash: String,

    pub file_id: FileId,

    pub length: u64,

    pub flags: u32,

    pub owner: Option<ObjectId>,

    // 可选,关联的quickhash
    pub quick_hash: Option<Vec<String>>,

    // 可选,关联的dirs
    pub dirs: Option<Vec<FileDirRef>>,
}

pub struct InsertFileRequest {
    pub file_id: FileId,

    // 需要插入的file对象
    pub file: File,

    pub flags: u32,

    // 关联的quickhash
    pub quick_hash: Option<Vec<String>>,

    // 关联的dirs信息
    pub dirs: Option<Vec<FileDirRef>>,
}

pub struct RemoveFileRequest {
    pub file_id: FileId,
}

// quickhash相关操作
pub struct FileAddQuickhashRequest {
    pub hash: String,
    
    // TODO 是否支持以file_id为键值来更新?
    // pub file_id: FileId,

    pub quick_hash: Vec<String>,
}

pub struct FileUpdateQuickhashRequest {
    pub hash: String,
    
    // TODO 是否支持以file_id为键值来更新?
    // pub file_id: FileId,

    pub add_list: Vec<String>,
    pub remove_list: Vec<String>,
}

// GetFileByHashRequest的标志位,表示是不是要获取对应的信息
pub const NDC_FILE_REQUEST_FLAG_QUICK_HASN: u32 = 0x01 << 1;
pub const NDC_FILE_REQUEST_FLAG_REF_DIRS: u32 = 0x01 << 2;

pub struct GetFileByHashRequest {
    pub hash: String,

    pub flags: u32,
}

pub struct GetFileByFileIdRequest {
    pub file_id: FileId,

    pub flags: u32,
}

pub struct GetFileByQuickHashRequest {
    pub quick_hash: String,
    pub length: u64,
    pub flags: u32,
}

pub struct GetFileByChunkRequest {
    pub chunk_id: ChunkId,
    pub flags: u32,
}

pub struct GetDirByFileRequest {
    pub file_id: FileId,
    pub flags: u32,
}

// chunk的状态
// chunk和object的关系
#[repr(u8)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, IntEnum)]
pub enum ChunkObjectRelation {
    Unknown = 0,
    FileBody = 1,
    DirMeta = 2,
}

impl Into<u8> for ChunkObjectRelation {
    fn into(self) -> u8 {
        unsafe { std::mem::transmute(self as u8) }
    }
}

impl From<u8> for ChunkObjectRelation {
    fn from(code: u8) -> Self {
        match ChunkObjectRelation::from_int(code) {
            Ok(code) => code,
            Err(e) => {
                error!("unknown ChunkObjectRelation code: {} {}", code, e);
                ChunkObjectRelation::Unknown
            }
        }
    }
}

// chunk关联的对象
#[derive(Debug, Clone)]
pub struct ChunkObjectRef {
    pub object_id: ObjectId,
    pub relation: ChunkObjectRelation,
}

//#[derive(Clone)]
pub struct InsertChunkRequest {
    pub chunk_id: ChunkId,

    pub state: ChunkState,

    // 有关系的对象
    pub ref_objects: Option<Vec<ChunkObjectRef>>,

    // 所属的trans_session列表
    pub trans_sessions: Option<Vec<String>>,

    pub flags: u32,
}

pub struct RemoveChunkRequest {
    pub chunk_id: ChunkId,
}

// GetChunkRequest的额外查询信息
pub const NDC_CHUNK_REQUEST_FLAG_TRANS_SESSIONS: u32 = 0x01 << 1;
pub const NDC_CHUNK_REQUEST_FLAG_REF_OBJECTS: u32 = 0x01 << 2;

pub struct GetChunkRequest {
    pub chunk_id: ChunkId,
    pub flags: u32,
}

pub struct ExistsChunkRequest {
    pub chunk_list: Vec<ChunkId>,
    pub states: Vec<ChunkState>,
}

pub struct ChunkCacheData {
    pub chunk_id: ChunkId,

    pub state: ChunkState,
    pub flags: u32,
    
    pub insert_time: u64,
    pub update_time: u64,
    pub last_access_time: u64,

    pub trans_sessions: Option<Vec<String>>,
    pub ref_objects: Option<Vec<ChunkObjectRef>>,
}


pub struct UpdateChunkStateRequest {
    pub chunk_id: ChunkId,

    // 如果指定了当前状态,那么只有在匹配情况下才更新到目标状态
    pub current_state: Option<ChunkState>,
    
    pub state: ChunkState,
}

pub struct UpdateChunkTransSessionRequest {
    pub chunk_id: ChunkId,

    pub add_list: Vec<String>,
    pub remove_list: Vec<String>,
}

pub struct UpdateChunkRefsRequest {
    pub chunk_id: ChunkId,

    pub add_list: Vec<ChunkObjectRef>,
    pub remove_list: Vec<ChunkObjectRef>,
}

pub struct GetChunkTransSessionsRequest {
    pub chunk_id: ChunkId,
}

pub struct GetChunkTransSessionsResponse {
    pub chunk_id: ChunkId,
    pub trans_sessions: Option<Vec<String>>,
}

pub struct GetChunkRefObjectsRequest {
    pub chunk_id: ChunkId,
    pub relation: Option<ChunkObjectRelation>,
}

pub struct GetChunkRefObjectsResponse {
    pub chunk_id: ChunkId,
    pub ref_objects: Option<ChunkObjectRef>,
}

#[async_trait]
pub trait NamedDataCache: Sync + Send + 'static {

    fn clone(&self) -> Box<dyn NamedDataCache>;

    // file相关接口
    async fn insert_file(&self, req: &InsertFileRequest) -> BuckyResult<()>;
    async fn remove_file(&self, req: &RemoveFileRequest) -> BuckyResult<usize>;

    async fn file_update_quick_hash(&self, req: &FileUpdateQuickhashRequest) -> BuckyResult<()>;

    async fn get_file_by_hash(&self, req: &GetFileByHashRequest) -> BuckyResult<Option<FileCacheData>>;
    async fn get_file_by_file_id(&self, req: &GetFileByFileIdRequest) -> BuckyResult<Option<FileCacheData>>;
    async fn get_files_by_quick_hash(&self, req: &GetFileByQuickHashRequest) -> BuckyResult<Vec<FileCacheData>>;
    async fn get_files_by_chunk(&self, req: &GetFileByChunkRequest) -> BuckyResult<Vec<FileCacheData>>;
    async fn get_dirs_by_file(&self, req: &GetDirByFileRequest) -> BuckyResult<Vec<FileDirRef>>;

    // chunk相关接口
    async fn insert_chunk(&self, req: &InsertChunkRequest) -> BuckyResult<()>;
    async fn remove_chunk(&self, req: &RemoveChunkRequest) -> BuckyResult<usize>;

    async fn update_chunk_state(&self, req: &UpdateChunkStateRequest) -> BuckyResult<ChunkState>;
    //async fn update_chunk_trans_session(&self, req: &UpdateChunkTransSessionRequest) -> BuckyResult<()>;
    async fn update_chunk_ref_objects(&self, req: &UpdateChunkRefsRequest) -> BuckyResult<()>;

    async fn exists_chunks(&self, req: &ExistsChunkRequest) -> BuckyResult<Vec<bool>>;

    async fn get_chunk(&self, req: &GetChunkRequest) -> BuckyResult<Option<ChunkCacheData>>;
    async fn get_chunks(&self, req: &Vec<GetChunkRequest>) -> BuckyResult<Vec<Option<ChunkCacheData>>>;
    //async fn get_chunk_trans_sessions(&self, req: &GetChunkTransSessionsRequest) -> BuckyResult<GetChunkTransSessionsResponse>;
    async fn get_chunk_ref_objects(&self, req: &GetChunkRefObjectsRequest) -> BuckyResult<Vec<ChunkObjectRef>>;
}