diff options
-rw-r--r-- | src/sys/aio.rs | 100 | ||||
-rw-r--r-- | test/sys/test_aio.rs | 74 |
2 files changed, 90 insertions, 84 deletions
diff --git a/src/sys/aio.rs b/src/sys/aio.rs index f0fce435..17c20288 100644 --- a/src/sys/aio.rs +++ b/src/sys/aio.rs @@ -153,56 +153,67 @@ impl<'a> AioCb<'a> { pub fn set_sigev_notify(&mut self, sigev_notify: SigevNotify) { self.aiocb.aio_sigevent = SigEvent::new(sigev_notify).sigevent(); } -} -/// Cancels outstanding AIO requests. If `aiocb` is `None`, then all requests -/// for `fd` will be cancelled. Otherwise, only the given `AioCb` will be -/// cancelled. -pub fn aio_cancel(fd: RawFd, aiocb: Option<&mut AioCb>) -> Result<AioCancelStat> { - let p: *mut libc::aiocb = match aiocb { - None => null_mut(), - Some(x) => &mut x.aiocb - }; - match unsafe { libc::aio_cancel(fd, p) } { - libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled), - libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled), - libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone), - -1 => Err(Error::last()), - _ => panic!("unknown aio_cancel return value") + /// Cancels an outstanding AIO request. + pub fn cancel(&mut self) -> Result<AioCancelStat> { + match unsafe { libc::aio_cancel(self.aiocb.aio_fildes, &mut self.aiocb) } { + libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled), + libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled), + libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone), + -1 => Err(Error::last()), + _ => panic!("unknown aio_cancel return value") + } } -} -/// Retrieve error status of an asynchronous operation. If the request has not -/// yet completed, returns `EINPROGRESS`. Otherwise, returns `Ok` or any other -/// error. -pub fn aio_error(aiocb: &mut AioCb) -> Result<()> { - let p: *mut libc::aiocb = &mut aiocb.aiocb; - match unsafe { libc::aio_error(p) } { - 0 => Ok(()), - num if num > 0 => Err(Error::from_errno(Errno::from_i32(num))), - -1 => Err(Error::last()), - num => panic!("unknown aio_error return value {:?}", num) + /// Retrieve error status of an asynchronous operation. If the request has not + /// yet completed, returns `EINPROGRESS`. Otherwise, returns `Ok` or any other + /// error. + pub fn error(&mut self) -> Result<()> { + match unsafe { libc::aio_error(&mut self.aiocb as *mut libc::aiocb) } { + 0 => Ok(()), + num if num > 0 => Err(Error::from_errno(Errno::from_i32(num))), + -1 => Err(Error::last()), + num => panic!("unknown aio_error return value {:?}", num) + } } -} -/// An asynchronous version of `fsync`. -pub fn aio_fsync(mode: AioFsyncMode, aiocb: &mut AioCb) -> Result<()> { - let p: *mut libc::aiocb = &mut aiocb.aiocb; - Errno::result(unsafe { libc::aio_fsync(mode as ::c_int, p) }).map(drop) -} + /// An asynchronous version of `fsync`. + pub fn fsync(&mut self, mode: AioFsyncMode) -> Result<()> { + let p: *mut libc::aiocb = &mut self.aiocb; + Errno::result(unsafe { libc::aio_fsync(mode as ::c_int, p) }).map(drop) + } + + /// Asynchronously reads from a file descriptor into a buffer + pub fn read(&mut self) -> Result<()> { + let p: *mut libc::aiocb = &mut self.aiocb; + Errno::result(unsafe { libc::aio_read(p) }).map(drop) + } + + /// Retrieve return status of an asynchronous operation. Should only be called + /// once for each `AioCb`, after `aio_error` indicates that it has completed. + /// The result the same as for `read`, `write`, of `fsync`. + pub fn aio_return(&mut self) -> Result<isize> { + let p: *mut libc::aiocb = &mut self.aiocb; + Errno::result(unsafe { libc::aio_return(p) }) + } + + /// Asynchronously writes from a buffer to a file descriptor + pub fn write(&mut self) -> Result<()> { + let p: *mut libc::aiocb = &mut self.aiocb; + Errno::result(unsafe { libc::aio_write(p) }).map(drop) + } -/// Asynchronously reads from a file descriptor into a buffer -pub fn aio_read(aiocb: &mut AioCb) -> Result<()> { - let p: *mut libc::aiocb = &mut aiocb.aiocb; - Errno::result(unsafe { libc::aio_read(p) }).map(drop) } -/// Retrieve return status of an asynchronous operation. Should only be called -/// once for each `AioCb`, after `aio_error` indicates that it has completed. -/// The result the same as for `read`, `write`, of `fsync`. -pub fn aio_return(aiocb: &mut AioCb) -> Result<isize> { - let p: *mut libc::aiocb = &mut aiocb.aiocb; - Errno::result(unsafe { libc::aio_return(p) }) +/// Cancels outstanding AIO requests. All requests for `fd` will be cancelled. +pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> { + match unsafe { libc::aio_cancel(fd, null_mut()) } { + libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled), + libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled), + libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone), + -1 => Err(Error::last()), + _ => panic!("unknown aio_cancel return value") + } } /// Suspends the calling process until at least one of the specified `AioCb`s @@ -224,11 +235,6 @@ pub fn aio_suspend(list: &[&AioCb], timeout: Option<TimeSpec>) -> Result<()> { }).map(drop) } -/// Asynchronously writes from a buffer to a file descriptor -pub fn aio_write(aiocb: &mut AioCb) -> Result<()> { - let p: *mut libc::aiocb = &mut aiocb.aiocb; - Errno::result(unsafe { libc::aio_write(p) }).map(drop) -} /// Submits multiple asynchronous I/O requests with a single system call. The /// order in which the requests are carried out is not specified. diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index 825282f1..41070c04 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -12,17 +12,17 @@ use tempfile::tempfile; // Helper that polls an AioCb for completion or error fn poll_aio(mut aiocb: &mut AioCb) -> Result<()> { loop { - let err = aio_error(&mut aiocb); + let err = aiocb.error(); if err != Err(Error::from(Errno::EINPROGRESS)) { return err; }; thread::sleep(time::Duration::from_millis(10)); } } -// Tests aio_cancel. We aren't trying to test the OS's implementation, only our -// bindings. So it's sufficient to check that aio_cancel returned any +// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only our +// bindings. So it's sufficient to check that AioCb.cancel returned any // AioCancelStat value. #[test] -fn test_aio_cancel() { +fn test_cancel() { let mut wbuf = "CDEF".to_string().into_bytes(); let f = tempfile().unwrap(); @@ -32,19 +32,19 @@ fn test_aio_cancel() { 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_NOP); - aio_write(&mut aiocb).unwrap(); - let err = aio_error(&mut aiocb); + aiocb.write().unwrap(); + let err = aiocb.error(); assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS))); - let cancelstat = aio_cancel(f.as_raw_fd(), Some(&mut aiocb)); + let cancelstat = aiocb.cancel(); assert!(cancelstat.is_ok()); // Wait for aiocb to complete, but don't care whether it succeeded let _ = poll_aio(&mut aiocb); - let _ = aio_return(&mut aiocb); + let _ = aiocb.aio_return(); } -// Tests using aio_cancel for all outstanding IOs. +// Tests using aio_cancel_all for all outstanding IOs. #[test] fn test_aio_cancel_all() { let mut wbuf = "CDEF".to_string().into_bytes(); @@ -56,30 +56,30 @@ fn test_aio_cancel_all() { 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_NOP); - aio_write(&mut aiocb).unwrap(); - let err = aio_error(&mut aiocb); + aiocb.write().unwrap(); + let err = aiocb.error(); assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS))); - let cancelstat = aio_cancel(f.as_raw_fd(), None); + let cancelstat = aio_cancel_all(f.as_raw_fd()); assert!(cancelstat.is_ok()); // Wait for aiocb to complete, but don't care whether it succeeded let _ = poll_aio(&mut aiocb); - let _ = aio_return(&mut aiocb); + let _ = aiocb.aio_return(); } #[test] -fn test_aio_fsync() { +fn test_fsync() { const INITIAL: &'static [u8] = b"abcdef123456"; let mut f = tempfile().unwrap(); f.write(INITIAL).unwrap(); let mut aiocb = AioCb::from_fd( f.as_raw_fd(), 0, //priority SigevNotify::SigevNone); - let err = aio_fsync(AioFsyncMode::O_SYNC, &mut aiocb); + let err = aiocb.fsync(AioFsyncMode::O_SYNC); assert!(err.is_ok()); poll_aio(&mut aiocb).unwrap(); - aio_return(&mut aiocb).unwrap(); + aiocb.aio_return().unwrap(); } @@ -107,27 +107,27 @@ fn test_aio_suspend() { 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_READ); - aio_write(&mut wcb).unwrap(); - aio_read(&mut rcb).unwrap(); + wcb.write().unwrap(); + rcb.read().unwrap(); loop { { let cbbuf = [&wcb, &rcb]; assert!(aio_suspend(&cbbuf[..], Some(timeout)).is_ok()); } - if aio_error(&mut rcb) != Err(Error::from(Errno::EINPROGRESS)) && - aio_error(&mut wcb) != Err(Error::from(Errno::EINPROGRESS)) { + if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) && + wcb.error() != Err(Error::from(Errno::EINPROGRESS)) { break } } - assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len()); - assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len()); + assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); } // Test a simple aio operation with no completion notification. We must poll // for completion #[test] -fn test_aio_read() { +fn test_read() { const INITIAL: &'static [u8] = b"abcdef123456"; let mut rbuf = vec![0; 4]; const EXPECT: &'static [u8] = b"cdef"; @@ -140,11 +140,11 @@ fn test_aio_read() { 0, //priority SigevNotify::SigevNone, LioOpcode::LIO_NOP); - aio_read(&mut aiocb).unwrap(); + aiocb.read().unwrap(); let err = poll_aio(&mut aiocb); assert!(err == Ok(())); - assert!(aio_return(&mut aiocb).unwrap() as usize == EXPECT.len()); + assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len()); } assert!(rbuf == EXPECT); @@ -153,7 +153,7 @@ fn test_aio_read() { // Test a simple aio operation with no completion notification. We must poll // for completion. Unlike test_aio_read, this test uses AioCb::from_slice #[test] -fn test_aio_write() { +fn test_write() { const INITIAL: &'static [u8] = b"abcdef123456"; const WBUF: &'static [u8] = b"CDEF"; //"CDEF".to_string().into_bytes(); let mut rbuf = Vec::new(); @@ -169,11 +169,11 @@ fn test_aio_write() { SigevNotify::SigevNone, LioOpcode::LIO_NOP) }; - aio_write(&mut aiocb).unwrap(); + aiocb.write().unwrap(); let err = poll_aio(&mut aiocb); assert!(err == Ok(())); - assert!(aio_return(&mut aiocb).unwrap() as usize == WBUF.len()); + assert!(aiocb.aio_return().unwrap() as usize == WBUF.len()); f.seek(SeekFrom::Start(0)).unwrap(); let len = f.read_to_end(&mut rbuf).unwrap(); @@ -192,7 +192,7 @@ extern fn sigfunc(_: c_int) { // Test an aio operation with completion delivered by a signal #[test] -fn test_aio_write_sigev_signal() { +fn test_write_sigev_signal() { let sa = SigAction::new(SigHandler::Handler(sigfunc), SA_RESETHAND, SigSet::empty()); @@ -217,12 +217,12 @@ fn test_aio_write_sigev_signal() { }, LioOpcode::LIO_NOP) }; - aio_write(&mut aiocb).unwrap(); + aiocb.write().unwrap(); while unsafe { signaled == 0 } { thread::sleep(time::Duration::from_millis(10)); } - assert!(aio_return(&mut aiocb).unwrap() as usize == WBUF.len()); + assert!(aiocb.aio_return().unwrap() as usize == WBUF.len()); f.seek(SeekFrom::Start(0)).unwrap(); let len = f.read_to_end(&mut rbuf).unwrap(); assert!(len == EXPECT.len()); @@ -262,8 +262,8 @@ fn test_lio_listio_wait() { let err = lio_listio(LioMode::LIO_WAIT, &[&mut wcb, &mut rcb], SigevNotify::SigevNone); err.expect("lio_listio failed"); - assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len()); - assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len()); + assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); } assert!(rbuf == b"3456"); @@ -308,8 +308,8 @@ fn test_lio_listio_nowait() { poll_aio(&mut wcb).unwrap(); poll_aio(&mut rcb).unwrap(); - assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len()); - assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len()); + assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); } assert!(rbuf == b"3456"); @@ -362,8 +362,8 @@ fn test_lio_listio_signal() { thread::sleep(time::Duration::from_millis(10)); } - assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len()); - assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len()); + assert!(wcb.aio_return().unwrap() as usize == WBUF.len()); + assert!(rcb.aio_return().unwrap() as usize == WBUF.len()); } assert!(rbuf == b"3456"); |