diff --git a/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs b/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs index 105df299c..3ccfe6a58 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs @@ -198,13 +198,7 @@ impl SessionImpl where T: SessionTransport { /// Wait for session completion. pub fn wait(&self) -> Result<(H256, NodeId), Error> { - let mut data = self.data.lock(); - if !data.result.is_some() { - self.core.completed.wait(&mut data); - } - - data.result.clone() - .expect("checked above or waited for completed; completed is only signaled when result.is_some(); qed") + Self::wait_session(&self.core.completed, &self.data, None, |data| data.result.clone()) } /// Initialize session. diff --git a/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs index 17a1468a2..93bdc27e6 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs @@ -207,13 +207,7 @@ impl SessionImpl { /// Wait for session completion. pub fn wait(&self) -> Result<(), Error> { - let mut data = self.data.lock(); - if !data.result.is_some() { - self.core.completed.wait(&mut data); - } - - data.result.clone() - .expect("checked above or waited for completed; completed is only signaled when result.is_some(); qed") + Self::wait_session(&self.core.completed, &self.data, None, |data| data.result.clone()) } /// Initialize servers set change session on master node. diff --git a/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs b/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs index 58ae20661..da2048ccf 100644 --- a/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs @@ -202,14 +202,7 @@ impl SessionImpl { /// Wait for session completion. pub fn wait(&self) -> Result { - let mut data = self.data.lock(); - if !data.result.is_some() { - self.core.completed.wait(&mut data); - } - - data.result.as_ref() - .expect("checked above or waited for completed; completed is only signaled when result.is_some(); qed") - .clone() + Self::wait_session(&self.core.completed, &self.data, None, |data| data.result.clone()) } /// Delegate session to other node. diff --git a/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs b/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs index 1cc6ad9f3..ff173a968 100644 --- a/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs @@ -132,17 +132,7 @@ impl SessionImpl { /// Wait for session completion. pub fn wait(&self, timeout: Option) -> Result<(), Error> { - let mut data = self.data.lock(); - if !data.result.is_some() { - match timeout { - None => self.completed.wait(&mut data), - Some(timeout) => { self.completed.wait_for(&mut data, timeout); }, - } - } - - data.result.as_ref() - .expect("checked above or waited for completed; completed is only signaled when result.is_some(); qed") - .clone() + Self::wait_session(&self.completed, &self.data, timeout, |data| data.result.clone()) } diff --git a/secret_store/src/key_server_cluster/client_sessions/generation_session.rs b/secret_store/src/key_server_cluster/client_sessions/generation_session.rs index 84c1b43e5..92dee3709 100644 --- a/secret_store/src/key_server_cluster/client_sessions/generation_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/generation_session.rs @@ -223,17 +223,8 @@ impl SessionImpl { /// Wait for session completion. pub fn wait(&self, timeout: Option) -> Result { - let mut data = self.data.lock(); - if !data.joint_public_and_secret.is_some() { - match timeout { - None => self.completed.wait(&mut data), - Some(timeout) => { self.completed.wait_for(&mut data, timeout); }, - } - } - - data.joint_public_and_secret.clone() - .expect("checked above or waited for completed; completed is only signaled when joint_public.is_some(); qed") - .map(|p| p.0) + Self::wait_session(&self.completed, &self.data, timeout, |data| data.joint_public_and_secret.clone() + .map(|r| r.map(|r| r.0.clone()))) } /// Get generated public and secret (if any). diff --git a/secret_store/src/key_server_cluster/client_sessions/signing_session.rs b/secret_store/src/key_server_cluster/client_sessions/signing_session.rs index a0895ceb0..cd72cc8e7 100644 --- a/secret_store/src/key_server_cluster/client_sessions/signing_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/signing_session.rs @@ -207,14 +207,7 @@ impl SessionImpl { /// Wait for session completion. pub fn wait(&self) -> Result<(Secret, Secret), Error> { - let mut data = self.data.lock(); - if !data.result.is_some() { - self.core.completed.wait(&mut data); - } - - data.result.as_ref() - .expect("checked above or waited for completed; completed is only signaled when result.is_some(); qed") - .clone() + Self::wait_session(&self.core.completed, &self.data, None, |data| data.result.clone()) } /// Delegate session to other node. diff --git a/secret_store/src/key_server_cluster/cluster_sessions.rs b/secret_store/src/key_server_cluster/cluster_sessions.rs index cd07045df..3cba0e14c 100644 --- a/secret_store/src/key_server_cluster/cluster_sessions.rs +++ b/secret_store/src/key_server_cluster/cluster_sessions.rs @@ -18,7 +18,7 @@ use std::time; use std::sync::{Arc, Weak}; use std::sync::atomic::AtomicBool; use std::collections::{VecDeque, BTreeMap}; -use parking_lot::{Mutex, RwLock}; +use parking_lot::{Mutex, RwLock, Condvar}; use bigint::hash::H256; use ethkey::{Secret, Signature}; use key_server_cluster::{Error, NodeId, SessionId}; @@ -79,6 +79,25 @@ pub trait ClusterSession { fn on_session_error(&self, sender: &NodeId, error: Error); /// Process session message. fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error>; + + /// 'Wait for session completion' helper. + fn wait_session Option>>(completion_event: &Condvar, session_data: &Mutex, timeout: Option, result_reader: F) -> Result { + let mut locked_data = session_data.lock(); + match result_reader(&locked_data) { + Some(result) => result, + None => { + match timeout { + None => completion_event.wait(&mut locked_data), + Some(timeout) => { + completion_event.wait_for(&mut locked_data, timeout); + }, + } + + result_reader(&locked_data) + .expect("waited for completion; completion is only signaled when result.is_some(); qed") + }, + } + } } /// Administrative session. @@ -529,7 +548,6 @@ pub fn create_cluster_view(data: &Arc, requires_all_connections: bo Ok(Arc::new(ClusterView::new(data.clone(), connected_nodes))) } - #[cfg(test)] mod tests { use std::sync::Arc;