veilid/veilid-core/src/core_context.rs

298 lines
9.6 KiB
Rust
Raw Normal View History

2022-03-15 13:51:45 +00:00
use crate::api_logger::*;
2022-02-07 02:18:42 +00:00
use crate::attachment_manager::*;
2022-05-31 23:54:52 +00:00
use crate::dht::Crypto;
2022-02-07 02:18:42 +00:00
use crate::intf::*;
use crate::veilid_api::*;
use crate::veilid_config::*;
use crate::xx::*;
cfg_if! {
if #[cfg(target_arch = "wasm32")] {
2022-03-11 12:35:41 +00:00
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate)>;
2022-02-07 02:18:42 +00:00
} else {
2022-03-15 13:33:34 +00:00
2022-03-11 12:35:41 +00:00
pub type UpdateCallback = Arc<dyn Fn(VeilidUpdate) + Send + Sync>;
2022-02-07 02:18:42 +00:00
}
}
2022-03-09 03:32:12 +00:00
struct ServicesContext {
2022-02-07 02:18:42 +00:00
pub config: VeilidConfig,
2022-02-15 18:40:17 +00:00
pub update_callback: UpdateCallback,
2022-03-09 03:32:12 +00:00
pub protected_store: Option<ProtectedStore>,
pub table_store: Option<TableStore>,
pub block_store: Option<BlockStore>,
pub crypto: Option<Crypto>,
pub attachment_manager: Option<AttachmentManager>,
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
impl ServicesContext {
pub fn new_empty(config: VeilidConfig, update_callback: UpdateCallback) -> Self {
Self {
config,
update_callback,
protected_store: None,
table_store: None,
block_store: None,
crypto: None,
attachment_manager: None,
2022-02-09 14:47:36 +00:00
}
}
2022-03-09 03:32:12 +00:00
pub fn new_full(
config: VeilidConfig,
2022-02-09 14:47:36 +00:00
update_callback: UpdateCallback,
2022-03-09 03:32:12 +00:00
protected_store: ProtectedStore,
table_store: TableStore,
block_store: BlockStore,
crypto: Crypto,
attachment_manager: AttachmentManager,
) -> Self {
Self {
config,
update_callback,
protected_store: Some(protected_store),
table_store: Some(table_store),
block_store: Some(block_store),
crypto: Some(crypto),
attachment_manager: Some(attachment_manager),
2022-02-07 02:18:42 +00:00
}
2022-02-09 14:47:36 +00:00
}
2022-02-07 02:18:42 +00:00
2022-03-09 03:32:12 +00:00
pub async fn startup(&mut self) -> Result<(), VeilidAPIError> {
2022-03-15 13:33:34 +00:00
let log_level: VeilidConfigLogLevel = self.config.get().log_level;
if log_level != VeilidConfigLogLevel::Off {
2022-03-15 13:51:45 +00:00
ApiLogger::init(log_level.to_level_filter(), self.update_callback.clone()).await;
for ig in crate::DEFAULT_LOG_IGNORE_LIST {
ApiLogger::add_filter_ignore_str(ig);
2022-02-09 14:47:36 +00:00
}
2022-03-15 13:51:45 +00:00
info!("Veilid logging initialized");
2022-02-07 02:18:42 +00:00
}
2022-03-11 12:35:41 +00:00
info!("Veilid API starting up");
2022-03-09 03:32:12 +00:00
2022-02-07 02:18:42 +00:00
// Set up protected store
2022-03-09 03:32:12 +00:00
trace!("init protected store");
let protected_store = ProtectedStore::new(self.config.clone());
2022-02-07 02:18:42 +00:00
if let Err(e) = protected_store.init().await {
2022-03-09 03:32:12 +00:00
self.shutdown().await;
2022-02-09 14:47:36 +00:00
return Err(VeilidAPIError::Internal { message: e });
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
self.protected_store = Some(protected_store.clone());
2022-02-07 02:18:42 +00:00
// Init node id from config now that protected store is set up
2022-03-09 03:32:12 +00:00
if let Err(e) = self.config.init_node_id(protected_store.clone()).await {
self.shutdown().await;
2022-02-09 14:47:36 +00:00
return Err(VeilidAPIError::Internal { message: e });
2022-02-07 02:18:42 +00:00
}
// Set up tablestore
2022-03-09 03:32:12 +00:00
trace!("init table store");
let table_store = TableStore::new(self.config.clone());
2022-02-07 02:18:42 +00:00
if let Err(e) = table_store.init().await {
2022-03-09 03:32:12 +00:00
self.shutdown().await;
2022-02-09 14:47:36 +00:00
return Err(VeilidAPIError::Internal { message: e });
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
self.table_store = Some(table_store.clone());
2022-02-07 02:18:42 +00:00
// Set up crypto
2022-03-09 03:32:12 +00:00
trace!("init crypto");
let crypto = Crypto::new(self.config.clone(), table_store.clone());
2022-02-07 02:18:42 +00:00
if let Err(e) = crypto.init().await {
2022-03-09 03:32:12 +00:00
self.shutdown().await;
2022-02-09 14:47:36 +00:00
return Err(VeilidAPIError::Internal { message: e });
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
self.crypto = Some(crypto.clone());
2022-02-07 02:18:42 +00:00
// Set up block store
2022-03-09 03:32:12 +00:00
trace!("init block store");
let block_store = BlockStore::new(self.config.clone());
2022-02-07 02:18:42 +00:00
if let Err(e) = block_store.init().await {
2022-03-09 03:32:12 +00:00
self.shutdown().await;
2022-02-09 14:47:36 +00:00
return Err(VeilidAPIError::Internal { message: e });
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
self.block_store = Some(block_store.clone());
2022-02-07 02:18:42 +00:00
// Set up attachment manager
2022-03-09 03:32:12 +00:00
trace!("init attachment manager");
2022-03-24 14:14:50 +00:00
let update_callback = self.update_callback.clone();
2022-03-09 03:32:12 +00:00
let attachment_manager = AttachmentManager::new(self.config.clone(), table_store, crypto);
2022-03-24 14:14:50 +00:00
if let Err(e) = attachment_manager.init(update_callback).await {
2022-03-09 03:32:12 +00:00
self.shutdown().await;
return Err(VeilidAPIError::Internal { message: e });
}
self.attachment_manager = Some(attachment_manager);
2022-03-11 12:35:41 +00:00
info!("Veilid API startup complete");
2022-03-09 03:32:12 +00:00
Ok(())
}
pub async fn shutdown(&mut self) {
2022-03-11 12:35:41 +00:00
info!("Veilid API shutting down");
2022-03-09 03:32:12 +00:00
if let Some(attachment_manager) = &mut self.attachment_manager {
trace!("terminate attachment manager");
attachment_manager.terminate().await;
}
if let Some(block_store) = &mut self.block_store {
trace!("terminate block store");
2022-02-07 02:18:42 +00:00
block_store.terminate().await;
2022-03-09 03:32:12 +00:00
}
if let Some(crypto) = &mut self.crypto {
trace!("terminate crypto");
2022-02-07 02:18:42 +00:00
crypto.terminate().await;
2022-03-09 03:32:12 +00:00
}
if let Some(table_store) = &mut self.table_store {
trace!("terminate table store");
2022-02-07 02:18:42 +00:00
table_store.terminate().await;
2022-03-09 03:32:12 +00:00
}
if let Some(protected_store) = &mut self.protected_store {
trace!("terminate protected store");
2022-02-07 02:18:42 +00:00
protected_store.terminate().await;
2022-03-09 03:32:12 +00:00
}
2022-03-11 12:35:41 +00:00
info!("Veilid API shutdown complete");
2022-03-09 03:32:12 +00:00
// api logger terminate is idempotent
2022-03-15 13:51:45 +00:00
ApiLogger::terminate().await;
2022-03-09 03:32:12 +00:00
// send final shutdown update
2022-03-11 12:35:41 +00:00
(self.update_callback)(VeilidUpdate::Shutdown);
2022-03-09 03:32:12 +00:00
}
}
/////////////////////////////////////////////////////////////////////////////
///
pub struct VeilidCoreContext {
pub config: VeilidConfig,
pub update_callback: UpdateCallback,
// Services
pub protected_store: ProtectedStore,
pub table_store: TableStore,
pub block_store: BlockStore,
pub crypto: Crypto,
pub attachment_manager: AttachmentManager,
}
impl VeilidCoreContext {
async fn new_with_config_callback(
update_callback: UpdateCallback,
config_callback: ConfigCallback,
) -> Result<VeilidCoreContext, VeilidAPIError> {
// Set up config from callback
trace!("setup config with callback");
let mut config = VeilidConfig::new();
if let Err(e) = config.setup(config_callback) {
2022-02-09 14:47:36 +00:00
return Err(VeilidAPIError::Internal { message: e });
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
Self::new_common(update_callback, config).await
2022-02-07 02:18:42 +00:00
}
2022-03-09 03:32:12 +00:00
async fn new_with_config_json(
update_callback: UpdateCallback,
config_json: String,
) -> Result<VeilidCoreContext, VeilidAPIError> {
// Set up config from callback
trace!("setup config with json");
let mut config = VeilidConfig::new();
if let Err(e) = config.setup_from_json(config_json) {
return Err(VeilidAPIError::Internal { message: e });
}
Self::new_common(update_callback, config).await
}
2022-02-07 02:18:42 +00:00
2022-03-09 03:32:12 +00:00
async fn new_common(
update_callback: UpdateCallback,
config: VeilidConfig,
) -> Result<VeilidCoreContext, VeilidAPIError> {
cfg_if! {
if #[cfg(target_os = "android")] {
if utils::android::ANDROID_GLOBALS.lock().is_none() {
error!("Android globals are not set up");
return Err(VeilidAPIError::Internal { message: "Android globals are not set up".to_owned() });
}
}
}
2022-02-07 02:18:42 +00:00
2022-03-09 03:32:12 +00:00
let mut sc = ServicesContext::new_empty(config.clone(), update_callback);
sc.startup().await?;
2022-02-15 18:40:17 +00:00
2022-03-09 03:32:12 +00:00
Ok(VeilidCoreContext {
update_callback: sc.update_callback,
config: sc.config,
protected_store: sc.protected_store.unwrap(),
table_store: sc.table_store.unwrap(),
block_store: sc.block_store.unwrap(),
crypto: sc.crypto.unwrap(),
attachment_manager: sc.attachment_manager.unwrap(),
})
}
async fn shutdown(self) {
let mut sc = ServicesContext::new_full(
self.config.clone(),
self.update_callback.clone(),
self.protected_store,
self.table_store,
self.block_store,
self.crypto,
self.attachment_manager,
);
sc.shutdown().await;
2022-02-07 02:18:42 +00:00
}
}
/////////////////////////////////////////////////////////////////////////////
static INITIALIZED: AsyncMutex<bool> = AsyncMutex::new(false);
2022-02-09 14:47:36 +00:00
pub async fn api_startup(
update_callback: UpdateCallback,
config_callback: ConfigCallback,
) -> Result<VeilidAPI, VeilidAPIError> {
// See if we have an API started up already
let mut initialized_lock = INITIALIZED.lock().await;
if *initialized_lock {
return Err(VeilidAPIError::AlreadyInitialized);
}
// Create core context
let context =
VeilidCoreContext::new_with_config_callback(update_callback, config_callback).await?;
// Return an API object around our context
let veilid_api = VeilidAPI::new(context);
*initialized_lock = true;
Ok(veilid_api)
}
pub async fn api_startup_json(
update_callback: UpdateCallback,
config_json: String,
) -> Result<VeilidAPI, VeilidAPIError> {
2022-02-07 02:18:42 +00:00
// See if we have an API started up already
let mut initialized_lock = INITIALIZED.lock().await;
if *initialized_lock {
return Err(VeilidAPIError::AlreadyInitialized);
}
// Create core context
2022-02-09 14:47:36 +00:00
let context = VeilidCoreContext::new_with_config_json(update_callback, config_json).await?;
2022-02-07 02:18:42 +00:00
// Return an API object around our context
let veilid_api = VeilidAPI::new(context);
*initialized_lock = true;
Ok(veilid_api)
}
2022-03-09 03:32:12 +00:00
pub(crate) async fn api_shutdown(context: VeilidCoreContext) {
2022-02-07 02:18:42 +00:00
let mut initialized_lock = INITIALIZED.lock().await;
context.shutdown().await;
*initialized_lock = false;
}