use std::fs::File;
use std::io::Result;
#[cfg(unix)]
use crate::unix::sync_impl as sys;
#[cfg(windows)]
use crate::windows::sync_impl as sys;
pub trait FileExt {
fn allocated_size(&self) -> Result<u64>;
fn allocate(&self, len: u64) -> Result<()>;
fn lock_shared(&self) -> Result<()>;
fn lock_exclusive(&self) -> Result<()>;
fn try_lock_shared(&self) -> Result<()>;
fn try_lock_exclusive(&self) -> Result<()>;
fn unlock(&self) -> Result<()>;
}
impl FileExt for File {
fn allocated_size(&self) -> Result<u64> {
sys::allocated_size(self)
}
fn allocate(&self, len: u64) -> Result<()> {
sys::allocate(self, len)
}
fn lock_shared(&self) -> Result<()> {
sys::lock_shared(self)
}
fn lock_exclusive(&self) -> Result<()> {
sys::lock_exclusive(self)
}
fn try_lock_shared(&self) -> Result<()> {
sys::try_lock_shared(self)
}
fn try_lock_exclusive(&self) -> Result<()> {
sys::try_lock_exclusive(self)
}
fn unlock(&self) -> Result<()> {
sys::unlock(self)
}
}
#[cfg(test)]
mod test {
extern crate tempdir;
extern crate test;
use std::fs;
use super::*;
use crate::{allocation_granularity, available_space, free_space, lock_contended_error, total_space};
#[test]
fn lock_shared() {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("fs4");
let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
let file3 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
file1.lock_shared().unwrap();
file2.lock_shared().unwrap();
assert_eq!(file3.try_lock_exclusive().unwrap_err().kind(),
lock_contended_error().kind());
file1.unlock().unwrap();
assert_eq!(file3.try_lock_exclusive().unwrap_err().kind(),
lock_contended_error().kind());
file2.unlock().unwrap();
file3.lock_exclusive().unwrap();
}
#[test]
fn lock_exclusive() {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("fs4");
let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
file1.lock_exclusive().unwrap();
assert_eq!(file2.try_lock_exclusive().unwrap_err().kind(),
lock_contended_error().kind());
assert_eq!(file2.try_lock_shared().unwrap_err().kind(),
lock_contended_error().kind());
file1.unlock().unwrap();
file2.lock_exclusive().unwrap();
}
#[test]
fn lock_cleanup() {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("fs4");
let file1 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
let file2 = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
file1.lock_exclusive().unwrap();
assert_eq!(file2.try_lock_shared().unwrap_err().kind(),
lock_contended_error().kind());
drop(file1);
file2.lock_shared().unwrap();
}
#[test]
fn allocate() {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("fs4");
let file = fs::OpenOptions::new().write(true).create(true).open(&path).unwrap();
let blksize = allocation_granularity(&path).unwrap();
assert_eq!(0, file.allocated_size().unwrap());
assert_eq!(0, file.metadata().unwrap().len());
file.allocate(2 * blksize - 1).unwrap();
assert_eq!(2 * blksize, file.allocated_size().unwrap());
assert_eq!(2 * blksize - 1, file.metadata().unwrap().len());
file.set_len(blksize + 1).unwrap();
assert_eq!(2 * blksize, file.allocated_size().unwrap());
assert_eq!(blksize + 1, file.metadata().unwrap().len());
}
#[test]
fn filesystem_space() {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let total_space = total_space(&tempdir.path()).unwrap();
let free_space = free_space(&tempdir.path()).unwrap();
let available_space = available_space(&tempdir.path()).unwrap();
assert!(total_space > free_space);
assert!(total_space > available_space);
assert!(available_space <= free_space);
}
#[bench]
fn bench_file_create(b: &mut test::Bencher) {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("file");
b.iter(|| {
fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.unwrap();
fs::remove_file(&path).unwrap();
});
}
#[bench]
fn bench_file_truncate(b: &mut test::Bencher) {
let size = 32 * 1024 * 1024;
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("file");
b.iter(|| {
let file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.unwrap();
file.set_len(size).unwrap();
fs::remove_file(&path).unwrap();
});
}
#[bench]
fn bench_file_allocate(b: &mut test::Bencher) {
let size = 32 * 1024 * 1024;
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("file");
b.iter(|| {
let file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.unwrap();
file.allocate(size).unwrap();
fs::remove_file(&path).unwrap();
});
}
#[bench]
fn bench_allocated_size(b: &mut test::Bencher) {
let size = 32 * 1024 * 1024;
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("file");
let file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.unwrap();
file.allocate(size).unwrap();
b.iter(|| {
file.allocated_size().unwrap();
});
}
#[bench]
fn bench_lock_unlock(b: &mut test::Bencher) {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
let path = tempdir.path().join("fs4");
let file = fs::OpenOptions::new().read(true).write(true).create(true).open(&path).unwrap();
b.iter(|| {
file.lock_exclusive().unwrap();
file.unlock().unwrap();
});
}
#[bench]
fn bench_free_space(b: &mut test::Bencher) {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
b.iter(|| {
test::black_box(free_space(&tempdir.path()).unwrap());
});
}
#[bench]
fn bench_available_space(b: &mut test::Bencher) {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
b.iter(|| {
test::black_box(available_space(&tempdir.path()).unwrap());
});
}
#[bench]
fn bench_total_space(b: &mut test::Bencher) {
let tempdir = tempdir::TempDir::new("fs4").unwrap();
b.iter(|| {
test::black_box(total_space(&tempdir.path()).unwrap());
});
}
}