From 71904d1453fef9a52859b68c67a4188a92ab709b Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 4 Oct 2021 09:02:20 -0400 Subject: [PATCH] Sync stuff. --- cumberland/Cargo.toml | 1 + cumberland/src/hasher.rs | 6 +++++ cumberland/src/lib.rs | 11 ++++------ cumberland/src/network.rs | 23 +++++++++++++++++++ cumberland/src/store.rs | 44 +++++++++++++++++++++++++++++++++++++ cumberland/src/validator.rs | 11 ++++++++++ 6 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 cumberland/src/hasher.rs create mode 100644 cumberland/src/network.rs create mode 100644 cumberland/src/store.rs create mode 100644 cumberland/src/validator.rs diff --git a/cumberland/Cargo.toml b/cumberland/Cargo.toml index 53ef4a5b3..f1fc5bdac 100644 --- a/cumberland/Cargo.toml +++ b/cumberland/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2018" [dependencies] +parking_lot = "^0" diff --git a/cumberland/src/hasher.rs b/cumberland/src/hasher.rs new file mode 100644 index 000000000..3e5f8a7e7 --- /dev/null +++ b/cumberland/src/hasher.rs @@ -0,0 +1,6 @@ +/// Hasher responsible for hashing keys. +pub trait Hasher { + const OUTPUT_SIZE: usize; + fn new() -> Self; + fn digest(&mut self, b: &[u8]) -> [u8; Self::OUTPUT_SIZE]; +} diff --git a/cumberland/src/lib.rs b/cumberland/src/lib.rs index 31e1bb209..57010e333 100644 --- a/cumberland/src/lib.rs +++ b/cumberland/src/lib.rs @@ -1,7 +1,4 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } -} +mod store; +mod validator; +mod network; +mod hasher; diff --git a/cumberland/src/network.rs b/cumberland/src/network.rs new file mode 100644 index 000000000..9e98d14bf --- /dev/null +++ b/cumberland/src/network.rs @@ -0,0 +1,23 @@ +use std::hash::Hash; + +/// An interface to a physical network such as TCP/IP or ZeroTier. +pub trait Network { + /// An endpoint address on the network to which messages can be sent. + type Address: Hash + Clone; + + /// The maximum message size that can be handled by this Network. + /// Note that the underlying transport must be able to handle sizes of at least 4096. + const MAX_MESSAGE_SIZE: usize; + + /// Attempt to send a message to an address. + /// + /// The semantics required are similar to UDP in that delivery need not be guaranteed. + /// A return value of false indicates an obvious error such as invalid address. + fn send(&self, to: &Address, data: &[u8]) -> bool; + + /// Receive the next incoming message. + /// + /// This should block until the next message is available. A return of None indicates + /// that the instance is shutting down. + fn receive(&self) -> Option<(Address, Vec)>; +} diff --git a/cumberland/src/store.rs b/cumberland/src/store.rs new file mode 100644 index 000000000..05e3c8ef2 --- /dev/null +++ b/cumberland/src/store.rs @@ -0,0 +1,44 @@ +use std::collections::BTreeMap; +use std::ops::Bound::Included; +use std::sync::Arc; + +use parking_lot::Mutex; + +/// Trait to be implemented by any data store to be replicated. +pub trait Store { + fn load(&self, key: &[u8]) -> Option>; + fn store(&self, key: &[u8], value: &[u8]) -> bool; + fn for_each_range)>(&self, starting_key: &[u8], ending_key: &[u8], f: F); + fn count(&self, starting_key: &[u8], ending_key: &[u8]) -> Option; +} + +/// A simple BTreeMap backed Store, mostly for testing as it does not persist anything. +#[derive(Clone)] +pub struct BTreeStore(Mutex>>); + +impl BTreeStore { + pub fn new() -> Self { Self(Mutex::new(BTreeMap::new())) } +} + +impl Store for BTreeStore { + fn load(&self, key: &[u8]) -> Option> { + let db = self.0.lock(); + db.get(key).map(|v| v.clone()) + } + + fn store(&self, key: &[u8], value: &[u8]) -> bool { + let mut db = self.0.lock(); + let _ = db.insert(*key, Arc::from(value)); + true + } + + fn for_each_range))>(&self, starting_key: &[u8], ending_key: &[u8], f: F) { + let db = self.0.lock(); + db.range((Included(starting_key), Included(ending_key))).for_each(f) + } + + fn count(&self, starting_key: &[u8], ending_key: &[u8]) -> Option { + let db = self.0.lock(); + Some(db.range((Included(starting_key), Included(ending_key))).count() as u64) + } +} diff --git a/cumberland/src/validator.rs b/cumberland/src/validator.rs new file mode 100644 index 000000000..dea768079 --- /dev/null +++ b/cumberland/src/validator.rs @@ -0,0 +1,11 @@ +pub trait Validator { + /// Check an entry and return true if it should be stored, returned, or replicated. + fn validate(&self, key: &[u8; 48], value: &[u8]) -> bool; +} + +/// A validator that approves everything, mostly for testing. +pub struct NilValidator; + +impl Validator for NilValidator { + fn validate(&self, _: &[u8; 48], _: &[u8]) -> bool { true } +}