changeset 526:79e0bbc4f604

replace libc usage with fs2, support windows
author João Oliveira <hello@jxs.pt>
date Mon, 18 May 2020 23:43:14 +0100
parents c0e92d14e550
children deb79bf7f240
files Cargo.toml src/disk_env.rs src/env.rs src/lib.rs src/version_set.rs
diffstat 5 files changed, 30 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/Cargo.toml	Tue Mar 24 07:09:47 2020 +0100
+++ b/Cargo.toml	Mon May 18 23:43:14 2020 +0100
@@ -13,10 +13,10 @@
 [dependencies]
 crc = "1.8"
 integer-encoding = "1.0"
-libc = "0.2"
 rand = "0.7"
 snap = "1.0"
 errno = "0.2"
+fs2 = "0.4.3"
 
 [dev-dependencies]
 time-test = "0.2"
--- a/src/disk_env.rs	Tue Mar 24 07:09:47 2020 +0100
+++ b/src/disk_env.rs	Mon May 18 23:43:14 2020 +0100
@@ -1,26 +1,20 @@
 use env::{path_to_str, Env, FileLock, Logger, RandomAccess};
 use env_common::{micros, sleep_for};
 use error::{err, Result, Status, StatusCode};
+use fs2::FileExt;
 
 use std::collections::HashMap;
-use std::fs;
-use std::io::{self, Read, Write};
+use std::fs::{self, File};
+use std::io::{self, Read, Write, ErrorKind};
 use std::iter::FromIterator;
-use std::os::unix::io::IntoRawFd;
 use std::path::{Path, PathBuf};
 use std::sync::{Arc, Mutex};
 
-use libc;
-
-const F_RDLCK: libc::c_short = 0;
-const F_WRLCK: libc::c_short = 1;
-const F_UNLCK: libc::c_short = 2;
-
 type FileDescriptor = i32;
 
 #[derive(Clone)]
 pub struct PosixDiskEnv {
-    locks: Arc<Mutex<HashMap<String, FileDescriptor>>>,
+    locks: Arc<Mutex<HashMap<String, File>>>,
 }
 
 impl PosixDiskEnv {
@@ -127,23 +121,19 @@
                 .open(p)
                 .map_err(|e| map_err_with_name("lock", p, e))?;
 
-            let fd = f.into_raw_fd();
-            let result = unsafe { libc::flock(fd as libc::c_int, libc::LOCK_EX | libc::LOCK_NB) };
-
-            if result < 0 {
-                if errno::errno() == errno::Errno(libc::EWOULDBLOCK) {
-                    return Err(Status::new(
+            match f.try_lock_exclusive() {
+                Err(err) if err.kind() == ErrorKind::WouldBlock => return Err(Status::new(
                         StatusCode::LockError,
                         "lock on database is already held by different process",
-                    ));
-                }
-                return Err(Status::new(
+                    )),
+                Err(_) => return Err(Status::new(
                     StatusCode::Errno(errno::errno()),
-                    &format!("unknown lock error on fd {} (file {})", fd, p.display()),
-                ));
-            }
+                    &format!("unknown lock error on file {:?} (file {})", f, p.display()),
+                )),
+                _ => (),
+            };
 
-            locks.insert(p.to_str().unwrap().to_string(), fd);
+            locks.insert(p.to_str().unwrap().to_string(), f);
             let lock = FileLock {
                 id: p.to_str().unwrap().to_string(),
             };
@@ -158,16 +148,8 @@
                 &format!("unlocking a file that is not locked: {}", l.id),
             );
         } else {
-            let fd = locks.remove(&l.id).unwrap();
-            let result = unsafe {
-                let ok = libc::fcntl(fd, libc::F_GETFD);
-                if ok < 0 {
-                    // Likely EBADF when already closed. In that case, the lock is released and all is fine.
-                    return Ok(());
-                }
-                libc::flock(fd, libc::LOCK_UN)
-            };
-            if result < 0 {
+            let f = locks.remove(&l.id).unwrap();
+            if let Err(_) = f.unlock() {
                 return err(StatusCode::LockError, &format!("unlock failed: {}", l.id));
             }
             Ok(())
--- a/src/env.rs	Tue Mar 24 07:09:47 2020 +0100
+++ b/src/env.rs	Mon May 18 23:43:14 2020 +0100
@@ -5,19 +5,30 @@
 
 use std::fs::File;
 use std::io::prelude::*;
+#[cfg(unix)]
 use std::os::unix::fs::FileExt;
+#[cfg(windows)]
+use std::os::windows::fs::FileExt;
 use std::path::{Path, PathBuf};
 
 pub trait RandomAccess {
     fn read_at(&self, off: usize, dst: &mut [u8]) -> Result<usize>;
 }
 
+#[cfg(unix)]
 impl RandomAccess for File {
     fn read_at(&self, off: usize, dst: &mut [u8]) -> Result<usize> {
         Ok((self as &dyn FileExt).read_at(dst, off as u64)?)
     }
 }
 
+#[cfg(windows)]
+impl RandomAccess for File {
+    fn read_at(&self, off: usize, dst: &mut [u8]) -> Result<usize> {
+        Ok((self as &dyn FileExt).seek_read(dst, off as u64)?)
+    }
+}
+
 pub struct FileLock {
     pub id: String,
 }
--- a/src/lib.rs	Tue Mar 24 07:09:47 2020 +0100
+++ b/src/lib.rs	Mon May 18 23:43:14 2020 +0100
@@ -26,9 +26,9 @@
 extern crate crc;
 extern crate errno;
 extern crate integer_encoding;
-extern crate libc;
 extern crate rand;
 extern crate snap;
+extern crate fs2;
 
 #[cfg(test)]
 #[macro_use]
--- a/src/version_set.rs	Tue Mar 24 07:09:47 2020 +0100
+++ b/src/version_set.rs	Mon May 18 23:43:14 2020 +0100
@@ -18,8 +18,6 @@
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
 
-use std::os::unix::ffi::OsStrExt;
-
 pub struct Compaction {
     level: usize,
     max_file_size: usize,
@@ -888,8 +886,8 @@
     let tempfile = temp_file_name(dbname, manifest_file_num);
     {
         let mut f = env.open_writable_file(Path::new(&tempfile))?;
-        f.write(manifest_base.as_os_str().as_bytes())?;
-        f.write("\n".as_bytes())?;
+        f.write_all(manifest_base.display().to_string().as_bytes())?;
+        f.write_all(b"\n")?;
     }
     let currentfile = current_file_name(dbname);
     if let Err(e) = env.rename(Path::new(&tempfile), Path::new(&currentfile)) {