From 2397407dc4d7e196c6edc6436e9545149ccb1a21 Mon Sep 17 00:00:00 2001 From: hashmap Date: Tue, 5 May 2020 11:00:23 +0200 Subject: [PATCH] Always return a typed structure from lmdb store (#3312) We have a method get which returns a Vec, it's used in cases when we can't implement FromLmdbBytes or Readable on a desired type, eg when both traits and type are external for the current crate. This approach requires an extra allocation of a Vec, this PR introduces a method which accepts desirialzer as closure, which allows to desrialize in place without an intermidiate heap allocation. It's still possible to get a Vec if needed, just pass a Vec constructor to get_with. --- chain/src/store.rs | 10 +++++----- store/src/lmdb.rs | 16 ++++++++++------ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/chain/src/store.rs b/chain/src/store.rs index 5c27e0a58a..0dee43cd1e 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -348,11 +348,11 @@ impl<'a> Batch<'a> { } fn get_legacy_input_bitmap(&self, bh: &Hash) -> Result { - if let Ok(Some(bytes)) = self.db.get(&to_key(BLOCK_INPUT_BITMAP_PREFIX, bh)) { - Ok(Bitmap::deserialize(&bytes)) - } else { - Err(Error::NotFoundErr("legacy block input bitmap".to_string())) - } + option_to_not_found( + self.db + .get_with(&to_key(BLOCK_INPUT_BITMAP_PREFIX, bh), Bitmap::deserialize), + || "legacy block input bitmap".to_string(), + ) } /// Get the "spent index" from the db for the specified block. diff --git a/store/src/lmdb.rs b/store/src/lmdb.rs index 1419fc7ae5..96a43e06b1 100644 --- a/store/src/lmdb.rs +++ b/store/src/lmdb.rs @@ -235,14 +235,15 @@ impl Store { } /// Gets a value from the db, provided its key - pub fn get(&self, key: &[u8]) -> Result>, Error> { + pub fn get_with(&self, key: &[u8], f: F) -> Result, Error> + where + F: Fn(&[u8]) -> T, + { let db = self.db.read(); let txn = lmdb::ReadTransaction::new(self.env.clone())?; let access = txn.access(); let res = access.get(&db.as_ref().unwrap(), key); - res.map(|res: &[u8]| res.to_vec()) - .to_opt() - .map_err(From::from) + res.map(f).to_opt().map_err(From::from) } /// Gets a `Readable` value from the db, provided its key. Encapsulates @@ -345,8 +346,11 @@ impl<'a> Batch<'a> { } /// gets a value from the db, provided its key - pub fn get(&self, key: &[u8]) -> Result>, Error> { - self.store.get(key) + pub fn get_with(&self, key: &[u8], f: F) -> Result, Error> + where + F: Fn(&[u8]) -> T, + { + self.store.get_with(key, f) } /// Whether the provided key exists