diff --git a/Cargo.lock b/Cargo.lock index 17ed1bc99d92b1bbb3adc6a33d179de7b785bbda..2b5551845ef7fcb1b90eac95c7490173d0476893 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -879,6 +879,7 @@ dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mockall 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unwrap 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1016,6 +1017,7 @@ version = "0.1.0-a" dependencies = [ "bincode 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "durs-common-tools 0.2.0", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rkv 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/lib/modules-lib/bc-db-reader/Cargo.toml b/lib/modules-lib/bc-db-reader/Cargo.toml index e23d3c150523ed07643a7c6e95209790aedb2f7d..7dfb649613fd3015797d30517ea069022b7996d4 100644 --- a/lib/modules-lib/bc-db-reader/Cargo.toml +++ b/lib/modules-lib/bc-db-reader/Cargo.toml @@ -23,6 +23,7 @@ durs-dbs-tools = { path = "../../tools/dbs-tools" } durs-wot = { path = "../../dubp/wot" } log = "0.4.*" maplit = "1.0.1" +mockall = { version = "0.5.2", optional = true } fnv = "1.0.6" serde = { version = "1.0.*", features = ["derive"] } unwrap = "1.2.1" @@ -35,3 +36,5 @@ durs-common-tests-tools = { path = "../../tests-tools/common-tests-tools" } tempfile = "3.1.0" [features] +client-indexer = [] +mock = ["mockall"] diff --git a/lib/modules-lib/bc-db-reader/src/lib.rs b/lib/modules-lib/bc-db-reader/src/lib.rs index cd9a1ebb865bac6452ed4fddf0e1fe4389535cae..dc854cc01143c897f59ee25200acb16c38cd6d5f 100644 --- a/lib/modules-lib/bc-db-reader/src/lib.rs +++ b/lib/modules-lib/bc-db-reader/src/lib.rs @@ -17,7 +17,6 @@ #![allow(clippy::large_enum_variant)] #![deny( - missing_docs, missing_copy_implementations, trivial_casts, trivial_numeric_casts, @@ -34,12 +33,16 @@ pub mod current_meta_datas; pub mod indexes; pub mod paging; pub mod tools; +pub mod r#trait; pub use durs_dbs_tools::kv_db::{ KvFileDbRead as DbReadable, KvFileDbReader as Reader, KvFileDbRoHandler as BcDbRo, KvFileDbSchema, KvFileDbStoreType, KvFileDbValue as DbValue, Readable as DbReader, }; pub use durs_dbs_tools::DbError; +#[cfg(feature = "mock")] +pub use r#trait::MockBcDbRoTrait; +pub use r#trait::{BcDbRoTrait, BcDbRoWithReader}; use constants::*; use maplit::hashmap; diff --git a/lib/modules-lib/bc-db-reader/src/trait.rs b/lib/modules-lib/bc-db-reader/src/trait.rs new file mode 100644 index 0000000000000000000000000000000000000000..928f39998175b3671f1a34bd29b73e1f040e7f5d --- /dev/null +++ b/lib/modules-lib/bc-db-reader/src/trait.rs @@ -0,0 +1,109 @@ +// Copyright (C) 2017-2019 The AXIOM TEAM Association. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! BlockChain Datas Access Layer in Read-Only mode. +// ! Define read only trait + +use crate::blocks::DbBlock; +use crate::{BcDbRo, DbReadable, Reader}; +use dubp_common_doc::{BlockNumber, Blockstamp}; +use durs_dbs_tools::DbError; + +#[cfg(feature = "mock")] +use mockall::*; + +#[cfg_attr(feature = "mock", automock)] +pub trait BcDbRoTrait { + fn get_current_blockstamp(&self) -> Result<Option<Blockstamp>, DbError>; + fn get_current_block(&self) -> Result<Option<DbBlock>, DbError>; + fn get_db_block_in_local_blockchain( + &self, + block_number: BlockNumber, + ) -> Result<Option<DbBlock>, DbError>; + #[cfg(feature = "client-indexer")] + fn get_db_blocks_in_local_blockchain( + &self, + numbers: Vec<BlockNumber>, + ) -> Result<Vec<DbBlock>, DbError>; +} + +impl BcDbRoTrait for BcDbRo { + #[inline] + fn get_current_blockstamp(&self) -> Result<Option<Blockstamp>, DbError> { + self.read(|r| crate::current_meta_datas::get_current_blockstamp_(self, r)) + } + fn get_current_block(&self) -> Result<Option<DbBlock>, DbError> { + self.read(|r| { + if let Some(current_blockstamp) = + crate::current_meta_datas::get_current_blockstamp_(self, r)? + { + crate::blocks::get_db_block_in_local_blockchain(self, r, current_blockstamp.id) + } else { + Ok(None) + } + }) + } + #[inline] + fn get_db_block_in_local_blockchain( + &self, + block_number: BlockNumber, + ) -> Result<Option<DbBlock>, DbError> { + self.read(|r| crate::blocks::get_db_block_in_local_blockchain(self, r, block_number)) + } + #[cfg(feature = "client-indexer")] + fn get_db_blocks_in_local_blockchain( + &self, + numbers: Vec<BlockNumber>, + ) -> Result<Vec<DbBlock>, DbError> { + self.read(|r| { + numbers + .into_iter() + .filter_map( + |n| match crate::blocks::get_db_block_in_local_blockchain(self, r, n) { + Ok(Some(db_block)) => Some(Ok(db_block)), + Ok(None) => None, + Err(e) => Some(Err(e)), + }, + ) + .collect::<Result<Vec<DbBlock>, DbError>>() + }) + } +} + +pub struct BcDbRoWithReader<'r, 'db: 'r> { + pub db: &'db BcDbRo, + pub r: Reader<'r>, +} + +impl<'r, 'db: 'r> BcDbRoTrait for BcDbRoWithReader<'r, 'db> { + fn get_current_blockstamp(&self) -> Result<Option<Blockstamp>, DbError> { + crate::current_meta_datas::get_current_blockstamp_(self.db, self.r) + } + fn get_current_block(&self) -> Result<Option<DbBlock>, DbError> { + unimplemented!() + } + fn get_db_block_in_local_blockchain( + &self, + _block_number: BlockNumber, + ) -> Result<Option<DbBlock>, DbError> { + unimplemented!() + } + fn get_db_blocks_in_local_blockchain( + &self, + _numbers: Vec<BlockNumber>, + ) -> Result<Vec<DbBlock>, DbError> { + unimplemented!() + } +} diff --git a/lib/tools/dbs-tools/Cargo.toml b/lib/tools/dbs-tools/Cargo.toml index 387bf05f8e3e9f856a9e6689b61111e754ae6304..e00a66f2ff50a5c6fe49772cecd3544a6913c829 100644 --- a/lib/tools/dbs-tools/Cargo.toml +++ b/lib/tools/dbs-tools/Cargo.toml @@ -12,6 +12,7 @@ path = "src/lib.rs" [dependencies] bincode = "1.0.*" durs-common-tools = { path = "../common-tools" } +failure = "0.1.5" fnv = "1.0.6" log = "0.4.*" rkv = "0.9.7" diff --git a/lib/tools/dbs-tools/src/errors.rs b/lib/tools/dbs-tools/src/errors.rs index 0f6a07cfc4daf13dbea0dd3e5dabff1be5c2dcf5..ad32731da0d5d1ba14623e6a90a9ddc1d486fe7e 100644 --- a/lib/tools/dbs-tools/src/errors.rs +++ b/lib/tools/dbs-tools/src/errors.rs @@ -16,33 +16,44 @@ //! Common Datas Access Layer for Dunitrust project //! Errors manadgment +use failure::Fail; use rustbreak::error::{RustbreakError, RustbreakErrorKind}; -#[derive(Debug)] +#[derive(Debug, Fail)] /// Data Access Layer Error pub enum DbError { /// A database is corrupted, you have to reset the data completely + #[fail(display = "Database is corrupted, you have to reset the data completely")] DBCorrupted, - /// Database not exist + /// Database not exist + #[fail(display = "Database not exist")] DBNotExist, /// Error in read operation + #[fail(display = "Error in read operation")] ReadError, /// Error with the file system + #[fail(display = "Error with the file system")] FileSystemError(std::io::Error), /// Serialization/Deserialization error + #[fail(display = "Serialization/Deserialization error: {}", _0)] SerdeError(String), /// Rkv store error + #[fail(display = "Store error: {}", _0)] StoreError(rkv::error::StoreError), /// Unknown error + #[fail(display = "Unknown error")] UnknowError, /// Abort write transaction + #[fail(display = "Abort write transaction, reason: {}", _0)] WriteAbort { /// Reason of transaction abort reason: String, }, /// Error in write operation + #[fail(display = "Error in write operation")] WriteError, /// Capturing a panic signal during a write operation + #[fail(display = "Capturing a panic signal during a write operation")] WritePanic, } diff --git a/lib/tools/dbs-tools/src/kv_db/file.rs b/lib/tools/dbs-tools/src/kv_db/file.rs index b76ebc325cfa12334041376b5507f9106fa7235d..6f15d753502c51a3495c35d4b442cb535a2e2d7d 100644 --- a/lib/tools/dbs-tools/src/kv_db/file.rs +++ b/lib/tools/dbs-tools/src/kv_db/file.rs @@ -29,6 +29,28 @@ use std::sync::{Arc, RwLock}; /// Key-value database reader pub type KvFileDbReader<'a> = &'a rkv::Reader<'a>; +/// Mock db reader +pub struct MockKvFileDbReader; + +impl MockKvFileDbReader { + pub fn new() -> Self { + Self + } +} + +impl rkv::Readable for MockKvFileDbReader { + fn get<K: AsRef<[u8]>>( + &self, + _db: rkv::Database, + _k: &K, + ) -> Result<Option<Value>, rkv::StoreError> { + unimplemented!() + } + fn open_ro_cursor(&self, _db: rkv::Database) -> Result<rkv::RoCursor, rkv::StoreError> { + unimplemented!() + } +} + /// Key-value database writer pub struct KvFileDbWriter<'a> { buffer: Vec<u8>,