From 84442f5a2e101485c7013e16cab9fb6629fad388 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Sun, 22 Oct 2023 20:33:52 +0200 Subject: [PATCH] unifying plugn loading unfinished --- plugins/zenoh-backend-traits/src/config.rs | 23 +++---- .../zenoh-plugin-storage-manager/src/lib.rs | 56 ++++++----------- .../src/memory_backend/mod.rs | 2 +- plugins/zenoh-plugin-trait/src/loading.rs | 62 +++++++++++++------ zenoh/src/net/runtime/adminspace.rs | 13 ++-- zenohd/src/main.rs | 2 +- 6 files changed, 80 insertions(+), 78 deletions(-) diff --git a/plugins/zenoh-backend-traits/src/config.rs b/plugins/zenoh-backend-traits/src/config.rs index 20c3d5f3f4..2672a2f346 100644 --- a/plugins/zenoh-backend-traits/src/config.rs +++ b/plugins/zenoh-backend-traits/src/config.rs @@ -16,10 +16,8 @@ use schemars::JsonSchema; use serde_json::{Map, Value}; use std::convert::TryFrom; use std::time::Duration; -use zenoh::{ - key_expr::keyexpr, prelude::OwnedKeyExpr, Result as ZResult, -}; -use zenoh_plugin_trait::{CompatibilityVersion, concat_enabled_features}; +use zenoh::{key_expr::keyexpr, prelude::OwnedKeyExpr, Result as ZResult}; +use zenoh_plugin_trait::{concat_enabled_features, CompatibilityVersion}; use zenoh_result::{bail, zerror, Error}; #[derive(JsonSchema, Debug, Clone, AsMut, AsRef)] @@ -251,10 +249,6 @@ impl ConfigDiff { diffs } } -pub enum BackendSearchMethod<'a> { - ByPaths(&'a [String]), - ByName(&'a str), -} impl VolumeConfig { pub fn to_json_value(&self) -> Value { let mut result = self.rest.clone(); @@ -269,11 +263,14 @@ impl VolumeConfig { } Value::Object(result) } - pub fn backend_search_method(&self) -> BackendSearchMethod { - match &self.paths { - None => BackendSearchMethod::ByName(self.backend.as_deref().unwrap_or(&self.name)), - Some(paths) => BackendSearchMethod::ByPaths(paths), - } + pub fn name(&self) -> &str { + &self.name + } + pub fn backend(&self) -> &str { + self.backend.as_deref().unwrap_or(&self.name) + } + pub fn paths(&self) -> Option<&[String]> { + self.paths.as_deref() } fn try_from(plugin_name: &str, configs: &V) -> ZResult> { let configs = configs.as_object().ok_or_else(|| { diff --git a/plugins/zenoh-plugin-storage-manager/src/lib.rs b/plugins/zenoh-plugin-storage-manager/src/lib.rs index 613eae97d0..8b6ffbe3ef 100644 --- a/plugins/zenoh-plugin-storage-manager/src/lib.rs +++ b/plugins/zenoh-plugin-storage-manager/src/lib.rs @@ -35,6 +35,7 @@ use zenoh::prelude::sync::*; use zenoh::runtime::Runtime; use zenoh::Session; use zenoh_backend_traits::CreateVolume; +use zenoh_backend_traits::VolumePlugin; use zenoh_backend_traits::CREATE_VOLUME_FN_NAME; use zenoh_backend_traits::{config::*, Volume}; use zenoh_core::zlock; @@ -72,14 +73,17 @@ impl Plugin for StoragesPlugin { )?))) } } + +type PluginsManager = zenoh_plugin_trait::loading::PluginsManager; + struct StorageRuntime(Arc>); struct StorageRuntimeInner { name: String, runtime: Runtime, session: Arc, - lib_loader: LibLoader, volumes: HashMap, storages: HashMap>>, + plugins_manager: PluginsManager, } impl StorageRuntimeInner { fn status_key(&self) -> String { @@ -110,9 +114,9 @@ impl StorageRuntimeInner { name, runtime, session, - lib_loader, volumes: Default::default(), storages: Default::default(), + plugins_manager: PluginsManager::dynamic(lib_loader, BACKEND_LIB_PREFIX), }; new_self.spawn_volume(VolumeConfig { name: MEMORY_BACKEND_NAME.into(), @@ -153,51 +157,27 @@ impl StorageRuntimeInner { std::mem::drop(self.volumes.remove(&volume.name)); } fn spawn_volume(&mut self, config: VolumeConfig) -> ZResult<()> { - let volume_id = config.name.clone(); - if volume_id == MEMORY_BACKEND_NAME { + let volume_id = config.name(); + let backend_name = config.backend(); + if backend_name == MEMORY_BACKEND_NAME { match create_memory_backend(config) { Ok(backend) => { self.volumes.insert( - volume_id, + volume_id.to_string(), VolumeHandle::new(backend, None, "".into()), ); } Err(e) => bail!("{}", e), } } else { - match config.backend_search_method() { - BackendSearchMethod::ByPaths(paths) => { - for path in paths { - unsafe { - if let Ok((lib, path)) = LibLoader::load_file(path) { - return self.loaded_backend_from_lib( - &volume_id, - config.clone(), - lib, - path, - ); - } - } - } - bail!( - "Failed to find a suitable library for volume {} from paths: {:?}", - volume_id, - paths - ); - } - BackendSearchMethod::ByName(backend_name) => unsafe { - let backend_filename = format!("{}{}", BACKEND_LIB_PREFIX, &backend_name); - if let Ok((lib, path)) = self.lib_loader.search_and_load(&backend_filename) { - self.loaded_backend_from_lib(&volume_id, config.clone(), lib, path)?; - } else { - bail!( - "Failed to find a suitable library for volume {} (was looking for {}<.so/.dll/.dylib>)", - volume_id, - &backend_filename - ); - } - }, - }; + if let Some(paths) = config.paths() { + self.plugins_manager + .load_plugin_by_paths(volume_id, paths)?; + } else { + self.plugins_manager + .load_plugin_by_backend_name(volume_id, backend_name)?; + } + if let Some() }; Ok(()) } diff --git a/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs b/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs index 3def07880d..96a5ec22dc 100644 --- a/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs +++ b/plugins/zenoh-plugin-storage-manager/src/memory_backend/mod.rs @@ -21,7 +21,7 @@ use zenoh_backend_traits::config::{StorageConfig, VolumeConfig}; use zenoh_backend_traits::*; use zenoh_result::ZResult; -pub fn create_memory_backend(config: VolumeConfig) -> ZResult> { +pub fn create_memory_backend(config: VolumeConfig) -> ZResult { Ok(Box::new(MemoryBackend { config })) } diff --git a/plugins/zenoh-plugin-trait/src/loading.rs b/plugins/zenoh-plugin-trait/src/loading.rs index 1ca1320470..f8ec592715 100644 --- a/plugins/zenoh-plugin-trait/src/loading.rs +++ b/plugins/zenoh-plugin-trait/src/loading.rs @@ -16,30 +16,35 @@ use libloading::Library; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::path::PathBuf; -use vtable::{PluginVTable, PluginLoaderVersion, PLUGIN_LOADER_VERSION, Compatibility}; +use vtable::{Compatibility, PluginLoaderVersion, PluginVTable, PLUGIN_LOADER_VERSION}; use zenoh_result::{bail, zerror, ZResult}; use zenoh_util::LibLoader; /// A plugins manager that handles starting and stopping plugins. /// Plugins can be loaded from shared libraries using [`Self::load_plugin_by_name`] or [`Self::load_plugin_by_paths`], or added directly from the binary if available using [`Self::add_static`]. pub struct PluginsManager { + default_lib_prefix: String, loader: Option, plugin_starters: Vec + Send + Sync>>, running_plugins: HashMap, } -impl PluginsManager { +impl + PluginsManager +{ /// Constructs a new plugin manager with dynamic library loading enabled. - pub fn dynamic(loader: LibLoader) -> Self { + pub fn dynamic>(loader: LibLoader, default_lib_prefix: S) -> Self { PluginsManager { + default_lib_prefix: default_lib_prefix.into(), loader: Some(loader), plugin_starters: Vec::new(), running_plugins: HashMap::new(), } } - /// Constructs a new plugin manager with dynamic library loading enabled. + /// Constructs a new plugin manager with dynamic library loading disabled. pub fn static_plugins_only() -> Self { PluginsManager { + default_lib_prefix: String::new(), loader: None, plugin_starters: Vec::new(), running_plugins: HashMap::new(), @@ -157,12 +162,20 @@ impl ZResult { + /// Tries to load a plugin with the name `defaukt_lib_prefix` + `backend_name` + `.so | .dll | .dylib` + /// in lib_loader's search paths. + pub fn load_plugin_by_backend_name, T1: AsRef>( + &mut self, + name: T, + backend_name: T1, + ) -> ZResult { + let name = name.as_ref(); + let backend_name = backend_name.as_ref(); let (lib, p) = match &mut self.loader { - Some(l) => unsafe { l.search_and_load(&format!("zenoh_plugin_{}", &name))? }, - None => bail!("Can't load dynamic plugin ` {}`, as dynamic loading is not enabled for this plugin manager.", name), + 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()) { + let plugin = match Self::load_plugin(name, lib, p.clone()) { Ok(p) => p, Err(e) => bail!("After loading `{:?}`: {}", &p, e), }; @@ -170,16 +183,18 @@ impl + std::fmt::Debug>( + /// Tries to load a plugin from the list of path to plugin (absolute or relative to the current working directory) + pub fn load_plugin_by_paths, P: AsRef + std::fmt::Debug>( &mut self, - name: String, + name: T, paths: &[P], ) -> ZResult { + let name = name.as_ref(); 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)?; + let plugin = Self::load_plugin(name, lib, p)?; let path = plugin.path().into(); self.plugin_starters.push(Box::new(plugin)); return Ok(path); @@ -228,8 +243,8 @@ where } } -impl PluginStarter - for DynamicPlugin +impl + PluginStarter for DynamicPlugin { fn name(&self) -> &str { &self.name @@ -252,20 +267,29 @@ pub struct DynamicPlugin DynamicPlugin { +impl + DynamicPlugin +{ fn new(name: String, lib: Library, path: PathBuf) -> ZResult { - let get_plugin_loader_version = unsafe { - lib.get:: PluginLoaderVersion>(b"get_plugin_loader_version")? - }; + let get_plugin_loader_version = + unsafe { lib.get:: PluginLoaderVersion>(b"get_plugin_loader_version")? }; let plugin_loader_version = get_plugin_loader_version(); if plugin_loader_version != PLUGIN_LOADER_VERSION { - bail!("Plugin loader version mismatch: host = {}, plugin = {}", 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::(); if !plugin_compatibility_record.are_compatible(&host_compatibility_record) { - bail!("Plugin compatibility mismatch:\nhost = {:?}\nplugin = {:?}\n", host_compatibility_record, plugin_compatibility_record); + bail!( + "Plugin compatibility mismatch:\nhost = {:?}\nplugin = {:?}\n", + host_compatibility_record, + plugin_compatibility_record + ); } // TODO: check loader version and compatibility diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index a71382dea2..329cca0e47 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -195,12 +195,13 @@ impl AdminSpace { plugins_mgr.stop(&plugin); } PluginDiff::Start(plugin) => { - let load = match &plugin.paths { - Some(paths) => { - plugins_mgr.load_plugin_by_paths(plugin.name.clone(), paths) - } - None => plugins_mgr.load_plugin_by_name(plugin.name.clone()), - }; + let load = + match &plugin.paths { + Some(paths) => plugins_mgr + .load_plugin_by_paths(plugin.name.clone(), paths), + None => plugins_mgr + .load_plugin_by_backend_name(plugin.name.clone()), + }; match load { Err(e) => { if plugin.required { diff --git a/zenohd/src/main.rs b/zenohd/src/main.rs index 28df513a46..dc31a0d5bb 100644 --- a/zenohd/src/main.rs +++ b/zenohd/src/main.rs @@ -90,7 +90,7 @@ clap::Arg::new("adminspace-permissions").long("adminspace-permissions").value_na req = if required { "required" } else { "" } ); if let Err(e) = match paths { - None => plugins.load_plugin_by_name(name.clone()), + None => plugins.load_plugin_by_backend_name(name.clone()), Some(paths) => plugins.load_plugin_by_paths(name.clone(), &paths), } { if required {