Skip to content

Commit

Permalink
Merge pull request #296 from meilisearch/prevsnapshot
Browse files Browse the repository at this point in the history
Introduce the `PREV_SNAPSHOT` flag
  • Loading branch information
Kerollmops authored Feb 28, 2025
2 parents 03301c4 + f2b2da0 commit e26381b
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 5 deletions.
3 changes: 1 addition & 2 deletions convert-to-heed3.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ else
fi

# ...and replaces the `heed::` string by the `heed3::` one.
for file in $(find heed/src -type f -name "*.rs"); do
for file in $(find heed/src -type f -name "*.rs") examples/prev-snapshot.rs; do
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's/heed::/heed3::/g' "$file"
else
Expand All @@ -37,6 +37,5 @@ git diff -q --exit-code || git commit -am 'remove-me: heed3 changes generated by
git config --local --unset user.email
git config --local --unset user.name


echo "Heed3 crate setup completed successfully. Configurations for the heed crate have been copied and modified."
echo "A commit (starting with remove-me) has been generated and must be deleted before merging into the main branch."
85 changes: 85 additions & 0 deletions examples/prev-snapshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::error::Error;

use heed::types::*;
use heed::{Database, EnvFlags, EnvOpenOptions};

// In this test we are checking that we can move to a previous environement snapshot.
fn main() -> Result<(), Box<dyn Error>> {
let env_path = tempfile::tempdir()?;

let env = unsafe {
EnvOpenOptions::new()
.map_size(10 * 1024 * 1024) // 10MB
.max_dbs(3)
.open(&env_path)?
};

let mut wtxn = env.write_txn()?;
let db: Database<Str, Str> = env.create_database(&mut wtxn, None)?;

// We fill the db database with entries.
db.put(&mut wtxn, "I am here", "to test things")?;
db.put(&mut wtxn, "I am here too", "for the same purpose")?;

wtxn.commit()?;

env.prepare_for_closing().wait();

// We can get the env state from before the last commit
// and therefore see an empty env.
let env = unsafe {
EnvOpenOptions::new()
.map_size(10 * 1024 * 1024) // 10MB
.max_dbs(3)
.flags(EnvFlags::PREV_SNAPSHOT)
.open(&env_path)?
};

let mut wtxn = env.write_txn()?;
let db: Database<Str, Str> = env.create_database(&mut wtxn, None)?;

assert!(db.is_empty(&wtxn)?);

wtxn.abort();
env.prepare_for_closing().wait();

// However, if we don't commit we can still get
// back the latest version of the env.
let env = unsafe {
EnvOpenOptions::new()
.map_size(10 * 1024 * 1024) // 10MB
.max_dbs(3)
.open(&env_path)?
};

let mut wtxn = env.write_txn()?;
let db: Database<Str, Str> = env.create_database(&mut wtxn, None)?;

assert_eq!(db.get(&wtxn, "I am here")?, Some("to test things"));
assert_eq!(db.get(&wtxn, "I am here too")?, Some("for the same purpose"));

// And write new stuff in the env.
db.put(&mut wtxn, "I will fade away", "I am so sad")?;

wtxn.commit()?;
env.prepare_for_closing().wait();

// Once again we can get back the previous version
// of the env and see some entries disappear.
let env = unsafe {
EnvOpenOptions::new()
.map_size(10 * 1024 * 1024) // 10MB
.max_dbs(3)
.flags(EnvFlags::PREV_SNAPSHOT)
.open(&env_path)?
};

let rtxn = env.read_txn()?;
let db: Database<Str, Str> = env.open_database(&rtxn, None)?.unwrap();

assert_eq!(db.get(&rtxn, "I am here")?, Some("to test things"));
assert_eq!(db.get(&rtxn, "I am here too")?, Some("for the same purpose"));
assert_eq!(db.get(&rtxn, "I will fade away")?, None);

Ok(())
}
4 changes: 4 additions & 0 deletions heed/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ path = "../examples/multi-env.rs"
name = "nested"
path = "../examples/nested.rs"

[[example]]
name = "prev-snapshot"
path = "../examples/prev-snapshot.rs"

[[example]]
name = "rmp-serde"
path = "../examples/rmp-serde.rs"
Expand Down
6 changes: 3 additions & 3 deletions heed/src/mdb/lmdb_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ pub use ffi::{
mdb_env_get_fd, mdb_env_get_flags, mdb_env_get_maxkeysize, mdb_env_info, mdb_env_open,
mdb_env_set_flags, mdb_env_set_mapsize, mdb_env_set_maxdbs, mdb_env_set_maxreaders,
mdb_env_stat, mdb_env_sync, mdb_filehandle_t, mdb_get, mdb_put, mdb_reader_check,
mdb_set_compare, mdb_stat, mdb_txn_abort, mdb_txn_begin, mdb_txn_commit, mdb_version,
MDB_cursor, MDB_dbi, MDB_env, MDB_stat, MDB_txn, MDB_val, MDB_CP_COMPACT, MDB_CURRENT,
MDB_RDONLY, MDB_RESERVE,
mdb_set_compare, mdb_stat, mdb_txn_abort, mdb_txn_begin, mdb_txn_commit, mdb_txn_id,
mdb_version, MDB_cursor, MDB_dbi, MDB_env, MDB_stat, MDB_txn, MDB_val, MDB_CP_COMPACT,
MDB_CURRENT, MDB_RDONLY, MDB_RESERVE,
};
#[cfg(master3)]
pub use ffi::{mdb_env_set_encrypt, MDB_enc_func};
Expand Down
2 changes: 2 additions & 0 deletions heed/src/mdb/lmdb_flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ bitflags! {
const NO_SUB_DIR = ffi::MDB_NOSUBDIR;
/// Don't fsync after commit.
const NO_SYNC = ffi::MDB_NOSYNC;
/// Open the previous transaction.
const PREV_SNAPSHOT = ffi::MDB_PREVSNAPSHOT;
/// Read only.
const READ_ONLY = ffi::MDB_RDONLY;
/// Don't fsync metapage after commit.
Expand Down
9 changes: 9 additions & 0 deletions heed/src/txn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ impl<'e, T> RoTxn<'e, T> {
self.env.env_mut_ptr()
}

/// Return the transaction's ID.
///
/// This returns the identifier associated with this transaction. For a
/// [`RoTxn`], this corresponds to the snapshot being read;
/// concurrent readers will frequently have the same transaction ID.
pub fn id(&self) -> usize {
unsafe { ffi::mdb_txn_id(self.txn.unwrap().as_ptr()) }
}

/// Commit a read transaction.
///
/// Synchronizing some [`Env`] metadata with the global handle.
Expand Down
4 changes: 4 additions & 0 deletions heed3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ longer-keys = ["lmdb-master3-sys/longer-keys"]

# Examples are located outside the standard heed/examples directory to prevent
# conflicts between heed3 and heed examples when working on both crates.
[[example]]
name = "prev-snapshot"
path = "../examples/prev-snapshot.rs"

[[example]]
name = "heed3-encrypted"
path = "../examples/heed3-encrypted.rs"
Expand Down

0 comments on commit e26381b

Please sign in to comment.