use crate::core::Core;
use crate::registry;
use crate::tools::get_eva_dir;
use crate::tools::ErrLogger;
use crate::{EResult, Error};
use crate::{BUILD, PRODUCT_CODE, PRODUCT_NAME, VERSION};
use elbus::rpc::RpcClient;
use eva_common::Value;
use log::{debug, info};
use serde::Serialize;
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;
use std::sync::Arc;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Mode {
Normal,
Registry,
Info,
}
impl FromStr for Mode {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"normal" => Ok(Mode::Normal),
"registry" => Ok(Mode::Registry),
"info" => Ok(Mode::Info),
_ => Err(Error::invalid_data(format!("Invalid mode: {}", s))),
}
}
}
impl fmt::Display for Mode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Mode::Normal => "normal",
Mode::Registry => "registry",
Mode::Info => "info",
}
)
}
}
#[derive(Serialize)]
struct Info<'a> {
name: &'a str,
code: &'a str,
build: u64,
version: &'a str,
}
pub fn run(mode: Mode) -> EResult<()> {
if mode == Mode::Info {
let info = Info {
name: PRODUCT_NAME,
code: PRODUCT_CODE,
build: BUILD,
version: VERSION,
};
println!("{}", serde_json::to_string(&info)?);
return Ok(());
}
let dir_eva = get_eva_dir();
let reg_db = yedb::server::create_db();
let mut db = reg_db.try_write()?;
let db_path = format!("{dir_eva}/runtime/registry");
db.set_db_path(&db_path)?;
db.open()
.map_err(|e| Error::registry(format!("unable to open the registry {}: {}", db_path, e)))?;
let mut core = Core::new_from_db(&mut db, &dir_eva)?;
let log_config: Vec<HashMap<String, Value>> =
serde_json::from_value(db.key_get(®istry::format_config_key("logs"))?)?;
crate::logs::init(core.system_name(), "eva-node", log_config, &dir_eva);
info!("starting EVA ICS node {}", core.system_name());
info!("mode: {}", mode);
registry::load(&mut db)?;
core.set_boot_id(&mut db)?;
core.log_summary();
let mut broker = crate::bus::EvaBroker::new_from_db(&mut db, &dir_eva)?;
let rt = tokio::runtime::Builder::new_multi_thread()
.worker_threads(core.workers())
.enable_all()
.build()?;
if mode == Mode::Normal {
core.load_inventory(&mut db)?;
core.service_manager().load(&mut db)?;
}
drop(db);
debug!("starting runtime");
rt.block_on(async move {
crate::logs::start().await.log_err().unwrap();
broker.init(&mut core).await.log_err().unwrap();
let core_client = if mode == Mode::Normal {
let mut core_client = broker.register_client("eva.core").await.log_err().unwrap();
crate::core::init_core_client(&mut core_client)
.await
.log_err()
.unwrap();
Some(core_client)
} else {
None
};
let reg_client = broker
.register_client("eva.registry")
.await
.log_err()
.unwrap();
let laucher_client = broker
.register_client(crate::services::DEFAULT_LAUNCHER)
.await
.log_err()
.unwrap();
crate::launcher::init(laucher_client).await;
let _reg_rpc = RpcClient::new(reg_client, yedb::server::ElbusApi::new(reg_db.clone()));
let core = Arc::new(core);
if let Some(client) = core_client {
let core_rpc = RpcClient::new(client, crate::eapi::ElbusApi::new(core.clone()));
core.set_rpc(Arc::new(core_rpc)).await;
}
core.write_pid_file().await.log_err().unwrap();
core.register_signals().await;
core.start().await.log_err().unwrap();
core.mark_loaded().await;
core.service_manager()
.start(core.system_name(), core.timeout())
.await;
let c = core.clone();
tokio::spawn(async move {
c.announce_local().await;
});
core.block().await;
});
Ok(())
}