Open lazybilly opened 3 months ago
Hey @lazybilly 👋
Thanks for using heed and reporting possible improvements.
We recently released the Env::static_read_txn
for this specific purpose but it only works with read transaction. Can you maybe propose a PR to implement that for write transactions?
Hi @Kerollmops,
I'll try but I fear I might be a little too new to Rust for that.
I did actually see this static_read_txn
but I couldn't figure out how to open a database with it as I sadly couldn't find any info in the docs/issues/pr/examples
let env = unsafe { EnvOpenOptions::new().open(format!("{folder}/{file}"))? }; // Create env
let txn = env.static_read_txn().unwrap(); // static read txn takes env
let db = env.open_database(&txn, None)?.unwrap(); // Can't work
env.static_read_txn
eats env
but then I env
cannot be used to open the database, I must be missing something very obvious here !
Okay figured it out thanks to zed
's codebase ! Very simple but didn't feel intuitive at all at first
let env = unsafe { EnvOpenOptions::new().open("./db").unwrap() };
let db = {
// we will open the default unnamed database
let mut wtxn = env.write_txn().unwrap();
let db: Database<Str, U32<NativeEndian>> = env.create_database(&mut wtxn, None).unwrap();
// opening a write transaction
db.put(&mut wtxn, "seven", &7).unwrap();
db.put(&mut wtxn, "zero", &0).unwrap();
db.put(&mut wtxn, "five", &5).unwrap();
db.put(&mut wtxn, "three", &3).unwrap();
wtxn.commit().unwrap();
db
};
let rtxn = env.clone().static_read_txn().unwrap();
// Now we can use `rtxn` to read in threads etc
Though some examples would really be appreciated, I'm having quite a hard time with lifetimes... when trying to add functions like get/iter/.. to the wrapper. It seems that I must add 'static
everywhere, does it make sense ?
Here's what I got as of right now:
pub struct Database<Key, Value>
where
Key: Ord + Clone + Debug + ?Sized,
Value: PartialEq,
{
env: Env,
txn: RoTxn<'static>,
db: Database<Key, Value>,
}
impl<'p, Key, Value> Database<Key, Value>
where
Key: Ord
+ Clone
+ Debug
+ ?Sized
+ 'static
+ BytesEncode<'static, EItem = Key>
+ BytesDecode<'static, DItem = &'static Key>,
Value: PartialEq + 'static + BytesDecode<'static, DItem = &'static Value>,
{
pub fn open(path: &Path) -> color_eyre::Result<Self> {
fs::create_dir_all(path);
let env = unsafe { EnvOpenOptions::new().open(path)? };
let env = env.clone();
let mut txn = env.write_txn()?;
let db = env.create_database(&mut txn, None)?;
txn.commit()?;
let txn = env.clone().static_read_txn().unwrap();
Ok(Self {
env,
txn,
db,
})
}
pub fn iter<F>(&'static self, callback: &mut F)
where
F: FnMut((&Key, &Value)),
{
self.db
.iter(&self.txn)
.unwrap()
.map(|res| res.unwrap())
.for_each(callback);
}
pub fn get(&'static self, key: &'static Key) -> Option<&Value> {
self.db.get(&self.txn, key).unwrap()
}
}
As you can see, there is 'static
which really doesn't feel right
Hi !
Thank you for this library, it looks great but I'm no Rust expert and I really struggle its lifetimes and creating a struct wrapper around it.
Is it actually possible to have a generic struct owning the
env
,wtxn
anddatabase
?Like so:
The use case is that I have a lot of little databases with a ton of data spread among them and having to manage all
env
/wtxn
is quite complicated and kind of messy (again I'm not a rust expert). It would really be much nicer in a nice wrapper which is possible with many other databases.