From 12135cee52afa5dfe61347d273553013a334ae84 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sat, 11 Aug 2018 18:08:57 +1000 Subject: [PATCH 01/49] WIP on riker actor --- core/Cargo.toml | 2 ++ core/config/riker.toml | 37 ++++++++++++++++++++++++++++++++++++ core/src/agent/state.rs | 27 +++++++++++++++++++++++++- core/src/chain/actor.rs | 33 ++++++++++++++++++++++++++++++++ core/src/chain/mod.rs | 2 +- core/src/hash_table/actor.rs | 0 core/src/lib.rs | 2 ++ core/src/state.rs | 2 +- 8 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 core/config/riker.toml create mode 100644 core/src/chain/actor.rs create mode 100644 core/src/hash_table/actor.rs diff --git a/core/Cargo.toml b/core/Cargo.toml index 0770209fe0..773f4c1115 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,6 +17,8 @@ multihash = "0.8.0" rust-base58 = "0.0.4" bitflags = "1.0" holochain_wasm_utils = { path = "../wasm_utils"} +riker = "0.1.1" +riker-default = "0.1.1" [dev-dependencies] wabt = "0.4" diff --git a/core/config/riker.toml b/core/config/riker.toml new file mode 100644 index 0000000000..3718cca4ba --- /dev/null +++ b/core/config/riker.toml @@ -0,0 +1,37 @@ +debug = true + +[log] +# max level to log +level = "debug" + +# log format to use +# correlates to format!(log_format, date=, time=, level=, module=, body=); +# since named parameters are used the order of the fields is flexible +# the formatting of each field can be changed also +# e.g. to completely hide a field: {module:.0} +# See: https://doc.rust-lang.org/std/fmt/#syntax + +# {date} the calendar day +# {time} the calendar time +# {level} the level for the entry +# {module} the module path originating the entry +# {body} the message body +log_format = "{date} {time} {level} [{module}] {body}" +date_format = "%Y-%m-%d" +time_format = "%H:%M:%S%:z" + +[mailbox] +# maximum number of messages to process in each execution of mailbox +# the mailbox will be rescheduled if there are any remaining messages +msg_process_limit = 1000 + +[dispatcher] +# number of threads available to the CPU pool +pool_size = 4 + +[scheduler] +frequency_millis = 50 + +[cqrs] +# number of seconds of inactivity after which a cqrs actor will sleep +sleep_after_secs = 120 diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 25d4056d30..1b4bef7622 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -2,6 +2,8 @@ use agent::keys::Keys; use chain::Chain; use hash_table::{entry::Entry, memory::MemTable, pair::Pair}; use instance::Observer; +use riker::actors::*; +use riker_default::DefaultModel; use snowflake; use state; use std::{ @@ -9,8 +11,9 @@ use std::{ rc::Rc, sync::{mpsc::Sender, Arc}, }; +use chain::actor::ChainActor; -#[derive(Clone, Debug, PartialEq, Default)] +#[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers pub struct AgentState { keys: Option, @@ -22,15 +25,23 @@ pub struct AgentState { // @TODO this will blow up memory, implement as some kind of dropping/FIFO with a limit? // @see https://github.com/holochain/holochain-rust/issues/166 actions: HashMap, + chain: ActorRef, } impl AgentState { /// builds a new, empty AgentState pub fn new() -> AgentState { + let model: DefaultModel = DefaultModel::new(); + let sys = ActorSystem::new(&model).unwrap(); + + let props = ChainActor::props(); + let actor = sys.actor_of(props, "actor-name-here").unwrap(); + AgentState { keys: None, top_pair: None, actions: HashMap::new(), + chain: actor, } } @@ -186,6 +197,20 @@ pub mod tests { use super::{do_action_commit, do_action_get, Action, ActionResult, AgentState}; use hash_table::{entry::tests::test_entry, pair::tests::test_pair}; use std::collections::HashMap; + use riker::actor::Tell; + use std::thread; + + #[test] + fn test_actor_receive() { + let state = test_agent_state(); + + state.chain.tell("hi".to_string(), None); + let chain = state.chain.clone(); + let handle = thread::spawn(move || { + chain.tell("thread hi!".to_string(), None); + }); + handle.join().unwrap(); + } /// builds a dummy agent state for testing pub fn test_agent_state() -> AgentState { diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs new file mode 100644 index 0000000000..faf09627e8 --- /dev/null +++ b/core/src/chain/actor.rs @@ -0,0 +1,33 @@ +use riker::actors::*; + +#[derive(Clone, Debug)] +pub struct ChainActor; + +impl ChainActor { + pub fn new() -> ChainActor { + ChainActor {} + } +} + +impl Actor for ChainActor { + type Msg = String; + + fn receive( + &mut self, + context: &Context, + message: Self::Msg, + sender: Option>, + ) { + println!("received {}", message); + } +} + +impl ChainActor { + pub fn actor() -> BoxActor { + Box::new(ChainActor) + } + + pub fn props() -> BoxActorProd { + Props::new(Box::new(ChainActor::actor)) + } +} diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index d8d2d32c2a..e989ce315f 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,4 +1,4 @@ -// pub mod memory; +pub mod actor; use error::HolochainError; use hash_table::{entry::Entry, pair::Pair, HashTable}; use serde_json; diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core/src/lib.rs b/core/src/lib.rs index 39e061d6be..facd1bed37 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -11,6 +11,8 @@ extern crate test_utils; extern crate wasmi; #[macro_use] extern crate bitflags; +extern crate riker; +extern crate riker_default; extern crate holochain_agent; extern crate holochain_dna; diff --git a/core/src/state.rs b/core/src/state.rs index 0c628d36a8..1a494f5396 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -47,7 +47,7 @@ impl Hash for ActionWrapper { } } -#[derive(Clone, PartialEq, Debug, Default)] +#[derive(Clone, PartialEq, Debug)] pub struct State { nucleus: Arc, agent: Arc, From edb2676d24fad4a9fcf1a82b3f6fd43198147d25 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sat, 11 Aug 2018 19:18:42 +1000 Subject: [PATCH 02/49] passing tests with symlinked riker config --- {core/config => config}/riker.toml | 0 core/config | 1 + core_api/config | 1 + 3 files changed, 2 insertions(+) rename {core/config => config}/riker.toml (100%) create mode 120000 core/config create mode 120000 core_api/config diff --git a/core/config/riker.toml b/config/riker.toml similarity index 100% rename from core/config/riker.toml rename to config/riker.toml diff --git a/core/config b/core/config new file mode 120000 index 0000000000..3ca249e06b --- /dev/null +++ b/core/config @@ -0,0 +1 @@ +../config \ No newline at end of file diff --git a/core_api/config b/core_api/config new file mode 120000 index 0000000000..3ca249e06b --- /dev/null +++ b/core_api/config @@ -0,0 +1 @@ +../config \ No newline at end of file From 1480a6cef861393f256fa3ec97b3ed4c873b82b0 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sat, 11 Aug 2018 22:19:19 +1000 Subject: [PATCH 03/49] WIP on riker actors for chain --- core/Cargo.toml | 3 + core/src/agent/state.rs | 83 ++++++++++++++++---------- core/src/chain/actor.rs | 33 ----------- core/src/chain/mod.rs | 107 +++++++++++++++++++++++++--------- core/src/hash_table/actor.rs | 36 ++++++++++++ core/src/hash_table/header.rs | 4 +- core/src/hash_table/mod.rs | 1 + core/src/hash_table/pair.rs | 4 +- core/src/lib.rs | 4 ++ docker/Dockerfile.ubuntu | 6 +- 10 files changed, 183 insertions(+), 98 deletions(-) delete mode 100644 core/src/chain/actor.rs diff --git a/core/Cargo.toml b/core/Cargo.toml index 773f4c1115..2ef950a689 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -19,6 +19,9 @@ bitflags = "1.0" holochain_wasm_utils = { path = "../wasm_utils"} riker = "0.1.1" riker-default = "0.1.1" +riker-patterns = "0.1.0" +futures-preview = "0.2.2" +lazy_static = "1.1.0" [dev-dependencies] wabt = "0.4" diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 1b4bef7622..e85e3efe37 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -1,6 +1,6 @@ use agent::keys::Keys; use chain::Chain; -use hash_table::{entry::Entry, memory::MemTable, pair::Pair}; +use hash_table::{entry::Entry, pair::Pair}; use instance::Observer; use riker::actors::*; use riker_default::DefaultModel; @@ -8,10 +8,15 @@ use snowflake; use state; use std::{ collections::HashMap, - rc::Rc, sync::{mpsc::Sender, Arc}, }; -use chain::actor::ChainActor; +use chain::ChainProtocol; +use hash_table::actor::HashTableActor; +use hash_table::HashTable; +use hash_table::actor::HashTableProtocol; +use futures::executor::block_on; +use riker_patterns::ask::ask; +use chain::CHAIN_SYS; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers @@ -25,23 +30,25 @@ pub struct AgentState { // @TODO this will blow up memory, implement as some kind of dropping/FIFO with a limit? // @see https://github.com/holochain/holochain-rust/issues/166 actions: HashMap, - chain: ActorRef, + chain: ActorRef, } impl AgentState { /// builds a new, empty AgentState - pub fn new() -> AgentState { - let model: DefaultModel = DefaultModel::new(); - let sys = ActorSystem::new(&model).unwrap(); + pub fn new(table: T) -> AgentState { + let table_model: DefaultModel = DefaultModel::new(); + let table_sys = ActorSystem::new(&table_model).unwrap(); + let table_props = HashTableActor::props(&table); + let table_actor = table_sys.actor_of(table_props, "table").unwrap(); - let props = ChainActor::props(); - let actor = sys.actor_of(props, "actor-name-here").unwrap(); + let chain_props = Chain::props(&table_actor); + let chain = CHAIN_SYS.actor_of(chain_props, "chain").unwrap(); AgentState { keys: None, top_pair: None, actions: HashMap::new(), - chain: actor, + chain, } } @@ -114,22 +121,28 @@ pub enum ActionResult { fn do_action_commit(state: &mut AgentState, action: &Action) { match action { Action::Commit { entry, .. } => { - // add entry to source chain - // @TODO this does nothing! - // it needs to get something stateless from the agent state that points to - // something stateful that can handle an entire hash table (e.g. actor) - // @see https://github.com/holochain/holochain-rust/issues/135 - // @see https://github.com/holochain/holochain-rust/issues/148 - let mut chain = Chain::new(Rc::new(MemTable::new())); - // @TODO successfully validate before pushing a commit // @see https://github.com/holochain/holochain-rust/issues/97 - let result = chain.push(&entry).unwrap().entry().key(); + let a = ask( + &(*CHAIN_SYS), + &state.chain, + ChainProtocol::Push(entry.clone()), + ); + // .push(&entry).unwrap().entry().key(); + let response = block_on(a).unwrap(); + let result = match response { + ChainProtocol::PushResult(r) => { + r.unwrap().entry().key() + } + }; state .actions - .insert(action.clone(), ActionResult::Commit(result)); - } + .insert( + action.clone(), + ActionResult::Commit(result), + ); + }, _ => { panic!("action commit without commit action"); } @@ -141,25 +154,31 @@ fn do_action_commit(state: &mut AgentState, action: &Action) { fn do_action_get(state: &mut AgentState, action: &Action) { match action { Action::Get { key, .. } => { - // get pair from source chain - // @TODO this does nothing! - // it needs to get something stateless from the agent state that points to - // something stateful that can handle an entire hash table (e.g. actor) - // @see https://github.com/holochain/holochain-rust/issues/135 - // @see https://github.com/holochain/holochain-rust/issues/148 // drop in a dummy entry for testing - let mut chain = Chain::new(Rc::new(MemTable::new())); - let e = Entry::new("testEntryType", "test entry content"); - chain.push(&e).unwrap(); + let mut chain = state.chain; + + let a = ask( + &(*CHAIN_SYS), + &state.chain, + ChainProtocol::GetEntry(key.clone()), + ); + let response = block_on(a).unwrap(); + let result = match response { + ChainProtocol::GetEntryResult(r) => { + r.unwrap() + }, + }; // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 - let result = chain.get_entry(&key).unwrap(); state .actions - .insert(action.clone(), ActionResult::Get(result)); + .insert( + action.clone(), + ActionResult::Get(result), + ); } _ => { panic!("action get without get action"); diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs deleted file mode 100644 index faf09627e8..0000000000 --- a/core/src/chain/actor.rs +++ /dev/null @@ -1,33 +0,0 @@ -use riker::actors::*; - -#[derive(Clone, Debug)] -pub struct ChainActor; - -impl ChainActor { - pub fn new() -> ChainActor { - ChainActor {} - } -} - -impl Actor for ChainActor { - type Msg = String; - - fn receive( - &mut self, - context: &Context, - message: Self::Msg, - sender: Option>, - ) { - println!("received {}", message); - } -} - -impl ChainActor { - pub fn actor() -> BoxActor { - Box::new(ChainActor) - } - - pub fn props() -> BoxActorProd { - Props::new(Box::new(ChainActor::actor)) - } -} diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index e989ce315f..070c6151f7 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,26 +1,49 @@ -pub mod actor; use error::HolochainError; use hash_table::{entry::Entry, pair::Pair, HashTable}; use serde_json; -use std::{fmt, rc::Rc}; +use std::{fmt}; +use riker::actors::*; +use hash_table::actor::HashTableProtocol; +use riker_default::DefaultModel; + +lazy_static! { + pub static ref CHAIN_SYS: ActorSystem = { + let chain_model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&chain_model).unwrap() + }; +} + +#[derive(Debug, Clone)] +pub enum ChainProtocol { + Push(Entry), + PushResult(Result), + GetEntry(String), + GetEntryResult(Result, HolochainError>), +} + +impl Into> for ChainProtocol { + + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } + +} #[derive(Clone)] -pub struct ChainIterator { - // @TODO thread safe table references - // @see https://github.com/holochain/holochain-rust/issues/135 - table: Rc, +pub struct ChainIterator { + table: ActorRef, current: Option, } -impl ChainIterator { +impl ChainIterator { // @TODO table implementation is changing anyway so waste of time to mess with ref/value // @see https://github.com/holochain/holochain-rust/issues/135 #[allow(unknown_lints)] #[allow(needless_pass_by_value)] - pub fn new(table: Rc, pair: &Option) -> ChainIterator { + pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { ChainIterator { current: pair.clone(), - table: Rc::clone(&table), + table: table.clone(), } } @@ -30,7 +53,7 @@ impl ChainIterator { } } -impl Iterator for ChainIterator { +impl Iterator for ChainIterator { type Item = Pair; fn next(&mut self) -> Option { @@ -44,15 +67,39 @@ impl Iterator for ChainIterator { } } -pub struct Chain { +pub struct Chain { // @TODO thread safe table references // @see https://github.com/holochain/holochain-rust/issues/135 - table: Rc, + table: ActorRef, top: Option, } -impl PartialEq for Chain { - fn eq(&self, other: &Chain) -> bool { +impl Actor for Chain { + type Msg = ChainProtocol; + + fn receive( + &mut self, + context: &Context, + message: Self::Msg, + sender: Option>, + ) { + println!("received {}", message); + sender.try_tell( + match message { + ChainProtocol::Push(entry) => { + ChainProtocol::PushResult(self.push(entry)) + }, + ChainProtocol::GetEntry(key) => { + ChainProtocol::GetEntryResult(self.get_entry(&key)) + }, + }, + Some(context.myself()), + ).unwrap(); + } +} + +impl PartialEq for Chain { + fn eq(&self, other: &Chain) -> bool { // an invalid chain is like NaN... not even equal to itself self.validate() && other.validate() && @@ -61,44 +108,52 @@ impl PartialEq for Chain { } } -impl Eq for Chain {} +impl Eq for Chain {} -impl fmt::Debug for Chain { +impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Chain {{ top: {:?} }}", self.top) } } -impl IntoIterator for Chain { +impl IntoIterator for Chain { type Item = Pair; - type IntoIter = ChainIterator; + type IntoIter = ChainIterator; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl Chain { +impl Chain { // @TODO table implementation is changing anyway so waste of time to mess with ref/value // @see https://github.com/holochain/holochain-rust/issues/135 #[allow(unknown_lints)] #[allow(needless_pass_by_value)] /// build a new Chain against an existing HashTable - pub fn new(table: Rc) -> Chain { + pub fn new(table: ActorRef) -> Chain { Chain { top: None, - table: Rc::clone(&table), + table: table.clone(), } } + pub fn actor(table: &ActorRef) -> BoxActor { + Box::new(Chain::new(&table)) + } + + pub fn props(table: &ActorRef) -> BoxActorProd { + Props::new_args(Box::new(Chain::actor), &table) + } + /// returns a clone of the top Pair pub fn top(&self) -> Option { self.top.clone() } /// returns a reference to the underlying HashTable - pub fn table(&self) -> Rc { - Rc::clone(&self.table) + pub fn table(&self) -> ActorRef { + self.table.clone() } /// private pair-oriented version of push() (which expects Entries) @@ -122,7 +177,7 @@ impl Chain { // @TODO implement incubator for thread safety // @see https://github.com/holochain/holochain-rust/issues/135 - let table = Rc::get_mut(&mut self.table).unwrap(); + let table = &mut self.table; let result = table.commit(&pair); if result.is_ok() { self.top = Some(pair.clone()); @@ -148,7 +203,7 @@ impl Chain { } /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable - pub fn iter(&self) -> ChainIterator { + pub fn iter(&self) -> ChainIterator { ChainIterator::new(self.table(), &self.top()) } @@ -184,7 +239,7 @@ impl Chain { /// restore canonical JSON chain /// @TODO accept canonical JSON /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn from_json(table: Rc, s: &str) -> Self { + pub fn from_json(table: ActorRef, s: &str) -> Self { // @TODO inappropriate unwrap? // @see https://github.com/holochain/holochain-rust/issues/168 let mut as_seq: Vec = serde_json::from_str(s).unwrap(); diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index e69de29bb2..26fa4c5a19 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -0,0 +1,36 @@ +use riker::actors::*; +use hash_table::HashTable; + +#[derive(Debug, Clone)] +pub enum HashTableProtocol { + +} + +impl Into> for HashTableProtocol { + + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } + +} + +#[derive(Clone, Debug)] +pub struct HashTableActor { + table: T, +} + +impl HashTableActor { + pub fn new(table: T) -> HashTableActor { + HashTableActor { + table + } + } + + pub fn actor(table: &T) -> BoxActor { + Box::new(HashTableActor::new(&table)) + } + + pub fn props(table: &T) -> BoxActorProd { + Props::new(Box::new_args(HashTableActor::actor, &table)) + } +} diff --git a/core/src/hash_table/header.rs b/core/src/hash_table/header.rs index 37bab867bb..8687f636d4 100644 --- a/core/src/hash_table/header.rs +++ b/core/src/hash_table/header.rs @@ -1,6 +1,6 @@ use chain::Chain; use hash; -use hash_table::{entry::Entry, HashTable}; +use hash_table::{entry::Entry}; use multihash::Hash; // @TODO - serialize properties as defined in HeadersEntrySchema from golang alpha 1 @@ -38,7 +38,7 @@ impl Header { /// chain::SourceChain trait and should not need to be handled manually /// @see chain::pair::Pair /// @see chain::entry::Entry - pub fn new(chain: &Chain, entry: &Entry) -> Header { + pub fn new(chain: &Chain, entry: &Entry) -> Header { Header { entry_type: entry.entry_type().clone(), // @TODO implement timestamps diff --git a/core/src/hash_table/mod.rs b/core/src/hash_table/mod.rs index 4a986e6245..9caa1daf46 100644 --- a/core/src/hash_table/mod.rs +++ b/core/src/hash_table/mod.rs @@ -4,6 +4,7 @@ pub mod memory; pub mod pair; pub mod pair_meta; pub mod status; +pub mod actor; use agent::keys::Keys; use error::HolochainError; diff --git a/core/src/hash_table/pair.rs b/core/src/hash_table/pair.rs index 8f215f88e5..669b1b792b 100644 --- a/core/src/hash_table/pair.rs +++ b/core/src/hash_table/pair.rs @@ -1,5 +1,5 @@ use chain::Chain; -use hash_table::{entry::Entry, header::Header, HashTable}; +use hash_table::{entry::Entry, header::Header}; use serde_json; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -18,7 +18,7 @@ impl Pair { /// now be valid, the new Y' will include correct headers pointing to X. /// @see chain::entry::Entry /// @see chain::header::Header - pub fn new(chain: &Chain, entry: &Entry) -> Pair { + pub fn new(chain: &Chain, entry: &Entry) -> Pair { let header = Header::new(chain, entry); let p = Pair { diff --git a/core/src/lib.rs b/core/src/lib.rs index facd1bed37..310f5e8c7e 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -13,6 +13,10 @@ extern crate wasmi; extern crate bitflags; extern crate riker; extern crate riker_default; +extern crate riker_patterns; +extern crate futures; +#[macro_use] +extern crate lazy_static; extern crate holochain_agent; extern crate holochain_dna; diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu index 81aac157f0..5c5b39281d 100644 --- a/docker/Dockerfile.ubuntu +++ b/docker/Dockerfile.ubuntu @@ -7,13 +7,13 @@ ENV DEBIAN_FRONTEND noninteractive ENV DOCKER_BUILD_USER holochain # The Rust version used for the Wasm builds -ENV WASM_NIGHTLY nightly-2018-06-01 +ENV WASM_NIGHTLY nightly-2018-08-06 # The Rust version used for the tools -ENV TOOLS_NIGHTLY nightly-2018-07-17 +ENV TOOLS_NIGHTLY nightly-2018-08-06 # The Rust version that is used everywhere else -ENV CORE_RUST_VERSION stable +ENV CORE_RUST_VERSION nightly-2018-08-06 RUN apt-get update && apt-get install --yes\ libssl-dev \ From ffff40b0d76b7c0c3ec4d4ba5e451d09f752fb93 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 15 Aug 2018 19:33:16 +1000 Subject: [PATCH 04/49] WIP on porting hash table to riker --- core/src/chain/mod.rs | 44 +++++++++++++++++++++++++++++------- core/src/hash_table/actor.rs | 19 ++++++++++++++++ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 070c6151f7..c1fde16c54 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -5,6 +5,9 @@ use std::{fmt}; use riker::actors::*; use hash_table::actor::HashTableProtocol; use riker_default::DefaultModel; +use riker_patterns::ask::ask; +use hash_table::actor::HASH_TABLE_SYS; +use futures::executor::block_on; lazy_static! { pub static ref CHAIN_SYS: ActorSystem = { @@ -21,6 +24,12 @@ pub enum ChainProtocol { GetEntryResult(Result, HolochainError>), } +impl fmt::Display for ChainProtocol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + impl Into> for ChainProtocol { fn into(self) -> ActorMsg { @@ -62,7 +71,18 @@ impl Iterator for ChainIterator { .and_then(|p| p.header().next()) // @TODO should this panic? // @see https://github.com/holochain/holochain-rust/issues/146 - .and_then(|h| self.table.get(&h).unwrap()); + .and_then(|h| { + let a = ask( + &(*HASH_TABLE_SYS), + &self.table, + HashTableProtocol::Get(h.to_string()), + ); + let response = block_on(a).unwrap(); + let result = match response { + HashTableProtocol::GetResponse(r) => r, + }; + result.unwrap() + }); ret } } @@ -87,7 +107,7 @@ impl Actor for Chain { sender.try_tell( match message { ChainProtocol::Push(entry) => { - ChainProtocol::PushResult(self.push(entry)) + ChainProtocol::PushResult(self.push(&entry)) }, ChainProtocol::GetEntry(key) => { ChainProtocol::GetEntryResult(self.get_entry(&key)) @@ -139,11 +159,11 @@ impl Chain { } pub fn actor(table: &ActorRef) -> BoxActor { - Box::new(Chain::new(&table)) + Box::new(Chain::new(table.clone())) } pub fn props(table: &ActorRef) -> BoxActorProd { - Props::new_args(Box::new(Chain::actor), &table) + Props::new_args(Box::new(Chain::actor), &table.clone()) } /// returns a clone of the top Pair @@ -156,6 +176,15 @@ impl Chain { self.table.clone() } + pub fn ask_table_and_wait(&self, message: HashTableProtocol) { + let a = ask( + &(*HASH_TABLE_SYS), + &self.table, + message + ); + block_on(a).unwrap() + } + /// private pair-oriented version of push() (which expects Entries) fn push_pair(&mut self, pair: Pair) -> Result { if !(pair.validate()) { @@ -175,10 +204,9 @@ impl Chain { ))); } - // @TODO implement incubator for thread safety - // @see https://github.com/holochain/holochain-rust/issues/135 - let table = &mut self.table; - let result = table.commit(&pair); + let commit_response = self.ask_table_and_wait(HashTableProtocol::Commit(pair.clone())); + let result = unwrap_to!(commit_response => HashTableProtocol::CommitResponse); + if result.is_ok() { self.top = Some(pair.clone()); } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 26fa4c5a19..f6186781b3 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,8 +1,21 @@ use riker::actors::*; use hash_table::HashTable; +use riker_default::DefaultModel; +use hash_table::pair::Pair; +use error::HolochainError; + +lazy_static! { + pub static ref HASH_TABLE_SYS: ActorSystem = { + let hash_table_model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&hash_table_model).unwrap() + }; +} #[derive(Debug, Clone)] pub enum HashTableProtocol { + /// HashTable::get() + Get(String), + GetResponse(Result, HolochainError>), } @@ -34,3 +47,9 @@ impl HashTableActor { Props::new(Box::new_args(HashTableActor::actor, &table)) } } + +#[test] +pub mod tests { + + +} From 979271417ed1af8fdb9fc93d52441b40b6002ee7 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 15 Aug 2018 20:29:50 +1000 Subject: [PATCH 05/49] wip on porting hashtable to actor --- core/Cargo.toml | 1 + core/src/agent/state.rs | 55 ++++++++++++++++-------------------- core/src/chain/mod.rs | 33 ++++++++++++---------- core/src/hash_table/actor.rs | 40 ++++++++++++++++++++------ core/src/hash_table/mod.rs | 2 +- core/src/lib.rs | 2 ++ core/src/state.rs | 6 +++- 7 files changed, 82 insertions(+), 57 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 2ef950a689..1159139db2 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -22,6 +22,7 @@ riker-default = "0.1.1" riker-patterns = "0.1.0" futures-preview = "0.2.2" lazy_static = "1.1.0" +unwrap_to = "0.1.0" [dev-dependencies] wabt = "0.4" diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index e85e3efe37..a0916b39fc 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -3,7 +3,6 @@ use chain::Chain; use hash_table::{entry::Entry, pair::Pair}; use instance::Observer; use riker::actors::*; -use riker_default::DefaultModel; use snowflake; use state; use std::{ @@ -13,10 +12,10 @@ use std::{ use chain::ChainProtocol; use hash_table::actor::HashTableActor; use hash_table::HashTable; -use hash_table::actor::HashTableProtocol; use futures::executor::block_on; use riker_patterns::ask::ask; use chain::CHAIN_SYS; +use hash_table::actor::HASH_TABLE_SYS; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers @@ -35,13 +34,12 @@ pub struct AgentState { impl AgentState { /// builds a new, empty AgentState - pub fn new(table: T) -> AgentState { - let table_model: DefaultModel = DefaultModel::new(); - let table_sys = ActorSystem::new(&table_model).unwrap(); - let table_props = HashTableActor::props(&table); - let table_actor = table_sys.actor_of(table_props, "table").unwrap(); + pub fn new(table: HT) -> AgentState { - let chain_props = Chain::props(&table_actor); + let table_props = HashTableActor::props(table); + let table_actor = HASH_TABLE_SYS.actor_of(table_props, "table").unwrap(); + + let chain_props = Chain::props(table_actor.clone()); let chain = CHAIN_SYS.actor_of(chain_props, "chain").unwrap(); AgentState { @@ -52,6 +50,15 @@ impl AgentState { } } + fn ask_chain_for_response(&self, message: ChainProtocol) -> ChainProtocol { + let a = ask( + &(*CHAIN_SYS), + &self.chain, + message + ); + block_on(a).unwrap() + } + /// getter for a copy of self.keys pub fn keys(&self) -> Option { self.keys.clone() @@ -124,18 +131,14 @@ fn do_action_commit(state: &mut AgentState, action: &Action) { // @TODO successfully validate before pushing a commit // @see https://github.com/holochain/holochain-rust/issues/97 - let a = ask( - &(*CHAIN_SYS), - &state.chain, + let response = state.ask_chain_for_response( ChainProtocol::Push(entry.clone()), ); - // .push(&entry).unwrap().entry().key(); - let response = block_on(a).unwrap(); - let result = match response { - ChainProtocol::PushResult(r) => { - r.unwrap().entry().key() - } - }; + let result = unwrap_to!(response => ChainProtocol::PushResult); + // commit returns the entry key not the pair, from the action's perspective as this is + // what the zome API expects + let result = result.clone().unwrap().entry().key(); + state .actions .insert( @@ -155,20 +158,10 @@ fn do_action_get(state: &mut AgentState, action: &Action) { match action { Action::Get { key, .. } => { - // drop in a dummy entry for testing - let mut chain = state.chain; - - let a = ask( - &(*CHAIN_SYS), - &state.chain, + let response = state.ask_chain_for_response( ChainProtocol::GetEntry(key.clone()), ); - let response = block_on(a).unwrap(); - let result = match response { - ChainProtocol::GetEntryResult(r) => { - r.unwrap() - }, - }; + let result = unwrap_to!(response => ChainProtocol::GetEntryResult); // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 @@ -177,7 +170,7 @@ fn do_action_get(state: &mut AgentState, action: &Action) { .actions .insert( action.clone(), - ActionResult::Get(result), + ActionResult::Get(result.clone().unwrap()), ); } _ => { diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index c1fde16c54..c4ab47ffda 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,5 +1,5 @@ use error::HolochainError; -use hash_table::{entry::Entry, pair::Pair, HashTable}; +use hash_table::{entry::Entry, pair::Pair}; use serde_json; use std::{fmt}; use riker::actors::*; @@ -78,10 +78,8 @@ impl Iterator for ChainIterator { HashTableProtocol::Get(h.to_string()), ); let response = block_on(a).unwrap(); - let result = match response { - HashTableProtocol::GetResponse(r) => r, - }; - result.unwrap() + let result = unwrap_to!(response => HashTableProtocol::GetResponse); + result.clone().unwrap() }); ret } @@ -109,9 +107,12 @@ impl Actor for Chain { ChainProtocol::Push(entry) => { ChainProtocol::PushResult(self.push(&entry)) }, + ChainProtocol::PushResult(_) => unreachable!(), + ChainProtocol::GetEntry(key) => { ChainProtocol::GetEntryResult(self.get_entry(&key)) }, + ChainProtocol::GetEntryResult(_) => unreachable!(), }, Some(context.myself()), ).unwrap(); @@ -158,12 +159,12 @@ impl Chain { } } - pub fn actor(table: &ActorRef) -> BoxActor { - Box::new(Chain::new(table.clone())) + pub fn actor(table: ActorRef) -> BoxActor { + Box::new(Chain::new(table)) } - pub fn props(table: &ActorRef) -> BoxActorProd { - Props::new_args(Box::new(Chain::actor), &table.clone()) + pub fn props(table: ActorRef) -> BoxActorProd { + Props::new_args(Box::new(Chain::actor), table) } /// returns a clone of the top Pair @@ -176,7 +177,8 @@ impl Chain { self.table.clone() } - pub fn ask_table_and_wait(&self, message: HashTableProtocol) { + /// asks the table something and blocks for a response + fn ask_table_for_response(&self, message: HashTableProtocol) -> HashTableProtocol { let a = ask( &(*HASH_TABLE_SYS), &self.table, @@ -204,7 +206,7 @@ impl Chain { ))); } - let commit_response = self.ask_table_and_wait(HashTableProtocol::Commit(pair.clone())); + let commit_response = self.ask_table_for_response(HashTableProtocol::Commit(pair.clone())); let result = unwrap_to!(commit_response => HashTableProtocol::CommitResponse); if result.is_ok() { @@ -212,7 +214,7 @@ impl Chain { } match result { Ok(_) => Ok(pair), - Err(e) => Err(e), + Err(e) => Err(e.clone()), } } @@ -237,7 +239,8 @@ impl Chain { /// get a Pair by Pair/Header key from the HashTable if it exists pub fn get(&self, k: &str) -> Result, HolochainError> { - self.table.get(k) + let response = self.ask_table_for_response(HashTableProtocol::Get(k.to_string())); + unwrap_to!(response => HashTableProtocol::GetResponse).clone() } /// get an Entry by Entry key from the HashTable if it exists @@ -287,14 +290,14 @@ pub mod tests { use super::Chain; use hash_table::{ entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, - memory::{tests::test_table, MemTable}, + memory::{tests::test_table}, pair::Pair, HashTable, }; use std::rc::Rc; /// builds a dummy chain for testing - pub fn test_chain() -> Chain { + pub fn test_chain() -> Chain { Chain::new(Rc::new(test_table())) } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index f6186781b3..8f8386ac87 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -17,6 +17,10 @@ pub enum HashTableProtocol { Get(String), GetResponse(Result, HolochainError>), + /// HashTable::commit() + Commit(Pair), + CommitResponse(Result<(), HolochainError>), + } impl Into> for HashTableProtocol { @@ -28,28 +32,46 @@ impl Into> for HashTableProtocol { } #[derive(Clone, Debug)] -pub struct HashTableActor { - table: T, +pub struct HashTableActor { + table: HT, } -impl HashTableActor { - pub fn new(table: T) -> HashTableActor { +impl HashTableActor { + pub fn new (table: HT) -> HashTableActor { HashTableActor { table } } - pub fn actor(table: &T) -> BoxActor { - Box::new(HashTableActor::new(&table)) + pub fn actor(table: HT) -> BoxActor { + Box::new(HashTableActor::new(table)) } - pub fn props(table: &T) -> BoxActorProd { - Props::new(Box::new_args(HashTableActor::actor, &table)) + pub fn props(table: HT) -> BoxActorProd { + Props::new_args(Box::new(HashTableActor::actor), table) } } -#[test] +impl Actor for HashTableActor { + type Msg = HashTableProtocol; + + fn receive( + &mut self, + _context: &Context, + _message: Self::Msg, + _sender: Option>, + ) { + + } + +} + +#[cfg(test)] pub mod tests { + #[test] + fn round_trip() { + + } } diff --git a/core/src/hash_table/mod.rs b/core/src/hash_table/mod.rs index 9caa1daf46..ed77d72751 100644 --- a/core/src/hash_table/mod.rs +++ b/core/src/hash_table/mod.rs @@ -10,7 +10,7 @@ use agent::keys::Keys; use error::HolochainError; use hash_table::{pair::Pair, pair_meta::PairMeta}; -pub trait HashTable { +pub trait HashTable: Send + Sync + Clone + 'static { // internal state management fn setup(&mut self) -> Result<(), HolochainError>; fn teardown(&mut self) -> Result<(), HolochainError>; diff --git a/core/src/lib.rs b/core/src/lib.rs index 310f5e8c7e..838a0fe9e3 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -17,6 +17,8 @@ extern crate riker_patterns; extern crate futures; #[macro_use] extern crate lazy_static; +#[macro_use] +extern crate unwrap_to; extern crate holochain_agent; extern crate holochain_dna; diff --git a/core/src/state.rs b/core/src/state.rs index 1a494f5396..f485479260 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -8,6 +8,7 @@ use std::{ hash::{Hash, Hasher}, sync::{mpsc::Sender, Arc}, }; +use hash_table::memory::MemTable; #[derive(Clone, Debug, PartialEq)] #[allow(unknown_lints)] @@ -58,9 +59,12 @@ pub struct State { impl State { pub fn new() -> Self { + // @TODO file table + let table = MemTable::new(); + State { nucleus: Arc::new(NucleusState::new()), - agent: Arc::new(AgentState::new()), + agent: Arc::new(AgentState::new(table)), history: HashSet::new(), } } From 7431b71df14a79737c4f5076c6467249476fc0cb Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 16 Aug 2018 00:10:47 +1000 Subject: [PATCH 06/49] WIP on splitting out chain actor --- core/src/agent/state.rs | 63 ++++------- core/src/chain/actor.rs | 126 ++++++++++++++++++++++ core/src/chain/mod.rs | 126 +++++++--------------- core/src/hash_table/actor.rs | 40 +++++++ core/src/nucleus/mod.rs | 2 + core/src/nucleus/ribosome/callback/mod.rs | 2 +- core/src/state.rs | 53 +++------ 7 files changed, 236 insertions(+), 176 deletions(-) create mode 100644 core/src/chain/actor.rs diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 99f4420a3d..dd73eadcc4 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -1,26 +1,16 @@ use action::{Action, ActionWrapper, AgentReduceFn}; use agent::keys::Keys; -use chain::Chain; -use hash_table::{entry::Entry, pair::Pair}; use instance::Observer; use riker::actors::*; -use snowflake; -use state; use context::Context; use error::HolochainError; -use hash_table::{entry::Entry, memory::MemTable, pair::Pair}; -use instance::Observer; +use hash_table::{pair::Pair}; use std::{ collections::HashMap, sync::{mpsc::Sender, Arc}, }; -use chain::ChainProtocol; -use hash_table::actor::HashTableActor; -use hash_table::HashTable; -use futures::executor::block_on; -use riker_patterns::ask::ask; -use chain::CHAIN_SYS; -use hash_table::actor::HASH_TABLE_SYS; +use chain::actor::ChainProtocol; +use chain::actor::AskChain; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers @@ -39,31 +29,15 @@ pub struct AgentState { impl AgentState { /// builds a new, empty AgentState - pub fn new(table: HT) -> AgentState { - - let table_props = HashTableActor::props(table); - let table_actor = HASH_TABLE_SYS.actor_of(table_props, "table").unwrap(); - - let chain_props = Chain::props(table_actor.clone()); - let chain = CHAIN_SYS.actor_of(chain_props, "chain").unwrap(); - + pub fn new(chain: ActorRef) -> AgentState { AgentState { keys: None, top_pair: None, actions: HashMap::new(), - chain, + chain: chain.clone(), } } - fn ask_chain_for_response(&self, message: ChainProtocol) -> ChainProtocol { - let a = ask( - &(*CHAIN_SYS), - &self.chain, - message - ); - block_on(a).unwrap() - } - /// getter for a copy of self.keys pub fn keys(&self) -> Option { self.keys.clone() @@ -130,19 +104,19 @@ fn reduce_commit( // @TODO successfully validate before pushing a commit // @see https://github.com/holochain/holochain-rust/issues/97 - let response = state.ask_chain_for_response( + let response = state.chain.ask( ChainProtocol::Push(entry.clone()), ); let result = unwrap_to!(response => ChainProtocol::PushResult); // commit returns the entry key not the pair, from the action's perspective as this is // what the zome API expects - let result = result.clone().unwrap().entry().key(); + let result = result.clone(); state .actions .insert( action_wrapper.clone(), - ActionResult::Commit(result), + ActionResponse::Commit(result), ); } @@ -158,7 +132,7 @@ fn reduce_get( let action = action_wrapper.action(); let key = unwrap_to!(action => Action::Get); - let response = state.ask_chain_for_response( + let response = state.chain.ask( ChainProtocol::GetEntry(key.clone()), ); let result = unwrap_to!(response => ChainProtocol::GetEntryResult); @@ -170,7 +144,7 @@ fn reduce_get( .actions .insert( action_wrapper.clone(), - ActionResult::Get(result.clone().unwrap()), + ActionResponse::Get(result.clone().unwrap()), ); } @@ -216,24 +190,23 @@ pub mod tests { use hash_table::pair::tests::test_pair; use instance::tests::{test_context, test_instance_blank}; use std::collections::HashMap; - use riker::actor::Tell; - use std::thread; + use chain::actor::tests::test_chain_actor; #[test] fn test_actor_receive() { let state = test_agent_state(); - state.chain.tell("hi".to_string(), None); - let chain = state.chain.clone(); - let handle = thread::spawn(move || { - chain.tell("thread hi!".to_string(), None); - }); - handle.join().unwrap(); + // state.chain.tell("hi".to_string(), None); + // let chain = state.chain.clone(); + // let handle = thread::spawn(move || { + // chain.tell("thread hi!".to_string(), None); + // }); + // handle.join().unwrap(); } /// dummy agent state pub fn test_agent_state() -> AgentState { - AgentState::new() + AgentState::new(test_chain_actor()) } /// dummy action response for a successful commit as test_pair() diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs new file mode 100644 index 0000000000..3246433214 --- /dev/null +++ b/core/src/chain/actor.rs @@ -0,0 +1,126 @@ +use riker_default::DefaultModel; +use riker::actors::*; +use std::{fmt}; +use futures::executor::block_on; +use riker_patterns::ask::ask; +use hash_table::entry::Entry; +use hash_table::pair::Pair; +use error::HolochainError; +use chain::Chain; + +lazy_static! { + pub static ref CHAIN_SYS: ActorSystem = { + let chain_model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&chain_model).unwrap() + }; +} + +/// anything that can be asked ChainProtocol and block on responses +/// needed to support implementing ask on upstream ActorRef from riker +pub trait AskChain { + fn ask(&self, message: ChainProtocol) -> ChainProtocol; +} + +impl AskChain for ActorRef { + fn ask(&self, message: ChainProtocol) -> ChainProtocol { + block_on( + ask( + &(*CHAIN_SYS), + self, + message, + ) + ).unwrap() + } +} + +#[derive(Debug, Clone)] +pub enum ChainProtocol { + Push(Entry), + PushPair(Pair), + PushResult(Result), + + GetEntry(String), + GetEntryResult(Result, HolochainError>), +} + +impl fmt::Display for ChainProtocol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl Into> for ChainProtocol { + + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } + +} + +pub struct ChainActor { + + chain: Chain, + +} + +impl ChainActor { + + pub fn new(chain: Chain) -> ChainActor { + ChainActor{ + chain, + } + } + + pub fn actor(chain: Chain) -> BoxActor { + Box::new(ChainActor::new(chain)) + } + + pub fn props(chain: Chain) -> BoxActorProd { + Props::new_args(Box::new(ChainActor::actor), chain) + } + + pub fn new_ref(chain: Chain) -> ActorRef { + CHAIN_SYS.actor_of( + ChainActor::props(chain), + "chain", + ).unwrap() + } + +} + +impl Actor for ChainActor { + type Msg = ChainProtocol; + + fn receive( + &mut self, + context: &Context, + message: Self::Msg, + sender: Option>, + ) { + println!("received {}", message); + sender.try_tell( + match message { + ChainProtocol::Push(entry) => ChainProtocol::PushResult(self.chain.push(&entry)), + ChainProtocol::PushPair(pair) => ChainProtocol::PushResult(self.chain.push_pair(&pair)), + ChainProtocol::PushResult(_) => unreachable!(), + + ChainProtocol::GetEntry(key) => ChainProtocol::GetEntryResult(self.chain.get_entry(&key)), + ChainProtocol::GetEntryResult(_) => unreachable!(), + }, + Some(context.myself()), + ).unwrap(); + } +} + +#[cfg(test)] +pub mod tests { + use super::ChainActor; + use riker::actors::*; + use chain::tests::test_chain; + use chain::actor::ChainProtocol; + + pub fn test_chain_actor() -> ActorRef { + ChainActor::new_ref(test_chain()) + } + +} diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index c4ab47ffda..873e49f50d 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,42 +1,17 @@ +pub mod actor; + +use riker::actors::*; use error::HolochainError; use hash_table::{entry::Entry, pair::Pair}; use serde_json; use std::{fmt}; -use riker::actors::*; use hash_table::actor::HashTableProtocol; -use riker_default::DefaultModel; use riker_patterns::ask::ask; use hash_table::actor::HASH_TABLE_SYS; use futures::executor::block_on; - -lazy_static! { - pub static ref CHAIN_SYS: ActorSystem = { - let chain_model: DefaultModel = DefaultModel::new(); - ActorSystem::new(&chain_model).unwrap() - }; -} - -#[derive(Debug, Clone)] -pub enum ChainProtocol { - Push(Entry), - PushResult(Result), - GetEntry(String), - GetEntryResult(Result, HolochainError>), -} - -impl fmt::Display for ChainProtocol { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - -impl Into> for ChainProtocol { - - fn into(self) -> ActorMsg { - ActorMsg::User(self) - } - -} +use chain::actor::ChainProtocol; +use hash_table::actor::AskHashTable; +use chain::actor::AskChain; #[derive(Clone)] pub struct ChainIterator { @@ -85,6 +60,7 @@ impl Iterator for ChainIterator { } } +#[derive(Clone)] pub struct Chain { // @TODO thread safe table references // @see https://github.com/holochain/holochain-rust/issues/135 @@ -92,33 +68,6 @@ pub struct Chain { top: Option, } -impl Actor for Chain { - type Msg = ChainProtocol; - - fn receive( - &mut self, - context: &Context, - message: Self::Msg, - sender: Option>, - ) { - println!("received {}", message); - sender.try_tell( - match message { - ChainProtocol::Push(entry) => { - ChainProtocol::PushResult(self.push(&entry)) - }, - ChainProtocol::PushResult(_) => unreachable!(), - - ChainProtocol::GetEntry(key) => { - ChainProtocol::GetEntryResult(self.get_entry(&key)) - }, - ChainProtocol::GetEntryResult(_) => unreachable!(), - }, - Some(context.myself()), - ).unwrap(); - } -} - impl PartialEq for Chain { fn eq(&self, other: &Chain) -> bool { // an invalid chain is like NaN... not even equal to itself @@ -147,11 +96,7 @@ impl IntoIterator for Chain { } impl Chain { - // @TODO table implementation is changing anyway so waste of time to mess with ref/value - // @see https://github.com/holochain/holochain-rust/issues/135 - #[allow(unknown_lints)] - #[allow(needless_pass_by_value)] - /// build a new Chain against an existing HashTable + pub fn new(table: ActorRef) -> Chain { Chain { top: None, @@ -159,14 +104,6 @@ impl Chain { } } - pub fn actor(table: ActorRef) -> BoxActor { - Box::new(Chain::new(table)) - } - - pub fn props(table: ActorRef) -> BoxActorProd { - Props::new_args(Box::new(Chain::actor), table) - } - /// returns a clone of the top Pair pub fn top(&self) -> Option { self.top.clone() @@ -177,18 +114,8 @@ impl Chain { self.table.clone() } - /// asks the table something and blocks for a response - fn ask_table_for_response(&self, message: HashTableProtocol) -> HashTableProtocol { - let a = ask( - &(*HASH_TABLE_SYS), - &self.table, - message - ); - block_on(a).unwrap() - } - /// private pair-oriented version of push() (which expects Entries) - fn push_pair(&mut self, pair: Pair) -> Result { + fn push_pair(&mut self, pair: &Pair) -> Result { if !(pair.validate()) { return Err(HolochainError::new( "attempted to push an invalid pair for this chain", @@ -206,14 +133,14 @@ impl Chain { ))); } - let commit_response = self.ask_table_for_response(HashTableProtocol::Commit(pair.clone())); + let commit_response = self.table.ask(HashTableProtocol::Commit(pair.clone())); let result = unwrap_to!(commit_response => HashTableProtocol::CommitResponse); if result.is_ok() { self.top = Some(pair.clone()); } match result { - Ok(_) => Ok(pair), + Ok(_) => Ok(pair.clone()), Err(e) => Err(e.clone()), } } @@ -224,7 +151,7 @@ impl Chain { /// the newly created and pushed Pair is returned in the fn Result pub fn push(&mut self, entry: &Entry) -> Result { let pair = Pair::new(self, entry); - self.push_pair(pair) + self.push_pair(&pair) } /// returns true if all pairs in the chain pass validation @@ -239,7 +166,7 @@ impl Chain { /// get a Pair by Pair/Header key from the HashTable if it exists pub fn get(&self, k: &str) -> Result, HolochainError> { - let response = self.ask_table_for_response(HashTableProtocol::Get(k.to_string())); + let response = self.table.ask(HashTableProtocol::Get(k.to_string())); unwrap_to!(response => HashTableProtocol::GetResponse).clone() } @@ -270,20 +197,40 @@ impl Chain { /// restore canonical JSON chain /// @TODO accept canonical JSON /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn from_json(table: ActorRef, s: &str) -> Self { + pub fn from_json(table: ActorRef, s: &str) -> Chain { // @TODO inappropriate unwrap? // @see https://github.com/holochain/holochain-rust/issues/168 let mut as_seq: Vec = serde_json::from_str(s).unwrap(); as_seq.reverse(); let mut chain = Chain::new(table); + for p in as_seq { - chain.push_pair(p).unwrap(); + chain.push_pair(&p).unwrap(); + // let response = chain.ask(ChainProtocol::PushPair(p)); + // let result = unwrap_to!(response => ChainProtocol::PushResult); + // result.clone().unwrap(); } chain } } +trait SourceChain { + + fn push(&mut self, &Entry) -> Result; + +} + +impl SourceChain for ActorRef { + + fn push(&mut self, entry: &Entry) -> Result { + let response = &self.ask(ChainProtocol::Push(entry.clone())); + let result = unwrap_to!(response => ChainProtocol::PushResult); + result.clone() + } + +} + #[cfg(test)] pub mod tests { @@ -295,10 +242,11 @@ pub mod tests { HashTable, }; use std::rc::Rc; + use hash_table::actor::tests::test_table_actor; /// builds a dummy chain for testing pub fn test_chain() -> Chain { - Chain::new(Rc::new(test_table())) + Chain::new(test_table_actor()) } #[test] diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 8f8386ac87..a23aae9754 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -3,6 +3,8 @@ use hash_table::HashTable; use riker_default::DefaultModel; use hash_table::pair::Pair; use error::HolochainError; +use futures::executor::block_on; +use riker_patterns::ask::ask; lazy_static! { pub static ref HASH_TABLE_SYS: ActorSystem = { @@ -11,6 +13,26 @@ lazy_static! { }; } +/// anything that can be asked HashTableProtocol and block on responses +/// needed to support implementing ask on upstream ActorRef from riker +pub trait AskHashTable { + + fn ask(&self, message: HashTableProtocol) -> HashTableProtocol; + +} + +impl AskHashTable for ActorRef { + fn ask(&self, message: HashTableProtocol) -> HashTableProtocol { + block_on( + ask( + &(*HASH_TABLE_SYS), + self, + message, + ) + ).unwrap() + } +} + #[derive(Debug, Clone)] pub enum HashTableProtocol { /// HashTable::get() @@ -37,6 +59,7 @@ pub struct HashTableActor { } impl HashTableActor { + pub fn new (table: HT) -> HashTableActor { HashTableActor { table @@ -50,6 +73,14 @@ impl HashTableActor { pub fn props(table: HT) -> BoxActorProd { Props::new_args(Box::new(HashTableActor::actor), table) } + + pub fn new_ref(table: HT) -> ActorRef { + HASH_TABLE_SYS.actor_of( + HashTableActor::props(table), + "table", + ).unwrap() + } + } impl Actor for HashTableActor { @@ -69,6 +100,15 @@ impl Actor for HashTableActor { #[cfg(test)] pub mod tests { + use super::HashTableActor; + use hash_table::memory::tests::test_table; + use riker::actors::*; + use hash_table::actor::HashTableProtocol; + + pub fn test_table_actor() -> ActorRef { + HashTableActor::new_ref(test_table()); + } + #[test] fn round_trip() { diff --git a/core/src/nucleus/mod.rs b/core/src/nucleus/mod.rs index 998f3925f7..69e372c7eb 100644 --- a/core/src/nucleus/mod.rs +++ b/core/src/nucleus/mod.rs @@ -33,6 +33,8 @@ pub struct FunctionCall { impl FunctionCall { pub fn new(zome: &str, capability: &str, function: &str, parameters: &str) -> Self { FunctionCall { + // @TODO + // can we defer to the ActionWrapper id? id: snowflake::ProcessUniqueId::new(), zome: zome.to_string(), capability: capability.to_string(), diff --git a/core/src/nucleus/ribosome/callback/mod.rs b/core/src/nucleus/ribosome/callback/mod.rs index ff0a8a25d9..091fb62289 100644 --- a/core/src/nucleus/ribosome/callback/mod.rs +++ b/core/src/nucleus/ribosome/callback/mod.rs @@ -166,7 +166,7 @@ pub fn call( let call_result = call_zome_and_wait_for_result(function_call.clone(), &action_channel, &observer_channel); - // translate the call result to a lifecycle result + // translate the call result to a callback result match call_result { // empty string OK = Success Ok(ref s) if s.is_empty() => CallbackResult::Pass, diff --git a/core/src/state.rs b/core/src/state.rs index 29513149da..b07956a119 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -1,4 +1,3 @@ -use action::ActionWrapper; use agent::state::AgentState; use context::Context; use instance::Observer; @@ -8,44 +7,10 @@ use std::{ sync::{mpsc::Sender, Arc}, }; use hash_table::memory::MemTable; - -#[derive(Clone, Debug, PartialEq)] -#[allow(unknown_lints)] -#[allow(large_enum_variant)] -pub enum Action { - Agent(::agent::state::Action), - Network(::network::Action), - Nucleus(::nucleus::Action), -} - -#[derive(Clone, Debug)] -pub struct ActionWrapper { - pub action: Action, - pub id: snowflake::ProcessUniqueId, -} - -impl ActionWrapper { - pub fn new(a: Action) -> Self { - ActionWrapper { - action: a, - id: snowflake::ProcessUniqueId::new(), - } - } -} - -impl PartialEq for ActionWrapper { - fn eq(&self, other: &ActionWrapper) -> bool { - self.id == other.id - } -} - -impl Eq for ActionWrapper {} - -impl Hash for ActionWrapper { - fn hash(&self, state: &mut H) { - self.id.hash(state); - } -} +use action::ActionWrapper; +use chain::Chain; +use chain::actor::ChainActor; +use hash_table::actor::HashTableActor; #[derive(Clone, PartialEq, Debug)] pub struct State { @@ -59,11 +24,17 @@ pub struct State { impl State { pub fn new() -> Self { // @TODO file table - let table = MemTable::new(); + let chain_actor = ChainActor::new_ref( + Chain::new( + HashTableActor::new_ref( + MemTable::new(), + ), + ), + ); State { nucleus: Arc::new(NucleusState::new()), - agent: Arc::new(AgentState::new(table)), + agent: Arc::new(AgentState::new(chain_actor)), history: HashSet::new(), } } From 4842d8b0f0802da0cac01574fd71b97711c840a6 Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 16 Aug 2018 19:28:05 +1000 Subject: [PATCH 07/49] WIP on SourceChain trait --- core/src/agent/state.rs | 11 +- core/src/chain/actor.rs | 92 ++++++++++--- core/src/chain/mod.rs | 247 +++++++++++++++++----------------- core/src/hash_table/actor.rs | 4 +- core/src/hash_table/header.rs | 8 +- 5 files changed, 202 insertions(+), 160 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index dd73eadcc4..b7c0ea5784 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -11,6 +11,7 @@ use std::{ }; use chain::actor::ChainProtocol; use chain::actor::AskChain; +use chain::SourceChain; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers @@ -104,19 +105,11 @@ fn reduce_commit( // @TODO successfully validate before pushing a commit // @see https://github.com/holochain/holochain-rust/issues/97 - let response = state.chain.ask( - ChainProtocol::Push(entry.clone()), - ); - let result = unwrap_to!(response => ChainProtocol::PushResult); - // commit returns the entry key not the pair, from the action's perspective as this is - // what the zome API expects - let result = result.clone(); - state .actions .insert( action_wrapper.clone(), - ActionResponse::Commit(result), + ActionResponse::Commit(state.chain.push_entry(&entry)), ); } diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 3246433214..c66e621b1e 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -7,6 +7,7 @@ use hash_table::entry::Entry; use hash_table::pair::Pair; use error::HolochainError; use chain::Chain; +use chain::SourceChain; lazy_static! { pub static ref CHAIN_SYS: ActorSystem = { @@ -15,8 +16,42 @@ lazy_static! { }; } +#[derive(Debug, Clone)] +pub enum ChainProtocol { + TopPair, + TopPairResult(Option), + + TopPairType(String), + TopPairTypeResult(Option), + + PushEntry(Entry), + PushEntryResult(Result), + + PushPair(Pair), + PushPairResult(Result), + + GetEntry(String), + GetEntryResult(Result, HolochainError>), + + GetPair(String), + GetPairResult(Result, HolochainError>), +} + +impl Into> for ChainProtocol { + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } +} + +impl fmt::Display for ChainProtocol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self) + } +} + /// anything that can be asked ChainProtocol and block on responses /// needed to support implementing ask on upstream ActorRef from riker +/// convenience wrappers around chain struct methods pub trait AskChain { fn ask(&self, message: ChainProtocol) -> ChainProtocol; } @@ -33,26 +68,36 @@ impl AskChain for ActorRef { } } -#[derive(Debug, Clone)] -pub enum ChainProtocol { - Push(Entry), - PushPair(Pair), - PushResult(Result), +impl SourceChain for ActorRef { - GetEntry(String), - GetEntryResult(Result, HolochainError>), -} + fn top_pair(&self) -> Option { + let response = self.ask(ChainProtocol::TopPair); + unwrap_to!(response => ChainProtocol::TopPairResult).clone() + } -impl fmt::Display for ChainProtocol { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) + fn top_pair_type(&self, t: &str) -> Option { + let response = self.ask(ChainProtocol::TopPairType(t.to_string())); + unwrap_to!(response => ChainProtocol::TopPairTypeResult).clone() } -} -impl Into> for ChainProtocol { + fn push_entry(&mut self, entry: &Entry) -> Result { + let response = self.ask(ChainProtocol::PushEntry(entry.clone())); + unwrap_to!(response => ChainProtocol::PushEntryResult).clone() + } - fn into(self) -> ActorMsg { - ActorMsg::User(self) + fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { + let response = self.ask(ChainProtocol::GetEntry(entry_hash.to_string())); + unwrap_to!(response => ChainProtocol::GetEntryResult).clone() + } + + fn push_pair(&mut self, pair: &Pair) -> Result { + let response = self.ask(ChainProtocol::PushPair(pair.clone())); + unwrap_to!(response => ChainProtocol::PushPairResult).clone() + } + + fn get_pair(&self, k: &str) -> Result, HolochainError> { + let response = self.ask(ChainProtocol::GetPair(k.to_string())); + unwrap_to!(response => ChainProtocol::GetPairResult).clone() } } @@ -100,12 +145,23 @@ impl Actor for ChainActor { println!("received {}", message); sender.try_tell( match message { - ChainProtocol::Push(entry) => ChainProtocol::PushResult(self.chain.push(&entry)), - ChainProtocol::PushPair(pair) => ChainProtocol::PushResult(self.chain.push_pair(&pair)), - ChainProtocol::PushResult(_) => unreachable!(), + ChainProtocol::TopPair => ChainProtocol::TopPairResult(self.chain.top_pair()), + ChainProtocol::TopPairResult(_) => unreachable!(), + + ChainProtocol::TopPairType(t) => ChainProtocol::TopPairTypeResult(self.chain.top_pair_type(&t)), + ChainProtocol::TopPairTypeResult(_) => unreachable!(), + + ChainProtocol::PushPair(pair) => ChainProtocol::PushPairResult(self.chain.push_pair(&pair)), + ChainProtocol::PushPairResult(_) => unreachable!(), + + ChainProtocol::PushEntry(entry) => ChainProtocol::PushEntryResult(self.chain.push_entry(&entry)), + ChainProtocol::PushEntryResult(_) => unreachable!(), ChainProtocol::GetEntry(key) => ChainProtocol::GetEntryResult(self.chain.get_entry(&key)), ChainProtocol::GetEntryResult(_) => unreachable!(), + + ChainProtocol::GetPair(key) => ChainProtocol::GetPairResult(self.chain.get_pair(&key)), + ChainProtocol::GetPairResult(_) => unreachable!(), }, Some(context.myself()), ).unwrap(); diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 873e49f50d..c15d6d2457 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -6,12 +6,7 @@ use hash_table::{entry::Entry, pair::Pair}; use serde_json; use std::{fmt}; use hash_table::actor::HashTableProtocol; -use riker_patterns::ask::ask; -use hash_table::actor::HASH_TABLE_SYS; -use futures::executor::block_on; -use chain::actor::ChainProtocol; use hash_table::actor::AskHashTable; -use chain::actor::AskChain; #[derive(Clone)] pub struct ChainIterator { @@ -47,13 +42,8 @@ impl Iterator for ChainIterator { // @TODO should this panic? // @see https://github.com/holochain/holochain-rust/issues/146 .and_then(|h| { - let a = ask( - &(*HASH_TABLE_SYS), - &self.table, - HashTableProtocol::Get(h.to_string()), - ); - let response = block_on(a).unwrap(); - let result = unwrap_to!(response => HashTableProtocol::GetResponse); + let response = self.table.ask(HashTableProtocol::GetPair(h.to_string())); + let result = unwrap_to!(response => HashTableProtocol::GetPairResult); result.clone().unwrap() }); ret @@ -65,7 +55,7 @@ pub struct Chain { // @TODO thread safe table references // @see https://github.com/holochain/holochain-rust/issues/135 table: ActorRef, - top: Option, + top_pair: Option, } impl PartialEq for Chain { @@ -74,7 +64,7 @@ impl PartialEq for Chain { self.validate() && other.validate() && // header hashing ensures that if the tops match the whole chain matches - self.top() == other.top() + self.top_pair() == other.top_pair() } } @@ -82,7 +72,7 @@ impl Eq for Chain {} impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Chain {{ top: {:?} }}", self.top) + write!(f, "Chain {{ top: {:?} }}", self.top_pair) } } @@ -99,21 +89,68 @@ impl Chain { pub fn new(table: ActorRef) -> Chain { Chain { - top: None, + top_pair: None, table: table.clone(), } } - /// returns a clone of the top Pair - pub fn top(&self) -> Option { - self.top.clone() - } - /// returns a reference to the underlying HashTable pub fn table(&self) -> ActorRef { self.table.clone() } + /// returns true if all pairs in the chain pass validation + fn validate(&self) -> bool { + self.iter().all(|p| p.validate()) + } + + /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable + fn iter(&self) -> ChainIterator { + ChainIterator::new(self.table(), &self.top_pair()) + } + + /// get the entire chain, top to bottom as a JSON array or canonical pairs + /// @TODO return canonical JSON + /// @see https://github.com/holochain/holochain-rust/issues/75 + pub fn to_json(&self) -> Result { + let as_seq = self.iter().collect::>(); + serde_json::to_string(&as_seq) + } + + /// restore canonical JSON chain + /// @TODO accept canonical JSON + /// @see https://github.com/holochain/holochain-rust/issues/75 + pub fn from_json(table: ActorRef, s: &str) -> Chain { + // @TODO inappropriate unwrap? + // @see https://github.com/holochain/holochain-rust/issues/168 + let mut as_seq: Vec = serde_json::from_str(s).unwrap(); + as_seq.reverse(); + + let mut chain = Chain::new(table); + + for p in as_seq { + chain.push_pair(&p).unwrap(); + // let response = chain.ask(ChainProtocol::PushPair(p)); + // let result = unwrap_to!(response => ChainProtocol::PushResult); + // result.clone().unwrap(); + } + chain + } + +} + +impl SourceChain for Chain { + + /// returns a clone of the top Pair + fn top_pair(&self) -> Option { + self.top_pair.clone() + } + + /// get the top Pair by Entry type + fn top_pair_type(&self, t: &str) -> Option { + self.iter().find(|p| p.header().entry_type() == t) + } + /// private pair-oriented version of push() (which expects Entries) fn push_pair(&mut self, pair: &Pair) -> Result { if !(pair.validate()) { @@ -122,7 +159,7 @@ impl Chain { )); } - let top_pair = self.top().and_then(|p| Some(p.key())); + let top_pair = self.top_pair().and_then(|p| Some(p.key())); let next_pair = pair.header().next(); if top_pair != next_pair { @@ -137,7 +174,7 @@ impl Chain { let result = unwrap_to!(commit_response => HashTableProtocol::CommitResponse); if result.is_ok() { - self.top = Some(pair.clone()); + self.top_pair = Some(pair.clone()); } match result { Ok(_) => Ok(pair.clone()), @@ -149,29 +186,19 @@ impl Chain { /// the Pair for the new Entry is automatically generated and validated against the current top /// Pair to ensure the chain links up correctly across the underlying table data /// the newly created and pushed Pair is returned in the fn Result - pub fn push(&mut self, entry: &Entry) -> Result { + fn push_entry(&mut self, entry: &Entry) -> Result { let pair = Pair::new(self, entry); self.push_pair(&pair) } - /// returns true if all pairs in the chain pass validation - pub fn validate(&self) -> bool { - self.iter().all(|p| p.validate()) - } - - /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable - pub fn iter(&self) -> ChainIterator { - ChainIterator::new(self.table(), &self.top()) - } - /// get a Pair by Pair/Header key from the HashTable if it exists - pub fn get(&self, k: &str) -> Result, HolochainError> { - let response = self.table.ask(HashTableProtocol::Get(k.to_string())); - unwrap_to!(response => HashTableProtocol::GetResponse).clone() + fn get_pair(&self, k: &str) -> Result, HolochainError> { + let response = self.table.ask(HashTableProtocol::GetPair(k.to_string())); + unwrap_to!(response => HashTableProtocol::GetPairResult).clone() } /// get an Entry by Entry key from the HashTable if it exists - pub fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { + fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { // @TODO - this is a slow way to do a lookup // @see https://github.com/holochain/holochain-rust/issues/50 Ok(self @@ -180,55 +207,17 @@ impl Chain { // @see https://github.com/holochain/holochain-rust/issues/145 .find(|p| p.entry().hash() == entry_hash)) } - - /// get the top Pair by Entry type - pub fn top_type(&self, t: &str) -> Result, HolochainError> { - Ok(self.iter().find(|p| p.header().entry_type() == t)) - } - - /// get the entire chain, top to bottom as a JSON array or canonical pairs - /// @TODO return canonical JSON - /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn to_json(&self) -> Result { - let as_seq = self.iter().collect::>(); - serde_json::to_string(&as_seq) - } - - /// restore canonical JSON chain - /// @TODO accept canonical JSON - /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn from_json(table: ActorRef, s: &str) -> Chain { - // @TODO inappropriate unwrap? - // @see https://github.com/holochain/holochain-rust/issues/168 - let mut as_seq: Vec = serde_json::from_str(s).unwrap(); - as_seq.reverse(); - - let mut chain = Chain::new(table); - - for p in as_seq { - chain.push_pair(&p).unwrap(); - // let response = chain.ask(ChainProtocol::PushPair(p)); - // let result = unwrap_to!(response => ChainProtocol::PushResult); - // result.clone().unwrap(); - } - chain - } -} - -trait SourceChain { - - fn push(&mut self, &Entry) -> Result; - } -impl SourceChain for ActorRef { +pub trait SourceChain { + fn top_pair(&self) -> Option; + fn top_pair_type(&self, t: &str) -> Option; - fn push(&mut self, entry: &Entry) -> Result { - let response = &self.ask(ChainProtocol::Push(entry.clone())); - let result = unwrap_to!(response => ChainProtocol::PushResult); - result.clone() - } + fn push_entry(&mut self, entry: &Entry) -> Result; + fn get_entry(&self, entry_hash: &str) -> Result, HolochainError>; + fn push_pair(&mut self, pair: &Pair) -> Result; + fn get_pair(&self, message: &str) -> Result, HolochainError>; } #[cfg(test)] @@ -239,10 +228,11 @@ pub mod tests { entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, memory::{tests::test_table}, pair::Pair, - HashTable, }; use std::rc::Rc; + use chain::actor::ChainActor; use hash_table::actor::tests::test_table_actor; + use chain::SourceChain; /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -265,11 +255,11 @@ pub mod tests { let e1 = test_entry_a(); let e2 = test_entry_b(); - c1.push(&e1).unwrap(); - c2.push(&e1).unwrap(); - c3.push(&e2).unwrap(); + c1.push_entry(&e1).unwrap(); + c2.push_entry(&e1).unwrap(); + c3.push_entry(&e2).unwrap(); - assert_eq!(c1.top(), c2.top()); + assert_eq!(c1.top_pair(), c2.top_pair()); assert_eq!(c1, c2); assert_ne!(c1, c3); @@ -280,29 +270,34 @@ pub mod tests { /// tests for chain.top() fn top() { let mut chain = test_chain(); - assert_eq!(None, chain.top()); + assert_eq!(None, chain.top_pair()); let e1 = test_entry_a(); let e2 = test_entry_b(); - let p1 = chain.push(&e1).unwrap(); - assert_eq!(Some(p1), chain.top()); + let p1 = chain.push_entry(&e1).unwrap(); + assert_eq!(Some(p1), chain.top_pair()); - let p2 = chain.push(&e2).unwrap(); - assert_eq!(Some(p2), chain.top()); + let p2 = chain.push_entry(&e2).unwrap(); + assert_eq!(Some(p2), chain.top_pair()); } #[test] /// tests for chain.table() - fn table() { - let t = test_table(); - let mut c = Chain::new(Rc::new(t)); + fn table_push() { + let table_actor = test_table_actor(); + let chain = Chain::new(table_actor); + let chain_actor = ChainActor::new_ref(chain); + // test that adding something to the chain adds to the table - let p = c.push(&test_entry()).unwrap(); - let tr = Rc::new(c.table()); - assert_eq!(Some(p.clone()), c.table().get(&p.key()).unwrap(),); - assert_eq!(Some(p.clone()), tr.get(&p.key()).unwrap(),); - assert_eq!(c.table().get(&p.key()).unwrap(), tr.get(&p.key()).unwrap(),); + let pair = chain_actor.push_entry(&test_entry()).unwrap(); + + assert_eq!(Some(pair.clone()), table_actor.get_pair(&pair.key()).unwrap(),); + assert_eq!(Some(pair.clone()), chain_actor.get_pair(&pair.key()).unwrap(),); + assert_eq!( + chain_actor.get_pair(&pair.key()).unwrap(), + table_actor.get_pair(&pair.key()).unwrap(), + ); } #[test] @@ -314,9 +309,9 @@ pub mod tests { // chain top, pair entry and headers should all line up after a push let e1 = test_entry_a(); - let p1 = chain.push(&e1).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); - assert_eq!(Some(p1.clone()), chain.top()); + assert_eq!(Some(p1.clone()), chain.top_pair()); assert_eq!(e1, p1.entry()); assert_eq!(e1.hash(), p1.header().entry()); @@ -324,7 +319,7 @@ pub mod tests { let e2 = test_entry_b(); let p2 = chain.push(&e2).unwrap(); - assert_eq!(Some(p2.clone()), chain.top()); + assert_eq!(Some(p2.clone()), chain.top_pair()); assert_eq!(e2, p2.entry()); assert_eq!(e2.hash(), p2.header().entry()); } @@ -339,10 +334,10 @@ pub mod tests { assert!(chain.validate()); - chain.push(&e1).unwrap(); + chain.push_entry(&e1).unwrap(); assert!(chain.validate()); - chain.push(&e2).unwrap(); + chain.push_entry(&e2).unwrap(); assert!(chain.validate()); } @@ -351,8 +346,8 @@ pub mod tests { fn round_trip() { let mut c = test_chain(); let e = test_entry(); - let p = c.push(&e).unwrap(); - assert_eq!(Some(p.clone()), c.get(&p.key()).unwrap(),); + let p = c.push_entry(&e).unwrap(); + assert_eq!(Some(p.clone()), c.get_pair(&p.key()).unwrap(),); } #[test] @@ -363,8 +358,8 @@ pub mod tests { let e1 = test_entry_a(); let e2 = test_entry_b(); - let p1 = chain.push(&e1).unwrap(); - let p2 = chain.push(&e2).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); assert_eq!(vec![p2, p1], chain.iter().collect::>()); } @@ -377,9 +372,9 @@ pub mod tests { let e1 = test_entry_a(); let e2 = test_entry_b(); - let p1 = chain.push(&e1).unwrap(); - let _p2 = chain.push(&e2).unwrap(); - let p3 = chain.push(&e1).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); + let _p2 = chain.push_entry(&e2).unwrap(); + let p3 = chain.push_entry(&e1).unwrap(); assert_eq!( vec![p3, p1], @@ -399,17 +394,17 @@ pub mod tests { let e2 = test_entry_b(); let e3 = test_entry_a(); - let p1 = chain.push(&e1).unwrap(); - let p2 = chain.push(&e2).unwrap(); - let p3 = chain.push(&e3).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); + let p3 = chain.push_entry(&e3).unwrap(); - assert_eq!(None, chain.get("").unwrap()); - assert_eq!(Some(p1.clone()), chain.get(&p1.key()).unwrap()); - assert_eq!(Some(p2.clone()), chain.get(&p2.key()).unwrap()); - assert_eq!(Some(p3.clone()), chain.get(&p3.key()).unwrap()); - assert_eq!(Some(p1.clone()), chain.get(&p1.header().key()).unwrap()); - assert_eq!(Some(p2.clone()), chain.get(&p2.header().key()).unwrap()); - assert_eq!(Some(p3.clone()), chain.get(&p3.header().key()).unwrap()); + assert_eq!(None, chain.get_pair("").unwrap()); + assert_eq!(Some(p1.clone()), chain.get_pair(&p1.key()).unwrap()); + assert_eq!(Some(p2.clone()), chain.get_pair(&p2.key()).unwrap()); + assert_eq!(Some(p3.clone()), chain.get_pair(&p3.key()).unwrap()); + assert_eq!(Some(p1.clone()), chain.get_pair(&p1.header().key()).unwrap()); + assert_eq!(Some(p2.clone()), chain.get_pair(&p2.header().key()).unwrap()); + assert_eq!(Some(p3.clone()), chain.get_pair(&p3.header().key()).unwrap()); } #[test] @@ -421,9 +416,9 @@ pub mod tests { let e2 = test_entry_b(); let e3 = test_entry_a(); - let p1 = chain.push(&e1).unwrap(); - let p2 = chain.push(&e2).unwrap(); - let p3 = chain.push(&e3).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); + let p3 = chain.push_entry(&e3).unwrap(); assert_eq!(None, chain.get_entry("").unwrap()); // @TODO at this point we have p3 with the same entry key as p1... diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index a23aae9754..f9b6c456c5 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -36,8 +36,8 @@ impl AskHashTable for ActorRef { #[derive(Debug, Clone)] pub enum HashTableProtocol { /// HashTable::get() - Get(String), - GetResponse(Result, HolochainError>), + GetPair(String), + GetPairResult(Result, HolochainError>), /// HashTable::commit() Commit(Pair), diff --git a/core/src/hash_table/header.rs b/core/src/hash_table/header.rs index 8687f636d4..970e57ff87 100644 --- a/core/src/hash_table/header.rs +++ b/core/src/hash_table/header.rs @@ -2,6 +2,7 @@ use chain::Chain; use hash; use hash_table::{entry::Entry}; use multihash::Hash; +use chain::SourceChain; // @TODO - serialize properties as defined in HeadersEntrySchema from golang alpha 1 // @see https://github.com/holochain/holochain-proto/blob/4d1b8c8a926e79dfe8deaa7d759f930b66a5314f/entry_headers.go#L7 @@ -44,13 +45,10 @@ impl Header { // @TODO implement timestamps // https://github.com/holochain/holochain-rust/issues/70 time: String::new(), - next: chain.top().and_then(|p| Some(p.header().hash())), + next: chain.top_pair().and_then(|p| Some(p.header().hash())), entry: entry.hash().to_string(), type_next: chain - .top_type(&entry.entry_type()) - // @TODO inappropriate unwrap()? - // @see https://github.com/holochain/holochain-rust/issues/147 - .unwrap() + .top_pair_type(&entry.entry_type()) .and_then(|p| Some(p.header().hash())), // @TODO implement signatures // https://github.com/holochain/holochain-rust/issues/71 From db5beba1ba814222ac10b27f56260a18849b5b40 Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 16 Aug 2018 20:38:11 +1000 Subject: [PATCH 08/49] WIP on chain and hash table actors --- core/src/agent/state.rs | 2 +- core/src/chain/actor.rs | 12 +-- core/src/chain/mod.rs | 57 ++++++------ core/src/hash_table/actor.rs | 158 ++++++++++++++++++++++++++++++---- core/src/hash_table/header.rs | 17 ++-- core/src/hash_table/mod.rs | 1 + core/src/hash_table/pair.rs | 3 +- 7 files changed, 185 insertions(+), 65 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index b7c0ea5784..a976e20f16 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -187,7 +187,7 @@ pub mod tests { #[test] fn test_actor_receive() { - let state = test_agent_state(); + // let state = test_agent_state(); // state.chain.tell("hi".to_string(), None); // let chain = state.chain.clone(); diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index c66e621b1e..2ca3edf206 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -1,6 +1,5 @@ use riker_default::DefaultModel; use riker::actors::*; -use std::{fmt}; use futures::executor::block_on; use riker_patterns::ask::ask; use hash_table::entry::Entry; @@ -8,6 +7,7 @@ use hash_table::pair::Pair; use error::HolochainError; use chain::Chain; use chain::SourceChain; +use snowflake; lazy_static! { pub static ref CHAIN_SYS: ActorSystem = { @@ -43,12 +43,6 @@ impl Into> for ChainProtocol { } } -impl fmt::Display for ChainProtocol { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} - /// anything that can be asked ChainProtocol and block on responses /// needed to support implementing ask on upstream ActorRef from riker /// convenience wrappers around chain struct methods @@ -127,7 +121,7 @@ impl ChainActor { pub fn new_ref(chain: Chain) -> ActorRef { CHAIN_SYS.actor_of( ChainActor::props(chain), - "chain", + &snowflake::ProcessUniqueId::new().to_string(), ).unwrap() } @@ -142,7 +136,7 @@ impl Actor for ChainActor { message: Self::Msg, sender: Option>, ) { - println!("received {}", message); + println!("received {:?}", message); sender.try_tell( match message { ChainProtocol::TopPair => ChainProtocol::TopPairResult(self.chain.top_pair()), diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index c15d6d2457..c24927e060 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -7,6 +7,7 @@ use serde_json; use std::{fmt}; use hash_table::actor::HashTableProtocol; use hash_table::actor::AskHashTable; +use hash_table::HashTable; #[derive(Clone)] pub struct ChainIterator { @@ -170,8 +171,7 @@ impl SourceChain for Chain { ))); } - let commit_response = self.table.ask(HashTableProtocol::Commit(pair.clone())); - let result = unwrap_to!(commit_response => HashTableProtocol::CommitResponse); + let result = self.table.commit(&pair.clone()); if result.is_ok() { self.top_pair = Some(pair.clone()); @@ -226,13 +226,12 @@ pub mod tests { use super::Chain; use hash_table::{ entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, - memory::{tests::test_table}, pair::Pair, }; - use std::rc::Rc; use chain::actor::ChainActor; use hash_table::actor::tests::test_table_actor; use chain::SourceChain; + use hash_table::HashTable; /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -286,17 +285,17 @@ pub mod tests { /// tests for chain.table() fn table_push() { let table_actor = test_table_actor(); - let chain = Chain::new(table_actor); - let chain_actor = ChainActor::new_ref(chain); + let chain = Chain::new(table_actor.clone()); + let mut chain_actor = ChainActor::new_ref(chain); // test that adding something to the chain adds to the table let pair = chain_actor.push_entry(&test_entry()).unwrap(); - assert_eq!(Some(pair.clone()), table_actor.get_pair(&pair.key()).unwrap(),); + assert_eq!(Some(pair.clone()), table_actor.get(&pair.key()).unwrap(),); assert_eq!(Some(pair.clone()), chain_actor.get_pair(&pair.key()).unwrap(),); assert_eq!( + table_actor.get(&pair.key()).unwrap(), chain_actor.get_pair(&pair.key()).unwrap(), - table_actor.get_pair(&pair.key()).unwrap(), ); } @@ -305,7 +304,7 @@ pub mod tests { fn push() { let mut chain = test_chain(); - assert_eq!(None, chain.top()); + assert_eq!(None, chain.top_pair()); // chain top, pair entry and headers should all line up after a push let e1 = test_entry_a(); @@ -317,7 +316,7 @@ pub mod tests { // we should be able to do it again let e2 = test_entry_b(); - let p2 = chain.push(&e2).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); assert_eq!(Some(p2.clone()), chain.top_pair()); assert_eq!(e2, p2.entry()); @@ -441,8 +440,8 @@ pub mod tests { fn top_type() { let mut chain = test_chain(); - assert_eq!(None, chain.top_type(&test_type_a()).unwrap()); - assert_eq!(None, chain.top_type(&test_type_b()).unwrap()); + assert_eq!(None, chain.top_pair_type(&test_type_a())); + assert_eq!(None, chain.top_pair_type(&test_type_b())); let e1 = test_entry_a(); let e2 = test_entry_b(); @@ -450,21 +449,21 @@ pub mod tests { // type a should be p1 // type b should be None - let p1 = chain.push(&e1).unwrap(); - assert_eq!(Some(p1.clone()), chain.top_type(&test_type_a()).unwrap()); - assert_eq!(None, chain.top_type(&test_type_b()).unwrap()); + let p1 = chain.push_entry(&e1).unwrap(); + assert_eq!(Some(p1.clone()), chain.top_pair_type(&test_type_a())); + assert_eq!(None, chain.top_pair_type(&test_type_b())); // type a should still be p1 // type b should be p2 - let p2 = chain.push(&e2).unwrap(); - assert_eq!(Some(p1.clone()), chain.top_type(&test_type_a()).unwrap()); - assert_eq!(Some(p2.clone()), chain.top_type(&test_type_b()).unwrap()); + let p2 = chain.push_entry(&e2).unwrap(); + assert_eq!(Some(p1.clone()), chain.top_pair_type(&test_type_a())); + assert_eq!(Some(p2.clone()), chain.top_pair_type(&test_type_b())); // type a should be p3 // type b should still be p2 - let p3 = chain.push(&e3).unwrap(); - assert_eq!(Some(p3.clone()), chain.top_type(&test_type_a()).unwrap()); - assert_eq!(Some(p2.clone()), chain.top_type(&test_type_b()).unwrap()); + let p3 = chain.push_entry(&e3).unwrap(); + assert_eq!(Some(p3.clone()), chain.top_pair_type(&test_type_a())); + assert_eq!(Some(p2.clone()), chain.top_pair_type(&test_type_b())); } #[test] @@ -476,9 +475,9 @@ pub mod tests { let e2 = test_entry_b(); let e3 = test_entry_a(); - let p1 = chain.push(&e1).unwrap(); - let p2 = chain.push(&e2).unwrap(); - let p3 = chain.push(&e3).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); + let p3 = chain.push_entry(&e3).unwrap(); // into_iter() returns clones of pairs let mut i = 0; @@ -498,15 +497,15 @@ pub mod tests { let e2 = test_entry_b(); let e3 = test_entry_a(); - chain.push(&e1).unwrap(); - chain.push(&e2).unwrap(); - chain.push(&e3).unwrap(); + chain.push_entry(&e1).unwrap(); + chain.push_entry(&e2).unwrap(); + chain.push_entry(&e3).unwrap(); let expected_json = "[{\"header\":{\"entry_type\":\"testEntryType\",\"time\":\"\",\"next\":\"QmPT5HXvyv54Dg36YSK1A2rYvoPCNWoqpLzzZnHnQBcU6x\",\"entry\":\"QmbXSE38SN3SuJDmHKSSw5qWWegvU7oTxrLDRavWjyxMrT\",\"type_next\":\"QmawqBCVVap9KdaakqEHF4JzUjjLhmR7DpM5jgJko8j1rA\",\"signature\":\"\"},\"entry\":{\"content\":\"test entry content\",\"entry_type\":\"testEntryType\"}},{\"header\":{\"entry_type\":\"testEntryTypeB\",\"time\":\"\",\"next\":\"QmawqBCVVap9KdaakqEHF4JzUjjLhmR7DpM5jgJko8j1rA\",\"entry\":\"QmPz5jKXsxq7gPVAbPwx5gD2TqHfqB8n25feX5YH18JXrT\",\"type_next\":null,\"signature\":\"\"},\"entry\":{\"content\":\"other test entry content\",\"entry_type\":\"testEntryTypeB\"}},{\"header\":{\"entry_type\":\"testEntryType\",\"time\":\"\",\"next\":null,\"entry\":\"QmbXSE38SN3SuJDmHKSSw5qWWegvU7oTxrLDRavWjyxMrT\",\"type_next\":null,\"signature\":\"\"},\"entry\":{\"content\":\"test entry content\",\"entry_type\":\"testEntryType\"}}]"; assert_eq!(expected_json, chain.to_json().unwrap()); - let table = test_table(); - assert_eq!(chain, Chain::from_json(Rc::new(table), expected_json)); + let table_actor = test_table_actor(); + assert_eq!(chain, Chain::from_json(table_actor, expected_json)); } } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index f9b6c456c5..086ab41211 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -5,6 +5,9 @@ use hash_table::pair::Pair; use error::HolochainError; use futures::executor::block_on; use riker_patterns::ask::ask; +use hash_table::pair_meta::PairMeta; +use agent::keys::Keys; +use snowflake; lazy_static! { pub static ref HASH_TABLE_SYS: ActorSystem = { @@ -13,6 +16,59 @@ lazy_static! { }; } +#[derive(Debug, Clone)] +pub enum HashTableProtocol { + /// HashTable::setup() + Setup, + SetupResult(Result<(), HolochainError>), + + /// HashTable::teardown() + Teardown, + TeardownResult(Result<(), HolochainError>), + + /// HashTable::modify() + Modify{ + keys: Keys, + old_pair: Pair, + new_pair: Pair, + }, + ModifyResult(Result<(), HolochainError>), + + /// HashTable::retract() + Retract{ + keys: Keys, + pair: Pair, + }, + RetractResult(Result<(), HolochainError>), + + /// HashTable::assert_meta() + AssertMeta(PairMeta), + AssertMetaResult(Result<(), HolochainError>), + + /// HashTable::get_meta() + GetMeta(String), + GetMetaResult(Result, HolochainError>), + + /// HashTable::get_pair_meta() + GetPairMeta(Pair), + GetPairMetaResult(Result, HolochainError>), + + /// HashTable::get() + GetPair(String), + GetPairResult(Result, HolochainError>), + + /// HashTable::commit() + Commit(Pair), + CommitResult(Result<(), HolochainError>), + +} + +impl Into> for HashTableProtocol { + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } +} + /// anything that can be asked HashTableProtocol and block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskHashTable { @@ -33,22 +89,57 @@ impl AskHashTable for ActorRef { } } -#[derive(Debug, Clone)] -pub enum HashTableProtocol { - /// HashTable::get() - GetPair(String), - GetPairResult(Result, HolochainError>), +impl HashTable for ActorRef { + fn setup(&mut self) -> Result<(), HolochainError> { + let response = self.ask(HashTableProtocol::Setup); + unwrap_to!(response => HashTableProtocol::SetupResult).clone() + } - /// HashTable::commit() - Commit(Pair), - CommitResponse(Result<(), HolochainError>), + fn teardown(&mut self) -> Result<(), HolochainError> { + let response = self.ask(HashTableProtocol::Teardown); + unwrap_to!(response => HashTableProtocol::TeardownResult).clone() + } -} + fn commit(&mut self, pair: &Pair) -> Result<(), HolochainError> { + let response = self.ask(HashTableProtocol::Commit(pair.clone())); + unwrap_to!(response => HashTableProtocol::CommitResult).clone() + } -impl Into> for HashTableProtocol { + fn get(&self, key: &str) -> Result, HolochainError> { + let response = self.ask(HashTableProtocol::GetPair(key.to_string())); + unwrap_to!(response => HashTableProtocol::GetPairResult).clone() + } - fn into(self) -> ActorMsg { - ActorMsg::User(self) + fn modify(&mut self, keys: &Keys, old_pair: &Pair, new_pair: &Pair,) -> Result<(), HolochainError> { + let response = self.ask(HashTableProtocol::Modify{ + keys: keys.clone(), + old_pair: old_pair.clone(), + new_pair: new_pair.clone(), + }); + unwrap_to!(response => HashTableProtocol::ModifyResult).clone() + } + + fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { + let response = self.ask(HashTableProtocol::Retract{ + keys: keys.clone(), + pair: pair.clone(), + }); + unwrap_to!(response => HashTableProtocol::RetractResult).clone() + } + + fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError> { + let response = self.ask(HashTableProtocol::AssertMeta(meta.clone())); + unwrap_to!(response => HashTableProtocol::AssertMetaResult).clone() + } + + fn get_meta(&mut self, key: &str) -> Result, HolochainError> { + let response = self.ask(HashTableProtocol::GetMeta(key.to_string())); + unwrap_to!(response => HashTableProtocol::GetMetaResult).clone() + } + + fn get_pair_meta(&mut self, pair: &Pair) -> Result, HolochainError> { + let response = self.ask(HashTableProtocol::GetPairMeta(pair.clone())); + unwrap_to!(response => HashTableProtocol::GetPairMetaResult).clone() } } @@ -77,7 +168,7 @@ impl HashTableActor { pub fn new_ref(table: HT) -> ActorRef { HASH_TABLE_SYS.actor_of( HashTableActor::props(table), - "table", + &snowflake::ProcessUniqueId::new().to_string(), ).unwrap() } @@ -88,10 +179,43 @@ impl Actor for HashTableActor { fn receive( &mut self, - _context: &Context, - _message: Self::Msg, - _sender: Option>, + context: &Context, + message: Self::Msg, + sender: Option>, ) { + println!("received {:?}", message); + + sender.try_tell( + match message { + HashTableProtocol::Setup => HashTableProtocol::SetupResult(self.table.setup()), + HashTableProtocol::SetupResult(_) => unreachable!(), + + HashTableProtocol::Teardown => HashTableProtocol::TeardownResult(self.table.teardown()), + HashTableProtocol::TeardownResult(_) => unreachable!(), + + HashTableProtocol::Commit(pair) => HashTableProtocol::CommitResult(self.table.commit(&pair)), + HashTableProtocol::CommitResult(_) => unreachable!(), + + HashTableProtocol::GetPair(hash) => HashTableProtocol::GetPairResult(self.table.get(&hash)), + HashTableProtocol::GetPairResult(_) => unreachable!(), + + HashTableProtocol::Modify{keys, old_pair, new_pair} => HashTableProtocol::ModifyResult(self.table.modify(&keys, &old_pair, &new_pair)), + HashTableProtocol::ModifyResult(_) => unreachable!(), + + HashTableProtocol::Retract{keys, pair} => HashTableProtocol::RetractResult(self.table.retract(&keys, &pair)), + HashTableProtocol::RetractResult(_) => unreachable!(), + + HashTableProtocol::AssertMeta(pair_meta) => HashTableProtocol::AssertMetaResult(self.table.assert_meta(&pair_meta)), + HashTableProtocol::AssertMetaResult(_) => unreachable!(), + + HashTableProtocol::GetMeta(key) => HashTableProtocol::GetMetaResult(self.table.get_meta(&key)), + HashTableProtocol::GetMetaResult(_) => unreachable!(), + + HashTableProtocol::GetPairMeta(pair) => HashTableProtocol::GetPairMetaResult(self.table.get_pair_meta(&pair)), + HashTableProtocol::GetPairMetaResult(_) => unreachable!(), + }, + Some(context.myself()), + ).unwrap(); } @@ -106,7 +230,7 @@ pub mod tests { use hash_table::actor::HashTableProtocol; pub fn test_table_actor() -> ActorRef { - HashTableActor::new_ref(test_table()); + HashTableActor::new_ref(test_table()) } #[test] diff --git a/core/src/hash_table/header.rs b/core/src/hash_table/header.rs index 970e57ff87..55478ef080 100644 --- a/core/src/hash_table/header.rs +++ b/core/src/hash_table/header.rs @@ -119,6 +119,7 @@ impl Header { mod tests { use chain::tests::test_chain; use hash_table::{entry::Entry, header::Header, pair::tests::test_pair}; + use chain::SourceChain; /// returns a dummy header for use in tests pub fn test_header() -> Header { @@ -155,7 +156,7 @@ mod tests { // different state is different let mut chain2 = test_chain(); let e = Entry::new(t1, c1); - chain2.push(&e).unwrap(); + chain2.push_entry(&e).unwrap(); assert_ne!(Header::new(&chain1, &e), Header::new(&chain2, &e)); } @@ -204,14 +205,14 @@ mod tests { // first header is genesis so next should be None let e1 = Entry::new(t, ""); - let p1 = chain.push(&e1).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); let h1 = p1.header(); assert_eq!(h1.next(), None); // second header next should be first header hash let e2 = Entry::new(t, "foo"); - let p2 = chain.push(&e2).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); let h2 = p2.header(); assert_eq!(h2.next(), Some(h1.hash())); @@ -239,21 +240,21 @@ mod tests { // first header is genesis so next should be None let e1 = Entry::new(t1, ""); - let p1 = chain.push(&e1).unwrap(); + let p1 = chain.push_entry(&e1).unwrap(); let h1 = p1.header(); assert_eq!(h1.type_next(), None); // second header is a different type so next should be None let e2 = Entry::new(t2, ""); - let p2 = chain.push(&e2).unwrap(); + let p2 = chain.push_entry(&e2).unwrap(); let h2 = p2.header(); assert_eq!(h2.type_next(), None); // third header is same type as first header so next should be first header hash let e3 = Entry::new(t1, ""); - let p3 = chain.push(&e3).unwrap(); + let p3 = chain.push_entry(&e3).unwrap(); let h3 = p3.header(); assert_eq!(h3.type_next(), Some(h1.hash())); @@ -334,9 +335,9 @@ mod tests { let e = Entry::new(t, c); let h = Header::new(&chain, &e); - let p1 = chain.push(&e).unwrap(); + let p1 = chain.push_entry(&e).unwrap(); // p2 will have a different hash to p1 with the same entry as the chain state is different - let p2 = chain.push(&e).unwrap(); + let p2 = chain.push_entry(&e).unwrap(); assert_eq!(h.hash(), p1.header().hash()); assert_ne!(h.hash(), p2.header().hash()); diff --git a/core/src/hash_table/mod.rs b/core/src/hash_table/mod.rs index ed77d72751..d35ca0b6c5 100644 --- a/core/src/hash_table/mod.rs +++ b/core/src/hash_table/mod.rs @@ -12,6 +12,7 @@ use hash_table::{pair::Pair, pair_meta::PairMeta}; pub trait HashTable: Send + Sync + Clone + 'static { // internal state management + // @TODO does this make sense at the trait level? fn setup(&mut self) -> Result<(), HolochainError>; fn teardown(&mut self) -> Result<(), HolochainError>; diff --git a/core/src/hash_table/pair.rs b/core/src/hash_table/pair.rs index 669b1b792b..8244422fec 100644 --- a/core/src/hash_table/pair.rs +++ b/core/src/hash_table/pair.rs @@ -90,6 +90,7 @@ pub mod tests { }, header::Header, }; + use chain::SourceChain; /// dummy pair pub fn test_pair() -> Pair { @@ -141,7 +142,7 @@ pub mod tests { let mut chain = test_chain(); let t = "foo"; let e = Entry::new(t, ""); - let p = chain.push(&e).unwrap(); + let p = chain.push_entry(&e).unwrap(); assert_eq!(e, p.entry()); } From e5e694dc039cab11aa90585cf9f678498ced8273 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sat, 18 Aug 2018 14:47:04 +1000 Subject: [PATCH 09/49] WIP on nested executors for actors --- core/Cargo.toml | 1 + core/src/chain/actor.rs | 65 ++++++++++++++++++++---- core/src/hash_table/actor.rs | 67 +++++++++++++++++++++---- core/src/lib.rs | 1 + core/src/nucleus/ribosome/api/commit.rs | 6 +-- core/src/nucleus/ribosome/api/get.rs | 13 +++-- 6 files changed, 127 insertions(+), 26 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 015d3fb77a..4e1840dd7a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -25,6 +25,7 @@ lazy_static = "1.1.0" unwrap_to = "0.1.0" num-traits = "0.2" num-derive = "0.2" +config = "0.8" [dev-dependencies] wabt = "0.4" diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 2ca3edf206..3dd0bc6cb2 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -1,4 +1,4 @@ -use riker_default::DefaultModel; +// use riker_default::DefaultModel; use riker::actors::*; use futures::executor::block_on; use riker_patterns::ask::ask; @@ -8,10 +8,57 @@ use error::HolochainError; use chain::Chain; use chain::SourceChain; use snowflake; +use riker_default::SimpleLogger; +use riker::kernel::Dispatcher; +use config::Config; +use futures::{Future, Never}; +use riker::futures_util::spawn; +use riker_default::DeadLettersActor; +use riker_default::BasicTimer; +use riker_default::MapVec; +use riker::system::NoIo; +use futures::executor::{ThreadPool, ThreadPoolBuilder}; + +struct ChainModel; + +// @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs +pub struct ChainDispatcher { + inner: ThreadPool, +} + +impl Dispatcher for ChainDispatcher { + fn new(_config: &Config, _: bool) -> ChainDispatcher { + ChainDispatcher { + inner: ThreadPoolBuilder::new() + .pool_size(4) + .name_prefix("pool-thread-chain-#") + .create() + .unwrap() + } + } + + fn execute(&mut self, f: F) + where F: Future + Send + 'static + { + self.inner.run(spawn(f)).unwrap(); + } +} + +impl Model for ChainModel { + type Msg = ChainProtocol; + type Dis = ChainDispatcher; + type Ded = DeadLettersActor; + type Tmr = BasicTimer; + type Evs = MapVec; + type Tcp = NoIo; + type Udp = NoIo; + type Log = SimpleLogger; +} lazy_static! { pub static ref CHAIN_SYS: ActorSystem = { - let chain_model: DefaultModel = DefaultModel::new(); + // let chain_model: DefaultModel = DefaultModel::new(); + let chain_model = ChainModel{}; ActorSystem::new(&chain_model).unwrap() }; } @@ -52,13 +99,13 @@ pub trait AskChain { impl AskChain for ActorRef { fn ask(&self, message: ChainProtocol) -> ChainProtocol { - block_on( - ask( - &(*CHAIN_SYS), - self, - message, - ) - ).unwrap() + let a = ask( + &(*CHAIN_SYS), + self, + message, + ); + println!("asking chain"); + block_on(a).unwrap() } } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 086ab41211..1baf5c9700 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,6 +1,6 @@ use riker::actors::*; use hash_table::HashTable; -use riker_default::DefaultModel; +// use riker_default::DefaultModel; use hash_table::pair::Pair; use error::HolochainError; use futures::executor::block_on; @@ -8,10 +8,57 @@ use riker_patterns::ask::ask; use hash_table::pair_meta::PairMeta; use agent::keys::Keys; use snowflake; +use riker::kernel::Dispatcher; +use config::Config; +use futures::executor::{ThreadPool, ThreadPoolBuilder}; +use futures::{Future, Never}; +use riker::futures_util::spawn; +use riker_default::DeadLettersActor; +use riker_default::BasicTimer; +use riker_default::MapVec; +use riker_default::SimpleLogger; +use riker::system::NoIo; + +struct HashTableModel; + +// @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs +pub struct HashTableDispatcher { + inner: ThreadPool, +} + +impl Dispatcher for HashTableDispatcher { + fn new(_config: &Config, _: bool) -> HashTableDispatcher { + HashTableDispatcher { + inner: ThreadPoolBuilder::new() + .pool_size(4) + .name_prefix("pool-thread-hash-table-#") + .create() + .unwrap() + } + } + + fn execute(&mut self, f: F) + where F: Future + Send + 'static + { + self.inner.run(spawn(f)).unwrap(); + } +} + +impl Model for HashTableModel { + type Msg = HashTableProtocol; + type Dis = HashTableDispatcher; + type Ded = DeadLettersActor; + type Tmr = BasicTimer; + type Evs = MapVec; + type Tcp = NoIo; + type Udp = NoIo; + type Log = SimpleLogger; +} lazy_static! { pub static ref HASH_TABLE_SYS: ActorSystem = { - let hash_table_model: DefaultModel = DefaultModel::new(); + // let hash_table_model: DefaultModel = DefaultModel::new(); + let hash_table_model = HashTableModel{}; ActorSystem::new(&hash_table_model).unwrap() }; } @@ -72,20 +119,18 @@ impl Into> for HashTableProtocol { /// anything that can be asked HashTableProtocol and block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskHashTable { - fn ask(&self, message: HashTableProtocol) -> HashTableProtocol; - } impl AskHashTable for ActorRef { fn ask(&self, message: HashTableProtocol) -> HashTableProtocol { - block_on( - ask( - &(*HASH_TABLE_SYS), - self, - message, - ) - ).unwrap() + let a = ask( + &(*HASH_TABLE_SYS), + self, + message, + ); + println!("asking table"); + block_on(a).unwrap() } } diff --git a/core/src/lib.rs b/core/src/lib.rs index 7431958b44..f57d2222db 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -26,6 +26,7 @@ extern crate num_traits; extern crate holochain_agent; extern crate holochain_dna; extern crate holochain_wasm_utils; +extern crate config; pub mod action; pub mod agent; diff --git a/core/src/nucleus/ribosome/api/commit.rs b/core/src/nucleus/ribosome/api/commit.rs index f571474fd5..1de7dff2fa 100644 --- a/core/src/nucleus/ribosome/api/commit.rs +++ b/core/src/nucleus/ribosome/api/commit.rs @@ -94,7 +94,7 @@ pub fn invoke_commit( } #[cfg(test)] -mod tests { +pub mod tests { extern crate test_utils; extern crate wabt; @@ -104,7 +104,7 @@ mod tests { use serde_json; /// dummy commit args from standard test entry - pub fn test_args_bytes() -> Vec { + pub fn test_commit_args_bytes() -> Vec { let e = test_entry(); let args = CommitArgs { entry_type_name: e.entry_type().into(), @@ -116,7 +116,7 @@ mod tests { #[test] /// test that we can round trip bytes through a commit action and get the result from WASM fn test_commit_round_trip() { - let (runtime, _) = test_zome_api_function_runtime("commit", test_args_bytes()); + let (runtime, _) = test_zome_api_function_runtime("commit", test_commit_args_bytes()); assert_eq!( runtime.result, diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index a106b972dd..8fa155449d 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -74,10 +74,11 @@ mod tests { use super::GetArgs; use hash_table::entry::tests::{test_entry, test_entry_hash}; use nucleus::ribosome::api::tests::test_zome_api_function_runtime; + use nucleus::ribosome::api::commit::tests::test_commit_args_bytes; use serde_json; /// dummy get args from standard test entry - pub fn test_args_bytes() -> Vec { + pub fn test_get_args_bytes() -> Vec { let args = GetArgs { key: test_entry().hash().into(), }; @@ -87,14 +88,20 @@ mod tests { #[test] /// test that we can round trip bytes through a get action and it comes back from wasm fn test_get_round_trip() { - let (runtime, _) = test_zome_api_function_runtime("get", test_args_bytes()); + let (commit_runtime, _) = test_zome_api_function_runtime("commit", test_commit_args_bytes()); + assert_eq!( + commit_runtime.result, + format!(r#"{{"hash":"{}"}}"#, test_entry().key()) + "\u{0}", + ); + + let (get_runtime, _) = test_zome_api_function_runtime("get", test_get_args_bytes()); let mut expected = "".to_owned(); expected.push_str("{\"header\":{\"entry_type\":\"testEntryType\",\"time\":\"\",\"next\":null,\"entry\":\""); expected.push_str(&test_entry_hash()); expected.push_str("\",\"type_next\":null,\"signature\":\"\"},\"entry\":{\"content\":\"test entry content\",\"entry_type\":\"testEntryType\"}}\u{0}"); - assert_eq!(runtime.result, expected,); + assert_eq!(get_runtime.result, expected,); } } From 2f7b6508561c226ac3b98452425b7ab37ffcf9eb Mon Sep 17 00:00:00 2001 From: David Meister Date: Sat, 18 Aug 2018 21:47:31 +1000 Subject: [PATCH 10/49] one sys for riker spike --- core/src/actor.rs | 86 +++++++++++ core/src/agent/state.rs | 10 +- core/src/chain/actor.rs | 231 +++++++++++++++--------------- core/src/chain/mod.rs | 22 +-- core/src/hash_table/actor.rs | 270 +++++++++++++++-------------------- core/src/lib.rs | 1 + 6 files changed, 334 insertions(+), 286 deletions(-) create mode 100644 core/src/actor.rs diff --git a/core/src/actor.rs b/core/src/actor.rs new file mode 100644 index 0000000000..4628831dd6 --- /dev/null +++ b/core/src/actor.rs @@ -0,0 +1,86 @@ +use hash_table::pair::Pair; +use riker_default::DefaultModel; +use riker::actors::*; +use hash_table::entry::Entry; +use error::HolochainError; +use agent::keys::Keys; +use hash_table::pair_meta::PairMeta; + +#[derive(Clone, Debug)] +pub enum Protocol { + + ChainTopPair, + ChainTopPairResult(Option), + + ChainTopPairType(String), + ChainTopPairTypeResult(Option), + + ChainPushEntry(Entry), + ChainPushEntryResult(Result), + + ChainPushPair(Pair), + ChainPushPairResult(Result), + + ChainGetEntry(String), + ChainGetEntryResult(Result, HolochainError>), + + ChainGetPair(String), + ChainGetPairResult(Result, HolochainError>), + + /// HashTable::setup() + HashTableSetup, + HashTableSetupResult(Result<(), HolochainError>), + + /// HashTable::teardown() + HashTableTeardown, + HashTableTeardownResult(Result<(), HolochainError>), + + /// HashTable::modify() + HashTableModify{ + keys: Keys, + old_pair: Pair, + new_pair: Pair, + }, + HashTableModifyResult(Result<(), HolochainError>), + + /// HashTable::retract() + HashTableRetract{ + keys: Keys, + pair: Pair, + }, + HashTableRetractResult(Result<(), HolochainError>), + + /// HashTable::assert_meta() + HashTableAssertMeta(PairMeta), + HashTableAssertMetaResult(Result<(), HolochainError>), + + /// HashTable::get_meta() + HashTableGetMeta(String), + HashTableGetMetaResult(Result, HolochainError>), + + /// HashTable::get_pair_meta() + HashTableGetPairMeta(Pair), + HashTableGetPairMetaResult(Result, HolochainError>), + + /// HashTable::get() + HashTableGetPair(String), + HashTableGetPairResult(Result, HolochainError>), + + /// HashTable::commit() + HashTableCommit(Pair), + HashTableCommitResult(Result<(), HolochainError>), +} + +lazy_static! { + pub static ref SYS: ActorSystem = { + let model: DefaultModel = DefaultModel::new(); + // let hash_table_model = HashTableModel{}; + ActorSystem::new(&model).unwrap() + }; +} + +impl Into> for Protocol { + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } +} diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index a976e20f16..14b15ca21a 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -9,7 +9,7 @@ use std::{ collections::HashMap, sync::{mpsc::Sender, Arc}, }; -use chain::actor::ChainProtocol; +use actor::Protocol; use chain::actor::AskChain; use chain::SourceChain; @@ -25,12 +25,12 @@ pub struct AgentState { // @TODO this will blow up memory, implement as some kind of dropping/FIFO with a limit? // @see https://github.com/holochain/holochain-rust/issues/166 actions: HashMap, - chain: ActorRef, + chain: ActorRef, } impl AgentState { /// builds a new, empty AgentState - pub fn new(chain: ActorRef) -> AgentState { + pub fn new(chain: ActorRef) -> AgentState { AgentState { keys: None, top_pair: None, @@ -126,9 +126,9 @@ fn reduce_get( let key = unwrap_to!(action => Action::Get); let response = state.chain.ask( - ChainProtocol::GetEntry(key.clone()), + Protocol::ChainGetEntry(key.clone()), ); - let result = unwrap_to!(response => ChainProtocol::GetEntryResult); + let result = unwrap_to!(response => Protocol::ChainGetEntryResult); // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 3dd0bc6cb2..a7cbc3439a 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -8,99 +8,93 @@ use error::HolochainError; use chain::Chain; use chain::SourceChain; use snowflake; -use riker_default::SimpleLogger; use riker::kernel::Dispatcher; -use config::Config; -use futures::{Future, Never}; -use riker::futures_util::spawn; -use riker_default::DeadLettersActor; -use riker_default::BasicTimer; -use riker_default::MapVec; -use riker::system::NoIo; -use futures::executor::{ThreadPool, ThreadPoolBuilder}; - -struct ChainModel; - -// @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs -pub struct ChainDispatcher { - inner: ThreadPool, -} - -impl Dispatcher for ChainDispatcher { - fn new(_config: &Config, _: bool) -> ChainDispatcher { - ChainDispatcher { - inner: ThreadPoolBuilder::new() - .pool_size(4) - .name_prefix("pool-thread-chain-#") - .create() - .unwrap() - } - } - - fn execute(&mut self, f: F) - where F: Future + Send + 'static - { - self.inner.run(spawn(f)).unwrap(); - } -} - -impl Model for ChainModel { - type Msg = ChainProtocol; - type Dis = ChainDispatcher; - type Ded = DeadLettersActor; - type Tmr = BasicTimer; - type Evs = MapVec; - type Tcp = NoIo; - type Udp = NoIo; - type Log = SimpleLogger; -} - -lazy_static! { - pub static ref CHAIN_SYS: ActorSystem = { - // let chain_model: DefaultModel = DefaultModel::new(); - let chain_model = ChainModel{}; - ActorSystem::new(&chain_model).unwrap() - }; -} - -#[derive(Debug, Clone)] -pub enum ChainProtocol { - TopPair, - TopPairResult(Option), - - TopPairType(String), - TopPairTypeResult(Option), - - PushEntry(Entry), - PushEntryResult(Result), - - PushPair(Pair), - PushPairResult(Result), - - GetEntry(String), - GetEntryResult(Result, HolochainError>), - - GetPair(String), - GetPairResult(Result, HolochainError>), -} - -impl Into> for ChainProtocol { - fn into(self) -> ActorMsg { - ActorMsg::User(self) - } -} - -/// anything that can be asked ChainProtocol and block on responses +// use hash_table::actor::HASH_TABLE_SYS; +use actor::SYS; +use actor::Protocol; + +// struct ChainModel; +// +// // @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs +// pub struct ChainDispatcher { +// inner: ThreadPool, +// } +// +// impl Dispatcher for ChainDispatcher { +// fn new(_config: &Config, _: bool) -> ChainDispatcher { +// ChainDispatcher { +// inner: ThreadPoolBuilder::new() +// .pool_size(4) +// .name_prefix("pool-thread-chain-#") +// .create() +// .unwrap() +// } +// } +// +// fn execute(&mut self, f: F) +// where F: Future + Send + 'static +// { +// self.inner.run(spawn(f)).unwrap(); +// } +// } +// +// impl Model for ChainModel { +// type Msg = Protocol; +// type Dis = ChainDispatcher; +// type Ded = DeadLettersActor; +// type Tmr = BasicTimer; +// type Evs = MapVec; +// type Tcp = NoIo; +// type Udp = NoIo; +// type Log = SimpleLogger; +// } + +// lazy_static! { +// pub static ref CHAIN_SYS: ActorSystem = { +// // let chain_model: DefaultModel = DefaultModel::new(); +// let chain_model = ChainModel{}; +// ActorSystem::new(&chain_model).unwrap() +// }; +// } + +// #[derive(Debug, Clone)] +// pub enum Protocol { +// TopPair, +// TopPairResult(Option), +// +// TopPairType(String), +// TopPairTypeResult(Option), +// +// PushEntry(Entry), +// PushEntryResult(Result), +// +// PushPair(Pair), +// PushPairResult(Result), +// +// GetEntry(String), +// GetEntryResult(Result, HolochainError>), +// +// GetPair(String), +// GetPairResult(Result, HolochainError>), +// } + +// impl Into> for Protocol { +// fn into(self) -> ActorMsg { +// ActorMsg::User(self) +// } +// } + +/// anything that can be asked Protocol and block on responses /// needed to support implementing ask on upstream ActorRef from riker /// convenience wrappers around chain struct methods pub trait AskChain { - fn ask(&self, message: ChainProtocol) -> ChainProtocol; + fn ask(&self, message: Protocol) -> Protocol; } -impl AskChain for ActorRef { - fn ask(&self, message: ChainProtocol) -> ChainProtocol { +impl AskChain for ActorRef { + fn ask(&self, message: Protocol) -> Protocol { let a = ask( - &(*CHAIN_SYS), + &(*SYS), self, message, ); @@ -109,36 +103,36 @@ impl AskChain for ActorRef { } } -impl SourceChain for ActorRef { +impl SourceChain for ActorRef { fn top_pair(&self) -> Option { - let response = self.ask(ChainProtocol::TopPair); - unwrap_to!(response => ChainProtocol::TopPairResult).clone() + let response = self.ask(Protocol::ChainTopPair); + unwrap_to!(response => Protocol::ChainTopPairResult).clone() } fn top_pair_type(&self, t: &str) -> Option { - let response = self.ask(ChainProtocol::TopPairType(t.to_string())); - unwrap_to!(response => ChainProtocol::TopPairTypeResult).clone() + let response = self.ask(Protocol::ChainTopPairType(t.to_string())); + unwrap_to!(response => Protocol::ChainTopPairTypeResult).clone() } fn push_entry(&mut self, entry: &Entry) -> Result { - let response = self.ask(ChainProtocol::PushEntry(entry.clone())); - unwrap_to!(response => ChainProtocol::PushEntryResult).clone() + let response = self.ask(Protocol::ChainPushEntry(entry.clone())); + unwrap_to!(response => Protocol::ChainPushEntryResult).clone() } fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { - let response = self.ask(ChainProtocol::GetEntry(entry_hash.to_string())); - unwrap_to!(response => ChainProtocol::GetEntryResult).clone() + let response = self.ask(Protocol::ChainGetEntry(entry_hash.to_string())); + unwrap_to!(response => Protocol::ChainGetEntryResult).clone() } fn push_pair(&mut self, pair: &Pair) -> Result { - let response = self.ask(ChainProtocol::PushPair(pair.clone())); - unwrap_to!(response => ChainProtocol::PushPairResult).clone() + let response = self.ask(Protocol::ChainPushPair(pair.clone())); + unwrap_to!(response => Protocol::ChainPushPairResult).clone() } fn get_pair(&self, k: &str) -> Result, HolochainError> { - let response = self.ask(ChainProtocol::GetPair(k.to_string())); - unwrap_to!(response => ChainProtocol::GetPairResult).clone() + let response = self.ask(Protocol::ChainGetPair(k.to_string())); + unwrap_to!(response => Protocol::ChainGetPairResult).clone() } } @@ -157,16 +151,16 @@ impl ChainActor { } } - pub fn actor(chain: Chain) -> BoxActor { + pub fn actor(chain: Chain) -> BoxActor { Box::new(ChainActor::new(chain)) } - pub fn props(chain: Chain) -> BoxActorProd { + pub fn props(chain: Chain) -> BoxActorProd { Props::new_args(Box::new(ChainActor::actor), chain) } - pub fn new_ref(chain: Chain) -> ActorRef { - CHAIN_SYS.actor_of( + pub fn new_ref(chain: Chain) -> ActorRef { + SYS.actor_of( ChainActor::props(chain), &snowflake::ProcessUniqueId::new().to_string(), ).unwrap() @@ -175,7 +169,7 @@ impl ChainActor { } impl Actor for ChainActor { - type Msg = ChainProtocol; + type Msg = Protocol; fn receive( &mut self, @@ -186,23 +180,24 @@ impl Actor for ChainActor { println!("received {:?}", message); sender.try_tell( match message { - ChainProtocol::TopPair => ChainProtocol::TopPairResult(self.chain.top_pair()), - ChainProtocol::TopPairResult(_) => unreachable!(), + Protocol::ChainTopPair => Protocol::ChainTopPairResult(self.chain.top_pair()), + Protocol::ChainTopPairResult(_) => unreachable!(), - ChainProtocol::TopPairType(t) => ChainProtocol::TopPairTypeResult(self.chain.top_pair_type(&t)), - ChainProtocol::TopPairTypeResult(_) => unreachable!(), + Protocol::ChainTopPairType(t) => Protocol::ChainTopPairTypeResult(self.chain.top_pair_type(&t)), + Protocol::ChainTopPairTypeResult(_) => unreachable!(), - ChainProtocol::PushPair(pair) => ChainProtocol::PushPairResult(self.chain.push_pair(&pair)), - ChainProtocol::PushPairResult(_) => unreachable!(), + Protocol::ChainPushPair(pair) => Protocol::ChainPushPairResult(self.chain.push_pair(&pair)), + Protocol::ChainPushPairResult(_) => unreachable!(), - ChainProtocol::PushEntry(entry) => ChainProtocol::PushEntryResult(self.chain.push_entry(&entry)), - ChainProtocol::PushEntryResult(_) => unreachable!(), + Protocol::ChainPushEntry(entry) => Protocol::ChainPushEntryResult(self.chain.push_entry(&entry)), + Protocol::ChainPushEntryResult(_) => unreachable!(), - ChainProtocol::GetEntry(key) => ChainProtocol::GetEntryResult(self.chain.get_entry(&key)), - ChainProtocol::GetEntryResult(_) => unreachable!(), + Protocol::ChainGetEntry(key) => Protocol::ChainGetEntryResult(self.chain.get_entry(&key)), + Protocol::ChainGetEntryResult(_) => unreachable!(), - ChainProtocol::GetPair(key) => ChainProtocol::GetPairResult(self.chain.get_pair(&key)), - ChainProtocol::GetPairResult(_) => unreachable!(), + Protocol::ChainGetPair(key) => Protocol::ChainGetPairResult(self.chain.get_pair(&key)), + Protocol::ChainGetPairResult(_) => unreachable!(), + _ => unreachable!(), }, Some(context.myself()), ).unwrap(); @@ -214,9 +209,9 @@ pub mod tests { use super::ChainActor; use riker::actors::*; use chain::tests::test_chain; - use chain::actor::ChainProtocol; + use chain::actor::Protocol; - pub fn test_chain_actor() -> ActorRef { + pub fn test_chain_actor() -> ActorRef { ChainActor::new_ref(test_chain()) } diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index c24927e060..b8ab44dfdd 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -5,13 +5,13 @@ use error::HolochainError; use hash_table::{entry::Entry, pair::Pair}; use serde_json; use std::{fmt}; -use hash_table::actor::HashTableProtocol; use hash_table::actor::AskHashTable; use hash_table::HashTable; +use actor::Protocol; #[derive(Clone)] pub struct ChainIterator { - table: ActorRef, + table: ActorRef, current: Option, } @@ -20,7 +20,7 @@ impl ChainIterator { // @see https://github.com/holochain/holochain-rust/issues/135 #[allow(unknown_lints)] #[allow(needless_pass_by_value)] - pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { + pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { ChainIterator { current: pair.clone(), table: table.clone(), @@ -43,8 +43,8 @@ impl Iterator for ChainIterator { // @TODO should this panic? // @see https://github.com/holochain/holochain-rust/issues/146 .and_then(|h| { - let response = self.table.ask(HashTableProtocol::GetPair(h.to_string())); - let result = unwrap_to!(response => HashTableProtocol::GetPairResult); + let response = self.table.ask(Protocol::HashTableGetPair(h.to_string())); + let result = unwrap_to!(response => Protocol::HashTableGetPairResult); result.clone().unwrap() }); ret @@ -55,7 +55,7 @@ impl Iterator for ChainIterator { pub struct Chain { // @TODO thread safe table references // @see https://github.com/holochain/holochain-rust/issues/135 - table: ActorRef, + table: ActorRef, top_pair: Option, } @@ -88,7 +88,7 @@ impl IntoIterator for Chain { impl Chain { - pub fn new(table: ActorRef) -> Chain { + pub fn new(table: ActorRef) -> Chain { Chain { top_pair: None, table: table.clone(), @@ -96,7 +96,7 @@ impl Chain { } /// returns a reference to the underlying HashTable - pub fn table(&self) -> ActorRef { + pub fn table(&self) -> ActorRef { self.table.clone() } @@ -121,7 +121,7 @@ impl Chain { /// restore canonical JSON chain /// @TODO accept canonical JSON /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn from_json(table: ActorRef, s: &str) -> Chain { + pub fn from_json(table: ActorRef, s: &str) -> Chain { // @TODO inappropriate unwrap? // @see https://github.com/holochain/holochain-rust/issues/168 let mut as_seq: Vec = serde_json::from_str(s).unwrap(); @@ -193,8 +193,8 @@ impl SourceChain for Chain { /// get a Pair by Pair/Header key from the HashTable if it exists fn get_pair(&self, k: &str) -> Result, HolochainError> { - let response = self.table.ask(HashTableProtocol::GetPair(k.to_string())); - unwrap_to!(response => HashTableProtocol::GetPairResult).clone() + let response = self.table.ask(Protocol::HashTableGetPair(k.to_string())); + unwrap_to!(response => Protocol::HashTableGetPairResult).clone() } /// get an Entry by Entry key from the HashTable if it exists diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 1baf5c9700..27e059afec 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,6 +1,5 @@ use riker::actors::*; use hash_table::HashTable; -// use riker_default::DefaultModel; use hash_table::pair::Pair; use error::HolochainError; use futures::executor::block_on; @@ -9,182 +8,147 @@ use hash_table::pair_meta::PairMeta; use agent::keys::Keys; use snowflake; use riker::kernel::Dispatcher; -use config::Config; -use futures::executor::{ThreadPool, ThreadPoolBuilder}; -use futures::{Future, Never}; +use futures::{Future}; use riker::futures_util::spawn; use riker_default::DeadLettersActor; use riker_default::BasicTimer; use riker_default::MapVec; use riker_default::SimpleLogger; use riker::system::NoIo; - -struct HashTableModel; - -// @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs -pub struct HashTableDispatcher { - inner: ThreadPool, -} - -impl Dispatcher for HashTableDispatcher { - fn new(_config: &Config, _: bool) -> HashTableDispatcher { - HashTableDispatcher { - inner: ThreadPoolBuilder::new() - .pool_size(4) - .name_prefix("pool-thread-hash-table-#") - .create() - .unwrap() - } - } - - fn execute(&mut self, f: F) - where F: Future + Send + 'static - { - self.inner.run(spawn(f)).unwrap(); - } -} - -impl Model for HashTableModel { - type Msg = HashTableProtocol; - type Dis = HashTableDispatcher; - type Ded = DeadLettersActor; - type Tmr = BasicTimer; - type Evs = MapVec; - type Tcp = NoIo; - type Udp = NoIo; - type Log = SimpleLogger; -} - -lazy_static! { - pub static ref HASH_TABLE_SYS: ActorSystem = { - // let hash_table_model: DefaultModel = DefaultModel::new(); - let hash_table_model = HashTableModel{}; - ActorSystem::new(&hash_table_model).unwrap() - }; -} - -#[derive(Debug, Clone)] -pub enum HashTableProtocol { - /// HashTable::setup() - Setup, - SetupResult(Result<(), HolochainError>), - - /// HashTable::teardown() - Teardown, - TeardownResult(Result<(), HolochainError>), - - /// HashTable::modify() - Modify{ - keys: Keys, - old_pair: Pair, - new_pair: Pair, - }, - ModifyResult(Result<(), HolochainError>), - - /// HashTable::retract() - Retract{ - keys: Keys, - pair: Pair, - }, - RetractResult(Result<(), HolochainError>), - - /// HashTable::assert_meta() - AssertMeta(PairMeta), - AssertMetaResult(Result<(), HolochainError>), - - /// HashTable::get_meta() - GetMeta(String), - GetMetaResult(Result, HolochainError>), - - /// HashTable::get_pair_meta() - GetPairMeta(Pair), - GetPairMetaResult(Result, HolochainError>), - - /// HashTable::get() - GetPair(String), - GetPairResult(Result, HolochainError>), - - /// HashTable::commit() - Commit(Pair), - CommitResult(Result<(), HolochainError>), - -} - -impl Into> for HashTableProtocol { - fn into(self) -> ActorMsg { - ActorMsg::User(self) - } -} - -/// anything that can be asked HashTableProtocol and block on responses +use riker_patterns::ask::Ask; +use futures::channel::oneshot::Canceled; +use futures::Async::Ready; +use actor::Protocol; +use actor::SYS; + +// struct HashTableModel; +// +// // @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs +// pub struct HashTableDispatcher { +// inner: ThreadPool, +// } +// +// impl Dispatcher for HashTableDispatcher { +// fn new(_config: &Config, _: bool) -> HashTableDispatcher { +// HashTableDispatcher { +// inner: ThreadPoolBuilder::new() +// .pool_size(4) +// .name_prefix("pool-thread-hash-table-#") +// .create() +// .unwrap() +// } +// } +// +// fn execute(&mut self, f: F) +// where F: Future + Send + 'static +// { +// self.inner.run(spawn(f)).unwrap(); +// } +// } +// +// impl Model for HashTableModel { +// type Msg = Protocol; +// type Dis = HashTableDispatcher; +// type Ded = DeadLettersActor; +// type Tmr = BasicTimer; +// type Evs = MapVec; +// type Tcp = NoIo; +// type Udp = NoIo; +// type Log = SimpleLogger; +// } + +// lazy_static! { +// pub static ref HASH_TABLE_SYS: ActorSystem HashTable= { +// let hash_table_model: DefaultModel HashTable= DefaultModel::new(); +// // let hash_table_model = HashTableModel{}; +// ActorSystem::new(&hash_table_model).unwrap() +// }; +// } + +// impl Into> for Protocol { +// fn into(self) -> ActorMsg { +// ActorMsg::User(self) +// } +// } + +// type HTAsk = Box + Send>; + +/// anything that can be asked Protocol aHashTablend block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskHashTable { - fn ask(&self, message: HashTableProtocol) -> HashTableProtocol; + fn ask(&self, message: Protocol) -> Protocol; } -impl AskHashTable for ActorRef { - fn ask(&self, message: HashTableProtocol) -> HashTableProtocol { +impl AskHashTable for ActorRef { + fn ask(&self, message: Protocol) -> Protocol { let a = ask( - &(*HASH_TABLE_SYS), + &(*SYS), self, message, ); - println!("asking table"); + // loop { + // match a.poll(context)? { + // Ready(v) => break v, + // _ => println!("polling"), + // } + // } + // println!("{:?}", &(*HASH_TABLE_SYS); + // println!("asking table"); block_on(a).unwrap() } } -impl HashTable for ActorRef { +impl HashTable for ActorRef { fn setup(&mut self) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Setup); - unwrap_to!(response => HashTableProtocol::SetupResult).clone() + let response = self.ask(Protocol::HashTableSetup); + unwrap_to!(response => Protocol::HashTableSetupResult).clone() } fn teardown(&mut self) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Teardown); - unwrap_to!(response => HashTableProtocol::TeardownResult).clone() + let response = self.ask(Protocol::HashTableTeardown); + unwrap_to!(response => Protocol::HashTableTeardownResult).clone() } fn commit(&mut self, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Commit(pair.clone())); - unwrap_to!(response => HashTableProtocol::CommitResult).clone() + let response = self.ask(Protocol::HashTableCommit(pair.clone())); + unwrap_to!(response => Protocol::HashTableCommitResult).clone() } fn get(&self, key: &str) -> Result, HolochainError> { - let response = self.ask(HashTableProtocol::GetPair(key.to_string())); - unwrap_to!(response => HashTableProtocol::GetPairResult).clone() + let response = self.ask(Protocol::HashTableGetPair(key.to_string())); + unwrap_to!(response => Protocol::HashTableGetPairResult).clone() } fn modify(&mut self, keys: &Keys, old_pair: &Pair, new_pair: &Pair,) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Modify{ + let response = self.ask(Protocol::HashTableModify{ keys: keys.clone(), old_pair: old_pair.clone(), new_pair: new_pair.clone(), }); - unwrap_to!(response => HashTableProtocol::ModifyResult).clone() + unwrap_to!(response => Protocol::HashTableModifyResult).clone() } fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Retract{ + let response = self.ask(Protocol::HashTableRetract{ keys: keys.clone(), pair: pair.clone(), }); - unwrap_to!(response => HashTableProtocol::RetractResult).clone() + unwrap_to!(response => Protocol::HashTableRetractResult).clone() } fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::AssertMeta(meta.clone())); - unwrap_to!(response => HashTableProtocol::AssertMetaResult).clone() + let response = self.ask(Protocol::HashTableAssertMeta(meta.clone())); + unwrap_to!(response => Protocol::HashTableAssertMetaResult).clone() } fn get_meta(&mut self, key: &str) -> Result, HolochainError> { - let response = self.ask(HashTableProtocol::GetMeta(key.to_string())); - unwrap_to!(response => HashTableProtocol::GetMetaResult).clone() + let response = self.ask(Protocol::HashTableGetMeta(key.to_string())); + unwrap_to!(response => Protocol::HashTableGetMetaResult).clone() } fn get_pair_meta(&mut self, pair: &Pair) -> Result, HolochainError> { - let response = self.ask(HashTableProtocol::GetPairMeta(pair.clone())); - unwrap_to!(response => HashTableProtocol::GetPairMetaResult).clone() + let response = self.ask(Protocol::HashTableGetPairMeta(pair.clone())); + unwrap_to!(response => Protocol::HashTableGetPairMetaResult).clone() } } @@ -202,16 +166,16 @@ impl HashTableActor { } } - pub fn actor(table: HT) -> BoxActor { + pub fn actor(table: HT) -> BoxActor { Box::new(HashTableActor::new(table)) } - pub fn props(table: HT) -> BoxActorProd { + pub fn props(table: HT) -> BoxActorProd { Props::new_args(Box::new(HashTableActor::actor), table) } - pub fn new_ref(table: HT) -> ActorRef { - HASH_TABLE_SYS.actor_of( + pub fn new_ref(table: HT) -> ActorRef { + SYS.actor_of( HashTableActor::props(table), &snowflake::ProcessUniqueId::new().to_string(), ).unwrap() @@ -220,7 +184,7 @@ impl HashTableActor { } impl Actor for HashTableActor { - type Msg = HashTableProtocol; + type Msg = Protocol; fn receive( &mut self, @@ -232,32 +196,34 @@ impl Actor for HashTableActor { sender.try_tell( match message { - HashTableProtocol::Setup => HashTableProtocol::SetupResult(self.table.setup()), - HashTableProtocol::SetupResult(_) => unreachable!(), + Protocol::HashTableSetup => Protocol::HashTableSetupResult(self.table.setup()), + Protocol::HashTableSetupResult(_) => unreachable!(), + + Protocol::HashTableTeardown => Protocol::HashTableTeardownResult(self.table.teardown()), + Protocol::HashTableTeardownResult(_) => unreachable!(), - HashTableProtocol::Teardown => HashTableProtocol::TeardownResult(self.table.teardown()), - HashTableProtocol::TeardownResult(_) => unreachable!(), + Protocol::HashTableCommit(pair) => Protocol::HashTableCommitResult(self.table.commit(&pair)), + Protocol::HashTableCommitResult(_) => unreachable!(), - HashTableProtocol::Commit(pair) => HashTableProtocol::CommitResult(self.table.commit(&pair)), - HashTableProtocol::CommitResult(_) => unreachable!(), + Protocol::HashTableGetPair(hash) => Protocol::HashTableGetPairResult(self.table.get(&hash)), + Protocol::HashTableGetPairResult(_) => unreachable!(), - HashTableProtocol::GetPair(hash) => HashTableProtocol::GetPairResult(self.table.get(&hash)), - HashTableProtocol::GetPairResult(_) => unreachable!(), + Protocol::HashTableModify{keys, old_pair, new_pair} => Protocol::HashTableModifyResult(self.table.modify(&keys, &old_pair, &new_pair)), + Protocol::HashTableModifyResult(_) => unreachable!(), - HashTableProtocol::Modify{keys, old_pair, new_pair} => HashTableProtocol::ModifyResult(self.table.modify(&keys, &old_pair, &new_pair)), - HashTableProtocol::ModifyResult(_) => unreachable!(), + Protocol::HashTableRetract{keys, pair} => Protocol::HashTableRetractResult(self.table.retract(&keys, &pair)), + Protocol::HashTableRetractResult(_) => unreachable!(), - HashTableProtocol::Retract{keys, pair} => HashTableProtocol::RetractResult(self.table.retract(&keys, &pair)), - HashTableProtocol::RetractResult(_) => unreachable!(), + Protocol::HashTableAssertMeta(pair_meta) => Protocol::HashTableAssertMetaResult(self.table.assert_meta(&pair_meta)), + Protocol::HashTableAssertMetaResult(_) => unreachable!(), - HashTableProtocol::AssertMeta(pair_meta) => HashTableProtocol::AssertMetaResult(self.table.assert_meta(&pair_meta)), - HashTableProtocol::AssertMetaResult(_) => unreachable!(), + Protocol::HashTableGetMeta(key) => Protocol::HashTableGetMetaResult(self.table.get_meta(&key)), + Protocol::HashTableGetMetaResult(_) => unreachable!(), - HashTableProtocol::GetMeta(key) => HashTableProtocol::GetMetaResult(self.table.get_meta(&key)), - HashTableProtocol::GetMetaResult(_) => unreachable!(), + Protocol::HashTableGetPairMeta(pair) => Protocol::HashTableGetPairMetaResult(self.table.get_pair_meta(&pair)), + Protocol::HashTableGetPairMetaResult(_) => unreachable!(), - HashTableProtocol::GetPairMeta(pair) => HashTableProtocol::GetPairMetaResult(self.table.get_pair_meta(&pair)), - HashTableProtocol::GetPairMetaResult(_) => unreachable!(), + _ => unreachable!(), }, Some(context.myself()), ).unwrap(); @@ -272,9 +238,9 @@ pub mod tests { use super::HashTableActor; use hash_table::memory::tests::test_table; use riker::actors::*; - use hash_table::actor::HashTableProtocol; + use hash_table::actor::Protocol; - pub fn test_table_actor() -> ActorRef { + pub fn test_table_actor() -> ActorRef { HashTableActor::new_ref(test_table()) } diff --git a/core/src/lib.rs b/core/src/lib.rs index f57d2222db..1e117707ae 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -28,6 +28,7 @@ extern crate holochain_dna; extern crate holochain_wasm_utils; extern crate config; +pub mod actor; pub mod action; pub mod agent; pub mod chain; From abb73121b6fb6ed9f5244f8c14be3624baff77ca Mon Sep 17 00:00:00 2001 From: David Meister Date: Sat, 18 Aug 2018 23:29:57 +1000 Subject: [PATCH 11/49] passing round trip through the hash table with an actor --- core/src/agent/state.rs | 32 ++++++--- core/src/chain/actor.rs | 2 +- core/src/chain/mod.rs | 14 +++- core/src/hash_table/actor.rs | 27 ++++---- core/src/hash_table/memory/mod.rs | 1 + core/src/nucleus/ribosome/api/get.rs | 100 ++++++++++++++++++++++++++- core/src/nucleus/ribosome/api/mod.rs | 60 +++++++++++----- core/src/state.rs | 12 ++-- 8 files changed, 193 insertions(+), 55 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 14b15ca21a..cb24a35ba8 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -1,7 +1,7 @@ use action::{Action, ActionWrapper, AgentReduceFn}; use agent::keys::Keys; use instance::Observer; -use riker::actors::*; +// use riker::actors::*; use context::Context; use error::HolochainError; use hash_table::{pair::Pair}; @@ -9,9 +9,10 @@ use std::{ collections::HashMap, sync::{mpsc::Sender, Arc}, }; -use actor::Protocol; -use chain::actor::AskChain; +// use actor::Protocol; +// use chain::actor::AskChain; use chain::SourceChain; +use chain::Chain; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers @@ -25,12 +26,12 @@ pub struct AgentState { // @TODO this will blow up memory, implement as some kind of dropping/FIFO with a limit? // @see https://github.com/holochain/holochain-rust/issues/166 actions: HashMap, - chain: ActorRef, + chain: Chain, } impl AgentState { /// builds a new, empty AgentState - pub fn new(chain: ActorRef) -> AgentState { + pub fn new(chain: Chain) -> AgentState { AgentState { keys: None, top_pair: None, @@ -111,6 +112,7 @@ fn reduce_commit( action_wrapper.clone(), ActionResponse::Commit(state.chain.push_entry(&entry)), ); + println!("chain commit: {:?}", state.chain); } /// do a get action against an agent state @@ -122,13 +124,19 @@ fn reduce_get( _action_channel: &Sender, _observer_channel: &Sender, ) { + println!("chain get: {:?}", state.chain); + let action = action_wrapper.action(); let key = unwrap_to!(action => Action::Get); - let response = state.chain.ask( - Protocol::ChainGetEntry(key.clone()), - ); - let result = unwrap_to!(response => Protocol::ChainGetEntryResult); + let result = state.chain.get_entry(&key.clone()); + + println!("result: {:?}", result); + + // let response = state.chain.ask( + // Protocol::ChainGetEntry(key.clone()), + // ); + // let result = unwrap_to!(response => Protocol::ChainGetEntryResult); // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 @@ -169,6 +177,7 @@ pub fn reduce( action_channel, observer_channel, ); + println!("reduce: {:?}", new_state.chain); Arc::new(new_state) } None => old_state, @@ -183,7 +192,8 @@ pub mod tests { use hash_table::pair::tests::test_pair; use instance::tests::{test_context, test_instance_blank}; use std::collections::HashMap; - use chain::actor::tests::test_chain_actor; + // use chain::actor::tests::test_chain_actor; + use chain::tests::test_chain; #[test] fn test_actor_receive() { @@ -199,7 +209,7 @@ pub mod tests { /// dummy agent state pub fn test_agent_state() -> AgentState { - AgentState::new(test_chain_actor()) + AgentState::new(test_chain()) } /// dummy action response for a successful commit as test_pair() diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index a7cbc3439a..6b1c283b0e 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -8,7 +8,7 @@ use error::HolochainError; use chain::Chain; use chain::SourceChain; use snowflake; -use riker::kernel::Dispatcher; +// use riker::kernel::Dispatcher; // use hash_table::actor::HASH_TABLE_SYS; use actor::SYS; use actor::Protocol; diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index b8ab44dfdd..ea5e91690e 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -8,6 +8,7 @@ use std::{fmt}; use hash_table::actor::AskHashTable; use hash_table::HashTable; use actor::Protocol; +// use futures::executor::block_on; #[derive(Clone)] pub struct ChainIterator { @@ -38,14 +39,17 @@ impl Iterator for ChainIterator { fn next(&mut self) -> Option { let ret = self.current(); + println!("next current: {:?}", ret); self.current = ret.clone() .and_then(|p| p.header().next()) // @TODO should this panic? // @see https://github.com/holochain/holochain-rust/issues/146 .and_then(|h| { - let response = self.table.ask(Protocol::HashTableGetPair(h.to_string())); - let result = unwrap_to!(response => Protocol::HashTableGetPairResult); - result.clone().unwrap() + // let response = self.table.ask(Protocol::HashTableGetPair(h.to_string())); + // let result = unwrap_to!(response => Protocol::HashTableGetPairResult); + // println!("next: {:?}", result); + // result.clone().unwrap() + self.table.get(&h.to_string()).unwrap() }); ret } @@ -107,6 +111,7 @@ impl Chain { /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable fn iter(&self) -> ChainIterator { + println!("at iter: {:?}", self); ChainIterator::new(self.table(), &self.top_pair()) } @@ -176,6 +181,8 @@ impl SourceChain for Chain { if result.is_ok() { self.top_pair = Some(pair.clone()); } + + println!("after commit: {:?}", self); match result { Ok(_) => Ok(pair.clone()), Err(e) => Err(e.clone()), @@ -199,6 +206,7 @@ impl SourceChain for Chain { /// get an Entry by Entry key from the HashTable if it exists fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { + println!("get entry: {:?}", entry_hash); // @TODO - this is a slow way to do a lookup // @see https://github.com/holochain/holochain-rust/issues/50 Ok(self diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 27e059afec..a5e356279c 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -7,19 +7,21 @@ use riker_patterns::ask::ask; use hash_table::pair_meta::PairMeta; use agent::keys::Keys; use snowflake; -use riker::kernel::Dispatcher; -use futures::{Future}; -use riker::futures_util::spawn; -use riker_default::DeadLettersActor; -use riker_default::BasicTimer; -use riker_default::MapVec; -use riker_default::SimpleLogger; -use riker::system::NoIo; -use riker_patterns::ask::Ask; -use futures::channel::oneshot::Canceled; -use futures::Async::Ready; +// use riker::kernel::Dispatcher; +// use futures::{Future}; +// use riker::futures_util::spawn; +// use riker_default::DeadLettersActor; +// use riker_default::BasicTimer; +// use riker_default::MapVec; +// use riker_default::SimpleLogger; +// use riker::system::NoIo; +// use riker_patterns::ask::Ask; +// use futures::channel::oneshot::Canceled; +// use futures::Async::Ready; use actor::Protocol; use actor::SYS; +// use futures::executor::spawn_with_handle; +// use futures::executor::SpawnWithHandle; // struct HashTableModel; // @@ -71,7 +73,7 @@ use actor::SYS; // } // } -// type HTAsk = Box + Send>; +// type HTAsk = Box + Send>; /// anything that can be asked Protocol aHashTablend block on responses /// needed to support implementing ask on upstream ActorRef from riker @@ -95,6 +97,7 @@ impl AskHashTable for ActorRef { // println!("{:?}", &(*HASH_TABLE_SYS); // println!("asking table"); block_on(a).unwrap() + // spawn_with_handle(a) } } diff --git a/core/src/hash_table/memory/mod.rs b/core/src/hash_table/memory/mod.rs index 19e05f9c66..f7be75437e 100644 --- a/core/src/hash_table/memory/mod.rs +++ b/core/src/hash_table/memory/mod.rs @@ -40,6 +40,7 @@ impl HashTable for MemTable { } fn get(&self, key: &str) -> Result, HolochainError> { + println!("get: {:?}", key); Ok(self.pairs.get(key).and_then(|p| Some(p.clone()))) } diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index 8fa155449d..70b2fe6b38 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -73,9 +73,21 @@ mod tests { use super::GetArgs; use hash_table::entry::tests::{test_entry, test_entry_hash}; - use nucleus::ribosome::api::tests::test_zome_api_function_runtime; + // use nucleus::ribosome::api::tests::test_zome_api_function_runtime; + use instance::tests::test_instance; + use self::wabt::Wat2Wasm; use nucleus::ribosome::api::commit::tests::test_commit_args_bytes; use serde_json; + use nucleus::ribosome::api::tests::test_zome_name; + use nucleus::ribosome::api::tests::test_capability; + // use nucleus::ribosome::api::tests::test_zome_api_function_call; + use instance::tests::test_context_and_logger; + use std::sync::Arc; + use nucleus::ribosome::api::tests::test_parameters; + use nucleus::{ + ribosome::api::{call}, + FunctionCall, + }; /// dummy get args from standard test entry pub fn test_get_args_bytes() -> Vec { @@ -85,16 +97,98 @@ mod tests { serde_json::to_string(&args).unwrap().into_bytes() } + pub fn test_get_round_trip_wat() -> Vec { + Wat2Wasm::new() + .canonicalize_lebs(false) + .write_debug_names(true) + .convert( + // format!( + r#" +(module + (import "env" "get" + (func $get + (param i32) + (result i32) + ) + ) + + (import "env" "commit" + (func $commit + (param i32) + (result i32) + ) + ) + + (memory 1) + (export "memory" (memory 0)) + + (func + (export "get_dispatch") + (param $allocation i32) + (result i32) + + (call + $get + (get_local $allocation) + ) + ) + + (func + (export "commit_dispatch") + (param $allocation i32) + (result i32) + + (call + $commit + (get_local $allocation) + ) + ) +) + "#, + // canonical_name + // ), + ) + .unwrap() + .as_ref() + .to_vec() + } + #[test] /// test that we can round trip bytes through a get action and it comes back from wasm fn test_get_round_trip() { - let (commit_runtime, _) = test_zome_api_function_runtime("commit", test_commit_args_bytes()); + let wasm = test_get_round_trip_wat(); + let dna = + test_utils::create_test_dna_with_wasm(&test_zome_name(), &test_capability(), wasm.clone()); + let instance = test_instance(dna); + let (context, _) = test_context_and_logger("joan"); + + let commit_call = FunctionCall::new(&test_zome_name(), &test_capability(), &"commit", &test_parameters()); + let commit_runtime = call( + Arc::clone(&context), + &instance.action_channel(), + &instance.observer_channel(), + wasm.clone(), + &commit_call, + Some(test_commit_args_bytes()), + ).expect("test should be callable"); + + // let (commit_runtime, _) = test_zome_api_function_call(Arc::clone(&context), Arc::clone(&logger), &instance, &wasm, test_commit_args_bytes()); assert_eq!( commit_runtime.result, format!(r#"{{"hash":"{}"}}"#, test_entry().key()) + "\u{0}", ); - let (get_runtime, _) = test_zome_api_function_runtime("get", test_get_args_bytes()); + // let (get_runtime, _) = test_zome_api_function_call(Arc::clone(&context), Arc::clone(&logger), &instance, &wasm, test_get_args_bytes()); + + let get_call = FunctionCall::new(&test_zome_name(), &test_capability(), &"get", &test_parameters()); + let get_runtime = call( + Arc::clone(&context), + &instance.action_channel(), + &instance.observer_channel(), + wasm.clone(), + &get_call, + Some(test_get_args_bytes()), + ).expect("test should be callable"); let mut expected = "".to_owned(); expected.push_str("{\"header\":{\"entry_type\":\"testEntryType\",\"time\":\"\",\"next\":null,\"entry\":\""); diff --git a/core/src/nucleus/ribosome/api/mod.rs b/core/src/nucleus/ribosome/api/mod.rs index fe02a3f130..48b57d1e47 100644 --- a/core/src/nucleus/ribosome/api/mod.rs +++ b/core/src/nucleus/ribosome/api/mod.rs @@ -312,6 +312,8 @@ pub mod tests { str::FromStr, sync::{Arc, Mutex}, }; + use context::Context; + use instance::Instance; use holochain_dna::zome::capabilities::ReservedCapabilityNames; @@ -401,28 +403,30 @@ pub mod tests { .to_vec() } - /// given a canonical zome API function name and args as bytes: - /// - builds wasm with test_zome_api_function_wasm - /// - builds dna and test instance - /// - calls the zome API function with passed bytes argument using the instance runtime - /// - returns the runtime after the call completes - pub fn test_zome_api_function_runtime( - canonical_name: &str, - args_bytes: Vec, - ) -> (Runtime, Arc>) { - let zome_name = "test_zome"; - let capability = ReservedCapabilityNames::MissingNo.as_str().to_string(); - let function_name = "test"; - let parameters = ""; + pub fn test_zome_name() -> String { + "test_zome".to_string() + } - let wasm = test_zome_api_function_wasm(canonical_name); - let dna = - test_utils::create_test_dna_with_wasm(zome_name.into(), &capability, wasm.clone()); - let instance = test_instance(dna); - let (context, logger) = test_context_and_logger("joan"); + pub fn test_capability() -> String { + ReservedCapabilityNames::MissingNo.as_str().to_string() + } + + pub fn test_function_name() -> String { + "test".to_string() + } - let fc = FunctionCall::new(&zome_name, &capability, &function_name, ¶meters); + pub fn test_parameters() -> String { + String::new() + } + pub fn test_zome_api_function_call( + context: Arc, + logger: Arc>, + instance: &Instance, + wasm: &Vec, + args_bytes: Vec, + ) -> (Runtime, Arc>) { + let fc = FunctionCall::new(&test_zome_name(), &test_capability(), &test_function_name(), &test_parameters()); ( call( context, @@ -436,6 +440,24 @@ pub mod tests { ) } + /// given a canonical zome API function name and args as bytes: + /// - builds wasm with test_zome_api_function_wasm + /// - builds dna and test instance + /// - calls the zome API function with passed bytes argument using the instance runtime + /// - returns the runtime after the call completes + pub fn test_zome_api_function_runtime( + canonical_name: &str, + args_bytes: Vec, + ) -> (Runtime, Arc>) { + let wasm = test_zome_api_function_wasm(canonical_name); + let dna = + test_utils::create_test_dna_with_wasm(&test_zome_name(), &test_capability(), wasm.clone()); + let instance = test_instance(dna); + let (context, logger) = test_context_and_logger("joan"); + + test_zome_api_function_call(context, logger, &instance, &wasm, args_bytes) + } + #[test] /// test the FromStr implementation for ZomeAPIFunction fn test_from_str() { diff --git a/core/src/state.rs b/core/src/state.rs index b07956a119..89537b5c1e 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -9,7 +9,7 @@ use std::{ use hash_table::memory::MemTable; use action::ActionWrapper; use chain::Chain; -use chain::actor::ChainActor; +// use chain::actor::ChainActor; use hash_table::actor::HashTableActor; #[derive(Clone, PartialEq, Debug)] @@ -24,17 +24,17 @@ pub struct State { impl State { pub fn new() -> Self { // @TODO file table - let chain_actor = ChainActor::new_ref( - Chain::new( + // let chain_actor = ChainActor::new_ref( + let chain = Chain::new( HashTableActor::new_ref( MemTable::new(), ), - ), - ); + ); + // ); State { nucleus: Arc::new(NucleusState::new()), - agent: Arc::new(AgentState::new(chain_actor)), + agent: Arc::new(AgentState::new(chain)), history: HashSet::new(), } } From e4411192511fd609d988bc69e9428364a8014038 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 19 Aug 2018 22:38:30 +1000 Subject: [PATCH 12/49] fixing tests --- core/src/actor.rs | 15 +- core/src/agent/state.rs | 82 +++++----- core/src/chain/actor.rs | 218 --------------------------- core/src/chain/mod.rs | 46 +++--- core/src/hash_table/actor.rs | 134 ++++++++-------- core/src/hash_table/header.rs | 8 +- core/src/hash_table/mod.rs | 2 +- core/src/hash_table/pair.rs | 3 +- core/src/lib.rs | 6 +- core/src/nucleus/ribosome/api/get.rs | 39 +++-- core/src/nucleus/ribosome/api/mod.rs | 22 ++- core/src/state.rs | 16 +- 12 files changed, 200 insertions(+), 391 deletions(-) delete mode 100644 core/src/chain/actor.rs diff --git a/core/src/actor.rs b/core/src/actor.rs index 4628831dd6..a21e7c2210 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -1,14 +1,11 @@ -use hash_table::pair::Pair; -use riker_default::DefaultModel; -use riker::actors::*; -use hash_table::entry::Entry; -use error::HolochainError; use agent::keys::Keys; -use hash_table::pair_meta::PairMeta; +use error::HolochainError; +use hash_table::{entry::Entry, pair::Pair, pair_meta::PairMeta}; +use riker::actors::*; +use riker_default::DefaultModel; #[derive(Clone, Debug)] pub enum Protocol { - ChainTopPair, ChainTopPairResult(Option), @@ -36,7 +33,7 @@ pub enum Protocol { HashTableTeardownResult(Result<(), HolochainError>), /// HashTable::modify() - HashTableModify{ + HashTableModify { keys: Keys, old_pair: Pair, new_pair: Pair, @@ -44,7 +41,7 @@ pub enum Protocol { HashTableModifyResult(Result<(), HolochainError>), /// HashTable::retract() - HashTableRetract{ + HashTableRetract { keys: Keys, pair: Pair, }, diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index cb24a35ba8..e19ffbb53a 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -4,15 +4,14 @@ use instance::Observer; // use riker::actors::*; use context::Context; use error::HolochainError; -use hash_table::{pair::Pair}; +use hash_table::pair::Pair; use std::{ collections::HashMap, sync::{mpsc::Sender, Arc}, }; // use actor::Protocol; // use chain::actor::AskChain; -use chain::SourceChain; -use chain::Chain; +use chain::{Chain, SourceChain}; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers @@ -31,7 +30,7 @@ pub struct AgentState { impl AgentState { /// builds a new, empty AgentState - pub fn new(chain: Chain) -> AgentState { + pub fn new(chain: &Chain) -> AgentState { AgentState { keys: None, top_pair: None, @@ -106,12 +105,10 @@ fn reduce_commit( // @TODO successfully validate before pushing a commit // @see https://github.com/holochain/holochain-rust/issues/97 - state - .actions - .insert( - action_wrapper.clone(), - ActionResponse::Commit(state.chain.push_entry(&entry)), - ); + state.actions.insert( + action_wrapper.clone(), + ActionResponse::Commit(state.chain.push_entry(&entry)), + ); println!("chain commit: {:?}", state.chain); } @@ -141,12 +138,10 @@ fn reduce_get( // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 - state - .actions - .insert( - action_wrapper.clone(), - ActionResponse::Get(result.clone().unwrap()), - ); + state.actions.insert( + action_wrapper.clone(), + ActionResponse::Get(result.clone().unwrap()), + ); } /// maps incoming action to the correct handler @@ -188,28 +183,15 @@ pub fn reduce( pub mod tests { use super::{reduce_commit, reduce_get, ActionResponse, AgentState}; use action::tests::{test_action_wrapper_commit, test_action_wrapper_get}; + use chain::tests::test_chain; use error::HolochainError; use hash_table::pair::tests::test_pair; use instance::tests::{test_context, test_instance_blank}; - use std::collections::HashMap; - // use chain::actor::tests::test_chain_actor; - use chain::tests::test_chain; - - #[test] - fn test_actor_receive() { - // let state = test_agent_state(); - - // state.chain.tell("hi".to_string(), None); - // let chain = state.chain.clone(); - // let handle = thread::spawn(move || { - // chain.tell("thread hi!".to_string(), None); - // }); - // handle.join().unwrap(); - } + use std::{collections::HashMap, sync::Arc}; /// dummy agent state pub fn test_agent_state() -> AgentState { - AgentState::new(test_chain()) + AgentState::new(&test_chain()) } /// dummy action response for a successful commit as test_pair() @@ -272,22 +254,46 @@ pub mod tests { /// test for reducing get fn test_reduce_get() { let mut state = test_agent_state(); - let action_wrapper = test_action_wrapper_get(); + let context = test_context("foo"); let instance = test_instance_blank(); + let aw1 = test_action_wrapper_get(); reduce_get( - test_context("foo"), + Arc::clone(&context), &mut state, - &action_wrapper, + &aw1, &instance.action_channel().clone(), &instance.observer_channel().clone(), ); - assert_eq!( - state.actions().get(&action_wrapper), - Some(&test_action_response_get()), + // nothing has been committed so the get must be None + assert_eq!(state.actions().get(&aw1), Some(&ActionResponse::Get(None)),); + + // do a round trip + reduce_commit( + Arc::clone(&context), + &mut state, + &test_action_wrapper_commit(), + &instance.action_channel().clone(), + &instance.observer_channel().clone(), + ); + + let aw2 = test_action_wrapper_get(); + reduce_get( + Arc::clone(&context), + &mut state, + &aw2, + &instance.action_channel().clone(), + &instance.observer_channel().clone(), ); + + assert_eq!(state.actions().get(&aw2), Some(&test_action_response_get()),); + } + + #[test] + fn test_round_trip_threads() { + // @TODO } #[test] diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs deleted file mode 100644 index 6b1c283b0e..0000000000 --- a/core/src/chain/actor.rs +++ /dev/null @@ -1,218 +0,0 @@ -// use riker_default::DefaultModel; -use riker::actors::*; -use futures::executor::block_on; -use riker_patterns::ask::ask; -use hash_table::entry::Entry; -use hash_table::pair::Pair; -use error::HolochainError; -use chain::Chain; -use chain::SourceChain; -use snowflake; -// use riker::kernel::Dispatcher; -// use hash_table::actor::HASH_TABLE_SYS; -use actor::SYS; -use actor::Protocol; - -// struct ChainModel; -// -// // @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs -// pub struct ChainDispatcher { -// inner: ThreadPool, -// } -// -// impl Dispatcher for ChainDispatcher { -// fn new(_config: &Config, _: bool) -> ChainDispatcher { -// ChainDispatcher { -// inner: ThreadPoolBuilder::new() -// .pool_size(4) -// .name_prefix("pool-thread-chain-#") -// .create() -// .unwrap() -// } -// } -// -// fn execute(&mut self, f: F) -// where F: Future + Send + 'static -// { -// self.inner.run(spawn(f)).unwrap(); -// } -// } -// -// impl Model for ChainModel { -// type Msg = Protocol; -// type Dis = ChainDispatcher; -// type Ded = DeadLettersActor; -// type Tmr = BasicTimer; -// type Evs = MapVec; -// type Tcp = NoIo; -// type Udp = NoIo; -// type Log = SimpleLogger; -// } - -// lazy_static! { -// pub static ref CHAIN_SYS: ActorSystem = { -// // let chain_model: DefaultModel = DefaultModel::new(); -// let chain_model = ChainModel{}; -// ActorSystem::new(&chain_model).unwrap() -// }; -// } - -// #[derive(Debug, Clone)] -// pub enum Protocol { -// TopPair, -// TopPairResult(Option), -// -// TopPairType(String), -// TopPairTypeResult(Option), -// -// PushEntry(Entry), -// PushEntryResult(Result), -// -// PushPair(Pair), -// PushPairResult(Result), -// -// GetEntry(String), -// GetEntryResult(Result, HolochainError>), -// -// GetPair(String), -// GetPairResult(Result, HolochainError>), -// } - -// impl Into> for Protocol { -// fn into(self) -> ActorMsg { -// ActorMsg::User(self) -// } -// } - -/// anything that can be asked Protocol and block on responses -/// needed to support implementing ask on upstream ActorRef from riker -/// convenience wrappers around chain struct methods -pub trait AskChain { - fn ask(&self, message: Protocol) -> Protocol; -} - -impl AskChain for ActorRef { - fn ask(&self, message: Protocol) -> Protocol { - let a = ask( - &(*SYS), - self, - message, - ); - println!("asking chain"); - block_on(a).unwrap() - } -} - -impl SourceChain for ActorRef { - - fn top_pair(&self) -> Option { - let response = self.ask(Protocol::ChainTopPair); - unwrap_to!(response => Protocol::ChainTopPairResult).clone() - } - - fn top_pair_type(&self, t: &str) -> Option { - let response = self.ask(Protocol::ChainTopPairType(t.to_string())); - unwrap_to!(response => Protocol::ChainTopPairTypeResult).clone() - } - - fn push_entry(&mut self, entry: &Entry) -> Result { - let response = self.ask(Protocol::ChainPushEntry(entry.clone())); - unwrap_to!(response => Protocol::ChainPushEntryResult).clone() - } - - fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { - let response = self.ask(Protocol::ChainGetEntry(entry_hash.to_string())); - unwrap_to!(response => Protocol::ChainGetEntryResult).clone() - } - - fn push_pair(&mut self, pair: &Pair) -> Result { - let response = self.ask(Protocol::ChainPushPair(pair.clone())); - unwrap_to!(response => Protocol::ChainPushPairResult).clone() - } - - fn get_pair(&self, k: &str) -> Result, HolochainError> { - let response = self.ask(Protocol::ChainGetPair(k.to_string())); - unwrap_to!(response => Protocol::ChainGetPairResult).clone() - } - -} - -pub struct ChainActor { - - chain: Chain, - -} - -impl ChainActor { - - pub fn new(chain: Chain) -> ChainActor { - ChainActor{ - chain, - } - } - - pub fn actor(chain: Chain) -> BoxActor { - Box::new(ChainActor::new(chain)) - } - - pub fn props(chain: Chain) -> BoxActorProd { - Props::new_args(Box::new(ChainActor::actor), chain) - } - - pub fn new_ref(chain: Chain) -> ActorRef { - SYS.actor_of( - ChainActor::props(chain), - &snowflake::ProcessUniqueId::new().to_string(), - ).unwrap() - } - -} - -impl Actor for ChainActor { - type Msg = Protocol; - - fn receive( - &mut self, - context: &Context, - message: Self::Msg, - sender: Option>, - ) { - println!("received {:?}", message); - sender.try_tell( - match message { - Protocol::ChainTopPair => Protocol::ChainTopPairResult(self.chain.top_pair()), - Protocol::ChainTopPairResult(_) => unreachable!(), - - Protocol::ChainTopPairType(t) => Protocol::ChainTopPairTypeResult(self.chain.top_pair_type(&t)), - Protocol::ChainTopPairTypeResult(_) => unreachable!(), - - Protocol::ChainPushPair(pair) => Protocol::ChainPushPairResult(self.chain.push_pair(&pair)), - Protocol::ChainPushPairResult(_) => unreachable!(), - - Protocol::ChainPushEntry(entry) => Protocol::ChainPushEntryResult(self.chain.push_entry(&entry)), - Protocol::ChainPushEntryResult(_) => unreachable!(), - - Protocol::ChainGetEntry(key) => Protocol::ChainGetEntryResult(self.chain.get_entry(&key)), - Protocol::ChainGetEntryResult(_) => unreachable!(), - - Protocol::ChainGetPair(key) => Protocol::ChainGetPairResult(self.chain.get_pair(&key)), - Protocol::ChainGetPairResult(_) => unreachable!(), - _ => unreachable!(), - }, - Some(context.myself()), - ).unwrap(); - } -} - -#[cfg(test)] -pub mod tests { - use super::ChainActor; - use riker::actors::*; - use chain::tests::test_chain; - use chain::actor::Protocol; - - pub fn test_chain_actor() -> ActorRef { - ChainActor::new_ref(test_chain()) - } - -} diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index ea5e91690e..d28d6df5f0 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,13 +1,9 @@ -pub mod actor; - -use riker::actors::*; +use actor::Protocol; use error::HolochainError; -use hash_table::{entry::Entry, pair::Pair}; +use hash_table::{actor::AskHashTable, entry::Entry, pair::Pair, HashTable}; +use riker::actors::*; use serde_json; -use std::{fmt}; -use hash_table::actor::AskHashTable; -use hash_table::HashTable; -use actor::Protocol; +use std::fmt; // use futures::executor::block_on; #[derive(Clone)] @@ -91,7 +87,6 @@ impl IntoIterator for Chain { } impl Chain { - pub fn new(table: ActorRef) -> Chain { Chain { top_pair: None, @@ -142,11 +137,9 @@ impl Chain { } chain } - } impl SourceChain for Chain { - /// returns a clone of the top Pair fn top_pair(&self) -> Option { self.top_pair.clone() @@ -232,14 +225,13 @@ pub trait SourceChain { pub mod tests { use super::Chain; + use chain::SourceChain; use hash_table::{ + actor::tests::test_table_actor, entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, pair::Pair, + HashTable, }; - use chain::actor::ChainActor; - use hash_table::actor::tests::test_table_actor; - use chain::SourceChain; - use hash_table::HashTable; /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -293,17 +285,16 @@ pub mod tests { /// tests for chain.table() fn table_push() { let table_actor = test_table_actor(); - let chain = Chain::new(table_actor.clone()); - let mut chain_actor = ChainActor::new_ref(chain); + let mut chain = Chain::new(table_actor.clone()); // test that adding something to the chain adds to the table - let pair = chain_actor.push_entry(&test_entry()).unwrap(); + let pair = chain.push_entry(&test_entry()).unwrap(); assert_eq!(Some(pair.clone()), table_actor.get(&pair.key()).unwrap(),); - assert_eq!(Some(pair.clone()), chain_actor.get_pair(&pair.key()).unwrap(),); + assert_eq!(Some(pair.clone()), chain.get_pair(&pair.key()).unwrap(),); assert_eq!( table_actor.get(&pair.key()).unwrap(), - chain_actor.get_pair(&pair.key()).unwrap(), + chain.get_pair(&pair.key()).unwrap(), ); } @@ -409,9 +400,18 @@ pub mod tests { assert_eq!(Some(p1.clone()), chain.get_pair(&p1.key()).unwrap()); assert_eq!(Some(p2.clone()), chain.get_pair(&p2.key()).unwrap()); assert_eq!(Some(p3.clone()), chain.get_pair(&p3.key()).unwrap()); - assert_eq!(Some(p1.clone()), chain.get_pair(&p1.header().key()).unwrap()); - assert_eq!(Some(p2.clone()), chain.get_pair(&p2.header().key()).unwrap()); - assert_eq!(Some(p3.clone()), chain.get_pair(&p3.header().key()).unwrap()); + assert_eq!( + Some(p1.clone()), + chain.get_pair(&p1.header().key()).unwrap() + ); + assert_eq!( + Some(p2.clone()), + chain.get_pair(&p2.header().key()).unwrap() + ); + assert_eq!( + Some(p3.clone()), + chain.get_pair(&p3.header().key()).unwrap() + ); } #[test] diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index a5e356279c..2a961d9b09 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,11 +1,9 @@ -use riker::actors::*; -use hash_table::HashTable; -use hash_table::pair::Pair; +use agent::keys::Keys; use error::HolochainError; use futures::executor::block_on; +use hash_table::{pair::Pair, pair_meta::PairMeta, HashTable}; +use riker::actors::*; use riker_patterns::ask::ask; -use hash_table::pair_meta::PairMeta; -use agent::keys::Keys; use snowflake; // use riker::kernel::Dispatcher; // use futures::{Future}; @@ -18,8 +16,7 @@ use snowflake; // use riker_patterns::ask::Ask; // use futures::channel::oneshot::Canceled; // use futures::Async::Ready; -use actor::Protocol; -use actor::SYS; +use actor::{Protocol, SYS}; // use futures::executor::spawn_with_handle; // use futures::executor::SpawnWithHandle; @@ -83,11 +80,7 @@ pub trait AskHashTable { impl AskHashTable for ActorRef { fn ask(&self, message: Protocol) -> Protocol { - let a = ask( - &(*SYS), - self, - message, - ); + let a = ask(&(*SYS), self, message); // loop { // match a.poll(context)? { // Ready(v) => break v, @@ -122,8 +115,13 @@ impl HashTable for ActorRef { unwrap_to!(response => Protocol::HashTableGetPairResult).clone() } - fn modify(&mut self, keys: &Keys, old_pair: &Pair, new_pair: &Pair,) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableModify{ + fn modify( + &mut self, + keys: &Keys, + old_pair: &Pair, + new_pair: &Pair, + ) -> Result<(), HolochainError> { + let response = self.ask(Protocol::HashTableModify { keys: keys.clone(), old_pair: old_pair.clone(), new_pair: new_pair.clone(), @@ -132,7 +130,7 @@ impl HashTable for ActorRef { } fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableRetract{ + let response = self.ask(Protocol::HashTableRetract { keys: keys.clone(), pair: pair.clone(), }); @@ -153,7 +151,6 @@ impl HashTable for ActorRef { let response = self.ask(Protocol::HashTableGetPairMeta(pair.clone())); unwrap_to!(response => Protocol::HashTableGetPairMetaResult).clone() } - } #[derive(Clone, Debug)] @@ -162,11 +159,8 @@ pub struct HashTableActor { } impl HashTableActor { - - pub fn new (table: HT) -> HashTableActor { - HashTableActor { - table - } + pub fn new(table: HT) -> HashTableActor { + HashTableActor { table } } pub fn actor(table: HT) -> BoxActor { @@ -183,7 +177,6 @@ impl HashTableActor { &snowflake::ProcessUniqueId::new().to_string(), ).unwrap() } - } impl Actor for HashTableActor { @@ -197,59 +190,76 @@ impl Actor for HashTableActor { ) { println!("received {:?}", message); - sender.try_tell( - match message { - Protocol::HashTableSetup => Protocol::HashTableSetupResult(self.table.setup()), - Protocol::HashTableSetupResult(_) => unreachable!(), - - Protocol::HashTableTeardown => Protocol::HashTableTeardownResult(self.table.teardown()), - Protocol::HashTableTeardownResult(_) => unreachable!(), - - Protocol::HashTableCommit(pair) => Protocol::HashTableCommitResult(self.table.commit(&pair)), - Protocol::HashTableCommitResult(_) => unreachable!(), - - Protocol::HashTableGetPair(hash) => Protocol::HashTableGetPairResult(self.table.get(&hash)), - Protocol::HashTableGetPairResult(_) => unreachable!(), - - Protocol::HashTableModify{keys, old_pair, new_pair} => Protocol::HashTableModifyResult(self.table.modify(&keys, &old_pair, &new_pair)), - Protocol::HashTableModifyResult(_) => unreachable!(), - - Protocol::HashTableRetract{keys, pair} => Protocol::HashTableRetractResult(self.table.retract(&keys, &pair)), - Protocol::HashTableRetractResult(_) => unreachable!(), - - Protocol::HashTableAssertMeta(pair_meta) => Protocol::HashTableAssertMetaResult(self.table.assert_meta(&pair_meta)), - Protocol::HashTableAssertMetaResult(_) => unreachable!(), - - Protocol::HashTableGetMeta(key) => Protocol::HashTableGetMetaResult(self.table.get_meta(&key)), - Protocol::HashTableGetMetaResult(_) => unreachable!(), - - Protocol::HashTableGetPairMeta(pair) => Protocol::HashTableGetPairMetaResult(self.table.get_pair_meta(&pair)), - Protocol::HashTableGetPairMetaResult(_) => unreachable!(), - - _ => unreachable!(), - }, - Some(context.myself()), - ).unwrap(); - + sender + .try_tell( + match message { + Protocol::HashTableSetup => Protocol::HashTableSetupResult(self.table.setup()), + Protocol::HashTableSetupResult(_) => unreachable!(), + + Protocol::HashTableTeardown => { + Protocol::HashTableTeardownResult(self.table.teardown()) + } + Protocol::HashTableTeardownResult(_) => unreachable!(), + + Protocol::HashTableCommit(pair) => { + Protocol::HashTableCommitResult(self.table.commit(&pair)) + } + Protocol::HashTableCommitResult(_) => unreachable!(), + + Protocol::HashTableGetPair(hash) => { + Protocol::HashTableGetPairResult(self.table.get(&hash)) + } + Protocol::HashTableGetPairResult(_) => unreachable!(), + + Protocol::HashTableModify { + keys, + old_pair, + new_pair, + } => Protocol::HashTableModifyResult( + self.table.modify(&keys, &old_pair, &new_pair), + ), + Protocol::HashTableModifyResult(_) => unreachable!(), + + Protocol::HashTableRetract { keys, pair } => { + Protocol::HashTableRetractResult(self.table.retract(&keys, &pair)) + } + Protocol::HashTableRetractResult(_) => unreachable!(), + + Protocol::HashTableAssertMeta(pair_meta) => { + Protocol::HashTableAssertMetaResult(self.table.assert_meta(&pair_meta)) + } + Protocol::HashTableAssertMetaResult(_) => unreachable!(), + + Protocol::HashTableGetMeta(key) => { + Protocol::HashTableGetMetaResult(self.table.get_meta(&key)) + } + Protocol::HashTableGetMetaResult(_) => unreachable!(), + + Protocol::HashTableGetPairMeta(pair) => { + Protocol::HashTableGetPairMetaResult(self.table.get_pair_meta(&pair)) + } + Protocol::HashTableGetPairMetaResult(_) => unreachable!(), + + _ => unreachable!(), + }, + Some(context.myself()), + ) + .unwrap(); } - } #[cfg(test)] pub mod tests { use super::HashTableActor; - use hash_table::memory::tests::test_table; + use hash_table::{actor::Protocol, memory::tests::test_table}; use riker::actors::*; - use hash_table::actor::Protocol; pub fn test_table_actor() -> ActorRef { HashTableActor::new_ref(test_table()) } #[test] - fn round_trip() { - - } + fn round_trip() {} } diff --git a/core/src/hash_table/header.rs b/core/src/hash_table/header.rs index 55478ef080..9ed5201570 100644 --- a/core/src/hash_table/header.rs +++ b/core/src/hash_table/header.rs @@ -1,8 +1,7 @@ -use chain::Chain; +use chain::{Chain, SourceChain}; use hash; -use hash_table::{entry::Entry}; +use hash_table::entry::Entry; use multihash::Hash; -use chain::SourceChain; // @TODO - serialize properties as defined in HeadersEntrySchema from golang alpha 1 // @see https://github.com/holochain/holochain-proto/blob/4d1b8c8a926e79dfe8deaa7d759f930b66a5314f/entry_headers.go#L7 @@ -117,9 +116,8 @@ impl Header { #[cfg(test)] mod tests { - use chain::tests::test_chain; + use chain::{tests::test_chain, SourceChain}; use hash_table::{entry::Entry, header::Header, pair::tests::test_pair}; - use chain::SourceChain; /// returns a dummy header for use in tests pub fn test_header() -> Header { diff --git a/core/src/hash_table/mod.rs b/core/src/hash_table/mod.rs index d35ca0b6c5..53fa4b23ee 100644 --- a/core/src/hash_table/mod.rs +++ b/core/src/hash_table/mod.rs @@ -1,10 +1,10 @@ +pub mod actor; pub mod entry; pub mod header; pub mod memory; pub mod pair; pub mod pair_meta; pub mod status; -pub mod actor; use agent::keys::Keys; use error::HolochainError; diff --git a/core/src/hash_table/pair.rs b/core/src/hash_table/pair.rs index 8244422fec..1c1495e262 100644 --- a/core/src/hash_table/pair.rs +++ b/core/src/hash_table/pair.rs @@ -82,7 +82,7 @@ impl Pair { #[cfg(test)] pub mod tests { use super::Pair; - use chain::tests::test_chain; + use chain::{tests::test_chain, SourceChain}; use hash_table::{ entry::{ tests::{test_entry, test_entry_b}, @@ -90,7 +90,6 @@ pub mod tests { }, header::Header, }; - use chain::SourceChain; /// dummy pair pub fn test_pair() -> Pair { diff --git a/core/src/lib.rs b/core/src/lib.rs index 1e117707ae..cb78fae38f 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -11,10 +11,10 @@ extern crate test_utils; extern crate wasmi; #[macro_use] extern crate bitflags; +extern crate futures; extern crate riker; extern crate riker_default; extern crate riker_patterns; -extern crate futures; #[macro_use] extern crate lazy_static; #[macro_use] @@ -23,13 +23,13 @@ extern crate unwrap_to; extern crate num_derive; extern crate num_traits; +extern crate config; extern crate holochain_agent; extern crate holochain_dna; extern crate holochain_wasm_utils; -extern crate config; -pub mod actor; pub mod action; +pub mod actor; pub mod agent; pub mod chain; pub mod context; diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index 70b2fe6b38..c229606eac 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -74,20 +74,20 @@ mod tests { use super::GetArgs; use hash_table::entry::tests::{test_entry, test_entry_hash}; // use nucleus::ribosome::api::tests::test_zome_api_function_runtime; - use instance::tests::test_instance; use self::wabt::Wat2Wasm; - use nucleus::ribosome::api::commit::tests::test_commit_args_bytes; + use instance::tests::test_instance; + use nucleus::ribosome::api::{ + commit::tests::test_commit_args_bytes, + tests::{test_capability, test_zome_name}, + }; use serde_json; - use nucleus::ribosome::api::tests::test_zome_name; - use nucleus::ribosome::api::tests::test_capability; // use nucleus::ribosome::api::tests::test_zome_api_function_call; use instance::tests::test_context_and_logger; - use std::sync::Arc; - use nucleus::ribosome::api::tests::test_parameters; use nucleus::{ - ribosome::api::{call}, + ribosome::api::{call, tests::test_parameters}, FunctionCall, }; + use std::sync::Arc; /// dummy get args from standard test entry pub fn test_get_args_bytes() -> Vec { @@ -103,7 +103,7 @@ mod tests { .write_debug_names(true) .convert( // format!( - r#" + r#" (module (import "env" "get" (func $get @@ -145,7 +145,7 @@ mod tests { ) ) "#, - // canonical_name + // canonical_name // ), ) .unwrap() @@ -157,12 +157,20 @@ mod tests { /// test that we can round trip bytes through a get action and it comes back from wasm fn test_get_round_trip() { let wasm = test_get_round_trip_wat(); - let dna = - test_utils::create_test_dna_with_wasm(&test_zome_name(), &test_capability(), wasm.clone()); + let dna = test_utils::create_test_dna_with_wasm( + &test_zome_name(), + &test_capability(), + wasm.clone(), + ); let instance = test_instance(dna); let (context, _) = test_context_and_logger("joan"); - let commit_call = FunctionCall::new(&test_zome_name(), &test_capability(), &"commit", &test_parameters()); + let commit_call = FunctionCall::new( + &test_zome_name(), + &test_capability(), + &"commit", + &test_parameters(), + ); let commit_runtime = call( Arc::clone(&context), &instance.action_channel(), @@ -180,7 +188,12 @@ mod tests { // let (get_runtime, _) = test_zome_api_function_call(Arc::clone(&context), Arc::clone(&logger), &instance, &wasm, test_get_args_bytes()); - let get_call = FunctionCall::new(&test_zome_name(), &test_capability(), &"get", &test_parameters()); + let get_call = FunctionCall::new( + &test_zome_name(), + &test_capability(), + &"get", + &test_parameters(), + ); let get_runtime = call( Arc::clone(&context), &instance.action_channel(), diff --git a/core/src/nucleus/ribosome/api/mod.rs b/core/src/nucleus/ribosome/api/mod.rs index 48b57d1e47..00df8781fd 100644 --- a/core/src/nucleus/ribosome/api/mod.rs +++ b/core/src/nucleus/ribosome/api/mod.rs @@ -303,7 +303,11 @@ pub mod tests { use self::wabt::Wat2Wasm; extern crate test_utils; use super::ZomeAPIFunction; - use instance::tests::{test_context_and_logger, test_instance, TestLogger}; + use context::Context; + use instance::{ + tests::{test_context_and_logger, test_instance, TestLogger}, + Instance, + }; use nucleus::{ ribosome::api::{call, Runtime}, FunctionCall, @@ -312,8 +316,6 @@ pub mod tests { str::FromStr, sync::{Arc, Mutex}, }; - use context::Context; - use instance::Instance; use holochain_dna::zome::capabilities::ReservedCapabilityNames; @@ -426,7 +428,12 @@ pub mod tests { wasm: &Vec, args_bytes: Vec, ) -> (Runtime, Arc>) { - let fc = FunctionCall::new(&test_zome_name(), &test_capability(), &test_function_name(), &test_parameters()); + let fc = FunctionCall::new( + &test_zome_name(), + &test_capability(), + &test_function_name(), + &test_parameters(), + ); ( call( context, @@ -450,8 +457,11 @@ pub mod tests { args_bytes: Vec, ) -> (Runtime, Arc>) { let wasm = test_zome_api_function_wasm(canonical_name); - let dna = - test_utils::create_test_dna_with_wasm(&test_zome_name(), &test_capability(), wasm.clone()); + let dna = test_utils::create_test_dna_with_wasm( + &test_zome_name(), + &test_capability(), + wasm.clone(), + ); let instance = test_instance(dna); let (context, logger) = test_context_and_logger("joan"); diff --git a/core/src/state.rs b/core/src/state.rs index 89537b5c1e..b9f3e487cf 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -1,14 +1,14 @@ +use action::ActionWrapper; use agent::state::AgentState; +use chain::Chain; use context::Context; +use hash_table::memory::MemTable; use instance::Observer; use nucleus::state::NucleusState; use std::{ collections::HashSet, sync::{mpsc::Sender, Arc}, }; -use hash_table::memory::MemTable; -use action::ActionWrapper; -use chain::Chain; // use chain::actor::ChainActor; use hash_table::actor::HashTableActor; @@ -24,17 +24,11 @@ pub struct State { impl State { pub fn new() -> Self { // @TODO file table - // let chain_actor = ChainActor::new_ref( - let chain = Chain::new( - HashTableActor::new_ref( - MemTable::new(), - ), - ); - // ); + let chain = Chain::new(HashTableActor::new_ref(MemTable::new())); State { nucleus: Arc::new(NucleusState::new()), - agent: Arc::new(AgentState::new(chain)), + agent: Arc::new(AgentState::new(&chain)), history: HashSet::new(), } } From 569541cc5cbde24e496397c5e08ddf31e7ec21b5 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 19 Aug 2018 23:01:04 +1000 Subject: [PATCH 13/49] move actor system into hash table --- core/src/actor.rs | 83 ---------- core/src/agent/state.rs | 12 -- core/src/chain/mod.rs | 40 ++--- core/src/hash_table/actor.rs | 245 +++++++++++++++--------------- core/src/hash_table/memory/mod.rs | 1 - core/src/lib.rs | 1 - 6 files changed, 135 insertions(+), 247 deletions(-) delete mode 100644 core/src/actor.rs diff --git a/core/src/actor.rs b/core/src/actor.rs deleted file mode 100644 index a21e7c2210..0000000000 --- a/core/src/actor.rs +++ /dev/null @@ -1,83 +0,0 @@ -use agent::keys::Keys; -use error::HolochainError; -use hash_table::{entry::Entry, pair::Pair, pair_meta::PairMeta}; -use riker::actors::*; -use riker_default::DefaultModel; - -#[derive(Clone, Debug)] -pub enum Protocol { - ChainTopPair, - ChainTopPairResult(Option), - - ChainTopPairType(String), - ChainTopPairTypeResult(Option), - - ChainPushEntry(Entry), - ChainPushEntryResult(Result), - - ChainPushPair(Pair), - ChainPushPairResult(Result), - - ChainGetEntry(String), - ChainGetEntryResult(Result, HolochainError>), - - ChainGetPair(String), - ChainGetPairResult(Result, HolochainError>), - - /// HashTable::setup() - HashTableSetup, - HashTableSetupResult(Result<(), HolochainError>), - - /// HashTable::teardown() - HashTableTeardown, - HashTableTeardownResult(Result<(), HolochainError>), - - /// HashTable::modify() - HashTableModify { - keys: Keys, - old_pair: Pair, - new_pair: Pair, - }, - HashTableModifyResult(Result<(), HolochainError>), - - /// HashTable::retract() - HashTableRetract { - keys: Keys, - pair: Pair, - }, - HashTableRetractResult(Result<(), HolochainError>), - - /// HashTable::assert_meta() - HashTableAssertMeta(PairMeta), - HashTableAssertMetaResult(Result<(), HolochainError>), - - /// HashTable::get_meta() - HashTableGetMeta(String), - HashTableGetMetaResult(Result, HolochainError>), - - /// HashTable::get_pair_meta() - HashTableGetPairMeta(Pair), - HashTableGetPairMetaResult(Result, HolochainError>), - - /// HashTable::get() - HashTableGetPair(String), - HashTableGetPairResult(Result, HolochainError>), - - /// HashTable::commit() - HashTableCommit(Pair), - HashTableCommitResult(Result<(), HolochainError>), -} - -lazy_static! { - pub static ref SYS: ActorSystem = { - let model: DefaultModel = DefaultModel::new(); - // let hash_table_model = HashTableModel{}; - ActorSystem::new(&model).unwrap() - }; -} - -impl Into> for Protocol { - fn into(self) -> ActorMsg { - ActorMsg::User(self) - } -} diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index e19ffbb53a..9cc563f820 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -19,7 +19,6 @@ pub struct AgentState { keys: Option, // @TODO how should this work with chains/HTs? // @see https://github.com/holochain/holochain-rust/issues/137 - // @see https://github.com/holochain/holochain-rust/issues/135 top_pair: Option, /// every action and the result of that action // @TODO this will blow up memory, implement as some kind of dropping/FIFO with a limit? @@ -109,7 +108,6 @@ fn reduce_commit( action_wrapper.clone(), ActionResponse::Commit(state.chain.push_entry(&entry)), ); - println!("chain commit: {:?}", state.chain); } /// do a get action against an agent state @@ -121,20 +119,11 @@ fn reduce_get( _action_channel: &Sender, _observer_channel: &Sender, ) { - println!("chain get: {:?}", state.chain); - let action = action_wrapper.action(); let key = unwrap_to!(action => Action::Get); let result = state.chain.get_entry(&key.clone()); - println!("result: {:?}", result); - - // let response = state.chain.ask( - // Protocol::ChainGetEntry(key.clone()), - // ); - // let result = unwrap_to!(response => Protocol::ChainGetEntryResult); - // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 @@ -172,7 +161,6 @@ pub fn reduce( action_channel, observer_channel, ); - println!("reduce: {:?}", new_state.chain); Arc::new(new_state) } None => old_state, diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index d28d6df5f0..f7487eed23 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,23 +1,24 @@ -use actor::Protocol; use error::HolochainError; -use hash_table::{actor::AskHashTable, entry::Entry, pair::Pair, HashTable}; +use hash_table::{ + actor::{AskHashTable, HashTableProtocol}, + entry::Entry, + pair::Pair, + HashTable, +}; use riker::actors::*; use serde_json; use std::fmt; -// use futures::executor::block_on; #[derive(Clone)] pub struct ChainIterator { - table: ActorRef, + table: ActorRef, current: Option, } impl ChainIterator { - // @TODO table implementation is changing anyway so waste of time to mess with ref/value - // @see https://github.com/holochain/holochain-rust/issues/135 #[allow(unknown_lints)] #[allow(needless_pass_by_value)] - pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { + pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { ChainIterator { current: pair.clone(), table: table.clone(), @@ -35,16 +36,11 @@ impl Iterator for ChainIterator { fn next(&mut self) -> Option { let ret = self.current(); - println!("next current: {:?}", ret); self.current = ret.clone() .and_then(|p| p.header().next()) // @TODO should this panic? // @see https://github.com/holochain/holochain-rust/issues/146 .and_then(|h| { - // let response = self.table.ask(Protocol::HashTableGetPair(h.to_string())); - // let result = unwrap_to!(response => Protocol::HashTableGetPairResult); - // println!("next: {:?}", result); - // result.clone().unwrap() self.table.get(&h.to_string()).unwrap() }); ret @@ -53,9 +49,7 @@ impl Iterator for ChainIterator { #[derive(Clone)] pub struct Chain { - // @TODO thread safe table references - // @see https://github.com/holochain/holochain-rust/issues/135 - table: ActorRef, + table: ActorRef, top_pair: Option, } @@ -87,7 +81,7 @@ impl IntoIterator for Chain { } impl Chain { - pub fn new(table: ActorRef) -> Chain { + pub fn new(table: ActorRef) -> Chain { Chain { top_pair: None, table: table.clone(), @@ -95,7 +89,7 @@ impl Chain { } /// returns a reference to the underlying HashTable - pub fn table(&self) -> ActorRef { + pub fn table(&self) -> ActorRef { self.table.clone() } @@ -106,7 +100,6 @@ impl Chain { /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable fn iter(&self) -> ChainIterator { - println!("at iter: {:?}", self); ChainIterator::new(self.table(), &self.top_pair()) } @@ -121,7 +114,7 @@ impl Chain { /// restore canonical JSON chain /// @TODO accept canonical JSON /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn from_json(table: ActorRef, s: &str) -> Chain { + pub fn from_json(table: ActorRef, s: &str) -> Chain { // @TODO inappropriate unwrap? // @see https://github.com/holochain/holochain-rust/issues/168 let mut as_seq: Vec = serde_json::from_str(s).unwrap(); @@ -131,9 +124,6 @@ impl Chain { for p in as_seq { chain.push_pair(&p).unwrap(); - // let response = chain.ask(ChainProtocol::PushPair(p)); - // let result = unwrap_to!(response => ChainProtocol::PushResult); - // result.clone().unwrap(); } chain } @@ -175,7 +165,6 @@ impl SourceChain for Chain { self.top_pair = Some(pair.clone()); } - println!("after commit: {:?}", self); match result { Ok(_) => Ok(pair.clone()), Err(e) => Err(e.clone()), @@ -193,13 +182,12 @@ impl SourceChain for Chain { /// get a Pair by Pair/Header key from the HashTable if it exists fn get_pair(&self, k: &str) -> Result, HolochainError> { - let response = self.table.ask(Protocol::HashTableGetPair(k.to_string())); - unwrap_to!(response => Protocol::HashTableGetPairResult).clone() + let response = self.table.ask(HashTableProtocol::GetPair(k.to_string())); + unwrap_to!(response => HashTableProtocol::GetPairResult).clone() } /// get an Entry by Entry key from the HashTable if it exists fn get_entry(&self, entry_hash: &str) -> Result, HolochainError> { - println!("get entry: {:?}", entry_hash); // @TODO - this is a slow way to do a lookup // @see https://github.com/holochain/holochain-rust/issues/50 Ok(self diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 2a961d9b09..37b0ef1558 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -3,8 +3,10 @@ use error::HolochainError; use futures::executor::block_on; use hash_table::{pair::Pair, pair_meta::PairMeta, HashTable}; use riker::actors::*; +use riker_default::DefaultModel; use riker_patterns::ask::ask; use snowflake; + // use riker::kernel::Dispatcher; // use futures::{Future}; // use riker::futures_util::spawn; @@ -16,103 +18,100 @@ use snowflake; // use riker_patterns::ask::Ask; // use futures::channel::oneshot::Canceled; // use futures::Async::Ready; -use actor::{Protocol, SYS}; // use futures::executor::spawn_with_handle; // use futures::executor::SpawnWithHandle; -// struct HashTableModel; -// -// // @see https://github.com/riker-rs/riker/blob/master/riker-default/riker-dispatcher/src/lib.rs -// pub struct HashTableDispatcher { -// inner: ThreadPool, -// } -// -// impl Dispatcher for HashTableDispatcher { -// fn new(_config: &Config, _: bool) -> HashTableDispatcher { -// HashTableDispatcher { -// inner: ThreadPoolBuilder::new() -// .pool_size(4) -// .name_prefix("pool-thread-hash-table-#") -// .create() -// .unwrap() -// } -// } -// -// fn execute(&mut self, f: F) -// where F: Future + Send + 'static -// { -// self.inner.run(spawn(f)).unwrap(); -// } -// } -// -// impl Model for HashTableModel { -// type Msg = Protocol; -// type Dis = HashTableDispatcher; -// type Ded = DeadLettersActor; -// type Tmr = BasicTimer; -// type Evs = MapVec; -// type Tcp = NoIo; -// type Udp = NoIo; -// type Log = SimpleLogger; -// } - -// lazy_static! { -// pub static ref HASH_TABLE_SYS: ActorSystem HashTable= { -// let hash_table_model: DefaultModel HashTable= DefaultModel::new(); -// // let hash_table_model = HashTableModel{}; -// ActorSystem::new(&hash_table_model).unwrap() -// }; -// } - -// impl Into> for Protocol { -// fn into(self) -> ActorMsg { -// ActorMsg::User(self) -// } -// } - -// type HTAsk = Box + Send>; +#[derive(Clone, Debug)] +pub enum HashTableProtocol { + /// HashTable::setup() + Setup, + SetupResult(Result<(), HolochainError>), + + /// HashTable::teardown() + Teardown, + TeardownResult(Result<(), HolochainError>), + + /// HashTable::modify() + Modify { + keys: Keys, + old_pair: Pair, + new_pair: Pair, + }, + ModifyResult(Result<(), HolochainError>), + + /// HashTable::retract() + Retract { + keys: Keys, + pair: Pair, + }, + RetractResult(Result<(), HolochainError>), + + /// HashTable::assert_meta() + AssertMeta(PairMeta), + AssertMetaResult(Result<(), HolochainError>), + + /// HashTable::get_meta() + GetMeta(String), + GetMetaResult(Result, HolochainError>), + + /// HashTable::get_pair_meta() + GetPairMeta(Pair), + GetPairMetaResult(Result, HolochainError>), + + /// HashTable::get() + GetPair(String), + GetPairResult(Result, HolochainError>), + + /// HashTable::commit() + Commit(Pair), + CommitResult(Result<(), HolochainError>), +} + +lazy_static! { + pub static ref HASH_TABLE_SYS: ActorSystem = { + let hash_table_model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&hash_table_model).unwrap() + }; +} + +impl Into> for HashTableProtocol { + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } +} /// anything that can be asked Protocol aHashTablend block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskHashTable { - fn ask(&self, message: Protocol) -> Protocol; + fn ask(&self, message: HashTableProtocol) -> HashTableProtocol; } -impl AskHashTable for ActorRef { - fn ask(&self, message: Protocol) -> Protocol { - let a = ask(&(*SYS), self, message); - // loop { - // match a.poll(context)? { - // Ready(v) => break v, - // _ => println!("polling"), - // } - // } - // println!("{:?}", &(*HASH_TABLE_SYS); - // println!("asking table"); +impl AskHashTable for ActorRef { + fn ask(&self, message: HashTableProtocol) -> HashTableProtocol { + let a = ask(&(*HASH_TABLE_SYS), self, message); block_on(a).unwrap() - // spawn_with_handle(a) } } -impl HashTable for ActorRef { +impl HashTable for ActorRef { fn setup(&mut self) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableSetup); - unwrap_to!(response => Protocol::HashTableSetupResult).clone() + let response = self.ask(HashTableProtocol::Setup); + unwrap_to!(response => HashTableProtocol::SetupResult).clone() } fn teardown(&mut self) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableTeardown); - unwrap_to!(response => Protocol::HashTableTeardownResult).clone() + let response = self.ask(HashTableProtocol::Teardown); + unwrap_to!(response => HashTableProtocol::TeardownResult).clone() } fn commit(&mut self, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableCommit(pair.clone())); - unwrap_to!(response => Protocol::HashTableCommitResult).clone() + let response = self.ask(HashTableProtocol::Commit(pair.clone())); + unwrap_to!(response => HashTableProtocol::CommitResult).clone() } fn get(&self, key: &str) -> Result, HolochainError> { - let response = self.ask(Protocol::HashTableGetPair(key.to_string())); - unwrap_to!(response => Protocol::HashTableGetPairResult).clone() + let response = self.ask(HashTableProtocol::GetPair(key.to_string())); + unwrap_to!(response => HashTableProtocol::GetPairResult).clone() } fn modify( @@ -121,35 +120,35 @@ impl HashTable for ActorRef { old_pair: &Pair, new_pair: &Pair, ) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableModify { + let response = self.ask(HashTableProtocol::Modify { keys: keys.clone(), old_pair: old_pair.clone(), new_pair: new_pair.clone(), }); - unwrap_to!(response => Protocol::HashTableModifyResult).clone() + unwrap_to!(response => HashTableProtocol::ModifyResult).clone() } fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableRetract { + let response = self.ask(HashTableProtocol::Retract { keys: keys.clone(), pair: pair.clone(), }); - unwrap_to!(response => Protocol::HashTableRetractResult).clone() + unwrap_to!(response => HashTableProtocol::RetractResult).clone() } fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError> { - let response = self.ask(Protocol::HashTableAssertMeta(meta.clone())); - unwrap_to!(response => Protocol::HashTableAssertMetaResult).clone() + let response = self.ask(HashTableProtocol::AssertMeta(meta.clone())); + unwrap_to!(response => HashTableProtocol::AssertMetaResult).clone() } fn get_meta(&mut self, key: &str) -> Result, HolochainError> { - let response = self.ask(Protocol::HashTableGetMeta(key.to_string())); - unwrap_to!(response => Protocol::HashTableGetMetaResult).clone() + let response = self.ask(HashTableProtocol::GetMeta(key.to_string())); + unwrap_to!(response => HashTableProtocol::GetMetaResult).clone() } fn get_pair_meta(&mut self, pair: &Pair) -> Result, HolochainError> { - let response = self.ask(Protocol::HashTableGetPairMeta(pair.clone())); - unwrap_to!(response => Protocol::HashTableGetPairMetaResult).clone() + let response = self.ask(HashTableProtocol::GetPairMeta(pair.clone())); + unwrap_to!(response => HashTableProtocol::GetPairMetaResult).clone() } } @@ -163,24 +162,26 @@ impl HashTableActor { HashTableActor { table } } - pub fn actor(table: HT) -> BoxActor { + pub fn actor(table: HT) -> BoxActor { Box::new(HashTableActor::new(table)) } - pub fn props(table: HT) -> BoxActorProd { + pub fn props(table: HT) -> BoxActorProd { Props::new_args(Box::new(HashTableActor::actor), table) } - pub fn new_ref(table: HT) -> ActorRef { - SYS.actor_of( - HashTableActor::props(table), - &snowflake::ProcessUniqueId::new().to_string(), - ).unwrap() + pub fn new_ref(table: HT) -> ActorRef { + HASH_TABLE_SYS + .actor_of( + HashTableActor::props(table), + &snowflake::ProcessUniqueId::new().to_string(), + ) + .unwrap() } } impl Actor for HashTableActor { - type Msg = Protocol; + type Msg = HashTableProtocol; fn receive( &mut self, @@ -188,59 +189,55 @@ impl Actor for HashTableActor { message: Self::Msg, sender: Option>, ) { - println!("received {:?}", message); - sender .try_tell( match message { - Protocol::HashTableSetup => Protocol::HashTableSetupResult(self.table.setup()), - Protocol::HashTableSetupResult(_) => unreachable!(), + HashTableProtocol::Setup => HashTableProtocol::SetupResult(self.table.setup()), + HashTableProtocol::SetupResult(_) => unreachable!(), - Protocol::HashTableTeardown => { - Protocol::HashTableTeardownResult(self.table.teardown()) + HashTableProtocol::Teardown => { + HashTableProtocol::TeardownResult(self.table.teardown()) } - Protocol::HashTableTeardownResult(_) => unreachable!(), + HashTableProtocol::TeardownResult(_) => unreachable!(), - Protocol::HashTableCommit(pair) => { - Protocol::HashTableCommitResult(self.table.commit(&pair)) + HashTableProtocol::Commit(pair) => { + HashTableProtocol::CommitResult(self.table.commit(&pair)) } - Protocol::HashTableCommitResult(_) => unreachable!(), + HashTableProtocol::CommitResult(_) => unreachable!(), - Protocol::HashTableGetPair(hash) => { - Protocol::HashTableGetPairResult(self.table.get(&hash)) + HashTableProtocol::GetPair(hash) => { + HashTableProtocol::GetPairResult(self.table.get(&hash)) } - Protocol::HashTableGetPairResult(_) => unreachable!(), + HashTableProtocol::GetPairResult(_) => unreachable!(), - Protocol::HashTableModify { + HashTableProtocol::Modify { keys, old_pair, new_pair, - } => Protocol::HashTableModifyResult( + } => HashTableProtocol::ModifyResult( self.table.modify(&keys, &old_pair, &new_pair), ), - Protocol::HashTableModifyResult(_) => unreachable!(), + HashTableProtocol::ModifyResult(_) => unreachable!(), - Protocol::HashTableRetract { keys, pair } => { - Protocol::HashTableRetractResult(self.table.retract(&keys, &pair)) + HashTableProtocol::Retract { keys, pair } => { + HashTableProtocol::RetractResult(self.table.retract(&keys, &pair)) } - Protocol::HashTableRetractResult(_) => unreachable!(), + HashTableProtocol::RetractResult(_) => unreachable!(), - Protocol::HashTableAssertMeta(pair_meta) => { - Protocol::HashTableAssertMetaResult(self.table.assert_meta(&pair_meta)) + HashTableProtocol::AssertMeta(pair_meta) => { + HashTableProtocol::AssertMetaResult(self.table.assert_meta(&pair_meta)) } - Protocol::HashTableAssertMetaResult(_) => unreachable!(), + HashTableProtocol::AssertMetaResult(_) => unreachable!(), - Protocol::HashTableGetMeta(key) => { - Protocol::HashTableGetMetaResult(self.table.get_meta(&key)) + HashTableProtocol::GetMeta(key) => { + HashTableProtocol::GetMetaResult(self.table.get_meta(&key)) } - Protocol::HashTableGetMetaResult(_) => unreachable!(), + HashTableProtocol::GetMetaResult(_) => unreachable!(), - Protocol::HashTableGetPairMeta(pair) => { - Protocol::HashTableGetPairMetaResult(self.table.get_pair_meta(&pair)) + HashTableProtocol::GetPairMeta(pair) => { + HashTableProtocol::GetPairMetaResult(self.table.get_pair_meta(&pair)) } - Protocol::HashTableGetPairMetaResult(_) => unreachable!(), - - _ => unreachable!(), + HashTableProtocol::GetPairMetaResult(_) => unreachable!(), }, Some(context.myself()), ) @@ -252,10 +249,10 @@ impl Actor for HashTableActor { pub mod tests { use super::HashTableActor; - use hash_table::{actor::Protocol, memory::tests::test_table}; + use hash_table::{actor::HashTableProtocol, memory::tests::test_table}; use riker::actors::*; - pub fn test_table_actor() -> ActorRef { + pub fn test_table_actor() -> ActorRef { HashTableActor::new_ref(test_table()) } diff --git a/core/src/hash_table/memory/mod.rs b/core/src/hash_table/memory/mod.rs index f7be75437e..19e05f9c66 100644 --- a/core/src/hash_table/memory/mod.rs +++ b/core/src/hash_table/memory/mod.rs @@ -40,7 +40,6 @@ impl HashTable for MemTable { } fn get(&self, key: &str) -> Result, HolochainError> { - println!("get: {:?}", key); Ok(self.pairs.get(key).and_then(|p| Some(p.clone()))) } diff --git a/core/src/lib.rs b/core/src/lib.rs index cb78fae38f..b3eb2dff48 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -29,7 +29,6 @@ extern crate holochain_dna; extern crate holochain_wasm_utils; pub mod action; -pub mod actor; pub mod agent; pub mod chain; pub mod context; From 39c0e6671431d58b671f4a04a42c010c3224585c Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 19 Aug 2018 23:01:39 +1000 Subject: [PATCH 14/49] lint --- core/src/agent/state.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 9cc563f820..23d56a1d11 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -1,7 +1,6 @@ use action::{Action, ActionWrapper, AgentReduceFn}; use agent::keys::Keys; use instance::Observer; -// use riker::actors::*; use context::Context; use error::HolochainError; use hash_table::pair::Pair; @@ -9,8 +8,6 @@ use std::{ collections::HashMap, sync::{mpsc::Sender, Arc}, }; -// use actor::Protocol; -// use chain::actor::AskChain; use chain::{Chain, SourceChain}; #[derive(Clone, Debug, PartialEq)] From c1d922f9120efd864888afcebc1e1a0e42cbb439 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 19 Aug 2018 23:10:34 +1000 Subject: [PATCH 15/49] lint --- core/src/hash_table/actor.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 37b0ef1558..30c195d9a5 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -7,20 +7,6 @@ use riker_default::DefaultModel; use riker_patterns::ask::ask; use snowflake; -// use riker::kernel::Dispatcher; -// use futures::{Future}; -// use riker::futures_util::spawn; -// use riker_default::DeadLettersActor; -// use riker_default::BasicTimer; -// use riker_default::MapVec; -// use riker_default::SimpleLogger; -// use riker::system::NoIo; -// use riker_patterns::ask::Ask; -// use futures::channel::oneshot::Canceled; -// use futures::Async::Ready; -// use futures::executor::spawn_with_handle; -// use futures::executor::SpawnWithHandle; - #[derive(Clone, Debug)] pub enum HashTableProtocol { /// HashTable::setup() From 8605b34a88cb7c3a69e869a15a4a5a8fdb5d8f1b Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 19 Aug 2018 23:15:30 +1000 Subject: [PATCH 16/49] lint --- core/src/nucleus/ribosome/api/get.rs | 8 -------- core/src/state.rs | 1 - 2 files changed, 9 deletions(-) diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index c229606eac..fb4ee2bccd 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -73,7 +73,6 @@ mod tests { use super::GetArgs; use hash_table::entry::tests::{test_entry, test_entry_hash}; - // use nucleus::ribosome::api::tests::test_zome_api_function_runtime; use self::wabt::Wat2Wasm; use instance::tests::test_instance; use nucleus::ribosome::api::{ @@ -81,7 +80,6 @@ mod tests { tests::{test_capability, test_zome_name}, }; use serde_json; - // use nucleus::ribosome::api::tests::test_zome_api_function_call; use instance::tests::test_context_and_logger; use nucleus::{ ribosome::api::{call, tests::test_parameters}, @@ -102,7 +100,6 @@ mod tests { .canonicalize_lebs(false) .write_debug_names(true) .convert( - // format!( r#" (module (import "env" "get" @@ -145,8 +142,6 @@ mod tests { ) ) "#, - // canonical_name - // ), ) .unwrap() .as_ref() @@ -180,14 +175,11 @@ mod tests { Some(test_commit_args_bytes()), ).expect("test should be callable"); - // let (commit_runtime, _) = test_zome_api_function_call(Arc::clone(&context), Arc::clone(&logger), &instance, &wasm, test_commit_args_bytes()); assert_eq!( commit_runtime.result, format!(r#"{{"hash":"{}"}}"#, test_entry().key()) + "\u{0}", ); - // let (get_runtime, _) = test_zome_api_function_call(Arc::clone(&context), Arc::clone(&logger), &instance, &wasm, test_get_args_bytes()); - let get_call = FunctionCall::new( &test_zome_name(), &test_capability(), diff --git a/core/src/state.rs b/core/src/state.rs index b9f3e487cf..8f9955b3d7 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -9,7 +9,6 @@ use std::{ collections::HashSet, sync::{mpsc::Sender, Arc}, }; -// use chain::actor::ChainActor; use hash_table::actor::HashTableActor; #[derive(Clone, PartialEq, Debug)] From 5cefae031904a9c165936a545041eebda3e2de99 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 19 Aug 2018 23:16:00 +1000 Subject: [PATCH 17/49] fmt --- core/src/agent/state.rs | 4 ++-- core/src/nucleus/ribosome/api/get.rs | 17 ++++++++--------- core/src/state.rs | 3 +-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 23d56a1d11..44408c32e5 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -1,14 +1,14 @@ use action::{Action, ActionWrapper, AgentReduceFn}; use agent::keys::Keys; -use instance::Observer; +use chain::{Chain, SourceChain}; use context::Context; use error::HolochainError; use hash_table::pair::Pair; +use instance::Observer; use std::{ collections::HashMap, sync::{mpsc::Sender, Arc}, }; -use chain::{Chain, SourceChain}; #[derive(Clone, Debug, PartialEq)] /// struct to track the internal state of an agent exposed to reducers/observers diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index fb4ee2bccd..1d39177728 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -71,20 +71,19 @@ mod tests { extern crate test_utils; extern crate wabt; + use self::wabt::Wat2Wasm; use super::GetArgs; use hash_table::entry::tests::{test_entry, test_entry_hash}; - use self::wabt::Wat2Wasm; - use instance::tests::test_instance; - use nucleus::ribosome::api::{ - commit::tests::test_commit_args_bytes, - tests::{test_capability, test_zome_name}, - }; - use serde_json; - use instance::tests::test_context_and_logger; + use instance::tests::{test_context_and_logger, test_instance}; use nucleus::{ - ribosome::api::{call, tests::test_parameters}, + ribosome::api::{ + call, + commit::tests::test_commit_args_bytes, + tests::{test_capability, test_parameters, test_zome_name}, + }, FunctionCall, }; + use serde_json; use std::sync::Arc; /// dummy get args from standard test entry diff --git a/core/src/state.rs b/core/src/state.rs index 8f9955b3d7..93af6173c4 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -2,14 +2,13 @@ use action::ActionWrapper; use agent::state::AgentState; use chain::Chain; use context::Context; -use hash_table::memory::MemTable; +use hash_table::{actor::HashTableActor, memory::MemTable}; use instance::Observer; use nucleus::state::NucleusState; use std::{ collections::HashSet, sync::{mpsc::Sender, Arc}, }; -use hash_table::actor::HashTableActor; #[derive(Clone, PartialEq, Debug)] pub struct State { From dcab7002f9aec7d4a052a7b77b8a63f62fe57744 Mon Sep 17 00:00:00 2001 From: David Meister Date: Mon, 20 Aug 2018 21:50:59 +1000 Subject: [PATCH 18/49] test for hash table round trip in threads --- core/src/agent/state.rs | 5 ---- core/src/hash_table/actor.rs | 53 +++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 44408c32e5..cd285b640a 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -276,11 +276,6 @@ pub mod tests { assert_eq!(state.actions().get(&aw2), Some(&test_action_response_get()),); } - #[test] - fn test_round_trip_threads() { - // @TODO - } - #[test] /// test response to json fn test_response_to_json() { diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 30c195d9a5..d4dfc20f19 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -237,12 +237,63 @@ pub mod tests { use super::HashTableActor; use hash_table::{actor::HashTableProtocol, memory::tests::test_table}; use riker::actors::*; + use hash::tests::test_hash; + use hash_table::HashTable; + use hash_table::pair::tests::test_pair; + use std::thread; + use std::sync::mpsc; pub fn test_table_actor() -> ActorRef { HashTableActor::new_ref(test_table()) } #[test] - fn round_trip() {} + fn round_trip() { + let mut table_actor = test_table_actor(); + + assert_eq!( + table_actor.get(&test_hash()).unwrap(), + None, + ); + + table_actor.commit(&test_pair()).unwrap(); + + assert_eq!( + table_actor.get(&test_pair().key()).unwrap(), + Some(test_pair()), + ); + } + + #[test] + fn test_round_trip_threads() { + let table_actor = test_table_actor(); + + let table_actor_thread = table_actor.clone(); + let (tx1, rx1) = mpsc::channel(); + thread::spawn(move || { + assert_eq!( + table_actor_thread.get(&test_hash()).unwrap(), + None, + ); + tx1.send(true).unwrap(); + }); + + let mut table_actor_thread = table_actor.clone(); + let (tx2, rx2) = mpsc::channel(); + thread::spawn(move || { + rx1.recv().unwrap(); + table_actor_thread.commit(&test_pair()).unwrap(); + tx2.send(true).unwrap(); + }); + + let table_actor_thread = table_actor.clone(); + thread::spawn(move || { + rx2.recv().unwrap(); + assert_eq!( + table_actor_thread.get(&test_pair().key()).unwrap(), + Some(test_pair()), + ); + }); + } } From cb8324e9605e729f4c12952aff02316b339a0ce4 Mon Sep 17 00:00:00 2001 From: David Meister Date: Mon, 20 Aug 2018 21:56:08 +1000 Subject: [PATCH 19/49] pass the test pair through the channel for the round trip --- core/src/hash_table/actor.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index d4dfc20f19..cd41435e9f 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -282,18 +282,21 @@ pub mod tests { let (tx2, rx2) = mpsc::channel(); thread::spawn(move || { rx1.recv().unwrap(); - table_actor_thread.commit(&test_pair()).unwrap(); - tx2.send(true).unwrap(); + let pair = test_pair(); + table_actor_thread.commit(&pair).unwrap(); + tx2.send(pair).unwrap(); }); let table_actor_thread = table_actor.clone(); - thread::spawn(move || { - rx2.recv().unwrap(); + let handle = thread::spawn(move || { + let pair = rx2.recv().unwrap(); assert_eq!( - table_actor_thread.get(&test_pair().key()).unwrap(), + table_actor_thread.get(&pair.key()).unwrap(), Some(test_pair()), ); }); + + handle.join().unwrap(); } } From 13d010b3660e47c25e3e998b3125b6d5b7aec49d Mon Sep 17 00:00:00 2001 From: David Meister Date: Mon, 20 Aug 2018 22:29:12 +1000 Subject: [PATCH 20/49] fmt --- core/src/hash_table/actor.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index cd41435e9f..dfee8359a2 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -265,6 +265,11 @@ pub mod tests { } #[test] + /// we want to show two things here: + /// - we can clone some stateful thing (i.e. actor ref) and mutate one clone and have that + /// consistent across all the clones + /// - we can send the cloned stateful thing into threads and have them see a consistent world + /// view without juggling direct message passing through channels fn test_round_trip_threads() { let table_actor = test_table_actor(); @@ -275,15 +280,18 @@ pub mod tests { table_actor_thread.get(&test_hash()).unwrap(), None, ); + // kick off the next thread tx1.send(true).unwrap(); }); + // mutate this clone of the original actor ref let mut table_actor_thread = table_actor.clone(); let (tx2, rx2) = mpsc::channel(); thread::spawn(move || { rx1.recv().unwrap(); let pair = test_pair(); table_actor_thread.commit(&pair).unwrap(); + // push the committed pair through to the next thread tx2.send(pair).unwrap(); }); @@ -292,7 +300,7 @@ pub mod tests { let pair = rx2.recv().unwrap(); assert_eq!( table_actor_thread.get(&pair.key()).unwrap(), - Some(test_pair()), + Some(pair), ); }); From fa8ef92f8d2b14105ba4889e600c690783454c84 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 21 Aug 2018 00:00:14 +1000 Subject: [PATCH 21/49] WIP on clone safety for chain --- core/src/agent/state.rs | 17 +---- core/src/chain/actor.rs | 114 ++++++++++++++++++++++++++++++++++ core/src/chain/mod.rs | 70 +++++++++++++++------ core/src/hash_table/actor.rs | 9 +-- core/src/hash_table/header.rs | 2 +- 5 files changed, 174 insertions(+), 38 deletions(-) create mode 100644 core/src/chain/actor.rs diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index cd285b640a..72e97e88f6 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -14,9 +14,6 @@ use std::{ /// struct to track the internal state of an agent exposed to reducers/observers pub struct AgentState { keys: Option, - // @TODO how should this work with chains/HTs? - // @see https://github.com/holochain/holochain-rust/issues/137 - top_pair: Option, /// every action and the result of that action // @TODO this will blow up memory, implement as some kind of dropping/FIFO with a limit? // @see https://github.com/holochain/holochain-rust/issues/166 @@ -29,7 +26,6 @@ impl AgentState { pub fn new(chain: &Chain) -> AgentState { AgentState { keys: None, - top_pair: None, actions: HashMap::new(), chain: chain.clone(), } @@ -40,10 +36,9 @@ impl AgentState { self.keys.clone() } - /// getter for a copy of self.top_pair - /// should be used with a source chain for validation/safety - pub fn top_pair(&self) -> Option { - self.top_pair.clone() + /// getter for the chain + pub fn chain(&self) -> Chain { + self.chain.clone() } /// getter for a copy of self.actions @@ -201,12 +196,6 @@ pub mod tests { assert_eq!(None, test_agent_state().keys()); } - #[test] - /// test for the agent state top pair getter - fn agent_state_top_pair() { - assert_eq!(None, test_agent_state().top_pair()); - } - #[test] /// test for the agent state actions getter fn agent_state_actions() { diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs new file mode 100644 index 0000000000..e2ec36c0f3 --- /dev/null +++ b/core/src/chain/actor.rs @@ -0,0 +1,114 @@ +use riker_default::DefaultModel; +use riker::actors::*; +use snowflake; +use hash_table::pair::Pair; +use error::HolochainError; +use riker_patterns::ask::ask; +use futures::executor::block_on; + +#[derive(Clone, Debug)] +pub enum ChainProtocol { + SetTopPair(Option), + SetTopPairResult(Result, HolochainError>), + + GetTopPair, + GetTopPairResult(Option), +} + +lazy_static! { + // @TODO Riker docs say make only one actor system per application but this seems weird advice + // if that were true, how could actors be in crates? + // if that were true, how could we have domain specific protocols? + pub static ref CHAIN_SYS: ActorSystem = { + let model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&model).unwrap() + }; +} + +impl Into> for ChainProtocol { + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } +} + +/// anything that can be asked of Chain and block on responses +/// needed to support implementing ask on upstream ActorRef from riker +pub trait AskChain { + fn ask(&self, message: ChainProtocol) -> ChainProtocol; + fn set_top_pair(&self, &Option) -> Result, HolochainError>; + fn get_top_pair(&self) -> Option; +} + +impl AskChain for ActorRef { + fn ask(&self, message: ChainProtocol) -> ChainProtocol { + let a = ask(&(*CHAIN_SYS), self, message); + block_on(a).unwrap() + } + + fn set_top_pair(&self, pair: &Option) -> Result, HolochainError> { + let response = self.ask(ChainProtocol::SetTopPair(pair.clone())); + unwrap_to!(response => ChainProtocol::SetTopPairResult).clone() + } + + fn get_top_pair(&self) -> Option { + let response = self.ask(ChainProtocol::GetTopPair); + unwrap_to!(response => ChainProtocol::GetTopPairResult).clone() + } +} + +pub struct ChainActor { + top_pair: Option, +} + +impl ChainActor { + pub fn new() -> ChainActor { + ChainActor { + top_pair: None, + } + } + + pub fn actor() -> BoxActor { + Box::new(ChainActor::new()) + } + + pub fn props() -> BoxActorProd { + Props::new(Box::new(ChainActor::actor)) + } + + pub fn new_ref() -> ActorRef { + CHAIN_SYS + .actor_of( + ChainActor::props(), + &snowflake::ProcessUniqueId::new().to_string(), + ) + .unwrap() + } +} + +impl Actor for ChainActor { + type Msg = ChainProtocol; + + fn receive( + &mut self, + context: &Context, + message: Self::Msg, + sender: Option>, + ) { + sender.try_tell( + // deliberately exhaustively matching here, don't give into _ temptation + match message { + ChainProtocol::SetTopPair(p) => { + self.top_pair = p; + ChainProtocol::SetTopPairResult(Ok(self.top_pair.clone())) + }, + ChainProtocol::SetTopPairResult(_) => unreachable!(), + + ChainProtocol::GetTopPair => ChainProtocol::GetTopPairResult(self.top_pair.clone()), + ChainProtocol::GetTopPairResult(_) => unreachable!(), + }, + Some(context.myself()), + ) + .unwrap(); + } + +} diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index f7487eed23..82c6fbb720 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,3 +1,5 @@ +pub mod actor; + use error::HolochainError; use hash_table::{ actor::{AskHashTable, HashTableProtocol}, @@ -8,6 +10,9 @@ use hash_table::{ use riker::actors::*; use serde_json; use std::fmt; +use chain::actor::ChainActor; +use chain::actor::ChainProtocol; +use chain::actor::AskChain; #[derive(Clone)] pub struct ChainIterator { @@ -49,17 +54,18 @@ impl Iterator for ChainIterator { #[derive(Clone)] pub struct Chain { + actor: ActorRef, table: ActorRef, - top_pair: Option, } impl PartialEq for Chain { + // @TODO can we just check the actors are equal? is actor equality a thing? fn eq(&self, other: &Chain) -> bool { // an invalid chain is like NaN... not even equal to itself self.validate() && other.validate() && // header hashing ensures that if the tops match the whole chain matches - self.top_pair() == other.top_pair() + self.get_top_pair() == other.get_top_pair() } } @@ -67,7 +73,7 @@ impl Eq for Chain {} impl fmt::Debug for Chain { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Chain {{ top: {:?} }}", self.top_pair) + write!(f, "Chain {{ top: {:?} }}", self.get_top_pair()) } } @@ -83,7 +89,7 @@ impl IntoIterator for Chain { impl Chain { pub fn new(table: ActorRef) -> Chain { Chain { - top_pair: None, + actor: ChainActor::new_ref(), table: table.clone(), } } @@ -100,7 +106,7 @@ impl Chain { /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable fn iter(&self) -> ChainIterator { - ChainIterator::new(self.table(), &self.top_pair()) + ChainIterator::new(self.table(), &self.get_top_pair()) } /// get the entire chain, top to bottom as a JSON array or canonical pairs @@ -131,8 +137,12 @@ impl Chain { impl SourceChain for Chain { /// returns a clone of the top Pair - fn top_pair(&self) -> Option { - self.top_pair.clone() + fn get_top_pair(&self) -> Option { + self.actor.get_top_pair() + } + + fn set_top_pair(&self, pair: &Option) -> Result, HolochainError> { + self.actor.set_top_pair(&pair) } /// get the top Pair by Entry type @@ -148,7 +158,7 @@ impl SourceChain for Chain { )); } - let top_pair = self.top_pair().and_then(|p| Some(p.key())); + let top_pair = self.get_top_pair().and_then(|p| Some(p.key())); let next_pair = pair.header().next(); if top_pair != next_pair { @@ -162,7 +172,9 @@ impl SourceChain for Chain { let result = self.table.commit(&pair.clone()); if result.is_ok() { - self.top_pair = Some(pair.clone()); + // @TODO instead of unwrapping this, move all the above validation logic inside of + // set_top_pair() + self.set_top_pair(&Some(pair.clone())).unwrap(); } match result { @@ -182,7 +194,9 @@ impl SourceChain for Chain { /// get a Pair by Pair/Header key from the HashTable if it exists fn get_pair(&self, k: &str) -> Result, HolochainError> { + // println!("get"); let response = self.table.ask(HashTableProtocol::GetPair(k.to_string())); + // println!("response"); unwrap_to!(response => HashTableProtocol::GetPairResult).clone() } @@ -198,8 +212,10 @@ impl SourceChain for Chain { } } +// @TODO should SourceChain have a bound on HashTable for consistency? pub trait SourceChain { - fn top_pair(&self) -> Option; + fn set_top_pair(&self, &Option) -> Result, HolochainError>; + fn get_top_pair(&self) -> Option; fn top_pair_type(&self, t: &str) -> Option; fn push_entry(&mut self, entry: &Entry) -> Result; @@ -246,7 +262,7 @@ pub mod tests { c2.push_entry(&e1).unwrap(); c3.push_entry(&e2).unwrap(); - assert_eq!(c1.top_pair(), c2.top_pair()); + assert_eq!(c1.get_top_pair(), c2.get_top_pair()); assert_eq!(c1, c2); assert_ne!(c1, c3); @@ -254,19 +270,35 @@ pub mod tests { } #[test] - /// tests for chain.top() - fn top() { + /// tests for chain.top_pair() + fn top_pair() { let mut chain = test_chain(); - assert_eq!(None, chain.top_pair()); + assert_eq!(None, chain.get_top_pair()); let e1 = test_entry_a(); let e2 = test_entry_b(); let p1 = chain.push_entry(&e1).unwrap(); - assert_eq!(Some(p1), chain.top_pair()); + assert_eq!(Some(p1), chain.get_top_pair()); let p2 = chain.push_entry(&e2).unwrap(); - assert_eq!(Some(p2), chain.top_pair()); + assert_eq!(Some(p2), chain.get_top_pair()); + } + + #[test] + /// tests that the chain state is consistent across clones + fn clone_safe() { + let c1 = test_chain(); + let mut c2 = c1.clone(); + let e = test_entry(); + + assert_eq!(None, c1.get_top_pair()); + assert_eq!(None, c2.get_top_pair()); + + let pair = c2.push_entry(&e).unwrap(); + + assert_eq!(Some(pair.clone()), c2.get_top_pair()); + assert_eq!(c1.get_top_pair(), c2.get_top_pair()); } #[test] @@ -291,13 +323,13 @@ pub mod tests { fn push() { let mut chain = test_chain(); - assert_eq!(None, chain.top_pair()); + assert_eq!(None, chain.get_top_pair()); // chain top, pair entry and headers should all line up after a push let e1 = test_entry_a(); let p1 = chain.push_entry(&e1).unwrap(); - assert_eq!(Some(p1.clone()), chain.top_pair()); + assert_eq!(Some(p1.clone()), chain.get_top_pair()); assert_eq!(e1, p1.entry()); assert_eq!(e1.hash(), p1.header().entry()); @@ -305,7 +337,7 @@ pub mod tests { let e2 = test_entry_b(); let p2 = chain.push_entry(&e2).unwrap(); - assert_eq!(Some(p2.clone()), chain.top_pair()); + assert_eq!(Some(p2.clone()), chain.get_top_pair()); assert_eq!(e2, p2.entry()); assert_eq!(e2.hash(), p2.header().entry()); } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index dfee8359a2..bf40c32acc 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -55,8 +55,8 @@ pub enum HashTableProtocol { lazy_static! { pub static ref HASH_TABLE_SYS: ActorSystem = { - let hash_table_model: DefaultModel = DefaultModel::new(); - ActorSystem::new(&hash_table_model).unwrap() + let model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&model).unwrap() }; } @@ -66,9 +66,9 @@ impl Into> for HashTableProtocol { } } -/// anything that can be asked Protocol aHashTablend block on responses +/// anything that can be asked of HashTable and block on responses /// needed to support implementing ask on upstream ActorRef from riker -pub trait AskHashTable { +pub trait AskHashTable: HashTable { fn ask(&self, message: HashTableProtocol) -> HashTableProtocol; } @@ -177,6 +177,7 @@ impl Actor for HashTableActor { ) { sender .try_tell( + // deliberately exhaustively matching here, don't give into _ temptation match message { HashTableProtocol::Setup => HashTableProtocol::SetupResult(self.table.setup()), HashTableProtocol::SetupResult(_) => unreachable!(), diff --git a/core/src/hash_table/header.rs b/core/src/hash_table/header.rs index 9ed5201570..90c3afc6d4 100644 --- a/core/src/hash_table/header.rs +++ b/core/src/hash_table/header.rs @@ -44,7 +44,7 @@ impl Header { // @TODO implement timestamps // https://github.com/holochain/holochain-rust/issues/70 time: String::new(), - next: chain.top_pair().and_then(|p| Some(p.header().hash())), + next: chain.get_top_pair().and_then(|p| Some(p.header().hash())), entry: entry.hash().to_string(), type_next: chain .top_pair_type(&entry.entry_type()) From ba096fc484e1cc712a4f504d27e5c1e88842075a Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 21 Aug 2018 22:45:12 +1000 Subject: [PATCH 22/49] WIP with debug on actors hanging --- core/src/actor.rs | 96 ++++++++++++++++++++ core/src/chain/actor.rs | 87 ++++++++++-------- core/src/chain/mod.rs | 77 +++++++++++----- core/src/hash_table/actor.rs | 169 +++++++++++++++++++---------------- core/src/hash_table/pair.rs | 12 +-- core/src/lib.rs | 1 + 6 files changed, 297 insertions(+), 145 deletions(-) create mode 100644 core/src/actor.rs diff --git a/core/src/actor.rs b/core/src/actor.rs new file mode 100644 index 0000000000..c9ad9584b4 --- /dev/null +++ b/core/src/actor.rs @@ -0,0 +1,96 @@ +use riker_default::DefaultModel; +use riker::actors::*; +use hash_table::pair::Pair; +use error::HolochainError; +use agent::keys::Keys; +use hash_table::pair_meta::PairMeta; +use riker_patterns::ask::ask; +use futures::executor::block_on; +use futures::Async; + +#[derive(Clone, Debug)] +pub enum Protocol { + SetTopPair(Option), + SetTopPairResult(Result, HolochainError>), + + GetTopPair, + GetTopPairResult(Option), + + /// HashTable::setup() + Setup, + SetupResult(Result<(), HolochainError>), + + /// HashTable::teardown() + Teardown, + TeardownResult(Result<(), HolochainError>), + + /// HashTable::modify() + Modify { + keys: Keys, + old_pair: Pair, + new_pair: Pair, + }, + ModifyResult(Result<(), HolochainError>), + + /// HashTable::retract() + Retract { + keys: Keys, + pair: Pair, + }, + RetractResult(Result<(), HolochainError>), + + /// HashTable::assert_meta() + AssertMeta(PairMeta), + AssertMetaResult(Result<(), HolochainError>), + + /// HashTable::get_meta() + GetMeta(String), + GetMetaResult(Result, HolochainError>), + + /// HashTable::get_pair_meta() + GetPairMeta(Pair), + GetPairMetaResult(Result, HolochainError>), + + /// HashTable::get() + GetPair(String), + GetPairResult(Result, HolochainError>), + + /// HashTable::commit() + Commit(Pair), + CommitResult(Result<(), HolochainError>), +} + +lazy_static! { + pub static ref SYS: ActorSystem = { + let model: DefaultModel = DefaultModel::new(); + ActorSystem::new(&model).unwrap() + }; +} + +impl Into> for Protocol { + fn into(self) -> ActorMsg { + ActorMsg::User(self) + } +} + +pub trait AskSelf { + fn ask(&self, message: Protocol) -> Protocol; +} + +impl AskSelf for ActorRef { + fn ask(&self, message: Protocol) -> Protocol { + println!("ask: {:?}", message); + let a = ask(&(*SYS), self, message); + println!("block"); + loop { + match ::futures::Future::poll(a) { + Ok(Async::Ready(e)) => { + break Ok(e) + }, + Ok(Async::NotReady(e)) => {}, + Err(e) => { break Err(e) }, + } + } + // block_on(a).unwrap() + } +} diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index e2ec36c0f3..1cea81de1c 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -1,10 +1,13 @@ -use riker_default::DefaultModel; +// use riker_default::DefaultModel; use riker::actors::*; use snowflake; use hash_table::pair::Pair; use error::HolochainError; -use riker_patterns::ask::ask; -use futures::executor::block_on; +// use riker_patterns::ask::ask; +// use futures::executor::block_on; +use actor::SYS; +use actor::Protocol; +use actor::AskSelf; #[derive(Clone, Debug)] pub enum ChainProtocol { @@ -15,44 +18,44 @@ pub enum ChainProtocol { GetTopPairResult(Option), } -lazy_static! { - // @TODO Riker docs say make only one actor system per application but this seems weird advice - // if that were true, how could actors be in crates? - // if that were true, how could we have domain specific protocols? - pub static ref CHAIN_SYS: ActorSystem = { - let model: DefaultModel = DefaultModel::new(); - ActorSystem::new(&model).unwrap() - }; -} - -impl Into> for ChainProtocol { - fn into(self) -> ActorMsg { - ActorMsg::User(self) - } -} +// lazy_static! { +// // @TODO Riker docs say make only one actor system per application but this seems weird advice +// // if that were true, how could actors be in crates? +// // if that were true, how could we have domain specific protocols? +// pub static ref CHAIN_SYS: ActorSystem = { +// let model: DefaultModel = DefaultModel::new(); +// ActorSystem::new(&model).unwrap() +// }; +// } + +// impl Into> for ChainProtocol { +// fn into(self) -> ActorMsg { +// ActorMsg::User(self) +// } +// } /// anything that can be asked of Chain and block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskChain { - fn ask(&self, message: ChainProtocol) -> ChainProtocol; + // fn ask(&self, message: Protocol) -> Protocol; fn set_top_pair(&self, &Option) -> Result, HolochainError>; fn get_top_pair(&self) -> Option; } -impl AskChain for ActorRef { - fn ask(&self, message: ChainProtocol) -> ChainProtocol { - let a = ask(&(*CHAIN_SYS), self, message); - block_on(a).unwrap() - } +impl AskChain for ActorRef { + // fn ask(&self, message: Protocol) -> Protocol { + // let a = ask(&(*SYS), self, message); + // block_on(a).unwrap() + // } fn set_top_pair(&self, pair: &Option) -> Result, HolochainError> { - let response = self.ask(ChainProtocol::SetTopPair(pair.clone())); - unwrap_to!(response => ChainProtocol::SetTopPairResult).clone() + let response = self.ask(Protocol::SetTopPair(pair.clone())); + unwrap_to!(response => Protocol::SetTopPairResult).clone() } fn get_top_pair(&self) -> Option { - let response = self.ask(ChainProtocol::GetTopPair); - unwrap_to!(response => ChainProtocol::GetTopPairResult).clone() + let response = self.ask(Protocol::GetTopPair); + unwrap_to!(response => Protocol::GetTopPairResult).clone() } } @@ -67,16 +70,16 @@ impl ChainActor { } } - pub fn actor() -> BoxActor { + pub fn actor() -> BoxActor { Box::new(ChainActor::new()) } - pub fn props() -> BoxActorProd { + pub fn props() -> BoxActorProd { Props::new(Box::new(ChainActor::actor)) } - pub fn new_ref() -> ActorRef { - CHAIN_SYS + pub fn new_ref() -> ActorRef { + SYS .actor_of( ChainActor::props(), &snowflake::ProcessUniqueId::new().to_string(), @@ -86,7 +89,7 @@ impl ChainActor { } impl Actor for ChainActor { - type Msg = ChainProtocol; + type Msg = Protocol; fn receive( &mut self, @@ -94,17 +97,25 @@ impl Actor for ChainActor { message: Self::Msg, sender: Option>, ) { + println!("rec: {:?}", message); sender.try_tell( // deliberately exhaustively matching here, don't give into _ temptation match message { - ChainProtocol::SetTopPair(p) => { + Protocol::SetTopPair(p) => { self.top_pair = p; - ChainProtocol::SetTopPairResult(Ok(self.top_pair.clone())) + Protocol::SetTopPairResult(Ok(self.top_pair.clone())) + }, + Protocol::SetTopPairResult(_) => unreachable!(), + + Protocol::GetTopPair => { + println!("get top pair inner"); + let ret = self.top_pair.clone(); + println!("inner: {:?}", ret); + Protocol::GetTopPairResult(ret) }, - ChainProtocol::SetTopPairResult(_) => unreachable!(), + Protocol::GetTopPairResult(_) => unreachable!(), - ChainProtocol::GetTopPair => ChainProtocol::GetTopPairResult(self.top_pair.clone()), - ChainProtocol::GetTopPairResult(_) => unreachable!(), + _ => unreachable!(), }, Some(context.myself()), ) diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 82c6fbb720..a40f0e9048 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -2,28 +2,31 @@ pub mod actor; use error::HolochainError; use hash_table::{ - actor::{AskHashTable, HashTableProtocol}, + // actor::{AskHashTable}, entry::Entry, pair::Pair, - HashTable, + // HashTable, }; use riker::actors::*; use serde_json; use std::fmt; use chain::actor::ChainActor; -use chain::actor::ChainProtocol; +// use chain::actor::ChainProtocol; use chain::actor::AskChain; +use actor::Protocol; +use actor::AskSelf; +use hash_table::HashTable; #[derive(Clone)] pub struct ChainIterator { - table: ActorRef, + table: ActorRef, current: Option, } impl ChainIterator { #[allow(unknown_lints)] #[allow(needless_pass_by_value)] - pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { + pub fn new(table: ActorRef, pair: &Option) -> ChainIterator { ChainIterator { current: pair.clone(), table: table.clone(), @@ -52,10 +55,10 @@ impl Iterator for ChainIterator { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Chain { - actor: ActorRef, - table: ActorRef, + actor: ActorRef, + table: ActorRef, } impl PartialEq for Chain { @@ -71,12 +74,6 @@ impl PartialEq for Chain { impl Eq for Chain {} -impl fmt::Debug for Chain { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Chain {{ top: {:?} }}", self.get_top_pair()) - } -} - impl IntoIterator for Chain { type Item = Pair; type IntoIter = ChainIterator; @@ -87,7 +84,7 @@ impl IntoIterator for Chain { } impl Chain { - pub fn new(table: ActorRef) -> Chain { + pub fn new(table: ActorRef) -> Chain { Chain { actor: ChainActor::new_ref(), table: table.clone(), @@ -95,7 +92,7 @@ impl Chain { } /// returns a reference to the underlying HashTable - pub fn table(&self) -> ActorRef { + pub fn table(&self) -> ActorRef { self.table.clone() } @@ -120,7 +117,7 @@ impl Chain { /// restore canonical JSON chain /// @TODO accept canonical JSON /// @see https://github.com/holochain/holochain-rust/issues/75 - pub fn from_json(table: ActorRef, s: &str) -> Chain { + pub fn from_json(table: ActorRef, s: &str) -> Chain { // @TODO inappropriate unwrap? // @see https://github.com/holochain/holochain-rust/issues/168 let mut as_seq: Vec = serde_json::from_str(s).unwrap(); @@ -152,16 +149,20 @@ impl SourceChain for Chain { /// private pair-oriented version of push() (which expects Entries) fn push_pair(&mut self, pair: &Pair) -> Result { + println!("start"); if !(pair.validate()) { + println!("validate fail"); return Err(HolochainError::new( "attempted to push an invalid pair for this chain", )); } + println!("get top"); let top_pair = self.get_top_pair().and_then(|p| Some(p.key())); let next_pair = pair.header().next(); if top_pair != next_pair { + println!("top pair fail"); return Err(HolochainError::new(&format!( "top pair did not match next hash pair from pushed pair: {:?} vs. {:?}", top_pair.clone(), @@ -169,18 +170,24 @@ impl SourceChain for Chain { ))); } + println!("commit"); let result = self.table.commit(&pair.clone()); if result.is_ok() { + println!("top"); // @TODO instead of unwrapping this, move all the above validation logic inside of // set_top_pair() + // @TODO if top pair set fails but commit succeeds? self.set_top_pair(&Some(pair.clone())).unwrap(); } - match result { + println!("match"); + let ret = match result { Ok(_) => Ok(pair.clone()), Err(e) => Err(e.clone()), - } + }; + println!("done"); + ret } /// push a new Entry on to the top of the Chain @@ -188,16 +195,18 @@ impl SourceChain for Chain { /// Pair to ensure the chain links up correctly across the underlying table data /// the newly created and pushed Pair is returned in the fn Result fn push_entry(&mut self, entry: &Entry) -> Result { + println!("push entry"); let pair = Pair::new(self, entry); + println!("push pair"); self.push_pair(&pair) } /// get a Pair by Pair/Header key from the HashTable if it exists fn get_pair(&self, k: &str) -> Result, HolochainError> { // println!("get"); - let response = self.table.ask(HashTableProtocol::GetPair(k.to_string())); + let response = self.table.ask(Protocol::GetPair(k.to_string())); // println!("response"); - unwrap_to!(response => HashTableProtocol::GetPairResult).clone() + unwrap_to!(response => Protocol::GetPairResult).clone() } /// get an Entry by Entry key from the HashTable if it exists @@ -234,8 +243,13 @@ pub mod tests { actor::tests::test_table_actor, entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, pair::Pair, - HashTable, + // HashTable, }; + use hash_table::HashTable; + use std::{thread, time}; + use actor::Protocol; + use riker::actors::*; + /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -368,6 +382,25 @@ pub mod tests { assert_eq!(Some(p.clone()), c.get_pair(&p.key()).unwrap(),); } + #[test] + /// show that we can push the chain a bit without issues e.g. async + fn round_trip_stress_test() { + let h = thread::spawn( || { + let mut chain = test_chain(); + let entry = test_entry(); + + for _ in 1..100 { + // println!("{:?}", chain); + chain.push_entry(&entry).unwrap(); + // assert_eq!( + // Some(pair.clone()), + // chain.get_pair(&pair.key()).unwrap(), + // ); + } + }); + h.join().unwrap(); + } + #[test] /// test chain.iter() fn iter() { diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index bf40c32acc..16417bc585 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,11 +1,16 @@ use agent::keys::Keys; use error::HolochainError; -use futures::executor::block_on; -use hash_table::{pair::Pair, pair_meta::PairMeta, HashTable}; +// use futures::executor::block_on; +use hash_table::{pair::Pair, pair_meta::PairMeta,}; use riker::actors::*; -use riker_default::DefaultModel; -use riker_patterns::ask::ask; +// use riker_default::DefaultModel; +// use riker_patterns::ask::ask; use snowflake; +// use actor::Protocol; +use actor::SYS; +use actor::AskSelf; +use actor::Protocol; +use hash_table::HashTable; #[derive(Clone, Debug)] pub enum HashTableProtocol { @@ -53,51 +58,51 @@ pub enum HashTableProtocol { CommitResult(Result<(), HolochainError>), } -lazy_static! { - pub static ref HASH_TABLE_SYS: ActorSystem = { - let model: DefaultModel = DefaultModel::new(); - ActorSystem::new(&model).unwrap() - }; -} - -impl Into> for HashTableProtocol { - fn into(self) -> ActorMsg { - ActorMsg::User(self) - } -} - -/// anything that can be asked of HashTable and block on responses -/// needed to support implementing ask on upstream ActorRef from riker +// lazy_static! { +// pub static ref HASH_TABLE_SYS: ActorSystem = { +// let model: DefaultModel = DefaultModel::new(); +// ActorSystem::new(&model).unwrap() +// }; +// } + +// impl Into> for HashTableProtocol { +// fn into(self) -> ActorMsg { +// ActorMsg::User(self) +// } +// } + +// anything that can be asked of HashTable and block on responses +// needed to support implementing ask on upstream ActorRef from riker pub trait AskHashTable: HashTable { - fn ask(&self, message: HashTableProtocol) -> HashTableProtocol; + // fn ask(&self, message: Protocol) -> Protocol; } -impl AskHashTable for ActorRef { - fn ask(&self, message: HashTableProtocol) -> HashTableProtocol { - let a = ask(&(*HASH_TABLE_SYS), self, message); - block_on(a).unwrap() - } +impl AskHashTable for ActorRef { + // fn ask(&self, message: Protocol) -> Protocol { + // let a = ask(&(*SYS), self, message); + // block_on(a).unwrap() + // } } -impl HashTable for ActorRef { +impl HashTable for ActorRef { fn setup(&mut self) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Setup); - unwrap_to!(response => HashTableProtocol::SetupResult).clone() + let response = self.ask(Protocol::Setup); + unwrap_to!(response => Protocol::SetupResult).clone() } fn teardown(&mut self) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Teardown); - unwrap_to!(response => HashTableProtocol::TeardownResult).clone() + let response = self.ask(Protocol::Teardown); + unwrap_to!(response => Protocol::TeardownResult).clone() } fn commit(&mut self, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Commit(pair.clone())); - unwrap_to!(response => HashTableProtocol::CommitResult).clone() + let response = self.ask(Protocol::Commit(pair.clone())); + unwrap_to!(response => Protocol::CommitResult).clone() } fn get(&self, key: &str) -> Result, HolochainError> { - let response = self.ask(HashTableProtocol::GetPair(key.to_string())); - unwrap_to!(response => HashTableProtocol::GetPairResult).clone() + let response = self.ask(Protocol::GetPair(key.to_string())); + unwrap_to!(response => Protocol::GetPairResult).clone() } fn modify( @@ -106,35 +111,35 @@ impl HashTable for ActorRef { old_pair: &Pair, new_pair: &Pair, ) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Modify { + let response = self.ask(Protocol::Modify { keys: keys.clone(), old_pair: old_pair.clone(), new_pair: new_pair.clone(), }); - unwrap_to!(response => HashTableProtocol::ModifyResult).clone() + unwrap_to!(response => Protocol::ModifyResult).clone() } fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::Retract { + let response = self.ask(Protocol::Retract { keys: keys.clone(), pair: pair.clone(), }); - unwrap_to!(response => HashTableProtocol::RetractResult).clone() + unwrap_to!(response => Protocol::RetractResult).clone() } fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError> { - let response = self.ask(HashTableProtocol::AssertMeta(meta.clone())); - unwrap_to!(response => HashTableProtocol::AssertMetaResult).clone() + let response = self.ask(Protocol::AssertMeta(meta.clone())); + unwrap_to!(response => Protocol::AssertMetaResult).clone() } fn get_meta(&mut self, key: &str) -> Result, HolochainError> { - let response = self.ask(HashTableProtocol::GetMeta(key.to_string())); - unwrap_to!(response => HashTableProtocol::GetMetaResult).clone() + let response = self.ask(Protocol::GetMeta(key.to_string())); + unwrap_to!(response => Protocol::GetMetaResult).clone() } fn get_pair_meta(&mut self, pair: &Pair) -> Result, HolochainError> { - let response = self.ask(HashTableProtocol::GetPairMeta(pair.clone())); - unwrap_to!(response => HashTableProtocol::GetPairMetaResult).clone() + let response = self.ask(Protocol::GetPairMeta(pair.clone())); + unwrap_to!(response => Protocol::GetPairMetaResult).clone() } } @@ -148,16 +153,16 @@ impl HashTableActor { HashTableActor { table } } - pub fn actor(table: HT) -> BoxActor { + pub fn actor(table: HT) -> BoxActor { Box::new(HashTableActor::new(table)) } - pub fn props(table: HT) -> BoxActorProd { + pub fn props(table: HT) -> BoxActorProd { Props::new_args(Box::new(HashTableActor::actor), table) } - pub fn new_ref(table: HT) -> ActorRef { - HASH_TABLE_SYS + pub fn new_ref(table: HT) -> ActorRef { + SYS .actor_of( HashTableActor::props(table), &snowflake::ProcessUniqueId::new().to_string(), @@ -167,7 +172,7 @@ impl HashTableActor { } impl Actor for HashTableActor { - type Msg = HashTableProtocol; + type Msg = Protocol; fn receive( &mut self, @@ -179,52 +184,54 @@ impl Actor for HashTableActor { .try_tell( // deliberately exhaustively matching here, don't give into _ temptation match message { - HashTableProtocol::Setup => HashTableProtocol::SetupResult(self.table.setup()), - HashTableProtocol::SetupResult(_) => unreachable!(), + Protocol::Setup => Protocol::SetupResult(self.table.setup()), + Protocol::SetupResult(_) => unreachable!(), - HashTableProtocol::Teardown => { - HashTableProtocol::TeardownResult(self.table.teardown()) + Protocol::Teardown => { + Protocol::TeardownResult(self.table.teardown()) } - HashTableProtocol::TeardownResult(_) => unreachable!(), + Protocol::TeardownResult(_) => unreachable!(), - HashTableProtocol::Commit(pair) => { - HashTableProtocol::CommitResult(self.table.commit(&pair)) + Protocol::Commit(pair) => { + Protocol::CommitResult(self.table.commit(&pair)) } - HashTableProtocol::CommitResult(_) => unreachable!(), + Protocol::CommitResult(_) => unreachable!(), - HashTableProtocol::GetPair(hash) => { - HashTableProtocol::GetPairResult(self.table.get(&hash)) + Protocol::GetPair(hash) => { + Protocol::GetPairResult(self.table.get(&hash)) } - HashTableProtocol::GetPairResult(_) => unreachable!(), + Protocol::GetPairResult(_) => unreachable!(), - HashTableProtocol::Modify { + Protocol::Modify { keys, old_pair, new_pair, - } => HashTableProtocol::ModifyResult( + } => Protocol::ModifyResult( self.table.modify(&keys, &old_pair, &new_pair), ), - HashTableProtocol::ModifyResult(_) => unreachable!(), + Protocol::ModifyResult(_) => unreachable!(), - HashTableProtocol::Retract { keys, pair } => { - HashTableProtocol::RetractResult(self.table.retract(&keys, &pair)) + Protocol::Retract { keys, pair } => { + Protocol::RetractResult(self.table.retract(&keys, &pair)) } - HashTableProtocol::RetractResult(_) => unreachable!(), + Protocol::RetractResult(_) => unreachable!(), - HashTableProtocol::AssertMeta(pair_meta) => { - HashTableProtocol::AssertMetaResult(self.table.assert_meta(&pair_meta)) + Protocol::AssertMeta(pair_meta) => { + Protocol::AssertMetaResult(self.table.assert_meta(&pair_meta)) } - HashTableProtocol::AssertMetaResult(_) => unreachable!(), + Protocol::AssertMetaResult(_) => unreachable!(), - HashTableProtocol::GetMeta(key) => { - HashTableProtocol::GetMetaResult(self.table.get_meta(&key)) + Protocol::GetMeta(key) => { + Protocol::GetMetaResult(self.table.get_meta(&key)) } - HashTableProtocol::GetMetaResult(_) => unreachable!(), + Protocol::GetMetaResult(_) => unreachable!(), - HashTableProtocol::GetPairMeta(pair) => { - HashTableProtocol::GetPairMetaResult(self.table.get_pair_meta(&pair)) + Protocol::GetPairMeta(pair) => { + Protocol::GetPairMetaResult(self.table.get_pair_meta(&pair)) } - HashTableProtocol::GetPairMetaResult(_) => unreachable!(), + Protocol::GetPairMetaResult(_) => unreachable!(), + + _ => unreachable!(), }, Some(context.myself()), ) @@ -236,15 +243,19 @@ impl Actor for HashTableActor { pub mod tests { use super::HashTableActor; - use hash_table::{actor::HashTableProtocol, memory::tests::test_table}; + use hash_table::{memory::tests::test_table}; use riker::actors::*; use hash::tests::test_hash; - use hash_table::HashTable; + // use hash_table::HashTable; use hash_table::pair::tests::test_pair; use std::thread; use std::sync::mpsc; + use actor::Protocol; + use hash_table::HashTable; - pub fn test_table_actor() -> ActorRef { + /// dummy table actor ref + /// every call produces a new actor, not just a new ref to the same actor + pub fn test_table_actor() -> ActorRef { HashTableActor::new_ref(test_table()) } @@ -266,7 +277,7 @@ pub mod tests { } #[test] - /// we want to show two things here: + /// show two things here: /// - we can clone some stateful thing (i.e. actor ref) and mutate one clone and have that /// consistent across all the clones /// - we can send the cloned stateful thing into threads and have them see a consistent world diff --git a/core/src/hash_table/pair.rs b/core/src/hash_table/pair.rs index 1c1495e262..934d03f222 100644 --- a/core/src/hash_table/pair.rs +++ b/core/src/hash_table/pair.rs @@ -26,12 +26,12 @@ impl Pair { entry: entry.clone(), }; - if !p.validate() { - // we panic as no code path should attempt to create invalid pairs - // creating a Pair is an internal process of chain.push() and is deterministic based on - // an immutable Entry (that itself cannot be invalid), so this should never happen. - panic!("attempted to create an invalid pair"); - }; + // if !p.validate() { + // // we panic as no code path should attempt to create invalid pairs + // // creating a Pair is an internal process of chain.push() and is deterministic based on + // // an immutable Entry (that itself cannot be invalid), so this should never happen. + // panic!("attempted to create an invalid pair"); + // }; p } diff --git a/core/src/lib.rs b/core/src/lib.rs index b3eb2dff48..6dd488efed 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -28,6 +28,7 @@ extern crate holochain_agent; extern crate holochain_dna; extern crate holochain_wasm_utils; +pub mod actor; pub mod action; pub mod agent; pub mod chain; From 0ce32515bc2ea241e91cda5f68abf2e310a3aaf3 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 20:08:48 +1000 Subject: [PATCH 23/49] WIP on merge cleanup --- core/Cargo.toml | 6 +- core/src/actor.rs | 14 +--- core/src/agent/state.rs | 2 +- core/src/chain/actor.rs | 37 +-------- core/src/chain/mod.rs | 117 ++++++++++----------------- core/src/hash_table/actor.rs | 82 ++----------------- core/src/hash_table/header.rs | 4 +- core/src/hash_table/memory/mod.rs | 56 ++++++------- core/src/hash_table/mod.rs | 4 +- core/src/hash_table/pair.rs | 12 +-- core/src/nucleus/ribosome/api/get.rs | 3 - 11 files changed, 96 insertions(+), 241 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index 4e1840dd7a..268ad05c51 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,9 +17,9 @@ multihash = "0.8.0" rust-base58 = "0.0.4" bitflags = "1.0" holochain_wasm_utils = { path = "../wasm_utils"} -riker = "0.1.1" -riker-default = "0.1.1" -riker-patterns = "0.1.0" +riker = "0.1.5" +riker-default = "0.1.5" +riker-patterns = "0.1.5" futures-preview = "0.2.2" lazy_static = "1.1.0" unwrap_to = "0.1.0" diff --git a/core/src/actor.rs b/core/src/actor.rs index c9ad9584b4..9997bbaad4 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -6,7 +6,6 @@ use agent::keys::Keys; use hash_table::pair_meta::PairMeta; use riker_patterns::ask::ask; use futures::executor::block_on; -use futures::Async; #[derive(Clone, Debug)] pub enum Protocol { @@ -79,18 +78,7 @@ pub trait AskSelf { impl AskSelf for ActorRef { fn ask(&self, message: Protocol) -> Protocol { - println!("ask: {:?}", message); let a = ask(&(*SYS), self, message); - println!("block"); - loop { - match ::futures::Future::poll(a) { - Ok(Async::Ready(e)) => { - break Ok(e) - }, - Ok(Async::NotReady(e)) => {}, - Err(e) => { break Err(e) }, - } - } - // block_on(a).unwrap() + block_on(a).unwrap() } } diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index b64e1ec7cf..c8d03ff9f9 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -114,7 +114,7 @@ fn reduce_get( let action = action_wrapper.action(); let key = unwrap_to!(action => Action::Get); - let result = state.chain.get_entry(&key.clone()); + let result = state.chain.entry(&key.clone()); // @TODO if the get fails local, do a network get // @see https://github.com/holochain/holochain-rust/issues/167 diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 1cea81de1c..4ce3a27793 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -9,51 +9,21 @@ use actor::SYS; use actor::Protocol; use actor::AskSelf; -#[derive(Clone, Debug)] -pub enum ChainProtocol { - SetTopPair(Option), - SetTopPairResult(Result, HolochainError>), - - GetTopPair, - GetTopPairResult(Option), -} - -// lazy_static! { -// // @TODO Riker docs say make only one actor system per application but this seems weird advice -// // if that were true, how could actors be in crates? -// // if that were true, how could we have domain specific protocols? -// pub static ref CHAIN_SYS: ActorSystem = { -// let model: DefaultModel = DefaultModel::new(); -// ActorSystem::new(&model).unwrap() -// }; -// } - -// impl Into> for ChainProtocol { -// fn into(self) -> ActorMsg { -// ActorMsg::User(self) -// } -// } - /// anything that can be asked of Chain and block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskChain { // fn ask(&self, message: Protocol) -> Protocol; fn set_top_pair(&self, &Option) -> Result, HolochainError>; - fn get_top_pair(&self) -> Option; + fn top_pair(&self) -> Option; } impl AskChain for ActorRef { - // fn ask(&self, message: Protocol) -> Protocol { - // let a = ask(&(*SYS), self, message); - // block_on(a).unwrap() - // } - fn set_top_pair(&self, pair: &Option) -> Result, HolochainError> { let response = self.ask(Protocol::SetTopPair(pair.clone())); unwrap_to!(response => Protocol::SetTopPairResult).clone() } - fn get_top_pair(&self) -> Option { + fn top_pair(&self) -> Option { let response = self.ask(Protocol::GetTopPair); unwrap_to!(response => Protocol::GetTopPairResult).clone() } @@ -97,7 +67,6 @@ impl Actor for ChainActor { message: Self::Msg, sender: Option>, ) { - println!("rec: {:?}", message); sender.try_tell( // deliberately exhaustively matching here, don't give into _ temptation match message { @@ -108,9 +77,7 @@ impl Actor for ChainActor { Protocol::SetTopPairResult(_) => unreachable!(), Protocol::GetTopPair => { - println!("get top pair inner"); let ret = self.top_pair.clone(); - println!("inner: {:?}", ret); Protocol::GetTopPairResult(ret) }, Protocol::GetTopPairResult(_) => unreachable!(), diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 423aeebc6a..e71c62fb82 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -9,7 +9,6 @@ use hash_table::{ }; use riker::actors::*; use serde_json; -use std::fmt; use chain::actor::ChainActor; use chain::actor::AskChain; use actor::Protocol; @@ -46,7 +45,7 @@ impl Iterator for ChainIterator { // @TODO should this panic? // @see https://github.com/holochain/holochain-rust/issues/146 .and_then(|h| { - self.table.get(&h.to_string()).expect("getting from a table shouldn't fail") + self.table.pair(&h.to_string()).expect("getting from a table shouldn't fail") }); previous } @@ -65,7 +64,7 @@ impl PartialEq for Chain { self.validate() && other.validate() && // header hashing ensures that if the tops match the whole chain matches - self.get_top_pair() == other.get_top_pair() + self.top_pair() == other.top_pair() } } @@ -102,7 +101,7 @@ impl Chain { /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable fn iter(&self) -> ChainIterator { - ChainIterator::new(self.table(), &self.get_top_pair()) + ChainIterator::new(self.table(), &self.top_pair()) } /// get the entire chain, top to bottom as a JSON array or canonical pairs @@ -125,7 +124,7 @@ impl Chain { let mut chain = Chain::new(table); for p in as_seq { - chain.push_pair(p).expect("pair should be valid"); + chain.push_pair(&p).expect("pair should be valid"); } chain } @@ -133,7 +132,7 @@ impl Chain { impl SourceChain for Chain { /// returns a reference to the top Pair - pub fn top_pair(&self) -> Option { + fn top_pair(&self) -> Option { self.actor.top_pair() } @@ -164,14 +163,14 @@ impl SourceChain for Chain { ))); } - let result = self.table.commit(&pair.clone())?; + self.table.commit(&pair.clone())?; // @TODO instead of unwrapping this, move all the above validation logic inside of // set_top_pair() // @TODO if top pair set fails but commit succeeds? self.set_top_pair(&Some(pair.clone()))?; - Ok(pair) + Ok(pair.clone()) } /// push a new Entry on to the top of the Chain @@ -183,16 +182,6 @@ impl SourceChain for Chain { self.push_pair(&pair) } - /// returns true if all pairs in the chain pass validation - pub fn validate(&self) -> bool { - self.iter().all(|p| p.validate()) - } - - /// returns a ChainIterator that provides cloned Pairs from the underlying HashTable - pub fn iter(&self) -> ChainIterator { - ChainIterator::new(self.table(), self.top().clone()) - } - /// get a Pair by Pair/Header key from the HashTable if it exists fn pair(&self, k: &str) -> Result, HolochainError> { let response = self.table.ask(Protocol::GetPair(k.to_string())); @@ -200,7 +189,7 @@ impl SourceChain for Chain { } /// get an Entry by Entry key from the HashTable if it exists - pub fn entry(&self, entry_hash: &str) -> Result, HolochainError> { + fn entry(&self, entry_hash: &str) -> Result, HolochainError> { // @TODO - this is a slow way to do a lookup // @see https://github.com/holochain/holochain-rust/issues/50 Ok(self @@ -233,13 +222,8 @@ pub mod tests { actor::tests::test_table_actor, entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, pair::Pair, - // HashTable, }; use hash_table::HashTable; - use std::{thread, time}; - use actor::Protocol; - use riker::actors::*; - /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -255,25 +239,25 @@ pub mod tests { #[test] /// test chain equality fn eq() { - let mut c1 = test_chain(); - let mut c2 = test_chain(); - let mut c3 = test_chain(); + let mut chain1 = test_chain(); + let mut chain2 = test_chain(); + let mut chain3 = test_chain(); - let e1 = test_entry_a(); - let e2 = test_entry_b(); + let entry_a = test_entry_a(); + let entry_b = test_entry_b(); - c1.push_entry(&e1) + chain1.push_entry(&entry_a) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - c2.push_entry(&e1) + chain2.push_entry(&entry_a) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - c3.push_entry(&e2) + chain3.push_entry(&entry_b) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - assert_eq!(c1.get_top_pair(), c2.get_top_pair()); - assert_eq!(c1, c2); + assert_eq!(chain1.top_pair(), chain2.top_pair()); + assert_eq!(chain1, chain2); - assert_ne!(c1, c3); - assert_ne!(c2, c3); + assert_ne!(chain1, chain3); + assert_ne!(chain2, chain3); } #[test] @@ -281,7 +265,7 @@ pub mod tests { fn top_pair() { let mut chain = test_chain(); - assert_eq!(&None, chain.top_pair()); + assert_eq!(None, chain.top_pair()); let entry_a = test_entry_a(); let entry_b = test_entry_b(); @@ -289,12 +273,12 @@ pub mod tests { let pair_a = chain .push_entry(&entry_a) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - assert_eq!(&Some(pair_a), chain.top_pair()); + assert_eq!(Some(pair_a), chain.top_pair()); let pair_b = chain .push_entry(&entry_b) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - assert_eq!(&Some(pair_b), chain.top_pair()); + assert_eq!(Some(pair_b), chain.top_pair()); } #[test] @@ -327,8 +311,8 @@ pub mod tests { let table_pair = table_actor.pair(&pair.key()).expect("getting an entry from a table in a chain shouldn't fail"); let chain_pair = chain.pair(&pair.key()).expect("getting an entry from a chain shouldn't fail"); - assert_eq!(Some(&p), table_pair.as_ref()); - assert_eq!(Some(&p), chain_pair.as_ref()); + assert_eq!(Some(&pair), table_pair.as_ref()); + assert_eq!(Some(&pair), chain_pair.as_ref()); assert_eq!(table_pair, chain_pair); } @@ -337,7 +321,7 @@ pub mod tests { fn push() { let mut chain = test_chain(); - assert_eq!(&None, chain.top_pair()); + assert_eq!(None, chain.top_pair()); // chain top, pair entry and headers should all line up after a push let e1 = test_entry_a(); @@ -387,7 +371,7 @@ pub mod tests { let mut chain = test_chain(); let entry = test_entry(); let pair = chain - .push_entry(&e) + .push_entry(&entry) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( @@ -591,77 +575,64 @@ pub mod tests { None, chain .top_pair_type(&test_type_a()) - .expect("finding top entry of a given type shouldn't fail") ); assert_eq!( None, chain .top_pair_type(&test_type_b()) - .expect("finding top entry of a given type shouldn't fail") ); - let e1 = test_entry_a(); - let e2 = test_entry_b(); - let e3 = test_entry_a(); + let entry1 = test_entry_a(); + let entry2 = test_entry_b(); + let entry3 = test_entry_a(); // type a should be p1 // type b should be None - let p1 = chain - .push_entry(&e1) + let pair1 = chain + .push_entry(&entry1) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( - Some(&p1), + Some(pair1), chain .top_pair_type(&test_type_a()) - .expect("finding top entry of a given type shouldn't fail") - .as_ref() ); assert_eq!( None, chain .top_pair_type(&test_type_b()) - .expect("finding top entry of a given type shouldn't fail") ); - // type a should still be p1 + // type a should still be pair1 // type b should be p2 - let p2 = chain - .push_entry(&e2) + let pair2 = chain + .push_entry(&entry2) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( - Some(&p1), + Some(pair1), chain .top_pair_type(&test_type_a()) - .expect("finding top entry of a given type shouldn't fail") - .as_ref() ); assert_eq!( - Some(&p2), + Some(pair2), chain .top_pair_type(&test_type_b()) - .expect("finding top entry of a given type shouldn't fail") - .as_ref() ); - // type a should be p3 - // type b should still be p2 - let p3 = chain - .push_entry(&e3) + // type a should be pair3 + // type b should still be pair2 + let pair3 = chain + .push_entry(&entry3) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( - Some(&p3), + Some(pair3), chain .top_pair_type(&test_type_a()) - .expect("finding top entry of a given type shouldn't fail") - .as_ref() ); assert_eq!( - Some(&p2), + Some(pair2), chain .top_pair_type(&test_type_b()) - .expect("finding top entry of a given type shouldn't fail") - .as_ref() ); } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 16417bc585..fdbee1c40b 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -12,77 +12,11 @@ use actor::AskSelf; use actor::Protocol; use hash_table::HashTable; -#[derive(Clone, Debug)] -pub enum HashTableProtocol { - /// HashTable::setup() - Setup, - SetupResult(Result<(), HolochainError>), - - /// HashTable::teardown() - Teardown, - TeardownResult(Result<(), HolochainError>), - - /// HashTable::modify() - Modify { - keys: Keys, - old_pair: Pair, - new_pair: Pair, - }, - ModifyResult(Result<(), HolochainError>), - - /// HashTable::retract() - Retract { - keys: Keys, - pair: Pair, - }, - RetractResult(Result<(), HolochainError>), - - /// HashTable::assert_meta() - AssertMeta(PairMeta), - AssertMetaResult(Result<(), HolochainError>), - - /// HashTable::get_meta() - GetMeta(String), - GetMetaResult(Result, HolochainError>), - - /// HashTable::get_pair_meta() - GetPairMeta(Pair), - GetPairMetaResult(Result, HolochainError>), - - /// HashTable::get() - GetPair(String), - GetPairResult(Result, HolochainError>), - - /// HashTable::commit() - Commit(Pair), - CommitResult(Result<(), HolochainError>), -} - -// lazy_static! { -// pub static ref HASH_TABLE_SYS: ActorSystem = { -// let model: DefaultModel = DefaultModel::new(); -// ActorSystem::new(&model).unwrap() -// }; -// } - -// impl Into> for HashTableProtocol { -// fn into(self) -> ActorMsg { -// ActorMsg::User(self) -// } -// } - // anything that can be asked of HashTable and block on responses // needed to support implementing ask on upstream ActorRef from riker -pub trait AskHashTable: HashTable { - // fn ask(&self, message: Protocol) -> Protocol; -} +pub trait AskHashTable: HashTable {} -impl AskHashTable for ActorRef { - // fn ask(&self, message: Protocol) -> Protocol { - // let a = ask(&(*SYS), self, message); - // block_on(a).unwrap() - // } -} +impl AskHashTable for ActorRef {} impl HashTable for ActorRef { fn setup(&mut self) -> Result<(), HolochainError> { @@ -100,7 +34,7 @@ impl HashTable for ActorRef { unwrap_to!(response => Protocol::CommitResult).clone() } - fn get(&self, key: &str) -> Result, HolochainError> { + fn pair(&self, key: &str) -> Result, HolochainError> { let response = self.ask(Protocol::GetPair(key.to_string())); unwrap_to!(response => Protocol::GetPairResult).clone() } @@ -198,7 +132,7 @@ impl Actor for HashTableActor { Protocol::CommitResult(_) => unreachable!(), Protocol::GetPair(hash) => { - Protocol::GetPairResult(self.table.get(&hash)) + Protocol::GetPairResult(self.table.pair(&hash)) } Protocol::GetPairResult(_) => unreachable!(), @@ -264,14 +198,14 @@ pub mod tests { let mut table_actor = test_table_actor(); assert_eq!( - table_actor.get(&test_hash()).unwrap(), + table_actor.pair(&test_hash()).unwrap(), None, ); table_actor.commit(&test_pair()).unwrap(); assert_eq!( - table_actor.get(&test_pair().key()).unwrap(), + table_actor.pair(&test_pair().key()).unwrap(), Some(test_pair()), ); } @@ -289,7 +223,7 @@ pub mod tests { let (tx1, rx1) = mpsc::channel(); thread::spawn(move || { assert_eq!( - table_actor_thread.get(&test_hash()).unwrap(), + table_actor_thread.pair(&test_hash()).unwrap(), None, ); // kick off the next thread @@ -311,7 +245,7 @@ pub mod tests { let handle = thread::spawn(move || { let pair = rx2.recv().unwrap(); assert_eq!( - table_actor_thread.get(&pair.key()).unwrap(), + table_actor_thread.pair(&pair.key()).unwrap(), Some(pair), ); }); diff --git a/core/src/hash_table/header.rs b/core/src/hash_table/header.rs index 0ba12fcdc7..fb62377e93 100644 --- a/core/src/hash_table/header.rs +++ b/core/src/hash_table/header.rs @@ -1,7 +1,6 @@ use chain::{Chain, SourceChain}; use hash; -use hash_table::entry::Entry; -use hash_table::{entry::Entry, HashString, HashTable}; +use hash_table::{entry::Entry, HashString}; use multihash::Hash; /// Header of a source chain "Item" @@ -55,7 +54,6 @@ impl Header { .top_pair_type(&entry.entry_type()) // @TODO inappropriate expect()? // @see https://github.com/holochain/holochain-rust/issues/147 - .expect("top type should never error") .map(|p| p.header().hash()), // @TODO implement signatures // https://github.com/holochain/holochain-rust/issues/71 diff --git a/core/src/hash_table/memory/mod.rs b/core/src/hash_table/memory/mod.rs index 6168df98fb..04c97eea64 100644 --- a/core/src/hash_table/memory/mod.rs +++ b/core/src/hash_table/memory/mod.rs @@ -40,7 +40,7 @@ impl HashTable for MemTable { Ok(()) } - fn get(&self, key: &str) -> Result, HolochainError> { + fn pair(&self, key: &str) -> Result, HolochainError> { Ok(self.pairs.get(key).cloned()) } @@ -54,7 +54,7 @@ impl HashTable for MemTable { // @TODO what if meta fails when commit succeeds? // @see https://github.com/holochain/holochain-rust/issues/142 - self.assert_meta(PairMeta::new( + self.assert_meta(&PairMeta::new( keys, &old_pair, STATUS_NAME, @@ -63,11 +63,11 @@ impl HashTable for MemTable { // @TODO what if meta fails when commit succeeds? // @see https://github.com/holochain/holochain-rust/issues/142 - self.assert_meta(PairMeta::new(keys, &old_pair, LINK_NAME, &new_pair.key())) + self.assert_meta(&PairMeta::new(keys, &old_pair, LINK_NAME, &new_pair.key())) } fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { - self.assert_meta(PairMeta::new( + self.assert_meta(&PairMeta::new( keys, &pair, STATUS_NAME, @@ -75,8 +75,8 @@ impl HashTable for MemTable { )) } - fn assert_meta(&mut self, meta: PairMeta) -> Result<(), HolochainError> { - self.meta.insert(meta.key(), meta); + fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError> { + self.meta.insert(meta.key(), meta.clone()); Ok(()) } @@ -140,10 +140,10 @@ pub mod tests { #[test] /// Pairs can round trip through table.commit() and table.get() fn pair_round_trip() { - let mut ht = test_table(); - let p = test_pair(); - ht.commit(&p).expect("should be able to commit valid pair"); - assert_eq!(ht.get(&p.key()), Ok(Some(p))); + let mut table = test_table(); + let pair = test_pair(); + table.commit(&pair).expect("should be able to commit valid pair"); + assert_eq!(table.pair(&pair.key()), Ok(Some(pair))); } #[test] @@ -210,53 +210,53 @@ pub mod tests { #[test] /// PairMeta can round trip through table.assert_meta() and table.get_meta() fn meta_round_trip() { - let mut ht = test_table(); - let m = test_pair_meta(); + let mut table = test_table(); + let pair_meta = test_pair_meta(); assert_eq!( None, - ht.get_meta(&m.key()) + table.get_meta(&pair_meta.key()) .expect("getting the metadata on a pair shouldn't fail") ); - ht.assert_meta(m.clone()) + table.assert_meta(&pair_meta) .expect("asserting metadata shouldn't fail"); assert_eq!( - Some(&m), - ht.get_meta(&m.key()) + Some(&pair_meta), + table.get_meta(&pair_meta.key()) .expect("getting the metadata on a pair shouldn't fail") .as_ref() ); } #[test] - /// all PairMeta for a Pair can be retrieved with get_pair_meta + /// all PairMeta for a Pair can be retrieved with pair_meta fn get_pair_meta() { - let mut ht = test_table(); - let p = test_pair(); - let m1 = test_pair_meta_a(); - let m2 = test_pair_meta_b(); + let mut table = test_table(); + let pair = test_pair(); + let pair_meta_a = test_pair_meta_a(); + let pair_meta_b = test_pair_meta_b(); let empty_vec: Vec = Vec::new(); assert_eq!( empty_vec, - ht.get_pair_meta(&p) + table.get_pair_meta(&pair) .expect("getting the metadata on a pair shouldn't fail") ); - ht.assert_meta(m1.clone()) + table.assert_meta(&pair_meta_a) .expect("asserting metadata shouldn't fail"); assert_eq!( - vec![m1.clone()], - ht.get_pair_meta(&p) + vec![pair_meta_a.clone()], + table.get_pair_meta(&pair) .expect("getting the metadata on a pair shouldn't fail") ); - ht.assert_meta(m2.clone()) + table.assert_meta(&pair_meta_b.clone()) .expect("asserting metadata shouldn't fail"); assert_eq!( - vec![m2, m1], - ht.get_pair_meta(&p) + vec![pair_meta_b, pair_meta_a], + table.get_pair_meta(&pair) .expect("getting the metadata on a pair shouldn't fail") ); } diff --git a/core/src/hash_table/mod.rs b/core/src/hash_table/mod.rs index 787a34037e..34f90c0077 100644 --- a/core/src/hash_table/mod.rs +++ b/core/src/hash_table/mod.rs @@ -26,7 +26,7 @@ pub trait HashTable: Send + Sync + Clone + 'static { /// add a Pair to the HashTable, analogous to chain.push() but ordering is not enforced fn commit(&mut self, pair: &Pair) -> Result<(), HolochainError>; /// lookup a Pair from the HashTable by Pair/Header key - fn get(&self, key: &str) -> Result, HolochainError>; + fn pair(&self, key: &str) -> Result, HolochainError>; /// add a new Pair to the HashTable as per commit and status link an old Pair as MODIFIED fn modify( &mut self, @@ -39,7 +39,7 @@ pub trait HashTable: Send + Sync + Clone + 'static { // meta /// assert a given PairMeta in the HashTable - fn assert_meta(&mut self, meta: PairMeta) -> Result<(), HolochainError>; + fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError>; /// lookup a PairMeta from the HashTable by key fn get_meta(&mut self, key: &str) -> Result, HolochainError>; /// lookup all PairMeta for a given Pair diff --git a/core/src/hash_table/pair.rs b/core/src/hash_table/pair.rs index f3a5a20787..bf05b6ba5c 100644 --- a/core/src/hash_table/pair.rs +++ b/core/src/hash_table/pair.rs @@ -34,7 +34,7 @@ impl Pair { let p = Pair { header: header, - entry: entry, + entry: entry.clone(), }; // we panic as no code path should attempt to create invalid pairs @@ -107,7 +107,7 @@ pub mod tests { /// dummy pair pub fn test_pair() -> Pair { - Pair::new(&test_chain(), test_entry()) + Pair::new(&test_chain(), &test_entry()) } /// dummy pair, same as test_pair() @@ -117,7 +117,7 @@ pub mod tests { /// dummy pair, differs from test_pair() pub fn test_pair_b() -> Pair { - Pair::new(&test_chain(), test_entry_b()) + Pair::new(&test_chain(), &test_entry_b()) } #[test] @@ -131,7 +131,7 @@ pub mod tests { assert_eq!(h1.entry_hash(), e1.hash()); assert_eq!(h1.link(), None); - let p1 = Pair::new(&chain, e1.clone()); + let p1 = Pair::new(&chain, &e1.clone()); assert_eq!(&e1, p1.entry()); assert_eq!(&h1, p1.header()); } @@ -144,7 +144,7 @@ pub mod tests { let c = "bar"; let e = Entry::new(t, c); let h = Header::new(&chain, &e); - let p = Pair::new(&chain, e); + let p = Pair::new(&chain, &e); assert_eq!(&h, p.header()); } @@ -169,7 +169,7 @@ pub mod tests { let t = "fooType"; let e1 = Entry::new(t, "bar"); - let p1 = Pair::new(&chain, e1); + let p1 = Pair::new(&chain, &e1); assert!(p1.validate()); } diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index a46fd2c44a..36d378f77c 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -88,9 +88,6 @@ mod tests { tests::{test_capability, test_parameters, test_zome_name}, }, FunctionCall, - use nucleus::ribosome::{ - api::{tests::test_zome_api_function_runtime, ZomeAPIFunction}, - Defn, }; use serde_json; use std::sync::Arc; From e38c4a008cff5bcdebdbcf88e674c695ebe52f15 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 20:10:00 +1000 Subject: [PATCH 24/49] remove riker config --- config/riker.toml | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 config/riker.toml diff --git a/config/riker.toml b/config/riker.toml deleted file mode 100644 index 3718cca4ba..0000000000 --- a/config/riker.toml +++ /dev/null @@ -1,37 +0,0 @@ -debug = true - -[log] -# max level to log -level = "debug" - -# log format to use -# correlates to format!(log_format, date=, time=, level=, module=, body=); -# since named parameters are used the order of the fields is flexible -# the formatting of each field can be changed also -# e.g. to completely hide a field: {module:.0} -# See: https://doc.rust-lang.org/std/fmt/#syntax - -# {date} the calendar day -# {time} the calendar time -# {level} the level for the entry -# {module} the module path originating the entry -# {body} the message body -log_format = "{date} {time} {level} [{module}] {body}" -date_format = "%Y-%m-%d" -time_format = "%H:%M:%S%:z" - -[mailbox] -# maximum number of messages to process in each execution of mailbox -# the mailbox will be rescheduled if there are any remaining messages -msg_process_limit = 1000 - -[dispatcher] -# number of threads available to the CPU pool -pool_size = 4 - -[scheduler] -frequency_millis = 50 - -[cqrs] -# number of seconds of inactivity after which a cqrs actor will sleep -sleep_after_secs = 120 From 4145a22a6b4a6d154108b11cf15968d9c5164aab Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 20:10:53 +1000 Subject: [PATCH 25/49] remove broken symlink --- core/config | 1 - 1 file changed, 1 deletion(-) delete mode 120000 core/config diff --git a/core/config b/core/config deleted file mode 120000 index 3ca249e06b..0000000000 --- a/core/config +++ /dev/null @@ -1 +0,0 @@ -../config \ No newline at end of file From 938c41ae77223fb0fe383841c3999db1bd8e945c Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 20:20:04 +1000 Subject: [PATCH 26/49] documentation for actor.rs --- core/src/actor.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/core/src/actor.rs b/core/src/actor.rs index 9997bbaad4..d34a36c045 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -8,10 +8,15 @@ use riker_patterns::ask::ask; use futures::executor::block_on; #[derive(Clone, Debug)] +/// riker protocol for all our actors +/// currently this is flat but may be nested/namespaced in the future or multi-protocol riker +/// @see https://github.com/riker-rs/riker/issues/17 pub enum Protocol { + /// Chain::set_top_pair() SetTopPair(Option), SetTopPairResult(Result, HolochainError>), + /// Chain::get_top_pair() GetTopPair, GetTopPairResult(Option), @@ -59,6 +64,10 @@ pub enum Protocol { CommitResult(Result<(), HolochainError>), } +/// this is the global state that manages every actor +/// to be thread/concurrency safe there must only ever be one actor system +/// @see https://github.com/riker-rs/riker/issues/17 +/// @see http://riker.rs/actors/#creating-actors lazy_static! { pub static ref SYS: ActorSystem = { let model: DefaultModel = DefaultModel::new(); @@ -66,18 +75,23 @@ lazy_static! { }; } +/// required by riker impl Into> for Protocol { fn into(self) -> ActorMsg { ActorMsg::User(self) } } +/// convenience trait to build fake synchronous facades for actors pub trait AskSelf { - fn ask(&self, message: Protocol) -> Protocol; + /// adapter for synchronous code to interact with an actor + /// uses the ask() fn from riker patterns under the hood to create a future then block on it + /// @see http://riker.rs/patterns/#ask + fn block_on_ask(&self, message: Protocol) -> Protocol; } impl AskSelf for ActorRef { - fn ask(&self, message: Protocol) -> Protocol { + fn block_on_ask(&self, message: Protocol) -> Protocol { let a = ask(&(*SYS), self, message); block_on(a).unwrap() } From 9824d0b15dae5a298e7ff48fbcec8cc45b101001 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 20:22:57 +1000 Subject: [PATCH 27/49] lint --- core/src/actor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/actor.rs b/core/src/actor.rs index d34a36c045..ab43a49e43 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -16,7 +16,7 @@ pub enum Protocol { SetTopPair(Option), SetTopPairResult(Result, HolochainError>), - /// Chain::get_top_pair() + /// Chain::top_pair() GetTopPair, GetTopPairResult(Option), @@ -55,7 +55,7 @@ pub enum Protocol { GetPairMeta(Pair), GetPairMetaResult(Result, HolochainError>), - /// HashTable::get() + /// HashTable::pair() GetPair(String), GetPairResult(Result, HolochainError>), From 2041b1f500102358b721274ed3cf4c3cccde459c Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 20:29:41 +1000 Subject: [PATCH 28/49] return reference to chain from agent state --- core/src/actor.rs | 1 + core/src/agent/state.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/actor.rs b/core/src/actor.rs index ab43a49e43..0a5893a3b6 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -86,6 +86,7 @@ impl Into> for Protocol { pub trait AskSelf { /// adapter for synchronous code to interact with an actor /// uses the ask() fn from riker patterns under the hood to create a future then block on it + /// handles passing the actor system through to ask() to hide that implementation detail /// @see http://riker.rs/patterns/#ask fn block_on_ask(&self, message: Protocol) -> Protocol; } diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index c8d03ff9f9..b81cc5f899 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -37,8 +37,8 @@ impl AgentState { } /// getter for the chain - pub fn chain(&self) -> Chain { - self.chain.clone() + pub fn chain(&self) -> &Chain { + &self.chain } /// getter for a copy of self.actions From 17e29426c94089f6c759a22511d7761f8c00bf0f Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 21:22:56 +1000 Subject: [PATCH 29/49] lint docs --- core/src/agent/state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index b81cc5f899..030efc0712 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -93,8 +93,8 @@ fn reduce_commit( let action = action_wrapper.action(); let entry = unwrap_to!(action => Action::Commit); - // @TODO successfully validate before pushing a commit - // @see https://github.com/holochain/holochain-rust/issues/97 + // @TODO validation dispatch should go here rather than upstream in invoke_commit + // @see https://github.com/holochain/holochain-rust/issues/256 state.actions.insert( action_wrapper.clone(), From ad248c00fc0ec88c57ad177f9f43bfb4da492d75 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 21:44:22 +1000 Subject: [PATCH 30/49] rename ask to block_on_ask --- core/src/agent/state.rs | 2 +- core/src/chain/actor.rs | 4 ++-- core/src/chain/mod.rs | 2 +- core/src/hash_table/actor.rs | 18 +++++++++--------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 030efc0712..43a752e593 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -121,7 +121,7 @@ fn reduce_get( state.actions.insert( action_wrapper.clone(), - ActionResponse::Get(result.clone().unwrap()), + ActionResponse::Get(result.clone().expect("should be able to get entry that we just added")), ); } diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 4ce3a27793..5ac9c0dc65 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -19,12 +19,12 @@ pub trait AskChain { impl AskChain for ActorRef { fn set_top_pair(&self, pair: &Option) -> Result, HolochainError> { - let response = self.ask(Protocol::SetTopPair(pair.clone())); + let response = self.block_on_ask(Protocol::SetTopPair(pair.clone())); unwrap_to!(response => Protocol::SetTopPairResult).clone() } fn top_pair(&self) -> Option { - let response = self.ask(Protocol::GetTopPair); + let response = self.block_on_ask(Protocol::GetTopPair); unwrap_to!(response => Protocol::GetTopPairResult).clone() } } diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index e71c62fb82..376fa4c1d5 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -184,7 +184,7 @@ impl SourceChain for Chain { /// get a Pair by Pair/Header key from the HashTable if it exists fn pair(&self, k: &str) -> Result, HolochainError> { - let response = self.table.ask(Protocol::GetPair(k.to_string())); + let response = self.table.block_on_ask(Protocol::GetPair(k.to_string())); unwrap_to!(response => Protocol::GetPairResult).clone() } diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index fdbee1c40b..a9a0bd9053 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -20,22 +20,22 @@ impl AskHashTable for ActorRef {} impl HashTable for ActorRef { fn setup(&mut self) -> Result<(), HolochainError> { - let response = self.ask(Protocol::Setup); + let response = self.block_on_ask(Protocol::Setup); unwrap_to!(response => Protocol::SetupResult).clone() } fn teardown(&mut self) -> Result<(), HolochainError> { - let response = self.ask(Protocol::Teardown); + let response = self.block_on_ask(Protocol::Teardown); unwrap_to!(response => Protocol::TeardownResult).clone() } fn commit(&mut self, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(Protocol::Commit(pair.clone())); + let response = self.block_on_ask(Protocol::Commit(pair.clone())); unwrap_to!(response => Protocol::CommitResult).clone() } fn pair(&self, key: &str) -> Result, HolochainError> { - let response = self.ask(Protocol::GetPair(key.to_string())); + let response = self.block_on_ask(Protocol::GetPair(key.to_string())); unwrap_to!(response => Protocol::GetPairResult).clone() } @@ -45,7 +45,7 @@ impl HashTable for ActorRef { old_pair: &Pair, new_pair: &Pair, ) -> Result<(), HolochainError> { - let response = self.ask(Protocol::Modify { + let response = self.block_on_ask(Protocol::Modify { keys: keys.clone(), old_pair: old_pair.clone(), new_pair: new_pair.clone(), @@ -54,7 +54,7 @@ impl HashTable for ActorRef { } fn retract(&mut self, keys: &Keys, pair: &Pair) -> Result<(), HolochainError> { - let response = self.ask(Protocol::Retract { + let response = self.block_on_ask(Protocol::Retract { keys: keys.clone(), pair: pair.clone(), }); @@ -62,17 +62,17 @@ impl HashTable for ActorRef { } fn assert_meta(&mut self, meta: &PairMeta) -> Result<(), HolochainError> { - let response = self.ask(Protocol::AssertMeta(meta.clone())); + let response = self.block_on_ask(Protocol::AssertMeta(meta.clone())); unwrap_to!(response => Protocol::AssertMetaResult).clone() } fn get_meta(&mut self, key: &str) -> Result, HolochainError> { - let response = self.ask(Protocol::GetMeta(key.to_string())); + let response = self.block_on_ask(Protocol::GetMeta(key.to_string())); unwrap_to!(response => Protocol::GetMetaResult).clone() } fn get_pair_meta(&mut self, pair: &Pair) -> Result, HolochainError> { - let response = self.ask(Protocol::GetPairMeta(pair.clone())); + let response = self.block_on_ask(Protocol::GetPairMeta(pair.clone())); unwrap_to!(response => Protocol::GetPairMetaResult).clone() } } From 4c4f041e509072516a31f68e2b56c1e2caef5794 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 22:05:07 +1000 Subject: [PATCH 31/49] test chain actor round trip --- core/src/chain/actor.rs | 57 ++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 5ac9c0dc65..8671c25054 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -1,10 +1,7 @@ -// use riker_default::DefaultModel; use riker::actors::*; use snowflake; use hash_table::pair::Pair; use error::HolochainError; -// use riker_patterns::ask::ask; -// use futures::executor::block_on; use actor::SYS; use actor::Protocol; use actor::AskSelf; @@ -12,7 +9,6 @@ use actor::AskSelf; /// anything that can be asked of Chain and block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskChain { - // fn ask(&self, message: Protocol) -> Protocol; fn set_top_pair(&self, &Option) -> Result, HolochainError>; fn top_pair(&self) -> Option; } @@ -34,27 +30,32 @@ pub struct ChainActor { } impl ChainActor { - pub fn new() -> ChainActor { + /// returns a new ChainActor struct + /// internal use for riker, use new_ref instead + fn new() -> ChainActor { ChainActor { top_pair: None, } } - pub fn actor() -> BoxActor { + /// actor() for riker + fn actor() -> BoxActor { Box::new(ChainActor::new()) } - pub fn props() -> BoxActorProd { + /// props() for riker + fn props() -> BoxActorProd { Props::new(Box::new(ChainActor::actor)) } + /// returns a new actor ref for a new actor in the main actor system pub fn new_ref() -> ActorRef { SYS .actor_of( ChainActor::props(), &snowflake::ProcessUniqueId::new().to_string(), ) - .unwrap() + .expect("could not create ChainActor in actor system") } } @@ -86,7 +87,45 @@ impl Actor for ChainActor { }, Some(context.myself()), ) - .unwrap(); + .expect("failed to tell ChainActor sender"); + } + +} + +#[cfg(test)] +pub mod tests { + use riker::actors::*; + use chain::actor::ChainActor; + use actor::Protocol; + use hash_table::pair::tests::test_pair_a; + use hash_table::pair::tests::test_pair_b; + use chain::actor::AskChain; + + pub fn test_chain_actor() -> ActorRef { + ChainActor::new_ref() + } + + #[test] + /// smoke test new refs + fn test_new_ref() { + test_chain_actor(); + } + + #[test] + fn test_round_trip() { + let chain_actor = test_chain_actor(); + + assert_eq!(None, chain_actor.top_pair()); + + let pair_a = test_pair_a(); + chain_actor.set_top_pair(&Some(pair_a.clone())); + + assert_eq!(Some(pair_a.clone()), chain_actor.top_pair()); + + let pair_b = test_pair_b(); + chain_actor.set_top_pair(&Some(pair_b.clone())); + + assert_eq!(Some(pair_b.clone()), chain_actor.top_pair()); } } From c0d1820c01f8564026a6773992ed79afe5161fd3 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 22:29:04 +1000 Subject: [PATCH 32/49] remove Get in protocol variant names --- core/src/actor.rs | 16 ++++++++-------- core/src/chain/actor.rs | 14 +++++++++----- core/src/chain/mod.rs | 6 ++---- core/src/hash_table/actor.rs | 36 ++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/core/src/actor.rs b/core/src/actor.rs index 0a5893a3b6..0196412ee6 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -17,8 +17,8 @@ pub enum Protocol { SetTopPairResult(Result, HolochainError>), /// Chain::top_pair() - GetTopPair, - GetTopPairResult(Option), + TopPair, + TopPairResult(Option), /// HashTable::setup() Setup, @@ -48,16 +48,16 @@ pub enum Protocol { AssertMetaResult(Result<(), HolochainError>), /// HashTable::get_meta() - GetMeta(String), - GetMetaResult(Result, HolochainError>), + Meta(String), + MetaResult(Result, HolochainError>), /// HashTable::get_pair_meta() - GetPairMeta(Pair), - GetPairMetaResult(Result, HolochainError>), + PairMeta(Pair), + PairMetaResult(Result, HolochainError>), /// HashTable::pair() - GetPair(String), - GetPairResult(Result, HolochainError>), + Pair(String), + PairResult(Result, HolochainError>), /// HashTable::commit() Commit(Pair), diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 8671c25054..aab076b07e 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -9,7 +9,9 @@ use actor::AskSelf; /// anything that can be asked of Chain and block on responses /// needed to support implementing ask on upstream ActorRef from riker pub trait AskChain { + /// Protocol::SetTopPair -> Protocol::SetTopPairResult fn set_top_pair(&self, &Option) -> Result, HolochainError>; + /// Protocol::TopPair -> Protocol::TopPairResult fn top_pair(&self) -> Option; } @@ -20,8 +22,8 @@ impl AskChain for ActorRef { } fn top_pair(&self) -> Option { - let response = self.block_on_ask(Protocol::GetTopPair); - unwrap_to!(response => Protocol::GetTopPairResult).clone() + let response = self.block_on_ask(Protocol::TopPair); + unwrap_to!(response => Protocol::TopPairResult).clone() } } @@ -71,17 +73,19 @@ impl Actor for ChainActor { sender.try_tell( // deliberately exhaustively matching here, don't give into _ temptation match message { + // set the top pair to the value passed Protocol::SetTopPair(p) => { self.top_pair = p; Protocol::SetTopPairResult(Ok(self.top_pair.clone())) }, Protocol::SetTopPairResult(_) => unreachable!(), - Protocol::GetTopPair => { + // evaluates to the current top pair + Protocol::TopPair => { let ret = self.top_pair.clone(); - Protocol::GetTopPairResult(ret) + Protocol::TopPairResult(ret) }, - Protocol::GetTopPairResult(_) => unreachable!(), + Protocol::TopPairResult(_) => unreachable!(), _ => unreachable!(), }, diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 376fa4c1d5..b9a6365b94 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -2,10 +2,8 @@ pub mod actor; use error::HolochainError; use hash_table::{ - // actor::{AskHashTable}, entry::Entry, pair::Pair, - // HashTable, }; use riker::actors::*; use serde_json; @@ -184,8 +182,8 @@ impl SourceChain for Chain { /// get a Pair by Pair/Header key from the HashTable if it exists fn pair(&self, k: &str) -> Result, HolochainError> { - let response = self.table.block_on_ask(Protocol::GetPair(k.to_string())); - unwrap_to!(response => Protocol::GetPairResult).clone() + let response = self.table.block_on_ask(Protocol::Pair(k.to_string())); + unwrap_to!(response => Protocol::PairResult).clone() } /// get an Entry by Entry key from the HashTable if it exists diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index a9a0bd9053..6ad1ff9d9f 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,12 +1,8 @@ use agent::keys::Keys; use error::HolochainError; -// use futures::executor::block_on; use hash_table::{pair::Pair, pair_meta::PairMeta,}; use riker::actors::*; -// use riker_default::DefaultModel; -// use riker_patterns::ask::ask; use snowflake; -// use actor::Protocol; use actor::SYS; use actor::AskSelf; use actor::Protocol; @@ -35,8 +31,8 @@ impl HashTable for ActorRef { } fn pair(&self, key: &str) -> Result, HolochainError> { - let response = self.block_on_ask(Protocol::GetPair(key.to_string())); - unwrap_to!(response => Protocol::GetPairResult).clone() + let response = self.block_on_ask(Protocol::Pair(key.to_string())); + unwrap_to!(response => Protocol::PairResult).clone() } fn modify( @@ -67,13 +63,13 @@ impl HashTable for ActorRef { } fn get_meta(&mut self, key: &str) -> Result, HolochainError> { - let response = self.block_on_ask(Protocol::GetMeta(key.to_string())); - unwrap_to!(response => Protocol::GetMetaResult).clone() + let response = self.block_on_ask(Protocol::Meta(key.to_string())); + unwrap_to!(response => Protocol::MetaResult).clone() } fn get_pair_meta(&mut self, pair: &Pair) -> Result, HolochainError> { - let response = self.block_on_ask(Protocol::GetPairMeta(pair.clone())); - unwrap_to!(response => Protocol::GetPairMetaResult).clone() + let response = self.block_on_ask(Protocol::PairMeta(pair.clone())); + unwrap_to!(response => Protocol::PairMetaResult).clone() } } @@ -131,10 +127,10 @@ impl Actor for HashTableActor { } Protocol::CommitResult(_) => unreachable!(), - Protocol::GetPair(hash) => { - Protocol::GetPairResult(self.table.pair(&hash)) + Protocol::Pair(hash) => { + Protocol::PairResult(self.table.pair(&hash)) } - Protocol::GetPairResult(_) => unreachable!(), + Protocol::PairResult(_) => unreachable!(), Protocol::Modify { keys, @@ -155,21 +151,21 @@ impl Actor for HashTableActor { } Protocol::AssertMetaResult(_) => unreachable!(), - Protocol::GetMeta(key) => { - Protocol::GetMetaResult(self.table.get_meta(&key)) + Protocol::Meta(key) => { + Protocol::MetaResult(self.table.get_meta(&key)) } - Protocol::GetMetaResult(_) => unreachable!(), + Protocol::MetaResult(_) => unreachable!(), - Protocol::GetPairMeta(pair) => { - Protocol::GetPairMetaResult(self.table.get_pair_meta(&pair)) + Protocol::PairMeta(pair) => { + Protocol::PairMetaResult(self.table.get_pair_meta(&pair)) } - Protocol::GetPairMetaResult(_) => unreachable!(), + Protocol::PairMetaResult(_) => unreachable!(), _ => unreachable!(), }, Some(context.myself()), ) - .unwrap(); + .expect("could not tell to HashTableActor sender"); } } From 86abfe9f154d0b3bc34af62203453bbd8ba5af0d Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 22:46:59 +1000 Subject: [PATCH 33/49] fix compiler issues --- core/src/chain/mod.rs | 15 ++++++++++----- core/src/nucleus/ribosome/api/get.rs | 4 +++- core/src/nucleus/ribosome/api/mod.rs | 5 +++-- docker/Dockerfile.ubuntu | 6 +++--- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index b9a6365b94..b9d246f893 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -590,9 +590,10 @@ pub mod tests { .push_entry(&entry1) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( - Some(pair1), + Some(&pair1), chain .top_pair_type(&test_type_a()) + .as_ref() ); assert_eq!( None, @@ -606,14 +607,16 @@ pub mod tests { .push_entry(&entry2) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( - Some(pair1), + Some(&pair1), chain .top_pair_type(&test_type_a()) + .as_ref() ); assert_eq!( - Some(pair2), + Some(&pair2), chain .top_pair_type(&test_type_b()) + .as_ref() ); // type a should be pair3 @@ -623,14 +626,16 @@ pub mod tests { .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!( - Some(pair3), + Some(&pair3), chain .top_pair_type(&test_type_a()) + .as_ref() ); assert_eq!( - Some(pair2), + Some(&pair2), chain .top_pair_type(&test_type_b()) + .as_ref() ); } diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index 36d378f77c..e86496a553 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -162,7 +162,7 @@ mod tests { &test_capability(), wasm.clone(), ); - let instance = test_instance(dna); + let instance = test_instance(dna.clone()); let (context, _) = test_context_and_logger("joan"); let commit_call = FunctionCall::new( @@ -172,6 +172,7 @@ mod tests { &test_parameters(), ); let commit_runtime = call( + &dna.name.to_string(), Arc::clone(&context), &instance.action_channel(), &instance.observer_channel(), @@ -192,6 +193,7 @@ mod tests { &test_parameters(), ); let get_runtime = call( + &dna.name.to_string(), Arc::clone(&context), &instance.action_channel(), &instance.observer_channel(), diff --git a/core/src/nucleus/ribosome/api/mod.rs b/core/src/nucleus/ribosome/api/mod.rs index 8aeaf4b6fa..c5d2b1cd7e 100644 --- a/core/src/nucleus/ribosome/api/mod.rs +++ b/core/src/nucleus/ribosome/api/mod.rs @@ -441,6 +441,7 @@ pub mod tests { } pub fn test_zome_api_function_call( + app_name: &str, context: Arc, logger: Arc>, instance: &Instance, @@ -482,10 +483,10 @@ pub mod tests { &test_capability(), wasm.clone(), ); - let instance = test_instance(dna); + let instance = test_instance(dna.clone()); let (context, logger) = test_context_and_logger("joan"); - test_zome_api_function_call(context, logger, &instance, &wasm, args_bytes) + test_zome_api_function_call(&dna.name.to_string(), context, logger, &instance, &wasm, args_bytes) } #[test] diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu index 5c5b39281d..0989515e47 100644 --- a/docker/Dockerfile.ubuntu +++ b/docker/Dockerfile.ubuntu @@ -7,13 +7,13 @@ ENV DEBIAN_FRONTEND noninteractive ENV DOCKER_BUILD_USER holochain # The Rust version used for the Wasm builds -ENV WASM_NIGHTLY nightly-2018-08-06 +ENV WASM_NIGHTLY nightly-2018-06-01 # The Rust version used for the tools -ENV TOOLS_NIGHTLY nightly-2018-08-06 +ENV TOOLS_NIGHTLY nightly-2018-07-17 # The Rust version that is used everywhere else -ENV CORE_RUST_VERSION nightly-2018-08-06 +ENV CORE_RUST_VERSION nightly-2018-06-01 RUN apt-get update && apt-get install --yes\ libssl-dev \ From eb172a170e45d6ca063ba8d8517730cd10272393 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:20:09 +1000 Subject: [PATCH 34/49] polish for PR --- core/src/chain/actor.rs | 4 +-- core/src/chain/mod.rs | 49 +++++++++++++++------------- core/src/instance.rs | 4 +-- core/src/nucleus/ribosome/api/get.rs | 10 +++--- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index aab076b07e..54028a0fa2 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -122,12 +122,12 @@ pub mod tests { assert_eq!(None, chain_actor.top_pair()); let pair_a = test_pair_a(); - chain_actor.set_top_pair(&Some(pair_a.clone())); + chain_actor.set_top_pair(&Some(pair_a.clone())).expect("could not set top pair a"); assert_eq!(Some(pair_a.clone()), chain_actor.top_pair()); let pair_b = test_pair_b(); - chain_actor.set_top_pair(&Some(pair_b.clone())); + chain_actor.set_top_pair(&Some(pair_b.clone())).expect("could not set top pair b"); assert_eq!(Some(pair_b.clone()), chain_actor.top_pair()); } diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index b9d246f893..80679d3bd7 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -57,6 +57,7 @@ pub struct Chain { impl PartialEq for Chain { // @TODO can we just check the actors are equal? is actor equality a thing? + // @see https://github.com/holochain/holochain-rust/issues/257 fn eq(&self, other: &Chain) -> bool { // an invalid chain is like NaN... not even equal to itself self.validate() && @@ -128,8 +129,31 @@ impl Chain { } } +// @TODO should SourceChain have a bound on HashTable for consistency? +// @see https://github.com/holochain/holochain-rust/issues/261 +pub trait SourceChain { + /// sets an option for the top Pair + fn set_top_pair(&self, &Option) -> Result, HolochainError>; + /// returns an option for the top Pair + fn top_pair(&self) -> Option; + /// get the top Pair by Entry type + fn top_pair_type(&self, t: &str) -> Option; + + /// push a new Entry on to the top of the Chain + /// the Pair for the new Entry is automatically generated and validated against the current top + /// Pair to ensure the chain links up correctly across the underlying table data + /// the newly created and pushed Pair is returned in the fn Result + fn push_entry(&mut self, entry: &Entry) -> Result; + /// get an Entry by Entry key from the HashTable if it exists + fn entry(&self, entry_hash: &str) -> Result, HolochainError>; + + /// pair-oriented version of push_entry() + fn push_pair(&mut self, pair: &Pair) -> Result; + /// get a Pair by Pair/Header key from the HashTable if it exists + fn pair(&self, message: &str) -> Result, HolochainError>; +} + impl SourceChain for Chain { - /// returns a reference to the top Pair fn top_pair(&self) -> Option { self.actor.top_pair() } @@ -138,12 +162,10 @@ impl SourceChain for Chain { self.actor.set_top_pair(&pair) } - /// get the top Pair by Entry type fn top_pair_type(&self, t: &str) -> Option { self.iter().find(|p| p.header().entry_type() == t) } - /// private pair-oriented version of push() (which expects Entries) fn push_pair(&mut self, pair: &Pair) -> Result { if !(pair.validate()) { return Err(HolochainError::new( @@ -165,28 +187,24 @@ impl SourceChain for Chain { // @TODO instead of unwrapping this, move all the above validation logic inside of // set_top_pair() + // @see https://github.com/holochain/holochain-rust/issues/258 // @TODO if top pair set fails but commit succeeds? + // @see https://github.com/holochain/holochain-rust/issues/259 self.set_top_pair(&Some(pair.clone()))?; Ok(pair.clone()) } - /// push a new Entry on to the top of the Chain - /// the Pair for the new Entry is automatically generated and validated against the current top - /// Pair to ensure the chain links up correctly across the underlying table data - /// the newly created and pushed Pair is returned in the fn Result fn push_entry(&mut self, entry: &Entry) -> Result { let pair = Pair::new(self, entry); self.push_pair(&pair) } - /// get a Pair by Pair/Header key from the HashTable if it exists fn pair(&self, k: &str) -> Result, HolochainError> { let response = self.table.block_on_ask(Protocol::Pair(k.to_string())); unwrap_to!(response => Protocol::PairResult).clone() } - /// get an Entry by Entry key from the HashTable if it exists fn entry(&self, entry_hash: &str) -> Result, HolochainError> { // @TODO - this is a slow way to do a lookup // @see https://github.com/holochain/holochain-rust/issues/50 @@ -198,19 +216,6 @@ impl SourceChain for Chain { } } -// @TODO should SourceChain have a bound on HashTable for consistency? -pub trait SourceChain { - fn set_top_pair(&self, &Option) -> Result, HolochainError>; - fn top_pair(&self) -> Option; - fn top_pair_type(&self, t: &str) -> Option; - - fn push_entry(&mut self, entry: &Entry) -> Result; - fn entry(&self, entry_hash: &str) -> Result, HolochainError>; - - fn push_pair(&mut self, pair: &Pair) -> Result; - fn pair(&self, message: &str) -> Result, HolochainError>; -} - #[cfg(test)] pub mod tests { diff --git a/core/src/instance.rs b/core/src/instance.rs index bcc9bc3ecb..7615a532e6 100644 --- a/core/src/instance.rs +++ b/core/src/instance.rs @@ -246,7 +246,6 @@ pub mod tests { extern crate test_utils; use super::Instance; use action::{tests::test_action_wrapper_get, Action, ActionWrapper}; - use agent::state::tests::test_action_response_get; use context::Context; use hash_table::sys_entry::EntryType; use holochain_agent::Agent; @@ -261,6 +260,7 @@ pub mod tests { thread::sleep, time::Duration, }; + use agent::state::ActionResponse; #[derive(Clone, Debug)] pub struct TestLogger { @@ -439,7 +439,7 @@ pub mod tests { .get(&aw) .expect("action and reponse should be added after Get action dispatch"); - assert_eq!(response, &test_action_response_get()); + assert_eq!(response, &ActionResponse::Get(None)); } /// create a test instance with a blank DNA diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index e86496a553..ff85348b5b 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -91,6 +91,8 @@ mod tests { }; use serde_json; use std::sync::Arc; + use nucleus::ribosome::api::ZomeAPIFunction; + use nucleus::ribosome::Defn; /// dummy get args from standard test entry pub fn test_get_args_bytes() -> Vec { @@ -107,14 +109,14 @@ mod tests { .convert( r#" (module - (import "env" "get" + (import "env" "hc_get_entry" (func $get (param i32) (result i32) ) ) - (import "env" "commit" + (import "env" "hc_commit_entry" (func $commit (param i32) (result i32) @@ -168,7 +170,7 @@ mod tests { let commit_call = FunctionCall::new( &test_zome_name(), &test_capability(), - &"commit", + "commit", &test_parameters(), ); let commit_runtime = call( @@ -189,7 +191,7 @@ mod tests { let get_call = FunctionCall::new( &test_zome_name(), &test_capability(), - &"get", + "get", &test_parameters(), ); let get_runtime = call( From 9b66a68b8b7d15ed1ff49827047d551c4af38d76 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:21:23 +1000 Subject: [PATCH 35/49] remove broken symlink --- core_api/config | 1 - 1 file changed, 1 deletion(-) delete mode 120000 core_api/config diff --git a/core_api/config b/core_api/config deleted file mode 120000 index 3ca249e06b..0000000000 --- a/core_api/config +++ /dev/null @@ -1 +0,0 @@ -../config \ No newline at end of file From f5636d6c051ab2f596b1869d7f442bd537cd2d5f Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:23:11 +1000 Subject: [PATCH 36/49] lint --- core/src/state.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/state.rs b/core/src/state.rs index 929ef59a82..4700f9fa2a 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -22,6 +22,7 @@ pub struct State { impl State { pub fn new() -> Self { // @TODO file table + // @see https://github.com/holochain/holochain-rust/pull/246 let chain = Chain::new(HashTableActor::new_ref(MemTable::new())); State { From d464a0275275bd25841a3bae08b0914152d73daa Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:25:36 +1000 Subject: [PATCH 37/49] lint --- core/src/nucleus/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/nucleus/mod.rs b/core/src/nucleus/mod.rs index 5d24b82b5d..0cc7f49d54 100644 --- a/core/src/nucleus/mod.rs +++ b/core/src/nucleus/mod.rs @@ -35,8 +35,8 @@ pub struct FunctionCall { impl FunctionCall { pub fn new(zome: &str, capability: &str, function: &str, parameters: &str) -> Self { FunctionCall { - // @TODO - // can we defer to the ActionWrapper id? + // @TODO can we defer to the ActionWrapper id? + // @see https://github.com/holochain/holochain-rust/issues/198 id: snowflake::ProcessUniqueId::new(), zome: zome.to_string(), capability: capability.to_string(), From 9d4f37cf4f4b034e3fc4c066657defa96abb3bde Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:28:38 +1000 Subject: [PATCH 38/49] lint docs --- core/src/nucleus/ribosome/api/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/nucleus/ribosome/api/mod.rs b/core/src/nucleus/ribosome/api/mod.rs index c5d2b1cd7e..22b8c36f30 100644 --- a/core/src/nucleus/ribosome/api/mod.rs +++ b/core/src/nucleus/ribosome/api/mod.rs @@ -424,22 +424,28 @@ pub mod tests { .to_vec() } + /// dummy zome name pub fn test_zome_name() -> String { "test_zome".to_string() } + /// dummy capability pub fn test_capability() -> String { ReservedCapabilityNames::MissingNo.as_str().to_string() } + /// dummy zome API function name pub fn test_function_name() -> String { "test".to_string() } + /// dummy parameters for a zome API function call pub fn test_parameters() -> String { String::new() } + /// calls the zome API function with passed bytes argument using the instance runtime + /// returns the runtime after the call completes pub fn test_zome_api_function_call( app_name: &str, context: Arc, From 9bb98ea209eb9a5acc8f2673e7c6222dbe34635e Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:30:18 +1000 Subject: [PATCH 39/49] lint docs --- core/src/nucleus/ribosome/api/get.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index ff85348b5b..3ddf821a33 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -102,6 +102,7 @@ mod tests { serde_json::to_string(&args).unwrap().into_bytes() } + /// wat string that exports both get and a commit dispatches so we can test a round trip pub fn test_get_round_trip_wat() -> Vec { Wat2Wasm::new() .canonicalize_lebs(false) From e1e463582655dd46acae7a1ddae4ebd650e001d7 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:33:35 +1000 Subject: [PATCH 40/49] lint docs --- core/src/hash_table/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/hash_table/mod.rs b/core/src/hash_table/mod.rs index 34f90c0077..098c239c40 100644 --- a/core/src/hash_table/mod.rs +++ b/core/src/hash_table/mod.rs @@ -19,6 +19,7 @@ pub type HashString = String; pub trait HashTable: Send + Sync + Clone + 'static { // internal state management // @TODO does this make sense at the trait level? + // @see https://github.com/holochain/holochain-rust/issues/262 fn setup(&mut self) -> Result<(), HolochainError>; fn teardown(&mut self) -> Result<(), HolochainError>; From a1a4a345f2e64a5e36d121d467acb85cb54e8b4a Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:40:42 +1000 Subject: [PATCH 41/49] fmt --- core/src/actor.rs | 11 ++-- core/src/agent/state.rs | 6 +- core/src/chain/actor.rs | 79 ++++++++++++------------- core/src/chain/mod.rs | 87 +++++++++------------------- core/src/hash_table/actor.rs | 76 ++++++------------------ core/src/hash_table/memory/mod.rs | 28 ++++++--- core/src/instance.rs | 2 +- core/src/lib.rs | 2 +- core/src/nucleus/ribosome/api/get.rs | 14 +++-- core/src/nucleus/ribosome/api/mod.rs | 9 ++- 10 files changed, 128 insertions(+), 186 deletions(-) diff --git a/core/src/actor.rs b/core/src/actor.rs index 0196412ee6..740dbeaf39 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -1,11 +1,10 @@ -use riker_default::DefaultModel; -use riker::actors::*; -use hash_table::pair::Pair; -use error::HolochainError; use agent::keys::Keys; -use hash_table::pair_meta::PairMeta; -use riker_patterns::ask::ask; +use error::HolochainError; use futures::executor::block_on; +use hash_table::{pair::Pair, pair_meta::PairMeta}; +use riker::actors::*; +use riker_default::DefaultModel; +use riker_patterns::ask::ask; #[derive(Clone, Debug)] /// riker protocol for all our actors diff --git a/core/src/agent/state.rs b/core/src/agent/state.rs index 43a752e593..e95806a31d 100644 --- a/core/src/agent/state.rs +++ b/core/src/agent/state.rs @@ -121,7 +121,11 @@ fn reduce_get( state.actions.insert( action_wrapper.clone(), - ActionResponse::Get(result.clone().expect("should be able to get entry that we just added")), + ActionResponse::Get( + result + .clone() + .expect("should be able to get entry that we just added"), + ), ); } diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 54028a0fa2..78f61d503e 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -1,10 +1,8 @@ +use actor::{AskSelf, Protocol, SYS}; +use error::HolochainError; +use hash_table::pair::Pair; use riker::actors::*; use snowflake; -use hash_table::pair::Pair; -use error::HolochainError; -use actor::SYS; -use actor::Protocol; -use actor::AskSelf; /// anything that can be asked of Chain and block on responses /// needed to support implementing ask on upstream ActorRef from riker @@ -35,9 +33,7 @@ impl ChainActor { /// returns a new ChainActor struct /// internal use for riker, use new_ref instead fn new() -> ChainActor { - ChainActor { - top_pair: None, - } + ChainActor { top_pair: None } } /// actor() for riker @@ -52,12 +48,10 @@ impl ChainActor { /// returns a new actor ref for a new actor in the main actor system pub fn new_ref() -> ActorRef { - SYS - .actor_of( - ChainActor::props(), - &snowflake::ProcessUniqueId::new().to_string(), - ) - .expect("could not create ChainActor in actor system") + SYS.actor_of( + ChainActor::props(), + &snowflake::ProcessUniqueId::new().to_string(), + ).expect("could not create ChainActor in actor system") } } @@ -70,40 +64,35 @@ impl Actor for ChainActor { message: Self::Msg, sender: Option>, ) { - sender.try_tell( - // deliberately exhaustively matching here, don't give into _ temptation - match message { - // set the top pair to the value passed - Protocol::SetTopPair(p) => { - self.top_pair = p; - Protocol::SetTopPairResult(Ok(self.top_pair.clone())) - }, - Protocol::SetTopPairResult(_) => unreachable!(), - - // evaluates to the current top pair - Protocol::TopPair => { - let ret = self.top_pair.clone(); - Protocol::TopPairResult(ret) + sender + .try_tell( + match message { + // set the top pair to the value passed + Protocol::SetTopPair(p) => { + self.top_pair = p; + Protocol::SetTopPairResult(Ok(self.top_pair.clone())) + } + + // evaluates to the current top pair + Protocol::TopPair => { + let ret = self.top_pair.clone(); + Protocol::TopPairResult(ret) + } + + _ => unreachable!(), }, - Protocol::TopPairResult(_) => unreachable!(), - - _ => unreachable!(), - }, - Some(context.myself()), - ) - .expect("failed to tell ChainActor sender"); + Some(context.myself()), + ) + .expect("failed to tell ChainActor sender"); } - } #[cfg(test)] pub mod tests { - use riker::actors::*; - use chain::actor::ChainActor; use actor::Protocol; - use hash_table::pair::tests::test_pair_a; - use hash_table::pair::tests::test_pair_b; - use chain::actor::AskChain; + use chain::actor::{AskChain, ChainActor}; + use hash_table::pair::tests::{test_pair_a, test_pair_b}; + use riker::actors::*; pub fn test_chain_actor() -> ActorRef { ChainActor::new_ref() @@ -122,12 +111,16 @@ pub mod tests { assert_eq!(None, chain_actor.top_pair()); let pair_a = test_pair_a(); - chain_actor.set_top_pair(&Some(pair_a.clone())).expect("could not set top pair a"); + chain_actor + .set_top_pair(&Some(pair_a.clone())) + .expect("could not set top pair a"); assert_eq!(Some(pair_a.clone()), chain_actor.top_pair()); let pair_b = test_pair_b(); - chain_actor.set_top_pair(&Some(pair_b.clone())).expect("could not set top pair b"); + chain_actor + .set_top_pair(&Some(pair_b.clone())) + .expect("could not set top pair b"); assert_eq!(Some(pair_b.clone()), chain_actor.top_pair()); } diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 80679d3bd7..1ac8a28e8f 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -1,17 +1,11 @@ pub mod actor; +use actor::{AskSelf, Protocol}; +use chain::actor::{AskChain, ChainActor}; use error::HolochainError; -use hash_table::{ - entry::Entry, - pair::Pair, -}; +use hash_table::{entry::Entry, pair::Pair, HashTable}; use riker::actors::*; use serde_json; -use chain::actor::ChainActor; -use chain::actor::AskChain; -use actor::Protocol; -use actor::AskSelf; -use hash_table::HashTable; /// Iterator type for pairs in a chain /// next method may panic if there is an error in the underlying table @@ -225,8 +219,8 @@ pub mod tests { actor::tests::test_table_actor, entry::tests::{test_entry, test_entry_a, test_entry_b, test_type_a, test_type_b}, pair::Pair, + HashTable, }; - use hash_table::HashTable; /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -249,11 +243,14 @@ pub mod tests { let entry_a = test_entry_a(); let entry_b = test_entry_b(); - chain1.push_entry(&entry_a) + chain1 + .push_entry(&entry_a) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - chain2.push_entry(&entry_a) + chain2 + .push_entry(&entry_a) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - chain3.push_entry(&entry_b) + chain3 + .push_entry(&entry_b) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); assert_eq!(chain1.top_pair(), chain2.top_pair()); @@ -311,8 +308,12 @@ pub mod tests { .push_entry(&test_entry()) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - let table_pair = table_actor.pair(&pair.key()).expect("getting an entry from a table in a chain shouldn't fail"); - let chain_pair = chain.pair(&pair.key()).expect("getting an entry from a chain shouldn't fail"); + let table_pair = table_actor + .pair(&pair.key()) + .expect("getting an entry from a table in a chain shouldn't fail"); + let chain_pair = chain + .pair(&pair.key()) + .expect("getting an entry from a chain shouldn't fail"); assert_eq!(Some(&pair), table_pair.as_ref()); assert_eq!(Some(&pair), chain_pair.as_ref()); @@ -379,7 +380,8 @@ pub mod tests { assert_eq!( Some(&pair), - chain.pair(&pair.key()) + chain + .pair(&pair.key()) .expect("getting an entry from a chain shouldn't fail") .as_ref() ); @@ -574,16 +576,8 @@ pub mod tests { fn top_type() { let mut chain = test_chain(); - assert_eq!( - None, - chain - .top_pair_type(&test_type_a()) - ); - assert_eq!( - None, - chain - .top_pair_type(&test_type_b()) - ); + assert_eq!(None, chain.top_pair_type(&test_type_a())); + assert_eq!(None, chain.top_pair_type(&test_type_b())); let entry1 = test_entry_a(); let entry2 = test_entry_b(); @@ -594,35 +588,16 @@ pub mod tests { let pair1 = chain .push_entry(&entry1) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - assert_eq!( - Some(&pair1), - chain - .top_pair_type(&test_type_a()) - .as_ref() - ); - assert_eq!( - None, - chain - .top_pair_type(&test_type_b()) - ); + assert_eq!(Some(&pair1), chain.top_pair_type(&test_type_a()).as_ref()); + assert_eq!(None, chain.top_pair_type(&test_type_b())); // type a should still be pair1 // type b should be p2 let pair2 = chain .push_entry(&entry2) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - assert_eq!( - Some(&pair1), - chain - .top_pair_type(&test_type_a()) - .as_ref() - ); - assert_eq!( - Some(&pair2), - chain - .top_pair_type(&test_type_b()) - .as_ref() - ); + assert_eq!(Some(&pair1), chain.top_pair_type(&test_type_a()).as_ref()); + assert_eq!(Some(&pair2), chain.top_pair_type(&test_type_b()).as_ref()); // type a should be pair3 // type b should still be pair2 @@ -630,18 +605,8 @@ pub mod tests { .push_entry(&entry3) .expect("pushing a valid entry to an exlusively owned chain shouldn't fail"); - assert_eq!( - Some(&pair3), - chain - .top_pair_type(&test_type_a()) - .as_ref() - ); - assert_eq!( - Some(&pair2), - chain - .top_pair_type(&test_type_b()) - .as_ref() - ); + assert_eq!(Some(&pair3), chain.top_pair_type(&test_type_a()).as_ref()); + assert_eq!(Some(&pair2), chain.top_pair_type(&test_type_b()).as_ref()); } #[test] diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index 6ad1ff9d9f..ba8e404ffe 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -1,12 +1,9 @@ +use actor::{AskSelf, Protocol, SYS}; use agent::keys::Keys; use error::HolochainError; -use hash_table::{pair::Pair, pair_meta::PairMeta,}; +use hash_table::{pair::Pair, pair_meta::PairMeta, HashTable}; use riker::actors::*; use snowflake; -use actor::SYS; -use actor::AskSelf; -use actor::Protocol; -use hash_table::HashTable; // anything that can be asked of HashTable and block on responses // needed to support implementing ask on upstream ActorRef from riker @@ -92,12 +89,10 @@ impl HashTableActor { } pub fn new_ref(table: HT) -> ActorRef { - SYS - .actor_of( - HashTableActor::props(table), - &snowflake::ProcessUniqueId::new().to_string(), - ) - .unwrap() + SYS.actor_of( + HashTableActor::props(table), + &snowflake::ProcessUniqueId::new().to_string(), + ).unwrap() } } @@ -112,54 +107,34 @@ impl Actor for HashTableActor { ) { sender .try_tell( - // deliberately exhaustively matching here, don't give into _ temptation + // every Protocol for HashTable maps directly to a method of the same name match message { Protocol::Setup => Protocol::SetupResult(self.table.setup()), - Protocol::SetupResult(_) => unreachable!(), - Protocol::Teardown => { - Protocol::TeardownResult(self.table.teardown()) - } - Protocol::TeardownResult(_) => unreachable!(), + Protocol::Teardown => Protocol::TeardownResult(self.table.teardown()), - Protocol::Commit(pair) => { - Protocol::CommitResult(self.table.commit(&pair)) - } - Protocol::CommitResult(_) => unreachable!(), + Protocol::Commit(pair) => Protocol::CommitResult(self.table.commit(&pair)), - Protocol::Pair(hash) => { - Protocol::PairResult(self.table.pair(&hash)) - } - Protocol::PairResult(_) => unreachable!(), + Protocol::Pair(hash) => Protocol::PairResult(self.table.pair(&hash)), Protocol::Modify { keys, old_pair, new_pair, - } => Protocol::ModifyResult( - self.table.modify(&keys, &old_pair, &new_pair), - ), - Protocol::ModifyResult(_) => unreachable!(), - + } => Protocol::ModifyResult(self.table.modify(&keys, &old_pair, &new_pair)), Protocol::Retract { keys, pair } => { Protocol::RetractResult(self.table.retract(&keys, &pair)) } - Protocol::RetractResult(_) => unreachable!(), Protocol::AssertMeta(pair_meta) => { Protocol::AssertMetaResult(self.table.assert_meta(&pair_meta)) } - Protocol::AssertMetaResult(_) => unreachable!(), - Protocol::Meta(key) => { - Protocol::MetaResult(self.table.get_meta(&key)) - } - Protocol::MetaResult(_) => unreachable!(), + Protocol::Meta(key) => Protocol::MetaResult(self.table.get_meta(&key)), Protocol::PairMeta(pair) => { Protocol::PairMetaResult(self.table.get_pair_meta(&pair)) } - Protocol::PairMetaResult(_) => unreachable!(), _ => unreachable!(), }, @@ -173,15 +148,11 @@ impl Actor for HashTableActor { pub mod tests { use super::HashTableActor; - use hash_table::{memory::tests::test_table}; - use riker::actors::*; - use hash::tests::test_hash; - // use hash_table::HashTable; - use hash_table::pair::tests::test_pair; - use std::thread; - use std::sync::mpsc; use actor::Protocol; - use hash_table::HashTable; + use hash::tests::test_hash; + use hash_table::{memory::tests::test_table, pair::tests::test_pair, HashTable}; + use riker::actors::*; + use std::{sync::mpsc, thread}; /// dummy table actor ref /// every call produces a new actor, not just a new ref to the same actor @@ -193,10 +164,7 @@ pub mod tests { fn round_trip() { let mut table_actor = test_table_actor(); - assert_eq!( - table_actor.pair(&test_hash()).unwrap(), - None, - ); + assert_eq!(table_actor.pair(&test_hash()).unwrap(), None,); table_actor.commit(&test_pair()).unwrap(); @@ -218,10 +186,7 @@ pub mod tests { let table_actor_thread = table_actor.clone(); let (tx1, rx1) = mpsc::channel(); thread::spawn(move || { - assert_eq!( - table_actor_thread.pair(&test_hash()).unwrap(), - None, - ); + assert_eq!(table_actor_thread.pair(&test_hash()).unwrap(), None,); // kick off the next thread tx1.send(true).unwrap(); }); @@ -240,10 +205,7 @@ pub mod tests { let table_actor_thread = table_actor.clone(); let handle = thread::spawn(move || { let pair = rx2.recv().unwrap(); - assert_eq!( - table_actor_thread.pair(&pair.key()).unwrap(), - Some(pair), - ); + assert_eq!(table_actor_thread.pair(&pair.key()).unwrap(), Some(pair),); }); handle.join().unwrap(); diff --git a/core/src/hash_table/memory/mod.rs b/core/src/hash_table/memory/mod.rs index 04c97eea64..a048a90ece 100644 --- a/core/src/hash_table/memory/mod.rs +++ b/core/src/hash_table/memory/mod.rs @@ -142,7 +142,9 @@ pub mod tests { fn pair_round_trip() { let mut table = test_table(); let pair = test_pair(); - table.commit(&pair).expect("should be able to commit valid pair"); + table + .commit(&pair) + .expect("should be able to commit valid pair"); assert_eq!(table.pair(&pair.key()), Ok(Some(pair))); } @@ -215,15 +217,18 @@ pub mod tests { assert_eq!( None, - table.get_meta(&pair_meta.key()) + table + .get_meta(&pair_meta.key()) .expect("getting the metadata on a pair shouldn't fail") ); - table.assert_meta(&pair_meta) + table + .assert_meta(&pair_meta) .expect("asserting metadata shouldn't fail"); assert_eq!( Some(&pair_meta), - table.get_meta(&pair_meta.key()) + table + .get_meta(&pair_meta.key()) .expect("getting the metadata on a pair shouldn't fail") .as_ref() ); @@ -240,23 +245,28 @@ pub mod tests { assert_eq!( empty_vec, - table.get_pair_meta(&pair) + table + .get_pair_meta(&pair) .expect("getting the metadata on a pair shouldn't fail") ); - table.assert_meta(&pair_meta_a) + table + .assert_meta(&pair_meta_a) .expect("asserting metadata shouldn't fail"); assert_eq!( vec![pair_meta_a.clone()], - table.get_pair_meta(&pair) + table + .get_pair_meta(&pair) .expect("getting the metadata on a pair shouldn't fail") ); - table.assert_meta(&pair_meta_b.clone()) + table + .assert_meta(&pair_meta_b.clone()) .expect("asserting metadata shouldn't fail"); assert_eq!( vec![pair_meta_b, pair_meta_a], - table.get_pair_meta(&pair) + table + .get_pair_meta(&pair) .expect("getting the metadata on a pair shouldn't fail") ); } diff --git a/core/src/instance.rs b/core/src/instance.rs index 7615a532e6..2db6681c2c 100644 --- a/core/src/instance.rs +++ b/core/src/instance.rs @@ -246,6 +246,7 @@ pub mod tests { extern crate test_utils; use super::Instance; use action::{tests::test_action_wrapper_get, Action, ActionWrapper}; + use agent::state::ActionResponse; use context::Context; use hash_table::sys_entry::EntryType; use holochain_agent::Agent; @@ -260,7 +261,6 @@ pub mod tests { thread::sleep, time::Duration, }; - use agent::state::ActionResponse; #[derive(Clone, Debug)] pub struct TestLogger { diff --git a/core/src/lib.rs b/core/src/lib.rs index 6dd488efed..cb78fae38f 100755 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -28,8 +28,8 @@ extern crate holochain_agent; extern crate holochain_dna; extern crate holochain_wasm_utils; -pub mod actor; pub mod action; +pub mod actor; pub mod agent; pub mod chain; pub mod context; diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index 3ddf821a33..752b24666a 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -82,17 +82,19 @@ mod tests { use hash_table::entry::tests::{test_entry, test_entry_hash}; use instance::tests::{test_context_and_logger, test_instance}; use nucleus::{ - ribosome::api::{ - call, - commit::tests::test_commit_args_bytes, - tests::{test_capability, test_parameters, test_zome_name}, + ribosome::{ + api::{ + call, + commit::tests::test_commit_args_bytes, + tests::{test_capability, test_parameters, test_zome_name}, + ZomeAPIFunction, + }, + Defn, }, FunctionCall, }; use serde_json; use std::sync::Arc; - use nucleus::ribosome::api::ZomeAPIFunction; - use nucleus::ribosome::Defn; /// dummy get args from standard test entry pub fn test_get_args_bytes() -> Vec { diff --git a/core/src/nucleus/ribosome/api/mod.rs b/core/src/nucleus/ribosome/api/mod.rs index 22b8c36f30..5d20b084b1 100644 --- a/core/src/nucleus/ribosome/api/mod.rs +++ b/core/src/nucleus/ribosome/api/mod.rs @@ -492,7 +492,14 @@ pub mod tests { let instance = test_instance(dna.clone()); let (context, logger) = test_context_and_logger("joan"); - test_zome_api_function_call(&dna.name.to_string(), context, logger, &instance, &wasm, args_bytes) + test_zome_api_function_call( + &dna.name.to_string(), + context, + logger, + &instance, + &wasm, + args_bytes, + ) } #[test] From a42fd91ee5c6c07d0e432e4280b8458f4abe6124 Mon Sep 17 00:00:00 2001 From: David Meister Date: Tue, 28 Aug 2018 23:42:53 +1000 Subject: [PATCH 42/49] lint ns --- core/src/nucleus/ribosome/api/get.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index 752b24666a..42fd6c61d1 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -87,9 +87,7 @@ mod tests { call, commit::tests::test_commit_args_bytes, tests::{test_capability, test_parameters, test_zome_name}, - ZomeAPIFunction, }, - Defn, }, FunctionCall, }; From 0b5a31b0461fbb5fd8aa35f44e1489388b3a493c Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 29 Aug 2018 00:02:38 +1000 Subject: [PATCH 43/49] fix non-deterministic test --- core/src/nucleus/ribosome/api/get.rs | 6 +++++- test_utils/src/lib.rs | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index 42fd6c61d1..acd70591a4 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -92,6 +92,7 @@ mod tests { FunctionCall, }; use serde_json; + use chain::SourceChain; use std::sync::Arc; /// dummy get args from standard test entry @@ -168,6 +169,9 @@ mod tests { let instance = test_instance(dna.clone()); let (context, _) = test_context_and_logger("joan"); + println!("{:?}", instance.state().agent().chain().top_pair()); + println!("{:?}", instance.state().agent().chain().top_pair().unwrap().key()); + let commit_call = FunctionCall::new( &test_zome_name(), &test_capability(), @@ -206,7 +210,7 @@ mod tests { ).expect("test should be callable"); let mut expected = "".to_owned(); - expected.push_str("{\"header\":{\"entry_type\":\"testEntryType\",\"timestamp\":\"\",\"link\":null,\"entry_hash\":\""); + expected.push_str("{\"header\":{\"entry_type\":\"testEntryType\",\"timestamp\":\"\",\"link\":\"QmSzPqpDCo5fEJpKo9qyPK8G8hByvkBG2qx8VaXr9MHhDc\",\"entry_hash\":\""); expected.push_str(&test_entry_hash()); expected.push_str("\",\"entry_signature\":\"\",\"link_same_type\":null},\"entry\":{\"content\":\"test entry content\",\"entry_type\":\"testEntryType\"}}\u{0}"); diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index 55ab142852..55802ab2a1 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -76,6 +76,7 @@ pub fn create_test_dna_with_wasm(zome_name: &str, cap_name: &str, wasm: Vec) // zome.capabilities.push(capability); dna.zomes.push(zome); dna.name = "TestApp".into(); + dna.uuid = "8ed84a02-a0e6-4c8c-a752-34828e302986".into(); dna } From 285da2a08b35b190b28e69fe3217a0380cec4606 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 29 Aug 2018 00:10:12 +1000 Subject: [PATCH 44/49] lint docs --- core/src/chain/actor.rs | 2 ++ core/src/instance.rs | 15 ++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index 78f61d503e..a832b1eccd 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -94,6 +94,7 @@ pub mod tests { use hash_table::pair::tests::{test_pair_a, test_pair_b}; use riker::actors::*; + /// dummy chain actor reference pub fn test_chain_actor() -> ActorRef { ChainActor::new_ref() } @@ -105,6 +106,7 @@ pub mod tests { } #[test] + /// can set and get top pairs through the chain actor fn test_round_trip() { let chain_actor = test_chain_actor(); diff --git a/core/src/instance.rs b/core/src/instance.rs index 2db6681c2c..abded48a76 100644 --- a/core/src/instance.rs +++ b/core/src/instance.rs @@ -396,6 +396,14 @@ pub mod tests { instance } + /// create a test instance with a blank DNA + pub fn test_instance_blank() -> Instance { + let mut dna = Dna::new(); + dna.zomes.push(Zome::default()); + dna.uuid = "2297b5bc-ef75-4702-8e15-66e0545f3482".into(); + test_instance(dna) + } + #[test] /// This tests calling `process_action` /// with an action that dispatches no new ones. @@ -442,13 +450,6 @@ pub mod tests { assert_eq!(response, &ActionResponse::Get(None)); } - /// create a test instance with a blank DNA - pub fn test_instance_blank() -> Instance { - let mut dna = Dna::new(); - dna.zomes.push(Zome::default()); - test_instance(dna) - } - #[test] /// This test shows how to call dispatch with a closure that should run /// when the action results in a state change. Note that the observer closure From 417ed514e6d36d9de929f8fd77a41a58b92bcc8f Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 29 Aug 2018 00:10:27 +1000 Subject: [PATCH 45/49] fmt --- core/src/nucleus/ribosome/api/get.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index acd70591a4..b46b925888 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -79,20 +79,18 @@ mod tests { use self::wabt::Wat2Wasm; use super::GetArgs; + use chain::SourceChain; use hash_table::entry::tests::{test_entry, test_entry_hash}; use instance::tests::{test_context_and_logger, test_instance}; use nucleus::{ - ribosome::{ - api::{ - call, - commit::tests::test_commit_args_bytes, - tests::{test_capability, test_parameters, test_zome_name}, - }, + ribosome::api::{ + call, + commit::tests::test_commit_args_bytes, + tests::{test_capability, test_parameters, test_zome_name}, }, FunctionCall, }; use serde_json; - use chain::SourceChain; use std::sync::Arc; /// dummy get args from standard test entry @@ -170,7 +168,10 @@ mod tests { let (context, _) = test_context_and_logger("joan"); println!("{:?}", instance.state().agent().chain().top_pair()); - println!("{:?}", instance.state().agent().chain().top_pair().unwrap().key()); + println!( + "{:?}", + instance.state().agent().chain().top_pair().unwrap().key() + ); let commit_call = FunctionCall::new( &test_zome_name(), From ca163dd5cc10167fdade23e6b35fb97dc1cddcb0 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 29 Aug 2018 00:17:03 +1000 Subject: [PATCH 46/49] lint docs --- core/src/chain/actor.rs | 2 +- core/src/hash_table/actor.rs | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/core/src/chain/actor.rs b/core/src/chain/actor.rs index a832b1eccd..ea08eb09bd 100644 --- a/core/src/chain/actor.rs +++ b/core/src/chain/actor.rs @@ -46,7 +46,7 @@ impl ChainActor { Props::new(Box::new(ChainActor::actor)) } - /// returns a new actor ref for a new actor in the main actor system + /// returns a new actor ref for a new ChainActor in the main actor system pub fn new_ref() -> ActorRef { SYS.actor_of( ChainActor::props(), diff --git a/core/src/hash_table/actor.rs b/core/src/hash_table/actor.rs index ba8e404ffe..9e1fbd3fd6 100644 --- a/core/src/hash_table/actor.rs +++ b/core/src/hash_table/actor.rs @@ -76,18 +76,23 @@ pub struct HashTableActor { } impl HashTableActor { - pub fn new(table: HT) -> HashTableActor { + /// returns a new HastTablActor struct + /// internal use for riker, use new_ref instead + fn new(table: HT) -> HashTableActor { HashTableActor { table } } - pub fn actor(table: HT) -> BoxActor { + /// actor() for riker + fn actor(table: HT) -> BoxActor { Box::new(HashTableActor::new(table)) } - pub fn props(table: HT) -> BoxActorProd { + /// props() for riker + fn props(table: HT) -> BoxActorProd { Props::new_args(Box::new(HashTableActor::actor), table) } + /// returns a new actor ref for a new HashTableActor in the main actor system pub fn new_ref(table: HT) -> ActorRef { SYS.actor_of( HashTableActor::props(table), @@ -211,4 +216,10 @@ pub mod tests { handle.join().unwrap(); } + #[test] + fn hash_table_suite() { + // @TODO there is a suite of standard HashTable tests coming + // @see https://github.com/holochain/holochain-rust/pull/246 + } + } From d33cf90686ab47acc17bd1b7ffa93ac84284e335 Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 30 Aug 2018 19:02:46 +1000 Subject: [PATCH 47/49] working stress test for actor round trip --- core/Cargo.toml | 6 ++-- core/src/chain/mod.rs | 29 ++++++++--------- doc/holochain_101/src/state/actors.md | 47 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 doc/holochain_101/src/state/actors.md diff --git a/core/Cargo.toml b/core/Cargo.toml index 268ad05c51..cc1a574d61 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,9 +17,9 @@ multihash = "0.8.0" rust-base58 = "0.0.4" bitflags = "1.0" holochain_wasm_utils = { path = "../wasm_utils"} -riker = "0.1.5" -riker-default = "0.1.5" -riker-patterns = "0.1.5" +riker = "0.1.7" +riker-default = "0.1.7" +riker-patterns = "0.1.7" futures-preview = "0.2.2" lazy_static = "1.1.0" unwrap_to = "0.1.0" diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 1ac8a28e8f..1aaac57ec0 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -221,6 +221,7 @@ pub mod tests { pair::Pair, HashTable, }; + use std::thread; /// builds a dummy chain for testing pub fn test_chain() -> Chain { @@ -389,22 +390,20 @@ pub mod tests { #[test] /// show that we can push the chain a bit without issues e.g. async - /// @TODO this fails upstream - /// @see https://github.com/riker-rs/riker-patterns/issues/2 fn round_trip_stress_test() { - // let h = thread::spawn( || { - // let mut chain = test_chain(); - // let entry = test_entry(); - // - // for _ in 1..100 { - // chain.push_entry(&entry).unwrap(); - // assert_eq!( - // Some(pair.clone()), - // chain.get_pair(&pair.key()).unwrap(), - // ); - // } - // }); - // h.join().unwrap(); + let h = thread::spawn( || { + let mut chain = test_chain(); + let entry = test_entry(); + + for _ in 1..100 { + let pair = chain.push_entry(&entry).unwrap(); + assert_eq!( + Some(pair.clone()), + chain.pair(&pair.key()).unwrap(), + ); + } + }); + h.join().unwrap(); } #[test] diff --git a/doc/holochain_101/src/state/actors.md b/doc/holochain_101/src/state/actors.md new file mode 100644 index 0000000000..0d562d3f4f --- /dev/null +++ b/doc/holochain_101/src/state/actors.md @@ -0,0 +1,47 @@ +# Internal actors + +Actors are discussed in two context: + +- Each Holochain agent as an actor in a networking context +- Riker actors as an implemenation detail in the Holochain core lib + +This article is about the latter. + +## Actor model + +The [actor model](https://en.wikipedia.org/wiki/Actor_model) is a relatively safe approach to co-ordinating concurrency. + +At a high level: + +- An actor is the "primitive", like objects are the primitive of the OO paradigm +- Actors are stateful but this state is never exposed to the rest of the system +- Actors manage their internal state +- Actors maintain a message queue or "inbox" +- Messages can be received concurrently but must be processed sequentially in FIFO order +- The messages have a preset format +- Actors update their internal state in response to messages +- Actors can send messages to each other +- Messages are always processed at most once +- Actors can "supervise" each other to create a fault tolerent system +- A supervisor can restart or stop a failed actor, or escalate the decision to another supervisor + +The guarantees provided by the message queue allow actors to use stateful logic +that would not be safe otherwise in a concurrent context. + +For example, we can implement logic that reads/writes to the file system without +locks or other co-ordination. Then put an actor in front of this logic and only +interact with the file system through the relevant actor. + +## Riker + +[Riker](http://riker.rs/) is an actor library for Rust. + +The actor implementation in Riker has a few key concepts: + +- protocol: a set of valid messages that can be sent (e.g. an enum) +- actor system: manages and co-ordinates all actors +- actor: anything implementing the `Actor` trait to create new actor instances and handle receiving messages +- actor instance: an instance of the actor struct that has internal state and is tracked by the actor system +- actor ref(erence): an ActorRef that can tell messages to the actor instance it references via. the actor system + +The actor reference is a "killer feature" of Riker for us. From 64ed52a16dde65a70defa10e74f7d4c2a6fccfb8 Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 30 Aug 2018 20:53:57 +1000 Subject: [PATCH 48/49] fmt --- core/src/chain/mod.rs | 7 ++----- core/src/instance.rs | 11 ++--------- core/src/nucleus/ribosome/api/get.rs | 2 +- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/core/src/chain/mod.rs b/core/src/chain/mod.rs index 1aaac57ec0..3b9d898436 100644 --- a/core/src/chain/mod.rs +++ b/core/src/chain/mod.rs @@ -391,16 +391,13 @@ pub mod tests { #[test] /// show that we can push the chain a bit without issues e.g. async fn round_trip_stress_test() { - let h = thread::spawn( || { + let h = thread::spawn(|| { let mut chain = test_chain(); let entry = test_entry(); for _ in 1..100 { let pair = chain.push_entry(&entry).unwrap(); - assert_eq!( - Some(pair.clone()), - chain.pair(&pair.key()).unwrap(), - ); + assert_eq!(Some(pair.clone()), chain.pair(&pair.key()).unwrap(),); } }); h.join().unwrap(); diff --git a/core/src/instance.rs b/core/src/instance.rs index 75056acd02..80d948736e 100644 --- a/core/src/instance.rs +++ b/core/src/instance.rs @@ -399,7 +399,7 @@ pub mod tests { /// create a test instance with a blank DNA pub fn test_instance_blank() -> Instance { let mut dna = Dna::new(); - dna.zomes.push(Zome::default()); + dna.zomes.insert("".to_string(), Zome::default()); dna.uuid = "2297b5bc-ef75-4702-8e15-66e0545f3482".into(); test_instance(dna) } @@ -450,13 +450,6 @@ pub mod tests { assert_eq!(response, &ActionResponse::Get(None)); } - /// create a test instance with a blank DNA - pub fn test_instance_blank() -> Instance { - let mut dna = Dna::new(); - dna.zomes.insert("".to_string(), Zome::default()); - test_instance(dna) - } - #[test] /// This test shows how to call dispatch with a closure that should run /// when the action results in a state change. Note that the observer closure @@ -517,7 +510,7 @@ pub mod tests { // Wait for Init to finish // @TODO don't use history length in tests // @see https://github.com/holochain/holochain-rust/issues/195 - while instance.state().history.len() < 2 { + while instance.state().history.len() < 3 { // @TODO don't use history length in tests // @see https://github.com/holochain/holochain-rust/issues/195 println!("Waiting... {}", instance.state().history.len()); diff --git a/core/src/nucleus/ribosome/api/get.rs b/core/src/nucleus/ribosome/api/get.rs index b46b925888..6882877d39 100644 --- a/core/src/nucleus/ribosome/api/get.rs +++ b/core/src/nucleus/ribosome/api/get.rs @@ -211,7 +211,7 @@ mod tests { ).expect("test should be callable"); let mut expected = "".to_owned(); - expected.push_str("{\"header\":{\"entry_type\":\"testEntryType\",\"timestamp\":\"\",\"link\":\"QmSzPqpDCo5fEJpKo9qyPK8G8hByvkBG2qx8VaXr9MHhDc\",\"entry_hash\":\""); + expected.push_str("{\"header\":{\"entry_type\":\"testEntryType\",\"timestamp\":\"\",\"link\":\"QmT1NRaxbwMqpxXU1Adt1pVqtgnDXYxH1qH5rRbWPGxrkW\",\"entry_hash\":\""); expected.push_str(&test_entry_hash()); expected.push_str("\",\"entry_signature\":\"\",\"link_same_type\":null},\"entry\":{\"content\":\"test entry content\",\"entry_type\":\"testEntryType\"}}\u{0}"); From a83b4c4615814568ce9a244b67ffc9bee1aae00b Mon Sep 17 00:00:00 2001 From: David Meister Date: Thu, 30 Aug 2018 21:21:12 +1000 Subject: [PATCH 49/49] basic mdbook docs for actors and hash table --- doc/holochain_101/src/SUMMARY.md | 1 + .../src/distributed_hash_table.md | 32 +++++++++++++++++++ doc/holochain_101/src/state/actors.md | 7 ++++ 3 files changed, 40 insertions(+) diff --git a/doc/holochain_101/src/SUMMARY.md b/doc/holochain_101/src/SUMMARY.md index ee64111c7a..aac0512a0a 100644 --- a/doc/holochain_101/src/SUMMARY.md +++ b/doc/holochain_101/src/SUMMARY.md @@ -25,3 +25,4 @@ - [Extending the Holochain Platform](./extending_hc_platform.md) - [Redux Architecture](./state_actions.md) - [State actions](./state/actions.md) + - [State actors](./state/actors.md) diff --git a/doc/holochain_101/src/distributed_hash_table.md b/doc/holochain_101/src/distributed_hash_table.md index 49d1833204..0a6808962f 100644 --- a/doc/holochain_101/src/distributed_hash_table.md +++ b/doc/holochain_101/src/distributed_hash_table.md @@ -1 +1,33 @@ # Distributed Hash Table + +## Local Hash Table + +### implementation details + +First, read about [state actors](/state/actors.html). + +The 1:1 API implementation between actors and their inner table is achieved by +internally blocking on an `ask` from riker patterns. + +https://github.com/riker-rs/riker-patterns + +The actor ref methods implementing `HashTable` sends messages to itself. + +Calling `table_actor_ref.commit(entry)` looks like this: + +0. the actor ref constructs a `HashTableProtocol::Commit` message including the entry +0. the actor ref calls its own `ask` method, which builds a future using riker's `ask` +0. the actor ref blocks on its internal future +0. the referenced actor receives the `Commit` message and matches/destructures this into the entry +0. the entry is passed to the `commit()` method of the inner table +0. the actor's inner table, implementing `HashTable`, does something with commit (e.g. MemTable inserts into a standard Rust, in-memory `HashMap`) +0. the return value of the inner table `commit` is inserted into a `CommitResult` message +0. the `CommitResult` message is sent by the actor back to the actor ref's internal future +0. the actor ref stops blocking +0. the `CommitResult` message is destructured by the actor ref so that the return of `commit` satisfies the `HashTable` trait implementation + +Riker `ask` returns a future from the futures `0.2.2` crate. + +`table_actor.block_on_ask()` calls `block_on` and `unwrap` against this ask. + +Both the block and the unwrap should be handled better in the future. diff --git a/doc/holochain_101/src/state/actors.md b/doc/holochain_101/src/state/actors.md index 0d562d3f4f..011d8fc903 100644 --- a/doc/holochain_101/src/state/actors.md +++ b/doc/holochain_101/src/state/actors.md @@ -45,3 +45,10 @@ The actor implementation in Riker has a few key concepts: - actor ref(erence): an ActorRef that can tell messages to the actor instance it references via. the actor system The actor reference is a "killer feature" of Riker for us. + +- known size at compile, safe as properties of structs/enums +- small size, almost free to clone +- safe to share across threads and copy, no Arc reference counting, no locks, etc. +- safe to drop (the actor system maintains a URI style lookup) +- known type, no onerous generic trait handling +- no onerous lifetimes