diff --git a/heed3/Cargo.toml b/heed3/Cargo.toml index e399a43e..5886dc23 100644 --- a/heed3/Cargo.toml +++ b/heed3/Cargo.toml @@ -26,9 +26,10 @@ synchronoise = "1.0.1" [dev-dependencies] argon2 = { version = "0.5.3", features = ["std"] } +chacha20poly1305 = "0.10.1" memchr = "2.7.4" +rayon = "1.10.0" serde = { version = "1.0.217", features = ["derive"] } -chacha20poly1305 = "0.10.1" tempfile = "3.15.0" [target.'cfg(windows)'.dependencies] @@ -116,5 +117,8 @@ name = "prev-snapshot" [[example]] name = "heed3-encrypted" +[[example]] +name = "heed3-encrypted-parallel-read" + [[example]] name = "heed3-all-types" diff --git a/heed3/examples/heed3-encrypted-parallel-read.rs b/heed3/examples/heed3-encrypted-parallel-read.rs new file mode 100644 index 00000000..b2c2b1e5 --- /dev/null +++ b/heed3/examples/heed3-encrypted-parallel-read.rs @@ -0,0 +1,61 @@ +use std::error::Error; + +use argon2::Argon2; +use chacha20poly1305::{ChaCha20Poly1305, Key}; +use heed3::types::*; +use heed3::EnvOpenOptions; + +fn main() -> Result<(), Box> { + let env_path = tempfile::tempdir()?; + let password = "This is the password that will be hashed by the argon2 algorithm"; + let salt = "The salt added to the password hashes to add more security when stored"; + + // We choose to use argon2 as our Key Derivation Function, but you can choose whatever you want. + // + let mut key = Key::default(); + Argon2::default().hash_password_into(password.as_bytes(), salt.as_bytes(), &mut key)?; + + // We open the environment + let mut options = EnvOpenOptions::new(); + let env = unsafe { + options + .map_size(10 * 1024 * 1024) // 10MB + .max_dbs(3) + .open_encrypted::(key, &env_path)? + }; + + let key1 = "first-key"; + let val1 = "this is a secret info"; + let key2 = "second-key"; + let val2 = "this is another secret info"; + + // We create database and write secret values in it + let mut wtxn = env.write_txn()?; + let db = env.create_database::(&mut wtxn, Some("first"))?; + db.put(&mut wtxn, key1, val1)?; + db.put(&mut wtxn, key2, val2)?; + wtxn.commit()?; + + let pool = rayon::ThreadPoolBuilder::new().num_threads(12).build().unwrap(); + + let results = pool.broadcast(|_| { + let mut rtxn = env.read_txn()?; + + for _ in 0..1000 { + let mut iter = db.iter(&mut rtxn)?; + assert_eq!(iter.next().transpose()?, Some((key1, val1))); + assert_eq!(iter.next().transpose()?, Some((key2, val2))); + assert_eq!(iter.next().transpose()?, None); + } + + Ok(()) as heed3::Result<()> + }); + + for result in results { + result?; + } + + eprintln!("Successful test!"); + + Ok(()) +}