From 1eb86298bd87f534f047395f4f9cb8bcc25b2a1e Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Mon, 11 Mar 2024 11:16:13 +0100 Subject: [PATCH 01/30] Router implements interests protocol for clients --- zenoh/src/net/routing/dispatcher/face.rs | 79 +++++- zenoh/src/net/routing/dispatcher/pubsub.rs | 85 ++++++- zenoh/src/net/routing/dispatcher/queries.rs | 84 +++++++ zenoh/src/net/routing/dispatcher/resource.rs | 161 +++++++++--- zenoh/src/net/routing/hat/client/pubsub.rs | 42 ++-- zenoh/src/net/routing/hat/client/queries.rs | 43 ++-- .../net/routing/hat/linkstate_peer/pubsub.rs | 42 ++-- .../net/routing/hat/linkstate_peer/queries.rs | 41 ++- zenoh/src/net/routing/hat/mod.rs | 38 ++- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 42 ++-- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 43 ++-- zenoh/src/net/routing/hat/router/mod.rs | 6 +- zenoh/src/net/routing/hat/router/pubsub.rs | 235 ++++++++++++++---- zenoh/src/net/routing/hat/router/queries.rs | 181 +++++++++++--- 14 files changed, 901 insertions(+), 221 deletions(-) diff --git a/zenoh/src/net/routing/dispatcher/face.rs b/zenoh/src/net/routing/dispatcher/face.rs index 79c9da9127..63b250a287 100644 --- a/zenoh/src/net/routing/dispatcher/face.rs +++ b/zenoh/src/net/routing/dispatcher/face.rs @@ -16,11 +16,14 @@ use super::tables::TablesLock; use super::{resource::*, tables}; use crate::net::primitives::{McastMux, Mux, Primitives}; use crate::net::routing::interceptor::{InterceptorTrait, InterceptorsChain}; +use crate::net::routing::RoutingContext; use crate::KeyExpr; use std::any::Any; use std::collections::HashMap; use std::fmt; use std::sync::Arc; +use zenoh_protocol::network::declare::{FinalInterest, InterestId}; +use zenoh_protocol::network::{ext, Declare, DeclareBody}; use zenoh_protocol::zenoh::RequestBody; use zenoh_protocol::{ core::{ExprId, WhatAmI, ZenohId}, @@ -38,6 +41,7 @@ pub struct FaceState { #[cfg(feature = "stats")] pub(crate) stats: Option>, pub(crate) primitives: Arc, + pub(crate) remote_key_interests: HashMap>>, pub(crate) local_mappings: HashMap>, pub(crate) remote_mappings: HashMap>, pub(crate) next_qid: RequestId, @@ -66,6 +70,7 @@ impl FaceState { #[cfg(feature = "stats")] stats, primitives, + remote_key_interests: HashMap::new(), local_mappings: HashMap::new(), remote_mappings: HashMap::new(), next_qid: 0, @@ -208,11 +213,75 @@ impl Primitives for Face { msg.ext_nodeid.node_id, ); } - zenoh_protocol::network::DeclareBody::DeclareToken(_m) => todo!(), - zenoh_protocol::network::DeclareBody::UndeclareToken(_m) => todo!(), - zenoh_protocol::network::DeclareBody::DeclareInterest(_m) => todo!(), - zenoh_protocol::network::DeclareBody::FinalInterest(_m) => todo!(), - zenoh_protocol::network::DeclareBody::UndeclareInterest(_m) => todo!(), + zenoh_protocol::network::DeclareBody::DeclareToken(m) => { + log::warn!("Received unsupported {m:?}") + } + zenoh_protocol::network::DeclareBody::UndeclareToken(m) => { + log::warn!("Received unsupported {m:?}") + } + zenoh_protocol::network::DeclareBody::DeclareInterest(m) => { + if m.interest.keyexprs() && m.interest.future() { + register_expr_interest( + &self.tables, + &mut self.state.clone(), + m.id, + m.wire_expr.as_ref(), + ); + } + if m.interest.subscribers() { + declare_sub_interest( + ctrl_lock.as_ref(), + &self.tables, + &mut self.state.clone(), + m.id, + m.wire_expr.as_ref(), + m.interest.current(), + m.interest.future(), + m.interest.aggregate(), + ); + } + if m.interest.queryables() { + declare_qabl_interest( + ctrl_lock.as_ref(), + &self.tables, + &mut self.state.clone(), + m.id, + m.wire_expr.as_ref(), + m.interest.current(), + m.interest.future(), + m.interest.aggregate(), + ); + } + if m.interest.current() { + self.state.primitives.send_declare(RoutingContext::new_out( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::FinalInterest(FinalInterest { id: m.id }), + }, + self.clone(), + )); + } + } + zenoh_protocol::network::DeclareBody::FinalInterest(m) => { + log::warn!("Received unsupported {m:?}") + } + zenoh_protocol::network::DeclareBody::UndeclareInterest(m) => { + unregister_expr_interest(&self.tables, &mut self.state.clone(), m.id); + undeclare_sub_interest( + ctrl_lock.as_ref(), + &self.tables, + &mut self.state.clone(), + m.id, + ); + undeclare_qabl_interest( + ctrl_lock.as_ref(), + &self.tables, + &mut self.state.clone(), + m.id, + ); + } } drop(ctrl_lock); } diff --git a/zenoh/src/net/routing/dispatcher/pubsub.rs b/zenoh/src/net/routing/dispatcher/pubsub.rs index c0d1bb4a34..4a6a350ee2 100644 --- a/zenoh/src/net/routing/dispatcher/pubsub.rs +++ b/zenoh/src/net/routing/dispatcher/pubsub.rs @@ -22,7 +22,7 @@ use std::sync::RwLock; use zenoh_core::zread; use zenoh_protocol::core::key_expr::{keyexpr, OwnedKeyExpr}; use zenoh_protocol::network::declare::subscriber::ext::SubscriberInfo; -use zenoh_protocol::network::declare::{Mode, SubscriberId}; +use zenoh_protocol::network::declare::{InterestId, Mode, SubscriberId}; use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::{declare::ext, Push}, @@ -30,6 +30,89 @@ use zenoh_protocol::{ }; use zenoh_sync::get_mut_unchecked; +#[allow(clippy::too_many_arguments)] // TODO refactor +pub(crate) fn declare_sub_interest( + hat_code: &(dyn HatTrait + Send + Sync), + tables: &TablesLock, + face: &mut Arc, + id: InterestId, + expr: Option<&WireExpr>, + current: bool, + future: bool, + aggregate: bool, +) { + if let Some(expr) = expr { + let rtables = zread!(tables.tables); + match rtables + .get_mapping(face, &expr.scope, expr.mapping) + .cloned() + { + Some(mut prefix) => { + log::debug!( + "{} Declare sub interest {} ({}{})", + face, + id, + prefix.expr(), + expr.suffix + ); + let res = Resource::get_resource(&prefix, &expr.suffix); + let (mut res, mut wtables) = if res + .as_ref() + .map(|r| r.context.is_some()) + .unwrap_or(false) + { + drop(rtables); + let wtables = zwrite!(tables.tables); + (res.unwrap(), wtables) + } else { + let mut fullexpr = prefix.expr(); + fullexpr.push_str(expr.suffix.as_ref()); + let mut matches = keyexpr::new(fullexpr.as_str()) + .map(|ke| Resource::get_matches(&rtables, ke)) + .unwrap_or_default(); + drop(rtables); + let mut wtables = zwrite!(tables.tables); + let mut res = + Resource::make_resource(&mut wtables, &mut prefix, expr.suffix.as_ref()); + matches.push(Arc::downgrade(&res)); + Resource::match_resource(&wtables, &mut res, matches); + (res, wtables) + }; + + hat_code.declare_sub_interest( + &mut wtables, + face, + id, + Some(&mut res), + current, + future, + aggregate, + ); + } + None => log::error!( + "{} Declare sub interest {} for unknown scope {}!", + face, + id, + expr.scope + ), + } + } else { + let mut wtables = zwrite!(tables.tables); + hat_code.declare_sub_interest(&mut wtables, face, id, None, current, future, aggregate); + } +} + +pub(crate) fn undeclare_sub_interest( + hat_code: &(dyn HatTrait + Send + Sync), + tables: &TablesLock, + face: &mut Arc, + id: InterestId, +) { + log::debug!("{} Undeclare sub interest {}", face, id,); + let mut wtables = zwrite!(tables.tables); + hat_code.undeclare_sub_interest(&mut wtables, face, id); +} + pub(crate) fn declare_subscription( hat_code: &(dyn HatTrait + Send + Sync), tables: &TablesLock, diff --git a/zenoh/src/net/routing/dispatcher/queries.rs b/zenoh/src/net/routing/dispatcher/queries.rs index 287621151a..009859a0a9 100644 --- a/zenoh/src/net/routing/dispatcher/queries.rs +++ b/zenoh/src/net/routing/dispatcher/queries.rs @@ -21,6 +21,7 @@ use async_trait::async_trait; use std::collections::HashMap; use std::sync::{Arc, Weak}; use zenoh_config::WhatAmI; +use zenoh_protocol::network::declare::InterestId; use zenoh_protocol::{ core::{key_expr::keyexpr, Encoding, WireExpr}, network::{ @@ -33,6 +34,89 @@ use zenoh_protocol::{ use zenoh_sync::get_mut_unchecked; use zenoh_util::Timed; +#[allow(clippy::too_many_arguments)] // TODO refactor +pub(crate) fn declare_qabl_interest( + hat_code: &(dyn HatTrait + Send + Sync), + tables: &TablesLock, + face: &mut Arc, + id: InterestId, + expr: Option<&WireExpr>, + current: bool, + future: bool, + aggregate: bool, +) { + if let Some(expr) = expr { + let rtables = zread!(tables.tables); + match rtables + .get_mapping(face, &expr.scope, expr.mapping) + .cloned() + { + Some(mut prefix) => { + log::debug!( + "{} Declare qabl interest {} ({}{})", + face, + id, + prefix.expr(), + expr.suffix + ); + let res = Resource::get_resource(&prefix, &expr.suffix); + let (mut res, mut wtables) = if res + .as_ref() + .map(|r| r.context.is_some()) + .unwrap_or(false) + { + drop(rtables); + let wtables = zwrite!(tables.tables); + (res.unwrap(), wtables) + } else { + let mut fullexpr = prefix.expr(); + fullexpr.push_str(expr.suffix.as_ref()); + let mut matches = keyexpr::new(fullexpr.as_str()) + .map(|ke| Resource::get_matches(&rtables, ke)) + .unwrap_or_default(); + drop(rtables); + let mut wtables = zwrite!(tables.tables); + let mut res = + Resource::make_resource(&mut wtables, &mut prefix, expr.suffix.as_ref()); + matches.push(Arc::downgrade(&res)); + Resource::match_resource(&wtables, &mut res, matches); + (res, wtables) + }; + + hat_code.declare_qabl_interest( + &mut wtables, + face, + id, + Some(&mut res), + current, + future, + aggregate, + ); + } + None => log::error!( + "{} Declare qabl interest {} for unknown scope {}!", + face, + id, + expr.scope + ), + } + } else { + let mut wtables = zwrite!(tables.tables); + hat_code.declare_qabl_interest(&mut wtables, face, id, None, current, future, aggregate); + } +} + +pub(crate) fn undeclare_qabl_interest( + hat_code: &(dyn HatTrait + Send + Sync), + tables: &TablesLock, + face: &mut Arc, + id: InterestId, +) { + log::debug!("{} Undeclare qabl interest {}", face, id,); + let mut wtables = zwrite!(tables.tables); + hat_code.undeclare_qabl_interest(&mut wtables, face, id); +} + pub(crate) struct Query { src_face: Arc, src_qid: RequestId, diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index 9f43841025..06da9294a0 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -21,6 +21,7 @@ use std::convert::TryInto; use std::hash::{Hash, Hasher}; use std::sync::{Arc, Weak}; use zenoh_config::WhatAmI; +use zenoh_protocol::network::declare::InterestId; #[cfg(feature = "complete_n")] use zenoh_protocol::network::request::ext::TargetType; use zenoh_protocol::network::RequestId; @@ -64,6 +65,21 @@ pub(crate) struct SessionContext { pub(crate) e_interceptor_cache: Option>, } +impl SessionContext { + pub(crate) fn new(face: Arc) -> Self { + Self { + face, + local_expr_id: None, + remote_expr_id: None, + subs: None, + qabl: None, + last_values: HashMap::new(), + in_interceptor_cache: None, + e_interceptor_cache: None, + } + } +} + #[derive(Default)] pub(crate) struct RoutesIndexes { pub(crate) routers: Vec, @@ -231,6 +247,16 @@ impl Resource { self.context.as_mut().unwrap() } + #[inline(always)] + pub(crate) fn matches(&self, other: &Arc) -> bool { + self.context + .as_ref() + .unwrap() + .matches + .iter() + .any(|m| m.upgrade().is_some_and(|m| &m == other)) + } + pub fn nonwild_prefix(res: &Arc) -> (Option>, String) { match &res.nonwild_prefix { None => (Some(res.clone()), "".to_string()), @@ -435,35 +461,34 @@ impl Resource { let (nonwild_prefix, wildsuffix) = Resource::nonwild_prefix(res); match nonwild_prefix { Some(mut nonwild_prefix) => { - let ctx = get_mut_unchecked(&mut nonwild_prefix) + if let Some(ctx) = get_mut_unchecked(&mut nonwild_prefix) .session_ctxs - .entry(face.id) - .or_insert_with(|| { - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: None, - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }) - }); - - if let Some(expr_id) = ctx.remote_expr_id { - WireExpr { - scope: expr_id, - suffix: wildsuffix.into(), - mapping: Mapping::Receiver, + .get(&face.id) + { + if let Some(expr_id) = ctx.remote_expr_id { + return WireExpr { + scope: expr_id, + suffix: wildsuffix.into(), + mapping: Mapping::Receiver, + }; } - } else if let Some(expr_id) = ctx.local_expr_id { - WireExpr { - scope: expr_id, - suffix: wildsuffix.into(), - mapping: Mapping::Sender, + if let Some(expr_id) = ctx.local_expr_id { + return WireExpr { + scope: expr_id, + suffix: wildsuffix.into(), + mapping: Mapping::Sender, + }; } - } else { + } + if face.remote_key_interests.values().any(|res| { + res.as_ref() + .map(|res| res.matches(&nonwild_prefix)) + .unwrap_or(true) + }) { + let ctx = get_mut_unchecked(&mut nonwild_prefix) + .session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))); let expr_id = face.get_next_local_id(); get_mut_unchecked(ctx).local_expr_id = Some(expr_id); get_mut_unchecked(face) @@ -487,6 +512,8 @@ impl Resource { suffix: wildsuffix.into(), mapping: Mapping::Sender, } + } else { + wildsuffix.into() } } None => wildsuffix.into(), @@ -651,7 +678,7 @@ impl Resource { } } -pub fn register_expr( +pub(crate) fn register_expr( tables: &TablesLock, face: &mut Arc, expr_id: ExprId, @@ -698,21 +725,12 @@ pub fn register_expr( Resource::match_resource(&wtables, &mut res, matches); (res, wtables) }; - get_mut_unchecked(&mut res) + let ctx = get_mut_unchecked(&mut res) .session_ctxs .entry(face.id) - .or_insert_with(|| { - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: Some(expr_id), - subs: None, - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }) - }); + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))); + + get_mut_unchecked(ctx).remote_expr_id = Some(expr_id); get_mut_unchecked(face) .remote_mappings @@ -730,7 +748,7 @@ pub fn register_expr( } } -pub fn unregister_expr(tables: &TablesLock, face: &mut Arc, expr_id: ExprId) { +pub(crate) fn unregister_expr(tables: &TablesLock, face: &mut Arc, expr_id: ExprId) { let wtables = zwrite!(tables.tables); match get_mut_unchecked(face).remote_mappings.remove(&expr_id) { Some(mut res) => Resource::clean(&mut res), @@ -738,3 +756,64 @@ pub fn unregister_expr(tables: &TablesLock, face: &mut Arc, expr_id: } drop(wtables); } + +pub(crate) fn register_expr_interest( + tables: &TablesLock, + face: &mut Arc, + id: InterestId, + expr: Option<&WireExpr>, +) { + if let Some(expr) = expr { + let rtables = zread!(tables.tables); + match rtables + .get_mapping(face, &expr.scope, expr.mapping) + .cloned() + { + Some(mut prefix) => { + let res = Resource::get_resource(&prefix, &expr.suffix); + let (res, wtables) = if res.as_ref().map(|r| r.context.is_some()).unwrap_or(false) { + drop(rtables); + let wtables = zwrite!(tables.tables); + (res.unwrap(), wtables) + } else { + let mut fullexpr = prefix.expr(); + fullexpr.push_str(expr.suffix.as_ref()); + let mut matches = keyexpr::new(fullexpr.as_str()) + .map(|ke| Resource::get_matches(&rtables, ke)) + .unwrap_or_default(); + drop(rtables); + let mut wtables = zwrite!(tables.tables); + let mut res = + Resource::make_resource(&mut wtables, &mut prefix, expr.suffix.as_ref()); + matches.push(Arc::downgrade(&res)); + Resource::match_resource(&wtables, &mut res, matches); + (res, wtables) + }; + get_mut_unchecked(face) + .remote_key_interests + .insert(id, Some(res)); + drop(wtables); + } + None => log::error!( + "Declare keyexpr interest with unknown scope {}!", + expr.scope + ), + } + } else { + let wtables = zwrite!(tables.tables); + get_mut_unchecked(face) + .remote_key_interests + .insert(id, None); + drop(wtables); + } +} + +pub(crate) fn unregister_expr_interest( + tables: &TablesLock, + face: &mut Arc, + id: InterestId, +) { + let wtables = zwrite!(tables.tables); + get_mut_unchecked(face).remote_key_interests.remove(&id); + drop(wtables); +} diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index f9f827ecc5..91ad87522c 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -25,7 +25,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::SubscriberId; +use zenoh_protocol::network::declare::{InterestId, SubscriberId}; use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ @@ -105,19 +105,11 @@ fn register_client_subscription( } }, None => { - res.session_ctxs.insert( - face.id, - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: Some(*sub_info), - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }), - ); + let ctx = res + .session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))); + get_mut_unchecked(ctx).subs = Some(*sub_info); } } } @@ -258,6 +250,28 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { } impl HatPubSubTrait for HatCode { + fn declare_sub_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + _res: Option<&mut Arc>, + _current: bool, + _future: bool, + _aggregate: bool, + ) { + todo!() + } + + fn undeclare_sub_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + ) { + todo!() + } + fn declare_subscription( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index 4964a8880a..af89cdeb66 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -22,13 +22,13 @@ use crate::net::routing::router::RoutesIndexes; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; use ordered_float::OrderedFloat; use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_buffers::ZBuf; use zenoh_protocol::core::key_expr::include::{Includer, DEFAULT_INCLUDER}; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::QueryableId; +use zenoh_protocol::network::declare::{InterestId, QueryableId}; use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::declare::{ @@ -126,18 +126,11 @@ fn register_client_queryable( // Register queryable { let res = get_mut_unchecked(res); - get_mut_unchecked(res.session_ctxs.entry(face.id).or_insert_with(|| { - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: None, - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }) - })) + get_mut_unchecked( + res.session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))), + ) .qabl = Some(*qabl_info); } face_hat_mut!(face).remote_qabls.insert(id, res.clone()); @@ -258,6 +251,28 @@ lazy_static::lazy_static! { } impl HatQueriesTrait for HatCode { + fn declare_qabl_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + _res: Option<&mut Arc>, + _current: bool, + _future: bool, + _aggregate: bool, + ) { + todo!() + } + + fn undeclare_qabl_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + ) { + todo!() + } + fn declare_queryable( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index 9a41915333..4b76e55387 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -28,7 +28,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::SubscriberId; +use zenoh_protocol::network::declare::{InterestId, SubscriberId}; use zenoh_protocol::{ core::{Reliability, WhatAmI, ZenohId}, network::declare::{ @@ -218,19 +218,11 @@ fn register_client_subscription( } }, None => { - res.session_ctxs.insert( - face.id, - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: Some(*sub_info), - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }), - ); + let ctx = res + .session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))); + get_mut_unchecked(ctx).subs = Some(*sub_info); } } } @@ -567,6 +559,28 @@ fn insert_faces_for_subs( } impl HatPubSubTrait for HatCode { + fn declare_sub_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + _res: Option<&mut Arc>, + _current: bool, + _future: bool, + _aggregate: bool, + ) { + todo!() + } + + fn undeclare_sub_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + ) { + todo!() + } + fn declare_subscription( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index 51aac2175a..d7f42120f0 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -31,7 +31,7 @@ use std::sync::Arc; use zenoh_buffers::ZBuf; use zenoh_protocol::core::key_expr::include::{Includer, DEFAULT_INCLUDER}; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::QueryableId; +use zenoh_protocol::network::declare::{InterestId, QueryableId}; use zenoh_protocol::{ core::{WhatAmI, WireExpr, ZenohId}, network::declare::{ @@ -278,18 +278,11 @@ fn register_client_queryable( // Register queryable { let res = get_mut_unchecked(res); - get_mut_unchecked(res.session_ctxs.entry(face.id).or_insert_with(|| { - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: None, - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }) - })) + get_mut_unchecked( + res.session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))), + ) .qabl = Some(*qabl_info); } face_hat_mut!(face).remote_qabls.insert(id, res.clone()); @@ -640,6 +633,28 @@ lazy_static::lazy_static! { } impl HatQueriesTrait for HatCode { + fn declare_qabl_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + _res: Option<&mut Arc>, + _current: bool, + _future: bool, + _aggregate: bool, + ) { + todo!() + } + + fn undeclare_qabl_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + ) { + todo!() + } + fn declare_queryable( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/mod.rs b/zenoh/src/net/routing/hat/mod.rs index d9feb687f2..05410a6359 100644 --- a/zenoh/src/net/routing/hat/mod.rs +++ b/zenoh/src/net/routing/hat/mod.rs @@ -32,8 +32,8 @@ use zenoh_protocol::{ core::WireExpr, network::{ declare::{ - queryable::ext::QueryableInfo, subscriber::ext::SubscriberInfo, QueryableId, - SubscriberId, + queryable::ext::QueryableInfo, subscriber::ext::SubscriberInfo, InterestId, + QueryableId, SubscriberId, }, Oam, }, @@ -116,6 +116,23 @@ pub(crate) trait HatBaseTrait { } pub(crate) trait HatPubSubTrait { + #[allow(clippy::too_many_arguments)] // TODO refactor + fn declare_sub_interest( + &self, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, + ); + fn undeclare_sub_interest( + &self, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + ); fn declare_subscription( &self, tables: &mut Tables, @@ -148,6 +165,23 @@ pub(crate) trait HatPubSubTrait { } pub(crate) trait HatQueriesTrait { + #[allow(clippy::too_many_arguments)] // TODO refactor + fn declare_qabl_interest( + &self, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, + ); + fn undeclare_qabl_interest( + &self, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + ); fn declare_queryable( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 4f6ce5aeca..976466af12 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -25,7 +25,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::SubscriberId; +use zenoh_protocol::network::declare::{InterestId, SubscriberId}; use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ @@ -105,19 +105,11 @@ fn register_client_subscription( } }, None => { - res.session_ctxs.insert( - face.id, - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: Some(*sub_info), - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }), - ); + let ctx = res + .session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))); + get_mut_unchecked(ctx).subs = Some(*sub_info); } } } @@ -258,6 +250,28 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { } impl HatPubSubTrait for HatCode { + fn declare_sub_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + _res: Option<&mut Arc>, + _current: bool, + _future: bool, + _aggregate: bool, + ) { + todo!() + } + + fn undeclare_sub_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + ) { + todo!() + } + fn declare_subscription( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index 04b31b41ef..d8d0a3fcc0 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -22,13 +22,13 @@ use crate::net::routing::router::RoutesIndexes; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; use ordered_float::OrderedFloat; use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_buffers::ZBuf; use zenoh_protocol::core::key_expr::include::{Includer, DEFAULT_INCLUDER}; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::QueryableId; +use zenoh_protocol::network::declare::{InterestId, QueryableId}; use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::declare::{ @@ -126,18 +126,11 @@ fn register_client_queryable( // Register queryable { let res = get_mut_unchecked(res); - get_mut_unchecked(res.session_ctxs.entry(face.id).or_insert_with(|| { - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: None, - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }) - })) + get_mut_unchecked( + res.session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))), + ) .qabl = Some(*qabl_info); } face_hat_mut!(face).remote_qabls.insert(id, res.clone()); @@ -258,6 +251,28 @@ lazy_static::lazy_static! { } impl HatQueriesTrait for HatCode { + fn declare_qabl_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + _res: Option<&mut Arc>, + _current: bool, + _future: bool, + _aggregate: bool, + ) { + todo!() + } + + fn undeclare_qabl_interest( + &self, + _tables: &mut Tables, + _face: &mut Arc, + _id: InterestId, + ) { + todo!() + } + fn declare_queryable( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/router/mod.rs b/zenoh/src/net/routing/hat/router/mod.rs index ff576ae271..ae3ea09db4 100644 --- a/zenoh/src/net/routing/hat/router/mod.rs +++ b/zenoh/src/net/routing/hat/router/mod.rs @@ -58,7 +58,7 @@ use zenoh_config::{unwrap_or_default, ModeDependent, WhatAmI, WhatAmIMatcher, Ze use zenoh_protocol::{ common::ZExtBody, network::{ - declare::{queryable::ext::QueryableInfo, QueryableId, SubscriberId}, + declare::{queryable::ext::QueryableInfo, InterestId, QueryableId, SubscriberId}, oam::id::OAM_LINKSTATE, Oam, }, @@ -775,8 +775,10 @@ impl HatContext { struct HatFace { link_id: usize, next_id: AtomicU32, // @TODO: manage rollover and uniqueness + remote_sub_interests: HashMap>, bool)>, local_subs: HashMap, SubscriberId>, remote_subs: HashMap>, + remote_qabl_interests: HashMap>>, local_qabls: HashMap, (QueryableId, QueryableInfo)>, remote_qabls: HashMap>, } @@ -786,8 +788,10 @@ impl HatFace { Self { link_id: 0, next_id: AtomicU32::new(0), + remote_sub_interests: HashMap::new(), local_subs: HashMap::new(), remote_subs: HashMap::new(), + remote_qabl_interests: HashMap::new(), local_qabls: HashMap::new(), remote_qabls: HashMap::new(), } diff --git a/zenoh/src/net/routing/hat/router/pubsub.rs b/zenoh/src/net/routing/hat/router/pubsub.rs index da1ca66efd..2e7b22894d 100644 --- a/zenoh/src/net/routing/hat/router/pubsub.rs +++ b/zenoh/src/net/routing/hat/router/pubsub.rs @@ -28,7 +28,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::SubscriberId; +use zenoh_protocol::network::declare::{InterestId, SubscriberId}; use zenoh_protocol::{ core::{Reliability, WhatAmI, ZenohId}, network::declare::{ @@ -99,22 +99,57 @@ fn propagate_simple_subscription_to( || hat!(tables).failover_brokering(src_face.zid, dst_face.zid)) } { - let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); - let key_expr = Resource::decl_key(res, dst_face); - dst_face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareSubscriber(DeclareSubscriber { - id, - wire_expr: key_expr, - ext_info: *sub_info, - }), - }, - res.expr(), - )); + if dst_face.whatami != WhatAmI::Client { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr: key_expr, + ext_info: *sub_info, + }), + }, + res.expr(), + )); + } else { + let matching_interests = face_hat!(dst_face) + .remote_sub_interests + .values() + .filter(|si| si.0.as_ref().map(|si| si.matches(res)).unwrap_or(true)) + .cloned() + .collect::>, bool)>>(); + + for (int_res, aggregate) in matching_interests { + let res = if aggregate { + int_res.as_ref().unwrap_or(res) + } else { + res + }; + if !face_hat!(dst_face).local_subs.contains_key(res) { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr: key_expr, + ext_info: *sub_info, + }), + }, + res.expr(), + )); + } + } + } } } @@ -271,19 +306,11 @@ fn register_client_subscription( } }, None => { - res.session_ctxs.insert( - face.id, - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: Some(*sub_info), - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }), - ); + let ctx = res + .session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))); + get_mut_unchecked(ctx).subs = Some(*sub_info); } } } @@ -390,6 +417,33 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc res.expr(), )); } + for res in face_hat!(face) + .local_subs + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + res_hat!(m.upgrade().unwrap()) + .router_subs + .contains(&tables.zid) + }) { + if let Some(id) = face_hat_mut!(face).local_subs.remove(&res) { + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { + id, + ext_wire_expr: WireExprType::null(), + }), + }, + res.expr(), + )); + } + } + } } } @@ -603,26 +657,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { mode: Mode::Push, }; - if face.whatami == WhatAmI::Client { - for sub in &hat!(tables).router_subs { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); - let key_expr = Resource::decl_key(sub, face); - face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareSubscriber(DeclareSubscriber { - id, - wire_expr: key_expr, - ext_info: sub_info, - }), - }, - sub.expr(), - )); - } - } else if face.whatami == WhatAmI::Peer && !hat!(tables).full_net(WhatAmI::Peer) { + if face.whatami == WhatAmI::Peer && !hat!(tables).full_net(WhatAmI::Peer) { for sub in &hat!(tables).router_subs { if sub.context.is_some() && (res_hat!(sub).router_subs.iter().any(|r| *r != tables.zid) @@ -857,6 +892,106 @@ fn insert_faces_for_subs( } impl HatPubSubTrait for HatCode { + fn declare_sub_interest( + &self, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, + ) { + if current && face.whatami == WhatAmI::Client { + let sub_info = SubscriberInfo { + reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers + mode: Mode::Push, + }; + if let Some(res) = res.as_ref() { + if aggregate { + if hat!(tables) + .router_subs + .iter() + .any(|sub| sub.context.is_some() && sub.matches(res)) + { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let wire_expr = Resource::decl_key(res, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + res.expr(), + )); + } + } else { + for sub in &hat!(tables).router_subs { + if sub.context.is_some() && sub.matches(res) { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let wire_expr = Resource::decl_key(sub, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + sub.expr(), + )); + } + } + } + } else { + for sub in &hat!(tables).router_subs { + if sub.context.is_some() { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let wire_expr = Resource::decl_key(sub, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + sub.expr(), + )); + } + } + } + } + if future { + face_hat_mut!(face) + .remote_sub_interests + .insert(id, (res.cloned(), aggregate)); + } + } + + fn undeclare_sub_interest( + &self, + _tables: &mut Tables, + face: &mut Arc, + id: InterestId, + ) { + face_hat_mut!(face).remote_sub_interests.remove(&id); + } + fn declare_subscription( &self, tables: &mut Tables, diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index b76f0adcc6..ddf8ef2226 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -31,7 +31,7 @@ use std::sync::Arc; use zenoh_buffers::ZBuf; use zenoh_protocol::core::key_expr::include::{Includer, DEFAULT_INCLUDER}; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::QueryableId; +use zenoh_protocol::network::declare::{InterestId, QueryableId}; use zenoh_protocol::{ core::{WhatAmI, WireExpr, ZenohId}, network::declare::{ @@ -241,6 +241,11 @@ fn propagate_simple_queryable( let current = face_hat!(dst_face).local_qabls.get(res); if (src_face.is_none() || src_face.as_ref().unwrap().id != dst_face.id) && (current.is_none() || current.unwrap().1 != info) + && (dst_face.whatami != WhatAmI::Client + || face_hat!(dst_face) + .remote_qabl_interests + .values() + .any(|si| si.as_ref().map(|si| si.matches(res)).unwrap_or(true))) && if full_peers_net { dst_face.whatami == WhatAmI::Client } else { @@ -406,18 +411,11 @@ fn register_client_queryable( // Register queryable { let res = get_mut_unchecked(res); - get_mut_unchecked(res.session_ctxs.entry(face.id).or_insert_with(|| { - Arc::new(SessionContext { - face: face.clone(), - local_expr_id: None, - remote_expr_id: None, - subs: None, - qabl: None, - last_values: HashMap::new(), - in_interceptor_cache: None, - e_interceptor_cache: None, - }) - })) + get_mut_unchecked( + res.session_ctxs + .entry(face.id) + .or_insert_with(|| Arc::new(SessionContext::new(face.clone()))), + ) .qabl = Some(*qabl_info); } face_hat_mut!(face).remote_qabls.insert(id, res.clone()); @@ -522,6 +520,34 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc>>() + { + if !res.context().matches.iter().any(|m| { + res_hat!(m.upgrade().unwrap()) + .router_qabls + .keys() + .any(|zid| zid == &tables.zid) + }) { + if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(&res) { + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr: WireExprType::null(), + }), + }, + res.expr(), + )); + } + } + } } } @@ -740,31 +766,7 @@ fn forget_client_queryable( } pub(super) fn queries_new_face(tables: &mut Tables, face: &mut Arc) { - if face.whatami == WhatAmI::Client { - for qabl in hat!(tables).router_qabls.iter() { - if qabl.context.is_some() { - let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); - let key_expr = Resource::decl_key(qabl, face); - face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareQueryable(DeclareQueryable { - id, - wire_expr: key_expr, - ext_info: info, - }), - }, - qabl.expr(), - )); - } - } - } else if face.whatami == WhatAmI::Peer && !hat!(tables).full_net(WhatAmI::Peer) { + if face.whatami == WhatAmI::Peer && !hat!(tables).full_net(WhatAmI::Peer) { for qabl in hat!(tables).router_qabls.iter() { if qabl.context.is_some() && (res_hat!(qabl).router_qabls.keys().any(|r| *r != tables.zid) @@ -1016,6 +1018,109 @@ lazy_static::lazy_static! { } impl HatQueriesTrait for HatCode { + fn declare_qabl_interest( + &self, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, + ) { + if current && face.whatami == WhatAmI::Client { + if let Some(res) = res.as_ref() { + if aggregate { + if hat!(tables) + .router_qabls + .iter() + .any(|qabl| qabl.context.is_some() && qabl.matches(res)) + { + let info = local_qabl_info(tables, res, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let wire_expr = Resource::decl_key(res, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr, + ext_info: info, + }), + }, + res.expr(), + )); + } + } else { + for qabl in hat!(tables).router_qabls.iter() { + if qabl.context.is_some() && qabl.matches(res) { + let info = local_qabl_info(tables, qabl, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + let key_expr = Resource::decl_key(qabl, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + qabl.expr(), + )); + } + } + } + } else { + for qabl in hat!(tables).router_qabls.iter() { + if qabl.context.is_some() { + let info = local_qabl_info(tables, qabl, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + let key_expr = Resource::decl_key(qabl, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + qabl.expr(), + )); + } + } + } + } + if future { + face_hat_mut!(face) + .remote_qabl_interests + .insert(id, res.cloned()); + } + } + + fn undeclare_qabl_interest( + &self, + _tables: &mut Tables, + face: &mut Arc, + id: InterestId, + ) { + face_hat_mut!(face).remote_qabl_interests.remove(&id); + } + fn declare_queryable( &self, tables: &mut Tables, From 16f77891a0075810805fe2417e0935b323297e68 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Mon, 11 Mar 2024 15:43:01 +0100 Subject: [PATCH 02/30] Send WireExpr in UndeclareSubscriber/UndeclareQueryable to clients for pico --- .../net/routing/hat/linkstate_peer/pubsub.rs | 20 ++++++- .../net/routing/hat/linkstate_peer/queries.rs | 23 ++++++-- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 20 ++++++- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 23 ++++++-- zenoh/src/net/routing/hat/router/pubsub.rs | 53 +++++++++++++++--- zenoh/src/net/routing/hat/router/queries.rs | 56 +++++++++++++++---- 6 files changed, 162 insertions(+), 33 deletions(-) diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index 4b76e55387..8188e2c5e6 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -307,6 +307,14 @@ fn send_forget_sourced_subscription_to_net_childs( fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { for face in tables.faces.values_mut() { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -314,7 +322,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), @@ -412,6 +420,14 @@ pub(super) fn undeclare_client_subscription( let face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -419,7 +435,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index d7f42120f0..6703769a4b 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -365,15 +365,20 @@ fn send_forget_sourced_queryable_to_net_childs( fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for face in tables.faces.values_mut() { if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::UndeclareQueryable(UndeclareQueryable { - id, - ext_wire_expr: WireExprType::null(), - }), + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, ext_wire_expr }), }, res.expr(), )); @@ -478,6 +483,14 @@ pub(super) fn undeclare_client_queryable( if client_qabls.len() == 1 && !peer_qabls { let face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -485,7 +498,7 @@ pub(super) fn undeclare_client_queryable( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 976466af12..22bd50eb3f 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -167,6 +167,14 @@ fn client_subs(res: &Arc) -> Vec> { fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { for face in tables.faces.values_mut() { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -174,7 +182,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), @@ -201,6 +209,14 @@ pub(super) fn undeclare_client_subscription( let face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -208,7 +224,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index d8d0a3fcc0..76c3675dca 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -164,15 +164,20 @@ fn client_qabls(res: &Arc) -> Vec> { fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for face in tables.faces.values_mut() { if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::UndeclareQueryable(UndeclareQueryable { - id, - ext_wire_expr: WireExprType::null(), - }), + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, ext_wire_expr }), }, res.expr(), )); @@ -203,6 +208,14 @@ pub(super) fn undeclare_client_queryable( if client_qabls.len() == 1 { let face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -210,7 +223,7 @@ pub(super) fn undeclare_client_queryable( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/router/pubsub.rs b/zenoh/src/net/routing/hat/router/pubsub.rs index 2e7b22894d..e349fc7df9 100644 --- a/zenoh/src/net/routing/hat/router/pubsub.rs +++ b/zenoh/src/net/routing/hat/router/pubsub.rs @@ -404,6 +404,14 @@ fn send_forget_sourced_subscription_to_net_childs( fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { for face in tables.faces.values_mut() { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -411,7 +419,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), @@ -429,6 +437,14 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc .contains(&tables.zid) }) { if let Some(id) = face_hat_mut!(face).local_subs.remove(&res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -436,7 +452,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), @@ -469,6 +485,14 @@ fn propagate_forget_simple_subscription_to_peers(tables: &mut Tables, res: &Arc< }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -476,7 +500,7 @@ fn propagate_forget_simple_subscription_to_peers(tables: &mut Tables, res: &Arc< ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), @@ -620,6 +644,14 @@ pub(super) fn undeclare_client_subscription( let face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -627,7 +659,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr: WireExprType::null(), + ext_wire_expr, }), }, res.expr(), @@ -810,16 +842,21 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: }) }; if forget { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if dst_face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", dst_face.id), + } + } else { + WireExprType::null() + }; dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber( - UndeclareSubscriber { - id, - ext_wire_expr: WireExprType::null(), - }, + UndeclareSubscriber { id, ext_wire_expr }, ), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index ddf8ef2226..8f87dc055f 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -507,15 +507,20 @@ fn send_forget_sourced_queryable_to_net_childs( fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for face in tables.faces.values_mut() { if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(res, "", face.id), + } + } else { + WireExprType::null() + }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::UndeclareQueryable(UndeclareQueryable { - id, - ext_wire_expr: WireExprType::null(), - }), + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, ext_wire_expr }), }, res.expr(), )); @@ -533,6 +538,14 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc Date: Tue, 12 Mar 2024 15:30:51 +0100 Subject: [PATCH 03/30] Fix WireExprExt M flag encoding/decoding --- commons/zenoh-codec/src/network/declare.rs | 6 +++--- commons/zenoh-protocol/src/network/declare.rs | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index bcc55ed62b..202d9b028c 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -1075,7 +1075,7 @@ where if x.wire_expr.has_suffix() { flags |= 1; } - if let Mapping::Receiver = wire_expr.mapping { + if let Mapping::Sender = wire_expr.mapping { flags |= 1 << 1; } codec.write(&mut zriter, flags)?; @@ -1115,9 +1115,9 @@ where String::new() }; let mapping = if imsg::has_flag(flags, 1 << 1) { - Mapping::Receiver - } else { Mapping::Sender + } else { + Mapping::Receiver }; Ok(( diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 2dd8de4ef8..614ace7ed7 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -177,6 +177,19 @@ pub mod common { pub mod ext { use super::*; + /// Flags: + /// - N: Named If N==1 then the key expr has name/suffix + /// - M: Mapping if M==1 then key expr mapping is the one declared by the sender, else it is the one declared by the receiver + /// + /// 7 6 5 4 3 2 1 0 + /// +-+-+-+-+-+-+-+-+ + /// |X|X|X|X|X|X|M|N| + /// +-+-+-+---------+ + /// ~ key_scope:z16 ~ + /// +---------------+ + /// ~ key_suffix ~ if N==1 -- + /// +---------------+ + /// pub type WireExprExt = zextzbuf!(0x0f, true); #[derive(Debug, Clone, PartialEq, Eq)] pub struct WireExprType { From 6047d75adde4b9fad784b7b337ccba55353458bb Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 15 Mar 2024 16:59:35 +0100 Subject: [PATCH 04/30] Fix decl_key --- zenoh/src/net/routing/dispatcher/resource.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index 06da9294a0..d7c79a646d 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -513,7 +513,7 @@ impl Resource { mapping: Mapping::Sender, } } else { - wildsuffix.into() + res.expr().into() } } None => wildsuffix.into(), From 5de298f55b34d5ef1af276c217e75a97a6a27ccd Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 15 Mar 2024 17:00:08 +0100 Subject: [PATCH 05/30] Clients send all samples and queries to routers and peers --- zenoh/src/net/routing/hat/client/pubsub.rs | 9 +++++++++ zenoh/src/net/routing/hat/client/queries.rs | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index 91ad87522c..fb35b787ea 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -330,6 +330,15 @@ impl HatPubSubTrait for HatCode { return Arc::new(route); } }; + + if let Some(face) = tables.faces.values().find(|f| f.whatami != WhatAmI::Client) { + let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); + route.insert( + face.id, + (face.clone(), key_expr.to_owned(), NodeId::default()), + ); + } + let res = Resource::get_resource(expr.prefix, expr.suffix); let matches = res .as_ref() diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index af89cdeb66..0643184b55 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -99,6 +99,7 @@ fn propagate_simple_queryable( .local_qabls .insert(res.clone(), (id, info)); let key_expr = Resource::decl_key(res, &mut dst_face); + println!("Decled key = {key_expr:?}"); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -331,6 +332,16 @@ impl HatQueriesTrait for HatCode { return EMPTY_ROUTE.clone(); } }; + + if let Some(face) = tables.faces.values().find(|f| f.whatami != WhatAmI::Client) { + let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); + route.push(QueryTargetQabl { + direction: (face.clone(), key_expr.to_owned(), NodeId::default()), + complete: 0, + distance: f64::MAX, + }); + } + let res = Resource::get_resource(expr.prefix, expr.suffix); let matches = res .as_ref() From 961bec765097f6ff504b5146a592c21feea27d18 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Tue, 19 Mar 2024 17:48:48 +0100 Subject: [PATCH 06/30] Avoid self declaration loop on interest --- zenoh/src/net/routing/hat/router/pubsub.rs | 90 +++++++++++++++++---- zenoh/src/net/routing/hat/router/queries.rs | 90 +++++++++++++++++---- 2 files changed, 149 insertions(+), 31 deletions(-) diff --git a/zenoh/src/net/routing/hat/router/pubsub.rs b/zenoh/src/net/routing/hat/router/pubsub.rs index e349fc7df9..801cd5d853 100644 --- a/zenoh/src/net/routing/hat/router/pubsub.rs +++ b/zenoh/src/net/routing/hat/router/pubsub.rs @@ -363,6 +363,13 @@ fn client_subs(res: &Arc) -> Vec> { .collect() } +#[inline] +fn remote_client_subs(res: &Arc, face: &Arc) -> bool { + res.session_ctxs + .values() + .any(|ctx| ctx.face.id != face.id && ctx.subs.is_some()) +} + #[inline] fn send_forget_sourced_subscription_to_net_childs( tables: &Tables, @@ -402,8 +409,8 @@ fn send_forget_sourced_subscription_to_net_childs( } fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { - for face in tables.faces.values_mut() { - if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + for mut face in tables.faces.values().cloned() { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { // Still send WireExpr in UndeclareSubscriber to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -425,18 +432,21 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc res.expr(), )); } - for res in face_hat!(face) + for res in face_hat!(&mut face) .local_subs .keys() .cloned() .collect::>>() { if !res.context().matches.iter().any(|m| { - res_hat!(m.upgrade().unwrap()) - .router_subs - .contains(&tables.zid) + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_subs(&m, &face) + || remote_peer_subs(tables, &m) + || remote_router_subs(tables, &m)) + }) }) { - if let Some(id) = face_hat_mut!(face).local_subs.remove(&res) { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { // Still send WireExpr in UndeclareSubscriber to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -640,8 +650,9 @@ pub(super) fn undeclare_client_subscription( } else { propagate_forget_simple_subscription_to_peers(tables, res); } + if client_subs.len() == 1 && !router_subs && !peer_subs { - let face = &mut client_subs[0]; + let mut face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { // Still send WireExpr in UndeclareSubscriber to clients for pico @@ -665,6 +676,44 @@ pub(super) fn undeclare_client_subscription( res.expr(), )); } + for res in face_hat!(face) + .local_subs + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_subs(&m, face) + || remote_peer_subs(tables, &m) + || remote_router_subs(tables, &m)) + }) + }) { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } } @@ -946,11 +995,13 @@ impl HatPubSubTrait for HatCode { }; if let Some(res) = res.as_ref() { if aggregate { - if hat!(tables) - .router_subs - .iter() - .any(|sub| sub.context.is_some() && sub.matches(res)) - { + if hat!(tables).router_subs.iter().any(|sub| { + sub.context.is_some() + && sub.matches(res) + && (remote_client_subs(sub, face) + || remote_peer_subs(tables, sub) + || remote_router_subs(tables, sub)) + }) { let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); face_hat_mut!(face).local_subs.insert((*res).clone(), id); let wire_expr = Resource::decl_key(res, face); @@ -970,7 +1021,12 @@ impl HatPubSubTrait for HatCode { } } else { for sub in &hat!(tables).router_subs { - if sub.context.is_some() && sub.matches(res) { + if sub.context.is_some() + && sub.matches(res) + && (remote_client_subs(sub, face) + || remote_peer_subs(tables, sub) + || remote_router_subs(tables, sub)) + { let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); face_hat_mut!(face).local_subs.insert(sub.clone(), id); let wire_expr = Resource::decl_key(sub, face); @@ -992,7 +1048,11 @@ impl HatPubSubTrait for HatCode { } } else { for sub in &hat!(tables).router_subs { - if sub.context.is_some() { + if sub.context.is_some() + && (remote_client_subs(sub, face) + || remote_peer_subs(tables, sub) + || remote_router_subs(tables, sub)) + { let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); face_hat_mut!(face).local_subs.insert(sub.clone(), id); let wire_expr = Resource::decl_key(sub, face); diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index 8f87dc055f..6909f1f4e9 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -466,6 +466,13 @@ fn client_qabls(res: &Arc) -> Vec> { .collect() } +#[inline] +fn remote_client_qabls(res: &Arc, face: &Arc) -> bool { + res.session_ctxs + .values() + .any(|ctx| ctx.face.id != face.id && ctx.qabl.is_some()) +} + #[inline] fn send_forget_sourced_queryable_to_net_childs( tables: &Tables, @@ -505,8 +512,8 @@ fn send_forget_sourced_queryable_to_net_childs( } fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { - for face in tables.faces.values_mut() { - if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + for mut face in tables.faces.values().cloned() { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(res) { // Still send WireExpr in UndeclareQueryable to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -525,19 +532,21 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc>>() { if !res.context().matches.iter().any(|m| { - res_hat!(m.upgrade().unwrap()) - .router_qabls - .keys() - .any(|zid| zid == &tables.zid) + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_qabls(&m, &face) + || remote_peer_qabls(tables, &m) + || remote_router_qabls(tables, &m)) + }) }) { - if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(&res) { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { // Still send WireExpr in UndeclareQueryable to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -754,7 +763,7 @@ pub(super) fn undeclare_client_queryable( } if client_qabls.len() == 1 && !router_qabls && !peer_qabls { - let face = &mut client_qabls[0]; + let mut face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { // Still send WireExpr in UndeclareQueryable to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { @@ -777,6 +786,44 @@ pub(super) fn undeclare_client_queryable( res.expr(), )); } + for res in face_hat!(face) + .local_qabls + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_qabls(&m, face) + || remote_peer_qabls(tables, &m) + || remote_router_qabls(tables, &m)) + }) + }) { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } } @@ -1065,11 +1112,13 @@ impl HatQueriesTrait for HatCode { if current && face.whatami == WhatAmI::Client { if let Some(res) = res.as_ref() { if aggregate { - if hat!(tables) - .router_qabls - .iter() - .any(|qabl| qabl.context.is_some() && qabl.matches(res)) - { + if hat!(tables).router_qabls.iter().any(|qabl| { + qabl.context.is_some() + && qabl.matches(res) + && (remote_client_qabls(qabl, face) + || remote_peer_qabls(tables, qabl) + || remote_router_qabls(tables, qabl)) + }) { let info = local_qabl_info(tables, res, face); let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); face_hat_mut!(face).local_subs.insert((*res).clone(), id); @@ -1090,7 +1139,12 @@ impl HatQueriesTrait for HatCode { } } else { for qabl in hat!(tables).router_qabls.iter() { - if qabl.context.is_some() && qabl.matches(res) { + if qabl.context.is_some() + && qabl.matches(res) + && (remote_client_qabls(qabl, face) + || remote_peer_qabls(tables, qabl) + || remote_router_qabls(tables, qabl)) + { let info = local_qabl_info(tables, qabl, face); let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); face_hat_mut!(face) @@ -1115,7 +1169,11 @@ impl HatQueriesTrait for HatCode { } } else { for qabl in hat!(tables).router_qabls.iter() { - if qabl.context.is_some() { + if qabl.context.is_some() + && (remote_client_qabls(qabl, face) + || remote_peer_qabls(tables, qabl) + || remote_router_qabls(tables, qabl)) + { let info = local_qabl_info(tables, qabl, face); let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); face_hat_mut!(face) From eb976c80f6fd31876362ba8c2826916cc6a89d62 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Thu, 21 Mar 2024 17:06:12 +0100 Subject: [PATCH 07/30] Fix query/replies copy/paste bugs --- zenoh/src/net/routing/hat/router/queries.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index 6909f1f4e9..63f1a02b24 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -939,7 +939,8 @@ pub(super) fn queries_linkstate_change(tables: &mut Tables, zid: &ZenohId, links { let dst_face = &mut get_mut_unchecked(ctx).face; if dst_face.whatami == WhatAmI::Peer && src_face.zid != dst_face.zid { - if let Some(id) = face_hat!(dst_face).local_subs.get(res).cloned() { + if let Some((id, _)) = face_hat!(dst_face).local_qabls.get(res).cloned() + { let forget = !HatTables::failover_brokering_to(links, dst_face.zid) && { let ctx_links = hat!(tables) @@ -1121,7 +1122,9 @@ impl HatQueriesTrait for HatCode { }) { let info = local_qabl_info(tables, res, face); let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert((*res).clone(), id); + face_hat_mut!(face) + .local_qabls + .insert((*res).clone(), (id, info)); let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { From b8f1a9ca23fdd8695b81ec1876de9c579c359f00 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Thu, 21 Mar 2024 17:51:54 +0100 Subject: [PATCH 08/30] Peers implement interests protocol for clients --- .../src/net/routing/hat/linkstate_peer/mod.rs | 6 +- .../net/routing/hat/linkstate_peer/pubsub.rs | 286 +++++++++++++---- .../net/routing/hat/linkstate_peer/queries.rs | 219 ++++++++++--- zenoh/src/net/routing/hat/p2p_peer/mod.rs | 6 +- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 301 +++++++++++++++--- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 293 ++++++++++++++--- 6 files changed, 920 insertions(+), 191 deletions(-) diff --git a/zenoh/src/net/routing/hat/linkstate_peer/mod.rs b/zenoh/src/net/routing/hat/linkstate_peer/mod.rs index 5591ea3b3e..59f7d96613 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/mod.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/mod.rs @@ -53,7 +53,7 @@ use zenoh_config::{unwrap_or_default, ModeDependent, WhatAmI, WhatAmIMatcher, Ze use zenoh_protocol::{ common::ZExtBody, network::{ - declare::{queryable::ext::QueryableInfo, QueryableId, SubscriberId}, + declare::{queryable::ext::QueryableInfo, InterestId, QueryableId, SubscriberId}, oam::id::OAM_LINKSTATE, Oam, }, @@ -474,8 +474,10 @@ impl HatContext { struct HatFace { link_id: usize, next_id: AtomicU32, // @TODO: manage rollover and uniqueness + remote_sub_interests: HashMap>, bool)>, local_subs: HashMap, SubscriberId>, remote_subs: HashMap>, + remote_qabl_interests: HashMap>>, local_qabls: HashMap, (QueryableId, QueryableInfo)>, remote_qabls: HashMap>, } @@ -485,8 +487,10 @@ impl HatFace { Self { link_id: 0, next_id: AtomicU32::new(0), + remote_sub_interests: HashMap::new(), local_subs: HashMap::new(), remote_subs: HashMap::new(), + remote_qabl_interests: HashMap::new(), local_qabls: HashMap::new(), remote_qabls: HashMap::new(), } diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index 8188e2c5e6..ef83c2179f 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -90,22 +90,57 @@ fn propagate_simple_subscription_to( && !face_hat!(dst_face).local_subs.contains_key(res) && dst_face.whatami == WhatAmI::Client { - let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); - let key_expr = Resource::decl_key(res, dst_face); - dst_face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareSubscriber(DeclareSubscriber { - id, - wire_expr: key_expr, - ext_info: *sub_info, - }), - }, - res.expr(), - )); + if dst_face.whatami != WhatAmI::Client { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr: key_expr, + ext_info: *sub_info, + }), + }, + res.expr(), + )); + } else { + let matching_interests = face_hat!(dst_face) + .remote_sub_interests + .values() + .filter(|si| si.0.as_ref().map(|si| si.matches(res)).unwrap_or(true)) + .cloned() + .collect::>, bool)>>(); + + for (int_res, aggregate) in matching_interests { + let res = if aggregate { + int_res.as_ref().unwrap_or(res) + } else { + res + }; + if !face_hat!(dst_face).local_subs.contains_key(res) { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr: key_expr, + ext_info: *sub_info, + }), + }, + res.expr(), + )); + } + } + } } } @@ -266,6 +301,13 @@ fn client_subs(res: &Arc) -> Vec> { .collect() } +#[inline] +fn remote_client_subs(res: &Arc, face: &Arc) -> bool { + res.session_ctxs + .values() + .any(|ctx| ctx.face.id != face.id && ctx.subs.is_some()) +} + #[inline] fn send_forget_sourced_subscription_to_net_childs( tables: &Tables, @@ -305,8 +347,8 @@ fn send_forget_sourced_subscription_to_net_childs( } fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { - for face in tables.faces.values_mut() { - if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + for mut face in tables.faces.values().cloned() { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { // Still send WireExpr in UndeclareSubscriber to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -328,6 +370,42 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc res.expr(), )); } + for res in face_hat!(face) + .local_subs + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_subs(&m, &face) || remote_peer_subs(tables, &m)) + }) + }) { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } @@ -416,8 +494,9 @@ pub(super) fn undeclare_client_subscription( if client_subs.is_empty() { undeclare_peer_subscription(tables, None, res, &tables.zid.clone()); } + if client_subs.len() == 1 && !peer_subs { - let face = &mut client_subs[0]; + let mut face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { // Still send WireExpr in UndeclareSubscriber to clients for pico @@ -441,6 +520,42 @@ pub(super) fn undeclare_client_subscription( res.expr(), )); } + for res in face_hat!(face) + .local_subs + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_subs(&m, face) || remote_peer_subs(tables, &m)) + }) + }) { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } } @@ -459,32 +574,8 @@ fn forget_client_subscription( } } -pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { - let sub_info = SubscriberInfo { - reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers - mode: Mode::Push, - }; - - if face.whatami == WhatAmI::Client { - for sub in &hat!(tables).peer_subs { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); - let key_expr = Resource::decl_key(sub, face); - face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareSubscriber(DeclareSubscriber { - id, - wire_expr: key_expr, - ext_info: sub_info, - }), - }, - sub.expr(), - )); - } - } +pub(super) fn pubsub_new_face(_tables: &mut Tables, _face: &mut Arc) { + // Nothing to do } pub(super) fn pubsub_remove_node(tables: &mut Tables, node: &ZenohId) { @@ -577,24 +668,107 @@ fn insert_faces_for_subs( impl HatPubSubTrait for HatCode { fn declare_sub_interest( &self, - _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, - _res: Option<&mut Arc>, - _current: bool, - _future: bool, - _aggregate: bool, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, ) { - todo!() + if current && face.whatami == WhatAmI::Client { + let sub_info = SubscriberInfo { + reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers + mode: Mode::Push, + }; + if let Some(res) = res.as_ref() { + if aggregate { + if hat!(tables).peer_subs.iter().any(|sub| { + sub.context.is_some() + && sub.matches(res) + && (remote_client_subs(sub, face) || remote_peer_subs(tables, sub)) + }) { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let wire_expr = Resource::decl_key(res, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + res.expr(), + )); + } + } else { + for sub in &hat!(tables).peer_subs { + if sub.context.is_some() + && sub.matches(res) + && (remote_client_subs(sub, face) || remote_peer_subs(tables, sub)) + { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let wire_expr = Resource::decl_key(sub, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + sub.expr(), + )); + } + } + } + } else { + for sub in &hat!(tables).peer_subs { + if sub.context.is_some() + && (remote_client_subs(sub, face) || remote_peer_subs(tables, sub)) + { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let wire_expr = Resource::decl_key(sub, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + sub.expr(), + )); + } + } + } + } + if future { + face_hat_mut!(face) + .remote_sub_interests + .insert(id, (res.cloned(), aggregate)); + } } fn undeclare_sub_interest( &self, _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, + face: &mut Arc, + id: InterestId, ) { - todo!() + face_hat_mut!(face).remote_sub_interests.remove(&id); } fn declare_subscription( diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index 6703769a4b..aa7728552b 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -170,6 +170,10 @@ fn propagate_simple_queryable( if (src_face.is_none() || src_face.as_ref().unwrap().id != dst_face.id) && (current.is_none() || current.unwrap().1 != info) && dst_face.whatami == WhatAmI::Client + && face_hat!(dst_face) + .remote_qabl_interests + .values() + .any(|si| si.as_ref().map(|si| si.matches(res)).unwrap_or(true)) { let id = current .map(|c| c.0) @@ -324,6 +328,13 @@ fn client_qabls(res: &Arc) -> Vec> { .collect() } +#[inline] +fn remote_client_qabls(res: &Arc, face: &Arc) -> bool { + res.session_ctxs + .values() + .any(|ctx| ctx.face.id != face.id && ctx.qabl.is_some()) +} + #[inline] fn send_forget_sourced_queryable_to_net_childs( tables: &Tables, @@ -363,8 +374,8 @@ fn send_forget_sourced_queryable_to_net_childs( } fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { - for face in tables.faces.values_mut() { - if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { + for mut face in tables.faces.values().cloned() { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(res) { // Still send WireExpr in UndeclareQueryable to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -383,6 +394,34 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_qabls(&m, &face) || remote_peer_qabls(tables, &m)) + }) + }) { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr: WireExprType::null(), + }), + }, + res.expr(), + )); + } + } + } } } @@ -481,7 +520,7 @@ pub(super) fn undeclare_client_queryable( } if client_qabls.len() == 1 && !peer_qabls { - let face = &mut client_qabls[0]; + let mut face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { // Still send WireExpr in UndeclareQueryable to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { @@ -504,6 +543,42 @@ pub(super) fn undeclare_client_queryable( res.expr(), )); } + for res in face_hat!(face) + .local_qabls + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade().is_some_and(|m| { + m.context.is_some() + && (remote_client_qabls(&m, face) || remote_peer_qabls(tables, &m)) + }) + }) { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } } @@ -521,32 +596,8 @@ fn forget_client_queryable( } } -pub(super) fn queries_new_face(tables: &mut Tables, face: &mut Arc) { - if face.whatami == WhatAmI::Client { - for qabl in &hat!(tables).peer_qabls { - if qabl.context.is_some() { - let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); - let key_expr = Resource::decl_key(qabl, face); - face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareQueryable(DeclareQueryable { - id, - wire_expr: key_expr, - ext_info: info, - }), - }, - qabl.expr(), - )); - } - } - } +pub(super) fn queries_new_face(_tables: &mut Tables, _face: &mut Arc) { + // Nothing to do } pub(super) fn queries_remove_node(tables: &mut Tables, node: &ZenohId) { @@ -648,24 +699,112 @@ lazy_static::lazy_static! { impl HatQueriesTrait for HatCode { fn declare_qabl_interest( &self, - _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, - _res: Option<&mut Arc>, - _current: bool, - _future: bool, - _aggregate: bool, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, ) { - todo!() + if current && face.whatami == WhatAmI::Client { + if let Some(res) = res.as_ref() { + if aggregate { + if hat!(tables).peer_qabls.iter().any(|qabl| { + qabl.context.is_some() + && qabl.matches(res) + && (remote_client_qabls(qabl, face) || remote_peer_qabls(tables, qabl)) + }) { + let info = local_qabl_info(tables, res, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert((*res).clone(), (id, info)); + let wire_expr = Resource::decl_key(res, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr, + ext_info: info, + }), + }, + res.expr(), + )); + } + } else { + for qabl in hat!(tables).peer_qabls.iter() { + if qabl.context.is_some() + && qabl.matches(res) + && (remote_client_qabls(qabl, face) || remote_peer_qabls(tables, qabl)) + { + let info = local_qabl_info(tables, qabl, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + let key_expr = Resource::decl_key(qabl, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + qabl.expr(), + )); + } + } + } + } else { + for qabl in hat!(tables).peer_qabls.iter() { + if qabl.context.is_some() + && (remote_client_qabls(qabl, face) || remote_peer_qabls(tables, qabl)) + { + let info = local_qabl_info(tables, qabl, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + let key_expr = Resource::decl_key(qabl, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + qabl.expr(), + )); + } + } + } + } + if future { + face_hat_mut!(face) + .remote_qabl_interests + .insert(id, res.cloned()); + } } fn undeclare_qabl_interest( &self, _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, + face: &mut Arc, + id: InterestId, ) { - todo!() + face_hat_mut!(face).remote_qabl_interests.remove(&id); } fn declare_queryable( diff --git a/zenoh/src/net/routing/hat/p2p_peer/mod.rs b/zenoh/src/net/routing/hat/p2p_peer/mod.rs index 1a6c1ba407..f068209b82 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/mod.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/mod.rs @@ -50,7 +50,7 @@ use std::{ }; use zenoh_config::{unwrap_or_default, ModeDependent, WhatAmI, WhatAmIMatcher}; use zenoh_protocol::network::{ - declare::{QueryableId, SubscriberId}, + declare::{InterestId, QueryableId, SubscriberId}, Oam, }; use zenoh_protocol::{ @@ -367,8 +367,10 @@ impl HatContext { struct HatFace { next_id: AtomicU32, // @TODO: manage rollover and uniqueness + remote_sub_interests: HashMap>, bool)>, local_subs: HashMap, SubscriberId>, remote_subs: HashMap>, + remote_qabl_interests: HashMap>>, local_qabls: HashMap, (QueryableId, QueryableInfo)>, remote_qabls: HashMap>, } @@ -377,8 +379,10 @@ impl HatFace { fn new() -> Self { Self { next_id: AtomicU32::new(0), + remote_sub_interests: HashMap::new(), local_subs: HashMap::new(), remote_subs: HashMap::new(), + remote_qabl_interests: HashMap::new(), local_qabls: HashMap::new(), remote_qabls: HashMap::new(), } diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 22bd50eb3f..58a7a3e730 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -48,22 +48,57 @@ fn propagate_simple_subscription_to( && !face_hat!(dst_face).local_subs.contains_key(res) && (src_face.whatami == WhatAmI::Client || dst_face.whatami == WhatAmI::Client) { - let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); - let key_expr = Resource::decl_key(res, dst_face); - dst_face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareSubscriber(DeclareSubscriber { - id, - wire_expr: key_expr, - ext_info: *sub_info, - }), - }, - res.expr(), - )); + if dst_face.whatami != WhatAmI::Client { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr: key_expr, + ext_info: *sub_info, + }), + }, + res.expr(), + )); + } else { + let matching_interests = face_hat!(dst_face) + .remote_sub_interests + .values() + .filter(|si| si.0.as_ref().map(|si| si.matches(res)).unwrap_or(true)) + .cloned() + .collect::>, bool)>>(); + + for (int_res, aggregate) in matching_interests { + let res = if aggregate { + int_res.as_ref().unwrap_or(res) + } else { + res + }; + if !face_hat!(dst_face).local_subs.contains_key(res) { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(dst_face).local_subs.insert(res.clone(), id); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr: key_expr, + ext_info: *sub_info, + }), + }, + res.expr(), + )); + } + } + } } } @@ -164,9 +199,16 @@ fn client_subs(res: &Arc) -> Vec> { .collect() } +#[inline] +fn remote_client_subs(res: &Arc, face: &Arc) -> bool { + res.session_ctxs + .values() + .any(|ctx| ctx.face.id != face.id && ctx.subs.is_some()) +} + fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { - for face in tables.faces.values_mut() { - if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { + for mut face in tables.faces.values().cloned() { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { // Still send WireExpr in UndeclareSubscriber to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { WireExprType { @@ -188,6 +230,40 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc res.expr(), )); } + for res in face_hat!(face) + .local_subs + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade() + .is_some_and(|m| m.context.is_some() && remote_client_subs(&m, &face)) + }) { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } @@ -205,8 +281,9 @@ pub(super) fn undeclare_client_subscription( if client_subs.is_empty() { propagate_forget_simple_subscription(tables, res); } + if client_subs.len() == 1 { - let face = &mut client_subs[0]; + let mut face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { // Still send WireExpr in UndeclareSubscriber to clients for pico @@ -230,6 +307,40 @@ pub(super) fn undeclare_client_subscription( res.expr(), )); } + for res in face_hat!(face) + .local_subs + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade() + .is_some_and(|m| m.context.is_some() && remote_client_subs(&m, face)) + }) { + if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { + // Still send WireExpr in UndeclareSubscriber to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } } @@ -249,18 +360,26 @@ fn forget_client_subscription( } pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { - let sub_info = SubscriberInfo { - reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers - mode: Mode::Push, - }; - for src_face in tables - .faces - .values() - .cloned() - .collect::>>() - { - for sub in face_hat!(src_face).remote_subs.values() { - propagate_simple_subscription_to(tables, face, sub, &sub_info, &mut src_face.clone()); + if face.whatami != WhatAmI::Client { + let sub_info = SubscriberInfo { + reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers + mode: Mode::Push, + }; + for src_face in tables + .faces + .values() + .cloned() + .collect::>>() + { + for sub in face_hat!(src_face).remote_subs.values() { + propagate_simple_subscription_to( + tables, + face, + sub, + &sub_info, + &mut src_face.clone(), + ); + } } } } @@ -268,24 +387,122 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { impl HatPubSubTrait for HatCode { fn declare_sub_interest( &self, - _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, - _res: Option<&mut Arc>, - _current: bool, - _future: bool, - _aggregate: bool, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, ) { - todo!() + if current && face.whatami == WhatAmI::Client { + let sub_info = SubscriberInfo { + reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers + mode: Mode::Push, + }; + if let Some(res) = res.as_ref() { + if aggregate { + if tables.faces.values().any(|src_face| { + src_face.id != face.id + && face_hat!(src_face) + .remote_subs + .values() + .any(|sub| sub.context.is_some() && sub.matches(res)) + }) { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let wire_expr = Resource::decl_key(res, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + res.expr(), + )); + } + } else { + for src_face in tables + .faces + .values() + .cloned() + .collect::>>() + { + if src_face.id != face.id { + for sub in face_hat!(src_face).remote_subs.values() { + if sub.context.is_some() && sub.matches(res) { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let wire_expr = Resource::decl_key(sub, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber( + DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }, + ), + }, + sub.expr(), + )); + } + } + } + } + } + } else { + for src_face in tables + .faces + .values() + .cloned() + .collect::>>() + { + if src_face.id != face.id { + for sub in face_hat!(src_face).remote_subs.values() { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let wire_expr = Resource::decl_key(sub, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareSubscriber(DeclareSubscriber { + id, + wire_expr, + ext_info: sub_info, + }), + }, + sub.expr(), + )); + } + } + } + } + } + if future { + face_hat_mut!(face) + .remote_sub_interests + .insert(id, (res.cloned(), aggregate)); + } } fn undeclare_sub_interest( &self, _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, + face: &mut Arc, + id: InterestId, ) { - todo!() + face_hat_mut!(face).remote_sub_interests.remove(&id); } fn declare_subscription( diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index 76c3675dca..aa9bc24826 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -77,42 +77,61 @@ fn local_qabl_info(_tables: &Tables, res: &Arc, face: &Arc) }) } +#[inline] +fn propagate_simple_queryable_to( + tables: &mut Tables, + dst_face: &mut Arc, + res: &Arc, + src_face: &Option<&mut Arc>, +) { + let info = local_qabl_info(tables, res, dst_face); + let current = face_hat!(dst_face).local_qabls.get(res); + if (src_face.is_none() || src_face.as_ref().unwrap().id != dst_face.id) + && (current.is_none() || current.unwrap().1 != info) + && (dst_face.whatami != WhatAmI::Client + || face_hat!(dst_face) + .remote_qabl_interests + .values() + .any(|si| si.as_ref().map(|si| si.matches(res)).unwrap_or(true))) + && (src_face.is_none() + || src_face.as_ref().unwrap().whatami == WhatAmI::Client + || dst_face.whatami == WhatAmI::Client) + { + let id = current + .map(|c| c.0) + .unwrap_or(face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst)); + face_hat_mut!(dst_face) + .local_qabls + .insert(res.clone(), (id, info)); + let key_expr = Resource::decl_key(res, dst_face); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + res.expr(), + )); + } +} + fn propagate_simple_queryable( tables: &mut Tables, res: &Arc, src_face: Option<&mut Arc>, ) { - let faces = tables.faces.values().cloned(); + let faces = tables + .faces + .values() + .cloned() + .collect::>>(); for mut dst_face in faces { - let info = local_qabl_info(tables, res, &dst_face); - let current = face_hat!(dst_face).local_qabls.get(res); - if (src_face.is_none() || src_face.as_ref().unwrap().id != dst_face.id) - && (current.is_none() || current.unwrap().1 != info) - && (src_face.is_none() - || src_face.as_ref().unwrap().whatami == WhatAmI::Client - || dst_face.whatami == WhatAmI::Client) - { - let id = current - .map(|c| c.0) - .unwrap_or(face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst)); - face_hat_mut!(&mut dst_face) - .local_qabls - .insert(res.clone(), (id, info)); - let key_expr = Resource::decl_key(res, &mut dst_face); - dst_face.primitives.send_declare(RoutingContext::with_expr( - Declare { - ext_qos: ext::QoSType::DECLARE, - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::DeclareQueryable(DeclareQueryable { - id, - wire_expr: key_expr, - ext_info: info, - }), - }, - res.expr(), - )); - } + propagate_simple_queryable_to(tables, &mut dst_face, res, &src_face); } } @@ -161,6 +180,13 @@ fn client_qabls(res: &Arc) -> Vec> { .collect() } +#[inline] +fn remote_client_qabls(res: &Arc, face: &Arc) -> bool { + res.session_ctxs + .values() + .any(|ctx| ctx.face.id != face.id && ctx.qabl.is_some()) +} + fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for face in tables.faces.values_mut() { if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { @@ -182,6 +208,32 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade() + .is_some_and(|m| m.context.is_some() && remote_client_qabls(&m, face)) + }) { + if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(&res) { + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr: WireExprType::null(), + }), + }, + res.expr(), + )); + } + } + } } } @@ -206,7 +258,7 @@ pub(super) fn undeclare_client_queryable( propagate_simple_queryable(tables, res, None); } if client_qabls.len() == 1 { - let face = &mut client_qabls[0]; + let mut face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { // Still send WireExpr in UndeclareQueryable to clients for pico let ext_wire_expr = if face.whatami == WhatAmI::Client { @@ -229,6 +281,40 @@ pub(super) fn undeclare_client_queryable( res.expr(), )); } + for res in face_hat!(face) + .local_qabls + .keys() + .cloned() + .collect::>>() + { + if !res.context().matches.iter().any(|m| { + m.upgrade() + .is_some_and(|m| m.context.is_some() && (remote_client_qabls(&m, face))) + }) { + if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { + // Still send WireExpr in UndeclareQueryable to clients for pico + let ext_wire_expr = if face.whatami == WhatAmI::Client { + WireExprType { + wire_expr: Resource::get_best_key(&res, "", face.id), + } + } else { + WireExprType::null() + }; + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr, + }), + }, + res.expr(), + )); + } + } + } } } } @@ -246,15 +332,17 @@ fn forget_client_queryable( } } -pub(super) fn queries_new_face(tables: &mut Tables, _face: &mut Arc) { - for face in tables - .faces - .values() - .cloned() - .collect::>>() - { - for qabl in face_hat!(face).remote_qabls.values() { - propagate_simple_queryable(tables, qabl, Some(&mut face.clone())); +pub(super) fn queries_new_face(tables: &mut Tables, face: &mut Arc) { + if face.whatami != WhatAmI::Client { + for src_face in tables + .faces + .values() + .cloned() + .collect::>>() + { + for qabl in face_hat!(src_face).remote_qabls.values() { + propagate_simple_queryable_to(tables, face, qabl, &Some(&mut src_face.clone())); + } } } } @@ -266,24 +354,127 @@ lazy_static::lazy_static! { impl HatQueriesTrait for HatCode { fn declare_qabl_interest( &self, - _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, - _res: Option<&mut Arc>, - _current: bool, - _future: bool, - _aggregate: bool, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, + aggregate: bool, ) { - todo!() + if current && face.whatami == WhatAmI::Client { + if let Some(res) = res.as_ref() { + if aggregate { + if tables.faces.values().any(|src_face| { + src_face.id != face.id + && face_hat!(src_face) + .remote_qabls + .values() + .any(|qabl| qabl.context.is_some() && qabl.matches(res)) + }) { + let info = local_qabl_info(tables, res, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert((*res).clone(), (id, info)); + let wire_expr = Resource::decl_key(res, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr, + ext_info: info, + }), + }, + res.expr(), + )); + } + } else { + for src_face in tables + .faces + .values() + .cloned() + .collect::>>() + { + if src_face.id != face.id { + for qabl in face_hat!(src_face).remote_qabls.values() { + if qabl.context.is_some() && qabl.matches(res) { + let info = local_qabl_info(tables, qabl, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + let key_expr = Resource::decl_key(qabl, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + qabl.expr(), + )); + } + } + } + } + } + } else { + for src_face in tables + .faces + .values() + .cloned() + .collect::>>() + { + if src_face.id != face.id { + for qabl in face_hat!(src_face).remote_qabls.values() { + if qabl.context.is_some() { + let info = local_qabl_info(tables, qabl, face); + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + let key_expr = Resource::decl_key(qabl, face); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareQueryable(DeclareQueryable { + id, + wire_expr: key_expr, + ext_info: info, + }), + }, + qabl.expr(), + )); + } + } + } + } + } + } + if future { + face_hat_mut!(face) + .remote_qabl_interests + .insert(id, res.cloned()); + } } fn undeclare_qabl_interest( &self, _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, + face: &mut Arc, + id: InterestId, ) { - todo!() + face_hat_mut!(face).remote_qabl_interests.remove(&id); } fn declare_queryable( From 26bbd8ecd3afd951e9e3e6792a2938dc4a6b956e Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 22 Mar 2024 16:19:41 +0100 Subject: [PATCH 09/30] Don't send WireExpr in UndeclareSubscriber/UndeclareQueryable to clients --- .../net/routing/hat/linkstate_peer/pubsub.rs | 40 ++--------- .../net/routing/hat/linkstate_peer/queries.rs | 33 ++-------- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 40 ++--------- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 33 ++-------- zenoh/src/net/routing/hat/router/pubsub.rs | 63 +++--------------- zenoh/src/net/routing/hat/router/queries.rs | 66 ++++--------------- 6 files changed, 41 insertions(+), 234 deletions(-) diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index 31bcf7666a..9148d0558d 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -342,14 +342,6 @@ fn send_forget_sourced_subscription_to_net_childs( fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { for mut face in tables.faces.values().cloned() { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -357,7 +349,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -376,14 +368,6 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc }) }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -391,7 +375,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -492,14 +476,6 @@ pub(super) fn undeclare_client_subscription( let mut face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -507,7 +483,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -526,14 +502,6 @@ pub(super) fn undeclare_client_subscription( }) }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -541,7 +509,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index aa7728552b..0a763b2f46 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -376,20 +376,15 @@ fn send_forget_sourced_queryable_to_net_childs( fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for mut face in tables.faces.values().cloned() { if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, ext_wire_expr }), + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr: WireExprType::null(), + }), }, res.expr(), )); @@ -522,14 +517,6 @@ pub(super) fn undeclare_client_queryable( if client_qabls.len() == 1 && !peer_qabls { let mut face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -537,7 +524,7 @@ pub(super) fn undeclare_client_queryable( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -556,14 +543,6 @@ pub(super) fn undeclare_client_queryable( }) }) { if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -571,7 +550,7 @@ pub(super) fn undeclare_client_queryable( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 431f2d9cc9..64e4c5cf68 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -202,14 +202,6 @@ fn remote_client_subs(res: &Arc, face: &Arc) -> bool { fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { for mut face in tables.faces.values().cloned() { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -217,7 +209,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -234,14 +226,6 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc .is_some_and(|m| m.context.is_some() && remote_client_subs(&m, &face)) }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -249,7 +233,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -279,14 +263,6 @@ pub(super) fn undeclare_client_subscription( let mut face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -294,7 +270,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -311,14 +287,6 @@ pub(super) fn undeclare_client_subscription( .is_some_and(|m| m.context.is_some() && remote_client_subs(&m, face)) }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -326,7 +294,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index aa9bc24826..69580e3b40 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -190,20 +190,15 @@ fn remote_client_qabls(res: &Arc, face: &Arc) -> bool { fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for face in tables.faces.values_mut() { if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, ext_wire_expr }), + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr: WireExprType::null(), + }), }, res.expr(), )); @@ -260,14 +255,6 @@ pub(super) fn undeclare_client_queryable( if client_qabls.len() == 1 { let mut face = &mut client_qabls[0]; if let Some((id, _)) = face_hat_mut!(face).local_qabls.remove(res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -275,7 +262,7 @@ pub(super) fn undeclare_client_queryable( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -292,14 +279,6 @@ pub(super) fn undeclare_client_queryable( .is_some_and(|m| m.context.is_some() && (remote_client_qabls(&m, face))) }) { if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(&res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -307,7 +286,7 @@ pub(super) fn undeclare_client_queryable( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/router/pubsub.rs b/zenoh/src/net/routing/hat/router/pubsub.rs index d98cc64ae8..9e419e406a 100644 --- a/zenoh/src/net/routing/hat/router/pubsub.rs +++ b/zenoh/src/net/routing/hat/router/pubsub.rs @@ -403,14 +403,6 @@ fn send_forget_sourced_subscription_to_net_childs( fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc) { for mut face in tables.faces.values().cloned() { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -418,7 +410,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -439,14 +431,6 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc }) }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -454,7 +438,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -487,14 +471,6 @@ fn propagate_forget_simple_subscription_to_peers(tables: &mut Tables, res: &Arc< }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -502,7 +478,7 @@ fn propagate_forget_simple_subscription_to_peers(tables: &mut Tables, res: &Arc< ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -647,14 +623,6 @@ pub(super) fn undeclare_client_subscription( let mut face = &mut client_subs[0]; if !(face.whatami == WhatAmI::Client && res.expr().starts_with(PREFIX_LIVELINESS)) { if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -662,7 +630,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -683,14 +651,6 @@ pub(super) fn undeclare_client_subscription( }) }) { if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(&res) { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(&res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, @@ -698,7 +658,7 @@ pub(super) fn undeclare_client_subscription( ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber(UndeclareSubscriber { id, - ext_wire_expr, + ext_wire_expr: WireExprType::null(), }), }, res.expr(), @@ -881,21 +841,16 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: }) }; if forget { - // Still send WireExpr in UndeclareSubscriber to clients for pico - let ext_wire_expr = if dst_face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", dst_face.id), - } - } else { - WireExprType::null() - }; dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, body: DeclareBody::UndeclareSubscriber( - UndeclareSubscriber { id, ext_wire_expr }, + UndeclareSubscriber { + id, + ext_wire_expr: WireExprType::null(), + }, ), }, res.expr(), diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index 63f1a02b24..9a2797ea71 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -514,20 +514,15 @@ fn send_forget_sourced_queryable_to_net_childs( fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { for mut face in tables.faces.values().cloned() { if let Some((id, _)) = face_hat_mut!(&mut face).local_qabls.remove(res) { - // Still send WireExpr in UndeclareQueryable to clients for pico - let ext_wire_expr = if face.whatami == WhatAmI::Client { - WireExprType { - wire_expr: Resource::get_best_key(res, "", face.id), - } - } else { - WireExprType::null() - }; face.primitives.send_declare(RoutingContext::with_expr( Declare { ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, - body: DeclareBody::UndeclareQueryable(UndeclareQueryable { id, ext_wire_expr }), + body: DeclareBody::UndeclareQueryable(UndeclareQueryable { + id, + ext_wire_expr: WireExprType::null(), + }), }, res.expr(), )); @@ -547,14 +542,6 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc Date: Wed, 27 Mar 2024 10:19:11 +0100 Subject: [PATCH 10/30] Add client writer-side filtering (#863) * Add client writer-side filtering * Reimplement liveliness with interests * Fix writer-side filtering before receiving FinalInterest --- zenoh/src/net/routing/dispatcher/face.rs | 9 +- zenoh/src/net/routing/hat/client/mod.rs | 6 +- zenoh/src/net/routing/hat/client/pubsub.rs | 159 ++++++++++--- zenoh/src/publication.rs | 65 +++--- zenoh/src/session.rs | 249 +++++++++++++-------- zenoh/src/subscriber.rs | 4 +- 6 files changed, 340 insertions(+), 152 deletions(-) diff --git a/zenoh/src/net/routing/dispatcher/face.rs b/zenoh/src/net/routing/dispatcher/face.rs index e60b0abf12..3470540d39 100644 --- a/zenoh/src/net/routing/dispatcher/face.rs +++ b/zenoh/src/net/routing/dispatcher/face.rs @@ -22,7 +22,7 @@ use std::any::Any; use std::collections::HashMap; use std::fmt; use std::sync::Arc; -use zenoh_protocol::network::declare::{FinalInterest, InterestId}; +use zenoh_protocol::network::declare::{FinalInterest, Interest, InterestId}; use zenoh_protocol::network::{ext, Declare, DeclareBody}; use zenoh_protocol::zenoh::RequestBody; use zenoh_protocol::{ @@ -41,6 +41,7 @@ pub struct FaceState { #[cfg(feature = "stats")] pub(crate) stats: Option>, pub(crate) primitives: Arc, + pub(crate) local_interests: HashMap>, bool)>, pub(crate) remote_key_interests: HashMap>>, pub(crate) local_mappings: HashMap>, pub(crate) remote_mappings: HashMap>, @@ -70,6 +71,7 @@ impl FaceState { #[cfg(feature = "stats")] stats, primitives, + local_interests: HashMap::new(), remote_key_interests: HashMap::new(), local_mappings: HashMap::new(), remote_mappings: HashMap::new(), @@ -265,7 +267,10 @@ impl Primitives for Face { } } zenoh_protocol::network::DeclareBody::FinalInterest(m) => { - log::warn!("Received unsupported {m:?}") + get_mut_unchecked(&mut self.state.clone()) + .local_interests + .entry(m.id) + .and_modify(|interest| interest.2 = true); } zenoh_protocol::network::DeclareBody::UndeclareInterest(m) => { unregister_expr_interest(&self.tables, &mut self.state.clone(), m.id); diff --git a/zenoh/src/net/routing/hat/client/mod.rs b/zenoh/src/net/routing/hat/client/mod.rs index a9908f5f58..f18d7497f3 100644 --- a/zenoh/src/net/routing/hat/client/mod.rs +++ b/zenoh/src/net/routing/hat/client/mod.rs @@ -42,7 +42,9 @@ use std::{ sync::{atomic::AtomicU32, Arc}, }; use zenoh_config::WhatAmI; -use zenoh_protocol::network::declare::{queryable::ext::QueryableInfo, QueryableId, SubscriberId}; +use zenoh_protocol::network::declare::{ + queryable::ext::QueryableInfo, InterestId, QueryableId, SubscriberId, +}; use zenoh_protocol::network::Oam; use zenoh_result::ZResult; use zenoh_sync::get_mut_unchecked; @@ -282,6 +284,7 @@ impl HatContext { struct HatFace { next_id: AtomicU32, // @TODO: manage rollover and uniqueness + remote_sub_interests: HashMap>>, local_subs: HashMap, SubscriberId>, remote_subs: HashMap>, local_qabls: HashMap, (QueryableId, QueryableInfo)>, @@ -292,6 +295,7 @@ impl HatFace { fn new() -> Self { Self { next_id: AtomicU32::new(0), + remote_sub_interests: HashMap::new(), local_subs: HashMap::new(), remote_subs: HashMap::new(), local_qabls: HashMap::new(), diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index fb932dfed9..cf0f51496e 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -20,12 +20,14 @@ use crate::net::routing::dispatcher::tables::{Route, RoutingExpr}; use crate::net::routing::hat::HatPubSubTrait; use crate::net::routing::router::RoutesIndexes; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; +use crate::KeyExpr; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::sync::atomic::Ordering; use std::sync::Arc; use zenoh_protocol::core::key_expr::OwnedKeyExpr; -use zenoh_protocol::network::declare::{InterestId, SubscriberId}; +use zenoh_protocol::network::declare::{Interest, InterestId, SubscriberId}; +use zenoh_protocol::network::{DeclareInterest, UndeclareInterest}; use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ @@ -244,24 +246,96 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { impl HatPubSubTrait for HatCode { fn declare_sub_interest( &self, - _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, - _res: Option<&mut Arc>, - _current: bool, - _future: bool, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, + res: Option<&mut Arc>, + current: bool, + future: bool, _aggregate: bool, ) { - todo!() + face_hat_mut!(face) + .remote_sub_interests + .insert(id, res.as_ref().map(|res| (*res).clone())); + for dst_face in tables + .faces + .values_mut() + .filter(|f| f.whatami != WhatAmI::Client) + { + let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); + let mut interest = Interest::KEYEXPRS + Interest::SUBSCRIBERS; + if current { + interest += Interest::CURRENT; + } + if future { + interest += Interest::FUTURE; + } + get_mut_unchecked(dst_face).local_interests.insert( + id, + (interest, res.as_ref().map(|res| (*res).clone()), !current), + ); + let wire_expr = res.as_ref().map(|res| Resource::decl_key(res, dst_face)); + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareInterest(DeclareInterest { + id, + interest, + wire_expr, + }), + }, + res.as_ref().map(|res| res.expr()).unwrap_or_default(), + )); + } } fn undeclare_sub_interest( &self, - _tables: &mut Tables, - _face: &mut Arc, - _id: InterestId, + tables: &mut Tables, + face: &mut Arc, + id: InterestId, ) { - todo!() + if let Some(interest) = face_hat_mut!(face).remote_sub_interests.remove(&id) { + if !tables.faces.values().any(|f| { + f.whatami == WhatAmI::Client + && face_hat!(f) + .remote_sub_interests + .values() + .any(|i| *i == interest) + }) { + for dst_face in tables + .faces + .values_mut() + .filter(|f| f.whatami != WhatAmI::Client) + { + for id in dst_face + .local_interests + .keys() + .cloned() + .collect::>() + { + let (int, res, _) = dst_face.local_interests.get(&id).unwrap(); + if int.subscribers() && (*res == interest) { + dst_face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareInterest(UndeclareInterest { + id, + ext_wire_expr: WireExprType::null(), + }), + }, + res.as_ref().map(|res| res.expr()).unwrap_or_default(), + )); + get_mut_unchecked(dst_face).local_interests.remove(&id); + } + } + } + } + } } fn declare_subscription( @@ -323,12 +397,51 @@ impl HatPubSubTrait for HatCode { } }; - if let Some(face) = tables.faces.values().find(|f| f.whatami != WhatAmI::Client) { - let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); - route.insert( - face.id, - (face.clone(), key_expr.to_owned(), NodeId::default()), - ); + for face in tables + .faces + .values() + .filter(|f| f.whatami != WhatAmI::Client) + { + if face + .local_interests + .values() + .any(|(interest, res, finalized)| { + *finalized + && interest.subscribers() + && res + .as_ref() + .map(|res| { + KeyExpr::try_from(res.expr()) + .and_then(|intres| { + KeyExpr::try_from(expr.full_expr()) + .map(|putres| intres.includes(&putres)) + }) + .unwrap_or(false) + }) + .unwrap_or(true) + }) + { + if face_hat!(face).remote_subs.values().any(|sub| { + KeyExpr::try_from(sub.expr()) + .and_then(|subres| { + KeyExpr::try_from(expr.full_expr()) + .map(|putres| subres.intersects(&putres)) + }) + .unwrap_or(false) + }) { + let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); + route.insert( + face.id, + (face.clone(), key_expr.to_owned(), NodeId::default()), + ); + } + } else { + let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); + route.insert( + face.id, + (face.clone(), key_expr.to_owned(), NodeId::default()), + ); + } } let res = Resource::get_resource(expr.prefix, expr.suffix); @@ -342,15 +455,7 @@ impl HatPubSubTrait for HatCode { let mres = mres.upgrade().unwrap(); for (sid, context) in &mres.session_ctxs { - if context.subs.is_some() - && match tables.whatami { - WhatAmI::Router => context.face.whatami != WhatAmI::Router, - _ => { - source_type == WhatAmI::Client - || context.face.whatami == WhatAmI::Client - } - } - { + if context.subs.is_some() && context.face.whatami == WhatAmI::Client { route.entry(*sid).or_insert_with(|| { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, *sid); (context.face.clone(), key_expr.to_owned(), NodeId::default()) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 392c0bf8c1..9c2086eb90 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -25,6 +25,7 @@ use crate::{ handlers::{Callback, DefaultHandler, IntoHandler}, Id, }; +use std::fmt; use std::future::Ready; use zenoh_core::{zread, AsyncResolve, Resolvable, Resolve, SyncResolve}; use zenoh_protocol::network::push::ext; @@ -157,7 +158,7 @@ impl SyncResolve for PutBuilder<'_, '_> { let publisher = Publisher { session, #[cfg(feature = "unstable")] - eid: 0, // This is a one shot Publisher + id: 0, // This is a one shot Publisher key_expr: key_expr?, congestion_control, priority, @@ -193,6 +194,22 @@ use std::pin::Pin; use std::task::{Context, Poll}; use zenoh_result::Error; +pub(crate) struct PublisherState { + pub(crate) id: Id, + pub(crate) remote_id: Id, + pub(crate) key_expr: KeyExpr<'static>, + pub(crate) destination: Locality, +} + +impl fmt::Debug for PublisherState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Publisher") + .field("id", &self.id) + .field("key_expr", &self.key_expr) + .finish() + } +} + #[zenoh_macros::unstable] #[derive(Clone)] pub enum PublisherRef<'a> { @@ -254,8 +271,7 @@ impl std::fmt::Debug for PublisherRef<'_> { #[derive(Debug, Clone)] pub struct Publisher<'a> { pub(crate) session: SessionRef<'a>, - #[cfg(feature = "unstable")] - pub(crate) eid: EntityId, + pub(crate) id: Id, pub(crate) key_expr: KeyExpr<'a>, pub(crate) congestion_control: CongestionControl, pub(crate) priority: Priority, @@ -283,7 +299,7 @@ impl<'a> Publisher<'a> { pub fn id(&self) -> EntityGlobalId { EntityGlobalId { zid: self.session.zid(), - eid: self.eid, + eid: self.id, } } @@ -588,11 +604,9 @@ impl Resolvable for PublisherUndeclaration<'_> { impl SyncResolve for PublisherUndeclaration<'_> { fn res_sync(mut self) -> ::To { let Publisher { - session, key_expr, .. + session, id: eid, .. } = &self.publisher; - session - .undeclare_publication_intent(key_expr.clone()) - .res_sync()?; + session.undeclare_publisher_inner(*eid)?; self.publisher.key_expr = unsafe { keyexpr::from_str_unchecked("") }.into(); Ok(()) } @@ -609,10 +623,7 @@ impl AsyncResolve for PublisherUndeclaration<'_> { impl Drop for Publisher<'_> { fn drop(&mut self) { if !self.key_expr.is_empty() { - let _ = self - .session - .undeclare_publication_intent(self.key_expr.clone()) - .res_sync(); + let _ = self.session.undeclare_publisher_inner(self.id); } } } @@ -841,23 +852,19 @@ impl<'a, 'b> SyncResolve for PublisherBuilder<'a, 'b> { } } } - self.session - .declare_publication_intent(key_expr.clone()) - .res_sync()?; - #[cfg(feature = "unstable")] - let eid = self.session.runtime.next_id(); - let publisher = Publisher { - session: self.session, - #[cfg(feature = "unstable")] - eid, - key_expr, - congestion_control: self.congestion_control, - priority: self.priority, - is_express: self.is_express, - destination: self.destination, - }; - log::trace!("publish({:?})", publisher.key_expr); - Ok(publisher) + let session = self.session; + session + .declare_publisher_inner(key_expr.clone(), self.destination) + .map(|eid| Publisher { + session, + #[cfg(feature = "unstable")] + id: eid, + key_expr, + congestion_control: self.congestion_control, + priority: self.priority, + is_express: self.is_express, + destination: self.destination, + }) } } diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 496c6879ce..0e801f4522 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -57,10 +57,14 @@ use zenoh_buffers::ZBuf; use zenoh_collections::SingleOrVec; use zenoh_config::unwrap_or_default; use zenoh_core::{zconfigurable, zread, Resolve, ResolveClosure, ResolveFuture, SyncResolve}; +use zenoh_protocol::core::EntityId; +use zenoh_protocol::network::declare::Interest; #[cfg(feature = "unstable")] use zenoh_protocol::network::declare::SubscriberId; use zenoh_protocol::network::AtomicRequestId; +use zenoh_protocol::network::DeclareInterest; use zenoh_protocol::network::RequestId; +use zenoh_protocol::network::UndeclareInterest; use zenoh_protocol::zenoh::reply::ReplyBody; use zenoh_protocol::zenoh::Del; use zenoh_protocol::zenoh::Put; @@ -103,7 +107,7 @@ pub(crate) struct SessionState { pub(crate) remote_resources: HashMap, #[cfg(feature = "unstable")] pub(crate) remote_subscribers: HashMap>, - //pub(crate) publications: Vec, + pub(crate) publishers: HashMap, pub(crate) subscribers: HashMap>, pub(crate) queryables: HashMap>, #[cfg(feature = "unstable")] @@ -112,13 +116,13 @@ pub(crate) struct SessionState { pub(crate) matching_listeners: HashMap>, pub(crate) queries: HashMap, pub(crate) aggregated_subscribers: Vec, - //pub(crate) aggregated_publishers: Vec, + pub(crate) aggregated_publishers: Vec, } impl SessionState { pub(crate) fn new( aggregated_subscribers: Vec, - _aggregated_publishers: Vec, + aggregated_publishers: Vec, ) -> SessionState { SessionState { primitives: None, @@ -128,7 +132,7 @@ impl SessionState { remote_resources: HashMap::new(), #[cfg(feature = "unstable")] remote_subscribers: HashMap::new(), - //publications: Vec::new(), + publishers: HashMap::new(), subscribers: HashMap::new(), queryables: HashMap::new(), #[cfg(feature = "unstable")] @@ -137,7 +141,7 @@ impl SessionState { matching_listeners: HashMap::new(), queries: HashMap::new(), aggregated_subscribers, - //aggregated_publishers, + aggregated_publishers, } } } @@ -881,84 +885,103 @@ impl Session { }) } - /// Declare a publication for the given key expression. - /// - /// Puts that match the given key expression will only be sent on the network - /// if matching subscribers exist in the system. - /// - /// # Arguments - /// - /// * `key_expr` - The key expression to publish - pub(crate) fn declare_publication_intent<'a>( - &'a self, - _key_expr: KeyExpr<'a>, - ) -> impl Resolve> + 'a { - ResolveClosure::new(move || { - // log::trace!("declare_publication({:?})", key_expr); - // let mut state = zwrite!(self.state); - // if !state.publications.iter().any(|p| **p == **key_expr) { - // let declared_pub = if let Some(join_pub) = state - // .aggregated_publishers - // .iter() - // .find(|s| s.includes(&key_expr)) - // { - // let joined_pub = state.publications.iter().any(|p| join_pub.includes(p)); - // (!joined_pub).then(|| join_pub.clone().into()) - // } else { - // Some(key_expr.clone()) - // }; - // state.publications.push(key_expr.into()); - - // if let Some(res) = declared_pub { - // let primitives = state.primitives.as_ref().unwrap().clone(); - // drop(state); - // primitives.decl_publisher(&res.to_wire(self), None); - // } - // } - Ok(()) - }) + pub(crate) fn declare_publisher_inner( + &self, + key_expr: KeyExpr, + destination: Locality, + ) -> ZResult { + let mut state = zwrite!(self.state); + log::trace!("declare_publisher({:?})", key_expr); + let id = self.runtime.next_id(); + + let mut pub_state = PublisherState { + id, + remote_id: id, + key_expr: key_expr.clone().into_owned(), + destination, + }; + + let declared_pub = (destination != Locality::SessionLocal) + .then(|| { + match state + .aggregated_publishers + .iter() + .find(|s| s.includes(&key_expr)) + { + Some(join_pub) => { + if let Some(joined_pub) = state.publishers.values().find(|p| { + p.destination != Locality::SessionLocal + && join_pub.includes(&p.key_expr) + }) { + pub_state.remote_id = joined_pub.remote_id; + None + } else { + Some(join_pub.clone().into()) + } + } + None => { + if let Some(twin_pub) = state.publishers.values().find(|p| { + p.destination != Locality::SessionLocal && p.key_expr == key_expr + }) { + pub_state.remote_id = twin_pub.remote_id; + None + } else { + Some(key_expr.clone()) + } + } + } + }) + .flatten(); + + state.publishers.insert(id, pub_state); + + if let Some(res) = declared_pub { + let primitives = state.primitives.as_ref().unwrap().clone(); + drop(state); + primitives.send_declare(Declare { + ext_qos: declare::ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: declare::ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareInterest(DeclareInterest { + id, + interest: Interest::CURRENT + + Interest::FUTURE + + Interest::KEYEXPRS + + Interest::SUBSCRIBERS, + wire_expr: Some(res.to_wire(self).to_owned()), + }), + }); + } + Ok(id) } - /// Undeclare a publication previously declared - /// with [`declare_publication`](Session::declare_publication). - /// - /// # Arguments - /// - /// * `key_expr` - The key expression of the publication to undeclarte - pub(crate) fn undeclare_publication_intent<'a>( - &'a self, - _key_expr: KeyExpr<'a>, - ) -> impl Resolve> + 'a { - ResolveClosure::new(move || { - // let mut state = zwrite!(self.state); - // if let Some(idx) = state.publications.iter().position(|p| **p == *key_expr) { - // trace!("undeclare_publication({:?})", key_expr); - // state.publications.remove(idx); - // match state - // .aggregated_publishers - // .iter() - // .find(|s| s.includes(&key_expr)) - // { - // Some(join_pub) => { - // let joined_pub = state.publications.iter().any(|p| join_pub.includes(p)); - // if !joined_pub { - // let primitives = state.primitives.as_ref().unwrap().clone(); - // let key_expr = WireExpr::from(join_pub).to_owned(); - // drop(state); - // primitives.forget_publisher(&key_expr, None); - // } - // } - // None => { - // let primitives = state.primitives.as_ref().unwrap().clone(); - // drop(state); - // primitives.forget_publisher(&key_expr.to_wire(self), None); - // } - // }; - // } else { - // bail!("Unable to find publication") - // } + pub(crate) fn undeclare_publisher_inner(&self, pid: Id) -> ZResult<()> { + let mut state = zwrite!(self.state); + if let Some(pub_state) = state.publishers.remove(&pid) { + trace!("undeclare_publisher({:?})", pub_state); + if pub_state.destination != Locality::SessionLocal { + // Note: there might be several publishers on the same KeyExpr. + // Before calling forget_publishers(key_expr), check if this was the last one. + if !state.publishers.values().any(|p| { + p.destination != Locality::SessionLocal && p.remote_id == pub_state.remote_id + }) { + let primitives = state.primitives.as_ref().unwrap().clone(); + drop(state); + primitives.send_declare(Declare { + ext_qos: declare::ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: declare::ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareInterest(UndeclareInterest { + id: pub_state.remote_id, + ext_wire_expr: WireExprType::null(), + }), + }); + } + } Ok(()) - }) + } else { + Err(zerror!("Unable to find publisher").into()) + } } pub(crate) fn declare_subscriber_inner( @@ -970,7 +993,7 @@ impl Session { info: &SubscriberInfo, ) -> ZResult> { let mut state = zwrite!(self.state); - log::trace!("subscribe({:?})", key_expr); + log::trace!("declare_subscriber({:?})", key_expr); let id = self.runtime.next_id(); let key_expr = match scope { Some(scope) => scope / key_expr, @@ -1090,15 +1113,32 @@ impl Session { let state = zread!(self.state); self.update_status_up(&state, &key_expr) } + } else if key_expr + .as_str() + .starts_with(crate::liveliness::PREFIX_LIVELINESS) + { + let primitives = state.primitives.as_ref().unwrap().clone(); + drop(state); + + primitives.send_declare(Declare { + ext_qos: declare::ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: declare::ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareInterest(DeclareInterest { + id, + wire_expr: Some(key_expr.to_wire(self).to_owned()), + interest: Interest::KEYEXPRS + Interest::SUBSCRIBERS + Interest::FUTURE, + }), + }); } Ok(sub_state) } - pub(crate) fn unsubscribe(&self, sid: Id) -> ZResult<()> { + pub(crate) fn undeclare_subscriber_inner(&self, sid: Id) -> ZResult<()> { let mut state = zwrite!(self.state); if let Some(sub_state) = state.subscribers.remove(&sid) { - trace!("unsubscribe({:?})", sub_state); + trace!("undeclare_subscriber({:?})", sub_state); for res in state .local_resources .values_mut() @@ -1147,6 +1187,23 @@ impl Session { self.update_status_down(&state, &sub_state.key_expr) } } + } else if sub_state + .key_expr + .as_str() + .starts_with(crate::liveliness::PREFIX_LIVELINESS) + { + let primitives = state.primitives.as_ref().unwrap().clone(); + drop(state); + + primitives.send_declare(Declare { + ext_qos: declare::ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: declare::ext::NodeIdType::DEFAULT, + body: DeclareBody::UndeclareInterest(UndeclareInterest { + id: sub_state.id, + ext_wire_expr: WireExprType::null(), + }), + }); } Ok(()) } else { @@ -1162,7 +1219,7 @@ impl Session { callback: Callback<'static, Query>, ) -> ZResult> { let mut state = zwrite!(self.state); - log::trace!("queryable({:?})", key_expr); + log::trace!("declare_queryable({:?})", key_expr); let id = self.runtime.next_id(); let qable_state = Arc::new(QueryableState { id, @@ -1198,7 +1255,7 @@ impl Session { pub(crate) fn close_queryable(&self, qid: Id) -> ZResult<()> { let mut state = zwrite!(self.state); if let Some(qable_state) = state.queryables.remove(&qid) { - trace!("close_queryable({:?})", qable_state); + trace!("undeclare_queryable({:?})", qable_state); if qable_state.origin != Locality::SessionLocal { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); @@ -2003,7 +2060,7 @@ impl Primitives for Session { }; self.handle_data( false, - &m.ext_wire_expr.wire_expr, + &expr.to_wire(self), Some(data_info), ZBuf::default(), #[cfg(feature = "unstable")] @@ -2021,11 +2078,21 @@ impl Primitives for Session { zenoh_protocol::network::DeclareBody::UndeclareQueryable(m) => { trace!("recv UndeclareQueryable {:?}", m.id); } - DeclareBody::DeclareToken(_) => todo!(), - DeclareBody::UndeclareToken(_) => todo!(), - DeclareBody::DeclareInterest(_) => todo!(), - DeclareBody::FinalInterest(_) => todo!(), - DeclareBody::UndeclareInterest(_) => todo!(), + DeclareBody::DeclareToken(m) => { + trace!("recv DeclareToken {:?}", m.id); + } + DeclareBody::UndeclareToken(m) => { + trace!("recv UndeclareToken {:?}", m.id); + } + DeclareBody::DeclareInterest(m) => { + trace!("recv DeclareInterest {:?}", m.id); + } + DeclareBody::FinalInterest(m) => { + trace!("recv FinalInterest {:?}", m.id); + } + DeclareBody::UndeclareInterest(m) => { + trace!("recv UndeclareInterest {:?}", m.id); + } } } diff --git a/zenoh/src/subscriber.rs b/zenoh/src/subscriber.rs index 4488140610..9b778e070f 100644 --- a/zenoh/src/subscriber.rs +++ b/zenoh/src/subscriber.rs @@ -144,7 +144,7 @@ impl SyncResolve for SubscriberUndeclaration<'_> { self.subscriber.alive = false; self.subscriber .session - .unsubscribe(self.subscriber.state.id) + .undeclare_subscriber_inner(self.subscriber.state.id) } } @@ -159,7 +159,7 @@ impl AsyncResolve for SubscriberUndeclaration<'_> { impl Drop for SubscriberInner<'_> { fn drop(&mut self) { if self.alive { - let _ = self.session.unsubscribe(self.state.id); + let _ = self.session.undeclare_subscriber_inner(self.state.id); } } } From df2ea5849547ab02b944de85b90ce0fd8f71da61 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Wed, 27 Mar 2024 16:14:14 +0100 Subject: [PATCH 11/30] Fix pubsub interest based routing after router failover --- zenoh/src/net/routing/hat/client/pubsub.rs | 33 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index cf0f51496e..cc0cb09582 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -18,7 +18,7 @@ use crate::net::routing::dispatcher::resource::{NodeId, Resource, SessionContext use crate::net::routing::dispatcher::tables::Tables; use crate::net::routing::dispatcher::tables::{Route, RoutingExpr}; use crate::net::routing::hat::HatPubSubTrait; -use crate::net::routing::router::RoutesIndexes; +use crate::net::routing::router::{update_data_routes_from, RoutesIndexes}; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; use crate::KeyExpr; use std::borrow::Cow; @@ -231,7 +231,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let sub_info = SubscriberInfo { reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers }; - for src_face in tables + for mut src_face in tables .faces .values() .cloned() @@ -240,7 +240,36 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { for sub in face_hat!(src_face).remote_subs.values() { propagate_simple_subscription_to(tables, face, sub, &sub_info, &mut src_face.clone()); } + if face.whatami != WhatAmI::Client { + for res in face_hat_mut!(&mut src_face).remote_sub_interests.values() { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + let interest = Interest::KEYEXPRS + + Interest::SUBSCRIBERS + + Interest::CURRENT + + Interest::FUTURE; + get_mut_unchecked(face).local_interests.insert( + id, + (interest, res.as_ref().map(|res| (*res).clone()), false), + ); + let wire_expr = res.as_ref().map(|res| Resource::decl_key(res, face)); + face.primitives.send_declare(RoutingContext::with_expr( + Declare { + ext_qos: ext::QoSType::DECLARE, + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::DEFAULT, + body: DeclareBody::DeclareInterest(DeclareInterest { + id, + interest, + wire_expr, + }), + }, + res.as_ref().map(|res| res.expr()).unwrap_or_default(), + )); + } + } } + // recompute routes + update_data_routes_from(tables, &mut tables.root_res.clone()); } impl HatPubSubTrait for HatCode { From 41f59d362a6620f53030ff15e0c51bacc6a6baf0 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Thu, 4 Apr 2024 12:06:14 +0200 Subject: [PATCH 12/30] Declare message can be Push/Request/RequestContinuous/Response --- commons/zenoh-codec/src/network/declare.rs | 157 +++++++-------- commons/zenoh-codec/tests/codec.rs | 16 ++ commons/zenoh-protocol/src/network/declare.rs | 179 ++++++++++-------- commons/zenoh-protocol/src/network/mod.rs | 6 +- zenoh/src/key_expr.rs | 4 +- zenoh/src/net/routing/dispatcher/face.rs | 2 +- zenoh/src/net/routing/dispatcher/resource.rs | 4 +- zenoh/src/net/routing/hat/client/pubsub.rs | 10 +- zenoh/src/net/routing/hat/client/queries.rs | 8 +- .../net/routing/hat/linkstate_peer/pubsub.rs | 14 +- .../net/routing/hat/linkstate_peer/queries.rs | 14 +- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 10 +- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 8 +- zenoh/src/net/routing/hat/router/pubsub.rs | 22 +-- zenoh/src/net/routing/hat/router/queries.rs | 22 +-- zenoh/src/net/routing/mod.rs | 2 +- zenoh/src/net/runtime/adminspace.rs | 8 +- zenoh/src/net/tests/tables.rs | 12 +- zenoh/src/session.rs | 18 +- 19 files changed, 280 insertions(+), 236 deletions(-) diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index d7a25ea0a9..bad03cc5ae 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -19,12 +19,16 @@ use zenoh_buffers::{ ZBuf, }; use zenoh_protocol::{ - common::{iext, imsg, ZExtZ64}, + common::{ + iext, + imsg::{self, HEADER_BITS}, + ZExtZ64, + }, core::{ExprId, ExprLen, WireExpr}, network::{ declare::{ self, common, interest, keyexpr, queryable, subscriber, token, Declare, DeclareBody, - Interest, + DeclareMode, Interest, }, id, Mapping, }, @@ -48,8 +52,8 @@ where DeclareBody::DeclareToken(r) => self.write(&mut *writer, r)?, DeclareBody::UndeclareToken(r) => self.write(&mut *writer, r)?, DeclareBody::DeclareInterest(r) => self.write(&mut *writer, r)?, - DeclareBody::FinalInterest(r) => self.write(&mut *writer, r)?, DeclareBody::UndeclareInterest(r) => self.write(&mut *writer, r)?, + DeclareBody::DeclareFinal(r) => self.write(&mut *writer, r)?, } Ok(()) @@ -77,8 +81,8 @@ where D_TOKEN => DeclareBody::DeclareToken(codec.read(&mut *reader)?), U_TOKEN => DeclareBody::UndeclareToken(codec.read(&mut *reader)?), D_INTEREST => DeclareBody::DeclareInterest(codec.read(&mut *reader)?), - F_INTEREST => DeclareBody::FinalInterest(codec.read(&mut *reader)?), U_INTEREST => DeclareBody::UndeclareInterest(codec.read(&mut *reader)?), + D_FINAL => DeclareBody::DeclareFinal(codec.read(&mut *reader)?), _ => return Err(DidntRead), }; @@ -95,7 +99,7 @@ where fn write(self, writer: &mut W, x: &Declare) -> Self::Output { let Declare { - interest_id, + mode, ext_qos, ext_tstamp, ext_nodeid, @@ -104,9 +108,13 @@ where // Header let mut header = id::DECLARE; - if x.interest_id.is_some() { - header |= declare::flag::I; - } + header |= match mode { + DeclareMode::Push => 0b00, + DeclareMode::Request(_) => 0b01, + DeclareMode::RequestContinuous(_) => 0b10, + DeclareMode::Response(_) => 0b11, + } << HEADER_BITS; + let mut n_exts = ((ext_qos != &declare::ext::QoSType::DEFAULT) as u8) + (ext_tstamp.is_some() as u8) + ((ext_nodeid != &declare::ext::NodeIdType::DEFAULT) as u8); @@ -116,8 +124,11 @@ where self.write(&mut *writer, header)?; // Body - if let Some(interest_id) = interest_id { - self.write(&mut *writer, interest_id)?; + if let DeclareMode::Request(rid) + | DeclareMode::RequestContinuous(rid) + | DeclareMode::Response(rid) = mode + { + self.write(&mut *writer, rid)?; } // Extensions @@ -166,10 +177,14 @@ where return Err(DidntRead); } - let mut interest_id = None; - if imsg::has_flag(self.header, declare::flag::I) { - interest_id = Some(self.codec.read(&mut *reader)?); - } + // Body + let mode = match (self.header >> HEADER_BITS) & 0b11 { + 0b00 => DeclareMode::Push, + 0b01 => DeclareMode::Request(self.codec.read(&mut *reader)?), + 0b10 => DeclareMode::RequestContinuous(self.codec.read(&mut *reader)?), + 0b11 => DeclareMode::Response(self.codec.read(&mut *reader)?), + _ => return Err(DidntRead), + }; // Extensions let mut ext_qos = declare::ext::QoSType::DEFAULT; @@ -206,7 +221,7 @@ where let body: DeclareBody = self.codec.read(&mut *reader)?; Ok(Declare { - interest_id, + mode, ext_qos, ext_tstamp, ext_nodeid, @@ -215,6 +230,59 @@ where } } +// Final +impl WCodec<&common::DeclareFinal, &mut W> for Zenoh080 +where + W: Writer, +{ + type Output = Result<(), DidntWrite>; + + fn write(self, writer: &mut W, x: &common::DeclareFinal) -> Self::Output { + let common::DeclareFinal = x; + + // Header + let header = declare::id::D_FINAL; + self.write(&mut *writer, header)?; + + Ok(()) + } +} + +impl RCodec for Zenoh080 +where + R: Reader, +{ + type Error = DidntRead; + + fn read(self, reader: &mut R) -> Result { + let header: u8 = self.read(&mut *reader)?; + let codec = Zenoh080Header::new(header); + + codec.read(reader) + } +} + +impl RCodec for Zenoh080Header +where + R: Reader, +{ + type Error = DidntRead; + + fn read(self, reader: &mut R) -> Result { + if imsg::mid(self.header) != declare::id::D_FINAL { + return Err(DidntRead); + } + + // Extensions + let has_ext = imsg::has_flag(self.header, token::flag::Z); + if has_ext { + extension::skip_all(reader, "Final")?; + } + + Ok(common::DeclareFinal) + } +} + // DeclareKeyExpr impl WCodec<&keyexpr::DeclareKeyExpr, &mut W> for Zenoh080 where @@ -976,65 +1044,6 @@ where } } -// FinalInterest -impl WCodec<&interest::FinalInterest, &mut W> for Zenoh080 -where - W: Writer, -{ - type Output = Result<(), DidntWrite>; - - fn write(self, writer: &mut W, x: &interest::FinalInterest) -> Self::Output { - let interest::FinalInterest { id } = x; - - // Header - let header = declare::id::F_INTEREST; - self.write(&mut *writer, header)?; - - // Body - self.write(&mut *writer, id)?; - - Ok(()) - } -} - -impl RCodec for Zenoh080 -where - R: Reader, -{ - type Error = DidntRead; - - fn read(self, reader: &mut R) -> Result { - let header: u8 = self.read(&mut *reader)?; - let codec = Zenoh080Header::new(header); - - codec.read(reader) - } -} - -impl RCodec for Zenoh080Header -where - R: Reader, -{ - type Error = DidntRead; - - fn read(self, reader: &mut R) -> Result { - if imsg::mid(self.header) != declare::id::F_INTEREST { - return Err(DidntRead); - } - - // Body - let id: interest::InterestId = self.codec.read(&mut *reader)?; - - // Extensions - let has_ext = imsg::has_flag(self.header, token::flag::Z); - if has_ext { - extension::skip_all(reader, "FinalInterest")?; - } - - Ok(interest::FinalInterest { id }) - } -} - // UndeclareInterest impl WCodec<&interest::UndeclareInterest, &mut W> for Zenoh080 where diff --git a/commons/zenoh-codec/tests/codec.rs b/commons/zenoh-codec/tests/codec.rs index 2f0e870c4f..d28ba9a4d3 100644 --- a/commons/zenoh-codec/tests/codec.rs +++ b/commons/zenoh-codec/tests/codec.rs @@ -31,6 +31,22 @@ use zenoh_protocol::{ zenoh, zextunit, zextz64, zextzbuf, }; +#[test] +fn zbuf_test() { + let mut buffer = vec![0u8; 64]; + + let zbuf = ZBuf::empty(); + let mut writer = buffer.writer(); + + let codec = Zenoh080::new(); + codec.write(&mut writer, &zbuf).unwrap(); + println!("Buffer: {:?}", buffer); + + let mut reader = buffer.reader(); + let ret: ZBuf = codec.read(&mut reader).unwrap(); + assert_eq!(ret, zbuf); +} + const NUM_ITER: usize = 100; const MAX_PAYLOAD_SIZE: usize = 256; diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 10027259c2..b8f302b0f3 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -18,6 +18,8 @@ use crate::{ zextz64, zextzbuf, }; use alloc::borrow::Cow; +pub use common::*; +use core::sync::atomic::AtomicU32; pub use interest::*; pub use keyexpr::*; pub use queryable::*; @@ -31,24 +33,59 @@ pub mod flag { } /// Flags: -/// - I: Interest If I==1 then the declare is in a response to an Interest with future==false -/// - X: Reserved +/// - |: Mode The mode of the the declaration* +/// -/ /// - Z: Extension If Z==1 then at least one extension is present /// /// 7 6 5 4 3 2 1 0 /// +-+-+-+-+-+-+-+-+ -/// |Z|X|I| DECLARE | +/// |Z|Mod| DECLARE | /// +-+-+-+---------+ -/// ~interest_id:z32~ if I==1 +/// ~ rid:z32 ~ if Mode != Push /// +---------------+ /// ~ [decl_exts] ~ if Z==1 /// +---------------+ /// ~ declaration ~ /// +---------------+ /// +/// *Mode of declaration: +/// - Mode 0b00: Push +/// - Mode 0b01: Request +/// - Mode 0b10: RequestContinuous +/// - Mode 0b11: Response + +/// The resolution of a RequestId +pub type DeclareRequestId = u32; +pub type AtomicDeclareRequestId = AtomicU32; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum DeclareMode { + Push, + Request(DeclareRequestId), + RequestContinuous(DeclareRequestId), + Response(DeclareRequestId), +} + +impl DeclareMode { + #[cfg(feature = "test")] + pub fn rand() -> Self { + use rand::Rng; + + let mut rng = rand::thread_rng(); + + match rng.gen_range(0..4) { + 0 => DeclareMode::Push, + 1 => DeclareMode::Request(rng.gen()), + 2 => DeclareMode::RequestContinuous(rng.gen()), + 3 => DeclareMode::Response(rng.gen()), + _ => unreachable!(), + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Declare { - pub interest_id: Option, + pub mode: DeclareMode, pub ext_qos: ext::QoSType, pub ext_tstamp: Option, pub ext_nodeid: ext::NodeIdType, @@ -85,8 +122,9 @@ pub mod id { pub const U_TOKEN: u8 = 0x07; pub const D_INTEREST: u8 = 0x08; - pub const F_INTEREST: u8 = 0x09; - pub const U_INTEREST: u8 = 0x0A; + pub const U_INTEREST: u8 = 0x09; + + pub const D_FINAL: u8 = 0x1A; } #[derive(Debug, Clone, PartialEq, Eq)] @@ -100,8 +138,8 @@ pub enum DeclareBody { DeclareToken(DeclareToken), UndeclareToken(UndeclareToken), DeclareInterest(DeclareInterest), - FinalInterest(FinalInterest), UndeclareInterest(UndeclareInterest), + DeclareFinal(DeclareFinal), } impl DeclareBody { @@ -121,8 +159,8 @@ impl DeclareBody { 6 => DeclareBody::DeclareToken(DeclareToken::rand()), 7 => DeclareBody::UndeclareToken(UndeclareToken::rand()), 8 => DeclareBody::DeclareInterest(DeclareInterest::rand()), - 9 => DeclareBody::FinalInterest(FinalInterest::rand()), - 10 => DeclareBody::UndeclareInterest(UndeclareInterest::rand()), + 9 => DeclareBody::UndeclareInterest(UndeclareInterest::rand()), + 10 => DeclareBody::DeclareFinal(DeclareFinal::rand()), _ => unreachable!(), } } @@ -135,14 +173,14 @@ impl Declare { let mut rng = rand::thread_rng(); - let interest_id = rng.gen_bool(0.5).then_some(rng.gen::()); + let mode = DeclareMode::rand(); let ext_qos = ext::QoSType::rand(); let ext_tstamp = rng.gen_bool(0.5).then(ext::TimestampType::rand); let ext_nodeid = ext::NodeIdType::rand(); let body = DeclareBody::rand(); Self { - interest_id, + mode, ext_qos, ext_tstamp, ext_nodeid, @@ -154,6 +192,29 @@ impl Declare { pub mod common { use super::*; + /// ```text + /// Flags: + /// - X: Reserved + /// - X: Reserved + /// - Z: Extension If Z==1 then at least one extension is present + /// + /// 7 6 5 4 3 2 1 0 + /// +-+-+-+-+-+-+-+-+ + /// |Z|x|x| D_FINAL | + /// +---------------+ + /// ~ [final_exts] ~ if Z==1 + /// +---------------+ + /// ``` + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct DeclareFinal; + + impl DeclareFinal { + #[cfg(feature = "test")] + pub fn rand() -> Self { + Self + } + } + pub mod ext { use super::*; @@ -545,7 +606,7 @@ pub mod queryable { /// /// 7 6 5 4 3 2 1 0 /// +-+-+-+-+-+-+-+-+ - /// |Z|0_2| U_QBL | + /// |Z|X|X| U_QBL | /// +---------------+ /// ~ qbls_id:z32 ~ /// +---------------+ @@ -668,44 +729,51 @@ pub mod interest { pub type InterestId = u32; pub mod flag { - pub const C: u8 = 1 << 5; // 0x20 Current if C==1 then the interest refers to the current declarations. + // pub const X: u8 = 1 << 5; // 0x20 Reserved pub const F: u8 = 1 << 6; // 0x40 Future if F==1 then the interest refers to the future declarations. pub const Z: u8 = 1 << 7; // 0x80 Extensions if Z==1 then an extension will follow } /// # DeclareInterest message /// - /// The DECLARE INTEREST message is sent to request the transmission of existing and future - /// declarations of a given kind matching a target keyexpr. E.g., a declare interest could be sent to - /// request the transmisison of all existing subscriptions matching `a/*`. A FINAL INTEREST is used to - /// mark the end of the transmission of exisiting matching declarations. + /// The DECLARE INTEREST message is sent to request the transmission of current and/or future + /// declarations of a given kind matching a target keyexpr. E.g., a declare interest could be + /// sent to request the transmisison of all current subscriptions matching `a/*`. /// - /// E.g., the [`DeclareInterest`]/[`FinalInterest`]/[`UndeclareInterest`] message flow is the following: + /// The behaviour of a DECLARE INTEREST depends on the DECLARE MODE in the DECLARE MESSAGE: + /// - Push: only future declarations + /// - Request: only current declarations + /// - RequestContinous: current and future declarations + /// - Response: invalid + /// + /// E.g., the [`DeclareInterest`]/[`UndeclareInterest`] message flow is the following: /// /// ```text /// A B /// | DECL INTEREST | - /// |------------------>| -- This is a DeclareInterest e.g. for subscriber declarations/undeclarations. + /// |------------------>| -- Sent in Declare::RequestContinuous. + /// | | This is a DeclareInterest e.g. for subscriber declarations/undeclarations. /// | | /// | DECL SUBSCRIBER | - /// |<------------------| + /// |<------------------| -- Sent in Declare::Response /// | DECL SUBSCRIBER | - /// |<------------------| + /// |<------------------| -- Sent in Declare::Response /// | DECL SUBSCRIBER | - /// |<------------------| + /// |<------------------| -- Sent in Declare::Response /// | | - /// | FINAL INTEREST | - /// |<------------------| -- The FinalInterest signals that all known subscribers have been transmitted. + /// | FINAL | + /// |<------------------| -- Sent in Declare::Response /// | | /// | DECL SUBSCRIBER | - /// |<------------------| -- This is a new subscriber declaration. + /// |<------------------| -- Sent in Declare::Push. This is a new subscriber declaration. /// | UNDECL SUBSCRIBER | - /// |<------------------| -- This is a new subscriber undeclaration. + /// |<------------------| -- Sent in Declare::Push. This is a new subscriber undeclaration. /// | | /// | ... | /// | | /// | UNDECL INTEREST | - /// |------------------>| -- This is an UndeclareInterest to stop receiving subscriber declarations/undeclarations. + /// |------------------>| -- Sent in Declare::RequestContinuous. + /// | | This is an UndeclareInterest to stop receiving subscriber declarations/undeclarations. /// | | /// ``` /// @@ -713,7 +781,7 @@ pub mod interest { /// /// ```text /// Flags: - /// - C: Current if C==1 then the interest refers to the current declarations. + /// - X: Reserved /// - F: Future if F==1 then the interest refers to the future declarations. Note that if F==0 then: /// - Declarations SHOULD NOT be sent after the FinalInterest; /// - UndeclareInterest SHOULD NOT be sent after the FinalInterest. @@ -721,7 +789,7 @@ pub mod interest { /// /// 7 6 5 4 3 2 1 0 /// +-+-+-+-+-+-+-+-+ - /// |Z|F|C| D_INT | + /// |Z|F|X| D_INT | /// +---------------+ /// ~ intst_id:z32 ~ /// +---------------+ @@ -754,9 +822,6 @@ pub mod interest { impl DeclareInterest { pub fn flags(&self) -> u8 { let mut interest = self.interest; - if self.interest.current() { - interest += Interest::CURRENT; - } if self.interest.future() { interest += Interest::FUTURE; } @@ -802,7 +867,6 @@ pub mod interest { impl Interest { // Header - pub const CURRENT: Interest = Interest::flags(interest::flag::C); pub const FUTURE: Interest = Interest::flags(interest::flag::F); // Flags pub const KEYEXPRS: Interest = Interest::options(1); @@ -835,10 +899,6 @@ pub mod interest { } } - pub const fn current(&self) -> bool { - imsg::has_flag(self.flags, Self::CURRENT.flags) - } - pub const fn future(&self) -> bool { imsg::has_flag(self.flags, Self::FUTURE.flags) } @@ -881,9 +941,6 @@ pub mod interest { let mut rng = rand::thread_rng(); let mut s = Self::empty(); - if rng.gen_bool(0.5) { - s += Interest::CURRENT; - } if rng.gen_bool(0.5) { s += Interest::FUTURE; } @@ -905,8 +962,7 @@ pub mod interest { impl PartialEq for Interest { fn eq(&self, other: &Self) -> bool { - self.current() == other.current() - && self.future() == other.future() + self.future() == other.future() && self.keyexprs() == other.keyexprs() && self.subscribers() == other.subscribers() && self.queryables() == other.queryables() @@ -918,11 +974,6 @@ pub mod interest { impl Debug for Interest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Interest {{ ")?; - if self.current() { - write!(f, "C:Y, ")?; - } else { - write!(f, "C:N, ")?; - } if self.future() { write!(f, "F:Y, ")?; } else { @@ -1003,38 +1054,6 @@ pub mod interest { } } - /// ```text - /// Flags: - /// - X: Reserved - /// - X: Reserved - /// - Z: Extension If Z==1 then at least one extension is present - /// - /// 7 6 5 4 3 2 1 0 - /// +-+-+-+-+-+-+-+-+ - /// |Z|X|X| F_INT | - /// +---------------+ - /// ~ intst_id:z32 ~ - /// +---------------+ - /// ~ [decl_exts] ~ if Z==1 - /// +---------------+ - /// ``` - #[derive(Debug, Clone, PartialEq, Eq)] - pub struct FinalInterest { - pub id: InterestId, - } - - impl FinalInterest { - #[cfg(feature = "test")] - pub fn rand() -> Self { - use rand::Rng; - let mut rng = rand::thread_rng(); - - let id: InterestId = rng.gen(); - - Self { id } - } - } - /// ```text /// Flags: /// - X: Reserved diff --git a/commons/zenoh-protocol/src/network/mod.rs b/commons/zenoh-protocol/src/network/mod.rs index 0e198ddf0f..cbf9894aef 100644 --- a/commons/zenoh-protocol/src/network/mod.rs +++ b/commons/zenoh-protocol/src/network/mod.rs @@ -20,9 +20,9 @@ pub mod response; use core::fmt; pub use declare::{ - Declare, DeclareBody, DeclareInterest, DeclareKeyExpr, DeclareQueryable, DeclareSubscriber, - DeclareToken, UndeclareInterest, UndeclareKeyExpr, UndeclareQueryable, UndeclareSubscriber, - UndeclareToken, + Declare, DeclareBody, DeclareFinal, DeclareInterest, DeclareKeyExpr, DeclareMode, + DeclareQueryable, DeclareSubscriber, DeclareToken, UndeclareInterest, UndeclareKeyExpr, + UndeclareQueryable, UndeclareSubscriber, UndeclareToken, }; pub use oam::Oam; pub use push::Push; diff --git a/zenoh/src/key_expr.rs b/zenoh/src/key_expr.rs index aaa1d13724..17aa0425b6 100644 --- a/zenoh/src/key_expr.rs +++ b/zenoh/src/key_expr.rs @@ -53,7 +53,7 @@ pub use zenoh_keyexpr::*; pub use zenoh_macros::{kedefine, keformat, kewrite}; use zenoh_protocol::{ core::{key_expr::canon::Canonizable, ExprId, WireExpr}, - network::{declare, DeclareBody, Mapping, UndeclareKeyExpr}, + network::{declare, DeclareBody, DeclareMode, Mapping, UndeclareKeyExpr}, }; use zenoh_result::ZResult; @@ -664,7 +664,7 @@ impl SyncResolve for KeyExprUndeclaration<'_> { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(zenoh_protocol::network::Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/dispatcher/face.rs b/zenoh/src/net/routing/dispatcher/face.rs index cb565053c9..c5dc54faf7 100644 --- a/zenoh/src/net/routing/dispatcher/face.rs +++ b/zenoh/src/net/routing/dispatcher/face.rs @@ -211,8 +211,8 @@ impl Primitives for Face { zenoh_protocol::network::DeclareBody::DeclareToken(_m) => todo!(), zenoh_protocol::network::DeclareBody::UndeclareToken(_m) => todo!(), zenoh_protocol::network::DeclareBody::DeclareInterest(_m) => todo!(), - zenoh_protocol::network::DeclareBody::FinalInterest(_m) => todo!(), zenoh_protocol::network::DeclareBody::UndeclareInterest(_m) => todo!(), + zenoh_protocol::network::DeclareBody::DeclareFinal(_m) => todo!(), } drop(ctrl_lock); } diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index 194b97fca8..941b37f916 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -27,7 +27,7 @@ use zenoh_protocol::{ network::{ declare::{ ext, queryable::ext::QueryableInfoType, subscriber::ext::SubscriberInfo, Declare, - DeclareBody, DeclareKeyExpr, + DeclareBody, DeclareKeyExpr, DeclareMode, }, Mapping, }, @@ -452,7 +452,7 @@ impl Resource { .insert(expr_id, nonwild_prefix.clone()); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index e85bb77bf9..6c689d3336 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -30,7 +30,7 @@ use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ common::ext::WireExprType, ext, subscriber::ext::SubscriberInfo, Declare, DeclareBody, - DeclareSubscriber, UndeclareSubscriber, + DeclareMode, DeclareSubscriber, UndeclareSubscriber, }, }; use zenoh_sync::get_mut_unchecked; @@ -53,7 +53,7 @@ fn propagate_simple_subscription_to( let key_expr = Resource::decl_key(res, dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -137,7 +137,7 @@ fn declare_client_subscription( .primitives .send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -171,7 +171,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -206,7 +206,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index 5c0bc5349b..28e1d75460 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -33,7 +33,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareQueryable, UndeclareQueryable, + DeclareMode, DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -93,7 +93,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -165,7 +165,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -418,7 +418,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -460,7 +460,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index 150c12a632..356793e3a3 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -36,7 +36,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr, ZenohId}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareQueryable, UndeclareQueryable, + DeclareMode, DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -126,7 +126,7 @@ fn send_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -170,7 +170,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -339,7 +339,7 @@ fn send_forget_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -365,7 +365,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index b495248788..5ac0b22846 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -30,7 +30,7 @@ use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ common::ext::WireExprType, ext, subscriber::ext::SubscriberInfo, Declare, DeclareBody, - DeclareSubscriber, UndeclareSubscriber, + DeclareMode, DeclareSubscriber, UndeclareSubscriber, }, }; use zenoh_sync::get_mut_unchecked; @@ -53,7 +53,7 @@ fn propagate_simple_subscription_to( let key_expr = Resource::decl_key(res, dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -137,7 +137,7 @@ fn declare_client_subscription( .primitives .send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -171,7 +171,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -206,7 +206,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index 72c32b9217..c2d62c7658 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -33,7 +33,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareQueryable, UndeclareQueryable, + DeclareMode, DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -93,7 +93,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -165,7 +165,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -412,7 +412,7 @@ fn propagate_forget_simple_subscription_to_peers(tables: &mut Tables, res: &Arc< if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -564,7 +564,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -606,7 +606,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -635,7 +635,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -774,7 +774,7 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: if forget { dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -800,7 +800,7 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: }; dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index 99e787beb5..e647cf2dc7 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -36,7 +36,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr, ZenohId}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareQueryable, UndeclareQueryable, + DeclareMode, DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -194,7 +194,7 @@ fn send_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -248,7 +248,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -473,7 +473,7 @@ fn send_forget_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -499,7 +499,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -775,7 +775,7 @@ pub(super) fn queries_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -874,7 +874,7 @@ pub(super) fn queries_linkstate_change(tables: &mut Tables, zid: &ZenohId, links if forget { dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -900,7 +900,7 @@ pub(super) fn queries_linkstate_change(tables: &mut Tables, zid: &ZenohId, links let key_expr = Resource::decl_key(res, dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/mod.rs b/zenoh/src/net/routing/mod.rs index 0ddf12b82f..28c4a33b0b 100644 --- a/zenoh/src/net/routing/mod.rs +++ b/zenoh/src/net/routing/mod.rs @@ -117,8 +117,8 @@ impl RoutingContext { DeclareBody::DeclareToken(m) => Some(&m.wire_expr), DeclareBody::UndeclareToken(m) => Some(&m.ext_wire_expr.wire_expr), DeclareBody::DeclareInterest(m) => m.wire_expr.as_ref(), - DeclareBody::FinalInterest(_) => None, DeclareBody::UndeclareInterest(m) => Some(&m.ext_wire_expr.wire_expr), + DeclareBody::DeclareFinal(_) => None, }, NetworkBody::OAM(_) => None, } diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index d460ee3f1c..a5739d830c 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -39,8 +39,8 @@ use zenoh_protocol::{ }, network::{ declare::{queryable::ext::QueryableInfoType, subscriber::ext::SubscriberInfo}, - ext, Declare, DeclareBody, DeclareQueryable, DeclareSubscriber, Push, Request, Response, - ResponseFinal, + ext, Declare, DeclareBody, DeclareMode, DeclareQueryable, DeclareSubscriber, Push, Request, + Response, ResponseFinal, }, zenoh::{PushBody, RequestBody}, }; @@ -276,7 +276,7 @@ impl AdminSpace { zlock!(admin.primitives).replace(primitives.clone()); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, @@ -289,7 +289,7 @@ impl AdminSpace { }); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/tests/tables.rs b/zenoh/src/net/tests/tables.rs index 4067f2ad8f..55ff9f0a4d 100644 --- a/zenoh/src/net/tests/tables.rs +++ b/zenoh/src/net/tests/tables.rs @@ -26,7 +26,7 @@ use zenoh_protocol::core::{ key_expr::keyexpr, ExprId, Reliability, WhatAmI, WireExpr, ZenohId, EMPTY_EXPR_ID, }; use zenoh_protocol::network::declare::subscriber::ext::SubscriberInfo; -use zenoh_protocol::network::{ext, Declare, DeclareBody, DeclareKeyExpr}; +use zenoh_protocol::network::{ext, Declare, DeclareBody, DeclareKeyExpr, DeclareMode}; use zenoh_protocol::zenoh::{PushBody, Put}; #[test] @@ -579,7 +579,7 @@ fn client_test() { Primitives::send_declare( primitives0.as_ref(), Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -607,7 +607,7 @@ fn client_test() { Primitives::send_declare( primitives0.as_ref(), Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -629,7 +629,7 @@ fn client_test() { Primitives::send_declare( primitives1.as_ref(), Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -657,7 +657,7 @@ fn client_test() { Primitives::send_declare( primitives1.as_ref(), Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -679,7 +679,7 @@ fn client_test() { Primitives::send_declare( primitives2.as_ref(), Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index addb757807..5d615db93e 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -71,7 +71,7 @@ use zenoh_protocol::{ network::{ declare::{ self, common::ext::WireExprType, queryable::ext::QueryableInfoType, - subscriber::ext::SubscriberInfo, Declare, DeclareBody, DeclareKeyExpr, + subscriber::ext::SubscriberInfo, Declare, DeclareBody, DeclareKeyExpr, DeclareMode, DeclareQueryable, DeclareSubscriber, UndeclareQueryable, UndeclareSubscriber, }, ext, @@ -872,7 +872,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1085,7 +1085,7 @@ impl Session { // }; primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1142,7 +1142,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1194,7 +1194,7 @@ impl Session { distance: 0, }; primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1216,7 +1216,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1252,7 +1252,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1277,7 +1277,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - interest_id: None, + mode: DeclareMode::Push, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -2047,7 +2047,7 @@ impl Primitives for Session { DeclareBody::DeclareToken(_) => todo!(), DeclareBody::UndeclareToken(_) => todo!(), DeclareBody::DeclareInterest(_) => todo!(), - DeclareBody::FinalInterest(_) => todo!(), + DeclareBody::DeclareFinal(_) => todo!(), DeclareBody::UndeclareInterest(_) => todo!(), } } From 43a61c7207369f47313d1b3e6ffdda3a121705f7 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Thu, 4 Apr 2024 17:56:05 +0200 Subject: [PATCH 13/30] Address review comments --- commons/zenoh-codec/src/network/declare.rs | 89 ++----------------- commons/zenoh-protocol/src/network/declare.rs | 22 ++--- zenoh/src/net/routing/dispatcher/face.rs | 1 - zenoh/src/net/routing/mod.rs | 1 - zenoh/src/session.rs | 1 - 5 files changed, 15 insertions(+), 99 deletions(-) diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index bad03cc5ae..e64d680844 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -52,7 +52,6 @@ where DeclareBody::DeclareToken(r) => self.write(&mut *writer, r)?, DeclareBody::UndeclareToken(r) => self.write(&mut *writer, r)?, DeclareBody::DeclareInterest(r) => self.write(&mut *writer, r)?, - DeclareBody::UndeclareInterest(r) => self.write(&mut *writer, r)?, DeclareBody::DeclareFinal(r) => self.write(&mut *writer, r)?, } @@ -81,7 +80,6 @@ where D_TOKEN => DeclareBody::DeclareToken(codec.read(&mut *reader)?), U_TOKEN => DeclareBody::UndeclareToken(codec.read(&mut *reader)?), D_INTEREST => DeclareBody::DeclareInterest(codec.read(&mut *reader)?), - U_INTEREST => DeclareBody::UndeclareInterest(codec.read(&mut *reader)?), D_FINAL => DeclareBody::DeclareFinal(codec.read(&mut *reader)?), _ => return Err(DidntRead), }; @@ -110,9 +108,9 @@ where let mut header = id::DECLARE; header |= match mode { DeclareMode::Push => 0b00, - DeclareMode::Request(_) => 0b01, - DeclareMode::RequestContinuous(_) => 0b10, - DeclareMode::Response(_) => 0b11, + DeclareMode::Response(_) => 0b01, + DeclareMode::Request(_) => 0b10, + DeclareMode::RequestContinuous(_) => 0b11, } << HEADER_BITS; let mut n_exts = ((ext_qos != &declare::ext::QoSType::DEFAULT) as u8) @@ -180,9 +178,9 @@ where // Body let mode = match (self.header >> HEADER_BITS) & 0b11 { 0b00 => DeclareMode::Push, - 0b01 => DeclareMode::Request(self.codec.read(&mut *reader)?), - 0b10 => DeclareMode::RequestContinuous(self.codec.read(&mut *reader)?), - 0b11 => DeclareMode::Response(self.codec.read(&mut *reader)?), + 0b01 => DeclareMode::Response(self.codec.read(&mut *reader)?), + 0b10 => DeclareMode::Request(self.codec.read(&mut *reader)?), + 0b11 => DeclareMode::RequestContinuous(self.codec.read(&mut *reader)?), _ => return Err(DidntRead), }; @@ -1044,81 +1042,6 @@ where } } -// UndeclareInterest -impl WCodec<&interest::UndeclareInterest, &mut W> for Zenoh080 -where - W: Writer, -{ - type Output = Result<(), DidntWrite>; - - fn write(self, writer: &mut W, x: &interest::UndeclareInterest) -> Self::Output { - let interest::UndeclareInterest { id, ext_wire_expr } = x; - - // Header - let header = declare::id::U_INTEREST | interest::flag::Z; - self.write(&mut *writer, header)?; - - // Body - self.write(&mut *writer, id)?; - - // Extension - self.write(&mut *writer, (ext_wire_expr, false))?; - - Ok(()) - } -} - -impl RCodec for Zenoh080 -where - R: Reader, -{ - type Error = DidntRead; - - fn read(self, reader: &mut R) -> Result { - let header: u8 = self.read(&mut *reader)?; - let codec = Zenoh080Header::new(header); - - codec.read(reader) - } -} - -impl RCodec for Zenoh080Header -where - R: Reader, -{ - type Error = DidntRead; - - fn read(self, reader: &mut R) -> Result { - if imsg::mid(self.header) != declare::id::U_INTEREST { - return Err(DidntRead); - } - - // Body - let id: interest::InterestId = self.codec.read(&mut *reader)?; - - // Extensions - let mut ext_wire_expr = common::ext::WireExprType::null(); - - let mut has_ext = imsg::has_flag(self.header, interest::flag::Z); - while has_ext { - let ext: u8 = self.codec.read(&mut *reader)?; - let eodec = Zenoh080Header::new(ext); - match iext::eid(ext) { - common::ext::WireExprExt::ID => { - let (we, ext): (common::ext::WireExprType, bool) = eodec.read(&mut *reader)?; - ext_wire_expr = we; - has_ext = ext; - } - _ => { - has_ext = extension::skip(reader, "UndeclareInterest", ext)?; - } - } - } - - Ok(interest::UndeclareInterest { id, ext_wire_expr }) - } -} - // WARNING: this is a temporary extension used for undeclarations impl WCodec<(&common::ext::WireExprType, bool), &mut W> for Zenoh080 where diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index b8f302b0f3..7b8a1e2d07 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -50,9 +50,9 @@ pub mod flag { /// /// *Mode of declaration: /// - Mode 0b00: Push -/// - Mode 0b01: Request -/// - Mode 0b10: RequestContinuous -/// - Mode 0b11: Response +/// - Mode 0b01: Response +/// - Mode 0b10: Request +/// - Mode 0b11: RequestContinuous /// The resolution of a RequestId pub type DeclareRequestId = u32; @@ -122,7 +122,6 @@ pub mod id { pub const U_TOKEN: u8 = 0x07; pub const D_INTEREST: u8 = 0x08; - pub const U_INTEREST: u8 = 0x09; pub const D_FINAL: u8 = 0x1A; } @@ -138,7 +137,6 @@ pub enum DeclareBody { DeclareToken(DeclareToken), UndeclareToken(UndeclareToken), DeclareInterest(DeclareInterest), - UndeclareInterest(UndeclareInterest), DeclareFinal(DeclareFinal), } @@ -149,7 +147,7 @@ impl DeclareBody { let mut rng = rand::thread_rng(); - match rng.gen_range(0..11) { + match rng.gen_range(0..10) { 0 => DeclareBody::DeclareKeyExpr(DeclareKeyExpr::rand()), 1 => DeclareBody::UndeclareKeyExpr(UndeclareKeyExpr::rand()), 2 => DeclareBody::DeclareSubscriber(DeclareSubscriber::rand()), @@ -159,8 +157,7 @@ impl DeclareBody { 6 => DeclareBody::DeclareToken(DeclareToken::rand()), 7 => DeclareBody::UndeclareToken(UndeclareToken::rand()), 8 => DeclareBody::DeclareInterest(DeclareInterest::rand()), - 9 => DeclareBody::UndeclareInterest(UndeclareInterest::rand()), - 10 => DeclareBody::DeclareFinal(DeclareFinal::rand()), + 9 => DeclareBody::DeclareFinal(DeclareFinal::rand()), _ => unreachable!(), } } @@ -746,7 +743,7 @@ pub mod interest { /// - RequestContinous: current and future declarations /// - Response: invalid /// - /// E.g., the [`DeclareInterest`]/[`UndeclareInterest`] message flow is the following: + /// E.g., the [`DeclareInterest`] message flow is the following: /// /// ```text /// A B @@ -771,9 +768,9 @@ pub mod interest { /// | | /// | ... | /// | | - /// | UNDECL INTEREST | + /// | FINAL | /// |------------------>| -- Sent in Declare::RequestContinuous. - /// | | This is an UndeclareInterest to stop receiving subscriber declarations/undeclarations. + /// | | This stops the transmission of subscriber declarations/undeclarations. /// | | /// ``` /// @@ -783,8 +780,7 @@ pub mod interest { /// Flags: /// - X: Reserved /// - F: Future if F==1 then the interest refers to the future declarations. Note that if F==0 then: - /// - Declarations SHOULD NOT be sent after the FinalInterest; - /// - UndeclareInterest SHOULD NOT be sent after the FinalInterest. + /// - Declarations SHOULD NOT be sent after the Final; /// - Z: Extension If Z==1 then at least one extension is present /// /// 7 6 5 4 3 2 1 0 diff --git a/zenoh/src/net/routing/dispatcher/face.rs b/zenoh/src/net/routing/dispatcher/face.rs index c5dc54faf7..3531dd2d88 100644 --- a/zenoh/src/net/routing/dispatcher/face.rs +++ b/zenoh/src/net/routing/dispatcher/face.rs @@ -211,7 +211,6 @@ impl Primitives for Face { zenoh_protocol::network::DeclareBody::DeclareToken(_m) => todo!(), zenoh_protocol::network::DeclareBody::UndeclareToken(_m) => todo!(), zenoh_protocol::network::DeclareBody::DeclareInterest(_m) => todo!(), - zenoh_protocol::network::DeclareBody::UndeclareInterest(_m) => todo!(), zenoh_protocol::network::DeclareBody::DeclareFinal(_m) => todo!(), } drop(ctrl_lock); diff --git a/zenoh/src/net/routing/mod.rs b/zenoh/src/net/routing/mod.rs index 28c4a33b0b..77f51c16b3 100644 --- a/zenoh/src/net/routing/mod.rs +++ b/zenoh/src/net/routing/mod.rs @@ -117,7 +117,6 @@ impl RoutingContext { DeclareBody::DeclareToken(m) => Some(&m.wire_expr), DeclareBody::UndeclareToken(m) => Some(&m.ext_wire_expr.wire_expr), DeclareBody::DeclareInterest(m) => m.wire_expr.as_ref(), - DeclareBody::UndeclareInterest(m) => Some(&m.ext_wire_expr.wire_expr), DeclareBody::DeclareFinal(_) => None, }, NetworkBody::OAM(_) => None, diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 5d615db93e..9bc6c9c331 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -2048,7 +2048,6 @@ impl Primitives for Session { DeclareBody::UndeclareToken(_) => todo!(), DeclareBody::DeclareInterest(_) => todo!(), DeclareBody::DeclareFinal(_) => todo!(), - DeclareBody::UndeclareInterest(_) => todo!(), } } From bce88557110cf2d8abf005f2f68e9cd519bc4598 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 5 Apr 2024 10:05:26 +0200 Subject: [PATCH 14/30] Remove F: Future flag from DeclareInterest --- commons/zenoh-codec/src/network/declare.rs | 2 +- commons/zenoh-protocol/src/network/declare.rs | 34 ++----------------- 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index e64d680844..173fbe5e4a 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -973,7 +973,7 @@ where } = x; // Header - let header = declare::id::D_INTEREST | x.flags(); + let header = declare::id::D_INTEREST; self.write(&mut *writer, header)?; // Body diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 7b8a1e2d07..3ec43729d9 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -727,7 +727,7 @@ pub mod interest { pub mod flag { // pub const X: u8 = 1 << 5; // 0x20 Reserved - pub const F: u8 = 1 << 6; // 0x40 Future if F==1 then the interest refers to the future declarations. + // pub const X: u8 = 1 << 6; // 0x40 Reserved pub const Z: u8 = 1 << 7; // 0x80 Extensions if Z==1 then an extension will follow } @@ -779,8 +779,7 @@ pub mod interest { /// ```text /// Flags: /// - X: Reserved - /// - F: Future if F==1 then the interest refers to the future declarations. Note that if F==0 then: - /// - Declarations SHOULD NOT be sent after the Final; + /// - X: Reserved /// - Z: Extension If Z==1 then at least one extension is present /// /// 7 6 5 4 3 2 1 0 @@ -816,14 +815,6 @@ pub mod interest { } impl DeclareInterest { - pub fn flags(&self) -> u8 { - let mut interest = self.interest; - if self.interest.future() { - interest += Interest::FUTURE; - } - interest.flags - } - pub fn options(&self) -> u8 { let mut interest = self.interest; if let Some(we) = self.wire_expr.as_ref() { @@ -862,8 +853,6 @@ pub mod interest { } impl Interest { - // Header - pub const FUTURE: Interest = Interest::flags(interest::flag::F); // Flags pub const KEYEXPRS: Interest = Interest::options(1); pub const SUBSCRIBERS: Interest = Interest::options(1 << 1); @@ -880,10 +869,6 @@ pub mod interest { | Interest::TOKENS.options, ); - const fn flags(flags: u8) -> Self { - Self { flags, options: 0 } - } - const fn options(options: u8) -> Self { Self { flags: 0, options } } @@ -895,10 +880,6 @@ pub mod interest { } } - pub const fn future(&self) -> bool { - imsg::has_flag(self.flags, Self::FUTURE.flags) - } - pub const fn keyexprs(&self) -> bool { imsg::has_flag(self.options, Self::KEYEXPRS.options) } @@ -937,9 +918,6 @@ pub mod interest { let mut rng = rand::thread_rng(); let mut s = Self::empty(); - if rng.gen_bool(0.5) { - s += Interest::FUTURE; - } if rng.gen_bool(0.5) { s += Interest::KEYEXPRS; } @@ -958,8 +936,7 @@ pub mod interest { impl PartialEq for Interest { fn eq(&self, other: &Self) -> bool { - self.future() == other.future() - && self.keyexprs() == other.keyexprs() + self.keyexprs() == other.keyexprs() && self.subscribers() == other.subscribers() && self.queryables() == other.queryables() && self.tokens() == other.tokens() @@ -970,11 +947,6 @@ pub mod interest { impl Debug for Interest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Interest {{ ")?; - if self.future() { - write!(f, "F:Y, ")?; - } else { - write!(f, "F:N, ")?; - } if self.keyexprs() { write!(f, "K:Y, ")?; } else { From 3da2aed23953466eee87a7d0df807b026e280f26 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 5 Apr 2024 10:06:17 +0200 Subject: [PATCH 15/30] cargo fmt --all --- commons/zenoh-protocol/src/network/declare.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 3ec43729d9..996e7768ee 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -936,7 +936,7 @@ pub mod interest { impl PartialEq for Interest { fn eq(&self, other: &Self) -> bool { - self.keyexprs() == other.keyexprs() + self.keyexprs() == other.keyexprs() && self.subscribers() == other.subscribers() && self.queryables() == other.queryables() && self.tokens() == other.tokens() From c753e82c52cee552e474376b439ff050ae5308fe Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 5 Apr 2024 12:13:33 +0200 Subject: [PATCH 16/30] Remove unused Interest flags field --- commons/zenoh-codec/src/network/declare.rs | 2 +- commons/zenoh-protocol/src/network/declare.rs | 21 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index 173fbe5e4a..5682120b22 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -1014,7 +1014,7 @@ where // Body let id: interest::InterestId = self.codec.read(&mut *reader)?; let options: u8 = self.codec.read(&mut *reader)?; - let interest = Interest::from((imsg::flags(self.header), options)); + let interest = Interest::from(options); let mut wire_expr = None; if interest.restricted() { diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 996e7768ee..ef5b6afbeb 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -848,7 +848,6 @@ pub mod interest { #[derive(Clone, Copy)] pub struct Interest { - flags: u8, options: u8, } @@ -870,14 +869,11 @@ pub mod interest { ); const fn options(options: u8) -> Self { - Self { flags: 0, options } + Self { options } } pub const fn empty() -> Self { - Self { - flags: 0, - options: 0, - } + Self { options: 0 } } pub const fn keyexprs(&self) -> bool { @@ -982,17 +978,17 @@ pub mod interest { impl Add for Interest { type Output = Self; + #[allow(clippy::suspicious_arithmetic_impl)] // Allows to implement Add & Sub for Interest fn add(self, rhs: Self) -> Self::Output { Self { - flags: self.flags | rhs.flags, options: self.options | rhs.options, } } } impl AddAssign for Interest { + #[allow(clippy::suspicious_op_assign_impl)] // Allows to implement Add & Sub for Interest fn add_assign(&mut self, rhs: Self) { - self.flags |= rhs.flags; self.options |= rhs.options; } } @@ -1002,7 +998,6 @@ pub mod interest { fn sub(self, rhs: Self) -> Self::Output { Self { - flags: self.flags & !rhs.flags, options: self.options & !rhs.options, } } @@ -1010,15 +1005,13 @@ pub mod interest { impl SubAssign for Interest { fn sub_assign(&mut self, rhs: Self) { - self.flags &= !rhs.flags; self.options &= !rhs.options; } } - impl From<(u8, u8)> for Interest { - fn from(value: (u8, u8)) -> Self { - let (flags, options) = value; - Self { flags, options } + impl From for Interest { + fn from(options: u8) -> Self { + Self { options } } } From 52ff7d0661893a7be7e49ef7f01d103e73f0ff49 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 5 Apr 2024 12:18:28 +0200 Subject: [PATCH 17/30] Update doc --- commons/zenoh-protocol/src/network/declare.rs | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index ef5b6afbeb..8089c51983 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -733,23 +733,23 @@ pub mod interest { /// # DeclareInterest message /// - /// The DECLARE INTEREST message is sent to request the transmission of current and/or future + /// The DECLARE INTEREST message is sent to request the transmission of current and optionally future /// declarations of a given kind matching a target keyexpr. E.g., a declare interest could be /// sent to request the transmisison of all current subscriptions matching `a/*`. /// /// The behaviour of a DECLARE INTEREST depends on the DECLARE MODE in the DECLARE MESSAGE: - /// - Push: only future declarations + /// - Push: invalid /// - Request: only current declarations /// - RequestContinous: current and future declarations /// - Response: invalid /// - /// E.g., the [`DeclareInterest`] message flow is the following: + /// E.g., the [`DeclareInterest`] message flow is the following for a Request: /// /// ```text /// A B /// | DECL INTEREST | - /// |------------------>| -- Sent in Declare::RequestContinuous. - /// | | This is a DeclareInterest e.g. for subscriber declarations/undeclarations. + /// |------------------>| -- Sent in Declare::Request. + /// | | This is a DeclareInterest e.g. for subscriber declarations. /// | | /// | DECL SUBSCRIBER | /// |<------------------| -- Sent in Declare::Response @@ -760,6 +760,26 @@ pub mod interest { /// | | /// | FINAL | /// |<------------------| -- Sent in Declare::Response + /// ``` + /// + /// + /// And the [`DeclareInterest`] message flow is the following for a ContinuousRequest: + /// + /// ```text + /// A B + /// | DECL INTEREST | + /// |------------------>| -- Sent in Declare::RequestContinuous. + /// | | This is a DeclareInterest e.g. for subscriber declarations/undeclarations. + /// | | + /// | DECL SUBSCRIBER | + /// |<------------------| -- Sent in Declare::Push + /// | DECL SUBSCRIBER | + /// |<------------------| -- Sent in Declare::Push + /// | DECL SUBSCRIBER | + /// |<------------------| -- Sent in Declare::Push + /// | | + /// | FINAL | + /// |<------------------| -- Sent in Declare::Response /// | | /// | DECL SUBSCRIBER | /// |<------------------| -- Sent in Declare::Push. This is a new subscriber declaration. @@ -784,7 +804,7 @@ pub mod interest { /// /// 7 6 5 4 3 2 1 0 /// +-+-+-+-+-+-+-+-+ - /// |Z|F|X| D_INT | + /// |Z|X|X| D_INT | /// +---------------+ /// ~ intst_id:z32 ~ /// +---------------+ From 8c9abc1023040fc6f0a14921ea3c28bfb9a20a61 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 5 Apr 2024 12:21:28 +0200 Subject: [PATCH 18/30] Remove unneeded interest_id field --- commons/zenoh-codec/src/network/declare.rs | 4 ---- commons/zenoh-protocol/src/network/declare.rs | 5 ----- 2 files changed, 9 deletions(-) diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index 5682120b22..6e9dad12ce 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -967,7 +967,6 @@ where fn write(self, writer: &mut W, x: &interest::DeclareInterest) -> Self::Output { let interest::DeclareInterest { - id, interest: _, wire_expr, } = x; @@ -977,7 +976,6 @@ where self.write(&mut *writer, header)?; // Body - self.write(&mut *writer, id)?; self.write(&mut *writer, x.options())?; if let Some(we) = wire_expr.as_ref() { self.write(&mut *writer, we)?; @@ -1012,7 +1010,6 @@ where } // Body - let id: interest::InterestId = self.codec.read(&mut *reader)?; let options: u8 = self.codec.read(&mut *reader)?; let interest = Interest::from(options); @@ -1035,7 +1032,6 @@ where } Ok(interest::DeclareInterest { - id, interest, wire_expr, }) diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 8089c51983..4e28804e47 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -806,8 +806,6 @@ pub mod interest { /// +-+-+-+-+-+-+-+-+ /// |Z|X|X| D_INT | /// +---------------+ - /// ~ intst_id:z32 ~ - /// +---------------+ /// |A|M|N|R|T|Q|S|K| (*) /// +---------------+ /// ~ key_scope:z16 ~ if R==1 @@ -829,7 +827,6 @@ pub mod interest { /// ``` #[derive(Debug, Clone, PartialEq, Eq)] pub struct DeclareInterest { - pub id: InterestId, pub interest: Interest, pub wire_expr: Option>, } @@ -854,12 +851,10 @@ pub mod interest { use rand::Rng; let mut rng = rand::thread_rng(); - let id: InterestId = rng.gen(); let wire_expr = rng.gen_bool(0.5).then_some(WireExpr::rand()); let interest = Interest::rand(); Self { - id, wire_expr, interest, } From 9aa20797b08cd079f1c103286d76a9345ed5ea38 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 5 Apr 2024 12:47:13 +0200 Subject: [PATCH 19/30] Update commons/zenoh-protocol/src/network/declare.rs --- commons/zenoh-protocol/src/network/declare.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 4e28804e47..6cd2b2200f 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -763,7 +763,7 @@ pub mod interest { /// ``` /// /// - /// And the [`DeclareInterest`] message flow is the following for a ContinuousRequest: + /// And the [`DeclareInterest`] message flow is the following for a RequestContinuous: /// /// ```text /// A B From dd2ef808fe8521bf4aba6ef406863a07ec2196a4 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 5 Apr 2024 15:03:12 +0200 Subject: [PATCH 20/30] Remove unused UndeclareInterest --- commons/zenoh-protocol/src/network/declare.rs | 34 ------------------- commons/zenoh-protocol/src/network/mod.rs | 4 +-- 2 files changed, 2 insertions(+), 36 deletions(-) diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 6cd2b2200f..31e8adcc6e 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -1029,38 +1029,4 @@ pub mod interest { Self { options } } } - - /// ```text - /// Flags: - /// - X: Reserved - /// - X: Reserved - /// - Z: Extension If Z==1 then at least one extension is present - /// - /// 7 6 5 4 3 2 1 0 - /// +-+-+-+-+-+-+-+-+ - /// |Z|X|X| U_INT | - /// +---------------+ - /// ~ intst_id:z32 ~ - /// +---------------+ - /// ~ [decl_exts] ~ if Z==1 - /// +---------------+ - /// ``` - #[derive(Debug, Clone, PartialEq, Eq)] - pub struct UndeclareInterest { - pub id: InterestId, - pub ext_wire_expr: common::ext::WireExprType, - } - - impl UndeclareInterest { - #[cfg(feature = "test")] - pub fn rand() -> Self { - use rand::Rng; - let mut rng = rand::thread_rng(); - - let id: InterestId = rng.gen(); - let ext_wire_expr = common::ext::WireExprType::rand(); - - Self { id, ext_wire_expr } - } - } } diff --git a/commons/zenoh-protocol/src/network/mod.rs b/commons/zenoh-protocol/src/network/mod.rs index cbf9894aef..e60388f425 100644 --- a/commons/zenoh-protocol/src/network/mod.rs +++ b/commons/zenoh-protocol/src/network/mod.rs @@ -21,8 +21,8 @@ use core::fmt; pub use declare::{ Declare, DeclareBody, DeclareFinal, DeclareInterest, DeclareKeyExpr, DeclareMode, - DeclareQueryable, DeclareSubscriber, DeclareToken, UndeclareInterest, UndeclareKeyExpr, - UndeclareQueryable, UndeclareSubscriber, UndeclareToken, + DeclareQueryable, DeclareSubscriber, DeclareToken, UndeclareKeyExpr, UndeclareQueryable, + UndeclareSubscriber, UndeclareToken, }; pub use oam::Oam; pub use push::Push; From 7f55917d3001d89c2e6d14ff078266f06d59ffcb Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 5 Apr 2024 17:02:21 +0200 Subject: [PATCH 21/30] Implement proper Declare Request/Response id correlation --- commons/zenoh-protocol/src/network/declare.rs | 2 +- zenoh/src/net/routing/dispatcher/pubsub.rs | 6 +- zenoh/src/net/routing/dispatcher/queries.rs | 6 +- zenoh/src/net/routing/hat/client/pubsub.rs | 4 +- zenoh/src/net/routing/hat/client/queries.rs | 2 +- .../net/routing/hat/linkstate_peer/pubsub.rs | 42 ++++++++++---- .../net/routing/hat/linkstate_peer/queries.rs | 54 ++++++++++++------ zenoh/src/net/routing/hat/mod.rs | 4 +- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 43 +++++++++++---- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 55 +++++++++++++------ zenoh/src/net/routing/hat/router/pubsub.rs | 42 ++++++++++---- zenoh/src/net/routing/hat/router/queries.rs | 54 ++++++++++++------ 12 files changed, 218 insertions(+), 96 deletions(-) diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index afa632e941..87b9d8e0e6 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -58,7 +58,7 @@ pub mod flag { pub type DeclareRequestId = u32; pub type AtomicDeclareRequestId = AtomicU32; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DeclareMode { Push, Request(DeclareRequestId), diff --git a/zenoh/src/net/routing/dispatcher/pubsub.rs b/zenoh/src/net/routing/dispatcher/pubsub.rs index 81bc1d2a8e..2c1c51ff05 100644 --- a/zenoh/src/net/routing/dispatcher/pubsub.rs +++ b/zenoh/src/net/routing/dispatcher/pubsub.rs @@ -35,7 +35,7 @@ pub(crate) fn declare_sub_interest( face: &mut Arc, id: InterestId, expr: Option<&WireExpr>, - future: bool, + continuous: bool, aggregate: bool, ) { if let Some(expr) = expr { @@ -81,7 +81,7 @@ pub(crate) fn declare_sub_interest( face, id, Some(&mut res), - future, + continuous, aggregate, ); } @@ -94,7 +94,7 @@ pub(crate) fn declare_sub_interest( } } else { let mut wtables = zwrite!(tables.tables); - hat_code.declare_sub_interest(&mut wtables, face, id, None, future, aggregate); + hat_code.declare_sub_interest(&mut wtables, face, id, None, continuous, aggregate); } } diff --git a/zenoh/src/net/routing/dispatcher/queries.rs b/zenoh/src/net/routing/dispatcher/queries.rs index 586088ecf1..57481fbe26 100644 --- a/zenoh/src/net/routing/dispatcher/queries.rs +++ b/zenoh/src/net/routing/dispatcher/queries.rs @@ -41,7 +41,7 @@ pub(crate) fn declare_qabl_interest( face: &mut Arc, id: InterestId, expr: Option<&WireExpr>, - future: bool, + continuous: bool, aggregate: bool, ) { if let Some(expr) = expr { @@ -87,7 +87,7 @@ pub(crate) fn declare_qabl_interest( face, id, Some(&mut res), - future, + continuous, aggregate, ); } @@ -100,7 +100,7 @@ pub(crate) fn declare_qabl_interest( } } else { let mut wtables = zwrite!(tables.tables); - hat_code.declare_qabl_interest(&mut wtables, face, id, None, future, aggregate); + hat_code.declare_qabl_interest(&mut wtables, face, id, None, continuous, aggregate); } } diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index b1db25346a..8d6315e570 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -280,7 +280,7 @@ impl HatPubSubTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, _aggregate: bool, ) { face_hat_mut!(face) @@ -293,7 +293,7 @@ impl HatPubSubTrait for HatCode { { let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); let interest = Interest::KEYEXPRS + Interest::SUBSCRIBERS; - let mode = if future { + let mode = if continuous { DeclareMode::RequestContinuous(id) } else { DeclareMode::Request(id) diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index 7706a20f68..e41b94feec 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -253,7 +253,7 @@ impl HatQueriesTrait for HatCode { _face: &mut Arc, _id: InterestId, _res: Option<&mut Arc>, - _future: bool, + _continuous: bool, _aggregate: bool, ) { todo!() diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index f2d4a37d2b..47bb5f6db5 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -640,10 +640,15 @@ impl HatPubSubTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ) { if face.whatami == WhatAmI::Client { + let mode = if continuous { + DeclareMode::Push + } else { + DeclareMode::Response(id) + }; let sub_info = SubscriberInfo { reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers }; @@ -654,12 +659,17 @@ impl HatPubSubTrait for HatCode { && sub.matches(res) && (remote_client_subs(sub, face) || remote_peer_subs(tables, sub)) }) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -678,12 +688,17 @@ impl HatPubSubTrait for HatCode { && sub.matches(res) && (remote_client_subs(sub, face) || remote_peer_subs(tables, sub)) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -703,12 +718,17 @@ impl HatPubSubTrait for HatCode { if sub.context.is_some() && (remote_client_subs(sub, face) || remote_peer_subs(tables, sub)) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -724,7 +744,7 @@ impl HatPubSubTrait for HatCode { } } } - if future { + if continuous { face_hat_mut!(face) .remote_sub_interests .insert(id, (res.cloned(), aggregate)); diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index c71dc19337..bf65aba3c0 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -678,10 +678,15 @@ impl HatQueriesTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ) { if face.whatami == WhatAmI::Client { + let mode = if continuous { + DeclareMode::Push + } else { + DeclareMode::Response(id) + }; if let Some(res) = res.as_ref() { if aggregate { if hat!(tables).peer_qabls.iter().any(|qabl| { @@ -690,14 +695,19 @@ impl HatQueriesTrait for HatCode { && (remote_client_qabls(qabl, face) || remote_peer_qabls(tables, qabl)) }) { let info = local_qabl_info(tables, res, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert((*res).clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert((*res).clone(), (id, info)); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -717,14 +727,19 @@ impl HatQueriesTrait for HatCode { && (remote_client_qabls(qabl, face) || remote_peer_qabls(tables, qabl)) { let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + id + } else { + 0 + }; let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -745,14 +760,19 @@ impl HatQueriesTrait for HatCode { && (remote_client_qabls(qabl, face) || remote_peer_qabls(tables, qabl)) { let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + id + } else { + 0 + }; let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -768,7 +788,7 @@ impl HatQueriesTrait for HatCode { } } } - if future { + if continuous { face_hat_mut!(face) .remote_qabl_interests .insert(id, res.cloned()); diff --git a/zenoh/src/net/routing/hat/mod.rs b/zenoh/src/net/routing/hat/mod.rs index 60554c06d0..4151615d38 100644 --- a/zenoh/src/net/routing/hat/mod.rs +++ b/zenoh/src/net/routing/hat/mod.rs @@ -123,7 +123,7 @@ pub(crate) trait HatPubSubTrait { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ); fn undeclare_sub_interest( @@ -171,7 +171,7 @@ pub(crate) trait HatQueriesTrait { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ); fn undeclare_qabl_interest( diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index fb5f6f1136..f7ba6de349 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -358,10 +358,15 @@ impl HatPubSubTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ) { if face.whatami == WhatAmI::Client { + let mode = if continuous { + DeclareMode::Push + } else { + DeclareMode::Response(id) + }; let sub_info = SubscriberInfo { reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers }; @@ -374,12 +379,17 @@ impl HatPubSubTrait for HatCode { .values() .any(|sub| sub.context.is_some() && sub.matches(res)) }) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -402,12 +412,18 @@ impl HatPubSubTrait for HatCode { if src_face.id != face.id { for sub in face_hat!(src_face).remote_subs.values() { if sub.context.is_some() && sub.matches(res) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let id = if continuous { + let id = + face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -435,12 +451,17 @@ impl HatPubSubTrait for HatCode { { if src_face.id != face.id { for sub in face_hat!(src_face).remote_subs.values() { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -457,7 +478,7 @@ impl HatPubSubTrait for HatCode { } } } - if future { + if continuous { face_hat_mut!(face) .remote_sub_interests .insert(id, (res.cloned(), aggregate)); diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index d0fd53a216..e56e412b9c 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -334,10 +334,15 @@ impl HatQueriesTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ) { if face.whatami == WhatAmI::Client { + let mode = if continuous { + DeclareMode::Push + } else { + DeclareMode::Response(id) + }; if let Some(res) = res.as_ref() { if aggregate { if tables.faces.values().any(|src_face| { @@ -348,14 +353,19 @@ impl HatQueriesTrait for HatCode { .any(|qabl| qabl.context.is_some() && qabl.matches(res)) }) { let info = local_qabl_info(tables, res, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert((*res).clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert((*res).clone(), (id, info)); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -379,14 +389,20 @@ impl HatQueriesTrait for HatCode { for qabl in face_hat!(src_face).remote_qabls.values() { if qabl.context.is_some() && qabl.matches(res) { let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); + let id = if continuous { + let id = + face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + id + } else { + 0 + }; let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -414,14 +430,19 @@ impl HatQueriesTrait for HatCode { for qabl in face_hat!(src_face).remote_qabls.values() { if qabl.context.is_some() { let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + id + } else { + 0 + }; let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -439,7 +460,7 @@ impl HatQueriesTrait for HatCode { } } } - if future { + if continuous { face_hat_mut!(face) .remote_qabl_interests .insert(id, res.cloned()); diff --git a/zenoh/src/net/routing/hat/router/pubsub.rs b/zenoh/src/net/routing/hat/router/pubsub.rs index 664fe06f71..db915bb139 100644 --- a/zenoh/src/net/routing/hat/router/pubsub.rs +++ b/zenoh/src/net/routing/hat/router/pubsub.rs @@ -940,10 +940,15 @@ impl HatPubSubTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ) { if face.whatami == WhatAmI::Client { + let mode = if continuous { + DeclareMode::Push + } else { + DeclareMode::Response(id) + }; let sub_info = SubscriberInfo { reliability: Reliability::Reliable, // @TODO compute proper reliability to propagate from reliability of known subscribers }; @@ -956,12 +961,17 @@ impl HatPubSubTrait for HatCode { || remote_peer_subs(tables, sub) || remote_router_subs(tables, sub)) }) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert((*res).clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert((*res).clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -982,12 +992,17 @@ impl HatPubSubTrait for HatCode { || remote_peer_subs(tables, sub) || remote_router_subs(tables, sub)) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -1009,12 +1024,17 @@ impl HatPubSubTrait for HatCode { || remote_peer_subs(tables, sub) || remote_router_subs(tables, sub)) { - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face).local_subs.insert(sub.clone(), id); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face).local_subs.insert(sub.clone(), id); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -1030,7 +1050,7 @@ impl HatPubSubTrait for HatCode { } } } - if future { + if continuous { face_hat_mut!(face) .remote_sub_interests .insert(id, (res.cloned(), aggregate)); diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index ca5533d3d8..9c8c190d40 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -1061,10 +1061,15 @@ impl HatQueriesTrait for HatCode { face: &mut Arc, id: InterestId, res: Option<&mut Arc>, - future: bool, + continuous: bool, aggregate: bool, ) { if face.whatami == WhatAmI::Client { + let mode = if continuous { + DeclareMode::Push + } else { + DeclareMode::Response(id) + }; if let Some(res) = res.as_ref() { if aggregate { if hat!(tables).router_qabls.iter().any(|qabl| { @@ -1075,14 +1080,19 @@ impl HatQueriesTrait for HatCode { || remote_router_qabls(tables, qabl)) }) { let info = local_qabl_info(tables, res, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert((*res).clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert((*res).clone(), (id, info)); + id + } else { + 0 + }; let wire_expr = Resource::decl_key(res, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -1104,14 +1114,19 @@ impl HatQueriesTrait for HatCode { || remote_router_qabls(tables, qabl)) { let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + id + } else { + 0 + }; let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -1134,14 +1149,19 @@ impl HatQueriesTrait for HatCode { || remote_router_qabls(tables, qabl)) { let info = local_qabl_info(tables, qabl, face); - let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); - face_hat_mut!(face) - .local_qabls - .insert(qabl.clone(), (id, info)); + let id = if continuous { + let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); + face_hat_mut!(face) + .local_qabls + .insert(qabl.clone(), (id, info)); + id + } else { + 0 + }; let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + mode, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -1157,7 +1177,7 @@ impl HatQueriesTrait for HatCode { } } } - if future { + if continuous { face_hat_mut!(face) .remote_qabl_interests .insert(id, res.cloned()); From 62192b9617afb113256f1ede0421edcdfd697c2d Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Mon, 8 Apr 2024 17:28:07 +0200 Subject: [PATCH 22/30] Add new Interest network message --- commons/zenoh-codec/src/network/declare.rs | 133 +----- commons/zenoh-codec/src/network/interest.rs | 181 +++++++++ commons/zenoh-codec/src/network/mod.rs | 3 + commons/zenoh-protocol/src/network/declare.rs | 381 +----------------- .../zenoh-protocol/src/network/interest.rs | 370 +++++++++++++++++ commons/zenoh-protocol/src/network/mod.rs | 13 +- io/zenoh-transport/src/shm.rs | 10 +- zenoh/src/key_expr.rs | 4 +- zenoh/src/net/primitives/demux.rs | 1 + zenoh/src/net/primitives/mod.rs | 8 +- zenoh/src/net/primitives/mux.rs | 51 ++- zenoh/src/net/routing/dispatcher/face.rs | 7 +- zenoh/src/net/routing/dispatcher/resource.rs | 4 +- zenoh/src/net/routing/hat/client/pubsub.rs | 10 +- zenoh/src/net/routing/hat/client/queries.rs | 8 +- .../net/routing/hat/linkstate_peer/pubsub.rs | 14 +- .../net/routing/hat/linkstate_peer/queries.rs | 14 +- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 10 +- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 8 +- zenoh/src/net/routing/hat/router/pubsub.rs | 22 +- zenoh/src/net/routing/hat/router/queries.rs | 22 +- zenoh/src/net/routing/mod.rs | 4 +- zenoh/src/net/runtime/adminspace.rs | 13 +- zenoh/src/net/tests/tables.rs | 14 +- zenoh/src/session.rs | 22 +- 25 files changed, 753 insertions(+), 574 deletions(-) create mode 100644 commons/zenoh-codec/src/network/interest.rs create mode 100644 commons/zenoh-protocol/src/network/interest.rs diff --git a/commons/zenoh-codec/src/network/declare.rs b/commons/zenoh-codec/src/network/declare.rs index 6e9dad12ce..ddddac8699 100644 --- a/commons/zenoh-codec/src/network/declare.rs +++ b/commons/zenoh-codec/src/network/declare.rs @@ -19,17 +19,10 @@ use zenoh_buffers::{ ZBuf, }; use zenoh_protocol::{ - common::{ - iext, - imsg::{self, HEADER_BITS}, - ZExtZ64, - }, + common::{iext, imsg, ZExtZ64}, core::{ExprId, ExprLen, WireExpr}, network::{ - declare::{ - self, common, interest, keyexpr, queryable, subscriber, token, Declare, DeclareBody, - DeclareMode, Interest, - }, + declare::{self, common, keyexpr, queryable, subscriber, token, Declare, DeclareBody}, id, Mapping, }, }; @@ -51,8 +44,7 @@ where DeclareBody::UndeclareQueryable(r) => self.write(&mut *writer, r)?, DeclareBody::DeclareToken(r) => self.write(&mut *writer, r)?, DeclareBody::UndeclareToken(r) => self.write(&mut *writer, r)?, - DeclareBody::DeclareInterest(r) => self.write(&mut *writer, r)?, - DeclareBody::DeclareFinal(r) => self.write(&mut *writer, r)?, + DeclareBody::DeclareFinal => (), } Ok(()) @@ -79,8 +71,7 @@ where U_QUERYABLE => DeclareBody::UndeclareQueryable(codec.read(&mut *reader)?), D_TOKEN => DeclareBody::DeclareToken(codec.read(&mut *reader)?), U_TOKEN => DeclareBody::UndeclareToken(codec.read(&mut *reader)?), - D_INTEREST => DeclareBody::DeclareInterest(codec.read(&mut *reader)?), - D_FINAL => DeclareBody::DeclareFinal(codec.read(&mut *reader)?), + D_FINAL => DeclareBody::DeclareFinal, _ => return Err(DidntRead), }; @@ -97,7 +88,7 @@ where fn write(self, writer: &mut W, x: &Declare) -> Self::Output { let Declare { - mode, + interest_id, ext_qos, ext_tstamp, ext_nodeid, @@ -106,13 +97,9 @@ where // Header let mut header = id::DECLARE; - header |= match mode { - DeclareMode::Push => 0b00, - DeclareMode::Response(_) => 0b01, - DeclareMode::Request(_) => 0b10, - DeclareMode::RequestContinuous(_) => 0b11, - } << HEADER_BITS; - + if x.interest_id.is_some() { + header |= declare::flag::I; + } let mut n_exts = ((ext_qos != &declare::ext::QoSType::DEFAULT) as u8) + (ext_tstamp.is_some() as u8) + ((ext_nodeid != &declare::ext::NodeIdType::DEFAULT) as u8); @@ -121,12 +108,8 @@ where } self.write(&mut *writer, header)?; - // Body - if let DeclareMode::Request(rid) - | DeclareMode::RequestContinuous(rid) - | DeclareMode::Response(rid) = mode - { - self.write(&mut *writer, rid)?; + if let Some(interest_id) = interest_id { + self.write(&mut *writer, interest_id)?; } // Extensions @@ -175,14 +158,10 @@ where return Err(DidntRead); } - // Body - let mode = match (self.header >> HEADER_BITS) & 0b11 { - 0b00 => DeclareMode::Push, - 0b01 => DeclareMode::Response(self.codec.read(&mut *reader)?), - 0b10 => DeclareMode::Request(self.codec.read(&mut *reader)?), - 0b11 => DeclareMode::RequestContinuous(self.codec.read(&mut *reader)?), - _ => return Err(DidntRead), - }; + let mut interest_id = None; + if imsg::has_flag(self.header, declare::flag::I) { + interest_id = Some(self.codec.read(&mut *reader)?); + } // Extensions let mut ext_qos = declare::ext::QoSType::DEFAULT; @@ -219,7 +198,7 @@ where let body: DeclareBody = self.codec.read(&mut *reader)?; Ok(Declare { - mode, + interest_id, ext_qos, ext_tstamp, ext_nodeid, @@ -938,7 +917,7 @@ where // Extensions let mut ext_wire_expr = common::ext::WireExprType::null(); - let mut has_ext = imsg::has_flag(self.header, interest::flag::Z); + let mut has_ext = imsg::has_flag(self.header, token::flag::Z); while has_ext { let ext: u8 = self.codec.read(&mut *reader)?; let eodec = Zenoh080Header::new(ext); @@ -958,86 +937,6 @@ where } } -// DeclareInterest -impl WCodec<&interest::DeclareInterest, &mut W> for Zenoh080 -where - W: Writer, -{ - type Output = Result<(), DidntWrite>; - - fn write(self, writer: &mut W, x: &interest::DeclareInterest) -> Self::Output { - let interest::DeclareInterest { - interest: _, - wire_expr, - } = x; - - // Header - let header = declare::id::D_INTEREST; - self.write(&mut *writer, header)?; - - // Body - self.write(&mut *writer, x.options())?; - if let Some(we) = wire_expr.as_ref() { - self.write(&mut *writer, we)?; - } - - Ok(()) - } -} - -impl RCodec for Zenoh080 -where - R: Reader, -{ - type Error = DidntRead; - - fn read(self, reader: &mut R) -> Result { - let header: u8 = self.read(&mut *reader)?; - let codec = Zenoh080Header::new(header); - codec.read(reader) - } -} - -impl RCodec for Zenoh080Header -where - R: Reader, -{ - type Error = DidntRead; - - fn read(self, reader: &mut R) -> Result { - if imsg::mid(self.header) != declare::id::D_INTEREST { - return Err(DidntRead); - } - - // Body - let options: u8 = self.codec.read(&mut *reader)?; - let interest = Interest::from(options); - - let mut wire_expr = None; - if interest.restricted() { - let ccond = Zenoh080Condition::new(interest.named()); - let mut we: WireExpr<'static> = ccond.read(&mut *reader)?; - we.mapping = if interest.mapping() { - Mapping::Sender - } else { - Mapping::Receiver - }; - wire_expr = Some(we); - } - - // Extensions - let has_ext = imsg::has_flag(self.header, token::flag::Z); - if has_ext { - extension::skip_all(reader, "DeclareInterest")?; - } - - Ok(interest::DeclareInterest { - interest, - wire_expr, - }) - } -} - // WARNING: this is a temporary extension used for undeclarations impl WCodec<(&common::ext::WireExprType, bool), &mut W> for Zenoh080 where diff --git a/commons/zenoh-codec/src/network/interest.rs b/commons/zenoh-codec/src/network/interest.rs new file mode 100644 index 0000000000..db8e051cb6 --- /dev/null +++ b/commons/zenoh-codec/src/network/interest.rs @@ -0,0 +1,181 @@ +// +// Copyright (c) 2022 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// +use crate::{common::extension, RCodec, WCodec, Zenoh080, Zenoh080Condition, Zenoh080Header}; +use zenoh_buffers::{ + reader::{DidntRead, Reader}, + writer::{DidntWrite, Writer}, +}; +use zenoh_protocol::{ + common::{ + iext, + imsg::{self, HEADER_BITS}, + }, + core::WireExpr, + network::{ + declare, id, + interest::{self, Interest, InterestMode, InterestOptions}, + Mapping, + }, +}; + +// Interest +impl WCodec<&Interest, &mut W> for Zenoh080 +where + W: Writer, +{ + type Output = Result<(), DidntWrite>; + + fn write(self, writer: &mut W, x: &Interest) -> Self::Output { + let Interest { + id, + mode, + wire_expr, + ext_qos, + ext_tstamp, + ext_nodeid, + .. + } = x; + + // Header + let mut header = id::INTEREST; + header |= match mode { + InterestMode::Final => 0b00, + InterestMode::Current => 0b01, + InterestMode::Future => 0b10, + InterestMode::CurrentFuture => 0b11, + } << HEADER_BITS; + let mut n_exts = ((ext_qos != &declare::ext::QoSType::DEFAULT) as u8) + + (ext_tstamp.is_some() as u8) + + ((ext_nodeid != &declare::ext::NodeIdType::DEFAULT) as u8); + if n_exts != 0 { + header |= declare::flag::Z; + } + self.write(&mut *writer, header)?; + + self.write(&mut *writer, id)?; + + self.write(&mut *writer, x.options())?; + if let Some(we) = wire_expr.as_ref() { + self.write(&mut *writer, we)?; + } + + // Extensions + if ext_qos != &declare::ext::QoSType::DEFAULT { + n_exts -= 1; + self.write(&mut *writer, (*ext_qos, n_exts != 0))?; + } + if let Some(ts) = ext_tstamp.as_ref() { + n_exts -= 1; + self.write(&mut *writer, (ts, n_exts != 0))?; + } + if ext_nodeid != &declare::ext::NodeIdType::DEFAULT { + n_exts -= 1; + self.write(&mut *writer, (*ext_nodeid, n_exts != 0))?; + } + + Ok(()) + } +} + +impl RCodec for Zenoh080 +where + R: Reader, +{ + type Error = DidntRead; + + fn read(self, reader: &mut R) -> Result { + let header: u8 = self.read(&mut *reader)?; + let codec = Zenoh080Header::new(header); + + codec.read(reader) + } +} + +impl RCodec for Zenoh080Header +where + R: Reader, +{ + type Error = DidntRead; + + fn read(self, reader: &mut R) -> Result { + if imsg::mid(self.header) != id::INTEREST { + return Err(DidntRead); + } + + let id = self.codec.read(&mut *reader)?; + let mode = match (self.header >> HEADER_BITS) & 0b11 { + 0b00 => InterestMode::Final, + 0b01 => InterestMode::Current, + 0b10 => InterestMode::Future, + 0b11 => InterestMode::CurrentFuture, + _ => return Err(DidntRead), + }; + + let options: u8 = self.codec.read(&mut *reader)?; + let options = InterestOptions::from(options); + + let mut wire_expr = None; + if options.restricted() { + let ccond = Zenoh080Condition::new(options.named()); + let mut we: WireExpr<'static> = ccond.read(&mut *reader)?; + we.mapping = if options.mapping() { + Mapping::Sender + } else { + Mapping::Receiver + }; + wire_expr = Some(we); + } + // Extensions + let mut ext_qos = declare::ext::QoSType::DEFAULT; + let mut ext_tstamp = None; + let mut ext_nodeid = declare::ext::NodeIdType::DEFAULT; + + let mut has_ext = imsg::has_flag(self.header, declare::flag::Z); + while has_ext { + let ext: u8 = self.codec.read(&mut *reader)?; + let eodec = Zenoh080Header::new(ext); + match iext::eid(ext) { + declare::ext::QoS::ID => { + let (q, ext): (interest::ext::QoSType, bool) = eodec.read(&mut *reader)?; + ext_qos = q; + has_ext = ext; + } + declare::ext::Timestamp::ID => { + let (t, ext): (interest::ext::TimestampType, bool) = + eodec.read(&mut *reader)?; + ext_tstamp = Some(t); + has_ext = ext; + } + declare::ext::NodeId::ID => { + let (nid, ext): (interest::ext::NodeIdType, bool) = eodec.read(&mut *reader)?; + ext_nodeid = nid; + has_ext = ext; + } + _ => { + has_ext = extension::skip(reader, "Declare", ext)?; + } + } + } + + Ok(Interest { + id, + mode, + options, + wire_expr, + ext_qos, + ext_tstamp, + ext_nodeid, + }) + } +} diff --git a/commons/zenoh-codec/src/network/mod.rs b/commons/zenoh-codec/src/network/mod.rs index 3a227cd42a..5ebdb17b8e 100644 --- a/commons/zenoh-codec/src/network/mod.rs +++ b/commons/zenoh-codec/src/network/mod.rs @@ -12,6 +12,7 @@ // ZettaScale Zenoh Team, // mod declare; +mod interest; mod oam; mod push; mod request; @@ -45,6 +46,7 @@ where NetworkBody::Request(b) => self.write(&mut *writer, b), NetworkBody::Response(b) => self.write(&mut *writer, b), NetworkBody::ResponseFinal(b) => self.write(&mut *writer, b), + NetworkBody::Interest(b) => self.write(&mut *writer, b), NetworkBody::Declare(b) => self.write(&mut *writer, b), NetworkBody::OAM(b) => self.write(&mut *writer, b), } @@ -89,6 +91,7 @@ where id::REQUEST => NetworkBody::Request(self.read(&mut *reader)?), id::RESPONSE => NetworkBody::Response(self.read(&mut *reader)?), id::RESPONSE_FINAL => NetworkBody::ResponseFinal(self.read(&mut *reader)?), + id::INTEREST => NetworkBody::Interest(self.read(&mut *reader)?), id::DECLARE => NetworkBody::Declare(self.read(&mut *reader)?), id::OAM => NetworkBody::OAM(self.read(&mut *reader)?), _ => return Err(DidntRead), diff --git a/commons/zenoh-protocol/src/network/declare.rs b/commons/zenoh-protocol/src/network/declare.rs index 31e8adcc6e..0878f1c048 100644 --- a/commons/zenoh-protocol/src/network/declare.rs +++ b/commons/zenoh-protocol/src/network/declare.rs @@ -19,8 +19,6 @@ use crate::{ }; use alloc::borrow::Cow; pub use common::*; -use core::sync::atomic::AtomicU32; -pub use interest::*; pub use keyexpr::*; pub use queryable::*; pub use subscriber::*; @@ -33,59 +31,24 @@ pub mod flag { } /// Flags: -/// - |: Mode The mode of the the declaration* -/// -/ +/// - I: Interest If I==1 then interest_id is present +/// - X: Reserved /// - Z: Extension If Z==1 then at least one extension is present /// /// 7 6 5 4 3 2 1 0 /// +-+-+-+-+-+-+-+-+ -/// |Z|Mod| DECLARE | +/// |Z|X|I| DECLARE | /// +-+-+-+---------+ -/// ~ rid:z32 ~ if Mode != Push +/// ~interest_id:z32~ if I==1 /// +---------------+ /// ~ [decl_exts] ~ if Z==1 /// +---------------+ /// ~ declaration ~ /// +---------------+ /// -/// *Mode of declaration: -/// - Mode 0b00: Push -/// - Mode 0b01: Response -/// - Mode 0b10: Request -/// - Mode 0b11: RequestContinuous - -/// The resolution of a RequestId -pub type DeclareRequestId = u32; -pub type AtomicDeclareRequestId = AtomicU32; - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum DeclareMode { - Push, - Request(DeclareRequestId), - RequestContinuous(DeclareRequestId), - Response(DeclareRequestId), -} - -impl DeclareMode { - #[cfg(feature = "test")] - pub fn rand() -> Self { - use rand::Rng; - - let mut rng = rand::thread_rng(); - - match rng.gen_range(0..4) { - 0 => DeclareMode::Push, - 1 => DeclareMode::Request(rng.gen()), - 2 => DeclareMode::RequestContinuous(rng.gen()), - 3 => DeclareMode::Response(rng.gen()), - _ => unreachable!(), - } - } -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct Declare { - pub mode: DeclareMode, + pub interest_id: Option, pub ext_qos: ext::QoSType, pub ext_tstamp: Option, pub ext_nodeid: ext::NodeIdType, @@ -121,8 +84,6 @@ pub mod id { pub const D_TOKEN: u8 = 0x06; pub const U_TOKEN: u8 = 0x07; - pub const D_INTEREST: u8 = 0x08; - pub const D_FINAL: u8 = 0x1A; } @@ -136,8 +97,7 @@ pub enum DeclareBody { UndeclareQueryable(UndeclareQueryable), DeclareToken(DeclareToken), UndeclareToken(UndeclareToken), - DeclareInterest(DeclareInterest), - DeclareFinal(DeclareFinal), + DeclareFinal, } impl DeclareBody { @@ -147,7 +107,7 @@ impl DeclareBody { let mut rng = rand::thread_rng(); - match rng.gen_range(0..10) { + match rng.gen_range(0..8) { 0 => DeclareBody::DeclareKeyExpr(DeclareKeyExpr::rand()), 1 => DeclareBody::UndeclareKeyExpr(UndeclareKeyExpr::rand()), 2 => DeclareBody::DeclareSubscriber(DeclareSubscriber::rand()), @@ -156,8 +116,7 @@ impl DeclareBody { 5 => DeclareBody::UndeclareQueryable(UndeclareQueryable::rand()), 6 => DeclareBody::DeclareToken(DeclareToken::rand()), 7 => DeclareBody::UndeclareToken(UndeclareToken::rand()), - 8 => DeclareBody::DeclareInterest(DeclareInterest::rand()), - 9 => DeclareBody::DeclareFinal(DeclareFinal::rand()), + 8 => DeclareBody::DeclareFinal, _ => unreachable!(), } } @@ -170,14 +129,16 @@ impl Declare { let mut rng = rand::thread_rng(); - let mode = DeclareMode::rand(); + let interest_id = rng + .gen_bool(0.5) + .then_some(rng.gen::()); let ext_qos = ext::QoSType::rand(); let ext_tstamp = rng.gen_bool(0.5).then(ext::TimestampType::rand); let ext_nodeid = ext::NodeIdType::rand(); let body = DeclareBody::rand(); Self { - mode, + interest_id, ext_qos, ext_tstamp, ext_nodeid, @@ -197,7 +158,7 @@ pub mod common { /// /// 7 6 5 4 3 2 1 0 /// +-+-+-+-+-+-+-+-+ - /// |Z|x|x| D_FINAL | + /// |Z|X|X| D_FINAL | /// +---------------+ /// ~ [final_exts] ~ if Z==1 /// +---------------+ @@ -714,319 +675,3 @@ pub mod token { } } } - -pub mod interest { - use core::{ - fmt::{self, Debug}, - ops::{Add, AddAssign, Sub, SubAssign}, - }; - - use super::*; - - pub type InterestId = u32; - - pub mod flag { - // pub const X: u8 = 1 << 5; // 0x20 Reserved - // pub const X: u8 = 1 << 6; // 0x40 Reserved - pub const Z: u8 = 1 << 7; // 0x80 Extensions if Z==1 then an extension will follow - } - - /// # DeclareInterest message - /// - /// The DECLARE INTEREST message is sent to request the transmission of current and optionally future - /// declarations of a given kind matching a target keyexpr. E.g., a declare interest could be - /// sent to request the transmisison of all current subscriptions matching `a/*`. - /// - /// The behaviour of a DECLARE INTEREST depends on the DECLARE MODE in the DECLARE MESSAGE: - /// - Push: invalid - /// - Request: only current declarations - /// - RequestContinous: current and future declarations - /// - Response: invalid - /// - /// E.g., the [`DeclareInterest`] message flow is the following for a Request: - /// - /// ```text - /// A B - /// | DECL INTEREST | - /// |------------------>| -- Sent in Declare::Request. - /// | | This is a DeclareInterest e.g. for subscriber declarations. - /// | | - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Response - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Response - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Response - /// | | - /// | FINAL | - /// |<------------------| -- Sent in Declare::Response - /// ``` - /// - /// - /// And the [`DeclareInterest`] message flow is the following for a RequestContinuous: - /// - /// ```text - /// A B - /// | DECL INTEREST | - /// |------------------>| -- Sent in Declare::RequestContinuous. - /// | | This is a DeclareInterest e.g. for subscriber declarations/undeclarations. - /// | | - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Push - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Push - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Push - /// | | - /// | FINAL | - /// |<------------------| -- Sent in Declare::Response - /// | | - /// | DECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Push. This is a new subscriber declaration. - /// | UNDECL SUBSCRIBER | - /// |<------------------| -- Sent in Declare::Push. This is a new subscriber undeclaration. - /// | | - /// | ... | - /// | | - /// | FINAL | - /// |------------------>| -- Sent in Declare::RequestContinuous. - /// | | This stops the transmission of subscriber declarations/undeclarations. - /// | | - /// ``` - /// - /// The DECLARE INTEREST message structure is defined as follows: - /// - /// ```text - /// Flags: - /// - X: Reserved - /// - X: Reserved - /// - Z: Extension If Z==1 then at least one extension is present - /// - /// 7 6 5 4 3 2 1 0 - /// +-+-+-+-+-+-+-+-+ - /// |Z|X|X| D_INT | - /// +---------------+ - /// |A|M|N|R|T|Q|S|K| (*) - /// +---------------+ - /// ~ key_scope:z16 ~ if R==1 - /// +---------------+ - /// ~ key_suffix ~ if R==1 && N==1 -- - /// +---------------+ - /// ~ [decl_exts] ~ if Z==1 - /// +---------------+ - /// - /// (*) - if K==1 then the interest refers to key expressions - /// - if S==1 then the interest refers to subscribers - /// - if Q==1 then the interest refers to queryables - /// - if T==1 then the interest refers to tokens - /// - if R==1 then the interest is restricted to the matching key expression, else it is for all key expressions. - /// - if N==1 then the key expr has name/suffix. If R==0 then N should be set to 0. - /// - if M==1 then key expr mapping is the one declared by the sender, else it is the one declared by the receiver. - /// If R==0 then M should be set to 0. - /// - if A==1 then the replies SHOULD be aggregated - /// ``` - #[derive(Debug, Clone, PartialEq, Eq)] - pub struct DeclareInterest { - pub interest: Interest, - pub wire_expr: Option>, - } - - impl DeclareInterest { - pub fn options(&self) -> u8 { - let mut interest = self.interest; - if let Some(we) = self.wire_expr.as_ref() { - interest += Interest::RESTRICTED; - if we.has_suffix() { - interest += Interest::NAMED; - } - if let Mapping::Sender = we.mapping { - interest += Interest::MAPPING; - } - } - interest.options - } - - #[cfg(feature = "test")] - pub fn rand() -> Self { - use rand::Rng; - let mut rng = rand::thread_rng(); - - let wire_expr = rng.gen_bool(0.5).then_some(WireExpr::rand()); - let interest = Interest::rand(); - - Self { - wire_expr, - interest, - } - } - } - - #[derive(Clone, Copy)] - pub struct Interest { - options: u8, - } - - impl Interest { - // Flags - pub const KEYEXPRS: Interest = Interest::options(1); - pub const SUBSCRIBERS: Interest = Interest::options(1 << 1); - pub const QUERYABLES: Interest = Interest::options(1 << 2); - pub const TOKENS: Interest = Interest::options(1 << 3); - const RESTRICTED: Interest = Interest::options(1 << 4); - const NAMED: Interest = Interest::options(1 << 5); - const MAPPING: Interest = Interest::options(1 << 6); - pub const AGGREGATE: Interest = Interest::options(1 << 7); - pub const ALL: Interest = Interest::options( - Interest::KEYEXPRS.options - | Interest::SUBSCRIBERS.options - | Interest::QUERYABLES.options - | Interest::TOKENS.options, - ); - - const fn options(options: u8) -> Self { - Self { options } - } - - pub const fn empty() -> Self { - Self { options: 0 } - } - - pub const fn keyexprs(&self) -> bool { - imsg::has_flag(self.options, Self::KEYEXPRS.options) - } - - pub const fn subscribers(&self) -> bool { - imsg::has_flag(self.options, Self::SUBSCRIBERS.options) - } - - pub const fn queryables(&self) -> bool { - imsg::has_flag(self.options, Self::QUERYABLES.options) - } - - pub const fn tokens(&self) -> bool { - imsg::has_flag(self.options, Self::TOKENS.options) - } - - pub const fn restricted(&self) -> bool { - imsg::has_flag(self.options, Self::RESTRICTED.options) - } - - pub const fn named(&self) -> bool { - imsg::has_flag(self.options, Self::NAMED.options) - } - - pub const fn mapping(&self) -> bool { - imsg::has_flag(self.options, Self::MAPPING.options) - } - - pub const fn aggregate(&self) -> bool { - imsg::has_flag(self.options, Self::AGGREGATE.options) - } - - #[cfg(feature = "test")] - pub fn rand() -> Self { - use rand::Rng; - let mut rng = rand::thread_rng(); - - let mut s = Self::empty(); - if rng.gen_bool(0.5) { - s += Interest::KEYEXPRS; - } - if rng.gen_bool(0.5) { - s += Interest::SUBSCRIBERS; - } - if rng.gen_bool(0.5) { - s += Interest::TOKENS; - } - if rng.gen_bool(0.5) { - s += Interest::AGGREGATE; - } - s - } - } - - impl PartialEq for Interest { - fn eq(&self, other: &Self) -> bool { - self.keyexprs() == other.keyexprs() - && self.subscribers() == other.subscribers() - && self.queryables() == other.queryables() - && self.tokens() == other.tokens() - && self.aggregate() == other.aggregate() - } - } - - impl Debug for Interest { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Interest {{ ")?; - if self.keyexprs() { - write!(f, "K:Y, ")?; - } else { - write!(f, "K:N, ")?; - } - if self.subscribers() { - write!(f, "S:Y, ")?; - } else { - write!(f, "S:N, ")?; - } - if self.queryables() { - write!(f, "Q:Y, ")?; - } else { - write!(f, "Q:N, ")?; - } - if self.tokens() { - write!(f, "T:Y, ")?; - } else { - write!(f, "T:N, ")?; - } - if self.aggregate() { - write!(f, "A:Y")?; - } else { - write!(f, "A:N")?; - } - write!(f, " }}")?; - Ok(()) - } - } - - impl Eq for Interest {} - - impl Add for Interest { - type Output = Self; - - #[allow(clippy::suspicious_arithmetic_impl)] // Allows to implement Add & Sub for Interest - fn add(self, rhs: Self) -> Self::Output { - Self { - options: self.options | rhs.options, - } - } - } - - impl AddAssign for Interest { - #[allow(clippy::suspicious_op_assign_impl)] // Allows to implement Add & Sub for Interest - fn add_assign(&mut self, rhs: Self) { - self.options |= rhs.options; - } - } - - impl Sub for Interest { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self { - options: self.options & !rhs.options, - } - } - } - - impl SubAssign for Interest { - fn sub_assign(&mut self, rhs: Self) { - self.options &= !rhs.options; - } - } - - impl From for Interest { - fn from(options: u8) -> Self { - Self { options } - } - } -} diff --git a/commons/zenoh-protocol/src/network/interest.rs b/commons/zenoh-protocol/src/network/interest.rs new file mode 100644 index 0000000000..7da3ab414a --- /dev/null +++ b/commons/zenoh-protocol/src/network/interest.rs @@ -0,0 +1,370 @@ +// +// Copyright (c) 2022 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// +use crate::{common::imsg, core::WireExpr, network::Mapping}; +use core::{ + fmt::{self, Debug}, + ops::{Add, AddAssign, Sub, SubAssign}, + sync::atomic::AtomicU32, +}; + +pub type InterestId = u32; + +pub mod flag { + pub const Z: u8 = 1 << 7; // 0x80 Extensions if Z==1 then an extension will follow +} + +/// The INTEREST message is sent to request the transmission of current and optionally future +/// declarations of a given kind matching a target keyexpr. E.g., an interest could be +/// sent to request the transmisison of all current subscriptions matching `a/*`. +/// +/// The behaviour of a INTEREST depends on the INTEREST MODE. +/// +/// E.g., the message flow is the following for an [`Interest`] with mode `Current`: +/// +/// ```text +/// A B +/// | INTEREST | +/// |------------------>| -- Mode: Current +/// | | This is an Interest e.g. for subscriber declarations. +/// | | +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field set +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field set +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field set +/// | | +/// | DECL FINAL | +/// |<------------------| -- With interest_id field set +/// +/// +/// And the message flow is the following for an [`Interest`] with mode `CurrentFuture`: +/// +/// ```text +/// A B +/// | INTEREST | +/// |------------------>| -- This is a DeclareInterest e.g. for subscriber declarations/undeclarations. +/// | | +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field not set +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field not set +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field not set +/// | | +/// | DECL FINAL | +/// |<------------------| -- With interest_id field set +/// | | +/// | DECL SUBSCRIBER | +/// |<------------------| -- With interest_id field not set +/// | UNDECL SUBSCRIBER | +/// |<------------------| -- With interest_id field not set +/// | | +/// | ... | +/// | | +/// | INTEREST FINAL | +/// |------------------>| -- Mode: Final +/// | | This stops the transmission of subscriber declarations/undeclarations. +/// | +/// +/// Flags: +/// - |: Mode The mode of the interest* +/// -/ +/// - Z: Extension If Z==1 then at least one extension is present +/// +/// 7 6 5 4 3 2 1 0 +/// +-+-+-+-+-+-+-+-+ +/// |Z|Mod|INTEREST | +/// +-+-+-+---------+ +/// ~ id:z32 ~ +/// +---------------+ +/// |A|M|N|R|T|Q|S|K| (*) +/// +---------------+ +/// ~ key_scope:z16 ~ if R==1 +/// +---------------+ +/// ~ key_suffix ~ if R==1 && N==1 -- +/// +---------------+ +/// ~ [int_exts] ~ if Z==1 +/// +---------------+ +/// +/// *Mode of declaration: +/// - Mode 0b00: Final +/// - Mode 0b01: Current +/// - Mode 0b10: Future +/// - Mode 0b11: CurrentFuture + +/// The resolution of a RequestId +pub type DeclareRequestId = u32; +pub type AtomicDeclareRequestId = AtomicU32; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum InterestMode { + Final, + Current, + Future, + CurrentFuture, +} + +impl InterestMode { + #[cfg(feature = "test")] + pub fn rand() -> Self { + use rand::Rng; + + let mut rng = rand::thread_rng(); + + match rng.gen_range(0..4) { + 0 => InterestMode::Final, + 1 => InterestMode::Current, + 2 => InterestMode::Future, + 3 => InterestMode::CurrentFuture, + _ => unreachable!(), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Interest { + pub id: InterestId, + pub mode: InterestMode, + pub options: InterestOptions, + pub wire_expr: Option>, + pub ext_qos: ext::QoSType, + pub ext_tstamp: Option, + pub ext_nodeid: ext::NodeIdType, +} + +pub mod ext { + use crate::{ + common::{ZExtZ64, ZExtZBuf}, + zextz64, zextzbuf, + }; + + pub type QoS = zextz64!(0x1, false); + pub type QoSType = crate::network::ext::QoSType<{ QoS::ID }>; + + pub type Timestamp = zextzbuf!(0x2, false); + pub type TimestampType = crate::network::ext::TimestampType<{ Timestamp::ID }>; + + pub type NodeId = zextz64!(0x3, true); + pub type NodeIdType = crate::network::ext::NodeIdType<{ NodeId::ID }>; +} + +impl Interest { + pub fn options(&self) -> u8 { + let mut interest = self.options; + if let Some(we) = self.wire_expr.as_ref() { + interest += InterestOptions::RESTRICTED; + if we.has_suffix() { + interest += InterestOptions::NAMED; + } + if let Mapping::Sender = we.mapping { + interest += InterestOptions::MAPPING; + } + } + interest.options + } + + #[cfg(feature = "test")] + pub fn rand() -> Self { + use rand::Rng; + let mut rng = rand::thread_rng(); + + let id = rng.gen::(); + let mode = InterestMode::rand(); + let options = InterestOptions::rand(); + let wire_expr = rng.gen_bool(0.5).then_some(WireExpr::rand()); + let ext_qos = ext::QoSType::rand(); + let ext_tstamp = rng.gen_bool(0.5).then(ext::TimestampType::rand); + let ext_nodeid = ext::NodeIdType::rand(); + + Self { + id, + mode, + wire_expr, + options, + ext_qos, + ext_tstamp, + ext_nodeid, + } + } +} + +#[derive(Clone, Copy)] +pub struct InterestOptions { + options: u8, +} + +impl InterestOptions { + // Flags + pub const KEYEXPRS: InterestOptions = InterestOptions::options(1); + pub const SUBSCRIBERS: InterestOptions = InterestOptions::options(1 << 1); + pub const QUERYABLES: InterestOptions = InterestOptions::options(1 << 2); + pub const TOKENS: InterestOptions = InterestOptions::options(1 << 3); + const RESTRICTED: InterestOptions = InterestOptions::options(1 << 4); + const NAMED: InterestOptions = InterestOptions::options(1 << 5); + const MAPPING: InterestOptions = InterestOptions::options(1 << 6); + pub const AGGREGATE: InterestOptions = InterestOptions::options(1 << 7); + pub const ALL: InterestOptions = InterestOptions::options( + InterestOptions::KEYEXPRS.options + | InterestOptions::SUBSCRIBERS.options + | InterestOptions::QUERYABLES.options + | InterestOptions::TOKENS.options, + ); + + const fn options(options: u8) -> Self { + Self { options } + } + + pub const fn empty() -> Self { + Self { options: 0 } + } + + pub const fn keyexprs(&self) -> bool { + imsg::has_flag(self.options, Self::KEYEXPRS.options) + } + + pub const fn subscribers(&self) -> bool { + imsg::has_flag(self.options, Self::SUBSCRIBERS.options) + } + + pub const fn queryables(&self) -> bool { + imsg::has_flag(self.options, Self::QUERYABLES.options) + } + + pub const fn tokens(&self) -> bool { + imsg::has_flag(self.options, Self::TOKENS.options) + } + + pub const fn restricted(&self) -> bool { + imsg::has_flag(self.options, Self::RESTRICTED.options) + } + + pub const fn named(&self) -> bool { + imsg::has_flag(self.options, Self::NAMED.options) + } + + pub const fn mapping(&self) -> bool { + imsg::has_flag(self.options, Self::MAPPING.options) + } + + pub const fn aggregate(&self) -> bool { + imsg::has_flag(self.options, Self::AGGREGATE.options) + } + + #[cfg(feature = "test")] + pub fn rand() -> Self { + use rand::Rng; + let mut rng = rand::thread_rng(); + + let mut s = Self::empty(); + if rng.gen_bool(0.5) { + s += InterestOptions::KEYEXPRS; + } + if rng.gen_bool(0.5) { + s += InterestOptions::SUBSCRIBERS; + } + if rng.gen_bool(0.5) { + s += InterestOptions::TOKENS; + } + if rng.gen_bool(0.5) { + s += InterestOptions::AGGREGATE; + } + s + } +} + +impl PartialEq for InterestOptions { + fn eq(&self, other: &Self) -> bool { + self.keyexprs() == other.keyexprs() + && self.subscribers() == other.subscribers() + && self.queryables() == other.queryables() + && self.tokens() == other.tokens() + && self.aggregate() == other.aggregate() + } +} + +impl Debug for InterestOptions { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Interest {{ ")?; + if self.keyexprs() { + write!(f, "K:Y, ")?; + } else { + write!(f, "K:N, ")?; + } + if self.subscribers() { + write!(f, "S:Y, ")?; + } else { + write!(f, "S:N, ")?; + } + if self.queryables() { + write!(f, "Q:Y, ")?; + } else { + write!(f, "Q:N, ")?; + } + if self.tokens() { + write!(f, "T:Y, ")?; + } else { + write!(f, "T:N, ")?; + } + if self.aggregate() { + write!(f, "A:Y")?; + } else { + write!(f, "A:N")?; + } + write!(f, " }}")?; + Ok(()) + } +} + +impl Eq for InterestOptions {} + +impl Add for InterestOptions { + type Output = Self; + + #[allow(clippy::suspicious_arithmetic_impl)] // Allows to implement Add & Sub for Interest + fn add(self, rhs: Self) -> Self::Output { + Self { + options: self.options | rhs.options, + } + } +} + +impl AddAssign for InterestOptions { + #[allow(clippy::suspicious_op_assign_impl)] // Allows to implement Add & Sub for Interest + fn add_assign(&mut self, rhs: Self) { + self.options |= rhs.options; + } +} + +impl Sub for InterestOptions { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self { + options: self.options & !rhs.options, + } + } +} + +impl SubAssign for InterestOptions { + fn sub_assign(&mut self, rhs: Self) { + self.options &= !rhs.options; + } +} + +impl From for InterestOptions { + fn from(options: u8) -> Self { + Self { options } + } +} diff --git a/commons/zenoh-protocol/src/network/mod.rs b/commons/zenoh-protocol/src/network/mod.rs index e60388f425..ae92d22407 100644 --- a/commons/zenoh-protocol/src/network/mod.rs +++ b/commons/zenoh-protocol/src/network/mod.rs @@ -12,6 +12,7 @@ // ZettaScale Zenoh Team, // pub mod declare; +pub mod interest; pub mod oam; pub mod push; pub mod request; @@ -20,10 +21,10 @@ pub mod response; use core::fmt; pub use declare::{ - Declare, DeclareBody, DeclareFinal, DeclareInterest, DeclareKeyExpr, DeclareMode, - DeclareQueryable, DeclareSubscriber, DeclareToken, UndeclareKeyExpr, UndeclareQueryable, - UndeclareSubscriber, UndeclareToken, + Declare, DeclareBody, DeclareFinal, DeclareKeyExpr, DeclareQueryable, DeclareSubscriber, + DeclareToken, UndeclareKeyExpr, UndeclareQueryable, UndeclareSubscriber, UndeclareToken, }; +pub use interest::Interest; pub use oam::Oam; pub use push::Push; pub use request::{AtomicRequestId, Request, RequestId}; @@ -35,6 +36,7 @@ pub mod id { // WARNING: it's crucial that these IDs do NOT collide with the IDs // defined in `crate::transport::id`. pub const OAM: u8 = 0x1f; + pub const INTEREST: u8 = 0x19; pub const DECLARE: u8 = 0x1e; pub const PUSH: u8 = 0x1d; pub const REQUEST: u8 = 0x1c; @@ -73,6 +75,7 @@ pub enum NetworkBody { Request(Request), Response(Response), ResponseFinal(ResponseFinal), + Interest(Interest), Declare(Declare), OAM(Oam), } @@ -117,6 +120,7 @@ impl NetworkMessage { NetworkBody::Request(msg) => msg.ext_qos.is_express(), NetworkBody::Response(msg) => msg.ext_qos.is_express(), NetworkBody::ResponseFinal(msg) => msg.ext_qos.is_express(), + NetworkBody::Interest(msg) => msg.ext_qos.is_express(), NetworkBody::Declare(msg) => msg.ext_qos.is_express(), NetworkBody::OAM(msg) => msg.ext_qos.is_express(), } @@ -133,6 +137,7 @@ impl NetworkMessage { NetworkBody::Request(msg) => msg.ext_qos.get_congestion_control(), NetworkBody::Response(msg) => msg.ext_qos.get_congestion_control(), NetworkBody::ResponseFinal(msg) => msg.ext_qos.get_congestion_control(), + NetworkBody::Interest(msg) => msg.ext_qos.get_congestion_control(), NetworkBody::Declare(msg) => msg.ext_qos.get_congestion_control(), NetworkBody::OAM(msg) => msg.ext_qos.get_congestion_control(), }; @@ -147,6 +152,7 @@ impl NetworkMessage { NetworkBody::Request(msg) => msg.ext_qos.get_priority(), NetworkBody::Response(msg) => msg.ext_qos.get_priority(), NetworkBody::ResponseFinal(msg) => msg.ext_qos.get_priority(), + NetworkBody::Interest(msg) => msg.ext_qos.get_priority(), NetworkBody::Declare(msg) => msg.ext_qos.get_priority(), NetworkBody::OAM(msg) => msg.ext_qos.get_priority(), } @@ -162,6 +168,7 @@ impl fmt::Display for NetworkMessage { Request(_) => write!(f, "Request"), Response(_) => write!(f, "Response"), ResponseFinal(_) => write!(f, "ResponseFinal"), + Interest(_) => write!(f, "Interest"), Declare(_) => write!(f, "Declare"), } } diff --git a/io/zenoh-transport/src/shm.rs b/io/zenoh-transport/src/shm.rs index bf569d0345..09edde884e 100644 --- a/io/zenoh-transport/src/shm.rs +++ b/io/zenoh-transport/src/shm.rs @@ -145,7 +145,10 @@ pub fn map_zmsg_to_shminfo(msg: &mut NetworkMessage) -> ZResult { ResponseBody::Reply(b) => b.map_to_shminfo(), ResponseBody::Err(b) => b.map_to_shminfo(), }, - NetworkBody::ResponseFinal(_) | NetworkBody::Declare(_) | NetworkBody::OAM(_) => Ok(false), + NetworkBody::ResponseFinal(_) + | NetworkBody::Interest(_) + | NetworkBody::Declare(_) + | NetworkBody::OAM(_) => Ok(false), } } @@ -196,7 +199,10 @@ pub fn map_zmsg_to_shmbuf( ResponseBody::Reply(b) => b.map_to_shmbuf(shmr), ResponseBody::Err(b) => b.map_to_shmbuf(shmr), }, - NetworkBody::ResponseFinal(_) | NetworkBody::Declare(_) | NetworkBody::OAM(_) => Ok(false), + NetworkBody::ResponseFinal(_) + | NetworkBody::Interest(_) + | NetworkBody::Declare(_) + | NetworkBody::OAM(_) => Ok(false), } } diff --git a/zenoh/src/key_expr.rs b/zenoh/src/key_expr.rs index 17aa0425b6..aaa1d13724 100644 --- a/zenoh/src/key_expr.rs +++ b/zenoh/src/key_expr.rs @@ -53,7 +53,7 @@ pub use zenoh_keyexpr::*; pub use zenoh_macros::{kedefine, keformat, kewrite}; use zenoh_protocol::{ core::{key_expr::canon::Canonizable, ExprId, WireExpr}, - network::{declare, DeclareBody, DeclareMode, Mapping, UndeclareKeyExpr}, + network::{declare, DeclareBody, Mapping, UndeclareKeyExpr}, }; use zenoh_result::ZResult; @@ -664,7 +664,7 @@ impl SyncResolve for KeyExprUndeclaration<'_> { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(zenoh_protocol::network::Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/primitives/demux.rs b/zenoh/src/net/primitives/demux.rs index d62e410c81..e58e01a1b5 100644 --- a/zenoh/src/net/primitives/demux.rs +++ b/zenoh/src/net/primitives/demux.rs @@ -67,6 +67,7 @@ impl TransportPeerEventHandler for DeMux { match msg.body { NetworkBody::Push(m) => self.face.send_push(m), NetworkBody::Declare(m) => self.face.send_declare(m), + NetworkBody::Interest(_) => todo!(), NetworkBody::Request(m) => self.face.send_request(m), NetworkBody::Response(m) => self.face.send_response(m), NetworkBody::ResponseFinal(m) => self.face.send_response_final(m), diff --git a/zenoh/src/net/primitives/mod.rs b/zenoh/src/net/primitives/mod.rs index fd85280be0..d3aa8097ca 100644 --- a/zenoh/src/net/primitives/mod.rs +++ b/zenoh/src/net/primitives/mod.rs @@ -18,11 +18,15 @@ use std::any::Any; pub use demux::*; pub use mux::*; -use zenoh_protocol::network::{Declare, Push, Request, Response, ResponseFinal}; +use zenoh_protocol::network::{ + interest::Interest, Declare, Push, Request, Response, ResponseFinal, +}; use super::routing::RoutingContext; pub trait Primitives: Send + Sync { + fn send_interest(&self, msg: Interest); + fn send_declare(&self, msg: Declare); fn send_push(&self, msg: Push); @@ -56,6 +60,8 @@ pub(crate) trait EPrimitives: Send + Sync { pub struct DummyPrimitives; impl Primitives for DummyPrimitives { + fn send_interest(&self, _msg: Interest) {} + fn send_declare(&self, _msg: Declare) {} fn send_push(&self, _msg: Push) {} diff --git a/zenoh/src/net/primitives/mux.rs b/zenoh/src/net/primitives/mux.rs index 442c040624..9a0f825861 100644 --- a/zenoh/src/net/primitives/mux.rs +++ b/zenoh/src/net/primitives/mux.rs @@ -19,7 +19,8 @@ use crate::net::routing::{ }; use std::sync::OnceLock; use zenoh_protocol::network::{ - Declare, NetworkBody, NetworkMessage, Push, Request, Response, ResponseFinal, + interest::Interest, Declare, NetworkBody, NetworkMessage, Push, Request, Response, + ResponseFinal, }; use zenoh_transport::{multicast::TransportMulticast, unicast::TransportUnicast}; @@ -40,6 +41,30 @@ impl Mux { } impl Primitives for Mux { + fn send_interest(&self, msg: Interest) { + let msg = NetworkMessage { + body: NetworkBody::Interest(msg), + #[cfg(feature = "stats")] + size: None, + }; + if self.interceptor.interceptors.is_empty() { + let _ = self.handler.schedule(msg); + } else if let Some(face) = self.face.get() { + let ctx = RoutingContext::new_out(msg, face.clone()); + let prefix = ctx + .wire_expr() + .and_then(|we| (!we.has_suffix()).then(|| ctx.prefix())) + .flatten() + .cloned(); + let cache = prefix.as_ref().and_then(|p| p.get_egress_cache(face)); + if let Some(ctx) = self.interceptor.intercept(ctx, cache) { + let _ = self.handler.schedule(ctx.msg); + } + } else { + log::error!("Uninitialized multiplexer!"); + } + } + fn send_declare(&self, msg: Declare) { let msg = NetworkMessage { body: NetworkBody::Declare(msg), @@ -316,6 +341,30 @@ impl McastMux { } impl Primitives for McastMux { + fn send_interest(&self, msg: Interest) { + let msg = NetworkMessage { + body: NetworkBody::Interest(msg), + #[cfg(feature = "stats")] + size: None, + }; + if self.interceptor.interceptors.is_empty() { + let _ = self.handler.schedule(msg); + } else if let Some(face) = self.face.get() { + let ctx = RoutingContext::new_out(msg, face.clone()); + let prefix = ctx + .wire_expr() + .and_then(|we| (!we.has_suffix()).then(|| ctx.prefix())) + .flatten() + .cloned(); + let cache = prefix.as_ref().and_then(|p| p.get_egress_cache(face)); + if let Some(ctx) = self.interceptor.intercept(ctx, cache) { + let _ = self.handler.schedule(ctx.msg); + } + } else { + log::error!("Uninitialized multiplexer!"); + } + } + fn send_declare(&self, msg: Declare) { let msg = NetworkMessage { body: NetworkBody::Declare(msg), diff --git a/zenoh/src/net/routing/dispatcher/face.rs b/zenoh/src/net/routing/dispatcher/face.rs index 3531dd2d88..adbb3cacc8 100644 --- a/zenoh/src/net/routing/dispatcher/face.rs +++ b/zenoh/src/net/routing/dispatcher/face.rs @@ -157,6 +157,10 @@ pub struct Face { } impl Primitives for Face { + fn send_interest(&self, _msg: zenoh_protocol::network::Interest) { + todo!() + } + fn send_declare(&self, msg: zenoh_protocol::network::Declare) { let ctrl_lock = zlock!(self.tables.ctrl_lock); match msg.body { @@ -210,8 +214,7 @@ impl Primitives for Face { } zenoh_protocol::network::DeclareBody::DeclareToken(_m) => todo!(), zenoh_protocol::network::DeclareBody::UndeclareToken(_m) => todo!(), - zenoh_protocol::network::DeclareBody::DeclareInterest(_m) => todo!(), - zenoh_protocol::network::DeclareBody::DeclareFinal(_m) => todo!(), + zenoh_protocol::network::DeclareBody::DeclareFinal => todo!(), } drop(ctrl_lock); } diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index 941b37f916..194b97fca8 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -27,7 +27,7 @@ use zenoh_protocol::{ network::{ declare::{ ext, queryable::ext::QueryableInfoType, subscriber::ext::SubscriberInfo, Declare, - DeclareBody, DeclareKeyExpr, DeclareMode, + DeclareBody, DeclareKeyExpr, }, Mapping, }, @@ -452,7 +452,7 @@ impl Resource { .insert(expr_id, nonwild_prefix.clone()); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index 6c689d3336..e85bb77bf9 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -30,7 +30,7 @@ use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ common::ext::WireExprType, ext, subscriber::ext::SubscriberInfo, Declare, DeclareBody, - DeclareMode, DeclareSubscriber, UndeclareSubscriber, + DeclareSubscriber, UndeclareSubscriber, }, }; use zenoh_sync::get_mut_unchecked; @@ -53,7 +53,7 @@ fn propagate_simple_subscription_to( let key_expr = Resource::decl_key(res, dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -137,7 +137,7 @@ fn declare_client_subscription( .primitives .send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -171,7 +171,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -206,7 +206,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index 28e1d75460..5c0bc5349b 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -33,7 +33,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareMode, DeclareQueryable, UndeclareQueryable, + DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -93,7 +93,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -165,7 +165,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -418,7 +418,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -460,7 +460,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index 356793e3a3..150c12a632 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -36,7 +36,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr, ZenohId}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareMode, DeclareQueryable, UndeclareQueryable, + DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -126,7 +126,7 @@ fn send_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -170,7 +170,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -339,7 +339,7 @@ fn send_forget_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -365,7 +365,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 5ac0b22846..b495248788 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -30,7 +30,7 @@ use zenoh_protocol::{ core::{Reliability, WhatAmI}, network::declare::{ common::ext::WireExprType, ext, subscriber::ext::SubscriberInfo, Declare, DeclareBody, - DeclareMode, DeclareSubscriber, UndeclareSubscriber, + DeclareSubscriber, UndeclareSubscriber, }, }; use zenoh_sync::get_mut_unchecked; @@ -53,7 +53,7 @@ fn propagate_simple_subscription_to( let key_expr = Resource::decl_key(res, dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -137,7 +137,7 @@ fn declare_client_subscription( .primitives .send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -171,7 +171,7 @@ fn propagate_forget_simple_subscription(tables: &mut Tables, res: &Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -206,7 +206,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index c2d62c7658..72c32b9217 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -33,7 +33,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareMode, DeclareQueryable, UndeclareQueryable, + DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -93,7 +93,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -165,7 +165,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -412,7 +412,7 @@ fn propagate_forget_simple_subscription_to_peers(tables: &mut Tables, res: &Arc< if let Some(id) = face_hat_mut!(&mut face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -564,7 +564,7 @@ pub(super) fn undeclare_client_subscription( if let Some(id) = face_hat_mut!(face).local_subs.remove(res) { face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -606,7 +606,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -635,7 +635,7 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(sub, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -774,7 +774,7 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: if forget { dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -800,7 +800,7 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: }; dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index e647cf2dc7..99e787beb5 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -36,7 +36,7 @@ use zenoh_protocol::{ core::{WhatAmI, WireExpr, ZenohId}, network::declare::{ common::ext::WireExprType, ext, queryable::ext::QueryableInfoType, Declare, DeclareBody, - DeclareMode, DeclareQueryable, UndeclareQueryable, + DeclareQueryable, UndeclareQueryable, }, }; use zenoh_sync::get_mut_unchecked; @@ -194,7 +194,7 @@ fn send_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -248,7 +248,7 @@ fn propagate_simple_queryable( let key_expr = Resource::decl_key(res, &mut dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -473,7 +473,7 @@ fn send_forget_sourced_queryable_to_net_childs( someface.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType { @@ -499,7 +499,7 @@ fn propagate_forget_simple_queryable(tables: &mut Tables, res: &mut Arc) { let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -775,7 +775,7 @@ pub(super) fn queries_new_face(tables: &mut Tables, face: &mut Arc) { let key_expr = Resource::decl_key(qabl, face); face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -874,7 +874,7 @@ pub(super) fn queries_linkstate_change(tables: &mut Tables, zid: &ZenohId, links if forget { dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -900,7 +900,7 @@ pub(super) fn queries_linkstate_change(tables: &mut Tables, zid: &ZenohId, links let key_expr = Resource::decl_key(res, dst_face); dst_face.primitives.send_declare(RoutingContext::with_expr( Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/net/routing/mod.rs b/zenoh/src/net/routing/mod.rs index 77f51c16b3..67f1ca2ae1 100644 --- a/zenoh/src/net/routing/mod.rs +++ b/zenoh/src/net/routing/mod.rs @@ -107,6 +107,7 @@ impl RoutingContext { NetworkBody::Request(m) => Some(&m.wire_expr), NetworkBody::Response(m) => Some(&m.wire_expr), NetworkBody::ResponseFinal(_) => None, + NetworkBody::Interest(m) => m.wire_expr.as_ref(), NetworkBody::Declare(m) => match &m.body { DeclareBody::DeclareKeyExpr(m) => Some(&m.wire_expr), DeclareBody::UndeclareKeyExpr(_) => None, @@ -116,8 +117,7 @@ impl RoutingContext { DeclareBody::UndeclareQueryable(m) => Some(&m.ext_wire_expr.wire_expr), DeclareBody::DeclareToken(m) => Some(&m.wire_expr), DeclareBody::UndeclareToken(m) => Some(&m.ext_wire_expr.wire_expr), - DeclareBody::DeclareInterest(m) => m.wire_expr.as_ref(), - DeclareBody::DeclareFinal(_) => None, + DeclareBody::DeclareFinal => None, }, NetworkBody::OAM(_) => None, } diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index a5739d830c..2b12169d4d 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -32,6 +32,7 @@ use zenoh_buffers::buffer::SplitBuffer; use zenoh_config::{ConfigValidator, ValidatedMap, WhatAmI}; use zenoh_plugin_trait::{PluginControl, PluginStatus}; use zenoh_protocol::network::declare::QueryableId; +use zenoh_protocol::network::Interest; use zenoh_protocol::{ core::{ key_expr::{keyexpr, OwnedKeyExpr}, @@ -39,8 +40,8 @@ use zenoh_protocol::{ }, network::{ declare::{queryable::ext::QueryableInfoType, subscriber::ext::SubscriberInfo}, - ext, Declare, DeclareBody, DeclareMode, DeclareQueryable, DeclareSubscriber, Push, Request, - Response, ResponseFinal, + ext, Declare, DeclareBody, DeclareQueryable, DeclareSubscriber, Push, Request, Response, + ResponseFinal, }, zenoh::{PushBody, RequestBody}, }; @@ -276,7 +277,7 @@ impl AdminSpace { zlock!(admin.primitives).replace(primitives.clone()); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, @@ -289,7 +290,7 @@ impl AdminSpace { }); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -319,6 +320,10 @@ impl AdminSpace { } impl Primitives for AdminSpace { + fn send_interest(&self, msg: Interest) { + log::trace!("Recv interest {:?}", msg); + } + fn send_declare(&self, msg: Declare) { log::trace!("Recv declare {:?}", msg); if let DeclareBody::DeclareKeyExpr(m) = msg.body { diff --git a/zenoh/src/net/tests/tables.rs b/zenoh/src/net/tests/tables.rs index 55ff9f0a4d..5a881193ea 100644 --- a/zenoh/src/net/tests/tables.rs +++ b/zenoh/src/net/tests/tables.rs @@ -26,7 +26,7 @@ use zenoh_protocol::core::{ key_expr::keyexpr, ExprId, Reliability, WhatAmI, WireExpr, ZenohId, EMPTY_EXPR_ID, }; use zenoh_protocol::network::declare::subscriber::ext::SubscriberInfo; -use zenoh_protocol::network::{ext, Declare, DeclareBody, DeclareKeyExpr, DeclareMode}; +use zenoh_protocol::network::{ext, Declare, DeclareBody, DeclareKeyExpr}; use zenoh_protocol::zenoh::{PushBody, Put}; #[test] @@ -495,6 +495,8 @@ impl ClientPrimitives { } impl Primitives for ClientPrimitives { + fn send_interest(&self, _msg: zenoh_protocol::network::Interest) {} + fn send_declare(&self, msg: zenoh_protocol::network::Declare) { match msg.body { DeclareBody::DeclareKeyExpr(d) => { @@ -579,7 +581,7 @@ fn client_test() { Primitives::send_declare( primitives0.as_ref(), Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -607,7 +609,7 @@ fn client_test() { Primitives::send_declare( primitives0.as_ref(), Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -629,7 +631,7 @@ fn client_test() { Primitives::send_declare( primitives1.as_ref(), Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -657,7 +659,7 @@ fn client_test() { Primitives::send_declare( primitives1.as_ref(), Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -679,7 +681,7 @@ fn client_test() { Primitives::send_declare( primitives2.as_ref(), Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 9bc6c9c331..712f339e77 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -71,7 +71,7 @@ use zenoh_protocol::{ network::{ declare::{ self, common::ext::WireExprType, queryable::ext::QueryableInfoType, - subscriber::ext::SubscriberInfo, Declare, DeclareBody, DeclareKeyExpr, DeclareMode, + subscriber::ext::SubscriberInfo, Declare, DeclareBody, DeclareKeyExpr, DeclareQueryable, DeclareSubscriber, UndeclareQueryable, UndeclareSubscriber, }, ext, @@ -872,7 +872,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1085,7 +1085,7 @@ impl Session { // }; primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1142,7 +1142,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1194,7 +1194,7 @@ impl Session { distance: 0, }; primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1216,7 +1216,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1252,7 +1252,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: declare::ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: declare::ext::NodeIdType::DEFAULT, @@ -1277,7 +1277,7 @@ impl Session { let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { - mode: DeclareMode::Push, + interest_id: None, ext_qos: ext::QoSType::DECLARE, ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, @@ -1944,6 +1944,9 @@ impl<'s> SessionDeclarations<'s, 'static> for Arc { } impl Primitives for Session { + fn send_interest(&self, msg: zenoh_protocol::network::Interest) { + trace!("recv Interest {} {:?}", msg.id, msg.wire_expr); + } fn send_declare(&self, msg: zenoh_protocol::network::Declare) { match msg.body { zenoh_protocol::network::DeclareBody::DeclareKeyExpr(m) => { @@ -2046,8 +2049,7 @@ impl Primitives for Session { } DeclareBody::DeclareToken(_) => todo!(), DeclareBody::UndeclareToken(_) => todo!(), - DeclareBody::DeclareInterest(_) => todo!(), - DeclareBody::DeclareFinal(_) => todo!(), + DeclareBody::DeclareFinal => todo!(), } } From e3a8eb249a7b59ab8d493a3df5febb1f3c1ed2a8 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Mon, 8 Apr 2024 18:16:07 +0200 Subject: [PATCH 23/30] Update doc --- commons/zenoh-protocol/src/network/interest.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/commons/zenoh-protocol/src/network/interest.rs b/commons/zenoh-protocol/src/network/interest.rs index 7da3ab414a..73ad00406e 100644 --- a/commons/zenoh-protocol/src/network/interest.rs +++ b/commons/zenoh-protocol/src/network/interest.rs @@ -103,6 +103,16 @@ pub mod flag { /// - Mode 0b01: Current /// - Mode 0b10: Future /// - Mode 0b11: CurrentFuture +/// +/// (*) - if K==1 then the interest refers to key expressions +/// - if S==1 then the interest refers to subscribers +/// - if Q==1 then the interest refers to queryables +/// - if T==1 then the interest refers to tokens +/// - if R==1 then the interest is restricted to the matching key expression, else it is for all key expressions. +/// - if N==1 then the key expr has name/suffix. If R==0 then N should be set to 0. +/// - if M==1 then key expr mapping is the one declared by the sender, else it is the one declared by the receiver. +/// If R==0 then M should be set to 0. +/// - if A==1 then the replies SHOULD be aggregated /// The resolution of a RequestId pub type DeclareRequestId = u32; From a80ce2bd633fde88d14f9810ac764f8e98cd786d Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Mon, 8 Apr 2024 18:21:03 +0200 Subject: [PATCH 24/30] Update codec --- commons/zenoh-codec/src/network/interest.rs | 35 +++++++++++-------- .../zenoh-protocol/src/network/interest.rs | 6 ++-- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/commons/zenoh-codec/src/network/interest.rs b/commons/zenoh-codec/src/network/interest.rs index db8e051cb6..a7ed88f033 100644 --- a/commons/zenoh-codec/src/network/interest.rs +++ b/commons/zenoh-codec/src/network/interest.rs @@ -65,9 +65,11 @@ where self.write(&mut *writer, id)?; - self.write(&mut *writer, x.options())?; - if let Some(we) = wire_expr.as_ref() { - self.write(&mut *writer, we)?; + if *mode != InterestMode::Final { + self.write(&mut *writer, x.options())?; + if let Some(we) = wire_expr.as_ref() { + self.write(&mut *writer, we)?; + } } // Extensions @@ -122,20 +124,23 @@ where _ => return Err(DidntRead), }; - let options: u8 = self.codec.read(&mut *reader)?; - let options = InterestOptions::from(options); - + let mut options = InterestOptions::empty(); let mut wire_expr = None; - if options.restricted() { - let ccond = Zenoh080Condition::new(options.named()); - let mut we: WireExpr<'static> = ccond.read(&mut *reader)?; - we.mapping = if options.mapping() { - Mapping::Sender - } else { - Mapping::Receiver - }; - wire_expr = Some(we); + if mode != InterestMode::Final { + let options_byte: u8 = self.codec.read(&mut *reader)?; + options = InterestOptions::from(options_byte); + if options.restricted() { + let ccond = Zenoh080Condition::new(options.named()); + let mut we: WireExpr<'static> = ccond.read(&mut *reader)?; + we.mapping = if options.mapping() { + Mapping::Sender + } else { + Mapping::Receiver + }; + wire_expr = Some(we); + } } + // Extensions let mut ext_qos = declare::ext::QoSType::DEFAULT; let mut ext_tstamp = None; diff --git a/commons/zenoh-protocol/src/network/interest.rs b/commons/zenoh-protocol/src/network/interest.rs index 73ad00406e..0bee1580af 100644 --- a/commons/zenoh-protocol/src/network/interest.rs +++ b/commons/zenoh-protocol/src/network/interest.rs @@ -89,11 +89,11 @@ pub mod flag { /// +-+-+-+---------+ /// ~ id:z32 ~ /// +---------------+ -/// |A|M|N|R|T|Q|S|K| (*) +/// |A|M|N|R|T|Q|S|K| if Mod!=Final (*) /// +---------------+ -/// ~ key_scope:z16 ~ if R==1 +/// ~ key_scope:z16 ~ if Mod!=Final && R==1 /// +---------------+ -/// ~ key_suffix ~ if R==1 && N==1 -- +/// ~ key_suffix ~ if Mod!=Final && R==1 && N==1 -- /// +---------------+ /// ~ [int_exts] ~ if Z==1 /// +---------------+ From 59ae98f2d6f8acb3a55a3459295669b234e4f556 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Thu, 18 Apr 2024 15:52:54 +0200 Subject: [PATCH 25/30] Fix stable build --- zenoh/src/publication.rs | 8 ++--- zenoh/src/session.rs | 68 ++++++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/zenoh/src/publication.rs b/zenoh/src/publication.rs index 45458639eb..e7f5ec9c9f 100644 --- a/zenoh/src/publication.rs +++ b/zenoh/src/publication.rs @@ -16,13 +16,13 @@ use crate::net::primitives::Primitives; use crate::prelude::*; use crate::sample::{DataInfo, QoS, Sample, SampleFields, SampleKind}; +use crate::Id; use crate::SessionRef; use crate::Undeclarable; #[cfg(feature = "unstable")] use crate::{ bytes::{OptionZBytes, ZBytes}, handlers::{Callback, DefaultHandler, IntoHandler}, - Id, }; use std::fmt; use std::future::Ready; @@ -873,7 +873,6 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { fn create_one_shot_publisher(self) -> ZResult> { Ok(Publisher { session: self.session, - #[cfg(feature = "unstable")] id: 0, // This is a one shot Publisher key_expr: self.key_expr?, congestion_control: self.congestion_control, @@ -924,10 +923,9 @@ impl<'a, 'b> SyncResolve for PublisherBuilder<'a, 'b> { let session = self.session; session .declare_publisher_inner(key_expr.clone(), self.destination) - .map(|eid| Publisher { + .map(|id| Publisher { session, - #[cfg(feature = "unstable")] - id: eid, + id, key_expr, congestion_control: self.congestion_control, priority: self.priority, diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 23323a462a..2975b910ee 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -1140,22 +1140,25 @@ impl Session { let state = zread!(self.state); self.update_status_up(&state, &key_expr) } - } else if key_expr - .as_str() - .starts_with(crate::liveliness::PREFIX_LIVELINESS) - { - let primitives = state.primitives.as_ref().unwrap().clone(); - drop(state); + } else { + #[cfg(feature = "unstable")] + if key_expr + .as_str() + .starts_with(crate::liveliness::PREFIX_LIVELINESS) + { + let primitives = state.primitives.as_ref().unwrap().clone(); + drop(state); - primitives.send_interest(Interest { - id, - mode: InterestMode::CurrentFuture, - options: InterestOptions::KEYEXPRS + InterestOptions::SUBSCRIBERS, - wire_expr: Some(key_expr.to_wire(self).to_owned()), - ext_qos: network::ext::QoSType::DEFAULT, - ext_tstamp: None, - ext_nodeid: network::ext::NodeIdType::DEFAULT, - }); + primitives.send_interest(Interest { + id, + mode: InterestMode::CurrentFuture, + options: InterestOptions::KEYEXPRS + InterestOptions::SUBSCRIBERS, + wire_expr: Some(key_expr.to_wire(self).to_owned()), + ext_qos: network::ext::QoSType::DEFAULT, + ext_tstamp: None, + ext_nodeid: network::ext::NodeIdType::DEFAULT, + }); + } } Ok(sub_state) @@ -1214,23 +1217,26 @@ impl Session { self.update_status_down(&state, &sub_state.key_expr) } } - } else if sub_state - .key_expr - .as_str() - .starts_with(crate::liveliness::PREFIX_LIVELINESS) - { - let primitives = state.primitives.as_ref().unwrap().clone(); - drop(state); + } else { + #[cfg(feature = "unstable")] + if sub_state + .key_expr + .as_str() + .starts_with(crate::liveliness::PREFIX_LIVELINESS) + { + let primitives = state.primitives.as_ref().unwrap().clone(); + drop(state); - primitives.send_interest(Interest { - id: sub_state.id, - mode: InterestMode::Final, - options: InterestOptions::empty(), - wire_expr: None, - ext_qos: declare::ext::QoSType::DEFAULT, - ext_tstamp: None, - ext_nodeid: declare::ext::NodeIdType::DEFAULT, - }); + primitives.send_interest(Interest { + id: sub_state.id, + mode: InterestMode::Final, + options: InterestOptions::empty(), + wire_expr: None, + ext_qos: declare::ext::QoSType::DEFAULT, + ext_tstamp: None, + ext_nodeid: declare::ext::NodeIdType::DEFAULT, + }); + } } Ok(()) } else { From 6a9c4f7d90706843d97b6cb66b844999532fd4f5 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Thu, 18 Apr 2024 15:53:14 +0200 Subject: [PATCH 26/30] Fix test_acl --- zenoh/src/net/primitives/demux.rs | 2 +- zenoh/src/net/routing/hat/client/queries.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zenoh/src/net/primitives/demux.rs b/zenoh/src/net/primitives/demux.rs index e58e01a1b5..f6a2a60ac3 100644 --- a/zenoh/src/net/primitives/demux.rs +++ b/zenoh/src/net/primitives/demux.rs @@ -67,7 +67,7 @@ impl TransportPeerEventHandler for DeMux { match msg.body { NetworkBody::Push(m) => self.face.send_push(m), NetworkBody::Declare(m) => self.face.send_declare(m), - NetworkBody::Interest(_) => todo!(), + NetworkBody::Interest(m) => self.face.send_interest(m), NetworkBody::Request(m) => self.face.send_request(m), NetworkBody::Response(m) => self.face.send_response(m), NetworkBody::ResponseFinal(m) => self.face.send_response_final(m), diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index 57bcdda5a8..4b036fddd9 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -257,7 +257,7 @@ impl HatQueriesTrait for HatCode { _mode: InterestMode, _aggregate: bool, ) { - todo!() + // ignore } fn undeclare_qabl_interest( @@ -266,7 +266,7 @@ impl HatQueriesTrait for HatCode { _face: &mut Arc, _id: InterestId, ) { - todo!() + // ignore } fn declare_queryable( From 9a2a5397fdd8dde906292408035c89774e6c3b18 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Tue, 23 Apr 2024 12:21:45 +0200 Subject: [PATCH 27/30] Fix writer side filtering --- zenoh/src/net/routing/dispatcher/face.rs | 10 +++- zenoh/src/net/routing/hat/client/pubsub.rs | 67 ++++++++++++---------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/zenoh/src/net/routing/dispatcher/face.rs b/zenoh/src/net/routing/dispatcher/face.rs index 6af309a2ce..35758234e4 100644 --- a/zenoh/src/net/routing/dispatcher/face.rs +++ b/zenoh/src/net/routing/dispatcher/face.rs @@ -36,6 +36,12 @@ use zenoh_transport::multicast::TransportMulticast; #[cfg(feature = "stats")] use zenoh_transport::stats::TransportStats; +pub(crate) struct InterestState { + pub(crate) options: InterestOptions, + pub(crate) res: Option>, + pub(crate) finalized: bool, +} + pub struct FaceState { pub(crate) id: usize, pub(crate) zid: ZenohId, @@ -43,7 +49,7 @@ pub struct FaceState { #[cfg(feature = "stats")] pub(crate) stats: Option>, pub(crate) primitives: Arc, - pub(crate) local_interests: HashMap>, bool)>, + pub(crate) local_interests: HashMap, pub(crate) remote_key_interests: HashMap>>, pub(crate) local_mappings: HashMap>, pub(crate) remote_mappings: HashMap>, @@ -317,7 +323,7 @@ impl Primitives for Face { get_mut_unchecked(&mut self.state.clone()) .local_interests .entry(id) - .and_modify(|interest| interest.2 = true); + .and_modify(|interest| interest.finalized = true); } } } diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index 72618a1018..b87bfa4757 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -13,7 +13,7 @@ // use super::{face_hat, face_hat_mut, get_routes_entries}; use super::{HatCode, HatFace}; -use crate::net::routing::dispatcher::face::FaceState; +use crate::net::routing::dispatcher::face::{FaceState, InterestState}; use crate::net::routing::dispatcher::resource::{NodeId, Resource, SessionContext}; use crate::net::routing::dispatcher::tables::Tables; use crate::net::routing::dispatcher::tables::{Route, RoutingExpr}; @@ -248,9 +248,14 @@ pub(super) fn pubsub_new_face(tables: &mut Tables, face: &mut Arc) { for res in face_hat_mut!(&mut src_face).remote_sub_interests.values() { let id = face_hat!(face).next_id.fetch_add(1, Ordering::SeqCst); let options = InterestOptions::KEYEXPRS + InterestOptions::SUBSCRIBERS; - get_mut_unchecked(face) - .local_interests - .insert(id, (options, res.as_ref().map(|res| (*res).clone()), false)); + get_mut_unchecked(face).local_interests.insert( + id, + InterestState { + options, + res: res.as_ref().map(|res| (*res).clone()), + finalized: false, + }, + ); let wire_expr = res.as_ref().map(|res| Resource::decl_key(res, face)); face.primitives.send_interest(RoutingContext::with_expr( Interest { @@ -293,11 +298,11 @@ impl HatPubSubTrait for HatCode { let options = InterestOptions::KEYEXPRS + InterestOptions::SUBSCRIBERS; get_mut_unchecked(dst_face).local_interests.insert( id, - ( + InterestState { options, - res.as_ref().map(|res| (*res).clone()), - mode != InterestMode::Future, - ), + res: res.as_ref().map(|res| (*res).clone()), + finalized: mode == InterestMode::Future, + }, ); let wire_expr = res.as_ref().map(|res| Resource::decl_key(res, dst_face)); dst_face.primitives.send_interest(RoutingContext::with_expr( @@ -340,8 +345,9 @@ impl HatPubSubTrait for HatCode { .cloned() .collect::>() { - let (int, res, _) = dst_face.local_interests.get(&id).unwrap(); - if int.subscribers() && (*res == interest) { + let local_interest = dst_face.local_interests.get(&id).unwrap(); + if local_interest.options.subscribers() && (local_interest.res == interest) + { dst_face.primitives.send_interest(RoutingContext::with_expr( Interest { id, @@ -352,7 +358,11 @@ impl HatPubSubTrait for HatCode { ext_tstamp: None, ext_nodeid: ext::NodeIdType::DEFAULT, }, - res.as_ref().map(|res| res.expr()).unwrap_or_default(), + local_interest + .res + .as_ref() + .map(|res| res.expr()) + .unwrap_or_default(), )); get_mut_unchecked(dst_face).local_interests.remove(&id); } @@ -426,25 +436,22 @@ impl HatPubSubTrait for HatCode { .values() .filter(|f| f.whatami != WhatAmI::Client) { - if face - .local_interests - .values() - .any(|(interest, res, finalized)| { - *finalized - && interest.subscribers() - && res - .as_ref() - .map(|res| { - KeyExpr::try_from(res.expr()) - .and_then(|intres| { - KeyExpr::try_from(expr.full_expr()) - .map(|putres| intres.includes(&putres)) - }) - .unwrap_or(false) - }) - .unwrap_or(true) - }) - { + if face.local_interests.values().any(|interest| { + interest.finalized + && interest.options.subscribers() + && interest + .res + .as_ref() + .map(|res| { + KeyExpr::try_from(res.expr()) + .and_then(|intres| { + KeyExpr::try_from(expr.full_expr()) + .map(|putres| intres.includes(&putres)) + }) + .unwrap_or(false) + }) + .unwrap_or(true) + }) { if face_hat!(face).remote_subs.values().any(|sub| { KeyExpr::try_from(sub.expr()) .and_then(|subres| { From 0d5df181de8498d75d9ee8905c4f554343e9209e Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Thu, 2 May 2024 19:00:54 +0200 Subject: [PATCH 28/30] Add separate functions to compute matching status --- zenoh/src/net/routing/dispatcher/pubsub.rs | 17 +- zenoh/src/net/routing/hat/client/pubsub.rs | 58 +++++++ .../net/routing/hat/linkstate_peer/pubsub.rs | 139 +++++++++++---- zenoh/src/net/routing/hat/mod.rs | 10 +- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 32 ++++ zenoh/src/net/routing/hat/router/pubsub.rs | 158 ++++++++++++++---- zenoh/src/session.rs | 24 ++- 7 files changed, 345 insertions(+), 93 deletions(-) diff --git a/zenoh/src/net/routing/dispatcher/pubsub.rs b/zenoh/src/net/routing/dispatcher/pubsub.rs index f49943e1ec..37ab295c26 100644 --- a/zenoh/src/net/routing/dispatcher/pubsub.rs +++ b/zenoh/src/net/routing/dispatcher/pubsub.rs @@ -15,6 +15,8 @@ use super::face::FaceState; use super::resource::{DataRoutes, Direction, Resource}; use super::tables::{NodeId, Route, RoutingExpr, Tables, TablesLock}; use crate::net::routing::hat::HatTrait; +#[cfg(feature = "unstable")] +use crate::KeyExpr; use std::collections::HashMap; use std::sync::Arc; use zenoh_core::zread; @@ -407,18 +409,11 @@ fn get_data_route( #[zenoh_macros::unstable] #[inline] -pub(crate) fn get_local_data_route( +pub(crate) fn get_matching_subscriptions( tables: &Tables, - res: &Option>, - expr: &mut RoutingExpr, -) -> Arc { - res.as_ref() - .and_then(|res| res.data_route(WhatAmI::Client, 0)) - .unwrap_or_else(|| { - tables - .hat_code - .compute_data_route(tables, expr, 0, WhatAmI::Client) - }) + key_expr: &KeyExpr<'_>, +) -> HashMap> { + tables.hat_code.get_matching_subscriptions(tables, key_expr) } #[cfg(feature = "stats")] diff --git a/zenoh/src/net/routing/hat/client/pubsub.rs b/zenoh/src/net/routing/hat/client/pubsub.rs index 1547170d46..7373bfb0db 100644 --- a/zenoh/src/net/routing/hat/client/pubsub.rs +++ b/zenoh/src/net/routing/hat/client/pubsub.rs @@ -518,4 +518,62 @@ impl HatPubSubTrait for HatCode { fn get_data_routes_entries(&self, _tables: &Tables) -> RoutesIndexes { get_routes_entries() } + + fn get_matching_subscriptions( + &self, + tables: &Tables, + key_expr: &KeyExpr<'_>, + ) -> HashMap> { + let mut matching_subscriptions = HashMap::new(); + if key_expr.ends_with('/') { + return matching_subscriptions; + } + tracing::trace!("get_matching_subscriptions({})", key_expr,); + + for face in tables + .faces + .values() + .filter(|f| f.whatami != WhatAmI::Client) + { + if face.local_interests.values().any(|interest| { + interest.finalized + && interest.options.subscribers() + && interest + .res + .as_ref() + .map(|res| { + KeyExpr::try_from(res.expr()) + .map(|intres| intres.includes(key_expr)) + .unwrap_or(false) + }) + .unwrap_or(true) + }) && face_hat!(face).remote_subs.values().any(|sub| { + KeyExpr::try_from(sub.expr()) + .map(|subres| subres.intersects(key_expr)) + .unwrap_or(false) + }) { + matching_subscriptions.insert(face.id, face.clone()); + } + } + + let res = Resource::get_resource(&tables.root_res, key_expr); + let matches = res + .as_ref() + .and_then(|res| res.context.as_ref()) + .map(|ctx| Cow::from(&ctx.matches)) + .unwrap_or_else(|| Cow::from(Resource::get_matches(tables, key_expr))); + + for mres in matches.iter() { + let mres = mres.upgrade().unwrap(); + + for (sid, context) in &mres.session_ctxs { + if context.subs.is_some() && context.face.whatami == WhatAmI::Client { + matching_subscriptions + .entry(*sid) + .or_insert_with(|| context.face.clone()); + } + } + } + matching_subscriptions + } } diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index 1e7a2b7cf9..9c6c82dba6 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -22,6 +22,7 @@ use crate::net::routing::dispatcher::tables::{Route, RoutingExpr}; use crate::net::routing::hat::{CurrentFutureTrait, HatPubSubTrait, Sources}; use crate::net::routing::router::RoutesIndexes; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; +use crate::KeyExpr; use petgraph::graph::NodeIndex; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; @@ -601,39 +602,6 @@ pub(super) fn pubsub_tree_change(tables: &mut Tables, new_childs: &[Vec, -) { - if net.trees.len() > source as usize { - for sub in subs { - if let Some(sub_idx) = net.get_idx(sub) { - if net.trees[source as usize].directions.len() > sub_idx.index() { - if let Some(direction) = net.trees[source as usize].directions[sub_idx.index()] - { - if net.graph.contains_node(direction) { - if let Some(face) = tables.get_face(&net.graph[direction].zid) { - route.entry(face.id).or_insert_with(|| { - let key_expr = - Resource::get_best_key(expr.prefix, expr.suffix, face.id); - (face.clone(), key_expr.to_owned(), source) - }); - } - } - } - } - } - } - } else { - tracing::trace!("Tree for node sid:{} not yet ready", source); - } -} - impl HatPubSubTrait for HatCode { fn declare_sub_interest( &self, @@ -833,6 +801,43 @@ impl HatPubSubTrait for HatCode { source: NodeId, source_type: WhatAmI, ) -> Arc { + #[inline] + fn insert_faces_for_subs( + route: &mut Route, + expr: &RoutingExpr, + tables: &Tables, + net: &Network, + source: NodeId, + subs: &HashSet, + ) { + if net.trees.len() > source as usize { + for sub in subs { + if let Some(sub_idx) = net.get_idx(sub) { + if net.trees[source as usize].directions.len() > sub_idx.index() { + if let Some(direction) = + net.trees[source as usize].directions[sub_idx.index()] + { + if net.graph.contains_node(direction) { + if let Some(face) = tables.get_face(&net.graph[direction].zid) { + route.entry(face.id).or_insert_with(|| { + let key_expr = Resource::get_best_key( + expr.prefix, + expr.suffix, + face.id, + ); + (face.clone(), key_expr.to_owned(), source) + }); + } + } + } + } + } + } + } else { + tracing::trace!("Tree for node sid:{} not yet ready", source); + } + } + let mut route = HashMap::new(); let key_expr = expr.full_expr(); if key_expr.ends_with('/') { @@ -908,4 +913,72 @@ impl HatPubSubTrait for HatCode { fn get_data_routes_entries(&self, tables: &Tables) -> RoutesIndexes { get_routes_entries(tables) } + + fn get_matching_subscriptions( + &self, + tables: &Tables, + key_expr: &KeyExpr<'_>, + ) -> HashMap> { + #[inline] + fn insert_faces_for_subs( + route: &mut HashMap>, + tables: &Tables, + net: &Network, + source: usize, + subs: &HashSet, + ) { + if net.trees.len() > source { + for sub in subs { + if let Some(sub_idx) = net.get_idx(sub) { + if net.trees[source].directions.len() > sub_idx.index() { + if let Some(direction) = net.trees[source].directions[sub_idx.index()] { + if net.graph.contains_node(direction) { + if let Some(face) = tables.get_face(&net.graph[direction].zid) { + route.entry(face.id).or_insert_with(|| face.clone()); + } + } + } + } + } + } + } else { + tracing::trace!("Tree for node sid:{} not yet ready", source); + } + } + + let mut matching_subscriptions = HashMap::new(); + if key_expr.ends_with('/') { + return matching_subscriptions; + } + tracing::trace!("get_matching_subscriptions({})", key_expr,); + + let res = Resource::get_resource(&tables.root_res, key_expr); + let matches = res + .as_ref() + .and_then(|res| res.context.as_ref()) + .map(|ctx| Cow::from(&ctx.matches)) + .unwrap_or_else(|| Cow::from(Resource::get_matches(tables, key_expr))); + + for mres in matches.iter() { + let mres = mres.upgrade().unwrap(); + + let net = hat!(tables).peers_net.as_ref().unwrap(); + insert_faces_for_subs( + &mut matching_subscriptions, + tables, + net, + net.idx.index(), + &res_hat!(mres).peer_subs, + ); + + for (sid, context) in &mres.session_ctxs { + if context.subs.is_some() { + matching_subscriptions + .entry(*sid) + .or_insert_with(|| context.face.clone()); + } + } + } + matching_subscriptions + } } diff --git a/zenoh/src/net/routing/hat/mod.rs b/zenoh/src/net/routing/hat/mod.rs index 7bfca4ee71..7bdd620c14 100644 --- a/zenoh/src/net/routing/hat/mod.rs +++ b/zenoh/src/net/routing/hat/mod.rs @@ -24,8 +24,8 @@ use super::{ }, router::RoutesIndexes, }; -use crate::runtime::Runtime; -use std::{any::Any, sync::Arc}; +use crate::{runtime::Runtime, KeyExpr}; +use std::{any::Any, collections::HashMap, sync::Arc}; use zenoh_buffers::ZBuf; use zenoh_config::{unwrap_or_default, Config, WhatAmI, ZenohId}; use zenoh_protocol::{ @@ -179,6 +179,12 @@ pub(crate) trait HatPubSubTrait { ) -> Arc; fn get_data_routes_entries(&self, tables: &Tables) -> RoutesIndexes; + + fn get_matching_subscriptions( + &self, + tables: &Tables, + key_expr: &KeyExpr<'_>, + ) -> HashMap>; } pub(crate) trait HatQueriesTrait { diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index ab2d143ecf..4410b5d870 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -20,6 +20,7 @@ use crate::net::routing::dispatcher::tables::{Route, RoutingExpr}; use crate::net::routing::hat::{CurrentFutureTrait, HatPubSubTrait, Sources}; use crate::net::routing::router::RoutesIndexes; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; +use crate::KeyExpr; use std::borrow::Cow; use std::collections::HashMap; use std::sync::atomic::Ordering; @@ -600,4 +601,35 @@ impl HatPubSubTrait for HatCode { fn get_data_routes_entries(&self, _tables: &Tables) -> RoutesIndexes { get_routes_entries() } + + fn get_matching_subscriptions( + &self, + tables: &Tables, + key_expr: &KeyExpr<'_>, + ) -> HashMap> { + let mut matching_subscriptions = HashMap::new(); + if key_expr.ends_with('/') { + return matching_subscriptions; + } + tracing::trace!("get_matching_subscriptions({})", key_expr,); + let res = Resource::get_resource(&tables.root_res, key_expr); + let matches = res + .as_ref() + .and_then(|res| res.context.as_ref()) + .map(|ctx| Cow::from(&ctx.matches)) + .unwrap_or_else(|| Cow::from(Resource::get_matches(tables, key_expr))); + + for mres in matches.iter() { + let mres = mres.upgrade().unwrap(); + + for (sid, context) in &mres.session_ctxs { + if context.subs.is_some() { + matching_subscriptions + .entry(*sid) + .or_insert_with(|| context.face.clone()); + } + } + } + matching_subscriptions + } } diff --git a/zenoh/src/net/routing/hat/router/pubsub.rs b/zenoh/src/net/routing/hat/router/pubsub.rs index 62fc0eee2f..2e4603c72f 100644 --- a/zenoh/src/net/routing/hat/router/pubsub.rs +++ b/zenoh/src/net/routing/hat/router/pubsub.rs @@ -22,6 +22,7 @@ use crate::net::routing::dispatcher::tables::{Route, RoutingExpr}; use crate::net::routing::hat::{CurrentFutureTrait, HatPubSubTrait, Sources}; use crate::net::routing::router::RoutesIndexes; use crate::net::routing::{RoutingContext, PREFIX_LIVELINESS}; +use crate::KeyExpr; use petgraph::graph::NodeIndex; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; @@ -901,39 +902,6 @@ pub(super) fn pubsub_linkstate_change(tables: &mut Tables, zid: &ZenohId, links: } } -#[inline] -fn insert_faces_for_subs( - route: &mut Route, - expr: &RoutingExpr, - tables: &Tables, - net: &Network, - source: NodeId, - subs: &HashSet, -) { - if net.trees.len() > source as usize { - for sub in subs { - if let Some(sub_idx) = net.get_idx(sub) { - if net.trees[source as usize].directions.len() > sub_idx.index() { - if let Some(direction) = net.trees[source as usize].directions[sub_idx.index()] - { - if net.graph.contains_node(direction) { - if let Some(face) = tables.get_face(&net.graph[direction].zid) { - route.entry(face.id).or_insert_with(|| { - let key_expr = - Resource::get_best_key(expr.prefix, expr.suffix, face.id); - (face.clone(), key_expr.to_owned(), source) - }); - } - } - } - } - } - } - } else { - tracing::trace!("Tree for node sid:{} not yet ready", source); - } -} - impl HatPubSubTrait for HatCode { fn declare_sub_interest( &self, @@ -1176,6 +1144,43 @@ impl HatPubSubTrait for HatCode { source: NodeId, source_type: WhatAmI, ) -> Arc { + #[inline] + fn insert_faces_for_subs( + route: &mut Route, + expr: &RoutingExpr, + tables: &Tables, + net: &Network, + source: NodeId, + subs: &HashSet, + ) { + if net.trees.len() > source as usize { + for sub in subs { + if let Some(sub_idx) = net.get_idx(sub) { + if net.trees[source as usize].directions.len() > sub_idx.index() { + if let Some(direction) = + net.trees[source as usize].directions[sub_idx.index()] + { + if net.graph.contains_node(direction) { + if let Some(face) = tables.get_face(&net.graph[direction].zid) { + route.entry(face.id).or_insert_with(|| { + let key_expr = Resource::get_best_key( + expr.prefix, + expr.suffix, + face.id, + ); + (face.clone(), key_expr.to_owned(), source) + }); + } + } + } + } + } + } + } else { + tracing::trace!("Tree for node sid:{} not yet ready", source); + } + } + let mut route = HashMap::new(); let key_expr = expr.full_expr(); if key_expr.ends_with('/') { @@ -1267,4 +1272,91 @@ impl HatPubSubTrait for HatCode { fn get_data_routes_entries(&self, tables: &Tables) -> RoutesIndexes { get_routes_entries(tables) } + + fn get_matching_subscriptions( + &self, + tables: &Tables, + key_expr: &KeyExpr<'_>, + ) -> HashMap> { + #[inline] + fn insert_faces_for_subs( + route: &mut HashMap>, + tables: &Tables, + net: &Network, + source: usize, + subs: &HashSet, + ) { + if net.trees.len() > source { + for sub in subs { + if let Some(sub_idx) = net.get_idx(sub) { + if net.trees[source].directions.len() > sub_idx.index() { + if let Some(direction) = net.trees[source].directions[sub_idx.index()] { + if net.graph.contains_node(direction) { + if let Some(face) = tables.get_face(&net.graph[direction].zid) { + route.entry(face.id).or_insert_with(|| face.clone()); + } + } + } + } + } + } + } else { + tracing::trace!("Tree for node sid:{} not yet ready", source); + } + } + + let mut matching_subscriptions = HashMap::new(); + if key_expr.ends_with('/') { + return matching_subscriptions; + } + tracing::trace!("get_matching_subscriptions({})", key_expr,); + + let res = Resource::get_resource(&tables.root_res, key_expr); + let matches = res + .as_ref() + .and_then(|res| res.context.as_ref()) + .map(|ctx| Cow::from(&ctx.matches)) + .unwrap_or_else(|| Cow::from(Resource::get_matches(tables, key_expr))); + + let master = !hat!(tables).full_net(WhatAmI::Peer) + || *hat!(tables).elect_router(&tables.zid, key_expr, hat!(tables).shared_nodes.iter()) + == tables.zid; + + for mres in matches.iter() { + let mres = mres.upgrade().unwrap(); + + if master { + let net = hat!(tables).routers_net.as_ref().unwrap(); + insert_faces_for_subs( + &mut matching_subscriptions, + tables, + net, + net.idx.index(), + &res_hat!(mres).router_subs, + ); + } + + if hat!(tables).full_net(WhatAmI::Peer) { + let net = hat!(tables).peers_net.as_ref().unwrap(); + insert_faces_for_subs( + &mut matching_subscriptions, + tables, + net, + net.idx.index(), + &res_hat!(mres).peer_subs, + ); + } + + if master { + for (sid, context) in &mres.session_ctxs { + if context.subs.is_some() && context.face.whatami != WhatAmI::Router { + matching_subscriptions + .entry(*sid) + .or_insert_with(|| context.face.clone()); + } + } + } + } + matching_subscriptions + } } diff --git a/zenoh/src/session.rs b/zenoh/src/session.rs index 0d1c3a1a6f..7c09551031 100644 --- a/zenoh/src/session.rs +++ b/zenoh/src/session.rs @@ -1415,33 +1415,29 @@ impl Session { key_expr: &KeyExpr, destination: Locality, ) -> ZResult { - use crate::net::routing::dispatcher::tables::RoutingExpr; let router = self.runtime.router(); let tables = zread!(router.tables.tables); - let res = crate::net::routing::dispatcher::resource::Resource::get_resource( - &tables.root_res, - key_expr.as_str(), - ); - let route = crate::net::routing::dispatcher::pubsub::get_local_data_route( - &tables, - &res, - &mut RoutingExpr::new(&tables.root_res, key_expr.as_str()), - ); + let matching_subscriptions = + crate::net::routing::dispatcher::pubsub::get_matching_subscriptions(&tables, key_expr); drop(tables); let matching = match destination { - Locality::Any => !route.is_empty(), + Locality::Any => !matching_subscriptions.is_empty(), Locality::Remote => { if let Some(face) = zread!(self.state).primitives.as_ref() { - route.values().any(|dir| !Arc::ptr_eq(&dir.0, &face.state)) + matching_subscriptions + .values() + .any(|dir| !Arc::ptr_eq(dir, &face.state)) } else { - !route.is_empty() + !matching_subscriptions.is_empty() } } Locality::SessionLocal => { if let Some(face) = zread!(self.state).primitives.as_ref() { - route.values().any(|dir| Arc::ptr_eq(&dir.0, &face.state)) + matching_subscriptions + .values() + .any(|dir| Arc::ptr_eq(dir, &face.state)) } else { false } From b43b1598133e0a0897592cc18851358f285ca38b Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 3 May 2024 11:39:28 +0200 Subject: [PATCH 29/30] Fix unstable imports --- zenoh/src/api/publication.rs | 3 +-- zenoh/src/net/routing/dispatcher/pubsub.rs | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/zenoh/src/api/publication.rs b/zenoh/src/api/publication.rs index 12cb758c8e..d72f18739d 100644 --- a/zenoh/src/api/publication.rs +++ b/zenoh/src/api/publication.rs @@ -33,7 +33,6 @@ use zenoh_result::{Error, ZResult}; use { crate::api::handlers::{Callback, DefaultHandler, IntoHandler}, crate::api::sample::SourceInfo, - crate::api::Id, zenoh_protocol::core::EntityGlobalId, }; @@ -48,7 +47,7 @@ use super::{ sample::{DataInfo, Locality, QoS, Sample, SampleFields, SampleKind}, session::{SessionRef, Undeclarable}, }; -use crate::net::primitives::Primitives; +use crate::{api::Id, net::primitives::Primitives}; pub(crate) struct PublisherState { pub(crate) id: Id, diff --git a/zenoh/src/net/routing/dispatcher/pubsub.rs b/zenoh/src/net/routing/dispatcher/pubsub.rs index 4ff67ca026..4e69e45dc3 100644 --- a/zenoh/src/net/routing/dispatcher/pubsub.rs +++ b/zenoh/src/net/routing/dispatcher/pubsub.rs @@ -30,7 +30,9 @@ use super::{ resource::{DataRoutes, Direction, Resource}, tables::{NodeId, Route, RoutingExpr, Tables, TablesLock}, }; -use crate::{key_expr::KeyExpr, net::routing::hat::HatTrait}; +#[zenoh_macros::unstable] +use crate::key_expr::KeyExpr; +use crate::net::routing::hat::HatTrait; pub(crate) fn declare_sub_interest( hat_code: &(dyn HatTrait + Send + Sync), From 0eb4e9834ffd7ad81ee948930dfa64dab7e7d0d5 Mon Sep 17 00:00:00 2001 From: OlivierHecart Date: Fri, 3 May 2024 12:23:00 +0200 Subject: [PATCH 30/30] Remove useless checks --- zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs | 8 +------- zenoh/src/net/routing/hat/linkstate_peer/queries.rs | 5 +---- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 8 +------- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 5 +---- 4 files changed, 4 insertions(+), 22 deletions(-) diff --git a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs index 1b522ab8f7..135f899656 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/pubsub.rs @@ -891,13 +891,7 @@ impl HatPubSubTrait for HatCode { for (sid, context) in &mres.session_ctxs { if context.subs.is_some() - && match tables.whatami { - WhatAmI::Router => context.face.whatami != WhatAmI::Router, - _ => { - source_type == WhatAmI::Client - || context.face.whatami == WhatAmI::Client - } - } + && (source_type == WhatAmI::Client || context.face.whatami == WhatAmI::Client) { route.entry(*sid).or_insert_with(|| { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, *sid); diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index 2147f95ed6..3d9babbd5d 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -934,10 +934,7 @@ impl HatQueriesTrait for HatCode { ); for (sid, context) in &mres.session_ctxs { - if match tables.whatami { - WhatAmI::Router => context.face.whatami != WhatAmI::Router, - _ => source_type == WhatAmI::Client || context.face.whatami == WhatAmI::Client, - } { + if source_type == WhatAmI::Client || context.face.whatami == WhatAmI::Client { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, *sid); if let Some(qabl_info) = context.qabl.as_ref() { route.push(QueryTargetQabl { diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index bda9d0b1cd..31172e2804 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -577,13 +577,7 @@ impl HatPubSubTrait for HatCode { for (sid, context) in &mres.session_ctxs { if context.subs.is_some() - && match tables.whatami { - WhatAmI::Router => context.face.whatami != WhatAmI::Router, - _ => { - source_type == WhatAmI::Client - || context.face.whatami == WhatAmI::Client - } - } + && (source_type == WhatAmI::Client || context.face.whatami == WhatAmI::Client) { route.entry(*sid).or_insert_with(|| { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, *sid); diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index 67ecc16130..1801f66c84 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -560,10 +560,7 @@ impl HatQueriesTrait for HatCode { let mres = mres.upgrade().unwrap(); let complete = DEFAULT_INCLUDER.includes(mres.expr().as_bytes(), key_expr.as_bytes()); for (sid, context) in &mres.session_ctxs { - if match tables.whatami { - WhatAmI::Router => context.face.whatami != WhatAmI::Router, - _ => source_type == WhatAmI::Client || context.face.whatami == WhatAmI::Client, - } { + if source_type == WhatAmI::Client || context.face.whatami == WhatAmI::Client { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, *sid); if let Some(qabl_info) = context.qabl.as_ref() { route.push(QueryTargetQabl {