У меня возникли проблемы с созданием итератора для обтекания итератора LMDB и транзакции в ржавчине.
Я использую lmdb crate , который оборачивается вокруг привязок C LMDB ине могу найти способ сохранить транзакцию и курсор / iter.Как только транзакция отброшена, курсор / iter больше не действителен, и я получаю код ошибки LMDB для плохой транзакции mdb_cursor_get returned an unexpected error: -30782
. Для борьбы с этой проблемой я попытался обернуть транзакцию в ее собственную структуру.При создании обтекателя iter, передавая эту структуру Transaction как аргумент в попытке поддержать транзакцию, но, похоже, это не работает из-за некоторых конфликтующих проблем времени жизни.
pub struct Accessor {
db_env: Environment,
db: Database,
}
pub struct Accessor {
pub fn contents(
&self,
) -> Result<impl Iterator<Item=(EntryKey, EntryValue)> + '_>
{
let mut iter_factory = IterFactory::new(&self.db_env, &self.db);
let it = iter_factory.iter_start();
Ok(it)
}
}
#[derive(Debug)]
pub struct IterFactory<'a> {
txn: Box<RoTransaction<'a>>,
db: &'a Database,
}
impl <'a> IterFactory<'a> {
pub fn new(db_env: &'a Environment, db: &'a Database) -> IterFactory<'a> {
let txn = db_env.begin_ro_txn().expect("Error opening up ROTransaction on LMDB!");
IterFactory{txn: Box::new(txn), db: db, iter: None}
}
pub fn iter_start(&mut self) -> EntryIterator<'a> {
let mut cursor = self.txn.open_ro_cursor(*self.db).expect("Error opening up ROCursor on LMDB!");
let iter = cursor.iter_start();
EntryIterator::new(self, iter)
}
}
#[derive(Debug)]
pub struct EntryIterator<'a> {
iter_factory: &'a mut IterFactory<'a>,
inner_iter: Iter<'a>,
max_key: EntryKey,
}
impl<'a> EntryIterator<'a> {
fn new(iter_factory: &'a mut IterFactory<'a>, iter: Iter<'a>) -> EntryIterator<'a> {
EntryIterator {iter_factory: iter_factory, inner_iter: iter, max_key: SEG_KEY_MAX }
}
pub fn up_to(mut self, max_key: EntryKey) -> EntryIterator<'a> {
self.max_key = max_key;
self
}
}
impl<'a> Iterator for EntryIterator<'a> {
type Item = (EntryKey, EntryValue);
fn next(&mut self) -> Option<Self::Item> {
let res = self.inner_iter.next();
if res == None {
return None;
}
let (key, val) = res.unwrap();
let key_val: EntryKey = EntryKey::from_bytes(key);
if key_val > self.max_key {
None
} else {
let entry_val: EntryValue = EntryValue::from_bytes(val);
Some((key_val, entry_val))
}
}
}
Эта попытка выявляет некоторые странные проблемы в течение жизни, с которыми я не слишком знаком.
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
401 | EntryIterator::new(self, iter)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 398:5...
|
398 | / pub fn iter_start(&mut self) -> EntryIterator<'a> {
399 | | let mut cursor = self.txn.open_ro_cursor(*self.db).expect("Error opening up ROCursor on LMDB!");
400 | | let iter = cursor.iter_start();
401 | | EntryIterator::new(self, iter)
402 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
|
401 | EntryIterator::new(self, iter)
| ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 392:7...
|
392 | impl <'a> IterFactory<'a> {
| ^^
= note: ...so that the expression is assignable:
expected &mut log::index::IterFactory<'_>
found &mut log::index::IterFactory<'a>