Skip to content

Commit

Permalink
Add close() method to ReadTransaction
Browse files Browse the repository at this point in the history
Calling this method is entirely optional. Transactions still close
automatically, but this can be used to ensure that it can be closed
immediately
  • Loading branch information
cberner committed Jan 20, 2024
1 parent c87fbb4 commit 6601fa8
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
16 changes: 15 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::tree_store::{FILE_FORMAT_VERSION, MAX_VALUE_LENGTH};
use crate::TypeName;
use crate::{ReadTransaction, TypeName};
use std::fmt::{Display, Formatter};
use std::sync::PoisonError;
use std::{io, panic};
Expand Down Expand Up @@ -334,12 +334,15 @@ impl std::error::Error for CompactionError {}
pub enum TransactionError {
/// Error from underlying storage
Storage(StorageError),
/// The transaction is still referenced by a table or other object
ReadTransactionStillInUse(ReadTransaction<'static>),
}

impl TransactionError {
pub(crate) fn into_storage_error(self) -> StorageError {
match self {
TransactionError::Storage(storage) => storage,
_ => unreachable!(),
}
}
}
Expand All @@ -348,6 +351,9 @@ impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Error {
match err {
TransactionError::Storage(storage) => storage.into(),
TransactionError::ReadTransactionStillInUse(txn) => {
Error::ReadTransactionStillInUse(txn)
}
}
}
}
Expand All @@ -362,6 +368,9 @@ impl Display for TransactionError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
TransactionError::Storage(storage) => storage.fmt(f),
TransactionError::ReadTransactionStillInUse(_) => {
write!(f, "Transaction still in use")
}
}
}
}
Expand Down Expand Up @@ -453,6 +462,8 @@ pub enum Error {
TableAlreadyOpen(String, &'static panic::Location<'static>),
Io(io::Error),
LockPoisoned(&'static panic::Location<'static>),
/// The transaction is still referenced by a table or other object
ReadTransactionStillInUse(ReadTransaction<'static>),
}

impl<T> From<PoisonError<T>> for Error {
Expand Down Expand Up @@ -543,6 +554,9 @@ impl Display for Error {
Error::InvalidSavepoint => {
write!(f, "Savepoint is invalid or cannot be created.")
}
Error::ReadTransactionStillInUse(_) => {
write!(f, "Transaction still in use")
}
}
}
}
Expand Down
24 changes: 23 additions & 1 deletion src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use log::{info, warn};
use std::borrow::Borrow;
use std::cmp::min;
use std::collections::{HashMap, HashSet};
use std::fmt::{Display, Formatter};
use std::fmt::{Debug, Display, Formatter};
use std::marker::PhantomData;
use std::ops::{RangeBounds, RangeFull};
use std::sync::atomic::{AtomicBool, Ordering};
Expand Down Expand Up @@ -1276,6 +1276,28 @@ impl<'a> ReadTransaction<'a> {
}
}

impl ReadTransaction<'static> {
/// Close the transaction
///
/// Transactions are automatically closed when they and all objects referencing them have been dropped.
/// This method can be used to ensure that there are no outstanding objects remaining.
///
/// Returns `ReadTransactionStillInUse` error if a table or other object retrieved from the transaction still references this transaction
pub fn close(self) -> Result<(), TransactionError> {
if Arc::strong_count(&self.transaction_guard) > 1 {
return Err(TransactionError::ReadTransactionStillInUse(self));
}
// No-op, just drop ourself
Ok(())
}
}

impl Debug for ReadTransaction<'static> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("ReadTransaction")
}
}

#[cfg(test)]
mod test {
use crate::{Database, TableDefinition};
Expand Down

0 comments on commit 6601fa8

Please sign in to comment.