[niepce/lr-import: 8/20] npc-engine: remove ClientImpl




commit 48259fd069e46f2a7aa8f67460c3ff75dbf8935c
Author: Hubert Figuière <hub figuiere net>
Date:   Sun Nov 14 00:52:58 2021 -0500

    npc-engine: remove ClientImpl

 crates/npc-engine/src/libraryclient.rs            | 215 +++++++++++++----
 crates/npc-engine/src/libraryclient/clientimpl.rs | 270 ----------------------
 src/Makefile.am                                   |   1 -
 3 files changed, 168 insertions(+), 318 deletions(-)
---
diff --git a/crates/npc-engine/src/libraryclient.rs b/crates/npc-engine/src/libraryclient.rs
index 36958fa..e6bb2bc 100644
--- a/crates/npc-engine/src/libraryclient.rs
+++ b/crates/npc-engine/src/libraryclient.rs
@@ -17,23 +17,27 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-pub mod clientimpl;
 pub mod clientinterface;
 
 pub use self::clientinterface::{ClientInterface, ClientInterfaceSync};
 
 use libc::{c_char, c_void};
+use std::collections::VecDeque;
 use std::ffi::CStr;
 use std::path::PathBuf;
-use std::sync::Arc;
+use std::sync;
+use std::sync::atomic;
+use std::sync::mpsc;
+use std::thread;
 
-use self::clientimpl::ClientImpl;
 use crate::db::filebundle::FileBundle;
 use crate::db::library::Managed;
 use crate::db::props::NiepceProperties as Np;
-use crate::db::LibraryId;
+use crate::db::{Library, LibraryId};
 use crate::db::{NiepceProperties, NiepcePropertyIdx};
+use crate::library::commands;
 use crate::library::notification::{LcChannel, LibNotification};
+use crate::library::op::Op;
 use npc_fwk::base::PropertyValue;
 use npc_fwk::toolkit::PortableChannel;
 use npc_fwk::utils::files::FileList;
@@ -41,7 +45,7 @@ use npc_fwk::utils::files::FileList;
 /// Wrap the libclient Arc so that it can be passed around
 /// Used in the ffi for example.
 pub struct LibraryClientWrapper {
-    client: Arc<LibraryClient>,
+    client: sync::Arc<LibraryClient>,
 }
 
 impl LibraryClientWrapper {
@@ -50,7 +54,7 @@ impl LibraryClientWrapper {
         sender: async_channel::Sender<LibNotification>,
     ) -> LibraryClientWrapper {
         LibraryClientWrapper {
-            client: Arc::new(LibraryClient::new(dir, sender)),
+            client: sync::Arc::new(LibraryClient::new(dir, sender)),
         }
     }
 
@@ -58,20 +62,38 @@ impl LibraryClientWrapper {
     /// XXX we need to unsure this is thread safe.
     /// Don't hold this reference more than you need.
     pub fn unwrap_mut(&mut self) -> &mut LibraryClient {
-        Arc::get_mut(&mut self.client).unwrap()
+        sync::Arc::get_mut(&mut self.client).unwrap()
     }
 }
 
 pub struct LibraryClient {
-    pimpl: ClientImpl,
-
+    terminate: sync::Arc<atomic::AtomicBool>,
+    tasks: sync::Arc<(sync::Mutex<VecDeque<Op>>, sync::Condvar)>,
     trash_id: LibraryId,
 }
 
+impl Drop for LibraryClient {
+    fn drop(&mut self) {
+        self.stop();
+    }
+}
+
 impl LibraryClient {
     pub fn new(dir: PathBuf, sender: async_channel::Sender<LibNotification>) -> LibraryClient {
+        let tasks = sync::Arc::new((sync::Mutex::new(VecDeque::new()), sync::Condvar::new()));
+        let mut terminate = sync::Arc::new(atomic::AtomicBool::new(false));
+        let tasks2 = tasks.clone();
+        let terminate2 = terminate.clone();
+
+        /* let thread = */
+        thread::spawn(move || {
+            let library = Library::new(&dir, None, sender);
+            Self::main(&mut terminate, &tasks, &library);
+        });
+
         LibraryClient {
-            pimpl: ClientImpl::new(dir, sender),
+            terminate: terminate2,
+            tasks: tasks2,
             trash_id: 0,
         }
     }
@@ -83,110 +105,209 @@ impl LibraryClient {
     pub fn set_trash_id(&mut self, id: LibraryId) {
         self.trash_id = id;
     }
+
+    fn stop(&mut self) {
+        self.terminate.store(true, atomic::Ordering::Relaxed);
+        self.tasks.1.notify_one();
+    }
+
+    fn main(
+        terminate: &mut sync::Arc<atomic::AtomicBool>,
+        tasks: &sync::Arc<(sync::Mutex<VecDeque<Op>>, sync::Condvar)>,
+        library: &Library,
+    ) {
+        while !terminate.load(atomic::Ordering::Relaxed) {
+            let elem: Option<Op>;
+            {
+                let mut queue = tasks.0.lock().unwrap();
+                if !queue.is_empty() {
+                    elem = queue.pop_front();
+                } else {
+                    elem = None;
+                }
+            }
+
+            if let Some(op) = elem {
+                op.execute(library);
+            }
+
+            let queue = tasks.0.lock().unwrap();
+            if queue.is_empty() {
+                if let Err(err) = tasks.1.wait(queue) {
+                    err_out!("queue lock poisonned: {}", err);
+                    break;
+                }
+            }
+        }
+    }
+
+    pub fn schedule_op<F>(&mut self, f: F)
+    where
+        F: Fn(&Library) -> bool + Send + Sync + 'static,
+    {
+        let op = Op::new(f);
+
+        let mut queue = self.tasks.0.lock().unwrap();
+        queue.push_back(op);
+        self.tasks.1.notify_all();
+    }
 }
 
 impl ClientInterface for LibraryClient {
     /// get all the keywords
     fn get_all_keywords(&mut self) {
-        self.pimpl.get_all_keywords();
+        self.schedule_op(move |lib| commands::cmd_list_all_keywords(&lib));
     }
-    fn query_keyword_content(&mut self, id: LibraryId) {
-        self.pimpl.query_keyword_content(id);
+
+    fn query_keyword_content(&mut self, keyword_id: LibraryId) {
+        self.schedule_op(move |lib| commands::cmd_query_keyword_content(&lib, keyword_id));
     }
+
     fn count_keyword(&mut self, id: LibraryId) {
-        self.pimpl.count_keyword(id);
+        self.schedule_op(move |lib| commands::cmd_count_keyword(&lib, id));
     }
 
-    /// get all the folder
+    /// get all the folders
     fn get_all_folders(&mut self) {
-        self.pimpl.get_all_folders();
+        self.schedule_op(move |lib| commands::cmd_list_all_folders(&lib));
     }
-    fn query_folder_content(&mut self, id: LibraryId) {
-        self.pimpl.query_folder_content(id);
+
+    fn query_folder_content(&mut self, folder_id: LibraryId) {
+        self.schedule_op(move |lib| commands::cmd_query_folder_content(&lib, folder_id));
     }
-    fn count_folder(&mut self, id: LibraryId) {
-        self.pimpl.count_folder(id);
+
+    fn count_folder(&mut self, folder_id: LibraryId) {
+        self.schedule_op(move |lib| commands::cmd_count_folder(&lib, folder_id));
     }
 
     fn create_folder(&mut self, name: String, path: Option<String>) {
-        self.pimpl.create_folder(name, path);
+        self.schedule_op(move |lib| commands::cmd_create_folder(&lib, &name, path.clone()) != 0);
     }
 
     fn delete_folder(&mut self, id: LibraryId) {
-        self.pimpl.delete_folder(id);
+        self.schedule_op(move |lib| commands::cmd_delete_folder(&lib, id));
     }
 
     /// get all the albums
     fn get_all_albums(&mut self) {
-        self.pimpl.get_all_albums();
+        self.schedule_op(move |lib| commands::cmd_list_all_albums(&lib));
     }
 
     /// Create an album (async)
     fn create_album(&mut self, name: String, parent: LibraryId) {
-        self.pimpl.create_album(name, parent);
+        self.schedule_op(move |lib| commands::cmd_create_album(&lib, &name, parent) != 0);
     }
 
-    fn request_metadata(&mut self, id: LibraryId) {
-        self.pimpl.request_metadata(id);
+    fn request_metadata(&mut self, file_id: LibraryId) {
+        self.schedule_op(move |lib| commands::cmd_request_metadata(&lib, file_id));
     }
+
     /// set the metadata
-    fn set_metadata(&mut self, id: LibraryId, meta: Np, value: &PropertyValue) {
-        self.pimpl.set_metadata(id, meta, value);
+    fn set_metadata(&mut self, file_id: LibraryId, meta: Np, value: &PropertyValue) {
+        let value2 = value.clone();
+        self.schedule_op(move |lib| commands::cmd_set_metadata(&lib, file_id, meta, &value2));
     }
-    fn write_metadata(&mut self, id: LibraryId) {
-        self.pimpl.write_metadata(id);
+    fn write_metadata(&mut self, file_id: LibraryId) {
+        self.schedule_op(move |lib| commands::cmd_write_metadata(&lib, file_id));
     }
 
     fn move_file_to_folder(&mut self, file_id: LibraryId, from: LibraryId, to: LibraryId) {
-        self.pimpl.move_file_to_folder(file_id, from, to);
+        self.schedule_op(move |lib| commands::cmd_move_file_to_folder(&lib, file_id, from, to));
     }
+
     /// get all the labels
     fn get_all_labels(&mut self) {
-        self.pimpl.get_all_labels();
+        self.schedule_op(move |lib| commands::cmd_list_all_labels(&lib));
     }
-    fn create_label(&mut self, label: String, colour: String) {
-        self.pimpl.create_label(label, colour);
+    fn create_label(&mut self, name: String, colour: String) {
+        self.schedule_op(move |lib| commands::cmd_create_label(&lib, &name, &colour) != 0);
     }
-    fn delete_label(&mut self, id: LibraryId) {
-        self.pimpl.delete_label(id);
+    fn delete_label(&mut self, label_id: LibraryId) {
+        self.schedule_op(move |lib| commands::cmd_delete_label(&lib, label_id));
     }
     /// update a label
-    fn update_label(&mut self, id: LibraryId, new_name: String, new_colour: String) {
-        self.pimpl.update_label(id, new_name, new_colour);
+    fn update_label(&mut self, label_id: LibraryId, new_name: String, new_colour: String) {
+        self.schedule_op(move |lib| {
+            commands::cmd_update_label(&lib, label_id, &new_name, &new_colour)
+        });
     }
 
     /// tell to process the Xmp update Queue
     fn process_xmp_update_queue(&mut self, write_xmp: bool) {
-        self.pimpl.process_xmp_update_queue(write_xmp);
+        self.schedule_op(move |lib| commands::cmd_process_xmp_update_queue(&lib, write_xmp));
     }
 
     /// Import files from a directory
     /// @param dir the directory
     /// @param manage true if imports have to be managed
     fn import_files(&mut self, dir: String, files: Vec<PathBuf>, manage: Managed) {
-        self.pimpl.import_files(dir, files, manage);
+        self.schedule_op(move |lib| commands::cmd_import_files(&lib, &dir, &files, manage));
     }
 }
 
 impl ClientInterfaceSync for LibraryClient {
-    fn create_keyword_sync(&mut self, keyword: String) -> LibraryId {
-        self.pimpl.create_keyword_sync(keyword)
+    fn create_label_sync(&mut self, name: String, colour: String) -> LibraryId {
+        // can't use futures::sync::oneshot
+        let (tx, rx) = mpsc::sync_channel::<LibraryId>(1);
+
+        self.schedule_op(move |lib| {
+            tx.send(commands::cmd_create_label(&lib, &name, &colour))
+                .unwrap();
+            true
+        });
+
+        rx.recv().unwrap()
     }
 
-    fn create_label_sync(&mut self, name: String, colour: String) -> LibraryId {
-        self.pimpl.create_label_sync(name, colour)
+    fn create_keyword_sync(&mut self, keyword: String) -> LibraryId {
+        // can't use futures::sync::oneshot
+        let (tx, rx) = mpsc::sync_channel::<LibraryId>(1);
+
+        self.schedule_op(move |lib| {
+            tx.send(commands::cmd_add_keyword(&lib, &keyword)).unwrap();
+            true
+        });
+
+        rx.recv().unwrap()
     }
 
     fn create_folder_sync(&mut self, name: String, path: Option<String>) -> LibraryId {
-        self.pimpl.create_folder_sync(name, path)
+        // can't use futures::sync::oneshot
+        let (tx, rx) = mpsc::sync_channel::<LibraryId>(1);
+
+        self.schedule_op(move |lib| {
+            tx.send(commands::cmd_create_folder(&lib, &name, path.clone()))
+                .unwrap();
+            true
+        });
+
+        rx.recv().unwrap()
     }
 
     fn create_album_sync(&mut self, name: String, parent: LibraryId) -> LibraryId {
-        self.pimpl.create_album_sync(name, parent)
+        // can't use futures::sync::oneshot
+        let (tx, rx) = mpsc::sync_channel::<LibraryId>(1);
+
+        self.schedule_op(move |lib| {
+            tx.send(commands::cmd_create_album(&lib, &name, parent))
+                .unwrap();
+            true
+        });
+
+        rx.recv().unwrap()
     }
 
     fn add_bundle_sync(&mut self, bundle: &FileBundle, folder: LibraryId) -> LibraryId {
-        self.pimpl.add_bundle_sync(bundle, folder)
+        let (tx, rx) = mpsc::sync_channel::<LibraryId>(1);
+
+        let bundle = bundle.clone();
+        self.schedule_op(move |lib| {
+            tx.send(commands::cmd_add_bundle(&lib, &bundle, folder))
+                .unwrap();
+            true
+        });
+
+        rx.recv().unwrap()
     }
 }
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 6f620f7..6df7503 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,6 @@ RUST_SOURCES = \
        @top_srcdir@/crates/npc-engine/src/library/queriedcontent.rs \
        @top_srcdir@/crates/npc-engine/src/library/thumbnail_cache.rs \
        @top_srcdir@/crates/npc-engine/src/libraryclient.rs \
-       @top_srcdir@/crates/npc-engine/src/libraryclient/clientimpl.rs \
        @top_srcdir@/crates/npc-engine/src/libraryclient/clientinterface.rs \
        @top_srcdir@/crates/npc-engine/src/lib.rs \
        @top_srcdir@/crates/npc-fwk/Cargo.toml \


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