Skip to content

Commit

Permalink
Implement iox2 services details
Browse files Browse the repository at this point in the history
  • Loading branch information
orecham committed Sep 12, 2024
1 parent dc44a3a commit 638cc72
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ ouroboros = { version = "0.18.4" }
proc-macro2 = { version = "1.0.84" }
quote = { version = "1.0.36" }
serde = { version = "1.0.203", features = ["derive"] }
serde_yaml = { version = "0.9.34" }
serde_test = { version = "1.0.176" }
sha1_smol = { version = "1.0.0" }
syn = { version = "2.0.66", features = ["full"] }
Expand Down
3 changes: 3 additions & 0 deletions iceoryx2-cli/iox2-services/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ anyhow = { workspace = true }
better-panic = { workspace = true }
clap = { workspace = true }
human-panic = { workspace = true }
toml = { workspace = true }
serde = { workspace = true }
serde_yaml = { workspace = true }
27 changes: 26 additions & 1 deletion iceoryx2-cli/iox2-services/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,33 @@ pub struct Cli {
pub action: Option<Action>,
}

#[derive(Parser)]
pub struct DetailsOptions {
#[clap(long = "static", short = 's')]
pub static_flag: bool,
#[clap(long, short = 'd')]
pub dynamic: bool,
pub service: String,
}

pub enum DetailsFilter {
None,
Static,
Dynamic,
}

impl From<&DetailsOptions> for DetailsFilter {
fn from(options: &DetailsOptions) -> Self {
match (options.static_flag, options.dynamic) {
(true, false) => DetailsFilter::Static,
(false, true) => DetailsFilter::Dynamic,
_ => DetailsFilter::None,
}
}
}

#[derive(Subcommand)]
pub enum Action {
List,
Info { service: String },
Details(DetailsOptions),
}
41 changes: 40 additions & 1 deletion iceoryx2-cli/iox2-services/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,52 @@
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use anyhow::{Error, Result};
use anyhow::{anyhow, Error, Result};
use iceoryx2::prelude::*;

use crate::cli::DetailsFilter;

pub fn list() -> Result<()> {
ipc::Service::list(Config::global_config(), |service| {
println!("- {}", &service.static_details.name().as_str());
CallbackProgression::Continue
})
.map_err(Error::new)
}

pub fn details(name: &str, filter: DetailsFilter) -> Result<()> {
let service_name: ServiceName = name.try_into()?;
let mut error: Option<Error> = None;

ipc::Service::list(Config::global_config(), |service| {
if service_name == *service.static_details.name() {
match filter {
DetailsFilter::None => match serde_yaml::to_string(&service.to_serializable()) {
Ok(details_string) => print!("{}", details_string),
Err(e) => error = Some(anyhow!(e)),
},
DetailsFilter::Static => match serde_yaml::to_string(&service.static_details) {
Ok(details_string) => print!("{}", details_string),
Err(e) => error = Some(anyhow!(e)),
},
DetailsFilter::Dynamic => {
if let Some(dynamic_details) = &service.dynamic_details {
match serde_yaml::to_string(&dynamic_details.to_serializable()) {
Ok(details_string) => print!("{}", details_string),
Err(e) => error = Some(anyhow!(e)),
}
}
}
}
CallbackProgression::Stop
} else {
CallbackProgression::Continue
}
})
.map_err(Error::new)?;

if let Some(err) = error {
return Err(err);
}
Ok(())
}
8 changes: 6 additions & 2 deletions iceoryx2-cli/iox2-services/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod cli;
mod commands;

use cli::Action;
use cli::DetailsFilter;
use iceoryx2_bb_log::{set_log_level, LogLevel};

fn main() {
Expand Down Expand Up @@ -49,8 +50,11 @@ fn main() {
eprintln!("Failed to list services: {}", e);
}
}
Action::Info { service } => {
println!("Getting information for service: {}", service);
Action::Details(options) => {
let filter = DetailsFilter::from(&options);
if let Err(e) = commands::details(options.service.as_str(), filter) {
eprintln!("Failed to get service details: {}", e);
}
}
},
None => {
Expand Down
55 changes: 55 additions & 0 deletions iceoryx2/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,28 @@ impl<Service: service::Service> NodeState<Service> {
}
}

#[allow(missing_docs)]
impl<Service: service::Service> NodeState<Service> {
pub fn to_serializable(&self) -> SerializableNodeState {
match self {
NodeState::Alive(view) => SerializableNodeState::Alive(view.to_serializable()),
NodeState::Dead(view) => SerializableNodeState::Dead(view.to_serializable()),
NodeState::Inaccessible(id) => SerializableNodeState::Inaccessible(id.clone()),
NodeState::Undefined(id) => SerializableNodeState::Undefined(id.clone()),
}
}
}

#[allow(missing_docs)]
#[derive(serde::Serialize)]
#[serde(tag = "state")]
pub enum SerializableNodeState {
Alive(SerializableAliveNodeView),
Dead(SerializableDeadNodeView),
Inaccessible(NodeId),
Undefined(NodeId),
}

/// Returned by [`Node::cleanup_dead_nodes()`]. Contains the cleanup report of the call
/// and contains the number of dead nodes that were successfully cleaned up and how many
/// could not be cleaned up.
Expand Down Expand Up @@ -393,6 +415,14 @@ pub struct AliveNodeView<Service: service::Service> {
_service: PhantomData<Service>,
}

#[allow(missing_docs)]
#[derive(serde::Serialize)]
pub struct SerializableAliveNodeView {
id: NodeId,
#[serde(rename = "node_details")]
details: Option<NodeDetails>,
}

impl<Service: service::Service> Clone for AliveNodeView<Service> {
fn clone(&self) -> Self {
Self {
Expand All @@ -413,10 +443,27 @@ impl<Service: service::Service> NodeView for AliveNodeView<Service> {
}
}

#[allow(missing_docs)]
impl<Service: service::Service> AliveNodeView<Service> {
pub fn to_serializable(&self) -> SerializableAliveNodeView {
SerializableAliveNodeView {
id: self.id().clone(),
details: self.details().clone(),
}
}
}

/// All the informations and management operations belonging to a dead [`Node`].
#[derive(Debug)]
pub struct DeadNodeView<Service: service::Service>(AliveNodeView<Service>);

#[allow(missing_docs)]
#[derive(serde::Serialize)]
pub struct SerializableDeadNodeView {
id: NodeId,
details: Option<NodeDetails>,
}

impl<Service: service::Service> Clone for DeadNodeView<Service> {
fn clone(&self) -> Self {
Self(self.0.clone())
Expand Down Expand Up @@ -529,6 +576,14 @@ impl<Service: service::Service> DeadNodeView<Service> {
}
}
}

#[allow(missing_docs)]
pub fn to_serializable(&self) -> SerializableDeadNodeView {
SerializableDeadNodeView {
id: self.id().clone(),
details: self.details().clone(),
}
}
}

fn acquire_all_node_detail_storages<Service: service::Service>(
Expand Down
40 changes: 39 additions & 1 deletion iceoryx2/src/service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ use std::sync::Arc;
use std::time::Duration;

use crate::config;
use crate::node::{NodeId, NodeListFailure, NodeState, SharedNode};
use crate::node::{NodeId, NodeListFailure, NodeState, SerializableNodeState, SharedNode};
use crate::service::config_scheme::dynamic_config_storage_config;
use crate::service::dynamic_config::DynamicConfig;
use crate::service::static_config::*;
Expand Down Expand Up @@ -262,6 +262,27 @@ pub struct ServiceDynamicDetails<S: Service> {
pub nodes: Vec<NodeState<S>>,
}

#[allow(missing_docs)]
#[derive(serde::Serialize)]
pub struct SerializableServiceDynamicDetails {
num_nodes: usize,
nodes: Vec<SerializableNodeState>,
}

#[allow(missing_docs)]
impl<S: Service> ServiceDynamicDetails<S> {
pub fn to_serializable(&self) -> SerializableServiceDynamicDetails {
SerializableServiceDynamicDetails {
num_nodes: self.nodes.len(),
nodes: self
.nodes
.iter()
.map(|node| node.to_serializable())
.collect(),
}
}
}

/// Represents all the [`Service`] information that one can acquire with [`Service::list()`].
#[derive(Debug)]
pub struct ServiceDetails<S: Service> {
Expand All @@ -272,6 +293,23 @@ pub struct ServiceDetails<S: Service> {
pub dynamic_details: Option<ServiceDynamicDetails<S>>,
}

#[allow(missing_docs)]
#[derive(serde::Serialize)]
pub struct SerializableServiceDetails {
pub static_details: StaticConfig,
pub dynamic_details: Option<SerializableServiceDynamicDetails>,
}

#[allow(missing_docs)]
impl<S: Service> ServiceDetails<S> {
pub fn to_serializable(&self) -> SerializableServiceDetails {
SerializableServiceDetails {
static_details: self.static_details.clone(),
dynamic_details: self.dynamic_details.as_ref().map(|dd| dd.to_serializable()),
}
}
}

/// Represents the [`Service`]s state.
#[derive(Debug)]
pub struct ServiceState<S: Service> {
Expand Down

0 comments on commit 638cc72

Please sign in to comment.