Files
daqbuffer/fsio/src/fsio.rs
2021-12-17 18:24:44 +01:00

176 lines
5.1 KiB
Rust

use err::Error;
use netpod::log::*;
#[allow(unused)]
use std::os::unix::prelude::OpenOptionsExt;
use std::os::unix::prelude::{AsRawFd, OsStrExt};
use std::path::PathBuf;
use tokio::fs::OpenOptions;
const BASE: &str = "/data/daqbuffer-testdata";
fn fcntl_xlock(file: &mut std::fs::File, beg: i64, cmd: libc::c_int, ty: i32) -> i32 {
unsafe {
let p = libc::flock {
l_type: ty as i16,
l_whence: libc::SEEK_SET as i16,
l_start: beg,
l_len: 8,
l_pid: 0,
};
libc::fcntl(file.as_raw_fd(), cmd, &p)
}
}
fn wlock(file: &mut std::fs::File, beg: i64) -> i32 {
fcntl_xlock(file, beg, libc::F_OFD_SETLK, libc::F_WRLCK)
}
fn rlock(file: &mut std::fs::File, beg: i64) -> i32 {
fcntl_xlock(file, beg, libc::F_OFD_SETLK, libc::F_RDLCK)
}
fn unlock(file: &mut std::fs::File, beg: i64) -> i32 {
fcntl_xlock(file, beg, libc::F_OFD_SETLK, libc::F_UNLCK)
}
#[allow(unused)]
async fn lock_1() -> Result<(), Error> {
let path = PathBuf::from(BASE).join("tmp-daq4-f1");
let mut f1 = OpenOptions::new()
.write(true)
.read(true)
.create(true)
.truncate(false)
.open(path)
.await?;
f1.as_raw_fd();
let mx1 = std::sync::Arc::new(tokio::sync::Mutex::new(0usize));
let mg1 = mx1.lock().await;
let (tx1, rx2) = std::sync::mpsc::channel();
let (tx2, rx1) = std::sync::mpsc::channel();
let t1 = std::thread::spawn({
move || {
let path = PathBuf::from(BASE).join("tmp-daq4-f1");
let mut f1 = std::fs::OpenOptions::new().read(true).write(true).open(&path).unwrap();
info!("Thread 1 rlock...");
let ec = rlock(&mut f1, 0);
info!("Thread 1 rlock {}", ec);
tx1.send(1u32).unwrap();
rx1.recv().unwrap();
info!("Thread 1 unlock...");
let ec = unlock(&mut f1, 0);
info!("Thread 1 unlock {}", ec);
tx1.send(1u32).unwrap();
rx1.recv().unwrap();
info!("Thread 1 rlock...");
let ec = rlock(&mut f1, 0);
info!("Thread 1 rlock {}", ec);
tx1.send(1u32).unwrap();
rx1.recv().unwrap();
info!("Thread 1 done");
}
});
let t2 = std::thread::spawn({
move || {
let path = PathBuf::from(BASE).join("tmp-daq4-f1");
let mut f1 = std::fs::OpenOptions::new().read(true).write(true).open(&path).unwrap();
rx2.recv().unwrap();
info!("Thread 2 wlock...");
let ec = wlock(&mut f1, 0);
info!("Thread 2 wlock {}", ec);
tx2.send(1u32).unwrap();
rx2.recv().unwrap();
info!("Thread 2 rlock");
let ec = rlock(&mut f1, 0);
info!("Thread 2 rlock {}", ec);
tx2.send(1u32).unwrap();
rx2.recv().unwrap();
tx2.send(1u32).unwrap();
info!("Thread 2 done");
}
});
tokio::task::spawn_blocking(move || {
t1.join().map_err(|_| Error::with_msg_no_trace("join error"))?;
t2.join().map_err(|_| Error::with_msg_no_trace("join error"))?;
Ok::<_, Error>(())
})
.await??;
Ok(())
}
#[allow(unused)]
async fn write_1() -> Result<(), Error> {
let path = PathBuf::from(BASE).join("tmp-daq4-f2");
let mut f1 = OpenOptions::new()
.write(true)
.read(true)
.create(true)
.truncate(false)
.open(path)
.await?;
unsafe {
let path_d = PathBuf::from(BASE);
let mut path_d_b = path_d.as_os_str().as_bytes().to_vec();
//info!("path_d_b {:?}", path_d_b);
path_d_b.push(0);
let fdd = libc::open(path_d_b.as_ptr() as *const i8, libc::O_DIRECTORY | libc::O_RDONLY);
if fdd < 0 {
panic!();
}
let ec = libc::fsync(fdd);
if ec != 0 {
panic!();
}
let ec = libc::close(fdd);
if ec != 0 {
panic!();
}
let fd = f1.as_raw_fd();
let lockparam = libc::flock {
l_type: libc::F_RDLCK as i16,
l_whence: libc::SEEK_SET as i16,
l_start: 0,
l_len: 8,
l_pid: 0,
};
let ec = libc::fcntl(f1.as_raw_fd(), libc::F_OFD_SETLK, &lockparam);
if ec != 0 {
panic!();
}
let buf = b"world!";
let n = libc::pwrite(fd, buf.as_ptr() as *const libc::c_void, buf.len(), 0);
if n != buf.len() as isize {
panic!();
}
let ec = libc::fsync(fd);
if ec != 0 {
panic!();
}
let lockparam = libc::flock {
l_type: libc::F_UNLCK as i16,
l_whence: libc::SEEK_SET as i16,
l_start: 0,
l_len: 8,
l_pid: 0,
};
let ec = libc::fcntl(f1.as_raw_fd(), libc::F_OFD_SETLK, &lockparam);
if ec == 0 {
panic!();
}
}
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn t1() -> Result<(), Error> {
Ok(taskrun::run(write_1()).unwrap())
}
}