module loading works

This commit is contained in:
Sebastian Moser
2024-08-29 08:40:38 +02:00
parent ed9da830c9
commit 5cfc9cfe7c
10 changed files with 177 additions and 25 deletions

View File

@@ -20,7 +20,7 @@ use crate::instance::subscription::Subscription;
use crate::item::{Item, ItemData};
use crate::memstore::MemStore;
use crate::instance::updater::Operation;
use crate::mize_err;
use crate::{mize_err, Module};
use crate::proto::MizeMessage;
use self::connection::{ConnListener, Connection};
@@ -51,6 +51,7 @@ pub struct Instance {
connections: Arc<Mutex<Vec<Connection>>>,
next_con_id: Arc<Mutex<u64>>,
subs: Arc<Mutex<HashMap<MizeId, Vec<Subscription>>>>,
pub modules: Arc<Mutex<HashMap<String, Box<dyn Module + Sync + Send>>>>,
pub id_pool: Arc<Mutex<VecStringPool>>,
pub namespace_pool: Arc<Mutex<StringPool>>,
@@ -96,6 +97,7 @@ impl Instance {
connections, subs, id_pool,
namespace, self_namespace, op_tx,
namespace_pool: Arc::new(Mutex::new(namespace_pool_raw)),
modules: Arc::new(Mutex::new(HashMap::new())),
context: vec![],
threads: vec![],
next_con_id: Arc::new(Mutex::new(1)),
@@ -115,7 +117,8 @@ impl Instance {
let closure_two = move || updater_thread(op_rx, &instance_clone_two);
instance.spawn("updater_thread", closure_two)?;
// will probably move the msg stuff into it's own thread
// will move the msg stuff into it's own thread
// like this it can deadlock.... if a msg waits on an operation to complete
//let msg_instance_clone = instance.clone();
//let msg_closure = move || msg_thread(op_rx, instance_clone);
//instance.spawn("msg_thread", closure)?;
@@ -142,6 +145,16 @@ impl Instance {
crate::platform::any::instance_init(self);
// end of platform specific init code
self.load_module("Blob")?;
let mut modules_inner = self.modules.lock()?;
let module = modules_inner.get_mut("Blob").unwrap();
println!("right before segfault");
module.init(&self);
//self.load_module("String")?;
debug!("INSTANCE INIT DONE");
Ok(())
@@ -275,6 +288,11 @@ impl Instance {
Ok(id)
}
pub fn load_module(&mut self, name: &str) -> MizeResult<()> {
// platform specific init code
crate::platform::any::load_module(self, name)
}
pub fn namespace_from_string(&self, ns_str: String) -> MizeResult<Namespace> {
let namespace_pool_inner = self.namespace_pool.lock()?;
let namespace = Namespace ( namespace_pool_inner.get(ns_str) );

View File

@@ -2,5 +2,28 @@
// https://users.rust-lang.org/t/casting-between-trait-object-types/97220/2
use crate::instance::Instance;
use crate::error::MizeResult;
pub trait Module {
fn init(&mut self, instance: &Instance) -> MizeResult<()>;
fn exit(&mut self, instance: &Instance) -> MizeResult<()>;
}
pub struct EmptyModule {
}
impl Module for EmptyModule {
fn init(&mut self, instance: &Instance) -> MizeResult<()> {
println!("empty module fn init");
Ok(())
}
fn exit(&mut self, instance: &Instance) -> MizeResult<()> {
println!("empty module fn exit");
Ok(())
}
}

View File

@@ -15,7 +15,10 @@ mod core {
}
pub use core::*;
pub use core::instance::module::Module;
pub use core::instance::Instance;
pub use core::error::MizeError;
pub use core::error::MizeResult;
// platform specific stuff
pub mod platform {
@@ -31,8 +34,24 @@ pub mod platform {
#[cfg(feature = "os-target")]
pub use super::os::os_instance_init as instance_init;
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
pub use super::super::instance_init;
#[cfg(feature = "os-target")]
pub use super::os::load_module;
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
pub use super::super::load_module;
}
}
pub fn instance_init(instance: &mut core::instance::Instance) {}
pub fn load_module(instance: &mut core::instance::Instance, name: &str) -> MizeResult<()> { Ok(()) }

View File

@@ -5,6 +5,7 @@ use std::fs;
use tracing::{debug, error, info, trace, warn};
use clap::ArgMatches;
use std::path::Path;
use std::time::UNIX_EPOCH;
use crate::id::MizeId;
use crate::instance::store::Store;
@@ -12,8 +13,9 @@ use crate::instance::Instance;
use crate::error::{IntoMizeResult, MizeError, MizeResult};
use crate::item::{ItemData, IntoItemData};
use crate::memstore::MemStore;
use crate::mize_err;
use crate::{mize_err, Module};
use crate::platform::os::unix_socket::UnixListener;
use crate::instance::module::EmptyModule;
use self::fsstore::FileStore;
@@ -63,17 +65,17 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
////// if a config.store_path is set, upgrade to the filestore there
let mut test = instance.get("0")?.as_data_full()?;
let mut store_path = instance.get("0/config/store_path")?.value_string()?;
if store_path == "" {
let home_dir = env!("HOME");
if home_dir == "" {
return Err(mize_err!("env var $HOME empty"));
}
// the default store_path: $HOME/.mize
store_path = home_dir.to_owned() + "/.mize";
}
let mut store_path = match instance.get("0/config/store_path")?.value_string() {
Ok(path) => path,
Err(e) => {
// the default store_path: $HOME/.mize
let home_dir = env!("HOME");
if home_dir == "" {
return Err(mize_err!("env var $HOME empty"));
}
home_dir.to_owned() + "/.mize"
},
};
if FileStore::store_is_opened(store_path.to_owned())? {
// if the store is already opened, connect to the instance, that opened it and join
@@ -94,6 +96,62 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
Ok(())
}
pub fn seconds_since_modification(path: &Path) -> u64 {
let metadata = match fs::metadata(path) {
Err(_) => { return u64::MAX; }, // we are the older file, if it fails
Ok(data) => data,
};
let modified = match metadata.modified() {
Err(_) => { return u64::MAX; }, // we are the older file, if it fails
Ok(data) => data,
};
let duration = match modified.duration_since(UNIX_EPOCH) {
Err(_) => { return u64::MAX; }, // we are the older file, if it fails
Ok(data) => data,
};
duration.as_secs()
}
pub fn load_module(instance: &mut Instance, name: &str) -> MizeResult<()> {
let module_dir_str = instance.get("0/config/module_dir")?.value_string()?;
let module_dir = Path::new(&module_dir_str);
let release_path = module_dir.join("modules").join(name).join("target").join("release").join(format!("libmize_module_{}.so", name));
let debug_path = module_dir.join("modules").join(name).join("target").join("debug").join(format!("libmize_module_{}.so", name));
let module_path = match seconds_since_modification(&release_path) > seconds_since_modification(&debug_path) {
true => debug_path,
false => release_path,
};
let lib = unsafe { libloading::Library::new(module_path)? };
let func: libloading::Symbol<unsafe extern "C" fn(&mut Box<dyn Module + Send + Sync>) -> ()> = unsafe { lib.get(format!("get_mize_module_{}", name).as_bytes())? };
let mut module: Box<dyn Module + Send + Sync> = Box::new(EmptyModule {});
unsafe { func(&mut module) };
let mut modules_inner = instance.modules.lock()?;
module.init(&instance);
modules_inner.insert(name.to_owned(), module);
unsafe {
// dropping the lib, would (i suspect) free all memory, of the library's code, which would
// make the module's vtable point into empty memory
std::mem::forget(lib);
}
Ok(())
}
pub fn config_from_cli_args(matches: &ArgMatches) -> MizeResult<ItemData> {
let mut config = ItemData::new();