diff --git a/CHANGELOG.md b/CHANGELOG.md index b5eaeb3bb..32bc31485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 0.34.1 + +## New Features + +* #1136 Added the `TransactionalTree::flush` method to + flush the underlying database after the transaction + commits and before the transaction returns. + # 0.34 ## Improvements diff --git a/Cargo.toml b/Cargo.toml index 45cfaf5e7..53685a73e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sled" -version = "0.34.0" +version = "0.34.1" authors = ["Tyler Neely "] description = "a modern embedded database" license = "MIT/Apache-2.0" diff --git a/src/transaction.rs b/src/transaction.rs index 492e0d4bf..4f336c3a0 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -96,6 +96,7 @@ pub struct TransactionalTree { pub(super) tree: Tree, pub(super) writes: Rc>>>, pub(super) read_cache: Rc>>>, + pub(super) flush_on_commit: Rc>, } /// An error type that is returned from the closure @@ -329,6 +330,11 @@ impl TransactionalTree { Ok(()) } + /// Flush the database before returning from the transaction. + pub fn flush(&self) { + *self.flush_on_commit.borrow_mut() = true; + } + fn unstage(&self) { unimplemented!() } @@ -352,6 +358,7 @@ impl TransactionalTree { tree: tree.clone(), writes: Default::default(), read_cache: Default::default(), + flush_on_commit: Default::default(), } } } @@ -392,6 +399,22 @@ impl TransactionalTrees { // recovered atomically peg.seal_batch() } + + fn flush_if_configured(&self) -> Result<()> { + let mut should_flush = None; + + for tree in &self.inner { + if *tree.flush_on_commit.borrow() { + should_flush = Some(tree); + break; + } + } + + if let Some(tree) = should_flush { + tree.tree.flush()?; + } + Ok(()) + } } /// A simple constructor for `Err(TransactionError::Abort(_))` @@ -427,7 +450,7 @@ pub trait Transactional { let view = Self::view_overlay(&tt); // NB locks must exist until this function returns. - let _locks = if let Ok(l) = tt.stage() { + let locks = if let Ok(l) = tt.stage() { l } else { tt.unstage(); @@ -442,6 +465,8 @@ pub trait Transactional { Ok(r) => { let guard = pin(); tt.commit(&guard)?; + drop(locks); + tt.flush_if_configured()?; return Ok(r); } Err(ConflictableTransactionError::Abort(e)) => { diff --git a/tests/test_tree.rs b/tests/test_tree.rs index 4afe791ec..3f337b902 100644 --- a/tests/test_tree.rs +++ b/tests/test_tree.rs @@ -504,6 +504,21 @@ fn concurrent_tree_transactions() -> TransactionResult<()> { Ok(()) } +#[test] +fn tree_flush_in_transaction() { + let config = sled::Config::new().temporary(true); + let db = config.open().unwrap(); + let tree = db.open_tree(b"a").unwrap(); + + tree.transaction::<_, _, sled::transaction::TransactionError>(|tree| { + tree.insert(b"k1", b"cats")?; + tree.insert(b"k2", b"dogs")?; + tree.flush(); + Ok(()) + }) + .unwrap(); +} + #[test] fn incorrect_multiple_db_transactions() -> TransactionResult<()> { common::setup_logger();