use std::os::unix::io::RawFd;
use nix::unistd::{close, mkdir, unlinkat, UnlinkatFlags, ftruncate};
use nix::fcntl::{open, openat, OFlag, fallocate, FallocateFlags};
use nix::sys::{stat::Mode, uio::{pwrite, pread}};
use rand::{Rng, seq::SliceRandom};
use libc::off_t;
use growthring::wal::{WALFile, WALStore, WALPos, WALBytes, WALLoader, WALWriter, WALRingId};
struct WALFileTest {
filename: String,
fd: RawFd,
}
impl WALFileTest {
fn new(rootfd: RawFd, filename: &str) -> Result<Self, ()> {
openat(rootfd, filename,
OFlag::O_CREAT | OFlag::O_RDWR,
Mode::S_IRUSR | Mode::S_IWUSR).and_then(|fd| {
let filename = filename.to_string();
Ok (WALFileTest {
filename,
fd,
})
}).or_else(|_| Err(()))
}
}
impl Drop for WALFileTest {
fn drop(&mut self) {
close(self.fd).unwrap();
}
}
impl WALFile for WALFileTest {
fn allocate(&self, offset: WALPos, length: usize) -> Result<(), ()> {
println!("{}.allocate(offset=0x{:x}, end=0x{:x})", self.filename, offset, offset + length as u64);
fallocate(self.fd,
FallocateFlags::FALLOC_FL_ZERO_RANGE,
offset as off_t, length as off_t).and_then(|_| Ok(())).or_else(|_| Err(()))
}
fn truncate(&self, length: usize) -> Result<(), ()> {
println!("{}.truncate(length={})", self.filename, length);
ftruncate(self.fd, length as off_t).or_else(|_| Err(()))
}
fn write(&self, offset: WALPos, data: WALBytes) -> Result<(), ()> {
println!("{}.write(offset=0x{:x}, end=0x{:x}, data=0x{})",
self.filename, offset, offset + data.len() as u64, hex::encode(&data));
pwrite(self.fd, &*data, offset as off_t)
.or_else(|_| Err(()))
.and_then(|nwrote| if nwrote == data.len() { Ok(()) } else { Err(()) })
}
fn read(&self, offset: WALPos