Идиоматическое создание обернутого итератора курсора LMDB - PullRequest
0 голосов
/ 25 апреля 2019

У меня возникли проблемы с созданием итератора для обтекания итератора 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>
...