@@ -25,6 +25,9 @@ type buf_reader =
25
25
fn eof ( ) -> bool ;
26
26
fn seek ( int , seek_style ) ;
27
27
fn tell ( ) -> uint ;
28
+ // Needed on readers in case one needs to flush metadata
29
+ // changes (atime)
30
+ fn fsync ( level : fsync:: level ) -> int ;
28
31
} ;
29
32
30
33
@@ -58,7 +61,9 @@ fn convert_whence(whence: seek_style) -> i32 {
58
61
} ;
59
62
}
60
63
61
- resource FILE_res ( f: os:: libc:: FILE ) { os:: libc:: fclose ( f) ; }
64
+ resource FILE_res ( f: os:: libc:: FILE ) {
65
+ os:: libc:: fclose ( f) ;
66
+ }
62
67
63
68
obj FILE_buf_reader ( f: os:: libc:: FILE , res: option:: t<@FILE_res >) {
64
69
fn read ( len : uint ) -> [ u8 ] unsafe {
@@ -76,6 +81,9 @@ obj FILE_buf_reader(f: os::libc::FILE, res: option::t<@FILE_res>) {
76
81
assert ( os:: libc:: fseek ( f, offset, convert_whence ( whence) ) == 0i32 ) ;
77
82
}
78
83
fn tell ( ) -> uint { ret os:: libc:: ftell ( f) as uint ; }
84
+ fn fsync ( level : fsync:: level ) -> int {
85
+ ret os:: fsync_fd ( os:: libc:: fileno ( f) , level) as int ;
86
+ }
79
87
}
80
88
81
89
@@ -219,6 +227,7 @@ obj byte_buf_reader(bbuf: byte_buf) {
219
227
bbuf. pos = seek_in_buf ( offset, pos, len, whence) ;
220
228
}
221
229
fn tell ( ) -> uint { ret bbuf. pos ; }
230
+ fn fsync ( _level : fsync:: level ) -> int { ret 0 ; }
222
231
}
223
232
224
233
fn new_byte_buf_reader ( buf : [ u8 ] ) -> buf_reader {
@@ -242,6 +251,8 @@ type buf_writer =
242
251
fn write ( [ u8 ] ) ;
243
252
fn seek ( int , seek_style ) ;
244
253
fn tell ( ) -> uint ;
254
+ fn flush ( ) -> int ;
255
+ fn fsync ( level : fsync:: level ) -> int ;
245
256
} ;
246
257
247
258
obj FILE_writer ( f: os:: libc:: FILE , res: option:: t<@FILE_res >) {
@@ -255,6 +266,10 @@ obj FILE_writer(f: os::libc::FILE, res: option::t<@FILE_res>) {
255
266
assert ( os:: libc:: fseek ( f, offset, convert_whence ( whence) ) == 0i32 ) ;
256
267
}
257
268
fn tell ( ) -> uint { ret os:: libc:: ftell ( f) as uint ; }
269
+ fn flush ( ) -> int { ret os:: libc:: fflush ( f) as int ; }
270
+ fn fsync ( level : fsync:: level ) -> int {
271
+ ret os:: fsync_fd ( os:: libc:: fileno ( f) , level) as int ;
272
+ }
258
273
}
259
274
260
275
resource fd_res( fd: fd_t) { os:: libc:: close ( fd) ; }
@@ -283,6 +298,12 @@ obj fd_buf_writer(fd: fd_t, res: option::t<@fd_res>) {
283
298
log_err "need 64-bit native calls for tell, sorry" ;
284
299
fail;
285
300
}
301
+
302
+ fn flush ( ) -> int { ret 0 ; }
303
+
304
+ fn fsync ( level : fsync:: level ) -> int {
305
+ ret os:: fsync_fd ( fd, level) as int ;
306
+ }
286
307
}
287
308
288
309
fn file_buf_writer ( path : str ,
@@ -433,6 +454,8 @@ obj byte_buf_writer(buf: mutable_byte_buf) {
433
454
buf. pos = seek_in_buf ( offset, pos, len, whence) ;
434
455
}
435
456
fn tell ( ) -> uint { ret buf. pos ; }
457
+ fn flush ( ) -> int { ret 0 ; }
458
+ fn fsync ( _level : fsync:: level ) -> int { ret 0 ; }
436
459
}
437
460
438
461
fn string_writer ( ) -> str_writer {
@@ -477,6 +500,75 @@ fn read_whole_file(file: str) -> result::t<[u8], str> {
477
500
} )
478
501
}
479
502
503
+ // fsync related
504
+
505
+ mod fsync {
506
+
507
+ tag level {
508
+ // whatever fsync does on that platform
509
+ fsync;
510
+
511
+ // fdatasync on linux, similiar or more on other platforms
512
+ fdatasync;
513
+
514
+ // full fsync
515
+ //
516
+ // You must additionally sync the parent directory as well!
517
+ fullfsync;
518
+ }
519
+
520
+
521
+ // Resource of artifacts that need to fsync on destruction
522
+ resource res<t>( arg: arg<t>) {
523
+ alt arg. opt_level {
524
+ option:: none :: < level > . { }
525
+ option:: some :: < level > ( level) {
526
+ // fail hard if not succesful
527
+ assert ( arg. fsync_fn ( arg. val , level) != -1 ) ;
528
+ }
529
+ }
530
+ }
531
+
532
+ type arg<t> = {
533
+ val: t,
534
+ opt_level: option:: t<level>,
535
+ fsync_fn: fn ( t, level) -> int
536
+ } ;
537
+
538
+ // fsync file after executing blk
539
+ // FIXME find better way to create resources within lifetime of outer res
540
+ fn FILE_res_sync ( & & file: FILE_res , opt_level : option:: t < level > ,
541
+ blk : block ( & & res < os:: libc:: FILE > ) ) {
542
+ blk ( res ( {
543
+ val: * file, opt_level: opt_level,
544
+ fsync_fn : fn ( & & file: os:: libc:: FILE , l: level) -> int {
545
+ ret os:: fsync_fd ( os:: libc:: fileno ( file) , l) as int ;
546
+ }
547
+ } ) ) ;
548
+ }
549
+
550
+ // fsync fd after executing blk
551
+ fn fd_res_sync ( & & fd: fd_res , opt_level : option:: t < level > ,
552
+ blk : block ( & & res < fd_t > ) ) {
553
+ blk ( res ( {
554
+ val: * fd, opt_level: opt_level,
555
+ fsync_fn : fn ( & & fd: fd_t, l: level) -> int {
556
+ ret os:: fsync_fd ( fd, l) as int ;
557
+ }
558
+ } ) ) ;
559
+ }
560
+
561
+ // Type of objects that may want to fsync
562
+ type t = obj { fn fsync ( l : level ) -> int ; } ;
563
+
564
+ // Call o.fsync after executing blk
565
+ fn obj_sync ( & & o: t , opt_level : option:: t < level > , blk : block ( & & res < t > ) ) {
566
+ blk ( res ( {
567
+ val: o, opt_level: opt_level,
568
+ fsync_fn: fn ( & & o: t, l: level) -> int { ret o. fsync ( l) ; }
569
+ } ) ) ;
570
+ }
571
+ }
480
572
481
573
482
574
//
0 commit comments