[fractal] cache: Fix reinitializing cache after destroying it



commit d7d7ae3004fe55dd19953c550ea2f60b3fec3ec2
Author: Xiang Fan <sfanxiang gmail com>
Date:   Thu Feb 21 23:12:53 2019 +0800

    cache: Fix reinitializing cache after destroying it
    
    Currently the cache's directory is only initialized at first access. If
    the cache gets destroyed the directory won't be created again, so future
    cache data in the process cannot be saved. This can be reproduced by
    logging in immediately after logout.

 fractal-gtk/src/appop/login.rs |  2 +-
 fractal-gtk/src/cache/mod.rs   |  8 -------
 fractal-gtk/src/cache/state.rs | 51 ++++++++++++++++++++++++++----------------
 3 files changed, 33 insertions(+), 28 deletions(-)
---
diff --git a/fractal-gtk/src/appop/login.rs b/fractal-gtk/src/appop/login.rs
index 952ae12c..21a265d9 100644
--- a/fractal-gtk/src/appop/login.rs
+++ b/fractal-gtk/src/appop/login.rs
@@ -49,7 +49,7 @@ impl AppOp {
 
     pub fn bk_logout(&mut self) {
         self.set_rooms(vec![], true);
-        if let Err(_) = cache::destroy() {
+        if let Err(_) = cache::get().destroy() {
             error!("Error removing cache file");
         }
 
diff --git a/fractal-gtk/src/cache/mod.rs b/fractal-gtk/src/cache/mod.rs
index b7a90f66..1213d6ea 100644
--- a/fractal-gtk/src/cache/mod.rs
+++ b/fractal-gtk/src/cache/mod.rs
@@ -1,16 +1,13 @@
 use gtk;
 use gtk::LabelExt;
 use serde::{Deserialize, Serialize};
-use std::fs::remove_dir_all;
 
 use crate::types::Room;
 use crate::types::RoomList;
-use failure::err_msg;
 use failure::Error;
 use std::collections::HashMap;
 
 use crate::globals;
-use fractal_api::util::cache_path;
 
 /* includes for avatar download */
 use crate::backend::BKCommand;
@@ -98,11 +95,6 @@ pub fn load() -> Result<CacheData, Error> {
     Ok(data)
 }
 
-pub fn destroy() -> Result<(), Error> {
-    let fname = cache_path("cache.mdl").or(Err(err_msg("Can't remove cache file")))?;
-    remove_dir_all(fname).or_else(|_| Err(err_msg("Can't remove cache file")))
-}
-
 /// this downloads a avatar and stores it in the cache folder
 pub fn download_to_cache(backend: Sender<BKCommand>, name: String, data: Rc<RefCell<AvatarData>>) {
     let (tx, rx) = channel::<(String, String)>();
diff --git a/fractal-gtk/src/cache/state.rs b/fractal-gtk/src/cache/state.rs
index e37fec49..c76d4034 100644
--- a/fractal-gtk/src/cache/state.rs
+++ b/fractal-gtk/src/cache/state.rs
@@ -4,9 +4,11 @@ use mdl::Model;
 use mdl::Store;
 use serde::{Deserialize, Serialize};
 
+use failure::err_msg;
 use failure::Error;
 
 use std::cell::RefCell;
+use std::fs::remove_dir_all;
 use std::sync::{Arc, Mutex, MutexGuard};
 
 use crate::types::Message;
@@ -92,24 +94,38 @@ impl Model for AppMsg {
 
 #[derive(Clone)]
 pub struct FCache {
-    cache: Arc<Mutex<Cache>>,
+    cache: Arc<Mutex<Option<Cache>>>,
 }
 
 impl FCache {
-    pub fn get_store(&self) -> MutexGuard<'_, Cache> {
-        self.cache.lock().unwrap()
+    fn get_store<'a>(&'a self) -> MutexGuard<'a, Option<Cache>> {
+        let mut guard = self.cache.lock().unwrap();
+        if guard.is_none() {
+            let db: String = cache_path("cache.mdl").expect("Fatal error: Can't start the cache");
+            let mdl_cache = Cache::new(&db).expect("Fatal error: Can't start the cache");
+            *guard = Some(mdl_cache);
+        }
+        guard
+    }
+
+    pub fn destroy(&self) -> Result<(), Error> {
+        let mut guard = self.cache.lock().unwrap();
+        guard.take();
+
+        let fname = cache_path("cache.mdl").or(Err(err_msg("Can't remove cache file")))?;
+        remove_dir_all(fname).or_else(|_| Err(err_msg("Can't remove cache file")))
     }
 
     #[allow(dead_code)]
     pub fn get_room(&self, id: &str) -> Result<Room, Error> {
-        let cache = &*self.get_store();
-        let r = AppRoom::get(cache, id)?;
+        let cache = self.get_store();
+        let r = AppRoom::get(cache.as_ref().unwrap(), id)?;
         Ok(r.room.into_inner())
     }
 
     pub fn get_rooms(&self) -> Result<Vec<Room>, Error> {
-        let cache = &*self.get_store();
-        let rooms = AppRoom::all(cache, "room")?
+        let cache = self.get_store();
+        let rooms = AppRoom::all(cache.as_ref().unwrap(), "room")?
             .iter()
             .map(|r| r.room.borrow().clone())
             .collect();
@@ -124,23 +140,23 @@ impl FCache {
     }
 
     pub fn save_room(&self, room: Room) -> Result<(), Error> {
-        let cache = &*self.get_store();
+        let cache = self.get_store();
         let approom = AppRoom {
             room: RefCell::new(room),
         };
-        approom.store(cache)?;
+        approom.store(cache.as_ref().unwrap())?;
 
         Ok(())
     }
 
     pub fn get_st(&self) -> Result<AppState, Error> {
-        let cache = &*self.get_store();
-        AppState::get(cache, "state")
+        let cache = self.get_store();
+        AppState::get(cache.as_ref().unwrap(), "state")
     }
 
     pub fn save_st(&self, st: AppState) -> Result<(), Error> {
-        let cache = &*self.get_store();
-        st.store(cache)?;
+        let cache = self.get_store();
+        st.store(cache.as_ref().unwrap())?;
 
         Ok(())
     }
@@ -148,14 +164,11 @@ impl FCache {
 
 // The cache object, it's the same for the whole process
 lazy_static! {
-    static ref CACHE: FCache = {
-        let db: String = cache_path("cache.mdl").expect("Fatal error: Can't start the cache");
-        let mdl_cache = Cache::new(&db).expect("Fatal error: Can't start the cache");
-        let cache = Arc::new(Mutex::new(mdl_cache));
-        FCache { cache }
+    static ref CACHE: FCache = FCache {
+        cache: Arc::new(Mutex::new(None))
     };
 }
 
 pub fn get() -> FCache {
-    return CACHE.clone();
+    CACHE.clone()
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]