trying atomic rename thing
authorValentine Wallace <vwallace@protonmail.com>
Wed, 17 Feb 2021 01:22:53 +0000 (20:22 -0500)
committerValentine Wallace <vwallace@protonmail.com>
Wed, 17 Feb 2021 01:39:32 +0000 (20:39 -0500)
lightning-persister/Cargo.toml
lightning-persister/src/util.rs

index 63b69a1e166667118ffd2933797963232554e22b..a6c4645545d48e4fa238c461f2c57ce8913dd77f 100644 (file)
@@ -16,5 +16,8 @@ libc = "0.2"
 version = "0.24"
 features = ["bitcoinconsensus"]
 
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["winbase"] }
+
 [dev-dependencies]
 lightning = { version = "0.0.12", path = "../lightning", features = ["_test_utils"] }
index 004bc5d67def63864f5365b08b42b99b4e76e421..7d63a41565bac14edca10707f62499544caef96e 100644 (file)
@@ -1,6 +1,14 @@
+
+#[cfg(target_os = "windows")]
+extern crate winapi;
+
 use std::fs;
 use std::path::{Path, PathBuf};
-
+#[cfg(target_os = "windows")]
+       use {
+               std::ffi::OsStr,
+               std::os::windows::ffi::OsStrExt
+               };
 #[cfg(not(target_os = "windows"))]
 use std::os::unix::io::AsRawFd;
 
@@ -13,12 +21,34 @@ pub(crate) fn get_full_filepath(filepath: String, filename: String) -> String {
        path.push(filename);
        path.to_str().unwrap().to_string()
 }
+#[cfg(target_os = "windows")]
+macro_rules! call {
+       ($e: expr) => (
+               if $e != 0 {
+                       return Ok(())
+               } else {
+                       return Err(std::io::Error::last_os_error())
+               }
+       )
+}
+
+#[cfg(target_os = "windows")]
+fn path_to_windows_str<T: AsRef<OsStr>>(x: T) -> Vec<winapi::shared::ntdef::WCHAR> {
+       x.as_ref().encode_wide().chain(Some(0)).collect()
+}
 
 #[allow(bare_trait_objects)]
 pub(crate) fn write_to_file<D: DiskWriteable>(path: String, filename: String, data: &D) -> std::io::Result<()> {
        println!("VMW: creating dir");
        fs::create_dir_all(path.clone())?;
        println!("VMW: created dir");
+
+       println!("VMW: entries in dir:");
+       let dir = PathBuf::from(path.clone());
+       for entry in fs::read_dir(dir).unwrap() {
+               let entry = entry.unwrap();
+               println!("VMW: entry in dir: {:?}", entry.path());
+       }
        // Do a crazy dance with lots of fsync()s to be overly cautious here...
        // We never want to end up in a state where we've lost the old data, or end up using the
        // old data on power loss after we've returned.
@@ -38,16 +68,25 @@ pub(crate) fn write_to_file<D: DiskWriteable>(path: String, filename: String, da
                f.sync_all()?;
                println!("VMW: sync'd all");
        }
-       println!("VMW: about to rename");
-       fs::rename(&tmp_filename, &filename_with_path)?;
-       println!("VMW: renamed");
        // Fsync the parent directory on Unix.
        #[cfg(not(target_os = "windows"))]
        {
+               fs::rename(&tmp_filename, &filename_with_path)?;
                let path = Path::new(&filename_with_path).parent().unwrap();
                let dir_file = fs::OpenOptions::new().read(true).open(path)?;
                unsafe { libc::fsync(dir_file.as_raw_fd()); }
        }
+       #[cfg(target_os = "windows")]
+       {
+               println!("VMW: about to rename");
+               let src = PathBuf::from(tmp_filename);
+               let dst = PathBuf::from(filename_with_path);
+               call!(unsafe {winapi::um::winbase::MoveFileExW(
+                       path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
+                       winapi::um::winbase::MOVEFILE_WRITE_THROUGH | winapi::um::winbase::MOVEFILE_REPLACE_EXISTING
+               )});
+               println!("VMW: renamed");
+       }
        Ok(())
 }