From 02013ac2867e56d63ab59fbfce1fc0f06716ea85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 6 May 2020 15:20:20 +0200 Subject: [PATCH] base: Move the state store behind a lock. --- matrix_sdk/src/async_client.rs | 8 ++++---- matrix_sdk/src/base_client.rs | 35 +++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/matrix_sdk/src/async_client.rs b/matrix_sdk/src/async_client.rs index eb71e8a8..d9a62962 100644 --- a/matrix_sdk/src/async_client.rs +++ b/matrix_sdk/src/async_client.rs @@ -285,10 +285,10 @@ impl AsyncClient { let http_client = http_client.default_headers(headers).build()?; - let mut base_client = BaseClient::new(session)?; - - if let Some(store) = config.state_store { - base_client.state_store = Some(store); + let base_client = if let Some(store) = config.state_store { + BaseClient::new_with_state_store(session, store)? + } else { + BaseClient::new(session)? }; Ok(Self { diff --git a/matrix_sdk/src/base_client.rs b/matrix_sdk/src/base_client.rs index 6ff39444..421812d2 100644 --- a/matrix_sdk/src/base_client.rs +++ b/matrix_sdk/src/base_client.rs @@ -82,7 +82,7 @@ pub struct Client { /// some `BaseClient` state during `AsyncClient::sync` calls. /// /// There is a default implementation `JsonStore` that saves JSON to disk. - pub state_store: Option>, + pub state_store: Arc>>>, /// Does the `Client` need to sync with the state store. needs_state_store_sync: Arc, @@ -111,6 +111,26 @@ impl Client { /// * `session` - An optional session if the user already has one from a /// previous login call. pub fn new(session: Option) -> Result { + Client::new_helper(session, None) + } + + /// Create a new client. + /// + /// # Arguments + /// + /// * `session` - An optional session if the user already has one from a + /// previous login call. + /// + /// * `store` - An open state store implementation that will be used through + /// the lifetime of the client. + pub fn new_with_state_store( + session: Option, + store: Box, + ) -> Result { + Client::new_helper(session, Some(store)) + } + + fn new_helper(session: Option, store: Option>) -> Result { #[cfg(feature = "encryption")] let olm = match &session { Some(s) => Some(OlmMachine::new(&s.user_id, &s.device_id)), @@ -124,7 +144,7 @@ impl Client { ignored_users: Arc::new(RwLock::new(Vec::new())), push_ruleset: Arc::new(RwLock::new(None)), event_emitter: Arc::new(RwLock::new(None)), - state_store: None, + state_store: Arc::new(RwLock::new(store)), needs_state_store_sync: Arc::new(AtomicBool::from(true)), #[cfg(feature = "encryption")] olm: Arc::new(Mutex::new(olm)), @@ -154,7 +174,8 @@ impl Client { /// /// Returns `true` when a state store sync has successfully completed. pub(crate) async fn sync_with_state_store(&mut self) -> Result { - if let Some(store) = self.state_store.as_ref() { + let store = self.state_store.read().await; + if let Some(store) = store.as_ref() { if let Some(sess) = self.session.read().await.as_ref() { if let Some(client_state) = store.load_client_state(sess).await? { let ClientState { @@ -523,7 +544,9 @@ impl Client { } if updated { - if let Some(store) = self.state_store.as_ref() { + let store = self.state_store.read().await; + + if let Some(store) = store.as_ref() { store .store_room_state(matrix_room.read().await.deref()) .await?; @@ -532,7 +555,9 @@ impl Client { } if updated { - if let Some(store) = self.state_store.as_ref() { + let store = self.state_store.read().await; + + if let Some(store) = store.as_ref() { let state = ClientState::from_base_client(&self).await; store.store_client_state(state).await?; }