dotlib/
plugin_mngt.rs

1use dynamic_reload::{DynamicReload, Lib, Symbol, Search, PlatformName, UpdateState};
2use std::collections::BTreeMap;
3use std::sync::Arc;
4use std::time::Duration;
5use std::thread;
6
7pub struct Plugins {
8    pub plugins: Vec<Arc<Lib>>,
9}
10
11impl Plugins {
12    fn add_plugin(&mut self, lib: &Arc<Lib>) {
13        self.plugins.push(lib.clone());
14        //self.plugins.insert(name, lib.clone());
15    }
16
17    fn clear(&mut self){
18        self.plugins.clear();
19    }
20
21    fn get_plugins(&mut self) -> Vec<Arc<Lib>>{
22        self.plugins.clone()
23    }
24
25    fn get_plugin_count(&self) -> usize {
26        self.plugins.len()
27    }
28
29    fn unload_plugin(&mut self, lib: &Arc<Lib>) {
30        
31        for i in (0..self.plugins.len()).rev() {
32            if &self.plugins[i] == lib {
33                self.plugins.swap_remove(i);
34            }
35        }
36    }
37
38    fn reload_plugin(&mut self, lib: &Arc<Lib>) {
39        Self::add_plugin(self, lib);
40    }
41
42    // called when a lib needs to be reloaded.
43    pub fn reload_callback(&mut self, state: UpdateState, lib: Option<&Arc<Lib>>) {
44        match state {
45            UpdateState::Before => Self::unload_plugin(self, lib.unwrap()),
46            UpdateState::After => Self::reload_plugin(self, lib.unwrap()),
47            UpdateState::ReloadFailed(_) => println!("Failed to reload"),
48        }
49    }
50}
51
52pub struct PluginManager<'a> {
53    reload_handler: DynamicReload<'a>,
54    plugins: Plugins,
55}
56
57impl <'a> Drop for PluginManager<'a> {
58    fn drop(&mut self){
59        //self.plugins.clear();
60        self.unload();
61    }
62}
63
64impl<'a> PluginManager<'a> {
65    pub fn new(lib_dir_pathes: Vec<&'a str>, cache_dir_path: &'a str) -> PluginManager<'a>{
66        PluginManager {
67            reload_handler: DynamicReload::new(Some(lib_dir_pathes),
68                                               None,
69                                               Search::Backwards),
70            plugins: Plugins { plugins: Vec::new() },
71        }
72    }
73
74    pub fn add_plugin(&mut self, name: &str) -> std::result::Result<i32, &str>{
75        match &self.reload_handler.add_library(name, PlatformName::Yes) {
76            Ok(lib) => {
77                    self.plugins.add_plugin(&lib);
78                    Ok(1)
79                },
80            Err(e) => {
81                println!("Unable to load dynamic lib {}, err {:?}", name, e);
82                Err("Warning: Unable to load dynamic lib!")
83            }
84        }
85    }
86
87    pub fn get_plugin_count(&self) -> usize {
88        self.plugins.get_plugin_count()
89    } 
90
91    pub fn get_plugin(&mut self) -> Arc<Lib>{
92        self.plugins.plugins[0].clone()
93    }
94
95    pub fn get_plugins(&mut self) -> Vec<Arc<Lib>>{
96        self.plugins.plugins.clone()
97    }
98
99    pub fn refresh_plugins(&mut self){
100        &self.reload_handler.update(Plugins::reload_callback, &mut self.plugins);
101    }
102
103    pub fn unload(&mut self) -> std::result::Result<i32, &'static str>{
104        debug!("Unloading plugins");
105
106        for plugin in self.plugins.get_plugins() {
107            trace!("Firing on_plugin_unload for {:?}", plugin.original_path.as_ref());
108            //plugin.on_plugin_unload();
109        }
110
111        self.plugins.clear();
112        Ok(1)
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::PluginManager;
119    use dynamic_reload::{Lib,Symbol};
120
121    #[ignore]
122    #[test]
123    fn test_01() {
124        assert!(true)
125    }
126}