16
16
* specific language governing permissions and limitations
17
17
* under the License.
18
18
*/
19
- use crate :: filesystem:: { FileStat , PathFileSystem , RawFileSystem , Result } ;
19
+ use crate :: filesystem:: {
20
+ FileStat , PathFileSystem , RawFileSystem , Result , INITIAL_FILE_ID , ROOT_DIR_FILE_ID ,
21
+ ROOT_DIR_PARENT_FILE_ID , ROOT_DIR_PATH ,
22
+ } ;
20
23
use crate :: opened_file:: { FileHandle , OpenFileFlags } ;
21
24
use crate :: opened_file_manager:: OpenedFileManager ;
22
- use crate :: utils:: join_file_path;
23
25
use async_trait:: async_trait;
24
26
use bytes:: Bytes ;
25
27
use fuse3:: { Errno , FileType } ;
26
28
use std:: collections:: HashMap ;
29
+ use std:: ffi:: OsStr ;
30
+ use std:: path:: { Path , PathBuf } ;
27
31
use std:: sync:: atomic:: AtomicU64 ;
28
32
use tokio:: sync:: RwLock ;
29
33
@@ -43,16 +47,11 @@ pub struct DefaultRawFileSystem<T: PathFileSystem> {
43
47
}
44
48
45
49
impl < T : PathFileSystem > DefaultRawFileSystem < T > {
46
- const INITIAL_FILE_ID : u64 = 10000 ;
47
- const ROOT_DIR_PARENT_FILE_ID : u64 = 1 ;
48
- const ROOT_DIR_FILE_ID : u64 = 1 ;
49
- const ROOT_DIR_NAME : & ' static str = "" ;
50
-
51
50
pub ( crate ) fn new ( fs : T ) -> Self {
52
51
Self {
53
52
file_entry_manager : RwLock :: new ( FileEntryManager :: new ( ) ) ,
54
53
opened_file_manager : OpenedFileManager :: new ( ) ,
55
- file_id_generator : AtomicU64 :: new ( Self :: INITIAL_FILE_ID ) ,
54
+ file_id_generator : AtomicU64 :: new ( INITIAL_FILE_ID ) ,
56
55
fs,
57
56
}
58
57
}
@@ -70,7 +69,7 @@ impl<T: PathFileSystem> DefaultRawFileSystem<T> {
70
69
. ok_or ( Errno :: from ( libc:: ENOENT ) )
71
70
}
72
71
73
- async fn get_file_entry_by_path ( & self , path : & str ) -> Option < FileEntry > {
72
+ async fn get_file_entry_by_path ( & self , path : & Path ) -> Option < FileEntry > {
74
73
self . file_entry_manager
75
74
. read ( )
76
75
. await
@@ -123,12 +122,12 @@ impl<T: PathFileSystem> DefaultRawFileSystem<T> {
123
122
Ok ( file. file_handle ( ) )
124
123
}
125
124
126
- async fn remove_file_entry_locked ( & self , path : & str ) {
125
+ async fn remove_file_entry_locked ( & self , path : & Path ) {
127
126
let mut file_manager = self . file_entry_manager . write ( ) . await ;
128
127
file_manager. remove ( path) ;
129
128
}
130
129
131
- async fn insert_file_entry_locked ( & self , parent_file_id : u64 , file_id : u64 , path : & str ) {
130
+ async fn insert_file_entry_locked ( & self , parent_file_id : u64 , file_id : u64 , path : & Path ) {
132
131
let mut file_manager = self . file_entry_manager . write ( ) . await ;
133
132
file_manager. insert ( parent_file_id, file_id, path) ;
134
133
}
@@ -139,17 +138,17 @@ impl<T: PathFileSystem> RawFileSystem for DefaultRawFileSystem<T> {
139
138
async fn init ( & self ) -> Result < ( ) > {
140
139
// init root directory
141
140
self . insert_file_entry_locked (
142
- Self :: ROOT_DIR_PARENT_FILE_ID ,
143
- Self :: ROOT_DIR_FILE_ID ,
144
- Self :: ROOT_DIR_NAME ,
141
+ ROOT_DIR_PARENT_FILE_ID ,
142
+ ROOT_DIR_FILE_ID ,
143
+ Path :: new ( ROOT_DIR_PATH ) ,
145
144
)
146
145
. await ;
147
146
self . fs . init ( ) . await
148
147
}
149
148
150
149
async fn get_file_path ( & self , file_id : u64 ) -> Result < String > {
151
150
let file_entry = self . get_file_entry ( file_id) . await ?;
152
- Ok ( file_entry. path )
151
+ Ok ( file_entry. path . to_string_lossy ( ) . to_string ( ) )
153
152
}
154
153
155
154
async fn valid_file_handle_id ( & self , file_id : u64 , fh : u64 ) -> Result < ( ) > {
@@ -174,12 +173,15 @@ impl<T: PathFileSystem> RawFileSystem for DefaultRawFileSystem<T> {
174
173
Ok ( file_stat)
175
174
}
176
175
177
- async fn lookup ( & self , parent_file_id : u64 , name : & str ) -> Result < FileStat > {
176
+ async fn lookup ( & self , parent_file_id : u64 , name : & OsStr ) -> Result < FileStat > {
178
177
let parent_file_entry = self . get_file_entry ( parent_file_id) . await ?;
179
- let mut file_stat = self . fs . lookup ( & parent_file_entry. path , name) . await ?;
178
+
179
+ let path = parent_file_entry. path . join ( name) ;
180
+ let mut file_stat = self . fs . stat ( & path) . await ?;
180
181
// fill the file id to file stat
181
182
self . resolve_file_id_to_filestat ( & mut file_stat, parent_file_id)
182
183
. await ;
184
+
183
185
Ok ( file_stat)
184
186
}
185
187
@@ -203,11 +205,16 @@ impl<T: PathFileSystem> RawFileSystem for DefaultRawFileSystem<T> {
203
205
. await
204
206
}
205
207
206
- async fn create_file ( & self , parent_file_id : u64 , name : & str , flags : u32 ) -> Result < FileHandle > {
208
+ async fn create_file (
209
+ & self ,
210
+ parent_file_id : u64 ,
211
+ name : & OsStr ,
212
+ flags : u32 ,
213
+ ) -> Result < FileHandle > {
207
214
let parent_file_entry = self . get_file_entry ( parent_file_id) . await ?;
208
215
let mut file_without_id = self
209
216
. fs
210
- . create_file ( & parent_file_entry. path , name, OpenFileFlags ( flags) )
217
+ . create_file ( & parent_file_entry. path . join ( name) , OpenFileFlags ( flags) )
211
218
. await ?;
212
219
213
220
file_without_id. set_file_id ( parent_file_id, self . next_file_id ( ) ) ;
@@ -226,9 +233,10 @@ impl<T: PathFileSystem> RawFileSystem for DefaultRawFileSystem<T> {
226
233
Ok ( opened_file_with_file_handle_id. file_handle ( ) )
227
234
}
228
235
229
- async fn create_dir ( & self , parent_file_id : u64 , name : & str ) -> Result < u64 > {
236
+ async fn create_dir ( & self , parent_file_id : u64 , name : & OsStr ) -> Result < u64 > {
230
237
let parent_file_entry = self . get_file_entry ( parent_file_id) . await ?;
231
- let mut filestat = self . fs . create_dir ( & parent_file_entry. path , name) . await ?;
238
+ let path = parent_file_entry. path . join ( name) ;
239
+ let mut filestat = self . fs . create_dir ( & path) . await ?;
232
240
233
241
filestat. set_file_id ( parent_file_id, self . next_file_id ( ) ) ;
234
242
@@ -243,23 +251,23 @@ impl<T: PathFileSystem> RawFileSystem for DefaultRawFileSystem<T> {
243
251
self . fs . set_attr ( & file_entry. path , file_stat, true ) . await
244
252
}
245
253
246
- async fn remove_file ( & self , parent_file_id : u64 , name : & str ) -> Result < ( ) > {
254
+ async fn remove_file ( & self , parent_file_id : u64 , name : & OsStr ) -> Result < ( ) > {
247
255
let parent_file_entry = self . get_file_entry ( parent_file_id) . await ?;
248
- self . fs . remove_file ( & parent_file_entry. path , name) . await ?;
256
+ let path = parent_file_entry. path . join ( name) ;
257
+ self . fs . remove_file ( & path) . await ?;
249
258
250
259
// remove the file from file entry manager
251
- self . remove_file_entry_locked ( & join_file_path ( & parent_file_entry. path , name) )
252
- . await ;
260
+ self . remove_file_entry_locked ( & path) . await ;
253
261
Ok ( ( ) )
254
262
}
255
263
256
- async fn remove_dir ( & self , parent_file_id : u64 , name : & str ) -> Result < ( ) > {
264
+ async fn remove_dir ( & self , parent_file_id : u64 , name : & OsStr ) -> Result < ( ) > {
257
265
let parent_file_entry = self . get_file_entry ( parent_file_id) . await ?;
258
- self . fs . remove_dir ( & parent_file_entry. path , name) . await ?;
266
+ let path = parent_file_entry. path . join ( name) ;
267
+ self . fs . remove_dir ( & path) . await ?;
259
268
260
269
// remove the dir from file entry manager
261
- self . remove_file_entry_locked ( & join_file_path ( & parent_file_entry. path , name) )
262
- . await ;
270
+ self . remove_file_entry_locked ( & path) . await ;
263
271
Ok ( ( ) )
264
272
}
265
273
@@ -324,7 +332,7 @@ impl<T: PathFileSystem> RawFileSystem for DefaultRawFileSystem<T> {
324
332
struct FileEntry {
325
333
file_id : u64 ,
326
334
parent_file_id : u64 ,
327
- path : String ,
335
+ path : PathBuf ,
328
336
}
329
337
330
338
/// FileEntryManager is manage all the file entries in memory. it is used manger the file relationship and name mapping.
@@ -333,7 +341,7 @@ struct FileEntryManager {
333
341
file_id_map : HashMap < u64 , FileEntry > ,
334
342
335
343
// file_path_map is a map of file path to file entry.
336
- file_path_map : HashMap < String , FileEntry > ,
344
+ file_path_map : HashMap < PathBuf , FileEntry > ,
337
345
}
338
346
339
347
impl FileEntryManager {
@@ -348,21 +356,21 @@ impl FileEntryManager {
348
356
self . file_id_map . get ( & file_id) . cloned ( )
349
357
}
350
358
351
- fn get_file_entry_by_path ( & self , path : & str ) -> Option < FileEntry > {
359
+ fn get_file_entry_by_path ( & self , path : & Path ) -> Option < FileEntry > {
352
360
self . file_path_map . get ( path) . cloned ( )
353
361
}
354
362
355
- fn insert ( & mut self , parent_file_id : u64 , file_id : u64 , path : & str ) {
363
+ fn insert ( & mut self , parent_file_id : u64 , file_id : u64 , path : & Path ) {
356
364
let file_entry = FileEntry {
357
365
file_id,
358
366
parent_file_id,
359
- path : path. to_string ( ) ,
367
+ path : path. into ( ) ,
360
368
} ;
361
369
self . file_id_map . insert ( file_id, file_entry. clone ( ) ) ;
362
- self . file_path_map . insert ( path. to_string ( ) , file_entry) ;
370
+ self . file_path_map . insert ( path. into ( ) , file_entry) ;
363
371
}
364
372
365
- fn remove ( & mut self , path : & str ) {
373
+ fn remove ( & mut self , path : & Path ) {
366
374
if let Some ( file) = self . file_path_map . remove ( path) {
367
375
self . file_id_map . remove ( & file. file_id ) ;
368
376
}
@@ -372,23 +380,34 @@ impl FileEntryManager {
372
380
#[ cfg( test) ]
373
381
mod tests {
374
382
use super :: * ;
383
+ use crate :: filesystem:: tests:: TestRawFileSystem ;
384
+ use crate :: memory_filesystem:: MemoryFileSystem ;
375
385
376
386
#[ test]
377
387
fn test_file_entry_manager ( ) {
378
388
let mut manager = FileEntryManager :: new ( ) ;
379
- manager. insert ( 1 , 2 , "a/b" ) ;
389
+ manager. insert ( 1 , 2 , Path :: new ( "a/b" ) ) ;
380
390
let file = manager. get_file_entry_by_id ( 2 ) . unwrap ( ) ;
381
391
assert_eq ! ( file. file_id, 2 ) ;
382
392
assert_eq ! ( file. parent_file_id, 1 ) ;
383
- assert_eq ! ( file. path, "a/b" ) ;
393
+ assert_eq ! ( file. path, Path :: new ( "a/b" ) ) ;
384
394
385
- let file = manager. get_file_entry_by_path ( "a/b" ) . unwrap ( ) ;
395
+ let file = manager. get_file_entry_by_path ( Path :: new ( "a/b" ) ) . unwrap ( ) ;
386
396
assert_eq ! ( file. file_id, 2 ) ;
387
397
assert_eq ! ( file. parent_file_id, 1 ) ;
388
- assert_eq ! ( file. path, "a/b" ) ;
398
+ assert_eq ! ( file. path, Path :: new ( "a/b" ) ) ;
389
399
390
- manager. remove ( "a/b" ) ;
400
+ manager. remove ( Path :: new ( "a/b" ) ) ;
391
401
assert ! ( manager. get_file_entry_by_id( 2 ) . is_none( ) ) ;
392
- assert ! ( manager. get_file_entry_by_path( "a/b" ) . is_none( ) ) ;
402
+ assert ! ( manager. get_file_entry_by_path( Path :: new( "a/b" ) ) . is_none( ) ) ;
403
+ }
404
+
405
+ #[ tokio:: test]
406
+ async fn test_default_raw_file_system ( ) {
407
+ let memory_fs = MemoryFileSystem :: new ( ) . await ;
408
+ let raw_fs = DefaultRawFileSystem :: new ( memory_fs) ;
409
+ let _ = raw_fs. init ( ) . await ;
410
+ let mut tester = TestRawFileSystem :: new ( raw_fs) ;
411
+ tester. test_raw_file_system ( ) . await ;
393
412
}
394
413
}
0 commit comments