use crate::{check_cufile_error, sys, CuFileResult};
use std::fs::File;
use std::os::raw::{c_int, c_void};
use std::os::unix::io::AsRawFd;
use std::ptr;
pub struct CuFileHandle {
handle: sys::CUfileHandle_t,
_file: File, }
impl CuFileHandle {
pub fn register(file: File) -> CuFileResult<Self> {
let fd = file.as_raw_fd();
let mut handle = ptr::null_mut();
let mut descr = sys::CUfileDescr_t {
type_: sys::CUfileFileHandleType::CU_FILE_HANDLE_TYPE_OPAQUE_FD,
handle: sys::CUfileDescrHandle { fd: fd as c_int },
fs_ops: ptr::null_mut(),
};
unsafe {
check_cufile_error(sys::cuFileHandleRegister(&mut handle, &mut descr))?;
}
Ok(CuFileHandle {
handle,
_file: file,
})
}
pub(crate) fn raw_handle(&self) -> sys::CUfileHandle_t {
self.handle
}
pub fn read(
&self,
dest_base: *mut c_void,
size: usize,
file_offset: i64,
dest_offset: i64,
) -> CuFileResult<isize> {
unsafe {
let ret = sys::cuFileRead(self.handle, dest_base, size, file_offset, dest_offset);
if ret < 0 {
check_cufile_error((-ret).try_into().unwrap())?;
}
Ok(ret)
}
}
pub fn write(&self, dest_base: *const c_void, size: usize, file_offset: i64, dest_offset: i64) -> CuFileResult<isize> {
unsafe {
let ret = sys::cuFileWrite(
self.handle,
dest_base,
size,
file_offset,
dest_offset,
);
if ret < 0 {
check_cufile_error((-ret).try_into().unwrap())?;
}
Ok(ret)
}
}
}
impl Drop for CuFileHandle {
fn drop(&mut self) {
unsafe {
let _ = sys::cuFileHandleDeregister(self.handle);
}
}
}
unsafe impl Send for CuFileHandle {}
unsafe impl Sync for CuFileHandle {}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::OpenOptions;
use tempfile::tempdir;
#[test]
fn test_handle_creation() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("test_file.dat");
let file = OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(&file_path)
.unwrap();
match CuFileHandle::register(file) {
Ok(_handle) => {
println!("Handle created successfully");
}
Err(e) => {
println!(
"Handle creation failed (expected in test environment): {:?}",
e
);
}
}
}
}