@@ -17,6 +17,8 @@ use libc::{c_int, c_uint, c_void};
17
17
use ops:: Drop ;
18
18
use option:: * ;
19
19
use ptr;
20
+ use str;
21
+ use path:: Path ;
20
22
use result:: * ;
21
23
use rt:: io:: IoError ;
22
24
use rt:: io:: net:: ip:: { SocketAddr , IpAddr } ;
@@ -455,6 +457,68 @@ impl IoFactory for UvIoFactory {
455
457
let home = get_handle_to_current_scheduler ! ( ) ;
456
458
Ok ( ~UvTimer :: new ( watcher, home) )
457
459
}
460
+
461
+ fn fs_from_raw_fd ( & mut self , fd : c_int , close_on_drop : bool ) -> ~RtioFileDescriptor {
462
+ ~UvFileDescriptor {
463
+ loop_ : Loop { handle : self . uv_loop ( ) . native_handle ( ) } ,
464
+ fd : file:: FileDescriptor ( fd) ,
465
+ close_on_drop : close_on_drop
466
+ } as ~RtioFileDescriptor
467
+ }
468
+
469
+ fn fs_open ( & mut self , path : Path , flags : int , mode : int )
470
+ -> Result < ~RtioFileDescriptor , IoError > {
471
+ let loop_ = Loop { handle : self . uv_loop ( ) . native_handle ( ) } ;
472
+ let result_cell = Cell :: new_empty ( ) ;
473
+ let result_cell_ptr: * Cell < Result < ~RtioFileDescriptor , IoError > > = & result_cell;
474
+ let path_cell = Cell :: new ( path) ;
475
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
476
+ do scheduler. deschedule_running_task_and_then |_, task| {
477
+ let task_cell = Cell :: new ( task) ;
478
+ let path = path_cell. take ( ) ;
479
+ do file:: FileDescriptor :: open ( loop_, path, flags, mode) |req, err| {
480
+ if err. is_none ( ) {
481
+ let res = Ok ( ~UvFileDescriptor {
482
+ loop_ : loop_,
483
+ fd : file:: FileDescriptor ( req. get_result ( ) ) ,
484
+ close_on_drop : true } as ~RtioFileDescriptor ) ;
485
+ unsafe { ( * result_cell_ptr) . put_back ( res) ; }
486
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
487
+ scheduler. resume_blocked_task_immediately ( task_cell. take ( ) ) ;
488
+ } else {
489
+ let res = Err ( uv_error_to_io_error ( err. unwrap ( ) ) ) ;
490
+ unsafe { ( * result_cell_ptr) . put_back ( res) ; }
491
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
492
+ scheduler. resume_blocked_task_immediately ( task_cell. take ( ) ) ;
493
+ }
494
+ } ;
495
+ } ;
496
+ assert ! ( !result_cell. is_empty( ) ) ;
497
+ return result_cell. take ( ) ;
498
+ }
499
+
500
+ fn fs_unlink ( & mut self , path : Path ) -> Result < ( ) , IoError > {
501
+ let loop_ = Loop { handle : self . uv_loop ( ) . native_handle ( ) } ;
502
+ let result_cell = Cell :: new_empty ( ) ;
503
+ let result_cell_ptr: * Cell < Result < ( ) , IoError > > = & result_cell;
504
+ let path_cell = Cell :: new ( path) ;
505
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
506
+ do scheduler. deschedule_running_task_and_then |_, task| {
507
+ let task_cell = Cell :: new ( task) ;
508
+ let path = path_cell. take ( ) ;
509
+ do file:: FileDescriptor :: unlink ( loop_, path) |_, err| {
510
+ let res = match err {
511
+ None => Ok ( ( ) ) ,
512
+ Some ( err) => Err ( uv_error_to_io_error ( err) )
513
+ } ;
514
+ unsafe { ( * result_cell_ptr) . put_back ( res) ; }
515
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
516
+ scheduler. resume_blocked_task_immediately ( task_cell. take ( ) ) ;
517
+ } ;
518
+ } ;
519
+ assert ! ( !result_cell. is_empty( ) ) ;
520
+ return result_cell. take ( ) ;
521
+ }
458
522
}
459
523
460
524
pub struct UvTcpListener {
@@ -992,6 +1056,73 @@ impl RtioTimer for UvTimer {
992
1056
}
993
1057
}
994
1058
1059
+ pub struct UvFileDescriptor {
1060
+ loop_ : Loop ,
1061
+ fd : file:: FileDescriptor ,
1062
+ close_on_drop : bool
1063
+ }
1064
+
1065
+ impl UvFileDescriptor {
1066
+ }
1067
+
1068
+ impl Drop for UvFileDescriptor {
1069
+ fn drop ( & self ) {
1070
+ if self . close_on_drop {
1071
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
1072
+ do scheduler. deschedule_running_task_and_then |_, task| {
1073
+ let task_cell = Cell :: new ( task) ;
1074
+ do self. fd . close ( self . loop_ ) |_, _| {
1075
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
1076
+ scheduler. resume_blocked_task_immediately ( task_cell. take ( ) ) ;
1077
+ } ;
1078
+ } ;
1079
+ }
1080
+ }
1081
+ }
1082
+
1083
+ impl RtioFileDescriptor for UvFileDescriptor {
1084
+ fn read ( & mut self , buf : & mut [ u8 ] , offset : i64 ) -> Result < int , IoError > {
1085
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
1086
+ let result_cell = Cell :: new_empty ( ) ;
1087
+ let result_cell_ptr: * Cell < Result < int , IoError > > = & result_cell;
1088
+ let buf_ptr: * & mut [ u8 ] = & buf;
1089
+ do scheduler. deschedule_running_task_and_then |_, task| {
1090
+ let buf = unsafe { slice_to_uv_buf ( * buf_ptr) } ;
1091
+ let task_cell = Cell :: new ( task) ;
1092
+ do self. fd . read ( self . loop_ , buf, offset) |req, uverr| {
1093
+ let res = match uverr {
1094
+ None => Ok ( req. get_result ( ) as int ) ,
1095
+ Some ( err) => Err ( uv_error_to_io_error ( err) )
1096
+ } ;
1097
+ unsafe { ( * result_cell_ptr) . put_back ( res) ; }
1098
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
1099
+ scheduler. resume_blocked_task_immediately ( task_cell. take ( ) ) ;
1100
+ } ;
1101
+ } ;
1102
+ result_cell. take ( )
1103
+ }
1104
+ fn write ( & mut self , buf : & [ u8 ] , offset : i64 ) -> Result < ( ) , IoError > {
1105
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
1106
+ let result_cell = Cell :: new_empty ( ) ;
1107
+ let result_cell_ptr: * Cell < Result < ( ) , IoError > > = & result_cell;
1108
+ let buf_ptr: * & [ u8 ] = & buf;
1109
+ do scheduler. deschedule_running_task_and_then |_, task| {
1110
+ let buf = unsafe { slice_to_uv_buf ( * buf_ptr) } ;
1111
+ let task_cell = Cell :: new ( task) ;
1112
+ do self. fd . write ( self . loop_ , buf, offset) |_, uverr| {
1113
+ let res = match uverr {
1114
+ None => Ok ( ( ) ) ,
1115
+ Some ( err) => Err ( uv_error_to_io_error ( err) )
1116
+ } ;
1117
+ unsafe { ( * result_cell_ptr) . put_back ( res) ; }
1118
+ let scheduler = Local :: take :: < Scheduler > ( ) ;
1119
+ scheduler. resume_blocked_task_immediately ( task_cell. take ( ) ) ;
1120
+ } ;
1121
+ } ;
1122
+ result_cell. take ( )
1123
+ }
1124
+ }
1125
+
995
1126
#[ test]
996
1127
fn test_simple_io_no_connect ( ) {
997
1128
do run_in_newsched_task {
@@ -1498,3 +1629,39 @@ fn test_timer_sleep_simple() {
1498
1629
}
1499
1630
}
1500
1631
}
1632
+
1633
+ fn file_test_uvio_full_simple_impl ( ) {
1634
+ use libc:: { O_CREAT , O_RDWR , O_RDONLY ,
1635
+ S_IWUSR , S_IRUSR } ;
1636
+ use str:: StrSlice ; // why does this have to be explicitly imported to work?
1637
+ // compiler was complaining about no trait for str that
1638
+ // does .as_bytes() ..
1639
+ unsafe {
1640
+ let io = Local :: unsafe_borrow :: < IoFactoryObject > ( ) ;
1641
+ let create_flags = O_RDWR | O_CREAT ;
1642
+ let ro_flags = O_RDONLY ;
1643
+ let write_val = "hello uvio!" ;
1644
+ let mode = S_IWUSR | S_IRUSR ;
1645
+ let path = "./file_test_uvio_full.txt" ;
1646
+ {
1647
+ let mut fd = ( * io) . fs_open ( Path ( path) , create_flags as int , mode as int ) . unwrap ( ) ;
1648
+ let write_buf = write_val. as_bytes ( ) ;
1649
+ fd. write ( write_buf, 0 ) ;
1650
+ }
1651
+ {
1652
+ let mut fd = ( * io) . fs_open ( Path ( path) , ro_flags as int , mode as int ) . unwrap ( ) ;
1653
+ let mut read_vec = [ 0 , .. 1028 ] ;
1654
+ let nread = fd. read ( read_vec, 0 ) . unwrap ( ) ;
1655
+ let read_val = str:: from_bytes ( read_vec. slice ( 0 , nread as uint ) ) ;
1656
+ assert ! ( read_val == write_val. to_owned( ) ) ;
1657
+ }
1658
+ ( * io) . fs_unlink ( Path ( path) ) ;
1659
+ }
1660
+ }
1661
+
1662
+ #[ test]
1663
+ fn file_test_uvio_full_simple ( ) {
1664
+ do run_in_newsched_task {
1665
+ file_test_uvio_full_simple_impl( ) ;
1666
+ }
1667
+ }
0 commit comments