Skip to content

Commit

Permalink
enable self referential static rtxn
Browse files Browse the repository at this point in the history
  • Loading branch information
irevoire committed May 6, 2024
1 parent 522cf8c commit 28b1cfe
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 4 deletions.
30 changes: 30 additions & 0 deletions heed/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ impl Env {
///
/// You can make this transaction `Send`able between threads by
/// using the `read-txn-no-tls` crate feature.
/// See [`Self::static_read_txn`] if you want the txn to own the environment.
///
/// ## LMDB Limitations
///
Expand All @@ -771,6 +772,35 @@ impl Env {
RoTxn::new(self)
}

/// Create a transaction with read-only access for use with the environment.
/// Contrary to [`Self::read_txn`], this version **owns** the environment, which
/// means you won't be able to close the environment while this transaction is alive.
///
/// You can make this transaction `Send`able between threads by
/// using the `read-txn-no-tls` crate feature.
///
/// ## LMDB Limitations
///
/// It's possible to have multiple read transactions in the same environment
/// while there is a write transaction ongoing.
///
/// But read transactions prevent reuse of pages freed by newer write transactions,
/// thus the database can grow quickly. Write transactions prevent other write transactions,
/// since writes are serialized.
///
/// So avoid long-lived read transactions.
///
/// ## Errors
///
/// * [`crate::MdbError::Panic`]: A fatal error occurred earlier, and the environment must be shut down
/// * [`crate::MdbError::MapResized`]: Another process wrote data beyond this [`Env`] mapsize and this env
/// map must be resized
/// * [`crate::MdbError::ReadersFull`]: a read-only transaction was requested, and the reader lock table is
/// full
pub fn static_read_txn(self) -> Result<RoTxn<'static>> {
RoTxn::static_read_txn(self)
}

/// Copy an LMDB environment to the specified path, with options.
///
/// This function may be used to make a backup of an existing environment.
Expand Down
24 changes: 20 additions & 4 deletions heed/src/txn.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::ops::Deref;
use std::ptr;

Expand Down Expand Up @@ -26,7 +27,7 @@ use crate::{Env, Result};
/// You may increase the limit by editing it **at your own risk**: `/Library/LaunchDaemons/sysctl.plist`
pub struct RoTxn<'e> {
pub(crate) txn: *mut ffi::MDB_txn,
env: &'e Env,
env: Cow<'e, Env>,
}

impl<'e> RoTxn<'e> {
Expand All @@ -42,7 +43,22 @@ impl<'e> RoTxn<'e> {
))?
};

Ok(RoTxn { txn, env })
Ok(RoTxn { txn, env: Cow::Borrowed(env) })
}

pub(crate) fn static_read_txn(env: Env) -> Result<RoTxn<'static>> {
let mut txn: *mut ffi::MDB_txn = ptr::null_mut();

unsafe {
mdb_result(ffi::mdb_txn_begin(
env.env_mut_ptr(),
ptr::null_mut(),
ffi::MDB_RDONLY,
&mut txn,
))?
};

Ok(RoTxn { txn, env: Cow::Owned(env) })
}

pub(crate) fn env_mut_ptr(&self) -> *mut ffi::MDB_env {
Expand Down Expand Up @@ -110,7 +126,7 @@ impl<'p> RwTxn<'p> {

unsafe { mdb_result(ffi::mdb_txn_begin(env.env_mut_ptr(), ptr::null_mut(), 0, &mut txn))? };

Ok(RwTxn { txn: RoTxn { txn, env } })
Ok(RwTxn { txn: RoTxn { txn, env: Cow::Borrowed(env) } })
}

pub(crate) fn nested(env: &'p Env, parent: &'p mut RwTxn) -> Result<RwTxn<'p>> {
Expand All @@ -119,7 +135,7 @@ impl<'p> RwTxn<'p> {

unsafe { mdb_result(ffi::mdb_txn_begin(env.env_mut_ptr(), parent_ptr, 0, &mut txn))? };

Ok(RwTxn { txn: RoTxn { txn, env } })
Ok(RwTxn { txn: RoTxn { txn, env: Cow::Borrowed(env) } })
}

pub(crate) fn env_mut_ptr(&self) -> *mut ffi::MDB_env {
Expand Down

0 comments on commit 28b1cfe

Please sign in to comment.