diff --git a/src/middlewares/versioned_flat_key_value/mod.rs b/src/middlewares/versioned_flat_key_value/mod.rs index bc81de0..6032b6a 100644 --- a/src/middlewares/versioned_flat_key_value/mod.rs +++ b/src/middlewares/versioned_flat_key_value/mod.rs @@ -45,34 +45,12 @@ pub struct VersionedStore<'db, T: VersionedKeyValueSchema> { } impl<'db, T: VersionedKeyValueSchema> VersionedStore<'db, T> { - pub fn get_pending_part(&self, commit: CommitID, key: &T::Key) -> Result> { - let res_value = self.pending_part.query(commit, key); - let history_commit = match res_value { - Ok(Some(value)) => { - return Ok(value); - } - Ok(None) => { - if let Some(commit) = self.pending_part.get_parent_of_root() { - commit - } else { - return Ok(None); - } - } - Err(PendingError::CommitIDNotFound(target_commit)) => { - assert_eq!(target_commit, commit); - commit - } - Err(other_err) => { - return Err(StorageError::PendingError(other_err)); - } - }; - - let history_number = if let Some(value) = self.commit_id_table.get(&commit)? { - value.into_owned() + fn get_history_number_by_commit_id(&self, commit: CommitID) -> Result { + if let Some(value) = self.commit_id_table.get(&commit)? { + Ok(value.into_owned()) } else { - return Err(StorageError::CommitIDNotFound); - }; - self.get_historical_part(history_number, key) + Err(StorageError::CommitIDNotFound) + } } pub fn add_to_pending_part( @@ -216,6 +194,7 @@ impl<'db, T: VersionedKeyValueSchema> VersionedStore<'db, T> { // impl<'db, T: VersionedKeyValueSchema> KeyValueStoreManager // for VersionedStore<'db, T> // { + #[allow(clippy::type_complexity)] fn iter_historical_changes<'a>( &'a self, commit_id: &CommitID, @@ -225,28 +204,53 @@ impl<'db, T: VersionedKeyValueSchema> VersionedStore<'db, T> { match pending_res { Ok(pending_iter) => { if let Some(history_commit) = self.pending_part.get_parent_of_root() { - let history_iter = self.iter_historical_changes_history_part(&history_commit, key)?; - return Ok(Box::new(pending_iter.chain(history_iter))) + let history_iter = + self.iter_historical_changes_history_part(&history_commit, key)?; + Ok(Box::new(pending_iter.chain(history_iter))) } else { - return Ok(Box::new(pending_iter)) + Ok(Box::new(pending_iter)) } } Err(PendingError::CommitIDNotFound(target_commit)) => { assert_eq!(target_commit, *commit_id); - let history_iter = self.iter_historical_changes_history_part(&target_commit, key)?; - return Ok(Box::new(history_iter)) + let history_iter = + self.iter_historical_changes_history_part(&target_commit, key)?; + Ok(Box::new(history_iter)) } - _ => unreachable!("pending_part's iter_historical_changes() does not return other errors") - }; + Err(other_err) => Err(StorageError::PendingError(other_err)), + } } // fn discard(self, commit: CommitID) -> Result<()> { // todo!() // } - // fn get_versioned_key(&self, commit: &CommitID, key: &T::Key) -> Result> { - // todo!() - // } + fn get_versioned_key(&self, commit: &CommitID, key: &T::Key) -> Result> { + // let pending_res = self.pending_part.get_versioned_key(commit, key); // this will checkout_current + let pending_res = self.pending_part.get_versioned_key(commit, key); // this does not checkout_current + let history_commit = match pending_res { + Ok(Some(value)) => { + return Ok(value); + } + Ok(None) => { + if let Some(commit) = self.pending_part.get_parent_of_root() { + commit + } else { + return Ok(None); + } + } + Err(PendingError::CommitIDNotFound(target_commit)) => { + assert_eq!(target_commit, *commit); + target_commit + } + Err(other_err) => { + return Err(StorageError::PendingError(other_err)); + } + }; + + let history_number = self.get_history_number_by_commit_id(history_commit)?; + self.get_historical_part(history_number, key) + } // fn versioned_iter<'a>( // &'a self, diff --git a/src/middlewares/versioned_flat_key_value/pending_part/commit_tree.rs b/src/middlewares/versioned_flat_key_value/pending_part/commit_tree.rs index 420d59e..a315787 100644 --- a/src/middlewares/versioned_flat_key_value/pending_part/commit_tree.rs +++ b/src/middlewares/versioned_flat_key_value/pending_part/commit_tree.rs @@ -218,6 +218,21 @@ impl Tree { } Ok(path.into_iter()) } + + pub fn get_versioned_key( + &self, + commit_id: &S::CommitId, + key: &S::Key, + ) -> PendResult>, S> { + let mut node_option = Some(self.get_node_by_commit_id(*commit_id)?); + while let Some(node) = node_option { + if let Some(RecoverRecord { value, .. }) = node.modifications.get(key) { + return Ok(Some(value.clone())); + } + node_option = self.get_parent_node(node); + } + Ok(None) + } } impl Tree { diff --git a/src/middlewares/versioned_flat_key_value/pending_part/versioned_hash_map.rs b/src/middlewares/versioned_flat_key_value/pending_part/versioned_hash_map.rs index 30c1298..ccec480 100644 --- a/src/middlewares/versioned_flat_key_value/pending_part/versioned_hash_map.rs +++ b/src/middlewares/versioned_flat_key_value/pending_part/versioned_hash_map.rs @@ -177,6 +177,7 @@ impl VersionedHashMap { } } +// only one key, no need to invoke checkout_current impl VersionedHashMap { pub fn iter_historical_changes<'a>( &'a self, @@ -185,6 +186,14 @@ impl VersionedHashMap { ) -> PendResult)>, S> { self.tree.iter_historical_changes(commit_id, key) } + + pub fn get_versioned_key( + &self, + commit_id: &S::CommitId, + key: &S::Key, + ) -> PendResult>, S> { + self.tree.get_versioned_key(commit_id, key) + } } impl VersionedHashMap {