From 13381ddd4ba306b98abe78df620978a622b82937 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Thu, 2 Nov 2023 17:36:38 +0100 Subject: [PATCH] unfinished --- .../zenoh-plugin-storage-manager/src/lib.rs | 2 +- plugins/zenoh-plugin-trait/src/lib.rs | 17 - plugins/zenoh-plugin-trait/src/loading.rs | 436 +++++++++++------- zenoh/src/net/runtime/adminspace.rs | 2 +- zenohd/src/main.rs | 2 +- 5 files changed, 277 insertions(+), 182 deletions(-) diff --git a/plugins/zenoh-plugin-storage-manager/src/lib.rs b/plugins/zenoh-plugin-storage-manager/src/lib.rs index 538680019..466253a4d 100644 --- a/plugins/zenoh-plugin-storage-manager/src/lib.rs +++ b/plugins/zenoh-plugin-storage-manager/src/lib.rs @@ -168,7 +168,7 @@ impl StorageRuntimeInner { self.plugins_manager .load_plugin_by_backend_name(volume_id, backend_name)?; } - self.plugins_manager.plugin_mut(volume_id)?.start(&config)?; + self.plugins_manager.plugin_mut(volume_id)?.run(&config)?; Ok(()) } fn kill_storage(&mut self, config: StorageConfig) { diff --git a/plugins/zenoh-plugin-trait/src/lib.rs b/plugins/zenoh-plugin-trait/src/lib.rs index fef3315c8..566e8d112 100644 --- a/plugins/zenoh-plugin-trait/src/lib.rs +++ b/plugins/zenoh-plugin-trait/src/lib.rs @@ -49,23 +49,6 @@ pub trait CompatibilityVersion { fn features() -> &'static str; } -pub enum PluginState { - Declared, - Loaded, - Started, -} - -pub enum PluginCondition { - Ok, - Warning(String), - Error(String), -} - -pub struct PluginStatus { - pub state: PluginState, - pub condition: PluginCondition, -} - pub trait PluginControl { fn plugins(&self) -> Vec<&str>; fn status(&self, name: &str) -> PluginStatus; diff --git a/plugins/zenoh-plugin-trait/src/loading.rs b/plugins/zenoh-plugin-trait/src/loading.rs index d4799f5e9..2f068817c 100644 --- a/plugins/zenoh-plugin-trait/src/loading.rs +++ b/plugins/zenoh-plugin-trait/src/loading.rs @@ -13,67 +13,178 @@ // use crate::*; use libloading::Library; +use serde_json::de; use std::path::PathBuf; use vtable::{Compatibility, PluginLoaderVersion, PluginVTable, PLUGIN_LOADER_VERSION}; use zenoh_result::{bail, ZResult}; use zenoh_util::LibLoader; -pub struct PluginRecord { - starter: Box + Send + Sync>, +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum PluginState { + Declared, + Loaded, + Runnning, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum PluginCondition { + Ok, + Warning(String), + Error(String), +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct PluginStatus { + pub state: PluginState, + pub condition: PluginCondition, +} + +trait PluginLoader { + fn load( + &self, + ) -> ZResult + Send + Sync>>; +} + +trait PluginStarter { + fn start(&self, name: &str, args: &StartArgs) -> ZResult; +} + + +struct PluginRecord { + name: String, + path: Option, + condition: PluginCondition, + loader: Box + Send + Sync>, + starter: Option + Send + Sync>>, running_plugin: Option, } impl PluginRecord { - fn new + Send + Sync + 'static>(starter: T) -> Self { + fn new + Send + Sync + 'static>(name: String, loader: S) -> Self { Self { - starter: Box::new(starter), + name, + path: None, + condition: PluginCondition::Ok, + loader, + starter: None, running_plugin: None, } } - pub fn running(&self) -> Option<&dyn RunningPluginRecord> { - if self.running_plugin.is_some() { +} + +pub trait PluginInfo { + fn name(&self) -> &str; + fn path(&self) -> &str; + fn status(&self) -> PluginStatus; +} + +impl PluginInfo for PluginRecord { + fn name(&self) -> &str { + self.name.as_str() + } + fn path(&self) -> &str { + self.path.map_or("", |v| v.path()) + } + fn status(&self) -> PluginStatus { + PluginStatus { + state: if self.starter.is_some() { + if self.running_plugin.is_some() { + PluginState::Running + } else { + PluginState::Loaded + } + } else { + PluginState::Declared + }, + condition: self.condition, + } + } +} + +pub trait DeclaredPluginRecord : PluginInfo { + fn load(&mut self) -> ZResult<(bool, &mut dyn LoadedPluginRecord)>; + fn loaded(&self) -> Option<&dyn LoadedPluginRecord>; + fn loaded_mut( + &mut self + ) -> Option<&mut dyn LoadedPluginRecord>; +} + +impl DeclaredPluginRecord for PluginRecord { + fn load(&mut self) -> ZResult<(bool, &mut dyn LoadedPluginRecord)> { + if self.starter.is_some() { + Ok((false, self)) + } else { + match self.loader.load() { + Ok(starter) => { + self.starter = Some(starter); + self.condition = PluginCondition::Ok; + Ok((true, self)) + } + Err(e) => { + self.condition = PluginCondition::Error(format!("{}", e)); + Err(e) + } + } + } + } + fn loaded(&self) -> Option<&dyn LoadedPluginRecord> { + if self.starter.is_some() { Some(self) } else { None } } - pub fn running_mut( - &mut self, - ) -> Option<&mut dyn RunningPluginRecord> { - if self.running_plugin.is_some() { + fn loaded_mut( + &mut self + ) -> Option<&mut dyn LoadedPluginRecord> { + if self.starter.is_some() { Some(self) } else { None } } - pub fn start( - &mut self, - args: &StartArgs, - ) -> ZResult<(bool, &mut dyn RunningPluginRecord)> { +} + +pub trait LoadedPluginRecord : PluginInfo +{ + fn run(&mut self, args: &StartArgs) -> ZResult; + fn running(&self) -> Option<&dyn RunningPluginRecord>; + pub fn running_mut( + &mut self + ) -> Option<&mut dyn RunningPluginRecord>; +} + +impl LoadedPluginRecord for PluginRecord { + fn run(&mut self, args: &StartArgs) -> ZResult { + let starter = self.starter.as_ref().ok_or_else(|| format!("Plugin `{}` not loaded", self.name))?; let already_running = self.running_plugin.is_some(); if !already_running { - self.running_plugin = Some(self.starter.start(args)?); + self.running_plugin = Some(starter.start(self.name(), args)?); } - Ok((already_running, self)) - } - pub fn name(&self) -> &str { - self.starter.name() + Ok(self.running_plugin.as_ref().unwrap().clone()) } - pub fn path(&self) -> &str { - self.starter.path() + fn running(&self) -> Option<&dyn RunningPluginRecord> { + if self.running_plugin.is_some() { + Some(self) + } else { + None + } } - pub fn deletable(&self) -> bool { - self.starter.deletable() + fn running_mut( + &mut self + ) -> Option<&mut dyn RunningPluginRecord> { + if self.running_plugin.is_some() { + Some(self) + } else { + None + } } } pub trait RunningPluginRecord { - fn name(&self) -> &str; - fn path(&self) -> &str; - fn deletable(&self) -> bool; fn stop(&mut self); fn running(&self) -> &RunningPlugin; fn running_mut(&mut self) -> &mut RunningPlugin; @@ -82,15 +193,6 @@ pub trait RunningPluginRecord RunningPluginRecord for PluginRecord { - fn name(&self) -> &str { - self.name() - } - fn path(&self) -> &str { - self.path() - } - fn deletable(&self) -> bool { - self.deletable() - } fn stop(&mut self) { self.running_plugin = None; } @@ -136,8 +238,9 @@ impl( mut self, ) -> Self { - let plugin_starter: StaticPlugin

= StaticPlugin::new(); - self.plugins.push(PluginRecord::new(plugin_starter)); + let plugin_loader: StaticPlugin

= StaticPlugin::new(); + let name = P::STATIC_NAME.into(); + self.plugins.push(PluginRecord::new(name, Box::new(plugin_loader))); self } @@ -152,34 +255,48 @@ impl impl Iterator> + '_ { + /// Lists all plugins + pub fn plugins(&self) -> impl Iterator> + '_ { self.plugins.iter() } - /// Lists the loaded plugins mutable + /// Lists all plugins mutable pub fn plugins_mut( &mut self, ) -> impl Iterator> + '_ { self.plugins.iter_mut() } + /// Lists the loaded plugins + pub fn loaded_plugins( + &self, + ) -> impl Iterator> + '_ { + self.plugins().filter_map(|p| p.loaded()) + } + + /// Lists the loaded plugins mutable + pub fn loaded_plugins_mut( + &mut self, + ) -> impl Iterator> + '_ { + self.plugins_mut().filter_map(|p| p.loaded_mut()) + } + /// Lists the running plugins pub fn running_plugins( &self, ) -> impl Iterator> + '_ { - self.plugins().filter_map(|p| p.running()) + self.loaded_plugins().filter_map(|p| p.running()) } /// Lists the running plugins mutable pub fn running_plugins_mut( &mut self, ) -> impl Iterator> + '_ { - self.plugins_mut().filter_map(|p| p.running_mut()) + self.loaded_plugins_mut().filter_map(|p| p.running_mut()) } - /// Returns plugin record - pub fn plugin(&self, name: &str) -> ZResult<&PluginRecord> { + /// Returns single plugin record + pub fn plugin(&self, name: &str) -> ZResult<&dyn DeclaredPluginRecord> { Ok(&self.plugins[self.get_plugin_index_err(name)?]) } @@ -187,18 +304,40 @@ impl ZResult<&mut PluginRecord> { + ) -> ZResult<&mut DeclaredPluginRecord> { 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> { + Ok(self + .plugin(name)? + .loaded() + .ok_or_else(|| format!("Plugin `{}` not loaded", name))?) + } + + /// Returns mutable loaded plugin record + pub fn loaded_plugin_mut( + &mut self, + name: &str, + ) -> ZResult<&mut dyn LoadedPluginRecord> { + Ok(self + .plugin_mut(name)? + .loaded_mut() + .ok_or_else(|| format!("Plugin `{}` not loaded", name))?) + } + /// Returns running plugin record pub fn running_plugin( &self, name: &str, ) -> ZResult<&dyn RunningPluginRecord> { Ok(self - .plugin(name)? + .loaded_plugin(name)? .running() .ok_or_else(|| format!("Plugin `{}` is not running", name))?) } @@ -209,80 +348,69 @@ impl ZResult<&mut dyn RunningPluginRecord> { Ok(self - .plugin_mut(name)? + .loaded_plugin_mut(name)? .running_mut() .ok_or_else(|| format!("Plugin `{}` is not running", name))?) } - fn load_plugin( - name: &str, - lib: Library, - path: PathBuf, - ) -> ZResult> { - DynamicPlugin::new(name.into(), lib, path) - } - - /// Tries to load a plugin with the name `defaukt_lib_prefix` + `backend_name` + `.so | .dll | .dylib` - /// in lib_loader's search paths. - /// Returns a tuple of (retval, plugin_record) - /// where `retval`` is true if the plugin was successfully loaded, false if pluginw with this name it was already loaded - pub fn load_plugin_by_backend_name, T1: AsRef>( - &mut self, - name: T, - backend_name: T1, - ) -> ZResult<(bool, &mut PluginRecord)> { - let name = name.as_ref(); - if let Some(index) = self.get_plugin_index(name) { - return Ok((false, &mut self.plugins[index])); - } - let backend_name = backend_name.as_ref(); - let (lib, p) = match &mut self.loader { - Some(l) => unsafe { l.search_and_load(&format!("{}{}", &self.default_lib_prefix, &backend_name))? }, - None => bail!("Can't load dynamic plugin `{}`, as dynamic loading is not enabled for this plugin manager.", &name), - }; - let plugin = match Self::load_plugin(name, lib, p.clone()) { - Ok(p) => p, - Err(e) => bail!("After loading `{:?}`: {}", &p, e), - }; - self.plugins.push(PluginRecord::new(plugin)); - Ok((true, self.plugins.last_mut().unwrap())) - } - /// Tries to load a plugin from the list of path to plugin (absolute or relative to the current working directory) - /// Returns a tuple of (retval, plugin_record) - /// where `retval`` is true if the plugin was successfully loaded, false if pluginw with this name it was already loaded - pub fn load_plugin_by_paths, P: AsRef + std::fmt::Debug>( - &mut self, - name: T, - paths: &[P], - ) -> ZResult<(bool, &mut PluginRecord)> { - let name = name.as_ref(); - if let Some(index) = self.get_plugin_index(name) { - return Ok((false, &mut self.plugins[index])); - } - for path in paths { - let path = path.as_ref(); - match unsafe { LibLoader::load_file(path) } { - Ok((lib, p)) => { - let plugin = Self::load_plugin(name, lib, p)?; - self.plugins.push(PluginRecord::new(plugin)); - return Ok((true, self.plugins.last_mut().unwrap())); - } - Err(e) => log::warn!("Plugin '{}' load fail at {}: {}", &name, path, e), - } - } - bail!("Plugin '{}' not found in {:?}", name, &paths) - } -} - -pub trait PluginInfo { - fn name(&self) -> &str; - fn path(&self) -> &str; - fn deletable(&self) -> bool; -} - -trait PluginStarter: PluginInfo { - fn start(&self, args: &StartArgs) -> ZResult; - fn as_plugin_info(&self) -> &dyn PluginInfo; + // fn load_plugin( + // name: &str, + // lib: Library, + // path: PathBuf, + // ) -> ZResult> { + // DynamicPlugin::new(name.into(), lib, path) + // } + + // /// Tries to load a plugin with the name `defaukt_lib_prefix` + `backend_name` + `.so | .dll | .dylib` + // /// in lib_loader's search paths. + // /// Returns a tuple of (retval, plugin_record) + // /// where `retval`` is true if the plugin was successfully loaded, false if pluginw with this name it was already loaded + // pub fn load_plugin_by_backend_name, T1: AsRef>( + // &mut self, + // name: T, + // backend_name: T1, + // ) -> ZResult<(bool, &mut PluginRecord)> { + // let name = name.as_ref(); + // if let Some(index) = self.get_plugin_index(name) { + // return Ok((false, &mut self.plugins[index])); + // } + // let backend_name = backend_name.as_ref(); + // let (lib, p) = match &mut self.loader { + // Some(l) => unsafe { l.search_and_load(&format!("{}{}", &self.default_lib_prefix, &backend_name))? }, + // None => bail!("Can't load dynamic plugin `{}`, as dynamic loading is not enabled for this plugin manager.", &name), + // }; + // let plugin = match Self::load_plugin(name, lib, p.clone()) { + // Ok(p) => p, + // Err(e) => bail!("After loading `{:?}`: {}", &p, e), + // }; + // self.plugins.push(PluginRecord::new(plugin)); + // Ok((true, self.plugins.last_mut().unwrap())) + // } + // /// Tries to load a plugin from the list of path to plugin (absolute or relative to the current working directory) + // /// Returns a tuple of (retval, plugin_record) + // /// where `retval`` is true if the plugin was successfully loaded, false if pluginw with this name it was already loaded + // pub fn load_plugin_by_paths, P: AsRef + std::fmt::Debug>( + // &mut self, + // name: T, + // paths: &[P], + // ) -> ZResult<(bool, &mut PluginRecord)> { + // let name = name.as_ref(); + // if let Some(index) = self.get_plugin_index(name) { + // return Ok((false, &mut self.plugins[index])); + // } + // for path in paths { + // let path = path.as_ref(); + // match unsafe { LibLoader::load_file(path) } { + // Ok((lib, p)) => { + // let plugin = Self::load_plugin(name, lib, p)?; + // self.plugins.push(PluginRecord::new(plugin)); + // return Ok((true, self.plugins.last_mut().unwrap())); + // } + // Err(e) => log::warn!("Plugin '{}' load fail at {}: {}", &name, path, e), + // } + // } + // bail!("Plugin '{}' not found in {:?}", name, &paths) + // } } struct StaticPlugin

{ @@ -297,18 +425,15 @@ impl

StaticPlugin

{ } } -impl PluginInfo for StaticPlugin

+impl PluginLoader + for StaticPlugin

where P: Plugin, { - fn name(&self) -> &str { - P::STATIC_NAME - } - fn path(&self) -> &str { - "" - } - fn deletable(&self) -> bool { - false + fn load( + &self, + ) -> ZResult + Send + Sync>> { + Box::new(Self::new()) } } @@ -316,57 +441,45 @@ impl PluginStarter for St where P: Plugin, { - fn start(&self, args: &StartArgs) -> ZResult { - P::start(P::STATIC_NAME, args) - } - fn as_plugin_info(&self) -> &dyn PluginInfo { - self - } -} - -impl PluginInfo - for DynamicPlugin -{ - fn name(&self) -> &str { - &self.name - } - fn path(&self) -> &str { - self.path.to_str().unwrap() - } - fn deletable(&self) -> bool { - true + fn start(&self, name: &str, args: &StartArgs) -> ZResult { + P::start(name, args) } } impl PluginStarter for DynamicPlugin { - fn start(&self, args: &StartArgs) -> ZResult { - (self.vtable.start)(self.name(), args) - } - fn as_plugin_info(&self) -> &dyn PluginInfo { - self + fn start(&self, name: &str, args: &StartArgs) -> ZResult { + (self.vtable.start)(name, args) } } -struct +enum DynamicPluginLoader { + ByName((LibLoader, String)), + ByPaths((Vec)), +} -pub struct DynamicPlugin { - name: String, - lib: Option, - vtable: Option>, - path: Option, +impl PluginLoader for DynamicPluginLoader { + fn load( + &self, + ) -> ZResult + Send + Sync>> { + } +} + +struct DynamicPluginStarter { + path: PathBuf, + lib: Library, + vtable: PluginVTable, } impl - DynamicPlugin + DynamicPluginStarter { - pub fn new(name: String, lib: Library, path: PathBuf) -> Self { + pub fn new(path: PathBuf, lib: Library, vtable: PluginVTable) -> Self { Self { - name, - lib: None, - vtable: None, - path: None, + path, + lib, + vtable, } } @@ -448,4 +561,3 @@ impl } } -} diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index de6cef745..89e6e6e54 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -214,7 +214,7 @@ impl AdminSpace { rec.path() ); } - match rec.start(&admin.context.runtime) { + match rec.run(&admin.context.runtime) { Ok((true, rec)) => { active_plugins .insert(name.into(), rec.path().to_string()); diff --git a/zenohd/src/main.rs b/zenohd/src/main.rs index 6a2bc0a68..fe9b6a473 100644 --- a/zenohd/src/main.rs +++ b/zenohd/src/main.rs @@ -119,7 +119,7 @@ clap::Arg::new("adminspace-permissions").long("adminspace-permissions").value_na req = if required { "required" } else { "" }, name = plugin.name() ); - match plugin.start(&runtime) { + match plugin.run(&runtime) { Ok(_) => { log::info!( "Successfully started plugin {} from {:?}",