diff --git a/veilid-core/src/core_context.rs b/veilid-core/src/core_context.rs index 6eab73d5..e538413c 100644 --- a/veilid-core/src/core_context.rs +++ b/veilid-core/src/core_context.rs @@ -42,33 +42,23 @@ impl StartupShutdownContext { } #[allow(clippy::too_many_arguments)] - pub fn new_full( - config: VeilidConfig, - update_callback: UpdateCallback, - event_bus: EventBus, - protected_store: ProtectedStore, - table_store: TableStore, - #[cfg(feature = "unstable-blockstore")] block_store: BlockStore, - crypto: Crypto, - attachment_manager: AttachmentManager, - storage_manager: StorageManager, - ) -> Self { + pub fn new_full(context: VeilidCoreContext) -> Self { Self { - config, - update_callback, - event_bus: Some(event_bus), - protected_store: Some(protected_store), - table_store: Some(table_store), + config: context.config, + update_callback: context.update_callback, + event_bus: Some(context.event_bus), + protected_store: Some(context.protected_store), + table_store: Some(context.table_store), #[cfg(feature = "unstable-blockstore")] - block_store: Some(block_store), - crypto: Some(crypto), - attachment_manager: Some(attachment_manager), - storage_manager: Some(storage_manager), + block_store: Some(context.block_store), + crypto: Some(context.crypto), + attachment_manager: Some(context.attachment_manager), + storage_manager: Some(context.storage_manager), } } #[instrument(level = "trace", target = "core_context", err, skip_all)] - pub async fn startup(&mut self) -> EyreResult<()> { + pub async fn startup(mut self) -> EyreResult { info!("Veilid API starting up"); info!("init api tracing"); @@ -174,33 +164,44 @@ impl StartupShutdownContext { self.attachment_manager = Some(attachment_manager); info!("Veilid API startup complete"); - Ok(()) + Ok(VeilidCoreContext { + config: self.config, + update_callback: self.update_callback, + event_bus: self.event_bus.unwrap(), + storage_manager: self.storage_manager.unwrap(), + protected_store: self.protected_store.unwrap(), + table_store: self.table_store.unwrap(), + #[cfg(feature = "unstable-blockstore")] + block_store: self.block_store.unwrap(), + crypto: self.crypto.unwrap(), + attachment_manager: self.attachment_manager.unwrap(), + }) } #[instrument(level = "trace", target = "core_context", skip_all)] - pub async fn shutdown(&mut self) { + pub async fn shutdown(mut self) { info!("Veilid API shutting down"); - if let Some(attachment_manager) = &mut self.attachment_manager { + if let Some(attachment_manager) = self.attachment_manager.take() { attachment_manager.terminate().await; } - if let Some(storage_manager) = &mut self.storage_manager { + if let Some(storage_manager) = self.storage_manager.take() { storage_manager.terminate().await; } #[cfg(feature = "unstable-blockstore")] - if let Some(block_store) = &mut self.block_store { + if let Some(block_store) = self.block_store.take() { block_store.terminate().await; } - if let Some(crypto) = &mut self.crypto { + if let Some(crypto) = self.crypto.take() { crypto.terminate().await; } - if let Some(table_store) = &mut self.table_store { + if let Some(table_store) = self.table_store.take() { table_store.terminate().await; } - if let Some(protected_store) = &mut self.protected_store { + if let Some(protected_store) = self.protected_store.take() { protected_store.terminate().await; } - if let Some(event_bus) = &mut self.event_bus { + if let Some(event_bus) = self.event_bus.take() { event_bus.shutdown().await; } @@ -228,12 +229,12 @@ pub struct VeilidCoreContext { // Event bus pub event_bus: EventBus, // Services - pub storage_manager: StorageManager, + pub crypto: Crypto, pub protected_store: ProtectedStore, pub table_store: TableStore, #[cfg(feature = "unstable-blockstore")] pub block_store: BlockStore, - pub crypto: Crypto, + pub storage_manager: StorageManager, pub attachment_manager: AttachmentManager, } @@ -274,37 +275,13 @@ impl VeilidCoreContext { } } - let mut sc = StartupShutdownContext::new_empty(config.clone(), update_callback); - sc.startup().await.map_err(VeilidAPIError::generic)?; - - Ok(VeilidCoreContext { - config: sc.config, - update_callback: sc.update_callback, - event_bus: sc.event_bus.unwrap(), - storage_manager: sc.storage_manager.unwrap(), - protected_store: sc.protected_store.unwrap(), - table_store: sc.table_store.unwrap(), - #[cfg(feature = "unstable-blockstore")] - block_store: sc.block_store.unwrap(), - crypto: sc.crypto.unwrap(), - attachment_manager: sc.attachment_manager.unwrap(), - }) + let sc = StartupShutdownContext::new_empty(config.clone(), update_callback); + sc.startup().await.map_err(VeilidAPIError::generic) } #[instrument(level = "trace", target = "core_context", skip_all)] async fn shutdown(self) { - let mut sc = StartupShutdownContext::new_full( - self.config.clone(), - self.update_callback.clone(), - self.event_bus, - self.protected_store, - self.table_store, - #[cfg(feature = "unstable-blockstore")] - self.block_store, - self.crypto, - self.attachment_manager, - self.storage_manager, - ); + let sc = StartupShutdownContext::new_full(self); sc.shutdown().await; } } @@ -312,7 +289,8 @@ impl VeilidCoreContext { ///////////////////////////////////////////////////////////////////////////// lazy_static::lazy_static! { - static ref INITIALIZED: AsyncMutex> = AsyncMutex::new(HashSet::new()); + static ref INITIALIZED: Mutex> = Mutex::new(HashSet::new()); + static ref STARTUP_TABLE: AsyncTagLockTable<(String, String)> = AsyncTagLockTable::new(); } /// Initialize a Veilid node. @@ -345,9 +323,11 @@ pub async fn api_startup( })?; let init_key = (program_name, namespace); + // Only allow one startup/shutdown per program_name+namespace combination simultaneously + let _tag_guard = STARTUP_TABLE.lock_tag(init_key.clone()).await; + // See if we have an API started up already - let mut initialized_lock = INITIALIZED.lock().await; - if initialized_lock.contains(&init_key) { + if INITIALIZED.lock().contains(&init_key) { apibail_already_initialized!(); } @@ -358,7 +338,8 @@ pub async fn api_startup( // Return an API object around our context let veilid_api = VeilidAPI::new(context); - initialized_lock.insert(init_key); + // Add to the initialized set + INITIALIZED.lock().insert(init_key); Ok(veilid_api) } @@ -406,9 +387,11 @@ pub async fn api_startup_config( let init_key = (program_name, namespace); + // Only allow one startup/shutdown per program_name+namespace combination simultaneously + let _tag_guard = STARTUP_TABLE.lock_tag(init_key.clone()).await; + // See if we have an API started up already - let mut initialized_lock = INITIALIZED.lock().await; - if initialized_lock.contains(&init_key) { + if INITIALIZED.lock().contains(&init_key) { apibail_already_initialized!(); } @@ -418,20 +401,30 @@ pub async fn api_startup_config( // Return an API object around our context let veilid_api = VeilidAPI::new(context); - initialized_lock.insert(init_key); + // Add to the initialized set + INITIALIZED.lock().insert(init_key); Ok(veilid_api) } #[instrument(level = "trace", target = "core_context", skip_all)] -pub async fn api_shutdown(context: VeilidCoreContext) { - let mut initialized_lock = INITIALIZED.lock().await; - +pub(crate) async fn api_shutdown(context: VeilidCoreContext) { let init_key = { let config = context.config.get(); (config.program_name.clone(), config.namespace.clone()) }; + // Only allow one startup/shutdown per program_name+namespace combination simultaneously + let _tag_guard = STARTUP_TABLE.lock_tag(init_key.clone()).await; + + // See if we have an API started up already + if !INITIALIZED.lock().contains(&init_key) { + return; + } + + // Shutdown the context context.shutdown().await; - initialized_lock.remove(&init_key); + + // Remove from the initialized set + INITIALIZED.lock().remove(&init_key); } diff --git a/veilid-core/src/logging/api_tracing_layer.rs b/veilid-core/src/logging/api_tracing_layer.rs index af7be16a..a460a477 100644 --- a/veilid-core/src/logging/api_tracing_layer.rs +++ b/veilid-core/src/logging/api_tracing_layer.rs @@ -2,7 +2,6 @@ use crate::core_context::*; use crate::veilid_api::*; use crate::*; use core::fmt::Write; -use once_cell::sync::OnceCell; use tracing_subscriber::*; struct ApiTracingLayerInner { @@ -21,11 +20,10 @@ struct ApiTracingLayerInner { /// with many copies of Veilid running. #[derive(Clone)] -pub struct ApiTracingLayer { - inner: Arc>>, -} +pub struct ApiTracingLayer {} -static API_LOGGER: OnceCell = OnceCell::new(); +static API_LOGGER_INNER: Mutex> = Mutex::new(None); +static API_LOGGER_ENABLED: AtomicBool = AtomicBool::new(false); impl ApiTracingLayer { /// Initialize an ApiTracingLayer singleton @@ -33,11 +31,7 @@ impl ApiTracingLayer { /// This must be inserted into your tracing subscriber before you /// call api_startup() or api_startup_json() if you are going to use api tracing. pub fn init() -> ApiTracingLayer { - API_LOGGER - .get_or_init(|| ApiTracingLayer { - inner: Arc::new(Mutex::new(None)), - }) - .clone() + ApiTracingLayer {} } fn new_inner() -> ApiTracingLayerInner { @@ -52,12 +46,7 @@ impl ApiTracingLayer { namespace: String, update_callback: UpdateCallback, ) -> VeilidAPIResult<()> { - let Some(api_logger) = API_LOGGER.get() else { - // Did not init, so skip this - return Ok(()); - }; - - let mut inner = api_logger.inner.lock(); + let mut inner = API_LOGGER_INNER.lock(); if inner.is_none() { *inner = Some(Self::new_inner()); } @@ -70,6 +59,9 @@ impl ApiTracingLayer { .unwrap() .update_callbacks .insert(key, update_callback); + + API_LOGGER_ENABLED.store(true, Ordering::Release); + return Ok(()); } @@ -79,28 +71,29 @@ impl ApiTracingLayer { namespace: String, ) -> VeilidAPIResult<()> { let key = (program_name, namespace); - if let Some(api_logger) = API_LOGGER.get() { - let mut inner = api_logger.inner.lock(); - if inner.is_none() { - apibail_not_initialized!(); - } - if inner - .as_mut() - .unwrap() - .update_callbacks - .remove(&key) - .is_none() - { - apibail_not_initialized!(); - } - if inner.as_mut().unwrap().update_callbacks.is_empty() { - *inner = None; - } + + let mut inner = API_LOGGER_INNER.lock(); + if inner.is_none() { + apibail_not_initialized!(); } + if inner + .as_mut() + .unwrap() + .update_callbacks + .remove(&key) + .is_none() + { + apibail_not_initialized!(); + } + if inner.as_mut().unwrap().update_callbacks.is_empty() { + *inner = None; + API_LOGGER_ENABLED.store(false, Ordering::Release); + } + Ok(()) } - fn emit_log(&self, inner: &mut ApiTracingLayerInner, meta: &Metadata<'_>, message: String) { + fn emit_log(&self, meta: &'static Metadata<'static>, message: String) { let level = *meta.level(); let target = meta.target(); let log_level = VeilidLogLevel::from_tracing_level(level); @@ -148,8 +141,10 @@ impl ApiTracingLayer { backtrace, })); - for cb in inner.update_callbacks.values() { - (cb)(log_update.clone()); + if let Some(inner) = &mut *API_LOGGER_INNER.lock() { + for cb in inner.update_callbacks.values() { + (cb)(log_update.clone()); + } } } } @@ -159,17 +154,23 @@ pub struct SpanDuration { end: Timestamp, } -fn simplify_file(file: &str) -> String { - let path = std::path::Path::new(file); - let path_component_count = path.iter().count(); - if path.ends_with("mod.rs") && path_component_count >= 2 { - let outpath: std::path::PathBuf = path.iter().skip(path_component_count - 2).collect(); - outpath.to_string_lossy().to_string() - } else if let Some(filename) = path.file_name() { - filename.to_string_lossy().to_string() - } else { - file.to_string() - } +fn simplify_file(file: &'static str) -> &'static str { + file.static_transform(|file| { + let out = { + let path = std::path::Path::new(file); + let path_component_count = path.iter().count(); + if path.ends_with("mod.rs") && path_component_count >= 2 { + let outpath: std::path::PathBuf = + path.iter().skip(path_component_count - 2).collect(); + outpath.to_string_lossy().to_string() + } else if let Some(filename) = path.file_name() { + filename.to_string_lossy().to_string() + } else { + file.to_string() + } + }; + out.to_static_str() + }) } impl registry::LookupSpan<'a>> Layer for ApiTracingLayer { @@ -179,47 +180,51 @@ impl registry::LookupSpan<'a>> Layer for ApiTracingLa id: &tracing::Id, ctx: layer::Context<'_, S>, ) { - if let Some(_inner) = &mut *self.inner.lock() { - let mut new_debug_record = StringRecorder::new(); - attrs.record(&mut new_debug_record); + if !API_LOGGER_ENABLED.load(Ordering::Acquire) { + // Optimization if api logger has no callbacks + return; + } - if let Some(span_ref) = ctx.span(id) { + let mut new_debug_record = StringRecorder::new(); + attrs.record(&mut new_debug_record); + + if let Some(span_ref) = ctx.span(id) { + span_ref + .extensions_mut() + .insert::(new_debug_record); + if crate::DURATION_LOG_FACILITIES.contains(&attrs.metadata().target()) { span_ref .extensions_mut() - .insert::(new_debug_record); - if crate::DURATION_LOG_FACILITIES.contains(&attrs.metadata().target()) { - span_ref - .extensions_mut() - .insert::(SpanDuration { - start: Timestamp::now(), - end: Timestamp::default(), - }); - } + .insert::(SpanDuration { + start: Timestamp::now(), + end: Timestamp::default(), + }); } } } fn on_close(&self, id: span::Id, ctx: layer::Context<'_, S>) { - if let Some(inner) = &mut *self.inner.lock() { - if let Some(span_ref) = ctx.span(&id) { - if let Some(span_duration) = span_ref.extensions_mut().get_mut::() { - span_duration.end = Timestamp::now(); - let duration = span_duration.end.saturating_sub(span_duration.start); - let meta = span_ref.metadata(); - self.emit_log( - inner, - meta, - format!( - " {}{}: duration={}", - span_ref - .parent() - .map(|p| format!("{}::", p.name())) - .unwrap_or_default(), - span_ref.name(), - format_opt_ts(Some(duration)) - ), - ); - } + if !API_LOGGER_ENABLED.load(Ordering::Acquire) { + // Optimization if api logger has no callbacks + return; + } + if let Some(span_ref) = ctx.span(&id) { + if let Some(span_duration) = span_ref.extensions_mut().get_mut::() { + span_duration.end = Timestamp::now(); + let duration = span_duration.end.saturating_sub(span_duration.start); + let meta = span_ref.metadata(); + self.emit_log( + meta, + format!( + " {}{}: duration={}", + span_ref + .parent() + .map(|p| format!("{}::", p.name())) + .unwrap_or_default(), + span_ref.name(), + format_opt_ts(Some(duration)) + ), + ); } } } @@ -230,22 +235,26 @@ impl registry::LookupSpan<'a>> Layer for ApiTracingLa values: &tracing::span::Record<'_>, ctx: layer::Context<'_, S>, ) { - if let Some(_inner) = &mut *self.inner.lock() { - if let Some(span_ref) = ctx.span(id) { - if let Some(debug_record) = span_ref.extensions_mut().get_mut::() { - values.record(debug_record); - } + if !API_LOGGER_ENABLED.load(Ordering::Acquire) { + // Optimization if api logger has no callbacks + return; + } + if let Some(span_ref) = ctx.span(id) { + if let Some(debug_record) = span_ref.extensions_mut().get_mut::() { + values.record(debug_record); } } } fn on_event(&self, event: &tracing::Event<'_>, _ctx: layer::Context<'_, S>) { - if let Some(inner) = &mut *self.inner.lock() { - let mut recorder = StringRecorder::new(); - event.record(&mut recorder); - let meta = event.metadata(); - self.emit_log(inner, meta, recorder.to_string()); + if !API_LOGGER_ENABLED.load(Ordering::Acquire) { + // Optimization if api logger has no callbacks + return; } + let mut recorder = StringRecorder::new(); + event.record(&mut recorder); + let meta = event.metadata(); + self.emit_log(meta, recorder.to_string()); } } diff --git a/veilid-core/src/veilid_api/api.rs b/veilid-core/src/veilid_api/api.rs index 77e346eb..17988416 100644 --- a/veilid-core/src/veilid_api/api.rs +++ b/veilid-core/src/veilid_api/api.rs @@ -36,7 +36,7 @@ impl Drop for VeilidAPIInner { /// * Reply to `AppCall` RPCs. #[derive(Clone, Debug)] pub struct VeilidAPI { - pub(super) inner: Arc>, + inner: Arc>, } impl VeilidAPI { @@ -100,7 +100,7 @@ impl VeilidAPI { if let Some(context) = &inner.context { return Ok(context.table_store.clone()); } - Err(VeilidAPIError::not_initialized()) + Err(VeilidAPIError::NotInitialized) } /// Get the ProtectedStore manager. @@ -109,7 +109,7 @@ impl VeilidAPI { if let Some(context) = &inner.context { return Ok(context.protected_store.clone()); } - Err(VeilidAPIError::not_initialized()) + Err(VeilidAPIError::NotInitialized) } //////////////////////////////////////////////////////////////// @@ -119,14 +119,14 @@ impl VeilidAPI { if let Some(context) = &inner.context { return Ok(context.attachment_manager.clone()); } - Err(VeilidAPIError::not_initialized()) + Err(VeilidAPIError::NotInitialized) } pub(crate) fn network_manager(&self) -> VeilidAPIResult { let inner = self.inner.lock(); if let Some(context) = &inner.context { return Ok(context.attachment_manager.network_manager()); } - Err(VeilidAPIError::not_initialized()) + Err(VeilidAPIError::NotInitialized) } pub(crate) fn rpc_processor(&self) -> VeilidAPIResult { let inner = self.inner.lock(); @@ -155,7 +155,12 @@ impl VeilidAPI { if let Some(context) = &inner.context { return Ok(context.block_store.clone()); } - Err(VeilidAPIError::not_initialized()) + Err(VeilidAPIError::NotInitialized) + } + + pub(crate) fn with_debug_cache R>(&self, callback: F) -> R { + let mut inner = self.inner.lock(); + callback(&mut inner.debug_cache) } //////////////////////////////////////////////////////////////// diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 66e93a38..f56bad09 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -852,7 +852,9 @@ impl VeilidAPI { Ok("Connections purged".to_owned()) } else if args[0] == "routes" { // Purge route spec store - self.inner.lock().debug_cache.imported_routes.clear(); + self.with_debug_cache(|dc| { + dc.imported_routes.clear(); + }); let rss = self.network_manager()?.routing_table().route_spec_store(); match rss.purge().await { Ok(_) => Ok("Routes purged".to_owned()), @@ -1183,14 +1185,14 @@ impl VeilidAPI { let out = match rss.release_route(route_id) { true => { // release imported - let mut inner = self.inner.lock(); - let dc = &mut inner.debug_cache; - for (n, ir) in dc.imported_routes.iter().enumerate() { - if *ir == route_id { - dc.imported_routes.remove(n); - break; + self.with_debug_cache(|dc| { + for (n, ir) in dc.imported_routes.iter().enumerate() { + if *ir == route_id { + dc.imported_routes.remove(n); + break; + } } - } + }); "Released".to_owned() } false => "Route does not exist".to_owned(), @@ -1326,11 +1328,12 @@ impl VeilidAPI { .import_remote_private_route_blob(blob_dec) .map_err(VeilidAPIError::generic)?; - let mut inner = self.inner.lock(); - let dc = &mut inner.debug_cache; - let n = dc.imported_routes.len(); - let out = format!("Private route #{} imported: {}", n, route_id); - dc.imported_routes.push(route_id); + let out = self.with_debug_cache(|dc| { + let n = dc.imported_routes.len(); + let out = format!("Private route #{} imported: {}", n, route_id); + dc.imported_routes.push(route_id); + out + }); Ok(out) } @@ -1484,9 +1487,9 @@ impl VeilidAPI { }; // Save routing context for record - let mut inner = self.inner.lock(); - let dc = &mut inner.debug_cache; - dc.opened_record_contexts.insert(*record.key(), rc); + self.with_debug_cache(|dc| { + dc.opened_record_contexts.insert(*record.key(), rc); + }); Ok(format!( "Created: {} {}:{}\n{:?}", @@ -1529,9 +1532,9 @@ impl VeilidAPI { }; // Save routing context for record - let mut inner = self.inner.lock(); - let dc = &mut inner.debug_cache; - dc.opened_record_contexts.insert(*record.key(), rc); + self.with_debug_cache(|dc| { + dc.opened_record_contexts.insert(*record.key(), rc); + }); Ok(format!("Opened: {} : {:?}", key, record)) } @@ -2213,13 +2216,14 @@ TableDB Operations: // Private route let text = &text[1..]; - let private_route = - if let Some(prid) = get_route_id(rss.clone(), false, true)(text) { - rss.best_remote_private_route(&prid)? - } else { - let mut inner = self.inner.lock(); - let dc = &mut inner.debug_cache; - let n = get_number(text)?; + let private_route = if let Some(prid) = + get_route_id(rss.clone(), false, true)(text) + { + rss.best_remote_private_route(&prid)? + } else { + let n = get_number(text)?; + + self.with_debug_cache(|dc| { let prid = *dc.imported_routes.get(n)?; let Some(private_route) = rss.best_remote_private_route(&prid) else { // Remove imported route @@ -2227,8 +2231,9 @@ TableDB Operations: info!("removed dead imported route {}", n); return None; }; - private_route - }; + Some(private_route) + })? + }; Some(Destination::private_route( private_route, @@ -2273,14 +2278,11 @@ TableDB Operations: key: &str, arg: usize, ) -> VeilidAPIResult<(TypedKey, RoutingContext)> { - let mut inner = self.inner.lock(); - let dc = &mut inner.debug_cache; - let key = match get_debug_argument_at(args, arg, context, key, get_dht_key_no_safety) .ok() .or_else(|| { // If unspecified, use the most recent key opened or created - dc.opened_record_contexts.back().map(|kv| kv.0).copied() + self.with_debug_cache(|dc| dc.opened_record_contexts.back().map(|kv| kv.0).copied()) }) { Some(k) => k, None => { @@ -2289,7 +2291,9 @@ TableDB Operations: }; // Get routing context for record - let Some(rc) = dc.opened_record_contexts.get(&key).cloned() else { + + let Some(rc) = self.with_debug_cache(|dc| dc.opened_record_contexts.get(&key).cloned()) + else { apibail_missing_argument!("key is not opened", "key"); }; diff --git a/veilid-core/src/veilid_api/types/veilid_state.rs b/veilid-core/src/veilid_api/types/veilid_state.rs index 19d992d6..ff6afa01 100644 --- a/veilid-core/src/veilid_api/types/veilid_state.rs +++ b/veilid-core/src/veilid_api/types/veilid_state.rs @@ -98,7 +98,10 @@ pub struct VeilidStateAttachment { pub struct PeerTableData { /// The node ids used by this peer #[schemars(with = "Vec")] - #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), tsify(type = "string[]"))] + #[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + tsify(type = "string[]") + )] pub node_ids: Vec, /// The peer's human readable address. pub peer_address: String, @@ -167,7 +170,11 @@ pub struct VeilidValueChange { /// An update from the veilid-core to the host application describing a change /// to the internal state of the Veilid node. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify), tsify(into_wasm_abi))] +#[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + derive(Tsify), + tsify(into_wasm_abi) +)] #[serde(tag = "kind")] pub enum VeilidUpdate { Log(Box), @@ -184,7 +191,11 @@ from_impl_to_jsvalue!(VeilidUpdate); /// A queriable state of the internals of veilid-core. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify), tsify(into_wasm_abi))] +#[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + derive(Tsify), + tsify(into_wasm_abi) +)] pub struct VeilidState { pub attachment: Box, pub network: Box, diff --git a/veilid-tools/src/network_result.rs b/veilid-tools/src/network_result.rs index 1a922520..f2a5c654 100644 --- a/veilid-tools/src/network_result.rs +++ b/veilid-tools/src/network_result.rs @@ -53,21 +53,6 @@ impl IoNetworkResultExt for io::Result { fn into_network_result(self) -> io::Result> { match self { Ok(v) => Ok(NetworkResult::Value(v)), - // #[cfg(feature = "io_error_more")] - // Err(e) => match e.kind() { - // io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout), - // io::ErrorKind::UnexpectedEof - // | io::ErrorKind::NotConnected - // | io::ErrorKind::BrokenPipe - // | io::ErrorKind::ConnectionAborted - // | io::ErrorKind::ConnectionRefused - // | io::ErrorKind::ConnectionReset - // | io::ErrorKind::HostUnreachable - // | io::ErrorKind::NetworkUnreachable => Ok(NetworkResult::NoConnection(e)), - // io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)), - // _ => Err(e), - // }, - // #[cfg(not(feature = "io_error_more"))] Err(e) => io_error_kind_from_error(e), } } @@ -100,18 +85,6 @@ impl FoldedNetworkResultExt for io::Result> { match self { Ok(TimeoutOr::Timeout) => Ok(NetworkResult::Timeout), Ok(TimeoutOr::Value(v)) => Ok(NetworkResult::Value(v)), - // #[cfg(feature = "io_error_more")] - // Err(e) => match e.kind() { - // io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout), - // io::ErrorKind::ConnectionAborted - // | io::ErrorKind::ConnectionRefused - // | io::ErrorKind::ConnectionReset - // | io::ErrorKind::HostUnreachable - // | io::ErrorKind::NetworkUnreachable => Ok(NetworkResult::NoConnection(e)), - // io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)), - // _ => Err(e), - // }, - // #[cfg(not(feature = "io_error_more"))] Err(e) => io_error_kind_from_error(e), } } @@ -121,18 +94,6 @@ impl FoldedNetworkResultExt for io::Result> { fn folded(self) -> io::Result> { match self { Ok(v) => Ok(v), - // #[cfg(feature = "io_error_more")] - // Err(e) => match e.kind() { - // io::ErrorKind::TimedOut => Ok(NetworkResult::Timeout), - // io::ErrorKind::ConnectionAborted - // | io::ErrorKind::ConnectionRefused - // | io::ErrorKind::ConnectionReset - // | io::ErrorKind::HostUnreachable - // | io::ErrorKind::NetworkUnreachable => Ok(NetworkResult::NoConnection(e)), - // io::ErrorKind::AddrNotAvailable => Ok(NetworkResult::AlreadyExists(e)), - // _ => Err(e), - // }, - // #[cfg(not(feature = "io_error_more"))] Err(e) => io_error_kind_from_error(e), } } diff --git a/veilid-tools/src/static_string_table.rs b/veilid-tools/src/static_string_table.rs index 462c4d64..796187a5 100644 --- a/veilid-tools/src/static_string_table.rs +++ b/veilid-tools/src/static_string_table.rs @@ -3,6 +3,9 @@ use super::*; static STRING_TABLE: std::sync::LazyLock>> = std::sync::LazyLock::new(|| Mutex::new(BTreeSet::new())); +static STRING_TRANSFORM_TABLE: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); + pub trait ToStaticStr { fn to_static_str(&self) -> &'static str; } @@ -19,3 +22,26 @@ impl> ToStaticStr for T { ss } } + +pub trait StaticStrTransform { + fn static_transform &'static str>( + self, + transform: F, + ) -> &'static str; +} + +impl StaticStrTransform for &'static str { + fn static_transform &'static str>( + self, + transform: F, + ) -> &'static str { + let key = self.as_ptr() as usize; + let mut transform_table = STRING_TRANSFORM_TABLE.lock(); + if let Some(v) = transform_table.get(&key) { + return v; + } + let out = transform(self); + transform_table.insert(key, out); + out + } +}