From 57bec106b6e18117f516a5f0e08cb9acc151c49b Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 7 Nov 2023 18:05:03 +0100 Subject: [PATCH] unfinished --- plugins/zenoh-plugin-trait/src/loading.rs | 340 +++++++++------------- 1 file changed, 137 insertions(+), 203 deletions(-) diff --git a/plugins/zenoh-plugin-trait/src/loading.rs b/plugins/zenoh-plugin-trait/src/loading.rs index 0bd51942f3..28e574c344 100644 --- a/plugins/zenoh-plugin-trait/src/loading.rs +++ b/plugins/zenoh-plugin-trait/src/loading.rs @@ -29,23 +29,42 @@ pub enum PluginState { Running, } -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum PluginCondition { - Ok, - Warning(Cow<'static, str>), - Error(Cow<'static, str>), +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct PluginCondition { + warnings: Vec>, + errors: Vec>, } impl PluginCondition { - fn store(&mut self, result: ZResult) -> ZResult { - match result { + pub fn new() -> Self { + Self::default() + } + pub fn clear(&mut self) { + self.warnings.clear(); + self.errors.clear(); + } + pub fn add_error>>(&mut self, error: S) { + self.errors.push(error.into()); + } + pub fn add_warning>>(&mut self, warning: S) { + self.warnings.push(warning.into()); + } + pub fn catch_error ZResult>(&mut self, f: F) -> ZResult { + self.clear(); + match f() { Ok(v) => Ok(v), Err(e) => { - *self = PluginCondition::Error(e.to_string().into()); + self.add_error(format!("{}", e)); Err(e) } } } + pub fn errors(&self) -> &[Cow<'static, str>] { + &self.errors + } + pub fn warnings(&self) -> &[Cow<'static, str>] { + &self.warnings + } } #[derive(Clone, Debug, PartialEq, Eq)] @@ -104,6 +123,8 @@ where impl PluginInfo for StaticPlugin +where + P: Plugin, { fn name(&self) -> &str { P::STATIC_NAME @@ -116,7 +137,7 @@ impl PluginI state: self .instance .map_or(PluginState::Loaded, |_| PluginState::Running), - condition: PluginCondition::Ok, // TODO: request runnnig plugin status + condition: PluginCondition::new(), // TODO: request runnnig plugin status } } } @@ -215,7 +236,51 @@ struct DynamicPluginStarter DynamicPluginStarter { - fn new(lib: Library, path: PathBuf)`` + fn get_vtable(lib: &Library, path: &Path) -> ZResult> { + log::debug!("Loading plugin {}", &path.to_str().unwrap(),); + let get_plugin_loader_version = + unsafe { lib.get:: PluginLoaderVersion>(b"get_plugin_loader_version")? }; + let plugin_loader_version = get_plugin_loader_version(); + log::debug!("Plugin loader version: {}", &plugin_loader_version); + if plugin_loader_version != PLUGIN_LOADER_VERSION { + bail!( + "Plugin loader version mismatch: host = {}, plugin = {}", + PLUGIN_LOADER_VERSION, + plugin_loader_version + ); + } + let get_compatibility = unsafe { lib.get:: Compatibility>(b"get_compatibility")? }; + let plugin_compatibility_record = get_compatibility(); + let host_compatibility_record = Compatibility::new::(); + log::debug!( + "Plugin compativilty record: {:?}", + &plugin_compatibility_record + ); + if !plugin_compatibility_record.are_compatible(&host_compatibility_record) { + bail!( + "Plugin compatibility mismatch:\n\nHost:\n{}\nPlugin:\n{}\n", + host_compatibility_record, + plugin_compatibility_record + ); + } + let load_plugin = + unsafe { lib.get:: PluginVTable>(b"load_plugin")? }; + let vtable = load_plugin(); + Ok(vtable) + } + fn new(lib: Library, path: PathBuf) -> ZResult { + let vtable = Self::get_vtable(&lib, &path)?; + Ok(Self { + _lib: lib, + path, + vtable, + }) + } + fn start(&self, name: &str, args: &StartArgs) -> ZResult { + (self.vtable.start)(name, args) + } + fn path(&self) -> &str { + self.path.to_str().unwrap() } } @@ -233,7 +298,7 @@ impl fn new(name: String, source: DynamicPluginSource) -> Self { Self { name, - condition: PluginCondition::Ok, + condition: PluginCondition::new(), source, starter: None, instance: None, @@ -241,8 +306,6 @@ impl } } - - impl PluginInfo for DynamicPlugin { @@ -268,75 +331,27 @@ impl PluginInfo } } -fn get_vtable( - lib: &Library, - path: &Path, -) -> ZResult> { - log::debug!("Loading plugin {}", &path.to_str().unwrap(),); - let get_plugin_loader_version = - unsafe { lib.get:: PluginLoaderVersion>(b"get_plugin_loader_version")? }; - let plugin_loader_version = get_plugin_loader_version(); - log::debug!("Plugin loader version: {}", &plugin_loader_version); - if plugin_loader_version != PLUGIN_LOADER_VERSION { - bail!( - "Plugin loader version mismatch: host = {}, plugin = {}", - PLUGIN_LOADER_VERSION, - plugin_loader_version - ); - } - let get_compatibility = unsafe { lib.get:: Compatibility>(b"get_compatibility")? }; - let plugin_compatibility_record = get_compatibility(); - let host_compatibility_record = Compatibility::new::(); - log::debug!( - "Plugin compativilty record: {:?}", - &plugin_compatibility_record - ); - if !plugin_compatibility_record.are_compatible(&host_compatibility_record) { - bail!( - "Plugin compatibility mismatch:\n\nHost:\n{}\nPlugin:\n{}\n", - host_compatibility_record, - plugin_compatibility_record - ); - } - let load_plugin = - unsafe { lib.get:: PluginVTable>(b"load_plugin")? }; - let vtable = load_plugin(); - Ok(vtable) -} - - impl DeclaredPlugin for DynamicPlugin { fn load(&mut self) -> ZResult<&mut dyn LoadedPlugin> { - if self.starter.is_some() { - Ok(self) - } else { - let (lib, path) = self.source.load()?; - let starter = DynamicPluginStarter::new(lib, path)?; - - - match self.loader.load() { - Ok(starter) => { - self.starter = Some(starter); - self.condition = PluginCondition::Ok; - Ok((true, self)) - } - Err(e) => { - self.condition = PluginCondition::Error(e.to_string().into()); - Err(e) - } - } + if self.starter.is_none() { + self.condition.catch_error(|| { + let (lib, path) = self.source.load()?; + self.starter = Some(DynamicPluginStarter::new(lib, path)?); + Ok(()) + })?; } + Ok(self) } - fn loaded(&self) -> Option<&dyn LoadedPluginRecord> { + fn loaded(&self) -> Option<&dyn LoadedPlugin> { if self.starter.is_some() { Some(self) } else { None } } - fn loaded_mut(&mut self) -> Option<&mut dyn LoadedPluginRecord> { + fn loaded_mut(&mut self) -> Option<&mut dyn LoadedPlugin> { if self.starter.is_some() { Some(self) } else { @@ -346,30 +361,30 @@ impl } impl - LoadedPluginRecord for PluginRecord + LoadedPlugin for DynamicPlugin { - fn run( - &mut self, - args: &StartArgs, - ) -> ZResult<&mut dyn RunningPluginRecord> { - let starter = self - .starter - .as_ref() - .ok_or_else(|| format!("Plugin `{}` not loaded", self.name))?; - let already_running = self.instance.is_some(); - if !already_running { - self.instance = Some(starter.start(self.name(), args)?); - } + fn run(&mut self, args: &StartArgs) -> ZResult<&mut dyn RunningPlugin> { + self.condition.catch_error(|| { + let starter = self + .starter + .as_ref() + .ok_or_else(|| format!("Plugin `{}` not loaded", self.name))?; + let already_running = self.instance.is_some(); + if !already_running { + self.instance = Some(starter.start(self.name(), args)?); + } + Ok(()) + })?; Ok(self) } - fn running(&self) -> Option<&dyn RunningPluginRecord> { + fn running(&self) -> Option<&dyn RunningPlugin> { if self.instance.is_some() { Some(self) } else { None } } - fn running_mut(&mut self) -> Option<&mut dyn RunningPluginRecord> { + fn running_mut(&mut self) -> Option<&mut dyn RunningPlugin> { if self.instance.is_some() { Some(self) } else { @@ -379,7 +394,7 @@ impl } impl - RunningPluginRecord for PluginRecord + RunningPlugin for DynamicPlugin { fn stop(&mut self) { self.instance = None; @@ -397,7 +412,7 @@ impl pub struct PluginsManager { default_lib_prefix: String, loader: Option, - plugins: Vec>, + plugins: Vec>>, } impl @@ -426,37 +441,31 @@ impl( mut self, ) -> Self { - let plugin_loader: StaticPlugin

= StaticPlugin::new(); - let name = P::STATIC_NAME.into(); - self.plugins.push(PluginRecord::new(name, plugin_loader)); + let plugin_loader: StaticPlugin = StaticPlugin::new(); + self.plugins.push(Box::new(plugin_loader)); self } - fn add_dynamic< - L: PluginLoader + Send + Sync> + 'static + Send + Sync, - >( - &mut self, - name: String, - loader: L, - ) -> &mut dyn DeclaredPluginRecord { - self.plugins.push(PluginRecord::new(name, loader)); - self.plugins.last_mut().unwrap() - } - /// Add dynamic plugin to the manager by name, automatically prepending the default library prefix pub fn add_dynamic_plugin_by_name>( &mut self, name: S, plugin_name: &str, - ) -> ZResult<&dyn DeclaredPluginRecord> { + ) -> ZResult<&mut dyn DeclaredPlugin> { let plugin_name = format!("{}{}", self.default_lib_prefix, plugin_name); let libloader = self .loader .as_ref() .ok_or("Dynamic plugin loading is disabled")? .clone(); - let loader = DynamicPluginLoader::by_name(libloader, plugin_name); - Ok(self.add_dynamic(name.into(), loader)) + let loader = DynamicPlugin::new( + plugin_name, + DynamicPluginSource::ByName((libloader, plugin_name)), + ); + self.plugins.push(Box::new(loader)); + let plugin = self.plugins.last_mut().unwrap(); + let plugin = plugin as &mut dyn DeclaredPlugin; + Ok(plugin) } /// Add first available dynamic plugin from the list of paths to the plugin files @@ -464,70 +473,67 @@ impl ZResult<&dyn DeclaredPluginRecord> { - let loader = DynamicPluginLoader::by_paths(paths); - Ok(self.add_dynamic(name.into(), loader)) + ) -> ZResult<&mut dyn DeclaredPlugin> { + let name = name.into(); + let paths = paths.iter().map(|p| p.as_ref().into()).collect(); + let loader = DynamicPlugin::new(name, DynamicPluginSource::ByPaths(paths)); + self.plugins.push(Box::new(loader)); + let plugin = self.plugins.last_mut().unwrap(); + let plugin = plugin as &mut dyn DeclaredPlugin; + Ok(plugin) } - /// Returns plugin index by name fn get_plugin_index(&self, name: &str) -> Option { self.plugins.iter().position(|p| p.name() == name) } - /// Returns plugin index by name or error if plugin not found fn get_plugin_index_err(&self, name: &str) -> ZResult { self.get_plugin_index(name) .ok_or_else(|| format!("Plugin `{}` not found", name).into()) } /// Lists all plugins - pub fn plugins( - &self, - ) -> impl Iterator> + '_ { - self.plugins - .iter() - .map(|p| p as &dyn DeclaredPluginRecord) + pub fn plugins(&self) -> impl Iterator> + '_ { + self.plugins.iter().map(|p| p.as_ref()) } /// Lists all plugins mutable - pub fn plugins_mut( - &mut self, - ) -> impl Iterator> + '_ { - self.plugins - .iter_mut() - .map(|p| p as &mut dyn DeclaredPluginRecord) + pub fn plugins_mut<'a>( + &'a mut self, + ) -> impl Iterator+'a )> + 'a { + self.plugins.iter_mut().map(move|p| p.as_mut()) } /// Lists the loaded plugins pub fn loaded_plugins( &self, - ) -> impl Iterator> + '_ { + ) -> impl Iterator> + '_ { self.plugins().filter_map(|p| p.loaded()) } /// Lists the loaded plugins mutable pub fn loaded_plugins_mut( &mut self, - ) -> impl Iterator> + '_ { + ) -> impl Iterator> + '_ { self.plugins_mut().filter_map(|p| p.loaded_mut()) } /// Lists the running plugins pub fn running_plugins( &self, - ) -> impl Iterator> + '_ { + ) -> impl Iterator> + '_ { self.loaded_plugins().filter_map(|p| p.running()) } /// Lists the running plugins mutable pub fn running_plugins_mut( &mut self, - ) -> impl Iterator> + '_ { + ) -> impl Iterator> + '_ { self.loaded_plugins_mut().filter_map(|p| p.running_mut()) } /// Returns single plugin record - pub fn plugin(&self, name: &str) -> ZResult<&dyn DeclaredPluginRecord> { + pub fn plugin(&self, name: &str) -> ZResult<&dyn DeclaredPlugin> { Ok(&self.plugins[self.get_plugin_index_err(name)?]) } @@ -535,16 +541,13 @@ impl ZResult<&mut dyn DeclaredPluginRecord> { + ) -> ZResult<&mut dyn DeclaredPlugin> { let index = self.get_plugin_index_err(name)?; Ok(&mut self.plugins[index]) } /// Returns loaded plugin record - pub fn loaded_plugin( - &self, - name: &str, - ) -> ZResult<&dyn LoadedPluginRecord> { + pub fn loaded_plugin(&self, name: &str) -> ZResult<&dyn LoadedPlugin> { Ok(self .plugin(name)? .loaded() @@ -555,7 +558,7 @@ impl ZResult<&mut dyn LoadedPluginRecord> { + ) -> ZResult<&mut dyn LoadedPlugin> { Ok(self .plugin_mut(name)? .loaded_mut() @@ -563,10 +566,7 @@ impl ZResult<&dyn RunningPluginRecord> { + pub fn running_plugin(&self, name: &str) -> ZResult<&dyn RunningPlugin> { Ok(self .loaded_plugin(name)? .running() @@ -577,76 +577,10 @@ impl ZResult<&mut dyn RunningPluginRecord> { + ) -> ZResult<&mut dyn RunningPlugin> { Ok(self .loaded_plugin_mut(name)? .running_mut() .ok_or_else(|| format!("Plugin `{}` is not running", name))?) } } - -impl - DynamicPluginLoader -{ - fn by_name>(libloader: LibLoader, name: S) -> Self { - Self { - source: DynamicPluginSource::ByName((libloader, name.into())), - _phantom: PhantomData, - } - } - fn by_paths + std::fmt::Debug>(paths: &[P]) -> Self { - Self { - source: DynamicPluginSource::ByPaths(paths.iter().map(|p| p.as_ref().into()).collect()), - _phantom: PhantomData, - } - } - fn get_vtable(lib: &Library, path: &Path) -> ZResult> { - log::debug!("Loading plugin {}", &path.to_str().unwrap(),); - let get_plugin_loader_version = - unsafe { lib.get:: PluginLoaderVersion>(b"get_plugin_loader_version")? }; - let plugin_loader_version = get_plugin_loader_version(); - log::debug!("Plugin loader version: {}", &plugin_loader_version); - if plugin_loader_version != PLUGIN_LOADER_VERSION { - bail!( - "Plugin loader version mismatch: host = {}, plugin = {}", - PLUGIN_LOADER_VERSION, - plugin_loader_version - ); - } - let get_compatibility = unsafe { lib.get:: Compatibility>(b"get_compatibility")? }; - let plugin_compatibility_record = get_compatibility(); - let host_compatibility_record = Compatibility::new::(); - log::debug!( - "Plugin compativilty record: {:?}", - &plugin_compatibility_record - ); - if !plugin_compatibility_record.are_compatible(&host_compatibility_record) { - bail!( - "Plugin compatibility mismatch:\n\nHost:\n{}\nPlugin:\n{}\n", - host_compatibility_record, - plugin_compatibility_record - ); - } - let load_plugin = - unsafe { lib.get:: PluginVTable>(b"load_plugin")? }; - let vtable = load_plugin(); - Ok(vtable) - } -} - -struct DynamicPluginStarter { - _lib: Library, - path: PathBuf, - vtable: PluginVTable, -} - -impl - PluginStarter for DynamicPluginStarter -{ - fn start(&self, name: &str, args: &StartArgs) -> ZResult { - (self.vtable.start)(name, args) - } - fn path(&self) -> &str { - self.path.to_str().unwrap() - } -}