From 00a092239367ed5d5906c3d195784343cd6b07d9 Mon Sep 17 00:00:00 2001 From: Magnus Ulimoen Date: Thu, 28 Mar 2024 15:09:08 +0100 Subject: [PATCH 1/2] Add sync call --- netcdf/src/file.rs | 11 +++++++++++ netcdf/tests/lib.rs | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/netcdf/src/file.rs b/netcdf/src/file.rs index 17a8029..4a9d20f 100644 --- a/netcdf/src/file.rs +++ b/netcdf/src/file.rs @@ -423,6 +423,17 @@ impl FileMut { let (ncid, name) = super::group::get_parent_ncid_and_stem(self.ncid(), name)?; super::variable::add_variable_from_identifiers(ncid, name, dims, T::NCTYPE) } + + /// Flush pending buffers to disk to minimise data loss in case of termination. + /// + /// Note: When writing and reading from the same file from multiple processes + /// it is recommended to instead open the file in both the reader and + /// writer process with the [`Options::SHARE`] flag. + pub fn sync(&self) -> error::Result<()> { + error::checked(super::with_lock(|| unsafe { + netcdf_sys::nc_sync(self.ncid()) + })) + } } #[cfg(feature = "has-mmap")] diff --git a/netcdf/tests/lib.rs b/netcdf/tests/lib.rs index 8913db7..b0ca837 100644 --- a/netcdf/tests/lib.rs +++ b/netcdf/tests/lib.rs @@ -1743,3 +1743,14 @@ fn ndarray_get_into() { .unwrap(); assert_eq!(values, outarray.slice(s![0, .., .., ..])); } + +#[test] +fn sync_file() { + let d = tempfile::tempdir().unwrap(); + let path = d.path().join("sync_file.nc"); + + let mut f = netcdf::create(path).unwrap(); + + f.add_unlimited_dimension("t").unwrap(); + f.sync().unwrap(); +} From c868e4515625fe6300373f619eb3511ff129d152 Mon Sep 17 00:00:00 2001 From: Magnus Ulimoen Date: Thu, 28 Mar 2024 15:52:59 +0100 Subject: [PATCH 2/2] Add close call to catch IO errors --- netcdf/src/file.rs | 32 ++++++++++++++++++++++++++++---- netcdf/tests/lib.rs | 14 ++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/netcdf/src/file.rs b/netcdf/src/file.rs index 4a9d20f..0443594 100644 --- a/netcdf/src/file.rs +++ b/netcdf/src/file.rs @@ -19,12 +19,18 @@ pub(crate) struct RawFile { ncid: nc_type, } +impl RawFile { + fn close(self) -> error::Result<()> { + let Self { ncid } = self; + error::checked(super::with_lock(|| unsafe { nc_close(ncid) })) + } +} + impl Drop for RawFile { fn drop(&mut self) { - unsafe { - // Can't really do much with an error here - let _err = error::checked(super::with_lock(|| nc_close(self.ncid))); - } + // Can't really do much with an error here + let ncid = self.ncid; + let _err = error::checked(super::with_lock(|| unsafe { nc_close(ncid) })); } } @@ -245,6 +251,15 @@ impl File { pub fn types(&self) -> error::Result> { super::types::all_at_location(self.ncid()).map(|x| x.map(Result::unwrap)) } + + /// Close the file + /// + /// Note: This is called automatically by `Drop`, but can be useful + /// if flushing data or closing the file would result in an error. + pub fn close(self) -> error::Result<()> { + let Self(file) = self; + file.close() + } } /// Mutable access to file. @@ -434,6 +449,15 @@ impl FileMut { netcdf_sys::nc_sync(self.ncid()) })) } + + /// Close the file + /// + /// Note: This is called automatically by `Drop`, but can be useful + /// if flushing data or closing the file would result in an error. + pub fn close(self) -> error::Result<()> { + let Self(File(file)) = self; + file.close() + } } #[cfg(feature = "has-mmap")] diff --git a/netcdf/tests/lib.rs b/netcdf/tests/lib.rs index b0ca837..e714983 100644 --- a/netcdf/tests/lib.rs +++ b/netcdf/tests/lib.rs @@ -1754,3 +1754,17 @@ fn sync_file() { f.add_unlimited_dimension("t").unwrap(); f.sync().unwrap(); } + +#[test] +fn close_file() { + let d = tempfile::tempdir().unwrap(); + let path = d.path().join("close_file.nc"); + + let mut f = netcdf::create(&path).unwrap(); + + f.add_unlimited_dimension("t").unwrap(); + f.close().unwrap(); + + let f = netcdf::open(path).unwrap(); + f.close().unwrap(); +}