From 147ebc38a9968eaaf16919cb5f71d27800b76315 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 28 Aug 2024 07:07:38 +0200 Subject: [PATCH 01/34] feat!: bind callback subscriber/queryable to session lifetime To determine if the entity is callback-only, the only elegant way I've found is the rule "handler is ZST means callback-only". Unless users starts writing fancy implementations, it should be correct 100% of the time. Session entities now uses weak references, except publishers because it would impact performances. Weak references also solves the issue of mass undeclarations before closing the session (when the session is an `Arc`), except for publishers. `Undeclarable` trait has been refactored a little bit to better match its use in the code. --- examples/examples/z_sub_thr.rs | 4 +- zenoh/src/api/key_expr.rs | 5 +- zenoh/src/api/liveliness.rs | 59 +++++----- zenoh/src/api/publisher.rs | 97 ++++++---------- zenoh/src/api/queryable.rs | 201 ++++++++++++++++++--------------- zenoh/src/api/session.rs | 69 ++++++----- zenoh/src/api/subscriber.rs | 183 +++++++++++++----------------- zenoh/src/lib.rs | 4 +- 8 files changed, 297 insertions(+), 325 deletions(-) diff --git a/examples/examples/z_sub_thr.rs b/examples/examples/z_sub_thr.rs index 78626d1d1d..460a8dfe73 100644 --- a/examples/examples/z_sub_thr.rs +++ b/examples/examples/z_sub_thr.rs @@ -87,9 +87,7 @@ fn main() { } }) .wait() - .unwrap() - // Make the subscriber run in background, until the session is closed. - .background(); + .unwrap(); println!("Press CTRL-C to quit..."); std::thread::park(); diff --git a/zenoh/src/api/key_expr.rs b/zenoh/src/api/key_expr.rs index fc472e0db3..bde77f5d32 100644 --- a/zenoh/src/api/key_expr.rs +++ b/zenoh/src/api/key_expr.rs @@ -549,8 +549,9 @@ impl<'a> KeyExpr<'a> { } } -impl<'a> UndeclarableSealed<&'a Session, KeyExprUndeclaration<'a>> for KeyExpr<'a> { - fn undeclare_inner(self, session: &'a Session) -> KeyExprUndeclaration<'a> { +impl<'a> UndeclarableSealed<&'a Session> for KeyExpr<'a> { + type Undeclaration = KeyExprUndeclaration<'a>; + fn undeclare_inner(self, session: &'a Session) -> Self::Undeclaration { KeyExprUndeclaration { session, expr: self, diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 64f87c6de5..bb068b4e52 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -15,10 +15,12 @@ use std::{ convert::TryInto, future::{IntoFuture, Ready}, + mem::size_of, sync::Arc, time::Duration, }; +use tracing::error; use zenoh_config::unwrap_or_default; use zenoh_core::{Resolvable, Resolve, Result as ZResult, Wait}; @@ -31,6 +33,7 @@ use super::{ subscriber::{Subscriber, SubscriberInner}, Id, }; +use crate::api::session::WeakSessionRef; /// A structure with functions to declare a /// [`LivelinessToken`](LivelinessToken), query @@ -254,7 +257,7 @@ impl Wait for LivelinessTokenBuilder<'_, '_> { session .declare_liveliness_inner(&key_expr) .map(|tok_state| LivelinessToken { - session, + session: session.into(), state: tok_state, undeclare_on_drop: true, }) @@ -288,7 +291,7 @@ pub(crate) struct LivelinessTokenState { /// that declared the token has Zenoh connectivity with the Zenoh application /// that monitors it. /// -/// `LivelinessTokens` are automatically undeclared when dropped. +/// Liveliness tokens are automatically undeclared when dropped. /// /// # Examples /// ```no_run @@ -307,12 +310,12 @@ pub(crate) struct LivelinessTokenState { #[zenoh_macros::unstable] #[derive(Debug)] pub struct LivelinessToken<'a> { - pub(crate) session: SessionRef<'a>, - pub(crate) state: Arc, + session: WeakSessionRef<'a>, + state: Arc, undeclare_on_drop: bool, } -/// A [`Resolvable`] returned when undeclaring a [`LivelinessToken`](LivelinessToken). +/// A [`Resolvable`] returned when undeclaring a [`LivelinessToken`]. /// /// # Examples /// ``` @@ -332,9 +335,7 @@ pub struct LivelinessToken<'a> { /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[zenoh_macros::unstable] -pub struct LivelinessTokenUndeclaration<'a> { - token: LivelinessToken<'a>, -} +pub struct LivelinessTokenUndeclaration<'a>(LivelinessToken<'a>); #[zenoh_macros::unstable] impl Resolvable for LivelinessTokenUndeclaration<'_> { @@ -344,9 +345,7 @@ impl Resolvable for LivelinessTokenUndeclaration<'_> { #[zenoh_macros::unstable] impl Wait for LivelinessTokenUndeclaration<'_> { fn wait(mut self) -> ::To { - // set the flag first to avoid double panic if this function panic - self.token.undeclare_on_drop = false; - self.token.session.undeclare_liveliness(self.token.state.id) + self.0.undeclare_impl() } } @@ -362,11 +361,7 @@ impl<'a> IntoFuture for LivelinessTokenUndeclaration<'a> { #[zenoh_macros::unstable] impl<'a> LivelinessToken<'a> { - /// Undeclare a [`LivelinessToken`]. - /// - /// LivelinessTokens are automatically closed when dropped, - /// but you may want to use this function to handle errors or - /// undeclare the LivelinessToken asynchronously. + /// Undeclare the [`LivelinessToken`]. /// /// # Examples /// ``` @@ -389,21 +384,21 @@ impl<'a> LivelinessToken<'a> { UndeclarableSealed::undeclare_inner(self, ()) } - /// Keep this liveliness token in background, until the session is closed. - #[inline] - #[zenoh_macros::unstable] - pub fn background(mut self) { - // It's not necessary to undeclare this resource when session close, as other sessions - // will clean all resources related to the closed one. - // So we can just never undeclare it. + fn undeclare_impl(&mut self) -> ZResult<()> { self.undeclare_on_drop = false; + match self.session.upgrade() { + Some(session) => session.undeclare_liveliness(self.state.id), + None => Ok(()), + } } } #[zenoh_macros::unstable] -impl<'a> UndeclarableSealed<(), LivelinessTokenUndeclaration<'a>> for LivelinessToken<'a> { - fn undeclare_inner(self, _: ()) -> LivelinessTokenUndeclaration<'a> { - LivelinessTokenUndeclaration { token: self } +impl<'a> UndeclarableSealed<()> for LivelinessToken<'a> { + type Undeclaration = LivelinessTokenUndeclaration<'a>; + + fn undeclare_inner(self, _: ()) -> Self::Undeclaration { + LivelinessTokenUndeclaration(self) } } @@ -411,7 +406,9 @@ impl<'a> UndeclarableSealed<(), LivelinessTokenUndeclaration<'a>> for Liveliness impl Drop for LivelinessToken<'_> { fn drop(&mut self) { if self.undeclare_on_drop { - let _ = self.session.undeclare_liveliness(self.state.id); + if let Err(error) = self.undeclare_impl() { + error!(error); + } } } } @@ -578,11 +575,13 @@ where session .declare_liveliness_subscriber_inner(&key_expr, Locality::default(), callback) .map(|sub_state| Subscriber { - subscriber: SubscriberInner { - session, + inner: SubscriberInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: session.into(), state: sub_state, kind: SubscriberKind::LivelinessSubscriber, - undeclare_on_drop: true, + undeclare_on_drop: size_of::() > 0, }, handler, }) diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 02cfb406c9..4371255ac4 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -21,6 +21,7 @@ use std::{ }; use futures::Sink; +use tracing::error; use zenoh_core::{zread, Resolvable, Resolve, Wait}; use zenoh_protocol::{ core::{CongestionControl, Reliability}, @@ -78,7 +79,7 @@ impl fmt::Debug for PublisherState { #[derive(Clone)] pub enum PublisherRef<'a> { Borrow(&'a Publisher<'a>), - Shared(std::sync::Arc>), + Shared(Arc>), } #[zenoh_macros::unstable] @@ -349,7 +350,7 @@ impl<'a> Publisher<'a> { } } - /// Undeclares the [`Publisher`], informing the network that it needn't optimize publications for its key expression anymore. + /// Undeclare the [`Publisher`], informing the network that it needn't optimize publications for its key expression anymore. /// /// # Examples /// ``` @@ -366,13 +367,16 @@ impl<'a> Publisher<'a> { UndeclarableSealed::undeclare_inner(self, ()) } - #[cfg(feature = "unstable")] - fn undeclare_matching_listeners(&self) -> ZResult<()> { - let ids: Vec = zlock!(self.matching_listeners).drain().collect(); - for id in ids { - self.session.undeclare_matches_listener_inner(id)? + fn undeclare_impl(&mut self) -> ZResult<()> { + self.undeclare_on_drop = false; + #[cfg(feature = "unstable")] + { + let ids: Vec = zlock!(self.matching_listeners).drain().collect(); + for id in ids { + self.session.undeclare_matches_listener_inner(id)? + } } - Ok(()) + self.session.undeclare_publisher_inner(self.id) } } @@ -464,9 +468,11 @@ impl PublisherDeclarations for std::sync::Arc> { } } -impl<'a> UndeclarableSealed<(), PublisherUndeclaration<'a>> for Publisher<'a> { - fn undeclare_inner(self, _: ()) -> PublisherUndeclaration<'a> { - PublisherUndeclaration { publisher: self } +impl<'a> UndeclarableSealed<()> for Publisher<'a> { + type Undeclaration = PublisherUndeclaration<'a>; + + fn undeclare_inner(self, _: ()) -> Self::Undeclaration { + PublisherUndeclaration(self) } } @@ -484,9 +490,7 @@ impl<'a> UndeclarableSealed<(), PublisherUndeclaration<'a>> for Publisher<'a> { /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct PublisherUndeclaration<'a> { - publisher: Publisher<'a>, -} +pub struct PublisherUndeclaration<'a>(Publisher<'a>); impl Resolvable for PublisherUndeclaration<'_> { type To = ZResult<()>; @@ -494,13 +498,7 @@ impl Resolvable for PublisherUndeclaration<'_> { impl Wait for PublisherUndeclaration<'_> { fn wait(mut self) -> ::To { - // set the flag first to avoid double panic if this function panic - self.publisher.undeclare_on_drop = false; - #[cfg(feature = "unstable")] - self.publisher.undeclare_matching_listeners()?; - self.publisher - .session - .undeclare_publisher_inner(self.publisher.id) + self.0.undeclare_impl() } } @@ -516,9 +514,9 @@ impl IntoFuture for PublisherUndeclaration<'_> { impl Drop for Publisher<'_> { fn drop(&mut self) { if self.undeclare_on_drop { - #[cfg(feature = "unstable")] - let _ = self.undeclare_matching_listeners(); - let _ = self.session.undeclare_publisher_inner(self.id); + if let Err(error) = self.undeclare_impl() { + error!(error); + } } } } @@ -933,7 +931,6 @@ where listener: MatchingListenerInner { publisher: self.publisher, state, - undeclare_on_drop: true, }, receiver, }) @@ -958,7 +955,7 @@ where #[zenoh_macros::unstable] pub(crate) struct MatchingListenerState { pub(crate) id: Id, - pub(crate) current: std::sync::Mutex, + pub(crate) current: Mutex, pub(crate) key_expr: KeyExpr<'static>, pub(crate) destination: Locality, pub(crate) callback: Callback<'static, MatchingStatus>, @@ -977,8 +974,7 @@ impl std::fmt::Debug for MatchingListenerState { #[zenoh_macros::unstable] pub(crate) struct MatchingListenerInner<'a> { pub(crate) publisher: PublisherRef<'a>, - pub(crate) state: std::sync::Arc, - undeclare_on_drop: bool, + pub(crate) state: Arc, } #[zenoh_macros::unstable] @@ -990,8 +986,10 @@ impl<'a> MatchingListenerInner<'a> { } #[zenoh_macros::unstable] -impl<'a> UndeclarableSealed<(), MatchingListenerUndeclaration<'a>> for MatchingListenerInner<'a> { - fn undeclare_inner(self, _: ()) -> MatchingListenerUndeclaration<'a> { +impl<'a> UndeclarableSealed<()> for MatchingListenerInner<'a> { + type Undeclaration = MatchingListenerUndeclaration<'a>; + + fn undeclare_inner(self, _: ()) -> Self::Undeclaration { MatchingListenerUndeclaration { subscriber: self } } } @@ -999,6 +997,9 @@ impl<'a> UndeclarableSealed<(), MatchingListenerUndeclaration<'a>> for MatchingL /// A listener that sends notifications when the [`MatchingStatus`] of a /// publisher changes. /// +/// Matching litsteners run in background until the publisher is undeclared. +/// They can be manually undeclared, but will not be undeclared on drop. +/// /// # Examples /// ```no_run /// # #[tokio::main] @@ -1025,10 +1026,7 @@ pub struct MatchingListener<'a, Receiver> { #[zenoh_macros::unstable] impl<'a, Receiver> MatchingListener<'a, Receiver> { - /// Close a [`MatchingListener`]. - /// - /// MatchingListeners are automatically closed when dropped, but you may want to use this function to handle errors or - /// close the MatchingListener asynchronously. + /// Undeclare the [`MatchingListener`]. /// /// # Examples /// ``` @@ -1046,19 +1044,13 @@ impl<'a, Receiver> MatchingListener<'a, Receiver> { pub fn undeclare(self) -> MatchingListenerUndeclaration<'a> { self.listener.undeclare() } - - /// Make the matching listener run in background, until the publisher is undeclared. - #[inline] - #[zenoh_macros::unstable] - pub fn background(mut self) { - // The matching listener will be undeclared as part of publisher undeclaration. - self.listener.undeclare_on_drop = false; - } } #[zenoh_macros::unstable] -impl<'a, T> UndeclarableSealed<(), MatchingListenerUndeclaration<'a>> for MatchingListener<'a, T> { - fn undeclare_inner(self, _: ()) -> MatchingListenerUndeclaration<'a> { +impl<'a, T> UndeclarableSealed<()> for MatchingListener<'a, T> { + type Undeclaration = MatchingListenerUndeclaration<'a>; + + fn undeclare_inner(self, _: ()) -> Self::Undeclaration { UndeclarableSealed::undeclare_inner(self.listener, ()) } } @@ -1090,9 +1082,7 @@ impl Resolvable for MatchingListenerUndeclaration<'_> { #[zenoh_macros::unstable] impl Wait for MatchingListenerUndeclaration<'_> { - fn wait(mut self) -> ::To { - // set the flag first to avoid double panic if this function panic - self.subscriber.undeclare_on_drop = false; + fn wait(self) -> ::To { zlock!(self.subscriber.publisher.matching_listeners).remove(&self.subscriber.state.id); self.subscriber .publisher @@ -1111,19 +1101,6 @@ impl IntoFuture for MatchingListenerUndeclaration<'_> { } } -#[zenoh_macros::unstable] -impl Drop for MatchingListenerInner<'_> { - fn drop(&mut self) { - if self.undeclare_on_drop { - zlock!(self.publisher.matching_listeners).remove(&self.state.id); - let _ = self - .publisher - .session - .undeclare_matches_listener_inner(self.state.id); - } - } -} - #[cfg(test)] mod tests { use zenoh_config::Config; diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 61ae0093ea..d39b2411f5 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -14,10 +14,12 @@ use std::{ fmt, future::{IntoFuture, Ready}, + mem::size_of, ops::{Deref, DerefMut}, sync::Arc, }; +use tracing::error; use uhlc::Timestamp; use zenoh_core::{Resolvable, Resolve, Wait}; use zenoh_protocol::{ @@ -28,30 +30,32 @@ use zenoh_protocol::{ use zenoh_result::ZResult; #[zenoh_macros::unstable] use { - super::{query::ReplyKeyExpr, sample::SourceInfo}, - zenoh_config::wrappers::EntityGlobalId, + crate::api::{query::ReplyKeyExpr, sample::SourceInfo}, + zenoh_config::wrappers::{EntityGlobalId, ZenohId}, zenoh_protocol::core::EntityGlobalIdProto, }; #[zenoh_macros::unstable] -use super::selector::ZenohParameters; -use super::{ - builders::sample::{ - EncodingBuilderTrait, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, - TimestampBuilderTrait, +use crate::api::selector::ZenohParameters; +use crate::{ + api::{ + builders::sample::{ + EncodingBuilderTrait, QoSBuilderTrait, SampleBuilder, SampleBuilderTrait, + TimestampBuilderTrait, + }, + bytes::{OptionZBytes, ZBytes}, + encoding::Encoding, + handlers::{locked, DefaultHandler, IntoHandler}, + key_expr::KeyExpr, + publisher::Priority, + sample::{Locality, QoSBuilder, Sample, SampleKind}, + selector::Selector, + session::{SessionRef, UndeclarableSealed, WeakSessionRef}, + value::Value, + Id, }, - bytes::{OptionZBytes, ZBytes}, - encoding::Encoding, - handlers::{locked, DefaultHandler, IntoHandler}, - key_expr::KeyExpr, - publisher::Priority, - sample::{Locality, QoSBuilder, Sample, SampleKind}, - selector::Selector, - session::{SessionRef, UndeclarableSealed}, - value::Value, - Id, + net::primitives::Primitives, }; -use crate::net::primitives::Primitives; pub(crate) struct QueryInner { pub(crate) key_expr: KeyExpr<'static>, @@ -534,43 +538,13 @@ impl fmt::Debug for QueryableState { } } -/// An entity able to reply to queries through a callback. -/// -/// CallbackQueryables can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_queryable`](crate::Session::declare_queryable) function -/// and the [`callback`](QueryableBuilder::callback) function -/// of the resulting builder. -/// -/// Queryables are automatically undeclared when dropped. -/// -/// # Examples -/// ```no_run -/// # #[tokio::main] -/// # async fn main() { -/// use futures::prelude::*; -/// use zenoh::prelude::*; -/// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); -/// let queryable = session.declare_queryable("key/expression").await.unwrap(); -/// while let Ok(query) = queryable.recv_async().await { -/// println!(">> Handling query '{}'", query.selector()); -/// query.reply("key/expression", "value") -/// .await -/// .unwrap(); -/// } -/// # } -/// ``` #[derive(Debug)] -pub(crate) struct CallbackQueryable<'a> { - pub(crate) session: SessionRef<'a>, +pub(crate) struct QueryableInner<'a> { + #[cfg(feature = "unstable")] + pub(crate) session_id: ZenohId, + pub(crate) session: WeakSessionRef<'a>, pub(crate) state: Arc, - undeclare_on_drop: bool, -} - -impl<'a> UndeclarableSealed<(), QueryableUndeclaration<'a>> for CallbackQueryable<'a> { - fn undeclare_inner(self, _: ()) -> QueryableUndeclaration<'a> { - QueryableUndeclaration { queryable: self } - } + pub(crate) undeclare_on_drop: bool, } /// A [`Resolvable`] returned when undeclaring a queryable. @@ -587,25 +561,19 @@ impl<'a> UndeclarableSealed<(), QueryableUndeclaration<'a>> for CallbackQueryabl /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct QueryableUndeclaration<'a> { - queryable: CallbackQueryable<'a>, -} +pub struct QueryableUndeclaration<'a, Handler>(Queryable<'a, Handler>); -impl Resolvable for QueryableUndeclaration<'_> { +impl Resolvable for QueryableUndeclaration<'_, Handler> { type To = ZResult<()>; } -impl Wait for QueryableUndeclaration<'_> { +impl Wait for QueryableUndeclaration<'_, Handler> { fn wait(mut self) -> ::To { - // set the flag first to avoid double panic if this function panic - self.queryable.undeclare_on_drop = false; - self.queryable - .session - .close_queryable(self.queryable.state.id) + self.0.undeclare_impl() } } -impl<'a> IntoFuture for QueryableUndeclaration<'a> { +impl IntoFuture for QueryableUndeclaration<'_, Handler> { type Output = ::To; type IntoFuture = Ready<::To>; @@ -614,14 +582,6 @@ impl<'a> IntoFuture for QueryableUndeclaration<'a> { } } -impl Drop for CallbackQueryable<'_> { - fn drop(&mut self) { - if self.undeclare_on_drop { - let _ = self.session.close_queryable(self.state.id); - } - } -} - /// A builder for initializing a [`Queryable`]. /// /// # Examples @@ -778,9 +738,37 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// and the [`with`](QueryableBuilder::with) function /// of the resulting builder. /// -/// Queryables are automatically undeclared when dropped. +/// Callback queryables will run in background until the session is closed, +/// or until it is undeclared. +/// On the other hand, queryables with a handler are automatically undeclared when dropped. /// /// # Examples +/// +/// Using callback: +/// ```no_run +/// # #[tokio::main] +/// # async fn main() { +/// use futures::prelude::*; +/// use zenoh::prelude::*; +/// +/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); +/// let (tx, rx) = flume::bounded(32); +/// session +/// .declare_queryable("key/expression") +/// .callback(|query| tx.send(query).unwrap()) +/// .await +/// .unwrap(); +/// // queryable run in background until the session is closed +/// tokio::spawn(async move { +/// while let Ok(query) = rx.recv().await { +/// println!(">> Handling query '{}'", query.selector()); +/// query.reply("key/expression", "value").await.unwrap(); +/// } +/// }); +/// # } +/// ``` +/// +/// Using channel handler: /// ```no_run /// # #[tokio::main] /// # async fn main() { @@ -798,12 +786,13 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// .await /// .unwrap(); /// } +/// // queryable is undeclared at the end of the scope /// # } /// ``` #[non_exhaustive] #[derive(Debug)] pub struct Queryable<'a, Handler> { - pub(crate) queryable: CallbackQueryable<'a>, + pub(crate) inner: QueryableInner<'a>, pub(crate) handler: Handler, } @@ -826,8 +815,8 @@ impl<'a, Handler> Queryable<'a, Handler> { #[zenoh_macros::unstable] pub fn id(&self) -> EntityGlobalId { EntityGlobalIdProto { - zid: self.queryable.session.zid().into(), - eid: self.queryable.state.id, + zid: self.inner.session_id.into(), + eid: self.inner.state.id, } .into() } @@ -846,25 +835,53 @@ impl<'a, Handler> Queryable<'a, Handler> { &mut self.handler } + /// Undeclare the [`Queryable`]. + /// + /// # Examples + /// ``` + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let queryable = session.declare_queryable("key/expression") + /// .await + /// .unwrap(); + /// queryable.undeclare().await.unwrap(); + /// # } + /// ``` #[inline] - pub fn undeclare(self) -> impl Resolve> + 'a { + pub fn undeclare(self) -> impl Resolve> + 'a + where + Handler: Send + 'a, + { UndeclarableSealed::undeclare_inner(self, ()) } - /// Make the queryable run in background, until the session is closed. - #[inline] - #[zenoh_macros::unstable] - pub fn background(mut self) { - // It's not necessary to undeclare this resource when session close, as other sessions - // will clean all resources related to the closed one. - // So we can just never undeclare it. - self.queryable.undeclare_on_drop = false; + fn undeclare_impl(&mut self) -> ZResult<()> { + self.inner.undeclare_on_drop = false; + match self.inner.session.upgrade() { + Some(session) => session.close_queryable(self.inner.state.id), + None => Ok(()), + } + } +} + +impl Drop for Queryable<'_, Handler> { + fn drop(&mut self) { + if self.inner.undeclare_on_drop { + if let Err(error) = self.undeclare_impl() { + error!(error); + } + } } } -impl<'a, T> UndeclarableSealed<(), QueryableUndeclaration<'a>> for Queryable<'a, T> { - fn undeclare_inner(self, _: ()) -> QueryableUndeclaration<'a> { - UndeclarableSealed::undeclare_inner(self.queryable, ()) +impl<'a, Handler: Send + 'a> UndeclarableSealed<()> for Queryable<'a, Handler> { + type Undeclaration = QueryableUndeclaration<'a, Handler>; + + fn undeclare_inner(self, _: ()) -> Self::Undeclaration { + QueryableUndeclaration(self) } } @@ -906,10 +923,12 @@ where callback, ) .map(|qable_state| Queryable { - queryable: CallbackQueryable { - session, + inner: QueryableInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: session.into(), state: qable_state, - undeclare_on_drop: true, + undeclare_on_drop: size_of::() > 0, }, handler: receiver, }) diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 26704d378a..b6efb5946f 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -19,7 +19,7 @@ use std::{ ops::Deref, sync::{ atomic::{AtomicU16, Ordering}, - Arc, RwLock, + Arc, RwLock, Weak, }, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -452,19 +452,43 @@ impl fmt::Debug for SessionRef<'_> { } } -pub(crate) trait UndeclarableSealed> -where - O: Resolve + Send, -{ - fn undeclare_inner(self, session: S) -> O; +#[derive(Debug, Clone)] +pub(crate) enum WeakSessionRef<'a> { + Borrow(&'a Session), + Shared(Weak), } -impl<'a, O, T, G> UndeclarableSealed<&'a Session, O, T> for G +impl<'a> WeakSessionRef<'a> { + pub(crate) fn upgrade(&self) -> Option> { + match self { + Self::Borrow(s) => Some(SessionRef::Borrow(s)), + Self::Shared(s) => s.upgrade().map(SessionRef::Shared), + } + } +} + +impl<'a> From> for WeakSessionRef<'a> { + fn from(value: SessionRef<'a>) -> Self { + match value { + SessionRef::Borrow(s) => Self::Borrow(s), + SessionRef::Shared(s) => Self::Shared(Arc::downgrade(&s)), + } + } +} + +/// A trait implemented by types that can be undeclared. +pub trait UndeclarableSealed { + type Undeclaration: Resolve> + Send; + fn undeclare_inner(self, session: S) -> Self::Undeclaration; +} + +impl<'a, T> UndeclarableSealed<&'a Session> for T where - O: Resolve + Send, - G: UndeclarableSealed<(), O, T>, + T: UndeclarableSealed<()>, { - fn undeclare_inner(self, _: &'a Session) -> O { + type Undeclaration = >::Undeclaration; + + fn undeclare_inner(self, _session: &'a Session) -> Self::Undeclaration { self.undeclare_inner(()) } } @@ -473,18 +497,9 @@ where // care about the `private_bounds` lint in this particular case. #[allow(private_bounds)] /// A trait implemented by types that can be undeclared. -pub trait Undeclarable: UndeclarableSealed -where - O: Resolve + Send, -{ -} +pub trait Undeclarable: UndeclarableSealed {} -impl Undeclarable for U -where - O: Resolve + Send, - U: UndeclarableSealed, -{ -} +impl Undeclarable for T where T: UndeclarableSealed {} /// A zenoh session. /// @@ -637,10 +652,9 @@ impl Session { }) } - pub fn undeclare<'a, T, O>(&'a self, decl: T) -> O + pub fn undeclare<'a, T>(&'a self, decl: T) -> impl Resolve> + 'a where - O: Resolve>, - T: Undeclarable<&'a Self, O, ZResult<()>>, + T: Undeclarable<&'a Session> + 'a, { UndeclarableSealed::undeclare_inner(decl, self) } @@ -771,13 +785,6 @@ impl Session { >>::Error: Into, { let key_expr: ZResult = key_expr.try_into().map_err(Into::into); - self._declare_keyexpr(key_expr) - } - - fn _declare_keyexpr<'a, 'b: 'a>( - &'a self, - key_expr: ZResult>, - ) -> impl Resolve>> + 'a { let sid = self.id; ResolveClosure::new(move || { let key_expr: KeyExpr = key_expr?; diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 0e82a20331..abeb36aa28 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -15,21 +15,26 @@ use std::{ fmt, future::{IntoFuture, Ready}, + mem::size_of, ops::{Deref, DerefMut}, sync::Arc, }; +use tracing::error; use zenoh_core::{Resolvable, Wait}; use zenoh_protocol::network::declare::subscriber::ext::SubscriberInfo; use zenoh_result::ZResult; #[cfg(feature = "unstable")] -use {zenoh_config::wrappers::EntityGlobalId, zenoh_protocol::core::EntityGlobalIdProto}; +use { + zenoh_config::wrappers::{EntityGlobalId, ZenohId}, + zenoh_protocol::core::EntityGlobalIdProto, +}; -use super::{ +use crate::api::{ handlers::{locked, Callback, DefaultHandler, IntoHandler}, key_expr::KeyExpr, sample::{Locality, Sample}, - session::{SessionRef, UndeclarableSealed}, + session::{SessionRef, UndeclarableSealed, WeakSessionRef}, Id, }; #[cfg(feature = "unstable")] @@ -52,71 +57,16 @@ impl fmt::Debug for SubscriberState { } } -/// A subscriber that provides data through a callback. -/// -/// CallbackSubscribers can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_subscriber`](crate::SessionDeclarations::declare_subscriber) function -/// and the [`callback`](SubscriberBuilder::callback) function -/// of the resulting builder. -/// -/// Subscribers are automatically undeclared when dropped. -/// -/// # Examples -/// ``` -/// # #[tokio::main] -/// # async fn main() { -/// use zenoh::prelude::*; -/// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); -/// let subscriber = session -/// .declare_subscriber("key/expression") -/// .callback(|sample| { println!("Received: {} {:?}", sample.key_expr(), sample.payload()) }) -/// .await -/// .unwrap(); -/// # } -/// ``` #[derive(Debug)] pub(crate) struct SubscriberInner<'a> { - pub(crate) session: SessionRef<'a>, + #[cfg(feature = "unstable")] + pub(crate) session_id: ZenohId, + pub(crate) session: WeakSessionRef<'a>, pub(crate) state: Arc, pub(crate) kind: SubscriberKind, pub(crate) undeclare_on_drop: bool, } -impl<'a> SubscriberInner<'a> { - /// Close a [`CallbackSubscriber`](CallbackSubscriber). - /// - /// `CallbackSubscribers` are automatically closed when dropped, but you may want to use this function to handle errors or - /// close the `CallbackSubscriber` asynchronously. - /// - /// # Examples - /// ``` - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::{prelude::*, sample::Sample}; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); - /// # fn data_handler(_sample: Sample) { }; - /// let subscriber = session - /// .declare_subscriber("key/expression") - /// .callback(data_handler) - /// .await - /// .unwrap(); - /// subscriber.undeclare().await.unwrap(); - /// # } - /// ``` - #[inline] - pub fn undeclare(self) -> SubscriberUndeclaration<'a> { - UndeclarableSealed::undeclare_inner(self, ()) - } -} - -impl<'a> UndeclarableSealed<(), SubscriberUndeclaration<'a>> for SubscriberInner<'a> { - fn undeclare_inner(self, _: ()) -> SubscriberUndeclaration<'a> { - SubscriberUndeclaration { subscriber: self } - } -} - /// A [`Resolvable`] returned when undeclaring a subscriber. /// /// # Examples @@ -134,25 +84,19 @@ impl<'a> UndeclarableSealed<(), SubscriberUndeclaration<'a>> for SubscriberInner /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct SubscriberUndeclaration<'a> { - subscriber: SubscriberInner<'a>, -} +pub struct SubscriberUndeclaration<'a, Handler>(Subscriber<'a, Handler>); -impl Resolvable for SubscriberUndeclaration<'_> { +impl Resolvable for SubscriberUndeclaration<'_, Handler> { type To = ZResult<()>; } -impl Wait for SubscriberUndeclaration<'_> { +impl Wait for SubscriberUndeclaration<'_, Handler> { fn wait(mut self) -> ::To { - // set the flag first to avoid double panic if this function panic - self.subscriber.undeclare_on_drop = false; - self.subscriber - .session - .undeclare_subscriber_inner(self.subscriber.state.id, self.subscriber.kind) + self.0.undeclare_impl() } } -impl IntoFuture for SubscriberUndeclaration<'_> { +impl IntoFuture for SubscriberUndeclaration<'_, Handler> { type Output = ::To; type IntoFuture = Ready<::To>; @@ -161,16 +105,6 @@ impl IntoFuture for SubscriberUndeclaration<'_> { } } -impl Drop for SubscriberInner<'_> { - fn drop(&mut self) { - if self.undeclare_on_drop { - let _ = self - .session - .undeclare_subscriber_inner(self.state.id, self.kind); - } - } -} - /// A builder for initializing a [`FlumeSubscriber`]. /// /// # Examples @@ -394,11 +328,13 @@ where &SubscriberInfo::default(), ) .map(|sub_state| Subscriber { - subscriber: SubscriberInner { - session, + inner: SubscriberInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: session.into(), state: sub_state, kind: SubscriberKind::Subscriber, - undeclare_on_drop: true, + undeclare_on_drop: size_of::() > 0, }, handler: receiver, }) @@ -425,9 +361,29 @@ where /// and the [`with`](SubscriberBuilder::with) function /// of the resulting builder. /// -/// Subscribers are automatically undeclared when dropped. +/// Callback subscribers will run in background until the session is closed, +/// or until it is undeclared. +/// On the other hand, subscribers with a handler are automatically undeclared when dropped. /// /// # Examples +/// +/// Using callback: +/// ```no_run +/// # #[tokio::main] +/// # async fn main() { +/// use zenoh::prelude::*; +/// +/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); +/// session +/// .declare_subscriber("key/expression") +/// .callback(|sample| { println!("Received: {} {:?}", sample.key_expr(), sample.payload()) }) +/// .await +/// .unwrap(); +/// // subscriber run in background until the session is closed +/// # } +/// ``` +/// +/// Using channel handler: /// ```no_run /// # #[tokio::main] /// # async fn main() { @@ -442,12 +398,13 @@ where /// while let Ok(sample) = subscriber.recv_async().await { /// println!("Received: {} {:?}", sample.key_expr(), sample.payload()); /// } +/// // subscriber is undeclared at the end of the scope /// # } /// ``` #[non_exhaustive] #[derive(Debug)] pub struct Subscriber<'a, Handler> { - pub(crate) subscriber: SubscriberInner<'a>, + pub(crate) inner: SubscriberInner<'a>, pub(crate) handler: Handler, } @@ -470,15 +427,15 @@ impl<'a, Handler> Subscriber<'a, Handler> { #[zenoh_macros::unstable] pub fn id(&self) -> EntityGlobalId { EntityGlobalIdProto { - zid: self.subscriber.session.zid().into(), - eid: self.subscriber.state.id, + zid: self.inner.session_id.into(), + eid: self.inner.state.id, } .into() } /// Returns the [`KeyExpr`] this Subscriber subscribes to. pub fn key_expr(&self) -> &KeyExpr<'static> { - &self.subscriber.state.key_expr + &self.inner.state.key_expr } /// Returns a reference to this subscriber's handler. @@ -495,10 +452,7 @@ impl<'a, Handler> Subscriber<'a, Handler> { &mut self.handler } - /// Close a [`Subscriber`]. - /// - /// Subscribers are automatically closed when dropped, but you may want to use this function to handle errors or - /// close the Subscriber asynchronously. + /// Undeclare the [`Subscriber`]. /// /// # Examples /// ``` @@ -514,24 +468,39 @@ impl<'a, Handler> Subscriber<'a, Handler> { /// # } /// ``` #[inline] - pub fn undeclare(self) -> SubscriberUndeclaration<'a> { - self.subscriber.undeclare() + pub fn undeclare(self) -> SubscriberUndeclaration<'a, Handler> + where + Handler: Send + 'a, + { + self.undeclare_inner(()) } - /// Make the subscriber run in background, until the session is closed. - #[inline] - #[zenoh_macros::unstable] - pub fn background(mut self) { - // It's not necessary to undeclare this resource when session close, as other sessions - // will clean all resources related to the closed one. - // So we can just never undeclare it. - self.subscriber.undeclare_on_drop = false; + fn undeclare_impl(&mut self) -> ZResult<()> { + self.inner.undeclare_on_drop = false; + match self.inner.session.upgrade() { + Some(session) => { + session.undeclare_subscriber_inner(self.inner.state.id, self.inner.kind) + } + None => Ok(()), + } } } -impl<'a, T> UndeclarableSealed<(), SubscriberUndeclaration<'a>> for Subscriber<'a, T> { - fn undeclare_inner(self, _: ()) -> SubscriberUndeclaration<'a> { - UndeclarableSealed::undeclare_inner(self.subscriber, ()) +impl Drop for Subscriber<'_, Handler> { + fn drop(&mut self) { + if self.inner.undeclare_on_drop { + if let Err(error) = self.undeclare_impl() { + error!(error); + } + } + } +} + +impl<'a, Handler: Send + 'a> UndeclarableSealed<()> for Subscriber<'a, Handler> { + type Undeclaration = SubscriberUndeclaration<'a, Handler>; + + fn undeclare_inner(self, _: ()) -> Self::Undeclaration { + SubscriberUndeclaration(self) } } diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index 0190acc319..1b563bb4e4 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -191,13 +191,15 @@ pub mod session { pub use zenoh_config::wrappers::{EntityGlobalId, ZenohId}; pub use zenoh_protocol::core::EntityId; + #[zenoh_macros::unstable] + pub use crate::api::session::SessionRef; #[zenoh_macros::internal] pub use crate::api::session::{init, InitBuilder}; pub use crate::api::{ builders::publisher::{SessionDeleteBuilder, SessionPutBuilder}, info::{PeersZenohIdBuilder, RoutersZenohIdBuilder, SessionInfo, ZenohIdBuilder}, query::SessionGetBuilder, - session::{open, OpenBuilder, Session, SessionDeclarations, SessionRef, Undeclarable}, + session::{open, OpenBuilder, Session, SessionDeclarations, Undeclarable}, }; } From 82e7b16808c97828deffa6931d1b857e4d099a33 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 28 Aug 2024 07:51:27 +0200 Subject: [PATCH 02/34] fix: fix example --- zenoh/src/api/queryable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index d39b2411f5..bf8c482537 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -760,7 +760,7 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// .unwrap(); /// // queryable run in background until the session is closed /// tokio::spawn(async move { -/// while let Ok(query) = rx.recv().await { +/// while let Ok(query) = rx.recv_async().await { /// println!(">> Handling query '{}'", query.selector()); /// query.reply("key/expression", "value").await.unwrap(); /// } From 15fff73a9fc65d8436ac4a2ed8ef5b4524e659a1 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 28 Aug 2024 08:24:54 +0200 Subject: [PATCH 03/34] fix: fix example --- zenoh/src/api/queryable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index bf8c482537..163d32c011 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -755,7 +755,7 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// let (tx, rx) = flume::bounded(32); /// session /// .declare_queryable("key/expression") -/// .callback(|query| tx.send(query).unwrap()) +/// .callback(move |query| tx.send(query).unwrap()) /// .await /// .unwrap(); /// // queryable run in background until the session is closed From a1ff4a632060ef661fa562f329ede2d90a520048 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 2 Sep 2024 09:33:03 +0200 Subject: [PATCH 04/34] fix: add missing comment about ZST trick --- zenoh/src/api/liveliness.rs | 2 ++ zenoh/src/api/publisher.rs | 1 + zenoh/src/api/queryable.rs | 3 +++ zenoh/src/api/subscriber.rs | 3 +++ 4 files changed, 9 insertions(+) diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index bb068b4e52..10788f39e9 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -385,6 +385,7 @@ impl<'a> LivelinessToken<'a> { } fn undeclare_impl(&mut self) -> ZResult<()> { + // set the flag first to avoid double panic if this function panic self.undeclare_on_drop = false; match self.session.upgrade() { Some(session) => session.undeclare_liveliness(self.state.id), @@ -581,6 +582,7 @@ where session: session.into(), state: sub_state, kind: SubscriberKind::LivelinessSubscriber, + // `size_of::() == 0` means callback-only subscriber undeclare_on_drop: size_of::() > 0, }, handler, diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 4371255ac4..0661ad3dec 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -368,6 +368,7 @@ impl<'a> Publisher<'a> { } fn undeclare_impl(&mut self) -> ZResult<()> { + // set the flag first to avoid double panic if this function panic self.undeclare_on_drop = false; #[cfg(feature = "unstable")] { diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 163d32c011..89938f213b 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -544,6 +544,7 @@ pub(crate) struct QueryableInner<'a> { pub(crate) session_id: ZenohId, pub(crate) session: WeakSessionRef<'a>, pub(crate) state: Arc, + // Queryable is undeclared on drop unless its handler is a ZST, i.e. it is callback-only pub(crate) undeclare_on_drop: bool, } @@ -859,6 +860,7 @@ impl<'a, Handler> Queryable<'a, Handler> { } fn undeclare_impl(&mut self) -> ZResult<()> { + // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; match self.inner.session.upgrade() { Some(session) => session.close_queryable(self.inner.state.id), @@ -928,6 +930,7 @@ where session_id: session.zid(), session: session.into(), state: qable_state, + // `size_of::() == 0` means callback-only queryable undeclare_on_drop: size_of::() > 0, }, handler: receiver, diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index abeb36aa28..7c62e0502d 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -64,6 +64,7 @@ pub(crate) struct SubscriberInner<'a> { pub(crate) session: WeakSessionRef<'a>, pub(crate) state: Arc, pub(crate) kind: SubscriberKind, + // Subscriber is undeclared on drop unless its handler is a ZST, i.e. it is callback-only pub(crate) undeclare_on_drop: bool, } @@ -334,6 +335,7 @@ where session: session.into(), state: sub_state, kind: SubscriberKind::Subscriber, + // `size_of::() == 0` means callback-only subscriber undeclare_on_drop: size_of::() > 0, }, handler: receiver, @@ -476,6 +478,7 @@ impl<'a, Handler> Subscriber<'a, Handler> { } fn undeclare_impl(&mut self) -> ZResult<()> { + // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; match self.inner.session.upgrade() { Some(session) => { From 0d4423b5c209c2b9ddce4510ae4da24907230946 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 2 Sep 2024 16:19:08 +0200 Subject: [PATCH 05/34] Update zenoh/src/api/key_expr.rs Co-authored-by: Luca Cominardi --- zenoh/src/api/key_expr.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zenoh/src/api/key_expr.rs b/zenoh/src/api/key_expr.rs index bde77f5d32..8b11472dfb 100644 --- a/zenoh/src/api/key_expr.rs +++ b/zenoh/src/api/key_expr.rs @@ -551,6 +551,7 @@ impl<'a> KeyExpr<'a> { impl<'a> UndeclarableSealed<&'a Session> for KeyExpr<'a> { type Undeclaration = KeyExprUndeclaration<'a>; + fn undeclare_inner(self, session: &'a Session) -> Self::Undeclaration { KeyExprUndeclaration { session, From 150c497f989e94f92b355e2797af7006ed7d2de5 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 2 Sep 2024 17:24:01 +0200 Subject: [PATCH 06/34] fix: formatting --- zenoh/src/api/key_expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/api/key_expr.rs b/zenoh/src/api/key_expr.rs index 8b11472dfb..0f0d13a69c 100644 --- a/zenoh/src/api/key_expr.rs +++ b/zenoh/src/api/key_expr.rs @@ -551,7 +551,7 @@ impl<'a> KeyExpr<'a> { impl<'a> UndeclarableSealed<&'a Session> for KeyExpr<'a> { type Undeclaration = KeyExprUndeclaration<'a>; - + fn undeclare_inner(self, session: &'a Session) -> Self::Undeclaration { KeyExprUndeclaration { session, From baa242600e01dc3c49259087b1c4ae1d8404a81f Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Tue, 3 Sep 2024 11:27:16 +0200 Subject: [PATCH 07/34] fix: don't use `Weak` when undeclared on drop --- zenoh/src/api/liveliness.rs | 34 +++++++++++++++++++--------------- zenoh/src/api/queryable.rs | 27 +++++++++++++++------------ zenoh/src/api/session.rs | 27 ++++++++++++++------------- zenoh/src/api/subscriber.rs | 29 ++++++++++++++++------------- 4 files changed, 64 insertions(+), 53 deletions(-) diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 10788f39e9..f22de66b02 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -33,7 +33,7 @@ use super::{ subscriber::{Subscriber, SubscriberInner}, Id, }; -use crate::api::session::WeakSessionRef; +use crate::api::session::MaybeWeakSessionRef; /// A structure with functions to declare a /// [`LivelinessToken`](LivelinessToken), query @@ -254,12 +254,13 @@ impl Wait for LivelinessTokenBuilder<'_, '_> { fn wait(self) -> ::To { let session = self.session; let key_expr = self.key_expr?.into_owned(); + let undeclare_on_drop = true; session .declare_liveliness_inner(&key_expr) .map(|tok_state| LivelinessToken { - session: session.into(), + session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), state: tok_state, - undeclare_on_drop: true, + undeclare_on_drop, }) } } @@ -310,7 +311,7 @@ pub(crate) struct LivelinessTokenState { #[zenoh_macros::unstable] #[derive(Debug)] pub struct LivelinessToken<'a> { - session: WeakSessionRef<'a>, + session: MaybeWeakSessionRef<'a>, state: Arc, undeclare_on_drop: bool, } @@ -573,19 +574,22 @@ where let key_expr = self.key_expr?; let session = self.session; let (callback, handler) = self.handler.into_handler(); + let undeclare_on_drop = size_of::() > 0; session .declare_liveliness_subscriber_inner(&key_expr, Locality::default(), callback) - .map(|sub_state| Subscriber { - inner: SubscriberInner { - #[cfg(feature = "unstable")] - session_id: session.zid(), - session: session.into(), - state: sub_state, - kind: SubscriberKind::LivelinessSubscriber, - // `size_of::() == 0` means callback-only subscriber - undeclare_on_drop: size_of::() > 0, - }, - handler, + .map(|sub_state| { + Subscriber { + inner: SubscriberInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), + state: sub_state, + kind: SubscriberKind::LivelinessSubscriber, + // `size_of::() == 0` means callback-only subscriber + undeclare_on_drop, + }, + handler, + } }) } } diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 89938f213b..56b26fa36e 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -50,7 +50,7 @@ use crate::{ publisher::Priority, sample::{Locality, QoSBuilder, Sample, SampleKind}, selector::Selector, - session::{SessionRef, UndeclarableSealed, WeakSessionRef}, + session::{MaybeWeakSessionRef, SessionRef, UndeclarableSealed}, value::Value, Id, }, @@ -542,7 +542,7 @@ impl fmt::Debug for QueryableState { pub(crate) struct QueryableInner<'a> { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: WeakSessionRef<'a>, + pub(crate) session: MaybeWeakSessionRef<'a>, pub(crate) state: Arc, // Queryable is undeclared on drop unless its handler is a ZST, i.e. it is callback-only pub(crate) undeclare_on_drop: bool, @@ -917,6 +917,7 @@ where fn wait(self) -> ::To { let session = self.session; let (callback, receiver) = self.handler.into_handler(); + let undeclare_on_drop = size_of::() > 0; session .declare_queryable_inner( &self.key_expr?.to_wire(&session), @@ -924,16 +925,18 @@ where self.origin, callback, ) - .map(|qable_state| Queryable { - inner: QueryableInner { - #[cfg(feature = "unstable")] - session_id: session.zid(), - session: session.into(), - state: qable_state, - // `size_of::() == 0` means callback-only queryable - undeclare_on_drop: size_of::() > 0, - }, - handler: receiver, + .map(|qable_state| { + Queryable { + inner: QueryableInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), + state: qable_state, + // `size_of::() == 0` means callback-only queryable + undeclare_on_drop, + }, + handler: receiver, + } }) } } diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index b6efb5946f..231ab85d6d 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -453,25 +453,26 @@ impl fmt::Debug for SessionRef<'_> { } #[derive(Debug, Clone)] -pub(crate) enum WeakSessionRef<'a> { +pub(crate) enum MaybeWeakSessionRef<'a> { Borrow(&'a Session), - Shared(Weak), + Arc(Arc), + Weak(Weak), } -impl<'a> WeakSessionRef<'a> { - pub(crate) fn upgrade(&self) -> Option> { - match self { - Self::Borrow(s) => Some(SessionRef::Borrow(s)), - Self::Shared(s) => s.upgrade().map(SessionRef::Shared), +impl<'a> MaybeWeakSessionRef<'a> { + pub(crate) fn new(session: SessionRef<'a>, downgrade: bool) -> Self { + match session { + SessionRef::Borrow(s) => Self::Borrow(s), + SessionRef::Shared(s) if downgrade => Self::Weak(Arc::downgrade(&s)), + SessionRef::Shared(s) => Self::Arc(s), } } -} -impl<'a> From> for WeakSessionRef<'a> { - fn from(value: SessionRef<'a>) -> Self { - match value { - SessionRef::Borrow(s) => Self::Borrow(s), - SessionRef::Shared(s) => Self::Shared(Arc::downgrade(&s)), + pub(crate) fn upgrade(&self) -> Option> { + match self { + Self::Borrow(s) => Some(SessionRef::Borrow(s)), + Self::Arc(s) => Some(SessionRef::Shared(s.clone())), + Self::Weak(s) => s.upgrade().map(SessionRef::Shared), } } } diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 7c62e0502d..5bca8abcfa 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -34,7 +34,7 @@ use crate::api::{ handlers::{locked, Callback, DefaultHandler, IntoHandler}, key_expr::KeyExpr, sample::{Locality, Sample}, - session::{SessionRef, UndeclarableSealed, WeakSessionRef}, + session::{MaybeWeakSessionRef, SessionRef, UndeclarableSealed}, Id, }; #[cfg(feature = "unstable")] @@ -61,7 +61,7 @@ impl fmt::Debug for SubscriberState { pub(crate) struct SubscriberInner<'a> { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: WeakSessionRef<'a>, + pub(crate) session: MaybeWeakSessionRef<'a>, pub(crate) state: Arc, pub(crate) kind: SubscriberKind, // Subscriber is undeclared on drop unless its handler is a ZST, i.e. it is callback-only @@ -316,6 +316,7 @@ where let key_expr = self.key_expr?; let session = self.session; let (callback, receiver) = self.handler.into_handler(); + let undeclare_on_drop = size_of::() > 0; session .declare_subscriber_inner( &key_expr, @@ -328,17 +329,19 @@ where #[cfg(not(feature = "unstable"))] &SubscriberInfo::default(), ) - .map(|sub_state| Subscriber { - inner: SubscriberInner { - #[cfg(feature = "unstable")] - session_id: session.zid(), - session: session.into(), - state: sub_state, - kind: SubscriberKind::Subscriber, - // `size_of::() == 0` means callback-only subscriber - undeclare_on_drop: size_of::() > 0, - }, - handler: receiver, + .map(|sub_state| { + Subscriber { + inner: SubscriberInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), + state: sub_state, + kind: SubscriberKind::Subscriber, + // `size_of::() == 0` means callback-only subscriber + undeclare_on_drop, + }, + handler: receiver, + } }) } } From 2c52a3c3530db593405c86b684e0fe117b66ba97 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Tue, 3 Sep 2024 05:52:25 +0200 Subject: [PATCH 08/34] feat!: make session an arc-like object The refactoring is quite deep, so this is the first (dirty) iteration which passes the tests. --- examples/examples/z_forward.rs | 2 +- examples/examples/z_get_liveliness.rs | 2 +- examples/examples/z_info.rs | 2 +- examples/examples/z_liveliness.rs | 2 +- examples/examples/z_pong.rs | 2 +- examples/examples/z_pull.rs | 2 +- examples/examples/z_queryable.rs | 2 +- examples/examples/z_queryable_shm.rs | 1 - examples/examples/z_storage.rs | 1 - examples/examples/z_sub.rs | 2 +- examples/examples/z_sub_liveliness.rs | 2 +- examples/examples/z_sub_shm.rs | 2 +- plugins/zenoh-plugin-example/src/lib.rs | 1 - .../zenoh-plugin-rest/examples/z_serve_sse.rs | 1 - plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../src/replica/mod.rs | 2 +- .../src/replica/storage.rs | 2 +- zenoh-ext/examples/examples/z_query_sub.rs | 2 +- zenoh-ext/src/publication_cache.rs | 25 +- zenoh-ext/src/querying_subscriber.rs | 24 +- zenoh-ext/src/session_ext.rs | 59 +- zenoh-ext/src/subscriber_ext.rs | 2 +- zenoh-ext/tests/liveliness.rs | 4 +- zenoh/src/api/admin.rs | 52 +- zenoh/src/api/builders/publisher.rs | 73 +- zenoh/src/api/info.rs | 29 +- zenoh/src/api/key_expr.rs | 14 +- zenoh/src/api/liveliness.rs | 81 +- zenoh/src/api/publisher.rs | 215 +--- zenoh/src/api/query.rs | 1 + zenoh/src/api/queryable.rs | 73 +- zenoh/src/api/session.rs | 1062 ++++++----------- zenoh/src/api/subscriber.rs | 85 +- zenoh/src/lib.rs | 5 +- zenoh/src/prelude.rs | 4 +- zenoh/tests/events.rs | 1 - zenoh/tests/liveliness.rs | 12 +- zenoh/tests/routing.rs | 6 +- 38 files changed, 673 insertions(+), 1186 deletions(-) diff --git a/examples/examples/z_forward.rs b/examples/examples/z_forward.rs index be9df7e2b0..1f6969766f 100644 --- a/examples/examples/z_forward.rs +++ b/examples/examples/z_forward.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; use zenoh_ext::SubscriberForward; diff --git a/examples/examples/z_get_liveliness.rs b/examples/examples/z_get_liveliness.rs index 53f7abc92a..d0040fcea4 100644 --- a/examples/examples/z_get_liveliness.rs +++ b/examples/examples/z_get_liveliness.rs @@ -14,7 +14,7 @@ use std::time::Duration; use clap::Parser; -use zenoh::{key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_info.rs b/examples/examples/z_info.rs index aa40ef62d4..606cdcbd16 100644 --- a/examples/examples/z_info.rs +++ b/examples/examples/z_info.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{prelude::*, session::ZenohId}; +use zenoh::session::ZenohId; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_liveliness.rs b/examples/examples/z_liveliness.rs index bf8890a267..1c51c2fce6 100644 --- a/examples/examples/z_liveliness.rs +++ b/examples/examples/z_liveliness.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index 86b31d41f3..8794d6bc7a 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -21,7 +21,7 @@ fn main() { let (config, express) = parse_args(); - let session = zenoh::open(config).wait().unwrap().into_arc(); + let session = zenoh::open(config).wait().unwrap(); // The key expression to read the data from let key_expr_ping = keyexpr::new("test/ping").unwrap(); diff --git a/examples/examples/z_pull.rs b/examples/examples/z_pull.rs index 6716ef8cc5..1239f7347f 100644 --- a/examples/examples/z_pull.rs +++ b/examples/examples/z_pull.rs @@ -14,7 +14,7 @@ use std::time::Duration; use clap::Parser; -use zenoh::{handlers::RingChannel, key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{handlers::RingChannel, key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_queryable.rs b/examples/examples/z_queryable.rs index 4b950a0a33..905f8d50c9 100644 --- a/examples/examples/z_queryable.rs +++ b/examples/examples/z_queryable.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_queryable_shm.rs b/examples/examples/z_queryable_shm.rs index e92efbdc38..6801457d5a 100644 --- a/examples/examples/z_queryable_shm.rs +++ b/examples/examples/z_queryable_shm.rs @@ -15,7 +15,6 @@ use clap::Parser; use zenoh::{ bytes::ZBytes, key_expr::KeyExpr, - prelude::*, shm::{ zshm, BlockOn, GarbageCollect, PosixShmProviderBackend, ShmProviderBuilder, POSIX_PROTOCOL_ID, diff --git a/examples/examples/z_storage.rs b/examples/examples/z_storage.rs index f812c78094..360e00f9d1 100644 --- a/examples/examples/z_storage.rs +++ b/examples/examples/z_storage.rs @@ -19,7 +19,6 @@ use clap::Parser; use futures::select; use zenoh::{ key_expr::{keyexpr, KeyExpr}, - prelude::*, sample::{Sample, SampleKind}, Config, }; diff --git a/examples/examples/z_sub.rs b/examples/examples/z_sub.rs index 7f3a93c5fb..eca53a7849 100644 --- a/examples/examples/z_sub.rs +++ b/examples/examples/z_sub.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_sub_liveliness.rs b/examples/examples/z_sub_liveliness.rs index bb91c9f491..0b70d20786 100644 --- a/examples/examples/z_sub_liveliness.rs +++ b/examples/examples/z_sub_liveliness.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{key_expr::KeyExpr, prelude::*, sample::SampleKind, Config}; +use zenoh::{key_expr::KeyExpr, sample::SampleKind, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/examples/examples/z_sub_shm.rs b/examples/examples/z_sub_shm.rs index f45dab099d..1f35a2636e 100644 --- a/examples/examples/z_sub_shm.rs +++ b/examples/examples/z_sub_shm.rs @@ -14,7 +14,7 @@ use clap::Parser; #[cfg(all(feature = "shared-memory", feature = "unstable"))] use zenoh::shm::zshm; -use zenoh::{bytes::ZBytes, config::Config, key_expr::KeyExpr, prelude::*}; +use zenoh::{bytes::ZBytes, config::Config, key_expr::KeyExpr}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/plugins/zenoh-plugin-example/src/lib.rs b/plugins/zenoh-plugin-example/src/lib.rs index b7c494946d..086e23aaa8 100644 --- a/plugins/zenoh-plugin-example/src/lib.rs +++ b/plugins/zenoh-plugin-example/src/lib.rs @@ -36,7 +36,6 @@ use zenoh::{ key_expr::{keyexpr, KeyExpr}, prelude::ZResult, sample::Sample, - session::SessionDeclarations, }; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index aefdfd4f86..fbd0269498 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -18,7 +18,6 @@ use zenoh::{ config::Config, key_expr::keyexpr, qos::{CongestionControl, QoSBuilderTrait}, - session::SessionDeclarations, }; const HTML: &str = r#" diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index eb65a991d6..289fc9e055 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -47,7 +47,7 @@ use zenoh::{ prelude::*, query::{Parameters, QueryConsolidation, Reply, Selector, ZenohParameters}, sample::{Sample, SampleKind}, - session::{Session, SessionDeclarations}, + session::Session, }; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/mod.rs b/plugins/zenoh-plugin-storage-manager/src/replica/mod.rs index 4766914e21..a9302cd8cf 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/mod.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/mod.rs @@ -24,7 +24,7 @@ use std::{ use flume::{Receiver, Sender}; use futures::{pin_mut, select, FutureExt}; use tokio::{sync::RwLock, time::interval}; -use zenoh::{key_expr::keyexpr, prelude::*}; +use zenoh::key_expr::keyexpr; use zenoh_backend_traits::config::{ReplicaConfig, StorageConfig}; use crate::{backends_mgt::StoreIntercept, storages_mgt::StorageMessage}; diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index d2147b137c..94e9d85d82 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -36,7 +36,7 @@ use zenoh::{ }, query::{ConsolidationMode, QueryTarget}, sample::{Sample, SampleBuilder, SampleKind, TimestampBuilderTrait}, - session::{Session, SessionDeclarations}, + session::Session, time::{Timestamp, NTP64}, }; use zenoh_backend_traits::{ diff --git a/zenoh-ext/examples/examples/z_query_sub.rs b/zenoh-ext/examples/examples/z_query_sub.rs index c819a2a831..1c1a3eab27 100644 --- a/zenoh-ext/examples/examples/z_query_sub.rs +++ b/zenoh-ext/examples/examples/z_query_sub.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::{arg, Parser}; -use zenoh::{config::Config, prelude::*, query::ReplyKeyExpr}; +use zenoh::{config::Config, query::ReplyKeyExpr}; use zenoh_ext::*; use zenoh_ext_examples::CommonArgs; diff --git a/zenoh-ext/src/publication_cache.rs b/zenoh-ext/src/publication_cache.rs index 9c1536c2a1..af548a3b6c 100644 --- a/zenoh-ext/src/publication_cache.rs +++ b/zenoh-ext/src/publication_cache.rs @@ -25,14 +25,13 @@ use zenoh::{ pubsub::FlumeSubscriber, query::{Query, Queryable, ZenohParameters}, sample::{Locality, Sample}, - session::{SessionDeclarations, SessionRef}, - Error, Resolvable, Resolve, Result as ZResult, + Error, Resolvable, Resolve, Result as ZResult, Session, }; /// The builder of PublicationCache, allowing to configure it. #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] pub struct PublicationCacheBuilder<'a, 'b, 'c> { - session: SessionRef<'a>, + session: &'a Session, pub_key_expr: ZResult>, queryable_prefix: Option>>, queryable_origin: Option, @@ -43,7 +42,7 @@ pub struct PublicationCacheBuilder<'a, 'b, 'c> { impl<'a, 'b, 'c> PublicationCacheBuilder<'a, 'b, 'c> { pub(crate) fn new( - session: SessionRef<'a>, + session: &'a Session, pub_key_expr: ZResult>, ) -> PublicationCacheBuilder<'a, 'b, 'c> { PublicationCacheBuilder { @@ -95,8 +94,8 @@ impl<'a, 'b, 'c> PublicationCacheBuilder<'a, 'b, 'c> { } } -impl<'a> Resolvable for PublicationCacheBuilder<'a, '_, '_> { - type To = ZResult>; +impl Resolvable for PublicationCacheBuilder<'_, '_, '_> { + type To = ZResult; } impl Wait for PublicationCacheBuilder<'_, '_, '_> { @@ -105,7 +104,7 @@ impl Wait for PublicationCacheBuilder<'_, '_, '_> { } } -impl<'a> IntoFuture for PublicationCacheBuilder<'a, '_, '_> { +impl IntoFuture for PublicationCacheBuilder<'_, '_, '_> { type Output = ::To; type IntoFuture = Ready<::To>; @@ -114,14 +113,14 @@ impl<'a> IntoFuture for PublicationCacheBuilder<'a, '_, '_> { } } -pub struct PublicationCache<'a> { - local_sub: FlumeSubscriber<'a>, - _queryable: Queryable<'a, flume::Receiver>, +pub struct PublicationCache { + local_sub: FlumeSubscriber, + _queryable: Queryable>, task: TerminatableTask, } -impl<'a> PublicationCache<'a> { - fn new(conf: PublicationCacheBuilder<'a, '_, '_>) -> ZResult> { +impl PublicationCache { + fn new(conf: PublicationCacheBuilder<'_, '_, '_>) -> ZResult { let key_expr = conf.pub_key_expr?; // the queryable_prefix (optional), and the key_expr for PublicationCache's queryable ("[]/") let (queryable_prefix, queryable_key_expr): (Option, KeyExpr) = @@ -258,7 +257,7 @@ impl<'a> PublicationCache<'a> { /// Undeclare this [`PublicationCache`]`. #[inline] - pub fn undeclare(self) -> impl Resolve> + 'a { + pub fn undeclare(self) -> impl Resolve> { ResolveFuture::new(async move { let PublicationCache { _queryable, diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 224abfde87..893cbcbad0 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -28,9 +28,8 @@ use zenoh::{ pubsub::{Reliability, Subscriber}, query::{QueryConsolidation, QueryTarget, ReplyKeyExpr, Selector}, sample::{Locality, Sample, SampleBuilder, TimestampBuilderTrait}, - session::{SessionDeclarations, SessionRef}, time::Timestamp, - Error, Resolvable, Resolve, Result as ZResult, + Error, Resolvable, Resolve, Result as ZResult, Session, }; use crate::ExtractSample; @@ -38,7 +37,7 @@ use crate::ExtractSample; /// The builder of [`FetchingSubscriber`], allowing to configure it. #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] pub struct QueryingSubscriberBuilder<'a, 'b, KeySpace, Handler> { - pub(crate) session: SessionRef<'a>, + pub(crate) session: &'a Session, pub(crate) key_expr: ZResult>, pub(crate) key_space: KeySpace, pub(crate) reliability: Reliability, @@ -224,7 +223,7 @@ where Handler: IntoHandler<'static, Sample>, Handler::Handler: Send, { - type To = ZResult>; + type To = ZResult>; } impl Wait for QueryingSubscriberBuilder<'_, '_, KeySpace, Handler> @@ -362,7 +361,7 @@ pub struct FetchingSubscriberBuilder< > where TryIntoSample: ExtractSample, { - pub(crate) session: SessionRef<'a>, + pub(crate) session: &'a Session, pub(crate) key_expr: ZResult>, pub(crate) key_space: KeySpace, pub(crate) reliability: Reliability, @@ -548,7 +547,7 @@ where Handler::Handler: Send, TryIntoSample: ExtractSample, { - type To = ZResult>; + type To = ZResult>; } impl< @@ -620,28 +619,29 @@ where /// } /// # } /// ``` -pub struct FetchingSubscriber<'a, Handler> { - subscriber: Subscriber<'a, ()>, +pub struct FetchingSubscriber { + subscriber: Subscriber<()>, callback: Arc, state: Arc>, handler: Handler, } -impl std::ops::Deref for FetchingSubscriber<'_, Handler> { +impl std::ops::Deref for FetchingSubscriber { type Target = Handler; fn deref(&self) -> &Self::Target { &self.handler } } -impl std::ops::DerefMut for FetchingSubscriber<'_, Handler> { +impl std::ops::DerefMut for FetchingSubscriber { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.handler } } -impl<'a, Handler> FetchingSubscriber<'a, Handler> { +impl FetchingSubscriber { fn new< + 'a, KeySpace, InputHandler, Fetch: FnOnce(Box) -> ZResult<()> + Send + Sync, @@ -724,7 +724,7 @@ impl<'a, Handler> FetchingSubscriber<'a, Handler> { /// Undeclare this [`FetchingSubscriber`]`. #[inline] - pub fn undeclare(self) -> impl Resolve> + 'a { + pub fn undeclare(self) -> impl Resolve> { self.subscriber.undeclare() } diff --git a/zenoh-ext/src/session_ext.rs b/zenoh-ext/src/session_ext.rs index 606f00743b..21f2fc5c6e 100644 --- a/zenoh-ext/src/session_ext.rs +++ b/zenoh-ext/src/session_ext.rs @@ -11,54 +11,13 @@ // Contributors: // ZettaScale Zenoh Team, // -use std::{convert::TryInto, sync::Arc}; -use zenoh::{ - key_expr::KeyExpr, - session::{Session, SessionRef}, - Error, -}; +use zenoh::{key_expr::KeyExpr, session::Session, Error}; use super::PublicationCacheBuilder; /// Some extensions to the [`zenoh::Session`](zenoh::Session) pub trait SessionExt<'s, 'a> { - fn declare_publication_cache<'b, 'c, TryIntoKeyExpr>( - &'s self, - pub_key_expr: TryIntoKeyExpr, - ) -> PublicationCacheBuilder<'a, 'b, 'c> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into; -} - -impl<'s, 'a> SessionExt<'s, 'a> for SessionRef<'a> { - fn declare_publication_cache<'b, 'c, TryIntoKeyExpr>( - &'s self, - pub_key_expr: TryIntoKeyExpr, - ) -> PublicationCacheBuilder<'a, 'b, 'c> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - PublicationCacheBuilder::new(self.clone(), pub_key_expr.try_into().map_err(Into::into)) - } -} - -impl<'a> SessionExt<'a, 'a> for Session { - fn declare_publication_cache<'b, 'c, TryIntoKeyExpr>( - &'a self, - pub_key_expr: TryIntoKeyExpr, - ) -> PublicationCacheBuilder<'a, 'b, 'c> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - SessionRef::Borrow(self).declare_publication_cache(pub_key_expr) - } -} - -impl<'s> SessionExt<'s, 'static> for Arc { /// Examples: /// ``` /// # #[tokio::main] @@ -69,7 +28,7 @@ impl<'s> SessionExt<'s, 'static> for Arc { /// /// let mut config = zenoh::config::default(); /// config.timestamping.set_enabled(Some(Unique(true))); - /// let session = zenoh::open(config).await.unwrap().into_arc(); + /// let session = zenoh::open(config).await.unwrap(); /// let publication_cache = session.declare_publication_cache("key/expression").await.unwrap(); /// tokio::task::spawn(async move { /// publication_cache.key_expr(); @@ -79,11 +38,21 @@ impl<'s> SessionExt<'s, 'static> for Arc { fn declare_publication_cache<'b, 'c, TryIntoKeyExpr>( &'s self, pub_key_expr: TryIntoKeyExpr, - ) -> PublicationCacheBuilder<'static, 'b, 'c> + ) -> PublicationCacheBuilder<'a, 'b, 'c> + where + TryIntoKeyExpr: TryInto>, + >>::Error: Into; +} + +impl<'a> SessionExt<'a, 'a> for Session { + fn declare_publication_cache<'b, 'c, TryIntoKeyExpr>( + &'a self, + pub_key_expr: TryIntoKeyExpr, + ) -> PublicationCacheBuilder<'a, 'b, 'c> where TryIntoKeyExpr: TryInto>, >>::Error: Into, { - SessionRef::Shared(self.clone()).declare_publication_cache(pub_key_expr) + PublicationCacheBuilder::new(self, pub_key_expr.try_into().map_err(Into::into)) } } diff --git a/zenoh-ext/src/subscriber_ext.rs b/zenoh-ext/src/subscriber_ext.rs index a7356f86dc..434ec15234 100644 --- a/zenoh-ext/src/subscriber_ext.rs +++ b/zenoh-ext/src/subscriber_ext.rs @@ -32,7 +32,7 @@ pub trait SubscriberForward<'a, S> { type Output; fn forward(&'a mut self, sink: S) -> Self::Output; } -impl<'a, S> SubscriberForward<'a, S> for Subscriber<'_, flume::Receiver> +impl<'a, S> SubscriberForward<'a, S> for Subscriber> where S: futures::sink::Sink, { diff --git a/zenoh-ext/tests/liveliness.rs b/zenoh-ext/tests/liveliness.rs index 637d07ba57..51c8a79cd3 100644 --- a/zenoh-ext/tests/liveliness.rs +++ b/zenoh-ext/tests/liveliness.rs @@ -21,7 +21,7 @@ use zenoh::{ async fn test_liveliness_querying_subscriber_clique() { use std::time::Duration; - use zenoh::{internal::ztimeout, prelude::*}; + use zenoh::internal::ztimeout; use zenoh_ext::SubscriberBuilderExt; const TIMEOUT: Duration = Duration::from_secs(60); @@ -99,7 +99,7 @@ async fn test_liveliness_querying_subscriber_clique() { async fn test_liveliness_querying_subscriber_brokered() { use std::time::Duration; - use zenoh::{internal::ztimeout, prelude::*}; + use zenoh::internal::ztimeout; use zenoh_ext::SubscriberBuilderExt; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenoh/src/api/admin.rs b/zenoh/src/api/admin.rs index 8c20a275c1..7452431977 100644 --- a/zenoh/src/api/admin.rs +++ b/zenoh/src/api/admin.rs @@ -14,7 +14,7 @@ use std::{ collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, - sync::Arc, + sync::{Arc, Weak}, }; use zenoh_core::{Result as ZResult, Wait}; @@ -32,9 +32,9 @@ use super::{ key_expr::KeyExpr, queryable::Query, sample::{DataInfo, Locality, SampleKind}, - session::Session, subscriber::SubscriberKind, }; +use crate::api::session::SessionInner; lazy_static::lazy_static!( static ref KE_STARSTAR: &'static keyexpr = unsafe { keyexpr::from_str_unchecked("**") }; @@ -44,8 +44,8 @@ lazy_static::lazy_static!( static ref KE_LINK: &'static keyexpr = unsafe { keyexpr::from_str_unchecked("link") }; ); -pub(crate) fn init(session: &Session) { - if let Ok(own_zid) = keyexpr::new(&session.zid().to_string()) { +pub(crate) fn init(session: &Arc) { + if let Ok(own_zid) = keyexpr::new(&session.runtime.zid().to_string()) { let admin_key = KeyExpr::from(*KE_PREFIX / own_zid / *KE_SESSION / *KE_STARSTAR) .to_wire(session) .to_owned(); @@ -55,14 +55,18 @@ pub(crate) fn init(session: &Session) { true, Locality::SessionLocal, Arc::new({ - let session = session.clone(); - move |q| super::admin::on_admin_query(&session, q) + let session = Arc::downgrade(session); + move |q| { + if let Some(session) = Weak::upgrade(&session) { + on_admin_query(&session, q) + } + } }), ); } } -pub(crate) fn on_admin_query(session: &Session, query: Query) { +pub(crate) fn on_admin_query(session: &SessionInner, query: Query) { fn reply_peer(own_zid: &keyexpr, query: &Query, peer: TransportPeer) { let zid = peer.zid.to_string(); if let Ok(zid) = keyexpr::new(&zid) { @@ -104,7 +108,7 @@ pub(crate) fn on_admin_query(session: &Session, query: Query) { } } - if let Ok(own_zid) = keyexpr::new(&session.zid().to_string()) { + if let Ok(own_zid) = keyexpr::new(&session.runtime.zid().to_string()) { for transport in zenoh_runtime::ZRuntime::Net .block_in_place(session.runtime.manager().get_transports_unicast()) { @@ -124,14 +128,12 @@ pub(crate) fn on_admin_query(session: &Session, query: Query) { #[derive(Clone)] pub(crate) struct Handler { - pub(crate) session: Arc, + pub(crate) session: Weak, } impl Handler { - pub(crate) fn new(session: Session) -> Self { - Self { - session: Arc::new(session), - } + pub(crate) fn new(session: Weak) -> Self { + Self { session } } } @@ -157,7 +159,10 @@ impl TransportMulticastEventHandler for Handler { &self, peer: zenoh_transport::TransportPeer, ) -> ZResult> { - if let Ok(own_zid) = keyexpr::new(&self.session.zid().to_string()) { + let Some(session) = Weak::upgrade(&self.session) else { + bail!("session closed"); + }; + if let Ok(own_zid) = keyexpr::new(&session.runtime.zid().to_string()) { if let Ok(zid) = keyexpr::new(&peer.zid.to_string()) { let expr = WireExpr::from( &(*KE_PREFIX / own_zid / *KE_SESSION / *KE_TRANSPORT_UNICAST / zid), @@ -167,7 +172,7 @@ impl TransportMulticastEventHandler for Handler { encoding: Some(Encoding::APPLICATION_JSON), ..Default::default() }; - self.session.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( true, &expr, Some(info), @@ -200,7 +205,7 @@ impl TransportMulticastEventHandler for Handler { pub(crate) struct PeerHandler { pub(crate) expr: WireExpr<'static>, - pub(crate) session: Arc, + pub(crate) session: Weak, } impl TransportPeerEventHandler for PeerHandler { @@ -209,13 +214,16 @@ impl TransportPeerEventHandler for PeerHandler { } fn new_link(&self, link: zenoh_link::Link) { + let Some(session) = Weak::upgrade(&self.session) else { + return; + }; let mut s = DefaultHasher::new(); link.hash(&mut s); let info = DataInfo { encoding: Some(Encoding::APPLICATION_JSON), ..Default::default() }; - self.session.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( true, &self .expr @@ -231,13 +239,16 @@ impl TransportPeerEventHandler for PeerHandler { } fn del_link(&self, link: zenoh_link::Link) { + let Some(session) = Weak::upgrade(&self.session) else { + return; + }; let mut s = DefaultHasher::new(); link.hash(&mut s); let info = DataInfo { kind: SampleKind::Delete, ..Default::default() }; - self.session.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( true, &self .expr @@ -255,11 +266,14 @@ impl TransportPeerEventHandler for PeerHandler { fn closing(&self) {} fn closed(&self) { + let Some(session) = Weak::upgrade(&self.session) else { + return; + }; let info = DataInfo { kind: SampleKind::Delete, ..Default::default() }; - self.session.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( true, &self.expr, Some(info), diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index 8a6961ac55..957bee62f8 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -20,16 +20,18 @@ use zenoh_protocol::{core::CongestionControl, network::Mapping}; #[cfg(feature = "unstable")] use crate::api::sample::SourceInfo; -use crate::api::{ - builders::sample::{ - EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, +use crate::{ + api::{ + builders::sample::{ + EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, + }, + bytes::{OptionZBytes, ZBytes}, + encoding::Encoding, + key_expr::KeyExpr, + publisher::{Priority, Publisher}, + sample::{Locality, SampleKind}, }, - bytes::{OptionZBytes, ZBytes}, - encoding::Encoding, - key_expr::KeyExpr, - publisher::{Priority, Publisher}, - sample::{Locality, SampleKind}, - session::SessionRef, + Session, }; pub type SessionPutBuilder<'a, 'b> = @@ -245,8 +247,8 @@ impl IntoFuture for PublicationBuilder, PublicationBuil /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] -pub struct PublisherBuilder<'a, 'b: 'a> { - pub(crate) session: SessionRef<'a>, +pub struct PublisherBuilder<'a, 'b> { + pub(crate) session: &'a Session, pub(crate) key_expr: ZResult>, pub(crate) encoding: Encoding, pub(crate) congestion_control: CongestionControl, @@ -260,7 +262,7 @@ pub struct PublisherBuilder<'a, 'b: 'a> { impl<'a, 'b> Clone for PublisherBuilder<'a, 'b> { fn clone(&self) -> Self { Self { - session: self.session.clone(), + session: self.session, key_expr: match &self.key_expr { Ok(k) => Ok(k.clone()), Err(e) => Err(zerror!("Cloned KE Error: {}", e).into()), @@ -324,9 +326,9 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { } // internal function for performing the publication - fn create_one_shot_publisher(self) -> ZResult> { + fn create_one_shot_publisher(self) -> ZResult> { Ok(Publisher { - session: self.session, + session: self.session.clone().0, id: 0, // This is a one shot Publisher key_expr: self.key_expr?, encoding: self.encoding, @@ -344,15 +346,15 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { } impl<'a, 'b> Resolvable for PublisherBuilder<'a, 'b> { - type To = ZResult>; + type To = ZResult>; } impl<'a, 'b> Wait for PublisherBuilder<'a, 'b> { fn wait(self) -> ::To { let mut key_expr = self.key_expr?; - if !key_expr.is_fully_optimized(&self.session) { - let session_id = self.session.id; - let expr_id = self.session.declare_prefix(key_expr.as_str()).wait(); + if !key_expr.is_fully_optimized(&self.session.0) { + let session_id = self.session.0.id; + let expr_id = self.session.0.declare_prefix(key_expr.as_str()).wait()?; let prefix_len = key_expr .len() .try_into() @@ -380,23 +382,24 @@ impl<'a, 'b> Wait for PublisherBuilder<'a, 'b> { } } } - self.session - .declare_publisher_inner(key_expr.clone(), self.destination) - .map(|id| Publisher { - session: self.session, - id, - key_expr, - encoding: self.encoding, - congestion_control: self.congestion_control, - priority: self.priority, - is_express: self.is_express, - destination: self.destination, - #[cfg(feature = "unstable")] - reliability: self.reliability, - #[cfg(feature = "unstable")] - matching_listeners: Default::default(), - undeclare_on_drop: true, - }) + let id = self + .session + .0 + .declare_publisher_inner(key_expr.clone(), self.destination)?; + Ok(Publisher { + session: self.session.0.clone(), + id, + key_expr, + encoding: self.encoding, + congestion_control: self.congestion_control, + priority: self.priority, + is_express: self.is_express, + destination: self.destination, + #[cfg(feature = "unstable")] + reliability: self.reliability, + #[cfg(feature = "unstable")]matching_listeners: Default::default(), + undeclare_on_drop: true, + }) } } diff --git a/zenoh/src/api/info.rs b/zenoh/src/api/info.rs index 32bed0eb53..88f8dd57b7 100644 --- a/zenoh/src/api/info.rs +++ b/zenoh/src/api/info.rs @@ -19,7 +19,7 @@ use zenoh_config::wrappers::ZenohId; use zenoh_core::{Resolvable, Wait}; use zenoh_protocol::core::WhatAmI; -use super::session::SessionRef; +use crate::net::runtime::Runtime; /// A builder retuned by [`SessionInfo::zid()`](SessionInfo::zid) that allows /// to access the [`ZenohId`] of the current zenoh [`Session`](crate::Session). @@ -35,9 +35,8 @@ use super::session::SessionRef; /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -#[derive(Debug)] pub struct ZenohIdBuilder<'a> { - pub(crate) session: SessionRef<'a>, + runtime: &'a Runtime, } impl<'a> Resolvable for ZenohIdBuilder<'a> { @@ -46,7 +45,7 @@ impl<'a> Resolvable for ZenohIdBuilder<'a> { impl<'a> Wait for ZenohIdBuilder<'a> { fn wait(self) -> Self::To { - self.session.runtime.zid() + self.runtime.zid() } } @@ -75,9 +74,8 @@ impl<'a> IntoFuture for ZenohIdBuilder<'a> { /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -#[derive(Debug)] pub struct RoutersZenohIdBuilder<'a> { - pub(crate) session: SessionRef<'a>, + runtime: &'a Runtime, } impl<'a> Resolvable for RoutersZenohIdBuilder<'a> { @@ -88,7 +86,7 @@ impl<'a> Wait for RoutersZenohIdBuilder<'a> { fn wait(self) -> Self::To { Box::new( zenoh_runtime::ZRuntime::Application - .block_in_place(self.session.runtime.manager().get_transports_unicast()) + .block_in_place(self.runtime.manager().get_transports_unicast()) .into_iter() .filter_map(|s| { s.get_whatami() @@ -125,9 +123,8 @@ impl<'a> IntoFuture for RoutersZenohIdBuilder<'a> { /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -#[derive(Debug)] pub struct PeersZenohIdBuilder<'a> { - pub(crate) session: SessionRef<'a>, + runtime: &'a Runtime, } impl<'a> Resolvable for PeersZenohIdBuilder<'a> { @@ -138,7 +135,7 @@ impl<'a> Wait for PeersZenohIdBuilder<'a> { fn wait(self) -> ::To { Box::new( zenoh_runtime::ZRuntime::Application - .block_in_place(self.session.runtime.manager().get_transports_unicast()) + .block_in_place(self.runtime.manager().get_transports_unicast()) .into_iter() .filter_map(|s| { s.get_whatami() @@ -173,11 +170,11 @@ impl<'a> IntoFuture for PeersZenohIdBuilder<'a> { /// let zid = info.zid().await; /// # } /// ``` -pub struct SessionInfo<'a> { - pub(crate) session: SessionRef<'a>, +pub struct SessionInfo { + pub(crate) runtime: Runtime, } -impl SessionInfo<'_> { +impl SessionInfo { /// Return the [`ZenohId`] of the current zenoh [`Session`](crate::Session). /// /// # Examples @@ -192,7 +189,7 @@ impl SessionInfo<'_> { /// ``` pub fn zid(&self) -> ZenohIdBuilder<'_> { ZenohIdBuilder { - session: self.session.clone(), + runtime: &self.runtime, } } @@ -212,7 +209,7 @@ impl SessionInfo<'_> { /// ``` pub fn routers_zid(&self) -> RoutersZenohIdBuilder<'_> { RoutersZenohIdBuilder { - session: self.session.clone(), + runtime: &self.runtime, } } @@ -231,7 +228,7 @@ impl SessionInfo<'_> { /// ``` pub fn peers_zid(&self) -> PeersZenohIdBuilder<'_> { PeersZenohIdBuilder { - session: self.session.clone(), + runtime: &self.runtime, } } } diff --git a/zenoh/src/api/key_expr.rs b/zenoh/src/api/key_expr.rs index 0f0d13a69c..6ed0cbcea3 100644 --- a/zenoh/src/api/key_expr.rs +++ b/zenoh/src/api/key_expr.rs @@ -25,7 +25,7 @@ use zenoh_protocol::{ }; use zenoh_result::ZResult; -use super::session::{Session, UndeclarableSealed}; +use super::session::{Session, SessionInner, UndeclarableSealed}; use crate::net::primitives::Primitives; #[derive(Clone, Debug)] @@ -492,7 +492,7 @@ impl<'a> KeyExpr<'a> { //pub(crate) fn is_optimized(&self, session: &Session) -> bool { // matches!(&self.0, KeyExprInner::Wire { expr_id, session_id, .. } | KeyExprInner::BorrowedWire { expr_id, session_id, .. } if *expr_id != 0 && session.id == *session_id) //} - pub(crate) fn is_fully_optimized(&self, session: &Session) -> bool { + pub(crate) fn is_fully_optimized(&self, session: &SessionInner) -> bool { match &self.0 { KeyExprInner::Wire { key_expr, @@ -509,7 +509,7 @@ impl<'a> KeyExpr<'a> { _ => false, } } - pub(crate) fn to_wire(&'a self, session: &Session) -> WireExpr<'a> { + pub(crate) fn to_wire(&'a self, session: &SessionInner) -> WireExpr<'a> { match &self.0 { KeyExprInner::Wire { key_expr, @@ -594,7 +594,7 @@ impl Wait for KeyExprUndeclaration<'_> { session_id, .. } if *prefix_len as usize == key_expr.len() => { - if *session_id == session.id { + if *session_id == session.0.id { *expr_id } else { return Err(zerror!("Failed to undeclare {}, as it was declared by an other Session", expr).into()) @@ -607,7 +607,7 @@ impl Wait for KeyExprUndeclaration<'_> { session_id, .. } if *prefix_len as usize == key_expr.len() => { - if *session_id == session.id { + if *session_id == session.0.id { *expr_id } else { return Err(zerror!("Failed to undeclare {}, as it was declared by an other Session", expr).into()) @@ -616,10 +616,10 @@ impl Wait for KeyExprUndeclaration<'_> { _ => return Err(zerror!("Failed to undeclare {}, make sure you use the result of `Session::declare_keyexpr` to call `Session::undeclare`", expr).into()), }; tracing::trace!("undeclare_keyexpr({:?})", expr_id); - let mut state = zwrite!(session.state); + let mut state = zwrite!(session.0.state); state.local_resources.remove(&expr_id); - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_declare(zenoh_protocol::network::Declare { interest_id: None, diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index f22de66b02..50bcf9da67 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -16,7 +16,7 @@ use std::{ convert::TryInto, future::{IntoFuture, Ready}, mem::size_of, - sync::Arc, + sync::{Arc, Weak}, time::Duration, }; @@ -29,11 +29,11 @@ use super::{ key_expr::KeyExpr, query::Reply, sample::{Locality, Sample}, - session::{Session, SessionRef, UndeclarableSealed}, + session::{Session, UndeclarableSealed}, subscriber::{Subscriber, SubscriberInner}, Id, }; -use crate::api::session::MaybeWeakSessionRef; +use crate::api::session::SessionInner; /// A structure with functions to declare a /// [`LivelinessToken`](LivelinessToken), query @@ -97,7 +97,7 @@ use crate::api::session::MaybeWeakSessionRef; /// ``` #[zenoh_macros::unstable] pub struct Liveliness<'a> { - pub(crate) session: SessionRef<'a>, + pub(crate) session: &'a Session, } #[zenoh_macros::unstable] @@ -132,7 +132,7 @@ impl<'a> Liveliness<'a> { >>::Error: Into, { LivelinessTokenBuilder { - session: self.session.clone(), + session: self.session, key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), } } @@ -169,7 +169,7 @@ impl<'a> Liveliness<'a> { >>::Error: Into, { LivelinessSubscriberBuilder { - session: self.session.clone(), + session: self.session, key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), handler: DefaultHandler::default(), } @@ -207,11 +207,11 @@ impl<'a> Liveliness<'a> { { let key_expr = key_expr.try_into().map_err(Into::into); let timeout = { - let conf = self.session.runtime.config().lock(); + let conf = self.session.0.runtime.config().lock(); Duration::from_millis(unwrap_or_default!(conf.queries_default_timeout())) }; LivelinessGetBuilder { - session: &self.session, + session: self.session, key_expr, timeout, handler: DefaultHandler::default(), @@ -239,13 +239,13 @@ impl<'a> Liveliness<'a> { #[zenoh_macros::unstable] #[derive(Debug)] pub struct LivelinessTokenBuilder<'a, 'b> { - pub(crate) session: SessionRef<'a>, + pub(crate) session: &'a Session, pub(crate) key_expr: ZResult>, } #[zenoh_macros::unstable] -impl<'a> Resolvable for LivelinessTokenBuilder<'a, '_> { - type To = ZResult>; +impl Resolvable for LivelinessTokenBuilder<'_, '_> { + type To = ZResult; } #[zenoh_macros::unstable] @@ -254,13 +254,13 @@ impl Wait for LivelinessTokenBuilder<'_, '_> { fn wait(self) -> ::To { let session = self.session; let key_expr = self.key_expr?.into_owned(); - let undeclare_on_drop = true; session + .0 .declare_liveliness_inner(&key_expr) .map(|tok_state| LivelinessToken { - session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), + session: Arc::downgrade(&self.session.0), state: tok_state, - undeclare_on_drop, + undeclare_on_drop: true, }) } } @@ -310,8 +310,8 @@ pub(crate) struct LivelinessTokenState { /// ``` #[zenoh_macros::unstable] #[derive(Debug)] -pub struct LivelinessToken<'a> { - session: MaybeWeakSessionRef<'a>, +pub struct LivelinessToken { + session: Weak, state: Arc, undeclare_on_drop: bool, } @@ -336,22 +336,22 @@ pub struct LivelinessToken<'a> { /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[zenoh_macros::unstable] -pub struct LivelinessTokenUndeclaration<'a>(LivelinessToken<'a>); +pub struct LivelinessTokenUndeclaration(LivelinessToken); #[zenoh_macros::unstable] -impl Resolvable for LivelinessTokenUndeclaration<'_> { +impl Resolvable for LivelinessTokenUndeclaration { type To = ZResult<()>; } #[zenoh_macros::unstable] -impl Wait for LivelinessTokenUndeclaration<'_> { +impl Wait for LivelinessTokenUndeclaration { fn wait(mut self) -> ::To { self.0.undeclare_impl() } } #[zenoh_macros::unstable] -impl<'a> IntoFuture for LivelinessTokenUndeclaration<'a> { +impl IntoFuture for LivelinessTokenUndeclaration { type Output = ::To; type IntoFuture = Ready<::To>; @@ -361,7 +361,7 @@ impl<'a> IntoFuture for LivelinessTokenUndeclaration<'a> { } #[zenoh_macros::unstable] -impl<'a> LivelinessToken<'a> { +impl LivelinessToken { /// Undeclare the [`LivelinessToken`]. /// /// # Examples @@ -381,7 +381,7 @@ impl<'a> LivelinessToken<'a> { /// # } /// ``` #[inline] - pub fn undeclare(self) -> impl Resolve> + 'a { + pub fn undeclare(self) -> impl Resolve> { UndeclarableSealed::undeclare_inner(self, ()) } @@ -396,8 +396,8 @@ impl<'a> LivelinessToken<'a> { } #[zenoh_macros::unstable] -impl<'a> UndeclarableSealed<()> for LivelinessToken<'a> { - type Undeclaration = LivelinessTokenUndeclaration<'a>; +impl UndeclarableSealed<()> for LivelinessToken { + type Undeclaration = LivelinessTokenUndeclaration; fn undeclare_inner(self, _: ()) -> Self::Undeclaration { LivelinessTokenUndeclaration(self) @@ -405,7 +405,7 @@ impl<'a> UndeclarableSealed<()> for LivelinessToken<'a> { } #[zenoh_macros::unstable] -impl Drop for LivelinessToken<'_> { +impl Drop for LivelinessToken { fn drop(&mut self) { if self.undeclare_on_drop { if let Err(error) = self.undeclare_impl() { @@ -435,7 +435,7 @@ impl Drop for LivelinessToken<'_> { #[zenoh_macros::unstable] #[derive(Debug)] pub struct LivelinessSubscriberBuilder<'a, 'b, Handler> { - pub session: SessionRef<'a>, + pub session: &'a Session, pub key_expr: ZResult>, pub handler: Handler, } @@ -558,7 +558,7 @@ where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, { - type To = ZResult>; + type To = ZResult>; } #[zenoh_macros::unstable] @@ -574,22 +574,20 @@ where let key_expr = self.key_expr?; let session = self.session; let (callback, handler) = self.handler.into_handler(); - let undeclare_on_drop = size_of::() > 0; session + .0 .declare_liveliness_subscriber_inner(&key_expr, Locality::default(), callback) - .map(|sub_state| { - Subscriber { - inner: SubscriberInner { - #[cfg(feature = "unstable")] - session_id: session.zid(), - session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), - state: sub_state, - kind: SubscriberKind::LivelinessSubscriber, - // `size_of::() == 0` means callback-only subscriber - undeclare_on_drop, - }, - handler, - } + .map(|sub_state| Subscriber { + inner: SubscriberInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: Arc::downgrade(&self.session.0), + state: sub_state, + kind: SubscriberKind::LivelinessSubscriber, + // `size_of::() == 0` means callback-only subscriber + undeclare_on_drop: size_of::() > 0, + }, + handler, }) } } @@ -775,6 +773,7 @@ where fn wait(self) -> ::To { let (callback, receiver) = self.handler.into_handler(); self.session + .0 .liveliness_query(&self.key_expr?, self.timeout, callback) .map(|_| receiver) } diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 0661ad3dec..2777b52b8a 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -17,6 +17,7 @@ use std::{ fmt, future::{IntoFuture, Ready}, pin::Pin, + sync::Arc, task::{Context, Poll}, }; @@ -35,10 +36,7 @@ use { handlers::{Callback, DefaultHandler, IntoHandler}, sample::SourceInfo, }, - std::{ - collections::HashSet, - sync::{Arc, Mutex}, - }, + std::{collections::HashSet, sync::Mutex}, zenoh_config::wrappers::EntityGlobalId, zenoh_protocol::core::EntityGlobalIdProto, }; @@ -52,10 +50,10 @@ use super::{ encoding::Encoding, key_expr::KeyExpr, sample::{DataInfo, Locality, QoS, Sample, SampleFields, SampleKind}, - session::{SessionRef, UndeclarableSealed}, + session::UndeclarableSealed, }; use crate::{ - api::{subscriber::SubscriberKind, Id}, + api::{session::SessionInner, subscriber::SubscriberKind, Id}, net::primitives::Primitives, }; @@ -75,35 +73,6 @@ impl fmt::Debug for PublisherState { } } -#[zenoh_macros::unstable] -#[derive(Clone)] -pub enum PublisherRef<'a> { - Borrow(&'a Publisher<'a>), - Shared(Arc>), -} - -#[zenoh_macros::unstable] -impl<'a> std::ops::Deref for PublisherRef<'a> { - type Target = Publisher<'a>; - - fn deref(&self) -> &Self::Target { - match self { - PublisherRef::Borrow(b) => b, - PublisherRef::Shared(s) => s, - } - } -} - -#[zenoh_macros::unstable] -impl std::fmt::Debug for PublisherRef<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - PublisherRef::Borrow(b) => Publisher::fmt(b, f), - PublisherRef::Shared(s) => Publisher::fmt(s, f), - } - } -} - /// A publisher that allows to send data through a stream. /// /// Publishers are automatically undeclared when dropped. @@ -114,7 +83,7 @@ impl std::fmt::Debug for PublisherRef<'_> { /// # async fn main() { /// use zenoh::prelude::*; /// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); +/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); /// publisher.put("value").await.unwrap(); /// # } @@ -129,7 +98,7 @@ impl std::fmt::Debug for PublisherRef<'_> { /// use futures::StreamExt; /// use zenoh::prelude::*; /// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); +/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut subscriber = session.declare_subscriber("key/expression").await.unwrap(); /// let publisher = session.declare_publisher("another/key/expression").await.unwrap(); /// subscriber.stream().map(Ok).forward(publisher).await.unwrap(); @@ -137,7 +106,7 @@ impl std::fmt::Debug for PublisherRef<'_> { /// ``` #[derive(Debug, Clone)] pub struct Publisher<'a> { - pub(crate) session: SessionRef<'a>, + pub(crate) session: Arc, pub(crate) id: Id, pub(crate) key_expr: KeyExpr<'a>, pub(crate) encoding: Encoding, @@ -171,7 +140,7 @@ impl<'a> Publisher<'a> { #[zenoh_macros::unstable] pub fn id(&self) -> EntityGlobalId { EntityGlobalIdProto { - zid: self.session.zid().into(), + zid: self.session.runtime.zid().into(), eid: self.id, } .into() @@ -200,42 +169,6 @@ impl<'a> Publisher<'a> { self.priority } - /// Consumes the given `Publisher`, returning a thread-safe reference-counting - /// pointer to it (`Arc`). This is equivalent to `Arc::new(Publisher)`. - /// - /// This is useful to share ownership of the `Publisher` between several threads - /// and tasks. It also allows to create [`MatchingListener`] with static - /// lifetime that can be moved to several threads and tasks. - /// - /// Note: the given zenoh `Publisher` will be undeclared when the last reference to - /// it is dropped. - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let publisher = session.declare_publisher("key/expression").await.unwrap().into_arc(); - /// let matching_listener = publisher.matching_listener().await.unwrap(); - /// - /// tokio::task::spawn(async move { - /// while let Ok(matching_status) = matching_listener.recv_async().await { - /// if matching_status.matching_subscribers() { - /// println!("Publisher has matching subscribers."); - /// } else { - /// println!("Publisher has NO MORE matching subscribers."); - /// } - /// } - /// }).await; - /// # } - /// ``` - #[zenoh_macros::unstable] - pub fn into_arc(self) -> std::sync::Arc { - std::sync::Arc::new(self) - } - /// Put data. /// /// # Examples @@ -244,7 +177,7 @@ impl<'a> Publisher<'a> { /// # async fn main() { /// use zenoh::prelude::*; /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); /// publisher.put("value").await.unwrap(); /// # } @@ -275,7 +208,7 @@ impl<'a> Publisher<'a> { /// # async fn main() { /// use zenoh::prelude::*; /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); /// publisher.delete().await.unwrap(); /// # } @@ -302,7 +235,7 @@ impl<'a> Publisher<'a> { /// # async fn main() { /// use zenoh::prelude::*; /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); /// let matching_subscribers: bool = publisher /// .matching_status() @@ -343,9 +276,9 @@ impl<'a> Publisher<'a> { /// # } /// ``` #[zenoh_macros::unstable] - pub fn matching_listener(&self) -> MatchingListenerBuilder<'_, DefaultHandler> { + pub fn matching_listener(&self) -> MatchingListenerBuilder<'_, 'a, DefaultHandler> { MatchingListenerBuilder { - publisher: PublisherRef::Borrow(self), + publisher: self, handler: DefaultHandler::default(), } } @@ -381,94 +314,6 @@ impl<'a> Publisher<'a> { } } -/// Functions to create zenoh entities with `'static` lifetime. -/// -/// This trait contains functions to create zenoh entities like -/// [`MatchingListener`] with a `'static` lifetime. -/// This is useful to move zenoh entities to several threads and tasks. -/// -/// This trait is implemented for `Arc`. -/// -/// # Examples -/// ```no_run -/// # #[tokio::main] -/// # async fn main() { -/// use zenoh::prelude::*; -/// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); -/// let publisher = session.declare_publisher("key/expression").await.unwrap().into_arc(); -/// let matching_listener = publisher.matching_listener().await.unwrap(); -/// -/// tokio::task::spawn(async move { -/// while let Ok(matching_status) = matching_listener.recv_async().await { -/// if matching_status.matching_subscribers() { -/// println!("Publisher has matching subscribers."); -/// } else { -/// println!("Publisher has NO MORE matching subscribers."); -/// } -/// } -/// }).await; -/// # } -/// ``` -#[zenoh_macros::unstable] -pub trait PublisherDeclarations { - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let publisher = session.declare_publisher("key/expression").await.unwrap().into_arc(); - /// let matching_listener = publisher.matching_listener().await.unwrap(); - /// - /// tokio::task::spawn(async move { - /// while let Ok(matching_status) = matching_listener.recv_async().await { - /// if matching_status.matching_subscribers() { - /// println!("Publisher has matching subscribers."); - /// } else { - /// println!("Publisher has NO MORE matching subscribers."); - /// } - /// } - /// }).await; - /// # } - /// ``` - #[zenoh_macros::unstable] - fn matching_listener(&self) -> MatchingListenerBuilder<'static, DefaultHandler>; -} - -#[zenoh_macros::unstable] -impl PublisherDeclarations for std::sync::Arc> { - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let publisher = session.declare_publisher("key/expression").await.unwrap().into_arc(); - /// let matching_listener = publisher.matching_listener().await.unwrap(); - /// - /// tokio::task::spawn(async move { - /// while let Ok(matching_status) = matching_listener.recv_async().await { - /// if matching_status.matching_subscribers() { - /// println!("Publisher has matching subscribers."); - /// } else { - /// println!("Publisher has NO MORE matching subscribers."); - /// } - /// } - /// }).await; - /// # } - /// ``` - #[zenoh_macros::unstable] - fn matching_listener(&self) -> MatchingListenerBuilder<'static, DefaultHandler> { - MatchingListenerBuilder { - publisher: PublisherRef::Shared(self.clone()), - handler: DefaultHandler::default(), - } - } -} - impl<'a> UndeclarableSealed<()> for Publisher<'a> { type Undeclaration = PublisherUndeclaration<'a>; @@ -753,7 +598,7 @@ impl TryFrom for Priority { /// # async fn main() { /// use zenoh::prelude::*; /// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); +/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); /// let matching_status = publisher.matching_status().await.unwrap(); /// # } @@ -774,7 +619,7 @@ impl MatchingStatus { /// # async fn main() { /// use zenoh::prelude::*; /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); /// let matching_subscribers: bool = publisher /// .matching_status() @@ -791,13 +636,13 @@ impl MatchingStatus { /// A builder for initializing a [`MatchingListener`]. #[zenoh_macros::unstable] #[derive(Debug)] -pub struct MatchingListenerBuilder<'a, Handler> { - pub(crate) publisher: PublisherRef<'a>, +pub struct MatchingListenerBuilder<'a, 'b, Handler> { + pub(crate) publisher: &'a Publisher<'b>, pub handler: Handler, } #[zenoh_macros::unstable] -impl<'a> MatchingListenerBuilder<'a, DefaultHandler> { +impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { /// Receive the MatchingStatuses for this listener with a callback. /// /// # Examples @@ -823,7 +668,7 @@ impl<'a> MatchingListenerBuilder<'a, DefaultHandler> { /// ``` #[inline] #[zenoh_macros::unstable] - pub fn callback(self, callback: Callback) -> MatchingListenerBuilder<'a, Callback> + pub fn callback(self, callback: Callback) -> MatchingListenerBuilder<'a, 'b, Callback> where Callback: Fn(MatchingStatus) + Send + Sync + 'static, { @@ -860,7 +705,7 @@ impl<'a> MatchingListenerBuilder<'a, DefaultHandler> { pub fn callback_mut( self, callback: CallbackMut, - ) -> MatchingListenerBuilder<'a, impl Fn(MatchingStatus) + Send + Sync + 'static> + ) -> MatchingListenerBuilder<'a, 'b, impl Fn(MatchingStatus) + Send + Sync + 'static> where CallbackMut: FnMut(MatchingStatus) + Send + Sync + 'static, { @@ -893,7 +738,7 @@ impl<'a> MatchingListenerBuilder<'a, DefaultHandler> { /// ``` #[inline] #[zenoh_macros::unstable] - pub fn with(self, handler: Handler) -> MatchingListenerBuilder<'a, Handler> + pub fn with(self, handler: Handler) -> MatchingListenerBuilder<'a, 'b, Handler> where Handler: IntoHandler<'static, MatchingStatus>, { @@ -906,7 +751,7 @@ impl<'a> MatchingListenerBuilder<'a, DefaultHandler> { } #[zenoh_macros::unstable] -impl<'a, Handler> Resolvable for MatchingListenerBuilder<'a, Handler> +impl<'a, 'b, Handler> Resolvable for MatchingListenerBuilder<'a, 'b, Handler> where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, @@ -915,7 +760,7 @@ where } #[zenoh_macros::unstable] -impl<'a, Handler> Wait for MatchingListenerBuilder<'a, Handler> +impl<'a, 'b, Handler> Wait for MatchingListenerBuilder<'a, 'b, Handler> where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, @@ -926,11 +771,11 @@ where let state = self .publisher .session - .declare_matches_listener_inner(&self.publisher, callback)?; + .declare_matches_listener_inner(self.publisher, callback)?; zlock!(self.publisher.matching_listeners).insert(state.id); Ok(MatchingListener { listener: MatchingListenerInner { - publisher: self.publisher, + publisher: self.publisher.clone(), state, }, receiver, @@ -939,7 +784,7 @@ where } #[zenoh_macros::unstable] -impl<'a, Handler> IntoFuture for MatchingListenerBuilder<'a, Handler> +impl<'a, 'b, Handler> IntoFuture for MatchingListenerBuilder<'a, 'b, Handler> where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, @@ -963,8 +808,8 @@ pub(crate) struct MatchingListenerState { } #[zenoh_macros::unstable] -impl std::fmt::Debug for MatchingListenerState { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl fmt::Debug for MatchingListenerState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("MatchingListener") .field("id", &self.id) .field("key_expr", &self.key_expr) @@ -974,7 +819,7 @@ impl std::fmt::Debug for MatchingListenerState { #[zenoh_macros::unstable] pub(crate) struct MatchingListenerInner<'a> { - pub(crate) publisher: PublisherRef<'a>, + pub(crate) publisher: Publisher<'a>, pub(crate) state: Arc, } @@ -1107,7 +952,7 @@ mod tests { use zenoh_config::Config; use zenoh_core::Wait; - use crate::api::{sample::SampleKind, session::SessionDeclarations}; + use crate::api::sample::SampleKind; #[cfg(feature = "internal")] #[test] diff --git a/zenoh/src/api/query.rs b/zenoh/src/api/query.rs index 2a1016db5f..bea028ff97 100644 --- a/zenoh/src/api/query.rs +++ b/zenoh/src/api/query.rs @@ -489,6 +489,7 @@ where parameters, } = self.selector?; self.session + .0 .query( &key_expr, ¶meters, diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 56b26fa36e..37a5b6bc21 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -16,7 +16,7 @@ use std::{ future::{IntoFuture, Ready}, mem::size_of, ops::{Deref, DerefMut}, - sync::Arc, + sync::{Arc, Weak}, }; use tracing::error; @@ -50,11 +50,12 @@ use crate::{ publisher::Priority, sample::{Locality, QoSBuilder, Sample, SampleKind}, selector::Selector, - session::{MaybeWeakSessionRef, SessionRef, UndeclarableSealed}, + session::{SessionInner, UndeclarableSealed}, value::Value, Id, }, net::primitives::Primitives, + Session, }; pub(crate) struct QueryInner { @@ -539,10 +540,10 @@ impl fmt::Debug for QueryableState { } #[derive(Debug)] -pub(crate) struct QueryableInner<'a> { +pub(crate) struct QueryableInner { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: MaybeWeakSessionRef<'a>, + pub(crate) session: Weak, pub(crate) state: Arc, // Queryable is undeclared on drop unless its handler is a ZST, i.e. it is callback-only pub(crate) undeclare_on_drop: bool, @@ -562,19 +563,19 @@ pub(crate) struct QueryableInner<'a> { /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct QueryableUndeclaration<'a, Handler>(Queryable<'a, Handler>); +pub struct QueryableUndeclaration(Queryable); -impl Resolvable for QueryableUndeclaration<'_, Handler> { +impl Resolvable for QueryableUndeclaration { type To = ZResult<()>; } -impl Wait for QueryableUndeclaration<'_, Handler> { +impl Wait for QueryableUndeclaration { fn wait(mut self) -> ::To { self.0.undeclare_impl() } } -impl IntoFuture for QueryableUndeclaration<'_, Handler> { +impl IntoFuture for QueryableUndeclaration { type Output = ::To; type IntoFuture = Ready<::To>; @@ -598,7 +599,7 @@ impl IntoFuture for QueryableUndeclaration<'_, Handler> { #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] #[derive(Debug)] pub struct QueryableBuilder<'a, 'b, Handler> { - pub(crate) session: SessionRef<'a>, + pub(crate) session: &'a Session, pub(crate) key_expr: ZResult>, pub(crate) complete: bool, pub(crate) origin: Locality, @@ -792,12 +793,12 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// ``` #[non_exhaustive] #[derive(Debug)] -pub struct Queryable<'a, Handler> { - pub(crate) inner: QueryableInner<'a>, +pub struct Queryable { + pub(crate) inner: QueryableInner, pub(crate) handler: Handler, } -impl<'a, Handler> Queryable<'a, Handler> { +impl Queryable { /// Returns the [`EntityGlobalId`] of this Queryable. /// /// # Examples @@ -852,9 +853,9 @@ impl<'a, Handler> Queryable<'a, Handler> { /// # } /// ``` #[inline] - pub fn undeclare(self) -> impl Resolve> + 'a + pub fn undeclare(self) -> impl Resolve> where - Handler: Send + 'a, + Handler: Send, { UndeclarableSealed::undeclare_inner(self, ()) } @@ -869,7 +870,7 @@ impl<'a, Handler> Queryable<'a, Handler> { } } -impl Drop for Queryable<'_, Handler> { +impl Drop for Queryable { fn drop(&mut self) { if self.inner.undeclare_on_drop { if let Err(error) = self.undeclare_impl() { @@ -879,15 +880,15 @@ impl Drop for Queryable<'_, Handler> { } } -impl<'a, Handler: Send + 'a> UndeclarableSealed<()> for Queryable<'a, Handler> { - type Undeclaration = QueryableUndeclaration<'a, Handler>; +impl UndeclarableSealed<()> for Queryable { + type Undeclaration = QueryableUndeclaration; fn undeclare_inner(self, _: ()) -> Self::Undeclaration { QueryableUndeclaration(self) } } -impl Deref for Queryable<'_, Handler> { +impl Deref for Queryable { type Target = Handler; fn deref(&self) -> &Self::Target { @@ -895,21 +896,21 @@ impl Deref for Queryable<'_, Handler> { } } -impl DerefMut for Queryable<'_, Handler> { +impl DerefMut for Queryable { fn deref_mut(&mut self) -> &mut Self::Target { self.handler_mut() } } -impl<'a, Handler> Resolvable for QueryableBuilder<'a, '_, Handler> +impl Resolvable for QueryableBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Query> + Send, Handler::Handler: Send, { - type To = ZResult>; + type To = ZResult>; } -impl<'a, Handler> Wait for QueryableBuilder<'a, '_, Handler> +impl Wait for QueryableBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Query> + Send, Handler::Handler: Send, @@ -917,31 +918,29 @@ where fn wait(self) -> ::To { let session = self.session; let (callback, receiver) = self.handler.into_handler(); - let undeclare_on_drop = size_of::() > 0; session + .0 .declare_queryable_inner( - &self.key_expr?.to_wire(&session), + &self.key_expr?.to_wire(&session.0), self.complete, self.origin, callback, ) - .map(|qable_state| { - Queryable { - inner: QueryableInner { - #[cfg(feature = "unstable")] - session_id: session.zid(), - session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), - state: qable_state, - // `size_of::() == 0` means callback-only queryable - undeclare_on_drop, - }, - handler: receiver, - } + .map(|qable_state| Queryable { + inner: QueryableInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: Arc::downgrade(&self.session.0), + state: qable_state, + // `size_of::() == 0` means callback-only queryable + undeclare_on_drop: size_of::() > 0, + }, + handler: receiver, }) } } -impl<'a, Handler> IntoFuture for QueryableBuilder<'a, '_, Handler> +impl IntoFuture for QueryableBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Query> + Send, Handler::Handler: Send, diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 231ab85d6d..945a469bff 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -16,7 +16,6 @@ use std::{ convert::TryInto, fmt, future::{IntoFuture, Ready}, - ops::Deref, sync::{ atomic::{AtomicU16, Ordering}, Arc, RwLock, Weak, @@ -174,6 +173,14 @@ impl SessionState { } impl SessionState { + #[inline] + pub(crate) fn primitives(&self) -> ZResult> { + self.primitives + .as_ref() + .cloned() + .ok_or_else(|| zerror!("session closed").into()) + } + #[inline] fn get_local_res(&self, id: &ExprId) -> Option<&Resource> { self.local_resources.get(id) @@ -359,124 +366,6 @@ impl Resource { } } -#[derive(Clone)] -pub enum SessionRef<'a> { - Borrow(&'a Session), - Shared(Arc), -} - -impl<'s, 'a> SessionDeclarations<'s, 'a> for SessionRef<'a> { - fn declare_subscriber<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> SubscriberBuilder<'a, 'b, DefaultHandler> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - SubscriberBuilder { - session: self.clone(), - key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), - #[cfg(feature = "unstable")] - reliability: Reliability::DEFAULT, - origin: Locality::default(), - handler: DefaultHandler::default(), - } - } - fn declare_queryable<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> QueryableBuilder<'a, 'b, DefaultHandler> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - QueryableBuilder { - session: self.clone(), - key_expr: key_expr.try_into().map_err(Into::into), - complete: false, - origin: Locality::default(), - handler: DefaultHandler::default(), - } - } - fn declare_publisher<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> PublisherBuilder<'a, 'b> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - PublisherBuilder { - session: self.clone(), - key_expr: key_expr.try_into().map_err(Into::into), - encoding: Encoding::default(), - congestion_control: CongestionControl::DEFAULT, - priority: Priority::DEFAULT, - is_express: false, - #[cfg(feature = "unstable")] - reliability: Reliability::DEFAULT, - destination: Locality::default(), - } - } - #[zenoh_macros::unstable] - fn liveliness(&'s self) -> Liveliness<'a> { - Liveliness { - session: self.clone(), - } - } - fn info(&'s self) -> SessionInfo<'a> { - SessionInfo { - session: self.clone(), - } - } -} - -impl Deref for SessionRef<'_> { - type Target = Session; - - fn deref(&self) -> &Self::Target { - match self { - SessionRef::Borrow(b) => b, - SessionRef::Shared(s) => s, - } - } -} - -impl fmt::Debug for SessionRef<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SessionRef::Borrow(b) => Session::fmt(b, f), - SessionRef::Shared(s) => Session::fmt(s, f), - } - } -} - -#[derive(Debug, Clone)] -pub(crate) enum MaybeWeakSessionRef<'a> { - Borrow(&'a Session), - Arc(Arc), - Weak(Weak), -} - -impl<'a> MaybeWeakSessionRef<'a> { - pub(crate) fn new(session: SessionRef<'a>, downgrade: bool) -> Self { - match session { - SessionRef::Borrow(s) => Self::Borrow(s), - SessionRef::Shared(s) if downgrade => Self::Weak(Arc::downgrade(&s)), - SessionRef::Shared(s) => Self::Arc(s), - } - } - - pub(crate) fn upgrade(&self) -> Option> { - match self { - Self::Borrow(s) => Some(SessionRef::Borrow(s)), - Self::Arc(s) => Some(SessionRef::Shared(s.clone())), - Self::Weak(s) => s.upgrade().map(SessionRef::Shared), - } - } -} - /// A trait implemented by types that can be undeclared. pub trait UndeclarableSealed { type Undeclaration: Resolve> + Send; @@ -502,113 +391,60 @@ pub trait Undeclarable: UndeclarableSealed {} impl Undeclarable for T where T: UndeclarableSealed {} -/// A zenoh session. -/// -pub struct Session { +pub(crate) struct SessionInner { pub(crate) runtime: Runtime, - pub(crate) state: Arc>, + pub(crate) state: RwLock, pub(crate) id: u16, - close_on_drop: bool, owns_runtime: bool, task_controller: TaskController, } +impl fmt::Debug for SessionInner { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Session") + .field("id", &self.runtime.zid()) + .finish() + } +} + +/// A zenoh session. +/// +#[derive(Clone)] +pub struct Session(pub(crate) Arc); + static SESSION_ID_COUNTER: AtomicU16 = AtomicU16::new(0); impl Session { pub(crate) fn init( runtime: Runtime, aggregated_subscribers: Vec, aggregated_publishers: Vec, + owns_runtime: bool, ) -> impl Resolve { ResolveClosure::new(move || { let router = runtime.router(); - let state = Arc::new(RwLock::new(SessionState::new( + let state = RwLock::new(SessionState::new( aggregated_subscribers, aggregated_publishers, - ))); - let session = Session { + )); + let session = Arc::new(SessionInner { runtime: runtime.clone(), - state: state.clone(), + state, id: SESSION_ID_COUNTER.fetch_add(1, Ordering::SeqCst), - close_on_drop: true, - owns_runtime: false, + owns_runtime, task_controller: TaskController::default(), - }; + }); - runtime.new_handler(Arc::new(admin::Handler::new(session.clone()))); + runtime.new_handler(Arc::new(admin::Handler::new(Arc::downgrade(&session)))); - let primitives = Some(router.new_primitives(Arc::new(session.clone()))); - zwrite!(state).primitives = primitives; + let primitives = Some(router.new_primitives(Arc::new(Arc::downgrade(&session)))); + zwrite!(session.state).primitives = primitives; admin::init(&session); - session + Session(session) }) } - /// Consumes the given `Session`, returning a thread-safe reference-counting - /// pointer to it (`Arc`). This is equivalent to `Arc::new(session)`. - /// - /// This is useful to share ownership of the `Session` between several threads - /// and tasks. It also allows to create [`Subscriber`](crate::pubsub::Subscriber) and - /// [`Queryable`](crate::query::Queryable) with static lifetime that can be moved to several - /// threads and tasks - /// - /// Note: the given zenoh `Session` will be closed when the last reference to - /// it is dropped. - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let subscriber = session.declare_subscriber("key/expression") - /// .await - /// .unwrap(); - /// tokio::task::spawn(async move { - /// while let Ok(sample) = subscriber.recv_async().await { - /// println!("Received: {:?}", sample); - /// } - /// }).await; - /// # } - /// ``` - pub fn into_arc(self) -> Arc { - Arc::new(self) - } - - /// Consumes and leaks the given `Session`, returning a `'static` mutable - /// reference to it. The given `Session` will live for the remainder of - /// the program's life. Dropping the returned reference will cause a memory - /// leak. - /// - /// This is useful to move entities (like [`Subscriber`](crate::pubsub::Subscriber)) which - /// lifetimes are bound to the session lifetime in several threads or tasks. - /// - /// Note: the given zenoh `Session` cannot be closed any more. At process - /// termination the zenoh session will terminate abruptly. If possible prefer - /// using [`Session::into_arc()`](Session::into_arc). - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::Session::leak(zenoh::open(zenoh::config::peer()).await.unwrap()); - /// let subscriber = session.declare_subscriber("key/expression").await.unwrap(); - /// tokio::task::spawn(async move { - /// while let Ok(sample) = subscriber.recv_async().await { - /// println!("Received: {:?}", sample); - /// } - /// }).await; - /// # } - /// ``` - pub fn leak(s: Self) -> &'static mut Self { - Box::leak(Box::new(s)) - } - /// Returns the identifier of the current session. `zid()` is a convenient shortcut. /// See [`Session::info()`](`Session::info()`) and [`SessionInfo::zid()`](`SessionInfo::zid()`) for more details. pub fn zid(&self) -> ZenohId { @@ -616,7 +452,7 @@ impl Session { } pub fn hlc(&self) -> Option<&HLC> { - self.runtime.hlc() + self.0.runtime.hlc() } /// Close the zenoh [`Session`](Session). @@ -634,23 +470,8 @@ impl Session { /// session.close().await.unwrap(); /// # } /// ``` - pub fn close(mut self) -> impl Resolve> { - ResolveFuture::new(async move { - trace!("close()"); - // set the flag first to avoid double panic if this function panic - self.close_on_drop = false; - self.task_controller.terminate_all(Duration::from_secs(10)); - if self.owns_runtime { - self.runtime.close().await?; - } - let mut state = zwrite!(self.state); - // clean up to break cyclic references from self.state to itself - let primitives = state.primitives.take(); - state.queryables.clear(); - drop(state); - primitives.as_ref().unwrap().send_close(); - Ok(()) - }) + pub fn close(&self) -> impl Resolve> + '_ { + self.0.close() } pub fn undeclare<'a, T>(&'a self, decl: T) -> impl Resolve> + 'a @@ -690,7 +511,7 @@ impl Session { /// # } /// ``` pub fn config(&self) -> &Notifier { - self.runtime.config() + self.0.runtime.config() } /// Get a new Timestamp from a Zenoh session [`Session`](Session). @@ -715,49 +536,175 @@ impl Session { // Called in the case that the runtime is not initialized with an hlc // UNIX_EPOCH is Returns a Timespec::zero(), Unwrap Should be permissable here let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().into(); - Timestamp::new(now, self.runtime.zid().into()) + Timestamp::new(now, self.0.runtime.zid().into()) } } } } -impl<'a> SessionDeclarations<'a, 'a> for Session { - fn info(&self) -> SessionInfo { - SessionRef::Borrow(self).info() +impl Session { + /// Get information about the zenoh [`Session`](Session). + /// + /// # Examples + /// ``` + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let info = session.info(); + /// # } + /// ``` + pub fn info(&self) -> SessionInfo { + SessionInfo { + runtime: self.0.runtime.clone(), + } } - fn declare_subscriber<'b, TryIntoKeyExpr>( - &'a self, + + /// Create a [`Subscriber`](crate::pubsub::Subscriber) for the given key expression. + /// + /// # Arguments + /// + /// * `key_expr` - The resourkey expression to subscribe to + /// + /// # Examples + /// ```no_run + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let subscriber = session.declare_subscriber("key/expression") + /// .await + /// .unwrap(); + /// tokio::task::spawn(async move { + /// while let Ok(sample) = subscriber.recv_async().await { + /// println!("Received: {:?}", sample); + /// } + /// }).await; + /// # } + /// ``` + pub fn declare_subscriber<'b, TryIntoKeyExpr>( + &self, key_expr: TryIntoKeyExpr, - ) -> SubscriberBuilder<'a, 'b, DefaultHandler> + ) -> SubscriberBuilder<'_, 'b, DefaultHandler> where TryIntoKeyExpr: TryInto>, >>::Error: Into, { - SessionRef::Borrow(self).declare_subscriber(key_expr) + SubscriberBuilder { + session: self, + key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), + #[cfg(feature = "unstable")] + reliability: Reliability::DEFAULT, + origin: Locality::default(), + handler: DefaultHandler::default(), + } } - fn declare_queryable<'b, TryIntoKeyExpr>( - &'a self, + + /// Create a [`Queryable`](crate::query::Queryable) for the given key expression. + /// + /// # Arguments + /// + /// * `key_expr` - The key expression matching the queries the + /// [`Queryable`](crate::query::Queryable) will reply to + /// + /// # Examples + /// ```no_run + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let queryable = session.declare_queryable("key/expression") + /// .await + /// .unwrap(); + /// tokio::task::spawn(async move { + /// while let Ok(query) = queryable.recv_async().await { + /// query.reply( + /// "key/expression", + /// "value", + /// ).await.unwrap(); + /// } + /// }).await; + /// # } + /// ``` + pub fn declare_queryable<'b, TryIntoKeyExpr>( + &self, key_expr: TryIntoKeyExpr, - ) -> QueryableBuilder<'a, 'b, DefaultHandler> + ) -> QueryableBuilder<'_, 'b, DefaultHandler> where TryIntoKeyExpr: TryInto>, >>::Error: Into, { - SessionRef::Borrow(self).declare_queryable(key_expr) + QueryableBuilder { + session: self, + key_expr: key_expr.try_into().map_err(Into::into), + complete: false, + origin: Locality::default(), + handler: DefaultHandler::default(), + } } - fn declare_publisher<'b, TryIntoKeyExpr>( - &'a self, + + /// Create a [`Publisher`](crate::pubsub::Publisher) for the given key expression. + /// + /// # Arguments + /// + /// * `key_expr` - The key expression matching resources to write + /// + /// # Examples + /// ``` + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let publisher = session.declare_publisher("key/expression") + /// .await + /// .unwrap(); + /// publisher.put("value").await.unwrap(); + /// # } + /// ``` + pub fn declare_publisher<'b, TryIntoKeyExpr>( + &self, key_expr: TryIntoKeyExpr, - ) -> PublisherBuilder<'a, 'b> + ) -> PublisherBuilder<'_, 'b> where TryIntoKeyExpr: TryInto>, >>::Error: Into, { - SessionRef::Borrow(self).declare_publisher(key_expr) + PublisherBuilder { + session: self, + key_expr: key_expr.try_into().map_err(Into::into), + encoding: Encoding::default(), + congestion_control: CongestionControl::DEFAULT, + priority: Priority::DEFAULT, + is_express: false, + #[cfg(feature = "unstable")] + reliability: Reliability::DEFAULT, + destination: Locality::default(), + } } + + /// Obtain a [`Liveliness`] struct tied to this Zenoh [`Session`]. + /// + /// # Examples + /// ``` + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let liveliness = session + /// .liveliness() + /// .declare_token("key/expression") + /// .await + /// .unwrap(); + /// # } + /// ``` #[zenoh_macros::unstable] - fn liveliness(&'a self) -> Liveliness { - SessionRef::Borrow(self).liveliness() + pub fn liveliness(&self) -> Liveliness<'_> { + Liveliness { session: self } } } @@ -786,11 +733,11 @@ impl Session { >>::Error: Into, { let key_expr: ZResult = key_expr.try_into().map_err(Into::into); - let sid = self.id; + let sid = self.0.id; ResolveClosure::new(move || { let key_expr: KeyExpr = key_expr?; let prefix_len = key_expr.len() as u32; - let expr_id = self.declare_prefix(key_expr.as_str()).wait(); + let expr_id = self.0.declare_prefix(key_expr.as_str()).wait()?; let key_expr = match key_expr.0 { KeyExprInner::Borrowed(key_expr) | KeyExprInner::BorrowedWire { key_expr, .. } => { KeyExpr(KeyExprInner::BorrowedWire { @@ -926,7 +873,7 @@ impl Session { { let selector = selector.try_into().map_err(Into::into); let timeout = { - let conf = self.runtime.config().lock(); + let conf = self.0.runtime.config().lock(); Duration::from_millis(unwrap_or_default!(conf.queries_default_timeout())) }; let qos: QoS = request::ext::QoSType::REQUEST.into(); @@ -948,17 +895,6 @@ impl Session { } impl Session { - pub(crate) fn clone(&self) -> Self { - Self { - runtime: self.runtime.clone(), - state: self.state.clone(), - id: self.id, - close_on_drop: false, - owns_runtime: self.owns_runtime, - task_controller: self.task_controller.clone(), - } - } - #[allow(clippy::new_ret_no_self)] pub(super) fn new( config: Config, @@ -976,28 +912,47 @@ impl Session { } let mut runtime = runtime.build().await?; - let mut session = Self::init( + let session = Self::init( runtime.clone(), aggregated_subscribers, aggregated_publishers, + true, ) .await; - session.owns_runtime = true; runtime.start().await?; Ok(session) }) } - - pub(crate) fn declare_prefix<'a>(&'a self, prefix: &'a str) -> impl Resolve + 'a { +} +impl SessionInner { + fn close(&self) -> impl Resolve> + '_ { + ResolveFuture::new(async move { + let Some(primitives) = zwrite!(self.state).primitives.take() else { + return Ok(()); + }; + trace!("close()"); + self.task_controller.terminate_all(Duration::from_secs(10)); + if self.owns_runtime { + self.runtime.close().await?; + } + primitives.send_close(); + Ok(()) + }) + } + pub(crate) fn declare_prefix<'a>( + &'a self, + prefix: &'a str, + ) -> impl Resolve> + 'a { ResolveClosure::new(move || { trace!("declare_prefix({:?})", prefix); let mut state = zwrite!(self.state); + let primitives = state.primitives()?; match state .local_resources .iter() .find(|(_expr_id, res)| res.name() == prefix) { - Some((expr_id, _res)) => *expr_id, + Some((expr_id, _res)) => Ok(*expr_id), None => { let expr_id = state.expr_id_counter.fetch_add(1, Ordering::SeqCst); let mut res = Resource::new(Box::from(prefix)); @@ -1014,7 +969,6 @@ impl Session { } } state.local_resources.insert(expr_id, res); - let primitives = state.primitives.as_ref().unwrap().clone(); drop(state); primitives.send_declare(Declare { interest_id: None, @@ -1030,7 +984,7 @@ impl Session { }, }), }); - expr_id + Ok(expr_id) } } }) @@ -1087,7 +1041,7 @@ impl Session { state.publishers.insert(id, pub_state); if let Some(res) = declared_pub { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_interest(Interest { id, @@ -1112,7 +1066,7 @@ impl Session { 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(); + let primitives = state.primitives()?; drop(state); primitives.send_interest(Interest { id: pub_state.remote_id, @@ -1132,7 +1086,7 @@ impl Session { } pub(crate) fn declare_subscriber_inner( - &self, + self: &Arc, key_expr: &KeyExpr, origin: Locality, callback: Callback<'static, Sample>, @@ -1216,7 +1170,7 @@ impl Session { } if let Some(key_expr) = declared_sub { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); // If key_expr is a pure Expr, remap it to optimal Rid or RidWithSuffix // let key_expr = if !key_expr.is_optimized(self) { @@ -1263,7 +1217,11 @@ impl Session { Ok(sub_state) } - pub(crate) fn undeclare_subscriber_inner(&self, sid: Id, kind: SubscriberKind) -> ZResult<()> { + pub(crate) fn undeclare_subscriber_inner( + self: &Arc, + sid: Id, + kind: SubscriberKind, + ) -> ZResult<()> { let mut state = zwrite!(self.state); if let Some(sub_state) = state.subscribers_mut(kind).remove(&sid) { trace!("undeclare_subscriber({:?})", sub_state); @@ -1290,7 +1248,7 @@ impl Session { if !state.subscribers(kind).values().any(|s| { s.origin != Locality::SessionLocal && s.remote_id == sub_state.remote_id }) { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_declare(Declare { interest_id: None, @@ -1313,7 +1271,7 @@ impl Session { } else { #[cfg(feature = "unstable")] if kind == SubscriberKind::LivelinessSubscriber { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_interest(Interest { @@ -1355,7 +1313,7 @@ impl Session { state.queryables.insert(id, qable_state.clone()); if origin != Locality::SessionLocal { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); let qabl_info = QueryableInfoType { complete, @@ -1381,7 +1339,7 @@ impl Session { if let Some(qable_state) = state.queryables.remove(&qid) { trace!("undeclare_queryable({:?})", qable_state); if qable_state.origin != Locality::SessionLocal { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_declare(Declare { interest_id: None, @@ -1416,7 +1374,7 @@ impl Session { }); state.tokens.insert(tok_state.id, tok_state.clone()); - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_declare(Declare { interest_id: None, @@ -1478,7 +1436,7 @@ impl Session { } } - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_interest(Interest { @@ -1503,7 +1461,7 @@ impl Session { let key_expr = &tok_state.key_expr; let twin_tok = state.tokens.values().any(|s| s.key_expr == *key_expr); if !twin_tok { - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); primitives.send_declare(Declare { interest_id: None, @@ -1594,7 +1552,7 @@ impl Session { } #[zenoh_macros::unstable] - pub(crate) fn update_status_up(&self, state: &SessionState, key_expr: &KeyExpr) { + pub(crate) fn update_status_up(self: &Arc, state: &SessionState, key_expr: &KeyExpr) { for msub in state.matching_listeners.values() { if key_expr.intersects(&msub.key_expr) { // Cannot hold session lock when calling tables (matching_status()) @@ -1632,7 +1590,7 @@ impl Session { } #[zenoh_macros::unstable] - pub(crate) fn update_status_down(&self, state: &SessionState, key_expr: &KeyExpr) { + pub(crate) fn update_status_down(self: &Arc, state: &SessionState, key_expr: &KeyExpr) { for msub in state.matching_listeners.values() { if key_expr.intersects(&msub.key_expr) { // Cannot hold session lock when calling tables (matching_status()) @@ -1760,7 +1718,7 @@ impl Session { #[allow(clippy::too_many_arguments)] pub(crate) fn query( - &self, + self: &Arc, key_expr: &KeyExpr<'_>, parameters: &Parameters<'_>, target: QueryTarget, @@ -1795,13 +1753,13 @@ impl Session { let token = self.task_controller.get_cancellation_token(); self.task_controller .spawn_with_rt(zenoh_runtime::ZRuntime::Net, { - let state = self.state.clone(); + let session = self.clone(); #[cfg(feature = "unstable")] let zid = self.runtime.zid(); async move { tokio::select! { _ = tokio::time::sleep(timeout) => { - let mut state = zwrite!(state); + let mut state = zwrite!(session.state); if let Some(query) = state.queries.remove(&qid) { std::mem::drop(state); tracing::debug!("Timeout on query {}! Send error and close.", qid); @@ -1836,7 +1794,7 @@ impl Session { }, ); - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); if destination != Locality::SessionLocal { @@ -1890,7 +1848,7 @@ impl Session { #[cfg(feature = "unstable")] pub(crate) fn liveliness_query( - &self, + self: &Arc, key_expr: &KeyExpr<'_>, timeout: Duration, callback: Callback<'static, Reply>, @@ -1901,12 +1859,12 @@ impl Session { let token = self.task_controller.get_cancellation_token(); self.task_controller .spawn_with_rt(zenoh_runtime::ZRuntime::Net, { - let state = self.state.clone(); + let session = self.clone(); let zid = self.runtime.zid(); async move { tokio::select! { _ = tokio::time::sleep(timeout) => { - let mut state = zwrite!(state); + let mut state = zwrite!(session.state); if let Some(query) = state.liveliness_queries.remove(&id) { std::mem::drop(state); tracing::debug!("Timeout on liveliness query {}! Send error and close.", id); @@ -1928,266 +1886,115 @@ impl Session { .liveliness_queries .insert(id, LivelinessQueryState { callback }); - let primitives = state.primitives.as_ref().unwrap().clone(); + let primitives = state.primitives()?; drop(state); - primitives.send_interest(Interest { - id, - mode: InterestMode::Current, - options: InterestOptions::KEYEXPRS + InterestOptions::TOKENS, - wire_expr: Some(wexpr.clone()), - ext_qos: request::ext::QoSType::DEFAULT, - ext_tstamp: None, - ext_nodeid: request::ext::NodeIdType::DEFAULT, - }); - - Ok(()) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn handle_query( - &self, - local: bool, - key_expr: &WireExpr, - parameters: &str, - qid: RequestId, - _target: TargetType, - _consolidation: Consolidation, - body: Option, - attachment: Option, - ) { - let (primitives, key_expr, queryables) = { - let state = zread!(self.state); - match state.wireexpr_to_keyexpr(key_expr, local) { - Ok(key_expr) => { - let queryables = state - .queryables - .iter() - .filter( - |(_, queryable)| - (queryable.origin == Locality::Any - || (local == (queryable.origin == Locality::SessionLocal))) - && - match state.local_wireexpr_to_expr(&queryable.key_expr) { - Ok(qablname) => { - qablname.intersects(&key_expr) - } - Err(err) => { - error!( - "{}. Internal error (queryable key_expr to key_expr failed).", - err - ); - false - } - } - ) - .map(|(id, qable)| (*id, qable.callback.clone())) - .collect::)>>(); - ( - state.primitives.as_ref().unwrap().clone(), - key_expr.into_owned(), - queryables, - ) - } - Err(err) => { - error!("Received Query for unknown key_expr: {}", err); - return; - } - } - }; - - let zid = self.runtime.zid(); - - let query_inner = Arc::new(QueryInner { - key_expr, - parameters: parameters.to_owned().into(), - qid, - zid: zid.into(), - primitives: if local { - Arc::new(self.clone()) - } else { - primitives - }, - }); - for (eid, callback) in queryables { - callback(Query { - inner: query_inner.clone(), - eid, - value: body.as_ref().map(|b| Value { - payload: b.payload.clone().into(), - encoding: b.encoding.clone().into(), - }), - attachment: attachment.clone(), - }); - } - } -} - -impl<'s> SessionDeclarations<'s, 'static> for Arc { - /// Create a [`Subscriber`](crate::pubsub::Subscriber) for the given key expression. - /// - /// # Arguments - /// - /// * `key_expr` - The resourkey expression to subscribe to - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let subscriber = session.declare_subscriber("key/expression") - /// .await - /// .unwrap(); - /// tokio::task::spawn(async move { - /// while let Ok(sample) = subscriber.recv_async().await { - /// println!("Received: {:?}", sample); - /// } - /// }).await; - /// # } - /// ``` - fn declare_subscriber<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> SubscriberBuilder<'static, 'b, DefaultHandler> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - SubscriberBuilder { - session: SessionRef::Shared(self.clone()), - key_expr: key_expr.try_into().map_err(Into::into), - #[cfg(feature = "unstable")] - reliability: Reliability::DEFAULT, - origin: Locality::default(), - handler: DefaultHandler::default(), - } - } - - /// Create a [`Queryable`](crate::query::Queryable) for the given key expression. - /// - /// # Arguments - /// - /// * `key_expr` - The key expression matching the queries the - /// [`Queryable`](crate::query::Queryable) will reply to - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let queryable = session.declare_queryable("key/expression") - /// .await - /// .unwrap(); - /// tokio::task::spawn(async move { - /// while let Ok(query) = queryable.recv_async().await { - /// query.reply( - /// "key/expression", - /// "value", - /// ).await.unwrap(); - /// } - /// }).await; - /// # } - /// ``` - fn declare_queryable<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> QueryableBuilder<'static, 'b, DefaultHandler> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - QueryableBuilder { - session: SessionRef::Shared(self.clone()), - key_expr: key_expr.try_into().map_err(Into::into), - complete: false, - origin: Locality::default(), - handler: DefaultHandler::default(), - } - } + primitives.send_interest(Interest { + id, + mode: InterestMode::Current, + options: InterestOptions::KEYEXPRS + InterestOptions::TOKENS, + wire_expr: Some(wexpr.clone()), + ext_qos: request::ext::QoSType::DEFAULT, + ext_tstamp: None, + ext_nodeid: request::ext::NodeIdType::DEFAULT, + }); - /// Create a [`Publisher`](crate::pubsub::Publisher) for the given key expression. - /// - /// # Arguments - /// - /// * `key_expr` - The key expression matching resources to write - /// - /// # Examples - /// ``` - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let publisher = session.declare_publisher("key/expression") - /// .await - /// .unwrap(); - /// publisher.put("value").await.unwrap(); - /// # } - /// ``` - fn declare_publisher<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> PublisherBuilder<'static, 'b> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into, - { - PublisherBuilder { - session: SessionRef::Shared(self.clone()), - key_expr: key_expr.try_into().map_err(Into::into), - encoding: Encoding::default(), - congestion_control: CongestionControl::DEFAULT, - priority: Priority::DEFAULT, - is_express: false, - #[cfg(feature = "unstable")] - reliability: Reliability::DEFAULT, - destination: Locality::default(), - } + Ok(()) } - /// Obtain a [`Liveliness`] struct tied to this Zenoh [`Session`]. - /// - /// # Examples - /// ``` - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let liveliness = session - /// .liveliness() - /// .declare_token("key/expression") - /// .await - /// .unwrap(); - /// # } - /// ``` - #[zenoh_macros::unstable] - fn liveliness(&'s self) -> Liveliness<'static> { - Liveliness { - session: SessionRef::Shared(self.clone()), - } - } + #[allow(clippy::too_many_arguments)] + pub(crate) fn handle_query( + self: &Arc, + local: bool, + key_expr: &WireExpr, + parameters: &str, + qid: RequestId, + _target: TargetType, + _consolidation: Consolidation, + body: Option, + attachment: Option, + ) { + let (primitives, key_expr, queryables) = { + let state = zread!(self.state); + let Ok(primitives) = state.primitives() else { + return; + }; + match state.wireexpr_to_keyexpr(key_expr, local) { + Ok(key_expr) => { + let queryables = state + .queryables + .iter() + .filter( + |(_, queryable)| + (queryable.origin == Locality::Any + || (local == (queryable.origin == Locality::SessionLocal))) + && + match state.local_wireexpr_to_expr(&queryable.key_expr) { + Ok(qablname) => { + qablname.intersects(&key_expr) + } + Err(err) => { + error!( + "{}. Internal error (queryable key_expr to key_expr failed).", + err + ); + false + } + } + ) + .map(|(id, qable)| (*id, qable.callback.clone())) + .collect::)>>(); + (primitives, key_expr.into_owned(), queryables) + } + Err(err) => { + error!("Received Query for unknown key_expr: {}", err); + return; + } + } + }; - fn info(&'s self) -> SessionInfo<'static> { - SessionInfo { - session: SessionRef::Shared(self.clone()), + let zid = self.runtime.zid(); + + let query_inner = Arc::new(QueryInner { + key_expr, + parameters: parameters.to_owned().into(), + qid, + zid: zid.into(), + primitives: if local { + Arc::new(Arc::downgrade(self)) + } else { + primitives + }, + }); + for (eid, callback) in queryables { + callback(Query { + inner: query_inner.clone(), + eid, + value: body.as_ref().map(|b| Value { + payload: b.payload.clone().into(), + encoding: b.encoding.clone().into(), + }), + attachment: attachment.clone(), + }); } } } -impl Primitives for Session { +impl Primitives for Weak { fn send_interest(&self, msg: zenoh_protocol::network::Interest) { + if self.upgrade().is_none() { + return; + } trace!("recv Interest {} {:?}", msg.id, msg.wire_expr); } fn send_declare(&self, msg: zenoh_protocol::network::Declare) { + let Some(session) = self.upgrade() else { + return; + }; match msg.body { zenoh_protocol::network::DeclareBody::DeclareKeyExpr(m) => { trace!("recv DeclareKeyExpr {} {:?}", m.id, m.wire_expr); - let state = &mut zwrite!(self.state); + let state = &mut zwrite!(session.state); match state.remote_key_to_expr(&m.wire_expr) { Ok(key_expr) => { let mut res_node = ResourceNode::new(key_expr.clone().into()); @@ -2219,14 +2026,14 @@ impl Primitives for Session { trace!("recv DeclareSubscriber {} {:?}", m.id, m.wire_expr); #[cfg(feature = "unstable")] { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); match state .wireexpr_to_keyexpr(&m.wire_expr, false) .map(|e| e.into_owned()) { Ok(expr) => { state.remote_subscribers.insert(m.id, expr.clone()); - self.update_status_up(&state, &expr); + session.update_status_up(&state, &expr); } Err(err) => { tracing::error!( @@ -2241,9 +2048,9 @@ impl Primitives for Session { trace!("recv UndeclareSubscriber {:?}", m.id); #[cfg(feature = "unstable")] { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); if let Some(expr) = state.remote_subscribers.remove(&m.id) { - self.update_status_down(&state, &expr); + session.update_status_down(&state, &expr); } else { tracing::error!("Received Undeclare Subscriber for unknown id: {}", m.id); } @@ -2259,7 +2066,7 @@ impl Primitives for Session { trace!("recv DeclareToken {:?}", m.id); #[cfg(feature = "unstable")] { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); match state .wireexpr_to_keyexpr(&m.wire_expr, false) .map(|e| e.into_owned()) @@ -2293,7 +2100,7 @@ impl Primitives for Session { drop(state); - self.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( false, &m.wire_expr, None, @@ -2316,7 +2123,7 @@ impl Primitives for Session { trace!("recv UndeclareToken {:?}", m.id); #[cfg(feature = "unstable")] { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); if let Some(key_expr) = state.remote_tokens.remove(&m.id) { drop(state); @@ -2325,9 +2132,9 @@ impl Primitives for Session { ..Default::default() }; - self.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( false, - &key_expr.to_wire(self), + &key_expr.to_wire(&session), Some(data_info), ZBuf::default(), SubscriberKind::LivelinessSubscriber, @@ -2349,9 +2156,9 @@ impl Primitives for Session { ..Default::default() }; - self.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( false, - &key_expr.to_wire(self), + &key_expr.to_wire(&session), Some(data_info), ZBuf::default(), SubscriberKind::LivelinessSubscriber, @@ -2376,7 +2183,7 @@ impl Primitives for Session { #[cfg(feature = "unstable")] if let Some(interest_id) = msg.interest_id { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); let _ = state.liveliness_queries.remove(&interest_id); } } @@ -2384,6 +2191,9 @@ impl Primitives for Session { } fn send_push(&self, msg: Push, _reliability: Reliability) { + let Some(session) = self.upgrade() else { + return; + }; trace!("recv Push {:?}", msg); match msg.payload { PushBody::Put(m) => { @@ -2395,7 +2205,7 @@ impl Primitives for Session { source_id: m.ext_sinfo.as_ref().map(|i| i.id.into()), source_sn: m.ext_sinfo.as_ref().map(|i| i.sn as u64), }; - self.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( false, &msg.wire_expr, Some(info), @@ -2415,7 +2225,7 @@ impl Primitives for Session { source_id: m.ext_sinfo.as_ref().map(|i| i.id.into()), source_sn: m.ext_sinfo.as_ref().map(|i| i.sn as u64), }; - self.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( false, &msg.wire_expr, Some(info), @@ -2430,9 +2240,12 @@ impl Primitives for Session { } fn send_request(&self, msg: Request) { + let Some(session) = self.upgrade() else { + return; + }; trace!("recv Request {:?}", msg); match msg.payload { - RequestBody::Query(m) => self.handle_query( + RequestBody::Query(m) => session.handle_query( false, &msg.wire_expr, &m.parameters, @@ -2446,10 +2259,13 @@ impl Primitives for Session { } fn send_response(&self, msg: Response) { + let Some(session) = self.upgrade() else { + return; + }; trace!("recv Response {:?}", msg); match msg.payload { ResponseBody::Err(e) => { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); match state.queries.get_mut(&msg.rid) { Some(query) => { let callback = query.callback.clone(); @@ -2471,7 +2287,7 @@ impl Primitives for Session { } } ResponseBody::Reply(m) => { - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); let key_expr = match state.remote_key_to_expr(&msg.wire_expr) { Ok(key) => key.into_owned(), Err(e) => { @@ -2645,8 +2461,11 @@ impl Primitives for Session { } fn send_response_final(&self, msg: ResponseFinal) { + let Some(session) = self.upgrade() else { + return; + }; trace!("recv ResponseFinal {:?}", msg); - let mut state = zwrite!(self.state); + let mut state = zwrite!(session.state); match state.queries.get_mut(&msg.rid) { Some(query) => { query.nb_final -= 1; @@ -2668,178 +2487,28 @@ impl Primitives for Session { } fn send_close(&self) { + if self.upgrade().is_none() { + return; + } trace!("recv Close"); } } -impl Drop for Session { +impl Drop for SessionInner { fn drop(&mut self) { - if self.close_on_drop { - let _ = self.clone().close().wait(); + if let Err(error) = self.close().wait() { + tracing::error!(error); } } } impl fmt::Debug for Session { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Session").field("id", &self.zid()).finish() + self.0.fmt(f) } } -/// Functions to create zenoh entities -/// -/// This trait contains functions to create zenoh entities like -/// [`Subscriber`](crate::pubsub::Subscriber), and -/// [`Queryable`](crate::query::Queryable) -/// -/// This trait is implemented by [`Session`](crate::session::Session) itself and -/// by wrappers [`SessionRef`](crate::session::SessionRef) and [`Arc`](std::sync::Arc) -/// -/// # Examples -/// ```no_run -/// # #[tokio::main] -/// # async fn main() { -/// use zenoh::prelude::*; -/// -/// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); -/// let subscriber = session.declare_subscriber("key/expression") -/// .await -/// .unwrap(); -/// tokio::task::spawn(async move { -/// while let Ok(sample) = subscriber.recv_async().await { -/// println!("Received: {:?}", sample); -/// } -/// }).await; -/// # } -/// ``` -pub trait SessionDeclarations<'s, 'a> { - /// Create a [`Subscriber`](crate::pubsub::Subscriber) for the given key expression. - /// - /// # Arguments - /// - /// * `key_expr` - The resourkey expression to subscribe to - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let subscriber = session.declare_subscriber("key/expression") - /// .await - /// .unwrap(); - /// tokio::task::spawn(async move { - /// while let Ok(sample) = subscriber.recv_async().await { - /// println!("Received: {:?}", sample); - /// } - /// }).await; - /// # } - /// ``` - fn declare_subscriber<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> SubscriberBuilder<'a, 'b, DefaultHandler> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into; - - /// Create a [`Queryable`](crate::query::Queryable) for the given key expression. - /// - /// # Arguments - /// - /// * `key_expr` - The key expression matching the queries the - /// [`Queryable`](crate::query::Queryable) will reply to - /// - /// # Examples - /// ```no_run - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let queryable = session.declare_queryable("key/expression") - /// .await - /// .unwrap(); - /// tokio::task::spawn(async move { - /// while let Ok(query) = queryable.recv_async().await { - /// query.reply( - /// "key/expression", - /// "value", - /// ).await.unwrap(); - /// } - /// }).await; - /// # } - /// ``` - fn declare_queryable<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> QueryableBuilder<'a, 'b, DefaultHandler> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into; - - /// Create a [`Publisher`](crate::pubsub::Publisher) for the given key expression. - /// - /// # Arguments - /// - /// * `key_expr` - The key expression matching resources to write - /// - /// # Examples - /// ``` - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let publisher = session.declare_publisher("key/expression") - /// .await - /// .unwrap(); - /// publisher.put("value").await.unwrap(); - /// # } - /// ``` - fn declare_publisher<'b, TryIntoKeyExpr>( - &'s self, - key_expr: TryIntoKeyExpr, - ) -> PublisherBuilder<'a, 'b> - where - TryIntoKeyExpr: TryInto>, - >>::Error: Into; - - /// Obtain a [`Liveliness`] struct tied to this Zenoh [`Session`]. - /// - /// # Examples - /// ``` - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap().into_arc(); - /// let liveliness = session - /// .liveliness() - /// .declare_token("key/expression") - /// .await - /// .unwrap(); - /// # } - /// ``` - #[zenoh_macros::unstable] - fn liveliness(&'s self) -> Liveliness<'a>; - /// Get information about the zenoh [`Session`](Session). - /// - /// # Examples - /// ``` - /// # #[tokio::main] - /// # async fn main() { - /// use zenoh::prelude::*; - /// - /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); - /// let info = session.info(); - /// # } - /// ``` - fn info(&'s self) -> SessionInfo<'a>; -} - -impl crate::net::primitives::EPrimitives for Session { +impl crate::net::primitives::EPrimitives for Weak { #[inline] fn send_interest(&self, ctx: crate::net::routing::RoutingContext) { (self as &dyn Primitives).send_interest(ctx.msg) @@ -3039,6 +2708,7 @@ impl Wait for InitBuilder { self.runtime, self.aggregated_subscribers, self.aggregated_publishers, + false, ) .wait()) } diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 5bca8abcfa..1d15f71757 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -17,7 +17,7 @@ use std::{ future::{IntoFuture, Ready}, mem::size_of, ops::{Deref, DerefMut}, - sync::Arc, + sync::{Arc, Weak}, }; use tracing::error; @@ -30,15 +30,18 @@ use { zenoh_protocol::core::EntityGlobalIdProto, }; -use crate::api::{ - handlers::{locked, Callback, DefaultHandler, IntoHandler}, - key_expr::KeyExpr, - sample::{Locality, Sample}, - session::{MaybeWeakSessionRef, SessionRef, UndeclarableSealed}, - Id, -}; #[cfg(feature = "unstable")] use crate::pubsub::Reliability; +use crate::{ + api::{ + handlers::{locked, Callback, DefaultHandler, IntoHandler}, + key_expr::KeyExpr, + sample::{Locality, Sample}, + session::{SessionInner, UndeclarableSealed}, + Id, + }, + Session, +}; pub(crate) struct SubscriberState { pub(crate) id: Id, @@ -58,10 +61,10 @@ impl fmt::Debug for SubscriberState { } #[derive(Debug)] -pub(crate) struct SubscriberInner<'a> { +pub(crate) struct SubscriberInner { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: MaybeWeakSessionRef<'a>, + pub(crate) session: Weak, pub(crate) state: Arc, pub(crate) kind: SubscriberKind, // Subscriber is undeclared on drop unless its handler is a ZST, i.e. it is callback-only @@ -85,19 +88,19 @@ pub(crate) struct SubscriberInner<'a> { /// # } /// ``` #[must_use = "Resolvables do nothing unless you resolve them using the `res` method from either `SyncResolve` or `AsyncResolve`"] -pub struct SubscriberUndeclaration<'a, Handler>(Subscriber<'a, Handler>); +pub struct SubscriberUndeclaration(Subscriber); -impl Resolvable for SubscriberUndeclaration<'_, Handler> { +impl Resolvable for SubscriberUndeclaration { type To = ZResult<()>; } -impl Wait for SubscriberUndeclaration<'_, Handler> { +impl Wait for SubscriberUndeclaration { fn wait(mut self) -> ::To { self.0.undeclare_impl() } } -impl IntoFuture for SubscriberUndeclaration<'_, Handler> { +impl IntoFuture for SubscriberUndeclaration { type Output = ::To; type IntoFuture = Ready<::To>; @@ -126,9 +129,9 @@ impl IntoFuture for SubscriberUndeclaration<'_, Handler> { #[derive(Debug)] pub struct SubscriberBuilder<'a, 'b, Handler> { #[cfg(feature = "unstable")] - pub session: SessionRef<'a>, + pub session: &'a Session, #[cfg(not(feature = "unstable"))] - pub(crate) session: SessionRef<'a>, + pub(crate) session: &'a Session, #[cfg(feature = "unstable")] pub key_expr: ZResult>, @@ -304,7 +307,7 @@ where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, { - type To = ZResult>; + type To = ZResult>; } impl<'a, Handler> Wait for SubscriberBuilder<'a, '_, Handler> @@ -316,8 +319,8 @@ where let key_expr = self.key_expr?; let session = self.session; let (callback, receiver) = self.handler.into_handler(); - let undeclare_on_drop = size_of::() > 0; session + .0 .declare_subscriber_inner( &key_expr, self.origin, @@ -329,19 +332,17 @@ where #[cfg(not(feature = "unstable"))] &SubscriberInfo::default(), ) - .map(|sub_state| { - Subscriber { - inner: SubscriberInner { - #[cfg(feature = "unstable")] - session_id: session.zid(), - session: MaybeWeakSessionRef::new(session, !undeclare_on_drop), - state: sub_state, - kind: SubscriberKind::Subscriber, - // `size_of::() == 0` means callback-only subscriber - undeclare_on_drop, - }, - handler: receiver, - } + .map(|sub_state| Subscriber { + inner: SubscriberInner { + #[cfg(feature = "unstable")] + session_id: session.zid(), + session: Arc::downgrade(&session.0), + state: sub_state, + kind: SubscriberKind::Subscriber, + // `size_of::() == 0` means callback-only subscriber + undeclare_on_drop: size_of::() > 0, + }, + handler: receiver, }) } } @@ -408,12 +409,12 @@ where /// ``` #[non_exhaustive] #[derive(Debug)] -pub struct Subscriber<'a, Handler> { - pub(crate) inner: SubscriberInner<'a>, +pub struct Subscriber { + pub(crate) inner: SubscriberInner, pub(crate) handler: Handler, } -impl<'a, Handler> Subscriber<'a, Handler> { +impl Subscriber { /// Returns the [`EntityGlobalId`] of this Subscriber. /// /// # Examples @@ -473,9 +474,9 @@ impl<'a, Handler> Subscriber<'a, Handler> { /// # } /// ``` #[inline] - pub fn undeclare(self) -> SubscriberUndeclaration<'a, Handler> + pub fn undeclare(self) -> SubscriberUndeclaration where - Handler: Send + 'a, + Handler: Send, { self.undeclare_inner(()) } @@ -492,7 +493,7 @@ impl<'a, Handler> Subscriber<'a, Handler> { } } -impl Drop for Subscriber<'_, Handler> { +impl Drop for Subscriber { fn drop(&mut self) { if self.inner.undeclare_on_drop { if let Err(error) = self.undeclare_impl() { @@ -502,29 +503,29 @@ impl Drop for Subscriber<'_, Handler> { } } -impl<'a, Handler: Send + 'a> UndeclarableSealed<()> for Subscriber<'a, Handler> { - type Undeclaration = SubscriberUndeclaration<'a, Handler>; +impl<'a, Handler: Send + 'a> UndeclarableSealed<()> for Subscriber { + type Undeclaration = SubscriberUndeclaration; fn undeclare_inner(self, _: ()) -> Self::Undeclaration { SubscriberUndeclaration(self) } } -impl Deref for Subscriber<'_, Handler> { +impl Deref for Subscriber { type Target = Handler; fn deref(&self) -> &Self::Target { self.handler() } } -impl DerefMut for Subscriber<'_, Handler> { +impl DerefMut for Subscriber { fn deref_mut(&mut self) -> &mut Self::Target { self.handler_mut() } } /// A [`Subscriber`] that provides data through a `flume` channel. -pub type FlumeSubscriber<'a> = Subscriber<'a, flume::Receiver>; +pub type FlumeSubscriber = Subscriber>; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum SubscriberKind { diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index 1b563bb4e4..aacc52eefa 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -191,15 +191,13 @@ pub mod session { pub use zenoh_config::wrappers::{EntityGlobalId, ZenohId}; pub use zenoh_protocol::core::EntityId; - #[zenoh_macros::unstable] - pub use crate::api::session::SessionRef; #[zenoh_macros::internal] pub use crate::api::session::{init, InitBuilder}; pub use crate::api::{ builders::publisher::{SessionDeleteBuilder, SessionPutBuilder}, info::{PeersZenohIdBuilder, RoutersZenohIdBuilder, SessionInfo, ZenohIdBuilder}, query::SessionGetBuilder, - session::{open, OpenBuilder, Session, SessionDeclarations, Undeclarable}, + session::{open, OpenBuilder, Session, Undeclarable}, }; } @@ -238,7 +236,6 @@ pub mod pubsub { #[zenoh_macros::unstable] pub use crate::api::publisher::{ MatchingListener, MatchingListenerBuilder, MatchingListenerUndeclaration, MatchingStatus, - PublisherDeclarations, PublisherRef, }; pub use crate::api::{ builders::publisher::{ diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 373d56c65a..022a2d63cb 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -25,8 +25,6 @@ //! ``` mod _prelude { - #[zenoh_macros::unstable] - pub use crate::api::publisher::PublisherDeclarations; #[zenoh_macros::unstable] pub use crate::api::selector::ZenohParameters; pub use crate::{ @@ -34,7 +32,7 @@ mod _prelude { builders::sample::{ EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, }, - session::{SessionDeclarations, Undeclarable}, + session::Undeclarable, }, config::ValidatedMap, Error as ZError, Resolvable, Resolve, Result as ZResult, diff --git a/zenoh/tests/events.rs b/zenoh/tests/events.rs index 11a6e18b53..e3a4d61656 100644 --- a/zenoh/tests/events.rs +++ b/zenoh/tests/events.rs @@ -52,7 +52,6 @@ async fn close_session(session: Session) { #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn zenoh_events() { - use zenoh::prelude::SessionDeclarations; let session = open_session(&["tcp/127.0.0.1:18447"], &[]).await; let zid = session.zid(); let sub1 = diff --git a/zenoh/tests/liveliness.rs b/zenoh/tests/liveliness.rs index 4d964cc1cf..c67a1deb6d 100644 --- a/zenoh/tests/liveliness.rs +++ b/zenoh/tests/liveliness.rs @@ -19,7 +19,7 @@ use zenoh_core::ztimeout; async fn test_liveliness_subscriber_clique() { use std::time::Duration; - use zenoh::{config, prelude::*, sample::SampleKind}; + use zenoh::{config, sample::SampleKind}; use zenoh_config::WhatAmI; use zenoh_link::EndPoint; const TIMEOUT: Duration = Duration::from_secs(60); @@ -83,7 +83,7 @@ async fn test_liveliness_subscriber_clique() { async fn test_liveliness_query_clique() { use std::time::Duration; - use zenoh::{config, prelude::*, sample::SampleKind}; + use zenoh::{config, sample::SampleKind}; use zenoh_config::WhatAmI; use zenoh_link::EndPoint; const TIMEOUT: Duration = Duration::from_secs(60); @@ -140,7 +140,7 @@ async fn test_liveliness_query_clique() { async fn test_liveliness_subscriber_brokered() { use std::time::Duration; - use zenoh::{config, prelude::*, sample::SampleKind}; + use zenoh::{config, sample::SampleKind}; use zenoh_config::WhatAmI; use zenoh_link::EndPoint; @@ -219,7 +219,7 @@ async fn test_liveliness_subscriber_brokered() { async fn test_liveliness_query_brokered() { use std::time::Duration; - use zenoh::{config, prelude::*, sample::SampleKind}; + use zenoh::{config, sample::SampleKind}; use zenoh_config::WhatAmI; use zenoh_link::EndPoint; const TIMEOUT: Duration = Duration::from_secs(60); @@ -290,7 +290,7 @@ async fn test_liveliness_query_brokered() { async fn test_liveliness_subscriber_local() { use std::time::Duration; - use zenoh::{config, prelude::*, sample::SampleKind}; + use zenoh::{config, sample::SampleKind}; use zenoh_config::WhatAmI; const TIMEOUT: Duration = Duration::from_secs(60); const SLEEP: Duration = Duration::from_secs(1); @@ -333,7 +333,7 @@ async fn test_liveliness_subscriber_local() { async fn test_liveliness_query_local() { use std::time::Duration; - use zenoh::{config, prelude::*, sample::SampleKind}; + use zenoh::{config, sample::SampleKind}; use zenoh_config::WhatAmI; const TIMEOUT: Duration = Duration::from_secs(60); const SLEEP: Duration = Duration::from_secs(1); diff --git a/zenoh/tests/routing.rs b/zenoh/tests/routing.rs index 07971b7853..1023584c70 100644 --- a/zenoh/tests/routing.rs +++ b/zenoh/tests/routing.rs @@ -56,7 +56,7 @@ enum Task { impl Task { async fn run( &self, - session: Arc, + session: Session, remaining_checkpoints: Arc, token: CancellationToken, ) -> Result<()> { @@ -386,7 +386,7 @@ impl Recipe { // In case of client can't connect to some peers/routers loop { if let Ok(session) = ztimeout!(zenoh::open(config.clone())) { - break session.into_arc(); + break session; } else { tokio::time::sleep(Duration::from_secs(1)).await; } @@ -421,7 +421,7 @@ impl Recipe { // node_task_tracker.wait().await; // Close the session once all the task associated with the node are done. - ztimeout!(Arc::try_unwrap(session).unwrap().close())?; + ztimeout!(session.close())?; println!("Node: {} is closed.", &node.name); Result::Ok(()) From 155c92365398ff88b365ea8eb2855ece2db16493 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Tue, 3 Sep 2024 17:39:20 +0200 Subject: [PATCH 09/34] fix: use weak everywhere! --- zenoh/src/api/builders/publisher.rs | 13 +++++++-- zenoh/src/api/info.rs | 2 +- zenoh/src/api/publisher.rs | 43 +++++++++++++++++------------ zenoh/src/api/queryable.rs | 10 +++---- zenoh/src/api/session.rs | 1 + zenoh/src/api/subscriber.rs | 10 +++---- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index 957bee62f8..f41b46dfbb 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -11,7 +11,10 @@ // Contributors: // ZettaScale Zenoh Team, // -use std::future::{IntoFuture, Ready}; +use std::{ + future::{IntoFuture, Ready}, + sync::Arc, +}; use zenoh_core::{Resolvable, Result as ZResult, Wait}; #[cfg(feature = "unstable")] @@ -328,7 +331,9 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { // internal function for performing the publication fn create_one_shot_publisher(self) -> ZResult> { Ok(Publisher { - session: self.session.clone().0, + #[cfg(feature = "unstable")] + session_id: self.session.0.runtime.zid(), + session: Arc::downgrade(&self.session.0), id: 0, // This is a one shot Publisher key_expr: self.key_expr?, encoding: self.encoding, @@ -387,7 +392,9 @@ impl<'a, 'b> Wait for PublisherBuilder<'a, 'b> { .0 .declare_publisher_inner(key_expr.clone(), self.destination)?; Ok(Publisher { - session: self.session.0.clone(), + #[cfg(feature = "unstable")] + session_id: self.session.0.runtime.zid(), + session: Arc::downgrade(&self.session.0), id, key_expr, encoding: self.encoding, diff --git a/zenoh/src/api/info.rs b/zenoh/src/api/info.rs index 88f8dd57b7..0993663996 100644 --- a/zenoh/src/api/info.rs +++ b/zenoh/src/api/info.rs @@ -156,7 +156,7 @@ impl<'a> IntoFuture for PeersZenohIdBuilder<'a> { } } -/// Struct returned by [`Session::info()`](crate::session::SessionDeclarations::info) which allows +/// Struct returned by [`Session::info()`](crate::Session::info) which allows /// to access information about the current zenoh [`Session`](crate::Session). /// /// # Examples diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 2777b52b8a..03e78be52d 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -17,7 +17,7 @@ use std::{ fmt, future::{IntoFuture, Ready}, pin::Pin, - sync::Arc, + sync::{Arc, Weak}, task::{Context, Poll}, }; @@ -38,6 +38,7 @@ use { }, std::{collections::HashSet, sync::Mutex}, zenoh_config::wrappers::EntityGlobalId, + zenoh_config::ZenohId, zenoh_protocol::core::EntityGlobalIdProto, }; @@ -106,7 +107,9 @@ impl fmt::Debug for PublisherState { /// ``` #[derive(Debug, Clone)] pub struct Publisher<'a> { - pub(crate) session: Arc, + #[cfg(feature = "unstable")] + pub(crate) session_id: ZenohId, + pub(crate) session: Weak, pub(crate) id: Id, pub(crate) key_expr: KeyExpr<'a>, pub(crate) encoding: Encoding, @@ -122,6 +125,12 @@ pub struct Publisher<'a> { } impl<'a> Publisher<'a> { + fn session(&self) -> ZResult> { + self.session + .upgrade() + .ok_or_else(|| zerror!("session closed").into()) + } + /// Returns the [`EntityGlobalId`] of this Publisher. /// /// # Examples @@ -140,7 +149,7 @@ impl<'a> Publisher<'a> { #[zenoh_macros::unstable] pub fn id(&self) -> EntityGlobalId { EntityGlobalIdProto { - zid: self.session.runtime.zid().into(), + zid: self.session_id.into(), eid: self.id, } .into() @@ -247,7 +256,7 @@ impl<'a> Publisher<'a> { #[zenoh_macros::unstable] pub fn matching_status(&self) -> impl Resolve> + '_ { zenoh_core::ResolveFuture::new(async move { - self.session + self.session()? .matching_status(self.key_expr(), self.destination) }) } @@ -303,14 +312,17 @@ impl<'a> Publisher<'a> { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.undeclare_on_drop = false; + let Ok(session) = self.session() else { + return Ok(()); + }; #[cfg(feature = "unstable")] { let ids: Vec = zlock!(self.matching_listeners).drain().collect(); for id in ids { - self.session.undeclare_matches_listener_inner(id)? + session.undeclare_matches_listener_inner(id)? } } - self.session.undeclare_publisher_inner(self.id) + session.undeclare_publisher_inner(self.id) } } @@ -418,20 +430,17 @@ impl Publisher<'_> { attachment: Option, ) -> ZResult<()> { tracing::trace!("write({:?}, [...])", &self.key_expr); - let primitives = zread!(self.session.state) - .primitives - .as_ref() - .unwrap() - .clone(); + let session = self.session()?; + let primitives = zread!(session.state).primitives()?; let timestamp = if timestamp.is_none() { - self.session.runtime.new_timestamp() + session.runtime.new_timestamp() } else { timestamp }; if self.destination != Locality::SessionLocal { primitives.send_push( Push { - wire_expr: self.key_expr.to_wire(&self.session).to_owned(), + wire_expr: self.key_expr.to_wire(&session).to_owned(), ext_qos: ext::QoSType::new( self.priority.into(), self.congestion_control, @@ -484,9 +493,9 @@ impl Publisher<'_> { )), }; - self.session.execute_subscriber_callbacks( + session.execute_subscriber_callbacks( true, - &self.key_expr.to_wire(&self.session), + &self.key_expr.to_wire(&session), Some(data_info), payload.into(), SubscriberKind::Subscriber, @@ -770,7 +779,7 @@ where let (callback, receiver) = self.handler.into_handler(); let state = self .publisher - .session + .session()? .declare_matches_listener_inner(self.publisher, callback)?; zlock!(self.publisher.matching_listeners).insert(state.id); Ok(MatchingListener { @@ -932,7 +941,7 @@ impl Wait for MatchingListenerUndeclaration<'_> { zlock!(self.subscriber.publisher.matching_listeners).remove(&self.subscriber.state.id); self.subscriber .publisher - .session + .session()? .undeclare_matches_listener_inner(self.subscriber.state.id) } } diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 37a5b6bc21..590f864218 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -736,7 +736,7 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// A queryable that provides data through a [`Handler`](crate::handlers::IntoHandler). /// /// Queryables can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_queryable`](crate::session::SessionDeclarations::declare_queryable) function +/// with the [`declare_queryable`](crate::Session::declare_queryable) function /// and the [`with`](QueryableBuilder::with) function /// of the resulting builder. /// @@ -863,10 +863,10 @@ impl Queryable { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; - match self.inner.session.upgrade() { - Some(session) => session.close_queryable(self.inner.state.id), - None => Ok(()), - } + let Some(session) = self.inner.session.upgrade() else { + return Ok(()); + }; + session.close_queryable(self.inner.state.id) } } diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 945a469bff..bdade37b84 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -939,6 +939,7 @@ impl SessionInner { Ok(()) }) } + pub(crate) fn declare_prefix<'a>( &'a self, prefix: &'a str, diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 1d15f71757..6d3170c39d 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -484,12 +484,10 @@ impl Subscriber { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; - match self.inner.session.upgrade() { - Some(session) => { - session.undeclare_subscriber_inner(self.inner.state.id, self.inner.kind) - } - None => Ok(()), - } + let Some(session) = self.inner.session.upgrade() else { + return Ok(()); + }; + session.undeclare_subscriber_inner(self.inner.state.id, self.inner.kind) } } From 5dfd6f3bd4ae8b1d10b534b4a1281e44ddbe3de4 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 4 Sep 2024 13:00:25 +0200 Subject: [PATCH 10/34] fix: fix doc --- zenoh/src/api/subscriber.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 6d3170c39d..8aafb7a8f5 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -363,7 +363,7 @@ where /// A subscriber that provides data through a [`Handler`](crate::handlers::IntoHandler). /// /// Subscribers can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_subscriber`](crate::session::SessionDeclarations::declare_subscriber) function +/// with the [`declare_subscriber`](crate::Session::declare_subscriber) function /// and the [`with`](SubscriberBuilder::with) function /// of the resulting builder. /// From a938c78b7d169923e134fe4d68d3a69c7223454d Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 4 Sep 2024 16:59:39 +0200 Subject: [PATCH 11/34] feat: use pseudo-weak session with the same perf than arc --- .../src/pub_sub/bin/z_pub_sub.rs | 2 +- .../src/queryable_get/bin/z_queryable_get.rs | 1 - zenoh/src/api/admin.rs | 46 ++--- zenoh/src/api/builders/publisher.rs | 12 +- zenoh/src/api/liveliness.rs | 15 +- zenoh/src/api/publisher.rs | 37 ++-- zenoh/src/api/queryable.rs | 13 +- zenoh/src/api/session.rs | 178 +++++++++++------- zenoh/src/api/subscriber.rs | 15 +- 9 files changed, 160 insertions(+), 159 deletions(-) diff --git a/ci/valgrind-check/src/pub_sub/bin/z_pub_sub.rs b/ci/valgrind-check/src/pub_sub/bin/z_pub_sub.rs index f3b1dd0efe..ad96d0b2b0 100644 --- a/ci/valgrind-check/src/pub_sub/bin/z_pub_sub.rs +++ b/ci/valgrind-check/src/pub_sub/bin/z_pub_sub.rs @@ -13,7 +13,7 @@ // use std::time::Duration; -use zenoh::{config::Config, key_expr::KeyExpr, prelude::*}; +use zenoh::{config::Config, key_expr::KeyExpr}; #[tokio::main] async fn main() { diff --git a/ci/valgrind-check/src/queryable_get/bin/z_queryable_get.rs b/ci/valgrind-check/src/queryable_get/bin/z_queryable_get.rs index 8ea7be201b..e82ecba477 100644 --- a/ci/valgrind-check/src/queryable_get/bin/z_queryable_get.rs +++ b/ci/valgrind-check/src/queryable_get/bin/z_queryable_get.rs @@ -16,7 +16,6 @@ use std::{convert::TryFrom, time::Duration}; use zenoh::{ config::Config, key_expr::KeyExpr, - prelude::*, query::{QueryTarget, Selector}, }; diff --git a/zenoh/src/api/admin.rs b/zenoh/src/api/admin.rs index 7452431977..060bb78c43 100644 --- a/zenoh/src/api/admin.rs +++ b/zenoh/src/api/admin.rs @@ -14,7 +14,7 @@ use std::{ collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, - sync::{Arc, Weak}, + sync::Arc, }; use zenoh_core::{Result as ZResult, Wait}; @@ -34,7 +34,7 @@ use super::{ sample::{DataInfo, Locality, SampleKind}, subscriber::SubscriberKind, }; -use crate::api::session::SessionInner; +use crate::api::session::WeakSession; lazy_static::lazy_static!( static ref KE_STARSTAR: &'static keyexpr = unsafe { keyexpr::from_str_unchecked("**") }; @@ -44,10 +44,10 @@ lazy_static::lazy_static!( static ref KE_LINK: &'static keyexpr = unsafe { keyexpr::from_str_unchecked("link") }; ); -pub(crate) fn init(session: &Arc) { +pub(crate) fn init(session: WeakSession) { if let Ok(own_zid) = keyexpr::new(&session.runtime.zid().to_string()) { let admin_key = KeyExpr::from(*KE_PREFIX / own_zid / *KE_SESSION / *KE_STARSTAR) - .to_wire(session) + .to_wire(&session) .to_owned(); let _admin_qabl = session.declare_queryable_inner( @@ -55,18 +55,14 @@ pub(crate) fn init(session: &Arc) { true, Locality::SessionLocal, Arc::new({ - let session = Arc::downgrade(session); - move |q| { - if let Some(session) = Weak::upgrade(&session) { - on_admin_query(&session, q) - } - } + let session = session.clone(); + move |q| on_admin_query(&session, q) }), ); } } -pub(crate) fn on_admin_query(session: &SessionInner, query: Query) { +pub(crate) fn on_admin_query(session: &WeakSession, query: Query) { fn reply_peer(own_zid: &keyexpr, query: &Query, peer: TransportPeer) { let zid = peer.zid.to_string(); if let Ok(zid) = keyexpr::new(&zid) { @@ -128,11 +124,11 @@ pub(crate) fn on_admin_query(session: &SessionInner, query: Query) { #[derive(Clone)] pub(crate) struct Handler { - pub(crate) session: Weak, + pub(crate) session: WeakSession, } impl Handler { - pub(crate) fn new(session: Weak) -> Self { + pub(crate) fn new(session: WeakSession) -> Self { Self { session } } } @@ -159,10 +155,7 @@ impl TransportMulticastEventHandler for Handler { &self, peer: zenoh_transport::TransportPeer, ) -> ZResult> { - let Some(session) = Weak::upgrade(&self.session) else { - bail!("session closed"); - }; - if let Ok(own_zid) = keyexpr::new(&session.runtime.zid().to_string()) { + if let Ok(own_zid) = keyexpr::new(&self.session.runtime.zid().to_string()) { if let Ok(zid) = keyexpr::new(&peer.zid.to_string()) { let expr = WireExpr::from( &(*KE_PREFIX / own_zid / *KE_SESSION / *KE_TRANSPORT_UNICAST / zid), @@ -172,7 +165,7 @@ impl TransportMulticastEventHandler for Handler { encoding: Some(Encoding::APPLICATION_JSON), ..Default::default() }; - session.execute_subscriber_callbacks( + self.session.execute_subscriber_callbacks( true, &expr, Some(info), @@ -205,7 +198,7 @@ impl TransportMulticastEventHandler for Handler { pub(crate) struct PeerHandler { pub(crate) expr: WireExpr<'static>, - pub(crate) session: Weak, + pub(crate) session: WeakSession, } impl TransportPeerEventHandler for PeerHandler { @@ -214,16 +207,13 @@ impl TransportPeerEventHandler for PeerHandler { } fn new_link(&self, link: zenoh_link::Link) { - let Some(session) = Weak::upgrade(&self.session) else { - return; - }; let mut s = DefaultHasher::new(); link.hash(&mut s); let info = DataInfo { encoding: Some(Encoding::APPLICATION_JSON), ..Default::default() }; - session.execute_subscriber_callbacks( + self.session.execute_subscriber_callbacks( true, &self .expr @@ -239,16 +229,13 @@ impl TransportPeerEventHandler for PeerHandler { } fn del_link(&self, link: zenoh_link::Link) { - let Some(session) = Weak::upgrade(&self.session) else { - return; - }; let mut s = DefaultHasher::new(); link.hash(&mut s); let info = DataInfo { kind: SampleKind::Delete, ..Default::default() }; - session.execute_subscriber_callbacks( + self.session.execute_subscriber_callbacks( true, &self .expr @@ -266,14 +253,11 @@ impl TransportPeerEventHandler for PeerHandler { fn closing(&self) {} fn closed(&self) { - let Some(session) = Weak::upgrade(&self.session) else { - return; - }; let info = DataInfo { kind: SampleKind::Delete, ..Default::default() }; - session.execute_subscriber_callbacks( + self.session.execute_subscriber_callbacks( true, &self.expr, Some(info), diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index f41b46dfbb..53c32c8a7d 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -11,10 +11,7 @@ // Contributors: // ZettaScale Zenoh Team, // -use std::{ - future::{IntoFuture, Ready}, - sync::Arc, -}; +use std::future::{IntoFuture, Ready}; use zenoh_core::{Resolvable, Result as ZResult, Wait}; #[cfg(feature = "unstable")] @@ -333,7 +330,7 @@ impl<'a, 'b> PublisherBuilder<'a, 'b> { Ok(Publisher { #[cfg(feature = "unstable")] session_id: self.session.0.runtime.zid(), - session: Arc::downgrade(&self.session.0), + session: self.session.downgrade(), id: 0, // This is a one shot Publisher key_expr: self.key_expr?, encoding: self.encoding, @@ -394,7 +391,7 @@ impl<'a, 'b> Wait for PublisherBuilder<'a, 'b> { Ok(Publisher { #[cfg(feature = "unstable")] session_id: self.session.0.runtime.zid(), - session: Arc::downgrade(&self.session.0), + session: self.session.downgrade(), id, key_expr, encoding: self.encoding, @@ -404,7 +401,8 @@ impl<'a, 'b> Wait for PublisherBuilder<'a, 'b> { destination: self.destination, #[cfg(feature = "unstable")] reliability: self.reliability, - #[cfg(feature = "unstable")]matching_listeners: Default::default(), + #[cfg(feature = "unstable")] + matching_listeners: Default::default(), undeclare_on_drop: true, }) } diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 50bcf9da67..ce6a60ca35 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -16,7 +16,7 @@ use std::{ convert::TryInto, future::{IntoFuture, Ready}, mem::size_of, - sync::{Arc, Weak}, + sync::Arc, time::Duration, }; @@ -33,7 +33,7 @@ use super::{ subscriber::{Subscriber, SubscriberInner}, Id, }; -use crate::api::session::SessionInner; +use crate::api::session::WeakSession; /// A structure with functions to declare a /// [`LivelinessToken`](LivelinessToken), query @@ -258,7 +258,7 @@ impl Wait for LivelinessTokenBuilder<'_, '_> { .0 .declare_liveliness_inner(&key_expr) .map(|tok_state| LivelinessToken { - session: Arc::downgrade(&self.session.0), + session: self.session.downgrade(), state: tok_state, undeclare_on_drop: true, }) @@ -311,7 +311,7 @@ pub(crate) struct LivelinessTokenState { #[zenoh_macros::unstable] #[derive(Debug)] pub struct LivelinessToken { - session: Weak, + session: WeakSession, state: Arc, undeclare_on_drop: bool, } @@ -388,10 +388,7 @@ impl LivelinessToken { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.undeclare_on_drop = false; - match self.session.upgrade() { - Some(session) => session.undeclare_liveliness(self.state.id), - None => Ok(()), - } + self.session.undeclare_liveliness(self.state.id) } } @@ -581,7 +578,7 @@ where inner: SubscriberInner { #[cfg(feature = "unstable")] session_id: session.zid(), - session: Arc::downgrade(&self.session.0), + session: self.session.downgrade(), state: sub_state, kind: SubscriberKind::LivelinessSubscriber, // `size_of::() == 0` means callback-only subscriber diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 03e78be52d..0ebcc326ae 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -17,7 +17,6 @@ use std::{ fmt, future::{IntoFuture, Ready}, pin::Pin, - sync::{Arc, Weak}, task::{Context, Poll}, }; @@ -36,7 +35,7 @@ use { handlers::{Callback, DefaultHandler, IntoHandler}, sample::SourceInfo, }, - std::{collections::HashSet, sync::Mutex}, + std::{collections::HashSet, sync::Arc, sync::Mutex}, zenoh_config::wrappers::EntityGlobalId, zenoh_config::ZenohId, zenoh_protocol::core::EntityGlobalIdProto, @@ -54,7 +53,7 @@ use super::{ session::UndeclarableSealed, }; use crate::{ - api::{session::SessionInner, subscriber::SubscriberKind, Id}, + api::{session::WeakSession, subscriber::SubscriberKind, Id}, net::primitives::Primitives, }; @@ -109,7 +108,7 @@ impl fmt::Debug for PublisherState { pub struct Publisher<'a> { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: Weak, + pub(crate) session: WeakSession, pub(crate) id: Id, pub(crate) key_expr: KeyExpr<'a>, pub(crate) encoding: Encoding, @@ -125,12 +124,6 @@ pub struct Publisher<'a> { } impl<'a> Publisher<'a> { - fn session(&self) -> ZResult> { - self.session - .upgrade() - .ok_or_else(|| zerror!("session closed").into()) - } - /// Returns the [`EntityGlobalId`] of this Publisher. /// /// # Examples @@ -256,7 +249,7 @@ impl<'a> Publisher<'a> { #[zenoh_macros::unstable] pub fn matching_status(&self) -> impl Resolve> + '_ { zenoh_core::ResolveFuture::new(async move { - self.session()? + self.session .matching_status(self.key_expr(), self.destination) }) } @@ -312,17 +305,14 @@ impl<'a> Publisher<'a> { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.undeclare_on_drop = false; - let Ok(session) = self.session() else { - return Ok(()); - }; #[cfg(feature = "unstable")] { let ids: Vec = zlock!(self.matching_listeners).drain().collect(); for id in ids { - session.undeclare_matches_listener_inner(id)? + self.session.undeclare_matches_listener_inner(id)? } } - session.undeclare_publisher_inner(self.id) + self.session.undeclare_publisher_inner(self.id) } } @@ -430,17 +420,16 @@ impl Publisher<'_> { attachment: Option, ) -> ZResult<()> { tracing::trace!("write({:?}, [...])", &self.key_expr); - let session = self.session()?; - let primitives = zread!(session.state).primitives()?; + let primitives = zread!(self.session.state).primitives()?; let timestamp = if timestamp.is_none() { - session.runtime.new_timestamp() + self.session.runtime.new_timestamp() } else { timestamp }; if self.destination != Locality::SessionLocal { primitives.send_push( Push { - wire_expr: self.key_expr.to_wire(&session).to_owned(), + wire_expr: self.key_expr.to_wire(&self.session).to_owned(), ext_qos: ext::QoSType::new( self.priority.into(), self.congestion_control, @@ -493,9 +482,9 @@ impl Publisher<'_> { )), }; - session.execute_subscriber_callbacks( + self.session.execute_subscriber_callbacks( true, - &self.key_expr.to_wire(&session), + &self.key_expr.to_wire(&self.session), Some(data_info), payload.into(), SubscriberKind::Subscriber, @@ -779,7 +768,7 @@ where let (callback, receiver) = self.handler.into_handler(); let state = self .publisher - .session()? + .session .declare_matches_listener_inner(self.publisher, callback)?; zlock!(self.publisher.matching_listeners).insert(state.id); Ok(MatchingListener { @@ -941,7 +930,7 @@ impl Wait for MatchingListenerUndeclaration<'_> { zlock!(self.subscriber.publisher.matching_listeners).remove(&self.subscriber.state.id); self.subscriber .publisher - .session()? + .session .undeclare_matches_listener_inner(self.subscriber.state.id) } } diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 590f864218..0904fa138e 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -16,7 +16,7 @@ use std::{ future::{IntoFuture, Ready}, mem::size_of, ops::{Deref, DerefMut}, - sync::{Arc, Weak}, + sync::Arc, }; use tracing::error; @@ -50,7 +50,7 @@ use crate::{ publisher::Priority, sample::{Locality, QoSBuilder, Sample, SampleKind}, selector::Selector, - session::{SessionInner, UndeclarableSealed}, + session::{UndeclarableSealed, WeakSession}, value::Value, Id, }, @@ -543,7 +543,7 @@ impl fmt::Debug for QueryableState { pub(crate) struct QueryableInner { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: Weak, + pub(crate) session: WeakSession, pub(crate) state: Arc, // Queryable is undeclared on drop unless its handler is a ZST, i.e. it is callback-only pub(crate) undeclare_on_drop: bool, @@ -863,10 +863,7 @@ impl Queryable { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; - let Some(session) = self.inner.session.upgrade() else { - return Ok(()); - }; - session.close_queryable(self.inner.state.id) + self.inner.session.close_queryable(self.inner.state.id) } } @@ -930,7 +927,7 @@ where inner: QueryableInner { #[cfg(feature = "unstable")] session_id: session.zid(), - session: Arc::downgrade(&self.session.0), + session: self.session.downgrade(), state: qable_state, // `size_of::() == 0` means callback-only queryable undeclare_on_drop: size_of::() > 0, diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index bdade37b84..e2c4beeb30 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -16,9 +16,10 @@ use std::{ convert::TryInto, fmt, future::{IntoFuture, Ready}, + ops::Deref, sync::{ atomic::{AtomicU16, Ordering}, - Arc, RwLock, Weak, + Arc, Mutex, RwLock, }, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -392,6 +393,7 @@ pub trait Undeclarable: UndeclarableSealed {} impl Undeclarable for T where T: UndeclarableSealed {} pub(crate) struct SessionInner { + weak_counter: Mutex, pub(crate) runtime: Runtime, pub(crate) state: RwLock, pub(crate) id: u16, @@ -409,9 +411,78 @@ impl fmt::Debug for SessionInner { /// A zenoh session. /// -#[derive(Clone)] pub struct Session(pub(crate) Arc); +impl Session { + pub(crate) fn downgrade(&self) -> WeakSession { + WeakSession::new(&self.0) + } +} + +impl fmt::Debug for Session { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl Clone for Session { + fn clone(&self) -> Self { + let _weak = self.0.weak_counter.lock().unwrap(); + Self(self.0.clone()) + } +} + +impl Drop for Session { + fn drop(&mut self) { + let weak = self.0.weak_counter.lock().unwrap(); + if Arc::strong_count(&self.0) == *weak + 1 { + drop(weak); + if let Err(error) = self.close().wait() { + tracing::error!(error) + } + } + } +} + +pub(crate) struct WeakSession(Arc); + +impl WeakSession { + fn new(session: &Arc) -> Self { + let mut weak = session.weak_counter.lock().unwrap(); + *weak += 1; + Self(session.clone()) + } +} + +impl Clone for WeakSession { + fn clone(&self) -> Self { + let mut weak = self.0.weak_counter.lock().unwrap(); + *weak += 1; + Self(self.0.clone()) + } +} + +impl fmt::Debug for WeakSession { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl Deref for WeakSession { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Drop for WeakSession { + fn drop(&mut self) { + let mut weak = self.0.weak_counter.lock().unwrap(); + *weak -= 1; + } +} + static SESSION_ID_COUNTER: AtomicU16 = AtomicU16::new(0); impl Session { pub(crate) fn init( @@ -426,22 +497,23 @@ impl Session { aggregated_subscribers, aggregated_publishers, )); - let session = Arc::new(SessionInner { + let session = Session(Arc::new(SessionInner { + weak_counter: Mutex::new(0), runtime: runtime.clone(), state, id: SESSION_ID_COUNTER.fetch_add(1, Ordering::SeqCst), owns_runtime, task_controller: TaskController::default(), - }); + })); - runtime.new_handler(Arc::new(admin::Handler::new(Arc::downgrade(&session)))); + runtime.new_handler(Arc::new(admin::Handler::new(session.downgrade()))); - let primitives = Some(router.new_primitives(Arc::new(Arc::downgrade(&session)))); - zwrite!(session.state).primitives = primitives; + let primitives = Some(router.new_primitives(Arc::new(session.downgrade()))); + zwrite!(session.0.state).primitives = primitives; - admin::init(&session); + admin::init(session.downgrade()); - Session(session) + session }) } @@ -935,6 +1007,7 @@ impl SessionInner { if self.owns_runtime { self.runtime.close().await?; } + zwrite!(self.state).queryables.clear(); primitives.send_close(); Ok(()) }) @@ -1560,7 +1633,7 @@ impl SessionInner { // TODO: check which ZRuntime should be used self.task_controller .spawn_with_rt(zenoh_runtime::ZRuntime::Net, { - let session = self.clone(); + let session = WeakSession::new(self); let msub = msub.clone(); async move { match msub.current.lock() { @@ -1598,7 +1671,7 @@ impl SessionInner { // TODO: check which ZRuntime should be used self.task_controller .spawn_with_rt(zenoh_runtime::ZRuntime::Net, { - let session = self.clone(); + let session = WeakSession::new(self); let msub = msub.clone(); async move { match msub.current.lock() { @@ -1754,7 +1827,7 @@ impl SessionInner { let token = self.task_controller.get_cancellation_token(); self.task_controller .spawn_with_rt(zenoh_runtime::ZRuntime::Net, { - let session = self.clone(); + let session = WeakSession::new(self); #[cfg(feature = "unstable")] let zid = self.runtime.zid(); async move { @@ -1860,7 +1933,7 @@ impl SessionInner { let token = self.task_controller.get_cancellation_token(); self.task_controller .spawn_with_rt(zenoh_runtime::ZRuntime::Net, { - let session = self.clone(); + let session = WeakSession::new(self); let zid = self.runtime.zid(); async move { tokio::select! { @@ -1962,7 +2035,7 @@ impl SessionInner { qid, zid: zid.into(), primitives: if local { - Arc::new(Arc::downgrade(self)) + Arc::new(WeakSession::new(self)) } else { primitives }, @@ -1981,21 +2054,15 @@ impl SessionInner { } } -impl Primitives for Weak { +impl Primitives for WeakSession { fn send_interest(&self, msg: zenoh_protocol::network::Interest) { - if self.upgrade().is_none() { - return; - } trace!("recv Interest {} {:?}", msg.id, msg.wire_expr); } fn send_declare(&self, msg: zenoh_protocol::network::Declare) { - let Some(session) = self.upgrade() else { - return; - }; match msg.body { zenoh_protocol::network::DeclareBody::DeclareKeyExpr(m) => { trace!("recv DeclareKeyExpr {} {:?}", m.id, m.wire_expr); - let state = &mut zwrite!(session.state); + let state = &mut zwrite!(self.state); match state.remote_key_to_expr(&m.wire_expr) { Ok(key_expr) => { let mut res_node = ResourceNode::new(key_expr.clone().into()); @@ -2027,14 +2094,14 @@ impl Primitives for Weak { trace!("recv DeclareSubscriber {} {:?}", m.id, m.wire_expr); #[cfg(feature = "unstable")] { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); match state .wireexpr_to_keyexpr(&m.wire_expr, false) .map(|e| e.into_owned()) { Ok(expr) => { state.remote_subscribers.insert(m.id, expr.clone()); - session.update_status_up(&state, &expr); + self.update_status_up(&state, &expr); } Err(err) => { tracing::error!( @@ -2049,9 +2116,9 @@ impl Primitives for Weak { trace!("recv UndeclareSubscriber {:?}", m.id); #[cfg(feature = "unstable")] { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); if let Some(expr) = state.remote_subscribers.remove(&m.id) { - session.update_status_down(&state, &expr); + self.update_status_down(&state, &expr); } else { tracing::error!("Received Undeclare Subscriber for unknown id: {}", m.id); } @@ -2067,7 +2134,7 @@ impl Primitives for Weak { trace!("recv DeclareToken {:?}", m.id); #[cfg(feature = "unstable")] { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); match state .wireexpr_to_keyexpr(&m.wire_expr, false) .map(|e| e.into_owned()) @@ -2101,7 +2168,7 @@ impl Primitives for Weak { drop(state); - session.execute_subscriber_callbacks( + self.execute_subscriber_callbacks( false, &m.wire_expr, None, @@ -2124,7 +2191,7 @@ impl Primitives for Weak { trace!("recv UndeclareToken {:?}", m.id); #[cfg(feature = "unstable")] { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); if let Some(key_expr) = state.remote_tokens.remove(&m.id) { drop(state); @@ -2133,9 +2200,9 @@ impl Primitives for Weak { ..Default::default() }; - session.execute_subscriber_callbacks( + self.execute_subscriber_callbacks( false, - &key_expr.to_wire(&session), + &key_expr.to_wire(self), Some(data_info), ZBuf::default(), SubscriberKind::LivelinessSubscriber, @@ -2157,9 +2224,9 @@ impl Primitives for Weak { ..Default::default() }; - session.execute_subscriber_callbacks( + self.execute_subscriber_callbacks( false, - &key_expr.to_wire(&session), + &key_expr.to_wire(self), Some(data_info), ZBuf::default(), SubscriberKind::LivelinessSubscriber, @@ -2184,7 +2251,7 @@ impl Primitives for Weak { #[cfg(feature = "unstable")] if let Some(interest_id) = msg.interest_id { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); let _ = state.liveliness_queries.remove(&interest_id); } } @@ -2192,9 +2259,6 @@ impl Primitives for Weak { } fn send_push(&self, msg: Push, _reliability: Reliability) { - let Some(session) = self.upgrade() else { - return; - }; trace!("recv Push {:?}", msg); match msg.payload { PushBody::Put(m) => { @@ -2206,7 +2270,7 @@ impl Primitives for Weak { source_id: m.ext_sinfo.as_ref().map(|i| i.id.into()), source_sn: m.ext_sinfo.as_ref().map(|i| i.sn as u64), }; - session.execute_subscriber_callbacks( + self.execute_subscriber_callbacks( false, &msg.wire_expr, Some(info), @@ -2226,7 +2290,7 @@ impl Primitives for Weak { source_id: m.ext_sinfo.as_ref().map(|i| i.id.into()), source_sn: m.ext_sinfo.as_ref().map(|i| i.sn as u64), }; - session.execute_subscriber_callbacks( + self.execute_subscriber_callbacks( false, &msg.wire_expr, Some(info), @@ -2241,12 +2305,9 @@ impl Primitives for Weak { } fn send_request(&self, msg: Request) { - let Some(session) = self.upgrade() else { - return; - }; trace!("recv Request {:?}", msg); match msg.payload { - RequestBody::Query(m) => session.handle_query( + RequestBody::Query(m) => self.handle_query( false, &msg.wire_expr, &m.parameters, @@ -2260,13 +2321,10 @@ impl Primitives for Weak { } fn send_response(&self, msg: Response) { - let Some(session) = self.upgrade() else { - return; - }; trace!("recv Response {:?}", msg); match msg.payload { ResponseBody::Err(e) => { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); match state.queries.get_mut(&msg.rid) { Some(query) => { let callback = query.callback.clone(); @@ -2288,7 +2346,7 @@ impl Primitives for Weak { } } ResponseBody::Reply(m) => { - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); let key_expr = match state.remote_key_to_expr(&msg.wire_expr) { Ok(key) => key.into_owned(), Err(e) => { @@ -2462,11 +2520,8 @@ impl Primitives for Weak { } fn send_response_final(&self, msg: ResponseFinal) { - let Some(session) = self.upgrade() else { - return; - }; trace!("recv ResponseFinal {:?}", msg); - let mut state = zwrite!(session.state); + let mut state = zwrite!(self.state); match state.queries.get_mut(&msg.rid) { Some(query) => { query.nb_final -= 1; @@ -2488,28 +2543,11 @@ impl Primitives for Weak { } fn send_close(&self) { - if self.upgrade().is_none() { - return; - } trace!("recv Close"); } } -impl Drop for SessionInner { - fn drop(&mut self) { - if let Err(error) = self.close().wait() { - tracing::error!(error); - } - } -} - -impl fmt::Debug for Session { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl crate::net::primitives::EPrimitives for Weak { +impl crate::net::primitives::EPrimitives for WeakSession { #[inline] fn send_interest(&self, ctx: crate::net::routing::RoutingContext) { (self as &dyn Primitives).send_interest(ctx.msg) diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 8aafb7a8f5..4dd1caba38 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -17,7 +17,7 @@ use std::{ future::{IntoFuture, Ready}, mem::size_of, ops::{Deref, DerefMut}, - sync::{Arc, Weak}, + sync::Arc, }; use tracing::error; @@ -37,7 +37,7 @@ use crate::{ handlers::{locked, Callback, DefaultHandler, IntoHandler}, key_expr::KeyExpr, sample::{Locality, Sample}, - session::{SessionInner, UndeclarableSealed}, + session::{UndeclarableSealed, WeakSession}, Id, }, Session, @@ -64,7 +64,7 @@ impl fmt::Debug for SubscriberState { pub(crate) struct SubscriberInner { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, - pub(crate) session: Weak, + pub(crate) session: WeakSession, pub(crate) state: Arc, pub(crate) kind: SubscriberKind, // Subscriber is undeclared on drop unless its handler is a ZST, i.e. it is callback-only @@ -336,7 +336,7 @@ where inner: SubscriberInner { #[cfg(feature = "unstable")] session_id: session.zid(), - session: Arc::downgrade(&session.0), + session: session.downgrade(), state: sub_state, kind: SubscriberKind::Subscriber, // `size_of::() == 0` means callback-only subscriber @@ -484,10 +484,9 @@ impl Subscriber { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; - let Some(session) = self.inner.session.upgrade() else { - return Ok(()); - }; - session.undeclare_subscriber_inner(self.inner.state.id, self.inner.kind) + self.inner + .session + .undeclare_subscriber_inner(self.inner.state.id, self.inner.kind) } } From 2ef2446440a47be2033f453caa560be6c3ee8e9d Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Thu, 5 Sep 2024 18:25:20 +0200 Subject: [PATCH 12/34] fix: fix resource cleanup --- zenoh/src/api/session.rs | 3 ++- zenoh/src/net/routing/dispatcher/resource.rs | 1 + zenoh/src/net/runtime/mod.rs | 11 ++++------- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index e2c4beeb30..cf6cfd32da 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -1006,9 +1006,10 @@ impl SessionInner { self.task_controller.terminate_all(Duration::from_secs(10)); if self.owns_runtime { self.runtime.close().await?; + } else { + primitives.send_close(); } zwrite!(self.state).queryables.clear(); - primitives.send_close(); Ok(()) }) } diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index 01ff9b2817..ab84241666 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -341,6 +341,7 @@ impl Resource { r.parent.take(); r.children.clear(); r.nonwild_prefix.take(); + r.context.take(); r.session_ctxs.clear(); } diff --git a/zenoh/src/net/runtime/mod.rs b/zenoh/src/net/runtime/mod.rs index 9abb01b94e..9f56f4f720 100644 --- a/zenoh/src/net/runtime/mod.rs +++ b/zenoh/src/net/runtime/mod.rs @@ -279,13 +279,10 @@ impl Runtime { // the task responsible for resource clean up was aborted earlier than expected. // This should be resolved by identfying correspodning task, and placing // cancellation token manually inside it. - self.router() - .tables - .tables - .write() - .unwrap() - .root_res - .close(); + let router = self.router(); + let mut tables = router.tables.tables.write().unwrap(); + tables.root_res.close(); + tables.faces.clear(); Ok(()) } From 8f159eaa4af4ccaaa7ce65f43dc2f83dd56d8015 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Fri, 6 Sep 2024 10:50:38 +0200 Subject: [PATCH 13/34] Fix typo --- zenoh/src/api/publisher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 0ebcc326ae..54b70a7bca 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -841,7 +841,7 @@ impl<'a> UndeclarableSealed<()> for MatchingListenerInner<'a> { /// A listener that sends notifications when the [`MatchingStatus`] of a /// publisher changes. /// -/// Matching litsteners run in background until the publisher is undeclared. +/// Matching listeners run in background until the publisher is undeclared. /// They can be manually undeclared, but will not be undeclared on drop. /// /// # Examples From bb9de5a62118644a17458110268677359e65dbc6 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Fri, 6 Sep 2024 11:18:04 +0200 Subject: [PATCH 14/34] fix: align `MatchingListener` undeclaration on drop behavior --- zenoh/src/api/publisher.rs | 90 +++++++++++++++++-------------------- zenoh/src/api/queryable.rs | 4 +- zenoh/src/api/subscriber.rs | 6 +-- 3 files changed, 45 insertions(+), 55 deletions(-) diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 54b70a7bca..1212bc83f4 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -16,6 +16,7 @@ use std::{ convert::TryFrom, fmt, future::{IntoFuture, Ready}, + mem::size_of, pin::Pin, task::{Context, Poll}, }; @@ -765,18 +766,19 @@ where { #[zenoh_macros::unstable] fn wait(self) -> ::To { - let (callback, receiver) = self.handler.into_handler(); + let (callback, handler) = self.handler.into_handler(); let state = self .publisher .session .declare_matches_listener_inner(self.publisher, callback)?; zlock!(self.publisher.matching_listeners).insert(state.id); Ok(MatchingListener { - listener: MatchingListenerInner { + inner: MatchingListenerInner { publisher: self.publisher.clone(), state, + undeclare_on_drop: size_of::() > 0, }, - receiver, + handler, }) } } @@ -819,30 +821,15 @@ impl fmt::Debug for MatchingListenerState { pub(crate) struct MatchingListenerInner<'a> { pub(crate) publisher: Publisher<'a>, pub(crate) state: Arc, -} - -#[zenoh_macros::unstable] -impl<'a> MatchingListenerInner<'a> { - #[inline] - pub fn undeclare(self) -> MatchingListenerUndeclaration<'a> { - UndeclarableSealed::undeclare_inner(self, ()) - } -} - -#[zenoh_macros::unstable] -impl<'a> UndeclarableSealed<()> for MatchingListenerInner<'a> { - type Undeclaration = MatchingListenerUndeclaration<'a>; - - fn undeclare_inner(self, _: ()) -> Self::Undeclaration { - MatchingListenerUndeclaration { subscriber: self } - } + pub(crate) undeclare_on_drop: bool, } /// A listener that sends notifications when the [`MatchingStatus`] of a /// publisher changes. /// -/// Matching listeners run in background until the publisher is undeclared. -/// They can be manually undeclared, but will not be undeclared on drop. +/// Callback matching listeners will run in background until the publisher is undeclared, +/// or until it is undeclared. +/// On the other hand, matching listener with a handler are automatically undeclared when dropped. /// /// # Examples /// ```no_run @@ -863,13 +850,13 @@ impl<'a> UndeclarableSealed<()> for MatchingListenerInner<'a> { /// # } /// ``` #[zenoh_macros::unstable] -pub struct MatchingListener<'a, Receiver> { - pub(crate) listener: MatchingListenerInner<'a>, - pub(crate) receiver: Receiver, +pub struct MatchingListener<'a, Handler> { + pub(crate) inner: MatchingListenerInner<'a>, + pub(crate) handler: Handler, } #[zenoh_macros::unstable] -impl<'a, Receiver> MatchingListener<'a, Receiver> { +impl<'a, Handler> MatchingListener<'a, Handler> { /// Undeclare the [`MatchingListener`]. /// /// # Examples @@ -885,58 +872,65 @@ impl<'a, Receiver> MatchingListener<'a, Receiver> { /// # } /// ``` #[inline] - pub fn undeclare(self) -> MatchingListenerUndeclaration<'a> { - self.listener.undeclare() + pub fn undeclare(self) -> MatchingListenerUndeclaration<'a, Handler> + where + Handler: Send, + { + self.undeclare_inner(()) + } + + fn undeclare_impl(&mut self) -> ZResult<()> { + // set the flag first to avoid double panic if this function panic + self.inner.undeclare_on_drop = false; + zlock!(self.inner.publisher.matching_listeners).remove(&self.inner.state.id); + self.inner + .publisher + .session + .undeclare_matches_listener_inner(self.inner.state.id) } } #[zenoh_macros::unstable] -impl<'a, T> UndeclarableSealed<()> for MatchingListener<'a, T> { - type Undeclaration = MatchingListenerUndeclaration<'a>; +impl<'a, Handler: Send> UndeclarableSealed<()> for MatchingListener<'a, Handler> { + type Undeclaration = MatchingListenerUndeclaration<'a, Handler>; fn undeclare_inner(self, _: ()) -> Self::Undeclaration { - UndeclarableSealed::undeclare_inner(self.listener, ()) + MatchingListenerUndeclaration(self) } } #[zenoh_macros::unstable] -impl std::ops::Deref for MatchingListener<'_, Receiver> { - type Target = Receiver; +impl std::ops::Deref for MatchingListener<'_, Handler> { + type Target = Handler; fn deref(&self) -> &Self::Target { - &self.receiver + &self.handler } } #[zenoh_macros::unstable] -impl std::ops::DerefMut for MatchingListener<'_, Receiver> { +impl std::ops::DerefMut for MatchingListener<'_, Handler> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.receiver + &mut self.handler } } #[zenoh_macros::unstable] -pub struct MatchingListenerUndeclaration<'a> { - subscriber: MatchingListenerInner<'a>, -} +pub struct MatchingListenerUndeclaration<'a, Handler>(MatchingListener<'a, Handler>); #[zenoh_macros::unstable] -impl Resolvable for MatchingListenerUndeclaration<'_> { +impl Resolvable for MatchingListenerUndeclaration<'_, Handler> { type To = ZResult<()>; } #[zenoh_macros::unstable] -impl Wait for MatchingListenerUndeclaration<'_> { - fn wait(self) -> ::To { - zlock!(self.subscriber.publisher.matching_listeners).remove(&self.subscriber.state.id); - self.subscriber - .publisher - .session - .undeclare_matches_listener_inner(self.subscriber.state.id) +impl Wait for MatchingListenerUndeclaration<'_, Handler> { + fn wait(mut self) -> ::To { + self.0.undeclare_impl() } } #[zenoh_macros::unstable] -impl IntoFuture for MatchingListenerUndeclaration<'_> { +impl IntoFuture for MatchingListenerUndeclaration<'_, Handler> { type Output = ::To; type IntoFuture = Ready<::To>; diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 0904fa138e..e47248f57f 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -736,9 +736,7 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// A queryable that provides data through a [`Handler`](crate::handlers::IntoHandler). /// /// Queryables can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_queryable`](crate::Session::declare_queryable) function -/// and the [`with`](QueryableBuilder::with) function -/// of the resulting builder. +/// with the [`declare_queryable`](crate::Session::declare_queryable) function. /// /// Callback queryables will run in background until the session is closed, /// or until it is undeclared. diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 4dd1caba38..3b7fc6abc4 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -363,9 +363,7 @@ where /// A subscriber that provides data through a [`Handler`](crate::handlers::IntoHandler). /// /// Subscribers can be created from a zenoh [`Session`](crate::Session) -/// with the [`declare_subscriber`](crate::Session::declare_subscriber) function -/// and the [`with`](SubscriberBuilder::with) function -/// of the resulting builder. +/// with the [`declare_subscriber`](crate::Session::declare_subscriber) function. /// /// Callback subscribers will run in background until the session is closed, /// or until it is undeclared. @@ -500,7 +498,7 @@ impl Drop for Subscriber { } } -impl<'a, Handler: Send + 'a> UndeclarableSealed<()> for Subscriber { +impl UndeclarableSealed<()> for Subscriber { type Undeclaration = SubscriberUndeclaration; fn undeclare_inner(self, _: ()) -> Self::Undeclaration { From f2afe7051588854a6a88ee05853cb22918c5dc49 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Fri, 6 Sep 2024 12:11:07 +0200 Subject: [PATCH 15/34] refactor: add comments about `WeakSession` --- zenoh/src/api/session.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index cf6cfd32da..e0eac2951d 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -393,6 +393,7 @@ pub trait Undeclarable: UndeclarableSealed {} impl Undeclarable for T where T: UndeclarableSealed {} pub(crate) struct SessionInner { + /// See [`WeakSession`] doc weak_counter: Mutex, pub(crate) runtime: Runtime, pub(crate) state: RwLock, @@ -435,7 +436,7 @@ impl Clone for Session { impl Drop for Session { fn drop(&mut self) { let weak = self.0.weak_counter.lock().unwrap(); - if Arc::strong_count(&self.0) == *weak + 1 { + if Arc::strong_count(&self.0) == *weak + /* the `Arc` currently dropped */ 1 { drop(weak); if let Err(error) = self.close().wait() { tracing::error!(error) @@ -444,6 +445,20 @@ impl Drop for Session { } } +/// `WeakSession` provides a weak-like semantic to the arc-like session, without using [`Weak`]. +/// It allows notably to establish reference cycles inside the session, for the primitive +/// implementation. +/// When all `Session` instance are dropped, [`Session::close`] is be called and cleans +/// the reference cycles, allowing the underlying `Arc` to be properly reclaimed. +/// +/// The pseudo-weak algorithm relies on a counter wrapped in a mutex. It was indeed the simplest +/// to implement it, because atomic manipulations to achieve this semantic would not have been +/// trivial at all — what could happen if a pseudo-weak is cloned while the last session instance +/// is dropped? With a mutex, it's simple, and it works perfectly fine, as we don't care about the +/// performance penalty when it comes to session entities cloning/dropping. +/// +/// (Although it was planed to be used initially, `Weak` was in fact causing errors in the session +/// closing, because the primitive implementation seemed to be used in the closing operation.) pub(crate) struct WeakSession(Arc); impl WeakSession { From 8f15a04ddb8bd58a76ce943905e3fdb675812783 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 9 Sep 2024 14:49:50 +0200 Subject: [PATCH 16/34] refactor: add comment for `Session` and `Session::close` (#1369) * refactor: add comment for `Session` and `Session::close` * Update zenoh/src/api/session.rs Co-authored-by: Luca Cominardi * Update zenoh/src/api/session.rs Co-authored-by: Luca Cominardi * Update zenoh/src/api/session.rs Co-authored-by: Luca Cominardi * fix: don't run `Session::close` example * fix: fix `Session` example * fix: fix `Session` doc --------- Co-authored-by: Luca Cominardi --- zenoh/src/api/publisher.rs | 3 +- zenoh/src/api/session.rs | 68 ++++++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 1212bc83f4..b42635750b 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -12,11 +12,12 @@ // ZettaScale Zenoh Team, // +#[cfg(feature = "unstable")] +use std::mem::size_of; use std::{ convert::TryFrom, fmt, future::{IntoFuture, Ready}, - mem::size_of, pin::Pin, task::{Context, Poll}, }; diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index e0eac2951d..38548dd344 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -24,7 +24,7 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -use tracing::{error, trace, warn}; +use tracing::{error, info, trace, warn}; use uhlc::{Timestamp, HLC}; use zenoh_buffers::ZBuf; use zenoh_collections::SingleOrVec; @@ -410,8 +410,23 @@ impl fmt::Debug for SessionInner { } } -/// A zenoh session. +/// The entrypoint of the zenoh API. /// +/// Zenoh session is instantiated using [`zenoh::open`](crate::open) and it can be used to declare various +/// entities like publishers, subscribers, or querybables, as well as issuing queries. +/// +/// Session is an `Arc`-like type, it can be cloned, and it is closed when the last instance +/// is dropped (see [`Session::close`]). +/// +/// # Examples +/// ``` +/// # #[tokio::main] +/// # async fn main() { +/// use zenoh::prelude::*; +/// +/// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); +/// session.put("key/expression", "value").await.unwrap(); +/// # } pub struct Session(pub(crate) Arc); impl Session { @@ -544,23 +559,62 @@ impl Session { /// Close the zenoh [`Session`](Session). /// - /// Sessions are automatically closed when dropped, but you may want to use this function to handle errors or - /// close the Session asynchronously. + /// Every subscriber and queryable declared will stop receiving data, and further attempt to + /// publish or query with the session or publishers will result in an error. Undeclaring an + /// entity after session closing is a no-op. Session state can be checked with + /// [`Session::is_closed`]. + /// + /// Session are automatically closed when all its instances are dropped, same as `Arc`. + /// You may still want to use this function to handle errors or close the session + /// asynchronously. + ///
+ /// Closing the session can also save bandwidth, as it avoids propagating the undeclaration + /// of the remaining entities. + /// /// /// # Examples - /// ``` + /// ```no_run /// # #[tokio::main] /// # async fn main() { /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// let subscriber = session + /// .declare_subscriber("key/expression") + /// .await + /// .unwrap(); + /// let subscriber_task = tokio::spawn(async move { + /// while let Ok(sample) = subscriber.recv_async().await { + /// println!("Received: {} {:?}", sample.key_expr(), sample.payload()); + /// } + /// }); /// session.close().await.unwrap(); + /// // subscriber task will end as `subscriber.recv_async()` will return `Err` + /// // subscriber undeclaration has not been sent on the wire + /// subscriber_task.await.unwrap(); /// # } /// ``` pub fn close(&self) -> impl Resolve> + '_ { self.0.close() } + /// Check if the session has been closed. + /// + /// # Examples + /// ``` + /// # #[tokio::main] + /// # async fn main() { + /// use zenoh::prelude::*; + /// + /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); + /// assert!(!session.is_closed()); + /// session.close().await.unwrap(); + /// assert!(session.is_closed()); + /// # } + pub fn is_closed(&self) -> bool { + zread!(self.0.state).primitives.is_none() + } + pub fn undeclare<'a, T>(&'a self, decl: T) -> impl Resolve> + 'a where T: Undeclarable<&'a Session> + 'a, @@ -1017,7 +1071,9 @@ impl SessionInner { let Some(primitives) = zwrite!(self.state).primitives.take() else { return Ok(()); }; - trace!("close()"); + if self.owns_runtime { + info!(zid = %self.runtime.zid(), "close session"); + } self.task_controller.terminate_all(Duration::from_secs(10)); if self.owns_runtime { self.runtime.close().await?; From 2febb76c9f0824b66ef0618a1ea3c299accd08ae Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 9 Sep 2024 14:53:49 +0200 Subject: [PATCH 17/34] feat: use builder method instead of handler type for undeclaration on drop (#1377) * refactor: add comment for `Session` and `Session::close` * Update zenoh/src/api/session.rs Co-authored-by: Luca Cominardi * Update zenoh/src/api/session.rs Co-authored-by: Luca Cominardi * Update zenoh/src/api/session.rs Co-authored-by: Luca Cominardi * fix: don't run `Session::close` example * fix: fix `Session` example * fix: fix `Session` doc * feat: use builder method instead of handler type for undeclaration on drop --------- Co-authored-by: Luca Cominardi --- zenoh/src/api/liveliness.rs | 10 +++++++--- zenoh/src/api/publisher.rs | 13 +++++++++++-- zenoh/src/api/queryable.rs | 9 ++++++--- zenoh/src/api/session.rs | 2 ++ zenoh/src/api/subscriber.rs | 13 ++++++++++--- 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index ce6a60ca35..7c07056c1e 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -15,7 +15,6 @@ use std::{ convert::TryInto, future::{IntoFuture, Ready}, - mem::size_of, sync::Arc, time::Duration, }; @@ -172,6 +171,7 @@ impl<'a> Liveliness<'a> { session: self.session, key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), handler: DefaultHandler::default(), + undeclare_on_drop: true, } } @@ -435,6 +435,7 @@ pub struct LivelinessSubscriberBuilder<'a, 'b, Handler> { pub session: &'a Session, pub key_expr: ZResult>, pub handler: Handler, + pub undeclare_on_drop: bool, } #[zenoh_macros::unstable] @@ -469,11 +470,13 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { session, key_expr, handler: _, + undeclare_on_drop: _, } = self; LivelinessSubscriberBuilder { session, key_expr, handler: callback, + undeclare_on_drop: false, } } @@ -540,11 +543,13 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { session, key_expr, handler: _, + undeclare_on_drop: _, } = self; LivelinessSubscriberBuilder { session, key_expr, handler, + undeclare_on_drop: true, } } } @@ -581,8 +586,7 @@ where session: self.session.downgrade(), state: sub_state, kind: SubscriberKind::LivelinessSubscriber, - // `size_of::() == 0` means callback-only subscriber - undeclare_on_drop: size_of::() > 0, + undeclare_on_drop: self.undeclare_on_drop, }, handler, }) diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index b42635750b..a8ce4e5569 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -284,6 +284,7 @@ impl<'a> Publisher<'a> { MatchingListenerBuilder { publisher: self, handler: DefaultHandler::default(), + undeclare_on_drop: true, } } @@ -639,6 +640,7 @@ impl MatchingStatus { pub struct MatchingListenerBuilder<'a, 'b, Handler> { pub(crate) publisher: &'a Publisher<'b>, pub handler: Handler, + pub undeclare_on_drop: bool, } #[zenoh_macros::unstable] @@ -675,10 +677,12 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { let MatchingListenerBuilder { publisher, handler: _, + undeclare_on_drop: _, } = self; MatchingListenerBuilder { publisher, handler: callback, + undeclare_on_drop: false, } } @@ -745,8 +749,13 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { let MatchingListenerBuilder { publisher, handler: _, + undeclare_on_drop: _, } = self; - MatchingListenerBuilder { publisher, handler } + MatchingListenerBuilder { + publisher, + handler, + undeclare_on_drop: true, + } } } @@ -777,7 +786,7 @@ where inner: MatchingListenerInner { publisher: self.publisher.clone(), state, - undeclare_on_drop: size_of::() > 0, + undeclare_on_drop: self.undeclare_on_drop, }, handler, }) diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index e47248f57f..a1ac14b5f1 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -14,7 +14,6 @@ use std::{ fmt, future::{IntoFuture, Ready}, - mem::size_of, ops::{Deref, DerefMut}, sync::Arc, }; @@ -604,6 +603,7 @@ pub struct QueryableBuilder<'a, 'b, Handler> { pub(crate) complete: bool, pub(crate) origin: Locality, pub(crate) handler: Handler, + pub(crate) undeclare_on_drop: bool, } impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { @@ -634,6 +634,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler: _, + undeclare_on_drop: _, } = self; QueryableBuilder { session, @@ -641,6 +642,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler: callback, + undeclare_on_drop: false, } } @@ -705,6 +707,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler: _, + undeclare_on_drop: _, } = self; QueryableBuilder { session, @@ -712,6 +715,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler, + undeclare_on_drop: true, } } @@ -927,8 +931,7 @@ where session_id: session.zid(), session: self.session.downgrade(), state: qable_state, - // `size_of::() == 0` means callback-only queryable - undeclare_on_drop: size_of::() > 0, + undeclare_on_drop: self.undeclare_on_drop, }, handler: receiver, }) diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 38548dd344..4247f918a8 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -740,6 +740,7 @@ impl Session { reliability: Reliability::DEFAULT, origin: Locality::default(), handler: DefaultHandler::default(), + undeclare_on_drop: true, } } @@ -784,6 +785,7 @@ impl Session { complete: false, origin: Locality::default(), handler: DefaultHandler::default(), + undeclare_on_drop: true, } } diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 3b7fc6abc4..7571a1b97d 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -15,7 +15,6 @@ use std::{ fmt, future::{IntoFuture, Ready}, - mem::size_of, ops::{Deref, DerefMut}, sync::Arc, }; @@ -150,6 +149,11 @@ pub struct SubscriberBuilder<'a, 'b, Handler> { pub handler: Handler, #[cfg(not(feature = "unstable"))] pub(crate) handler: Handler, + + #[cfg(feature = "unstable")] + pub undeclare_on_drop: bool, + #[cfg(not(feature = "unstable"))] + pub(crate) undeclare_on_drop: bool, } impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { @@ -181,6 +185,7 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { reliability, origin, handler: _, + undeclare_on_drop: _, } = self; SubscriberBuilder { session, @@ -189,6 +194,7 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { reliability, origin, handler: callback, + undeclare_on_drop: false, } } @@ -254,6 +260,7 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { reliability, origin, handler: _, + undeclare_on_drop: _, } = self; SubscriberBuilder { session, @@ -262,6 +269,7 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { reliability, origin, handler, + undeclare_on_drop: true, } } } @@ -339,8 +347,7 @@ where session: session.downgrade(), state: sub_state, kind: SubscriberKind::Subscriber, - // `size_of::() == 0` means callback-only subscriber - undeclare_on_drop: size_of::() > 0, + undeclare_on_drop: self.undeclare_on_drop, }, handler: receiver, }) From f3f540320e211c8f720d3e660ac50af261df7bdf Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 9 Sep 2024 15:07:20 +0200 Subject: [PATCH 18/34] chore: merge main into dev/arcsession (#1378) * Fix bug with QueryTarget ALL_COMPLETE in clients and peers (#1358) * Fix bug with QueryTarget ALL_COMPLETE in clients and peers * Fix BEST_MATCHING queryable selection * Properly fix Query targeting in non writer side filtering situations * Improve fix * Update zenoh/src/net/routing/hat/linkstate_peer/queries.rs Co-authored-by: Joseph Perez * Update zenoh/src/net/routing/hat/p2p_peer/queries.rs Co-authored-by: Joseph Perez * Update zenoh/src/net/routing/hat/router/queries.rs Co-authored-by: Joseph Perez * Update zenoh/src/net/routing/hat/client/queries.rs Co-authored-by: Joseph Perez * Remove non used ordered-float dependency --------- Co-authored-by: Luca Cominardi Co-authored-by: Joseph Perez * fix: publisher should not be clonable (#1370) * made builder traits internal (#1376) * scaffolding macro added * builder traits made internal * doc corrected * cargo fmt * typo fix * typo fix * Fix bugs querying liveliness tokens (#1374) * Fix bug in liveliness get in client * Fix bug treating token interests replies from routers in peers * Peers propagate current token interests to remote peers with unfinalize initial declarations push * Don't register current interests declaration replies * Add comments * Add comments * Add comments --------- Co-authored-by: OlivierHecart Co-authored-by: Luca Cominardi Co-authored-by: Michael Ilyin --- Cargo.lock | 10 --- commons/zenoh-macros/src/lib.rs | 80 ++++++++++++++++++- .../zenoh-plugin-rest/examples/z_serve_sse.rs | 6 +- plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../src/replica/aligner.rs | 1 - .../src/replica/storage.rs | 3 +- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/Cargo.toml | 1 - zenoh/src/api/builders/publisher.rs | 11 ++- zenoh/src/api/builders/sample.rs | 4 + zenoh/src/api/publisher.rs | 2 +- zenoh/src/api/query.rs | 6 +- zenoh/src/api/queryable.rs | 4 + zenoh/src/lib.rs | 9 ++- zenoh/src/net/routing/dispatcher/queries.rs | 9 +-- zenoh/src/net/routing/dispatcher/resource.rs | 3 +- zenoh/src/net/routing/hat/client/queries.rs | 16 ++-- zenoh/src/net/routing/hat/client/token.rs | 9 +-- .../net/routing/hat/linkstate_peer/queries.rs | 23 +++--- .../src/net/routing/hat/p2p_peer/interests.rs | 15 ++-- zenoh/src/net/routing/hat/p2p_peer/mod.rs | 17 +++- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 10 +-- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 27 +++---- zenoh/src/net/routing/hat/p2p_peer/token.rs | 31 +++++-- zenoh/src/net/routing/hat/router/queries.rs | 23 +++--- zenoh/src/net/runtime/adminspace.rs | 1 - zenoh/src/prelude.rs | 10 +-- 27 files changed, 206 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aac8c0c10f..7c140c1c31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2587,15 +2587,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered-float" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a91171844676f8c7990ce64959210cd2eaef32c2612c50f9fae9f8aaa6065a6" -dependencies = [ - "num-traits", -] - [[package]] name = "overload" version = "0.1.1" @@ -5343,7 +5334,6 @@ dependencies = [ "itertools 0.13.0", "lazy_static", "once_cell", - "ordered-float", "paste", "petgraph", "phf", diff --git a/commons/zenoh-macros/src/lib.rs b/commons/zenoh-macros/src/lib.rs index 003525daa9..f3533a6aea 100644 --- a/commons/zenoh-macros/src/lib.rs +++ b/commons/zenoh-macros/src/lib.rs @@ -19,7 +19,7 @@ //! [Click here for Zenoh's documentation](../zenoh/index.html) use proc_macro::TokenStream; use quote::{quote, ToTokens}; -use syn::{parse_macro_input, parse_quote, Attribute, Error, Item, LitStr, TraitItem}; +use syn::{parse_macro_input, parse_quote, Attribute, Error, Item, ItemImpl, LitStr, TraitItem}; use zenoh_keyexpr::{ format::{ macro_support::{self, SegmentBuilder}, @@ -522,3 +522,81 @@ pub fn register_param(input: proc_macro::TokenStream) -> proc_macro::TokenStream .unwrap_or_else(syn::Error::into_compile_error) .into() } + +/// Macro `#[internal_trait]` should precede +/// `impl Trait for Struct { ... }` +/// +/// This macro wraps the implementations of "internal" tratis. +/// +/// These traits are used to group set of functions which should be implemented +/// together and with the same portotyoe. E.g. `QoSBuilderTrait` provides set of +/// setters (`congestion_control`, `priority`, `express`) and we should not +/// forget to implement all these setters for each entity which supports +/// QoS functionality. +/// +/// The traits mechanism is a good way to group functions. But additional traits +/// adds extra burden to end user who have to import it every time. +/// +/// The macro `internal_trait` solves this problem by adding +/// methods with same names as in trait to structure implementation itself, +/// making them available to user without additional trait import. +/// +#[proc_macro_attribute] +pub fn internal_trait(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as ItemImpl); + let trait_path = &input.trait_.as_ref().unwrap().1; + let struct_path = &input.self_ty; + let generics = &input.generics; + // let struct_lifetime = get_type_path_lifetime(struct_path); + + let mut struct_methods = quote! {}; + for item_fn in input.items.iter() { + if let syn::ImplItem::Fn(method) = item_fn { + let method_name = &method.sig.ident; + let method_generic_params = &method.sig.generics.params; + let method_generic_params = if method_generic_params.is_empty() { + quote! {} + } else { + quote! {<#method_generic_params>} + }; + let method_args = &method.sig.inputs; + let method_output = &method.sig.output; + let where_clause = &method.sig.generics.where_clause; + let mut method_call_args = quote! {}; + for arg in method_args.iter() { + match arg { + syn::FnArg::Receiver(_) => { + method_call_args.extend(quote! { self, }); + } + syn::FnArg::Typed(pat_type) => { + let pat = &pat_type.pat; + method_call_args.extend(quote! { #pat, }); + } + } + } + let mut attributes = quote! {}; + for attr in &method.attrs { + attributes.extend(quote! { + #attr + }); + } + // call corresponding trait method from struct method + struct_methods.extend(quote! { + #attributes + pub fn #method_name #method_generic_params (#method_args) #method_output #where_clause { + <#struct_path as #trait_path>::#method_name(#method_call_args) + } + }); + } + } + let struct_methods_output = quote! { + impl #generics #struct_path { + #struct_methods + } + }; + (quote! { + #input + #struct_methods_output + }) + .into() +} diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index fbd0269498..049e2756fb 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -14,11 +14,7 @@ use std::time::Duration; use clap::{arg, Command}; -use zenoh::{ - config::Config, - key_expr::keyexpr, - qos::{CongestionControl, QoSBuilderTrait}, -}; +use zenoh::{config::Config, key_expr::keyexpr, qos::CongestionControl}; const HTML: &str = r#"
diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index 289fc9e055..4b236e5d5a 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -53,7 +53,7 @@ use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginCont mod config; pub use config::Config; -use zenoh::{bytes::EncodingBuilderTrait, query::ReplyError}; +use zenoh::query::ReplyError; const GIT_VERSION: &str = git_version::git_version!(prefix = "v", cargo_prefix = "v"); lazy_static::lazy_static! { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index 952a72f499..cf38fe4728 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -24,7 +24,6 @@ use tokio::sync::RwLock; use zenoh::{ internal::Value, key_expr::{KeyExpr, OwnedKeyExpr}, - prelude::*, query::Selector, sample::{Sample, SampleBuilder}, time::Timestamp, diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 94e9d85d82..5ffccbbd54 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -23,7 +23,6 @@ use flume::{Receiver, Sender}; use futures::select; use tokio::sync::{Mutex, RwLock}; use zenoh::{ - bytes::EncodingBuilderTrait, internal::{ buffers::{SplitBuffer, ZBuf}, zenoh_home, Timed, TimedEvent, Timer, Value, @@ -35,7 +34,7 @@ use zenoh::{ KeyExpr, OwnedKeyExpr, }, query::{ConsolidationMode, QueryTarget}, - sample::{Sample, SampleBuilder, SampleKind, TimestampBuilderTrait}, + sample::{Sample, SampleBuilder, SampleKind}, session::Session, time::{Timestamp, NTP64}, }; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 893cbcbad0..c8a41b4e0a 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -27,7 +27,7 @@ use zenoh::{ prelude::Wait, pubsub::{Reliability, Subscriber}, query::{QueryConsolidation, QueryTarget, ReplyKeyExpr, Selector}, - sample::{Locality, Sample, SampleBuilder, TimestampBuilderTrait}, + sample::{Locality, Sample, SampleBuilder}, time::Timestamp, Error, Resolvable, Resolve, Result as ZResult, Session, }; diff --git a/zenoh/Cargo.toml b/zenoh/Cargo.toml index 701c22039a..32622509b5 100644 --- a/zenoh/Cargo.toml +++ b/zenoh/Cargo.toml @@ -77,7 +77,6 @@ git-version = { workspace = true } itertools = { workspace = true } lazy_static = { workspace = true } tracing = { workspace = true } -ordered-float = { workspace = true } paste = { workspace = true } petgraph = { workspace = true } phf = { workspace = true } diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index 53c32c8a7d..4b0c3d8459 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -18,13 +18,12 @@ use zenoh_core::{Resolvable, Result as ZResult, Wait}; use zenoh_protocol::core::Reliability; use zenoh_protocol::{core::CongestionControl, network::Mapping}; +use super::sample::TimestampBuilderTrait; #[cfg(feature = "unstable")] use crate::api::sample::SourceInfo; use crate::{ api::{ - builders::sample::{ - EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, - }, + builders::sample::{EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait}, bytes::{OptionZBytes, ZBytes}, encoding::Encoding, key_expr::KeyExpr, @@ -82,6 +81,7 @@ pub struct PublicationBuilder { pub(crate) attachment: Option, } +#[zenoh_macros::internal_trait] impl QoSBuilderTrait for PublicationBuilder, T> { #[inline] fn congestion_control(self, congestion_control: CongestionControl) -> Self { @@ -128,6 +128,7 @@ impl PublicationBuilder, T> { } } +#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for PublisherBuilder<'_, '_> { fn encoding>(self, encoding: T) -> Self { Self { @@ -137,6 +138,7 @@ impl EncodingBuilderTrait for PublisherBuilder<'_, '_> { } } +#[zenoh_macros::internal_trait] impl

EncodingBuilderTrait for PublicationBuilder { fn encoding>(self, encoding: T) -> Self { Self { @@ -149,6 +151,7 @@ impl

EncodingBuilderTrait for PublicationBuilder { } } +#[zenoh_macros::internal_trait] impl SampleBuilderTrait for PublicationBuilder { #[cfg(feature = "unstable")] fn source_info(self, source_info: SourceInfo) -> Self { @@ -166,6 +169,7 @@ impl SampleBuilderTrait for PublicationBuilder { } } +#[zenoh_macros::internal_trait] impl TimestampBuilderTrait for PublicationBuilder { fn timestamp>>(self, timestamp: TS) -> Self { Self { @@ -278,6 +282,7 @@ impl<'a, 'b> Clone for PublisherBuilder<'a, 'b> { } } +#[zenoh_macros::internal_trait] impl QoSBuilderTrait for PublisherBuilder<'_, '_> { /// Change the `congestion_control` to apply when routing the data. #[inline] diff --git a/zenoh/src/api/builders/sample.rs b/zenoh/src/api/builders/sample.rs index 4c1fa81406..cb7ada9e4f 100644 --- a/zenoh/src/api/builders/sample.rs +++ b/zenoh/src/api/builders/sample.rs @@ -166,6 +166,7 @@ impl SampleBuilder { } } +#[zenoh_macros::internal_trait] impl TimestampBuilderTrait for SampleBuilder { fn timestamp>>(self, timestamp: U) -> Self { Self { @@ -178,6 +179,7 @@ impl TimestampBuilderTrait for SampleBuilder { } } +#[zenoh_macros::internal_trait] impl SampleBuilderTrait for SampleBuilder { #[zenoh_macros::unstable] fn source_info(self, source_info: SourceInfo) -> Self { @@ -202,6 +204,7 @@ impl SampleBuilderTrait for SampleBuilder { } } +#[zenoh_macros::internal_trait] impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { let qos: QoSBuilder = self.sample.qos.into(); @@ -229,6 +232,7 @@ impl QoSBuilderTrait for SampleBuilder { } } +#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for SampleBuilder { fn encoding>(self, encoding: T) -> Self { Self { diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index a8ce4e5569..faa2e4eca6 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -106,7 +106,7 @@ impl fmt::Debug for PublisherState { /// subscriber.stream().map(Ok).forward(publisher).await.unwrap(); /// # } /// ``` -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Publisher<'a> { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, diff --git a/zenoh/src/api/query.rs b/zenoh/src/api/query.rs index bea028ff97..177ca565a1 100644 --- a/zenoh/src/api/query.rs +++ b/zenoh/src/api/query.rs @@ -28,7 +28,7 @@ use zenoh_protocol::core::{CongestionControl, Parameters}; use zenoh_result::ZResult; use super::{ - builders::sample::{EncodingBuilderTrait, QoSBuilderTrait}, + builders::sample::{EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait}, bytes::ZBytes, encoding::Encoding, handlers::{locked, Callback, DefaultHandler, IntoHandler}, @@ -41,7 +41,7 @@ use super::{ }; #[cfg(feature = "unstable")] use super::{sample::SourceInfo, selector::ZenohParameters}; -use crate::{bytes::OptionZBytes, sample::SampleBuilderTrait}; +use crate::bytes::OptionZBytes; /// The [`Queryable`](crate::query::Queryable)s that should be target of a [`get`](Session::get). pub type QueryTarget = zenoh_protocol::network::request::ext::TargetType; @@ -209,6 +209,7 @@ pub struct SessionGetBuilder<'a, 'b, Handler> { pub(crate) source_info: SourceInfo, } +#[zenoh_macros::internal_trait] impl SampleBuilderTrait for SessionGetBuilder<'_, '_, Handler> { #[zenoh_macros::unstable] fn source_info(self, source_info: SourceInfo) -> Self { @@ -244,6 +245,7 @@ impl QoSBuilderTrait for SessionGetBuilder<'_, '_, DefaultHandler> { } } +#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for SessionGetBuilder<'_, '_, Handler> { fn encoding>(self, encoding: T) -> Self { let mut value = self.value.unwrap_or_default(); diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index a1ac14b5f1..a04662dd8f 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -304,6 +304,7 @@ pub struct ReplyBuilder<'a, 'b, T> { attachment: Option, } +#[zenoh_macros::internal_trait] impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { fn timestamp>>(self, timestamp: U) -> Self { Self { @@ -313,6 +314,7 @@ impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { } } +#[zenoh_macros::internal_trait] impl SampleBuilderTrait for ReplyBuilder<'_, '_, T> { fn attachment>(self, attachment: U) -> Self { let attachment: OptionZBytes = attachment.into(); @@ -348,6 +350,7 @@ impl QoSBuilderTrait for ReplyBuilder<'_, '_, T> { } } +#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for ReplyBuilder<'_, '_, ReplyBuilderPut> { fn encoding>(self, encoding: T) -> Self { Self { @@ -471,6 +474,7 @@ pub struct ReplyErrBuilder<'a> { value: Value, } +#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for ReplyErrBuilder<'_> { fn encoding>(self, encoding: T) -> Self { let mut value = self.value.clone(); diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index 6a15afe150..d650ddb05d 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -210,7 +210,6 @@ pub mod sample { pub use crate::api::{ builders::sample::{ SampleBuilder, SampleBuilderAny, SampleBuilderDelete, SampleBuilderPut, - SampleBuilderTrait, TimestampBuilderTrait, }, sample::{Sample, SampleFields, SampleKind, SourceSn}, }; @@ -219,7 +218,6 @@ pub mod sample { /// Payload primitives pub mod bytes { pub use crate::api::{ - builders::sample::EncodingBuilderTrait, bytes::{ Deserialize, OptionZBytes, Serialize, ZBytes, ZBytesIterator, ZBytesReader, ZBytesSliceIterator, ZBytesWriter, ZDeserializeError, ZSerde, @@ -279,7 +277,7 @@ pub mod handlers { pub mod qos { pub use zenoh_protocol::core::CongestionControl; - pub use crate::api::{builders::sample::QoSBuilderTrait, publisher::Priority}; + pub use crate::api::publisher::Priority; } /// Scouting primitives @@ -374,6 +372,11 @@ compile_error!( #[zenoh_macros::internal] pub mod internal { + pub mod traits { + pub use crate::api::builders::sample::{ + EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, + }; + } pub use zenoh_core::{ zasync_executor_init, zasynclock, zerror, zlock, zread, ztimeout, zwrite, ResolveFuture, }; diff --git a/zenoh/src/net/routing/dispatcher/queries.rs b/zenoh/src/net/routing/dispatcher/queries.rs index c117bd51df..7d1287beeb 100644 --- a/zenoh/src/net/routing/dispatcher/queries.rs +++ b/zenoh/src/net/routing/dispatcher/queries.rs @@ -327,7 +327,7 @@ fn compute_final_route( TargetType::AllComplete => { let mut route = HashMap::new(); for qabl in qabls.iter() { - if qabl.complete > 0 + if qabl.info.map(|info| info.complete).unwrap_or(true) && tables .hat_code .egress_filter(tables, src_face, &qabl.direction.0, expr) @@ -342,10 +342,9 @@ fn compute_final_route( route } TargetType::BestMatching => { - if let Some(qabl) = qabls - .iter() - .find(|qabl| qabl.direction.0.id != src_face.id && qabl.complete > 0) - { + if let Some(qabl) = qabls.iter().find(|qabl| { + qabl.direction.0.id != src_face.id && qabl.info.is_some_and(|info| info.complete) + }) { let mut route = HashMap::new(); let mut direction = qabl.direction.clone(); diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index ab84241666..1636d192c4 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -46,8 +46,7 @@ pub(crate) type Route = HashMap; pub(crate) type QueryRoute = HashMap; pub(crate) struct QueryTargetQabl { pub(crate) direction: Direction, - pub(crate) complete: u64, - pub(crate) distance: f64, + pub(crate) info: Option, } pub(crate) type QueryTargetQablSet = Vec; diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index e711ccf2e8..cd417ef84b 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -17,7 +17,6 @@ use std::{ sync::{atomic::Ordering, Arc}, }; -use ordered_float::OrderedFloat; use zenoh_protocol::{ core::{ key_expr::{ @@ -354,8 +353,7 @@ impl HatQueriesTrait for HatCode { 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, + info: None, }); } } @@ -375,17 +373,15 @@ impl HatQueriesTrait for HatCode { if let Some(qabl_info) = context.qabl.as_ref() { route.push(QueryTargetQabl { direction: (context.face.clone(), key_expr.to_owned(), NodeId::default()), - complete: if complete { - qabl_info.complete as u64 - } else { - 0 - }, - distance: 0.5, + info: Some(QueryableInfoType { + complete: complete && qabl_info.complete, + distance: 1, + }), }); } } } - route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); + route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); Arc::new(route) } diff --git a/zenoh/src/net/routing/hat/client/token.rs b/zenoh/src/net/routing/hat/client/token.rs index 9e5923425c..5014ee5931 100644 --- a/zenoh/src/net/routing/hat/client/token.rs +++ b/zenoh/src/net/routing/hat/client/token.rs @@ -116,13 +116,9 @@ fn declare_simple_token( interest_id: Option, send_declare: &mut SendDeclare, ) { - register_simple_token(tables, face, id, res); - - propagate_simple_token(tables, res, face, send_declare); - - let wire_expr = Resource::decl_key(res, face, true); if let Some(interest_id) = interest_id { if let Some((interest, _)) = face.pending_current_interests.get(&interest_id) { + let wire_expr = Resource::get_best_key(res, "", interest.src_face.id); send_declare( &interest.src_face.primitives, RoutingContext::with_expr( @@ -137,6 +133,9 @@ fn declare_simple_token( ), ) } + } else { + register_simple_token(tables, face, id, res); + propagate_simple_token(tables, res, face, send_declare); } } diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index 6941466571..ce97803532 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -17,7 +17,6 @@ use std::{ sync::{atomic::Ordering, Arc}, }; -use ordered_float::OrderedFloat; use petgraph::graph::NodeIndex; use zenoh_protocol::{ core::{ @@ -718,12 +717,10 @@ fn insert_target_for_qabls( Resource::get_best_key(expr.prefix, expr.suffix, face.id); route.push(QueryTargetQabl { direction: (face.clone(), key_expr.to_owned(), source), - complete: if complete { - qabl_info.complete as u64 - } else { - 0 - }, - distance: net.distances[qabl_idx.index()], + info: Some(QueryableInfoType { + complete: complete && qabl_info.complete, + distance: net.distances[qabl_idx.index()] as u16, + }), }); } } @@ -1000,18 +997,16 @@ impl HatQueriesTrait for HatCode { key_expr.to_owned(), NodeId::default(), ), - complete: if complete { - qabl_info.complete as u64 - } else { - 0 - }, - distance: 0.5, + info: Some(QueryableInfoType { + complete: complete && qabl_info.complete, + distance: 1, + }), }); } } } } - route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); + route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); Arc::new(route) } diff --git a/zenoh/src/net/routing/hat/p2p_peer/interests.rs b/zenoh/src/net/routing/hat/p2p_peer/interests.rs index 2ed9e22840..3fa2bbe193 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/interests.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/interests.rs @@ -24,8 +24,8 @@ use zenoh_protocol::{ use zenoh_sync::get_mut_unchecked; use super::{ - face_hat, face_hat_mut, pubsub::declare_sub_interest, queries::declare_qabl_interest, - token::declare_token_interest, HatCode, HatFace, + face_hat, face_hat_mut, initial_interest, pubsub::declare_sub_interest, + queries::declare_qabl_interest, token::declare_token_interest, HatCode, HatFace, }; use crate::net::routing::{ dispatcher::{ @@ -132,11 +132,12 @@ impl HatInterestTrait for HatCode { src_interest_id: id, }); - for dst_face in tables - .faces - .values_mut() - .filter(|f| f.whatami == WhatAmI::Router) - { + for dst_face in tables.faces.values_mut().filter(|f| { + f.whatami == WhatAmI::Router + || (options.tokens() + && f.whatami == WhatAmI::Peer + && !initial_interest(f).map(|i| i.finalized).unwrap_or(true)) + }) { let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); get_mut_unchecked(dst_face).local_interests.insert( id, diff --git a/zenoh/src/net/routing/hat/p2p_peer/mod.rs b/zenoh/src/net/routing/hat/p2p_peer/mod.rs index 21737326e4..e68c2232fc 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/mod.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/mod.rs @@ -172,7 +172,7 @@ impl HatBaseTrait for HatCode { } if face.state.whatami == WhatAmI::Peer { get_mut_unchecked(&mut face.state).local_interests.insert( - 0, + INITIAL_INTEREST_ID, InterestState { options: InterestOptions::ALL, res: None, @@ -418,7 +418,7 @@ struct HatFace { impl HatFace { fn new() -> Self { Self { - next_id: AtomicU32::new(0), + next_id: AtomicU32::new(1), // In p2p, id 0 is erserved for initial interest remote_interests: HashMap::new(), local_subs: HashMap::new(), remote_subs: HashMap::new(), @@ -440,3 +440,16 @@ fn get_routes_entries() -> RoutesIndexes { clients: vec![0], } } + +// In p2p, at connection, while no interest is sent on the network, +// peers act as if they received an interest CurrentFuture with id 0 +// and send back a DeclareFinal with interest_id 0. +// This 'ghost' interest is registered locally to allow tracking if +// the DeclareFinal has been received or not (finalized). + +const INITIAL_INTEREST_ID: u32 = 0; + +#[inline] +fn initial_interest(face: &FaceState) -> Option<&InterestState> { + face.local_interests.get(&INITIAL_INTEREST_ID) +} diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 0dccf9ba3c..31336bc516 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -38,7 +38,9 @@ use crate::{ resource::{NodeId, Resource, SessionContext}, tables::{Route, RoutingExpr, Tables}, }, - hat::{CurrentFutureTrait, HatPubSubTrait, SendDeclare, Sources}, + hat::{ + p2p_peer::initial_interest, CurrentFutureTrait, HatPubSubTrait, SendDeclare, Sources, + }, router::{update_data_routes_from, RoutesIndexes}, RoutingContext, }, @@ -654,11 +656,7 @@ impl HatPubSubTrait for HatCode { for face in tables.faces.values().filter(|f| { f.whatami == WhatAmI::Peer - && !f - .local_interests - .get(&0) - .map(|i| i.finalized) - .unwrap_or(true) + && !initial_interest(f).map(|i| i.finalized).unwrap_or(true) }) { route.entry(face.id).or_insert_with(|| { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index 2fd6d6fa81..4a46ec6e85 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -17,7 +17,6 @@ use std::{ sync::{atomic::Ordering, Arc}, }; -use ordered_float::OrderedFloat; use zenoh_protocol::{ core::{ key_expr::{ @@ -43,7 +42,7 @@ use crate::net::routing::{ resource::{NodeId, Resource, SessionContext}, tables::{QueryTargetQabl, QueryTargetQablSet, RoutingExpr, Tables}, }, - hat::{CurrentFutureTrait, HatQueriesTrait, SendDeclare, Sources}, + hat::{p2p_peer::initial_interest, CurrentFutureTrait, HatQueriesTrait, SendDeclare, Sources}, router::{update_query_routes_from, RoutesIndexes}, RoutingContext, }; @@ -597,24 +596,18 @@ impl HatQueriesTrait for HatCode { 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, + info: None, }); } for face in tables.faces.values().filter(|f| { f.whatami == WhatAmI::Peer - && !f - .local_interests - .get(&0) - .map(|i| i.finalized) - .unwrap_or(true) + && !initial_interest(f).map(|i| i.finalized).unwrap_or(true) }) { 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: 0.5, + info: None, }); } } @@ -639,18 +632,16 @@ impl HatQueriesTrait for HatCode { key_expr.to_owned(), NodeId::default(), ), - complete: if complete { - qabl_info.complete as u64 - } else { - 0 - }, - distance: 0.5, + info: Some(QueryableInfoType { + complete: complete && qabl_info.complete, + distance: 1, + }), }); } } } } - route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); + route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); Arc::new(route) } diff --git a/zenoh/src/net/routing/hat/p2p_peer/token.rs b/zenoh/src/net/routing/hat/p2p_peer/token.rs index 866737f0df..a06b06f7e2 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/token.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/token.rs @@ -152,11 +152,30 @@ fn declare_simple_token( face: &mut Arc, id: TokenId, res: &mut Arc, + interest_id: Option, send_declare: &mut SendDeclare, ) { - register_simple_token(tables, face, id, res); - - propagate_simple_token(tables, res, face, send_declare); + if let Some(interest_id) = interest_id { + if let Some((interest, _)) = face.pending_current_interests.get(&interest_id) { + let wire_expr = Resource::get_best_key(res, "", interest.src_face.id); + send_declare( + &interest.src_face.primitives, + RoutingContext::with_expr( + Declare { + interest_id: Some(interest.src_interest_id), + ext_qos: ext::QoSType::default(), + ext_tstamp: None, + ext_nodeid: ext::NodeIdType::default(), + body: DeclareBody::DeclareToken(DeclareToken { id, wire_expr }), + }, + res.expr(), + ), + ) + } + } else { + register_simple_token(tables, face, id, res); + propagate_simple_token(tables, res, face, send_declare); + } } #[inline] @@ -411,7 +430,7 @@ pub(crate) fn declare_token_interest( aggregate: bool, send_declare: &mut SendDeclare, ) { - if mode.current() && face.whatami == WhatAmI::Client { + if mode.current() { let interest_id = (!mode.future()).then_some(id); if let Some(res) = res.as_ref() { if aggregate { @@ -525,10 +544,10 @@ impl HatTokenTrait for HatCode { id: TokenId, res: &mut Arc, _node_id: NodeId, - _interest_id: Option, + interest_id: Option, send_declare: &mut SendDeclare, ) { - declare_simple_token(tables, face, id, res, send_declare) + declare_simple_token(tables, face, id, res, interest_id, send_declare) } fn undeclare_token( diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index f45a260288..969d94f3a2 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -17,7 +17,6 @@ use std::{ sync::{atomic::Ordering, Arc}, }; -use ordered_float::OrderedFloat; use petgraph::graph::NodeIndex; use zenoh_protocol::{ core::{ @@ -1102,12 +1101,10 @@ fn insert_target_for_qabls( Resource::get_best_key(expr.prefix, expr.suffix, face.id); route.push(QueryTargetQabl { direction: (face.clone(), key_expr.to_owned(), source), - complete: if complete { - qabl_info.complete as u64 - } else { - 0 - }, - distance: net.distances[qabl_idx.index()], + info: Some(QueryableInfoType { + complete: complete && qabl_info.complete, + distance: net.distances[qabl_idx.index()] as u16, + }), }); } } @@ -1482,19 +1479,17 @@ impl HatQueriesTrait for HatCode { key_expr.to_owned(), NodeId::default(), ), - complete: if complete { - qabl_info.complete as u64 - } else { - 0 - }, - distance: 0.5, + info: Some(QueryableInfoType { + complete: complete && qabl_info.complete, + distance: 1, + }), }); } } } } } - route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); + route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); Arc::new(route) } diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index d3e2a3c1ad..dc984c2e92 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -44,7 +44,6 @@ use super::{routing::dispatcher::face::Face, Runtime}; use crate::api::plugins::PluginsManager; use crate::{ api::{ - builders::sample::EncodingBuilderTrait, bytes::ZBytes, key_expr::KeyExpr, queryable::{Query, QueryInner}, diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 022a2d63cb..02534af650 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -28,14 +28,8 @@ mod _prelude { #[zenoh_macros::unstable] pub use crate::api::selector::ZenohParameters; pub use crate::{ - api::{ - builders::sample::{ - EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, - }, - session::Undeclarable, - }, - config::ValidatedMap, - Error as ZError, Resolvable, Resolve, Result as ZResult, + api::session::Undeclarable, config::ValidatedMap, Error as ZError, Resolvable, Resolve, + Result as ZResult, }; } From 1c7f5c143a12e14a75128a8466945b6d766beaa1 Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Mon, 9 Sep 2024 15:08:46 +0200 Subject: [PATCH 19/34] Revert "chore: merge main into dev/arcsession (#1378)" (#1379) This reverts commit f3f540320e211c8f720d3e660ac50af261df7bdf. --- Cargo.lock | 10 +++ commons/zenoh-macros/src/lib.rs | 80 +------------------ .../zenoh-plugin-rest/examples/z_serve_sse.rs | 6 +- plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../src/replica/aligner.rs | 1 + .../src/replica/storage.rs | 3 +- zenoh-ext/src/querying_subscriber.rs | 2 +- zenoh/Cargo.toml | 1 + zenoh/src/api/builders/publisher.rs | 11 +-- zenoh/src/api/builders/sample.rs | 4 - zenoh/src/api/publisher.rs | 2 +- zenoh/src/api/query.rs | 6 +- zenoh/src/api/queryable.rs | 4 - zenoh/src/lib.rs | 9 +-- zenoh/src/net/routing/dispatcher/queries.rs | 9 ++- zenoh/src/net/routing/dispatcher/resource.rs | 3 +- zenoh/src/net/routing/hat/client/queries.rs | 16 ++-- zenoh/src/net/routing/hat/client/token.rs | 9 ++- .../net/routing/hat/linkstate_peer/queries.rs | 23 +++--- .../src/net/routing/hat/p2p_peer/interests.rs | 15 ++-- zenoh/src/net/routing/hat/p2p_peer/mod.rs | 17 +--- zenoh/src/net/routing/hat/p2p_peer/pubsub.rs | 10 ++- zenoh/src/net/routing/hat/p2p_peer/queries.rs | 27 ++++--- zenoh/src/net/routing/hat/p2p_peer/token.rs | 31 ++----- zenoh/src/net/routing/hat/router/queries.rs | 23 +++--- zenoh/src/net/runtime/adminspace.rs | 1 + zenoh/src/prelude.rs | 10 ++- 27 files changed, 129 insertions(+), 206 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c140c1c31..aac8c0c10f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2587,6 +2587,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "4.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a91171844676f8c7990ce64959210cd2eaef32c2612c50f9fae9f8aaa6065a6" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" @@ -5334,6 +5343,7 @@ dependencies = [ "itertools 0.13.0", "lazy_static", "once_cell", + "ordered-float", "paste", "petgraph", "phf", diff --git a/commons/zenoh-macros/src/lib.rs b/commons/zenoh-macros/src/lib.rs index f3533a6aea..003525daa9 100644 --- a/commons/zenoh-macros/src/lib.rs +++ b/commons/zenoh-macros/src/lib.rs @@ -19,7 +19,7 @@ //! [Click here for Zenoh's documentation](../zenoh/index.html) use proc_macro::TokenStream; use quote::{quote, ToTokens}; -use syn::{parse_macro_input, parse_quote, Attribute, Error, Item, ItemImpl, LitStr, TraitItem}; +use syn::{parse_macro_input, parse_quote, Attribute, Error, Item, LitStr, TraitItem}; use zenoh_keyexpr::{ format::{ macro_support::{self, SegmentBuilder}, @@ -522,81 +522,3 @@ pub fn register_param(input: proc_macro::TokenStream) -> proc_macro::TokenStream .unwrap_or_else(syn::Error::into_compile_error) .into() } - -/// Macro `#[internal_trait]` should precede -/// `impl Trait for Struct { ... }` -/// -/// This macro wraps the implementations of "internal" tratis. -/// -/// These traits are used to group set of functions which should be implemented -/// together and with the same portotyoe. E.g. `QoSBuilderTrait` provides set of -/// setters (`congestion_control`, `priority`, `express`) and we should not -/// forget to implement all these setters for each entity which supports -/// QoS functionality. -/// -/// The traits mechanism is a good way to group functions. But additional traits -/// adds extra burden to end user who have to import it every time. -/// -/// The macro `internal_trait` solves this problem by adding -/// methods with same names as in trait to structure implementation itself, -/// making them available to user without additional trait import. -/// -#[proc_macro_attribute] -pub fn internal_trait(_attr: TokenStream, item: TokenStream) -> TokenStream { - let input = parse_macro_input!(item as ItemImpl); - let trait_path = &input.trait_.as_ref().unwrap().1; - let struct_path = &input.self_ty; - let generics = &input.generics; - // let struct_lifetime = get_type_path_lifetime(struct_path); - - let mut struct_methods = quote! {}; - for item_fn in input.items.iter() { - if let syn::ImplItem::Fn(method) = item_fn { - let method_name = &method.sig.ident; - let method_generic_params = &method.sig.generics.params; - let method_generic_params = if method_generic_params.is_empty() { - quote! {} - } else { - quote! {<#method_generic_params>} - }; - let method_args = &method.sig.inputs; - let method_output = &method.sig.output; - let where_clause = &method.sig.generics.where_clause; - let mut method_call_args = quote! {}; - for arg in method_args.iter() { - match arg { - syn::FnArg::Receiver(_) => { - method_call_args.extend(quote! { self, }); - } - syn::FnArg::Typed(pat_type) => { - let pat = &pat_type.pat; - method_call_args.extend(quote! { #pat, }); - } - } - } - let mut attributes = quote! {}; - for attr in &method.attrs { - attributes.extend(quote! { - #attr - }); - } - // call corresponding trait method from struct method - struct_methods.extend(quote! { - #attributes - pub fn #method_name #method_generic_params (#method_args) #method_output #where_clause { - <#struct_path as #trait_path>::#method_name(#method_call_args) - } - }); - } - } - let struct_methods_output = quote! { - impl #generics #struct_path { - #struct_methods - } - }; - (quote! { - #input - #struct_methods_output - }) - .into() -} diff --git a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs index 049e2756fb..fbd0269498 100644 --- a/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs +++ b/plugins/zenoh-plugin-rest/examples/z_serve_sse.rs @@ -14,7 +14,11 @@ use std::time::Duration; use clap::{arg, Command}; -use zenoh::{config::Config, key_expr::keyexpr, qos::CongestionControl}; +use zenoh::{ + config::Config, + key_expr::keyexpr, + qos::{CongestionControl, QoSBuilderTrait}, +}; const HTML: &str = r#"

diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index 4b236e5d5a..289fc9e055 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -53,7 +53,7 @@ use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginCont mod config; pub use config::Config; -use zenoh::query::ReplyError; +use zenoh::{bytes::EncodingBuilderTrait, query::ReplyError}; const GIT_VERSION: &str = git_version::git_version!(prefix = "v", cargo_prefix = "v"); lazy_static::lazy_static! { diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs index cf38fe4728..952a72f499 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/aligner.rs @@ -24,6 +24,7 @@ use tokio::sync::RwLock; use zenoh::{ internal::Value, key_expr::{KeyExpr, OwnedKeyExpr}, + prelude::*, query::Selector, sample::{Sample, SampleBuilder}, time::Timestamp, diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs index 5ffccbbd54..94e9d85d82 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/storage.rs @@ -23,6 +23,7 @@ use flume::{Receiver, Sender}; use futures::select; use tokio::sync::{Mutex, RwLock}; use zenoh::{ + bytes::EncodingBuilderTrait, internal::{ buffers::{SplitBuffer, ZBuf}, zenoh_home, Timed, TimedEvent, Timer, Value, @@ -34,7 +35,7 @@ use zenoh::{ KeyExpr, OwnedKeyExpr, }, query::{ConsolidationMode, QueryTarget}, - sample::{Sample, SampleBuilder, SampleKind}, + sample::{Sample, SampleBuilder, SampleKind, TimestampBuilderTrait}, session::Session, time::{Timestamp, NTP64}, }; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index c8a41b4e0a..893cbcbad0 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -27,7 +27,7 @@ use zenoh::{ prelude::Wait, pubsub::{Reliability, Subscriber}, query::{QueryConsolidation, QueryTarget, ReplyKeyExpr, Selector}, - sample::{Locality, Sample, SampleBuilder}, + sample::{Locality, Sample, SampleBuilder, TimestampBuilderTrait}, time::Timestamp, Error, Resolvable, Resolve, Result as ZResult, Session, }; diff --git a/zenoh/Cargo.toml b/zenoh/Cargo.toml index 32622509b5..701c22039a 100644 --- a/zenoh/Cargo.toml +++ b/zenoh/Cargo.toml @@ -77,6 +77,7 @@ git-version = { workspace = true } itertools = { workspace = true } lazy_static = { workspace = true } tracing = { workspace = true } +ordered-float = { workspace = true } paste = { workspace = true } petgraph = { workspace = true } phf = { workspace = true } diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index 4b0c3d8459..53c32c8a7d 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -18,12 +18,13 @@ use zenoh_core::{Resolvable, Result as ZResult, Wait}; use zenoh_protocol::core::Reliability; use zenoh_protocol::{core::CongestionControl, network::Mapping}; -use super::sample::TimestampBuilderTrait; #[cfg(feature = "unstable")] use crate::api::sample::SourceInfo; use crate::{ api::{ - builders::sample::{EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait}, + builders::sample::{ + EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, + }, bytes::{OptionZBytes, ZBytes}, encoding::Encoding, key_expr::KeyExpr, @@ -81,7 +82,6 @@ pub struct PublicationBuilder { pub(crate) attachment: Option, } -#[zenoh_macros::internal_trait] impl QoSBuilderTrait for PublicationBuilder, T> { #[inline] fn congestion_control(self, congestion_control: CongestionControl) -> Self { @@ -128,7 +128,6 @@ impl PublicationBuilder, T> { } } -#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for PublisherBuilder<'_, '_> { fn encoding>(self, encoding: T) -> Self { Self { @@ -138,7 +137,6 @@ impl EncodingBuilderTrait for PublisherBuilder<'_, '_> { } } -#[zenoh_macros::internal_trait] impl

EncodingBuilderTrait for PublicationBuilder { fn encoding>(self, encoding: T) -> Self { Self { @@ -151,7 +149,6 @@ impl

EncodingBuilderTrait for PublicationBuilder { } } -#[zenoh_macros::internal_trait] impl SampleBuilderTrait for PublicationBuilder { #[cfg(feature = "unstable")] fn source_info(self, source_info: SourceInfo) -> Self { @@ -169,7 +166,6 @@ impl SampleBuilderTrait for PublicationBuilder { } } -#[zenoh_macros::internal_trait] impl TimestampBuilderTrait for PublicationBuilder { fn timestamp>>(self, timestamp: TS) -> Self { Self { @@ -282,7 +278,6 @@ impl<'a, 'b> Clone for PublisherBuilder<'a, 'b> { } } -#[zenoh_macros::internal_trait] impl QoSBuilderTrait for PublisherBuilder<'_, '_> { /// Change the `congestion_control` to apply when routing the data. #[inline] diff --git a/zenoh/src/api/builders/sample.rs b/zenoh/src/api/builders/sample.rs index cb7ada9e4f..4c1fa81406 100644 --- a/zenoh/src/api/builders/sample.rs +++ b/zenoh/src/api/builders/sample.rs @@ -166,7 +166,6 @@ impl SampleBuilder { } } -#[zenoh_macros::internal_trait] impl TimestampBuilderTrait for SampleBuilder { fn timestamp>>(self, timestamp: U) -> Self { Self { @@ -179,7 +178,6 @@ impl TimestampBuilderTrait for SampleBuilder { } } -#[zenoh_macros::internal_trait] impl SampleBuilderTrait for SampleBuilder { #[zenoh_macros::unstable] fn source_info(self, source_info: SourceInfo) -> Self { @@ -204,7 +202,6 @@ impl SampleBuilderTrait for SampleBuilder { } } -#[zenoh_macros::internal_trait] impl QoSBuilderTrait for SampleBuilder { fn congestion_control(self, congestion_control: CongestionControl) -> Self { let qos: QoSBuilder = self.sample.qos.into(); @@ -232,7 +229,6 @@ impl QoSBuilderTrait for SampleBuilder { } } -#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for SampleBuilder { fn encoding>(self, encoding: T) -> Self { Self { diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index faa2e4eca6..a8ce4e5569 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -106,7 +106,7 @@ impl fmt::Debug for PublisherState { /// subscriber.stream().map(Ok).forward(publisher).await.unwrap(); /// # } /// ``` -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Publisher<'a> { #[cfg(feature = "unstable")] pub(crate) session_id: ZenohId, diff --git a/zenoh/src/api/query.rs b/zenoh/src/api/query.rs index 177ca565a1..bea028ff97 100644 --- a/zenoh/src/api/query.rs +++ b/zenoh/src/api/query.rs @@ -28,7 +28,7 @@ use zenoh_protocol::core::{CongestionControl, Parameters}; use zenoh_result::ZResult; use super::{ - builders::sample::{EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait}, + builders::sample::{EncodingBuilderTrait, QoSBuilderTrait}, bytes::ZBytes, encoding::Encoding, handlers::{locked, Callback, DefaultHandler, IntoHandler}, @@ -41,7 +41,7 @@ use super::{ }; #[cfg(feature = "unstable")] use super::{sample::SourceInfo, selector::ZenohParameters}; -use crate::bytes::OptionZBytes; +use crate::{bytes::OptionZBytes, sample::SampleBuilderTrait}; /// The [`Queryable`](crate::query::Queryable)s that should be target of a [`get`](Session::get). pub type QueryTarget = zenoh_protocol::network::request::ext::TargetType; @@ -209,7 +209,6 @@ pub struct SessionGetBuilder<'a, 'b, Handler> { pub(crate) source_info: SourceInfo, } -#[zenoh_macros::internal_trait] impl SampleBuilderTrait for SessionGetBuilder<'_, '_, Handler> { #[zenoh_macros::unstable] fn source_info(self, source_info: SourceInfo) -> Self { @@ -245,7 +244,6 @@ impl QoSBuilderTrait for SessionGetBuilder<'_, '_, DefaultHandler> { } } -#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for SessionGetBuilder<'_, '_, Handler> { fn encoding>(self, encoding: T) -> Self { let mut value = self.value.unwrap_or_default(); diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index a04662dd8f..a1ac14b5f1 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -304,7 +304,6 @@ pub struct ReplyBuilder<'a, 'b, T> { attachment: Option, } -#[zenoh_macros::internal_trait] impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { fn timestamp>>(self, timestamp: U) -> Self { Self { @@ -314,7 +313,6 @@ impl TimestampBuilderTrait for ReplyBuilder<'_, '_, T> { } } -#[zenoh_macros::internal_trait] impl SampleBuilderTrait for ReplyBuilder<'_, '_, T> { fn attachment>(self, attachment: U) -> Self { let attachment: OptionZBytes = attachment.into(); @@ -350,7 +348,6 @@ impl QoSBuilderTrait for ReplyBuilder<'_, '_, T> { } } -#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for ReplyBuilder<'_, '_, ReplyBuilderPut> { fn encoding>(self, encoding: T) -> Self { Self { @@ -474,7 +471,6 @@ pub struct ReplyErrBuilder<'a> { value: Value, } -#[zenoh_macros::internal_trait] impl EncodingBuilderTrait for ReplyErrBuilder<'_> { fn encoding>(self, encoding: T) -> Self { let mut value = self.value.clone(); diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index d650ddb05d..6a15afe150 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -210,6 +210,7 @@ pub mod sample { pub use crate::api::{ builders::sample::{ SampleBuilder, SampleBuilderAny, SampleBuilderDelete, SampleBuilderPut, + SampleBuilderTrait, TimestampBuilderTrait, }, sample::{Sample, SampleFields, SampleKind, SourceSn}, }; @@ -218,6 +219,7 @@ pub mod sample { /// Payload primitives pub mod bytes { pub use crate::api::{ + builders::sample::EncodingBuilderTrait, bytes::{ Deserialize, OptionZBytes, Serialize, ZBytes, ZBytesIterator, ZBytesReader, ZBytesSliceIterator, ZBytesWriter, ZDeserializeError, ZSerde, @@ -277,7 +279,7 @@ pub mod handlers { pub mod qos { pub use zenoh_protocol::core::CongestionControl; - pub use crate::api::publisher::Priority; + pub use crate::api::{builders::sample::QoSBuilderTrait, publisher::Priority}; } /// Scouting primitives @@ -372,11 +374,6 @@ compile_error!( #[zenoh_macros::internal] pub mod internal { - pub mod traits { - pub use crate::api::builders::sample::{ - EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, - }; - } pub use zenoh_core::{ zasync_executor_init, zasynclock, zerror, zlock, zread, ztimeout, zwrite, ResolveFuture, }; diff --git a/zenoh/src/net/routing/dispatcher/queries.rs b/zenoh/src/net/routing/dispatcher/queries.rs index 7d1287beeb..c117bd51df 100644 --- a/zenoh/src/net/routing/dispatcher/queries.rs +++ b/zenoh/src/net/routing/dispatcher/queries.rs @@ -327,7 +327,7 @@ fn compute_final_route( TargetType::AllComplete => { let mut route = HashMap::new(); for qabl in qabls.iter() { - if qabl.info.map(|info| info.complete).unwrap_or(true) + if qabl.complete > 0 && tables .hat_code .egress_filter(tables, src_face, &qabl.direction.0, expr) @@ -342,9 +342,10 @@ fn compute_final_route( route } TargetType::BestMatching => { - if let Some(qabl) = qabls.iter().find(|qabl| { - qabl.direction.0.id != src_face.id && qabl.info.is_some_and(|info| info.complete) - }) { + if let Some(qabl) = qabls + .iter() + .find(|qabl| qabl.direction.0.id != src_face.id && qabl.complete > 0) + { let mut route = HashMap::new(); let mut direction = qabl.direction.clone(); diff --git a/zenoh/src/net/routing/dispatcher/resource.rs b/zenoh/src/net/routing/dispatcher/resource.rs index 1636d192c4..ab84241666 100644 --- a/zenoh/src/net/routing/dispatcher/resource.rs +++ b/zenoh/src/net/routing/dispatcher/resource.rs @@ -46,7 +46,8 @@ pub(crate) type Route = HashMap; pub(crate) type QueryRoute = HashMap; pub(crate) struct QueryTargetQabl { pub(crate) direction: Direction, - pub(crate) info: Option, + pub(crate) complete: u64, + pub(crate) distance: f64, } pub(crate) type QueryTargetQablSet = Vec; diff --git a/zenoh/src/net/routing/hat/client/queries.rs b/zenoh/src/net/routing/hat/client/queries.rs index cd417ef84b..e711ccf2e8 100644 --- a/zenoh/src/net/routing/hat/client/queries.rs +++ b/zenoh/src/net/routing/hat/client/queries.rs @@ -17,6 +17,7 @@ use std::{ sync::{atomic::Ordering, Arc}, }; +use ordered_float::OrderedFloat; use zenoh_protocol::{ core::{ key_expr::{ @@ -353,7 +354,8 @@ impl HatQueriesTrait for HatCode { 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()), - info: None, + complete: 0, + distance: f64::MAX, }); } } @@ -373,15 +375,17 @@ impl HatQueriesTrait for HatCode { if let Some(qabl_info) = context.qabl.as_ref() { route.push(QueryTargetQabl { direction: (context.face.clone(), key_expr.to_owned(), NodeId::default()), - info: Some(QueryableInfoType { - complete: complete && qabl_info.complete, - distance: 1, - }), + complete: if complete { + qabl_info.complete as u64 + } else { + 0 + }, + distance: 0.5, }); } } } - route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); + route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); Arc::new(route) } diff --git a/zenoh/src/net/routing/hat/client/token.rs b/zenoh/src/net/routing/hat/client/token.rs index 5014ee5931..9e5923425c 100644 --- a/zenoh/src/net/routing/hat/client/token.rs +++ b/zenoh/src/net/routing/hat/client/token.rs @@ -116,9 +116,13 @@ fn declare_simple_token( interest_id: Option, send_declare: &mut SendDeclare, ) { + register_simple_token(tables, face, id, res); + + propagate_simple_token(tables, res, face, send_declare); + + let wire_expr = Resource::decl_key(res, face, true); if let Some(interest_id) = interest_id { if let Some((interest, _)) = face.pending_current_interests.get(&interest_id) { - let wire_expr = Resource::get_best_key(res, "", interest.src_face.id); send_declare( &interest.src_face.primitives, RoutingContext::with_expr( @@ -133,9 +137,6 @@ fn declare_simple_token( ), ) } - } else { - register_simple_token(tables, face, id, res); - propagate_simple_token(tables, res, face, send_declare); } } diff --git a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs index ce97803532..6941466571 100644 --- a/zenoh/src/net/routing/hat/linkstate_peer/queries.rs +++ b/zenoh/src/net/routing/hat/linkstate_peer/queries.rs @@ -17,6 +17,7 @@ use std::{ sync::{atomic::Ordering, Arc}, }; +use ordered_float::OrderedFloat; use petgraph::graph::NodeIndex; use zenoh_protocol::{ core::{ @@ -717,10 +718,12 @@ fn insert_target_for_qabls( Resource::get_best_key(expr.prefix, expr.suffix, face.id); route.push(QueryTargetQabl { direction: (face.clone(), key_expr.to_owned(), source), - info: Some(QueryableInfoType { - complete: complete && qabl_info.complete, - distance: net.distances[qabl_idx.index()] as u16, - }), + complete: if complete { + qabl_info.complete as u64 + } else { + 0 + }, + distance: net.distances[qabl_idx.index()], }); } } @@ -997,16 +1000,18 @@ impl HatQueriesTrait for HatCode { key_expr.to_owned(), NodeId::default(), ), - info: Some(QueryableInfoType { - complete: complete && qabl_info.complete, - distance: 1, - }), + complete: if complete { + qabl_info.complete as u64 + } else { + 0 + }, + distance: 0.5, }); } } } } - route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); + route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); Arc::new(route) } diff --git a/zenoh/src/net/routing/hat/p2p_peer/interests.rs b/zenoh/src/net/routing/hat/p2p_peer/interests.rs index 3fa2bbe193..2ed9e22840 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/interests.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/interests.rs @@ -24,8 +24,8 @@ use zenoh_protocol::{ use zenoh_sync::get_mut_unchecked; use super::{ - face_hat, face_hat_mut, initial_interest, pubsub::declare_sub_interest, - queries::declare_qabl_interest, token::declare_token_interest, HatCode, HatFace, + face_hat, face_hat_mut, pubsub::declare_sub_interest, queries::declare_qabl_interest, + token::declare_token_interest, HatCode, HatFace, }; use crate::net::routing::{ dispatcher::{ @@ -132,12 +132,11 @@ impl HatInterestTrait for HatCode { src_interest_id: id, }); - for dst_face in tables.faces.values_mut().filter(|f| { - f.whatami == WhatAmI::Router - || (options.tokens() - && f.whatami == WhatAmI::Peer - && !initial_interest(f).map(|i| i.finalized).unwrap_or(true)) - }) { + for dst_face in tables + .faces + .values_mut() + .filter(|f| f.whatami == WhatAmI::Router) + { let id = face_hat!(dst_face).next_id.fetch_add(1, Ordering::SeqCst); get_mut_unchecked(dst_face).local_interests.insert( id, diff --git a/zenoh/src/net/routing/hat/p2p_peer/mod.rs b/zenoh/src/net/routing/hat/p2p_peer/mod.rs index e68c2232fc..21737326e4 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/mod.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/mod.rs @@ -172,7 +172,7 @@ impl HatBaseTrait for HatCode { } if face.state.whatami == WhatAmI::Peer { get_mut_unchecked(&mut face.state).local_interests.insert( - INITIAL_INTEREST_ID, + 0, InterestState { options: InterestOptions::ALL, res: None, @@ -418,7 +418,7 @@ struct HatFace { impl HatFace { fn new() -> Self { Self { - next_id: AtomicU32::new(1), // In p2p, id 0 is erserved for initial interest + next_id: AtomicU32::new(0), remote_interests: HashMap::new(), local_subs: HashMap::new(), remote_subs: HashMap::new(), @@ -440,16 +440,3 @@ fn get_routes_entries() -> RoutesIndexes { clients: vec![0], } } - -// In p2p, at connection, while no interest is sent on the network, -// peers act as if they received an interest CurrentFuture with id 0 -// and send back a DeclareFinal with interest_id 0. -// This 'ghost' interest is registered locally to allow tracking if -// the DeclareFinal has been received or not (finalized). - -const INITIAL_INTEREST_ID: u32 = 0; - -#[inline] -fn initial_interest(face: &FaceState) -> Option<&InterestState> { - face.local_interests.get(&INITIAL_INTEREST_ID) -} diff --git a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs index 31336bc516..0dccf9ba3c 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/pubsub.rs @@ -38,9 +38,7 @@ use crate::{ resource::{NodeId, Resource, SessionContext}, tables::{Route, RoutingExpr, Tables}, }, - hat::{ - p2p_peer::initial_interest, CurrentFutureTrait, HatPubSubTrait, SendDeclare, Sources, - }, + hat::{CurrentFutureTrait, HatPubSubTrait, SendDeclare, Sources}, router::{update_data_routes_from, RoutesIndexes}, RoutingContext, }, @@ -656,7 +654,11 @@ impl HatPubSubTrait for HatCode { for face in tables.faces.values().filter(|f| { f.whatami == WhatAmI::Peer - && !initial_interest(f).map(|i| i.finalized).unwrap_or(true) + && !f + .local_interests + .get(&0) + .map(|i| i.finalized) + .unwrap_or(true) }) { route.entry(face.id).or_insert_with(|| { let key_expr = Resource::get_best_key(expr.prefix, expr.suffix, face.id); diff --git a/zenoh/src/net/routing/hat/p2p_peer/queries.rs b/zenoh/src/net/routing/hat/p2p_peer/queries.rs index 4a46ec6e85..2fd6d6fa81 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/queries.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/queries.rs @@ -17,6 +17,7 @@ use std::{ sync::{atomic::Ordering, Arc}, }; +use ordered_float::OrderedFloat; use zenoh_protocol::{ core::{ key_expr::{ @@ -42,7 +43,7 @@ use crate::net::routing::{ resource::{NodeId, Resource, SessionContext}, tables::{QueryTargetQabl, QueryTargetQablSet, RoutingExpr, Tables}, }, - hat::{p2p_peer::initial_interest, CurrentFutureTrait, HatQueriesTrait, SendDeclare, Sources}, + hat::{CurrentFutureTrait, HatQueriesTrait, SendDeclare, Sources}, router::{update_query_routes_from, RoutesIndexes}, RoutingContext, }; @@ -596,18 +597,24 @@ impl HatQueriesTrait for HatCode { 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()), - info: None, + complete: 0, + distance: f64::MAX, }); } for face in tables.faces.values().filter(|f| { f.whatami == WhatAmI::Peer - && !initial_interest(f).map(|i| i.finalized).unwrap_or(true) + && !f + .local_interests + .get(&0) + .map(|i| i.finalized) + .unwrap_or(true) }) { 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()), - info: None, + complete: 0, + distance: 0.5, }); } } @@ -632,16 +639,18 @@ impl HatQueriesTrait for HatCode { key_expr.to_owned(), NodeId::default(), ), - info: Some(QueryableInfoType { - complete: complete && qabl_info.complete, - distance: 1, - }), + complete: if complete { + qabl_info.complete as u64 + } else { + 0 + }, + distance: 0.5, }); } } } } - route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); + route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); Arc::new(route) } diff --git a/zenoh/src/net/routing/hat/p2p_peer/token.rs b/zenoh/src/net/routing/hat/p2p_peer/token.rs index a06b06f7e2..866737f0df 100644 --- a/zenoh/src/net/routing/hat/p2p_peer/token.rs +++ b/zenoh/src/net/routing/hat/p2p_peer/token.rs @@ -152,30 +152,11 @@ fn declare_simple_token( face: &mut Arc, id: TokenId, res: &mut Arc, - interest_id: Option, send_declare: &mut SendDeclare, ) { - if let Some(interest_id) = interest_id { - if let Some((interest, _)) = face.pending_current_interests.get(&interest_id) { - let wire_expr = Resource::get_best_key(res, "", interest.src_face.id); - send_declare( - &interest.src_face.primitives, - RoutingContext::with_expr( - Declare { - interest_id: Some(interest.src_interest_id), - ext_qos: ext::QoSType::default(), - ext_tstamp: None, - ext_nodeid: ext::NodeIdType::default(), - body: DeclareBody::DeclareToken(DeclareToken { id, wire_expr }), - }, - res.expr(), - ), - ) - } - } else { - register_simple_token(tables, face, id, res); - propagate_simple_token(tables, res, face, send_declare); - } + register_simple_token(tables, face, id, res); + + propagate_simple_token(tables, res, face, send_declare); } #[inline] @@ -430,7 +411,7 @@ pub(crate) fn declare_token_interest( aggregate: bool, send_declare: &mut SendDeclare, ) { - if mode.current() { + if mode.current() && face.whatami == WhatAmI::Client { let interest_id = (!mode.future()).then_some(id); if let Some(res) = res.as_ref() { if aggregate { @@ -544,10 +525,10 @@ impl HatTokenTrait for HatCode { id: TokenId, res: &mut Arc, _node_id: NodeId, - interest_id: Option, + _interest_id: Option, send_declare: &mut SendDeclare, ) { - declare_simple_token(tables, face, id, res, interest_id, send_declare) + declare_simple_token(tables, face, id, res, send_declare) } fn undeclare_token( diff --git a/zenoh/src/net/routing/hat/router/queries.rs b/zenoh/src/net/routing/hat/router/queries.rs index 969d94f3a2..f45a260288 100644 --- a/zenoh/src/net/routing/hat/router/queries.rs +++ b/zenoh/src/net/routing/hat/router/queries.rs @@ -17,6 +17,7 @@ use std::{ sync::{atomic::Ordering, Arc}, }; +use ordered_float::OrderedFloat; use petgraph::graph::NodeIndex; use zenoh_protocol::{ core::{ @@ -1101,10 +1102,12 @@ fn insert_target_for_qabls( Resource::get_best_key(expr.prefix, expr.suffix, face.id); route.push(QueryTargetQabl { direction: (face.clone(), key_expr.to_owned(), source), - info: Some(QueryableInfoType { - complete: complete && qabl_info.complete, - distance: net.distances[qabl_idx.index()] as u16, - }), + complete: if complete { + qabl_info.complete as u64 + } else { + 0 + }, + distance: net.distances[qabl_idx.index()], }); } } @@ -1479,17 +1482,19 @@ impl HatQueriesTrait for HatCode { key_expr.to_owned(), NodeId::default(), ), - info: Some(QueryableInfoType { - complete: complete && qabl_info.complete, - distance: 1, - }), + complete: if complete { + qabl_info.complete as u64 + } else { + 0 + }, + distance: 0.5, }); } } } } } - route.sort_by_key(|qabl| qabl.info.map_or(u16::MAX, |i| i.distance)); + route.sort_by_key(|qabl| OrderedFloat(qabl.distance)); Arc::new(route) } diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index dc984c2e92..d3e2a3c1ad 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -44,6 +44,7 @@ use super::{routing::dispatcher::face::Face, Runtime}; use crate::api::plugins::PluginsManager; use crate::{ api::{ + builders::sample::EncodingBuilderTrait, bytes::ZBytes, key_expr::KeyExpr, queryable::{Query, QueryInner}, diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 02534af650..022a2d63cb 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -28,8 +28,14 @@ mod _prelude { #[zenoh_macros::unstable] pub use crate::api::selector::ZenohParameters; pub use crate::{ - api::session::Undeclarable, config::ValidatedMap, Error as ZError, Resolvable, Resolve, - Result as ZResult, + api::{ + builders::sample::{ + EncodingBuilderTrait, QoSBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait, + }, + session::Undeclarable, + }, + config::ValidatedMap, + Error as ZError, Resolvable, Resolve, Result as ZResult, }; } From 21f544a92ade9c2017078192b99c25523ea77ce1 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 9 Sep 2024 15:56:03 +0200 Subject: [PATCH 20/34] fix: various fixes --- examples/examples/z_pub.rs | 2 +- .../src/replica/align_queryable.rs | 4 +- zenoh/src/api/publisher.rs | 39 +++++++++---------- zenoh/tests/qos.rs | 1 - zenoh/tests/routing.rs | 1 - zenoh/tests/session.rs | 4 +- zenoh/tests/unicity.rs | 1 - 7 files changed, 23 insertions(+), 29 deletions(-) diff --git a/examples/examples/z_pub.rs b/examples/examples/z_pub.rs index 4ff177c32a..3b125419cd 100644 --- a/examples/examples/z_pub.rs +++ b/examples/examples/z_pub.rs @@ -14,7 +14,7 @@ use std::time::Duration; use clap::Parser; -use zenoh::{bytes::Encoding, key_expr::KeyExpr, prelude::*, Config}; +use zenoh::{bytes::Encoding, key_expr::KeyExpr, Config}; use zenoh_examples::CommonArgs; #[tokio::main] diff --git a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs index 737ce79144..1baad55db6 100644 --- a/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs +++ b/plugins/zenoh-plugin-storage-manager/src/replica/align_queryable.rs @@ -21,8 +21,8 @@ use std::{ }; use zenoh::{ - internal::Value, key_expr::OwnedKeyExpr, prelude::*, query::Parameters, sample::Sample, - time::Timestamp, Session, + internal::Value, key_expr::OwnedKeyExpr, query::Parameters, sample::Sample, time::Timestamp, + Session, }; use super::{digest::*, Snapshotter}; diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index faa2e4eca6..33f04d0cda 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -12,8 +12,6 @@ // ZettaScale Zenoh Team, // -#[cfg(feature = "unstable")] -use std::mem::size_of; use std::{ convert::TryFrom, fmt, @@ -765,7 +763,7 @@ where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, { - type To = ZResult>; + type To = ZResult>; } #[zenoh_macros::unstable] @@ -784,7 +782,8 @@ where zlock!(self.publisher.matching_listeners).insert(state.id); Ok(MatchingListener { inner: MatchingListenerInner { - publisher: self.publisher.clone(), + session: self.publisher.session.clone(), + matching_listeners: self.publisher.matching_listeners.clone(), state, undeclare_on_drop: self.undeclare_on_drop, }, @@ -828,8 +827,9 @@ impl fmt::Debug for MatchingListenerState { } #[zenoh_macros::unstable] -pub(crate) struct MatchingListenerInner<'a> { - pub(crate) publisher: Publisher<'a>, +pub(crate) struct MatchingListenerInner { + pub(crate) session: WeakSession, + pub(crate) matching_listeners: Arc>>, pub(crate) state: Arc, pub(crate) undeclare_on_drop: bool, } @@ -860,13 +860,13 @@ pub(crate) struct MatchingListenerInner<'a> { /// # } /// ``` #[zenoh_macros::unstable] -pub struct MatchingListener<'a, Handler> { - pub(crate) inner: MatchingListenerInner<'a>, +pub struct MatchingListener { + pub(crate) inner: MatchingListenerInner, pub(crate) handler: Handler, } #[zenoh_macros::unstable] -impl<'a, Handler> MatchingListener<'a, Handler> { +impl MatchingListener { /// Undeclare the [`MatchingListener`]. /// /// # Examples @@ -882,7 +882,7 @@ impl<'a, Handler> MatchingListener<'a, Handler> { /// # } /// ``` #[inline] - pub fn undeclare(self) -> MatchingListenerUndeclaration<'a, Handler> + pub fn undeclare(self) -> MatchingListenerUndeclaration where Handler: Send, { @@ -892,17 +892,16 @@ impl<'a, Handler> MatchingListener<'a, Handler> { fn undeclare_impl(&mut self) -> ZResult<()> { // set the flag first to avoid double panic if this function panic self.inner.undeclare_on_drop = false; - zlock!(self.inner.publisher.matching_listeners).remove(&self.inner.state.id); + zlock!(self.inner.matching_listeners).remove(&self.inner.state.id); self.inner - .publisher .session .undeclare_matches_listener_inner(self.inner.state.id) } } #[zenoh_macros::unstable] -impl<'a, Handler: Send> UndeclarableSealed<()> for MatchingListener<'a, Handler> { - type Undeclaration = MatchingListenerUndeclaration<'a, Handler>; +impl UndeclarableSealed<()> for MatchingListener { + type Undeclaration = MatchingListenerUndeclaration; fn undeclare_inner(self, _: ()) -> Self::Undeclaration { MatchingListenerUndeclaration(self) @@ -910,7 +909,7 @@ impl<'a, Handler: Send> UndeclarableSealed<()> for MatchingListener<'a, Handler> } #[zenoh_macros::unstable] -impl std::ops::Deref for MatchingListener<'_, Handler> { +impl std::ops::Deref for MatchingListener { type Target = Handler; fn deref(&self) -> &Self::Target { @@ -918,29 +917,29 @@ impl std::ops::Deref for MatchingListener<'_, Handler> { } } #[zenoh_macros::unstable] -impl std::ops::DerefMut for MatchingListener<'_, Handler> { +impl std::ops::DerefMut for MatchingListener { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.handler } } #[zenoh_macros::unstable] -pub struct MatchingListenerUndeclaration<'a, Handler>(MatchingListener<'a, Handler>); +pub struct MatchingListenerUndeclaration(MatchingListener); #[zenoh_macros::unstable] -impl Resolvable for MatchingListenerUndeclaration<'_, Handler> { +impl Resolvable for MatchingListenerUndeclaration { type To = ZResult<()>; } #[zenoh_macros::unstable] -impl Wait for MatchingListenerUndeclaration<'_, Handler> { +impl Wait for MatchingListenerUndeclaration { fn wait(mut self) -> ::To { self.0.undeclare_impl() } } #[zenoh_macros::unstable] -impl IntoFuture for MatchingListenerUndeclaration<'_, Handler> { +impl IntoFuture for MatchingListenerUndeclaration { type Output = ::To; type IntoFuture = Ready<::To>; diff --git a/zenoh/tests/qos.rs b/zenoh/tests/qos.rs index 8d7d7e7322..2ba3226310 100644 --- a/zenoh/tests/qos.rs +++ b/zenoh/tests/qos.rs @@ -15,7 +15,6 @@ use std::time::Duration; use zenoh::{ bytes::Encoding, - prelude::*, qos::{CongestionControl, Priority}, }; use zenoh_core::ztimeout; diff --git a/zenoh/tests/routing.rs b/zenoh/tests/routing.rs index 1023584c70..8b272b274a 100644 --- a/zenoh/tests/routing.rs +++ b/zenoh/tests/routing.rs @@ -22,7 +22,6 @@ use std::{ use tokio_util::sync::CancellationToken; use zenoh::{ config::{ModeDependentValue, WhatAmI, WhatAmIMatcher}, - prelude::*, qos::CongestionControl, Config, Result, Session, }; diff --git a/zenoh/tests/session.rs b/zenoh/tests/session.rs index 7515eefc49..a1e374e379 100644 --- a/zenoh/tests/session.rs +++ b/zenoh/tests/session.rs @@ -23,9 +23,7 @@ use std::{ use zenoh::internal::runtime::{Runtime, RuntimeBuilder}; #[cfg(feature = "unstable")] use zenoh::pubsub::Reliability; -use zenoh::{ - config, key_expr::KeyExpr, prelude::*, qos::CongestionControl, sample::SampleKind, Session, -}; +use zenoh::{config, key_expr::KeyExpr, qos::CongestionControl, sample::SampleKind, Session}; use zenoh_core::ztimeout; #[cfg(not(feature = "unstable"))] use zenoh_protocol::core::Reliability; diff --git a/zenoh/tests/unicity.rs b/zenoh/tests/unicity.rs index 49663249ad..657edae1c9 100644 --- a/zenoh/tests/unicity.rs +++ b/zenoh/tests/unicity.rs @@ -24,7 +24,6 @@ use zenoh::{ config, config::{EndPoint, WhatAmI}, key_expr::KeyExpr, - prelude::*, qos::CongestionControl, Session, }; From 6915be70ed4ea1c363244a6d734c684ef8a70896 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 9 Sep 2024 16:11:40 +0200 Subject: [PATCH 21/34] fix: various fixes (2) --- zenoh/tests/shm.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zenoh/tests/shm.rs b/zenoh/tests/shm.rs index 0febac2eaa..d223b1d4a6 100644 --- a/zenoh/tests/shm.rs +++ b/zenoh/tests/shm.rs @@ -22,7 +22,6 @@ use std::{ use zenoh::{ config, - prelude::*, pubsub::Reliability, qos::CongestionControl, shm::{ From dff8456530481ba0423382cfcd945358a9ea24cb Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Mon, 9 Sep 2024 18:09:30 +0200 Subject: [PATCH 22/34] chore: merge branch 'main' into 'dev/arcsession' (#1384) * feat(zenoh_id): exposing into slice & try from slice Allowing users to create a ZenohId from a slice, using TryFrom, and also allowing users to convert a ZenohId into a [u8; 16]. * Add LivlinessSubscriber history option (#1355) * Close #1357 * feat(zenoh_id): replacing from slice with function --------- Co-authored-by: Darius Maitia Co-authored-by: OlivierHecart Co-authored-by: Luca Cominardi --- commons/zenoh-config/src/wrappers.rs | 13 +++++++ examples/examples/z_sub_liveliness.rs | 12 ++++--- .../zenoh-link-unixsock_stream/src/unicast.rs | 2 +- zenoh/src/api/liveliness.rs | 35 ++++++++++++++++++- zenoh/src/api/session.rs | 7 +++- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/commons/zenoh-config/src/wrappers.rs b/commons/zenoh-config/src/wrappers.rs index fd6d2ef50b..d04950f21e 100644 --- a/commons/zenoh-config/src/wrappers.rs +++ b/commons/zenoh-config/src/wrappers.rs @@ -35,6 +35,10 @@ impl ZenohId { pub fn into_keyexpr(self) -> OwnedKeyExpr { self.into() } + + pub fn to_le_bytes(self) -> [u8; uhlc::ID::MAX_SIZE] { + self.0.to_le_bytes() + } } impl fmt::Debug for ZenohId { @@ -54,6 +58,15 @@ impl From for ZenohId { } } +impl TryFrom<&[u8]> for ZenohId { + type Error = zenoh_result::Error; + + fn try_from(value: &[u8]) -> Result { + let proto: ZenohIdProto = value.try_into()?; + Ok(ZenohId::from(proto)) + } +} + impl From for ZenohIdProto { fn from(id: ZenohId) -> Self { id.0 diff --git a/examples/examples/z_sub_liveliness.rs b/examples/examples/z_sub_liveliness.rs index 0b70d20786..d3f13a05cc 100644 --- a/examples/examples/z_sub_liveliness.rs +++ b/examples/examples/z_sub_liveliness.rs @@ -20,7 +20,7 @@ async fn main() { // Initiate logging zenoh::try_init_log_from_env(); - let (config, key_expr) = parse_args(); + let (config, key_expr, history) = parse_args(); println!("Opening session..."); let session = zenoh::open(config).await.unwrap(); @@ -30,6 +30,7 @@ async fn main() { let subscriber = session .liveliness() .declare_subscriber(&key_expr) + .history(history) .await .unwrap(); @@ -51,13 +52,16 @@ async fn main() { #[derive(clap::Parser, Clone, PartialEq, Eq, Hash, Debug)] struct Args { #[arg(short, long, default_value = "group1/**")] - /// The key expression to write to. + /// The key expression to subscribe to. key: KeyExpr<'static>, + #[arg(long)] + /// Get historical liveliness tokens. + history: bool, #[command(flatten)] common: CommonArgs, } -fn parse_args() -> (Config, KeyExpr<'static>) { +fn parse_args() -> (Config, KeyExpr<'static>, bool) { let args = Args::parse(); - (args.common.into(), args.key) + (args.common.into(), args.key, args.history) } diff --git a/io/zenoh-links/zenoh-link-unixsock_stream/src/unicast.rs b/io/zenoh-links/zenoh-link-unixsock_stream/src/unicast.rs index a07267416d..5632da26f4 100644 --- a/io/zenoh-links/zenoh-link-unixsock_stream/src/unicast.rs +++ b/io/zenoh-links/zenoh-link-unixsock_stream/src/unicast.rs @@ -333,7 +333,7 @@ impl LinkManagerUnicastTrait for LinkManagerUnicastUnixSocketStream { nix::fcntl::flock(lock_fd, nix::fcntl::FlockArg::LockExclusiveNonblock).map_err(|e| { let _ = nix::unistd::close(lock_fd); let e = zerror!( - "Can not create a new UnixSocketStream listener on {} - Unable to acquire look: {}", + "Can not create a new UnixSocketStream listener on {} - Unable to acquire lock: {}", path, e ); diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 7c07056c1e..24c9d9871d 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -172,6 +172,7 @@ impl<'a> Liveliness<'a> { key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), handler: DefaultHandler::default(), undeclare_on_drop: true, + history: false, } } @@ -436,6 +437,7 @@ pub struct LivelinessSubscriberBuilder<'a, 'b, Handler> { pub key_expr: ZResult>, pub handler: Handler, pub undeclare_on_drop: bool, + pub history: bool, } #[zenoh_macros::unstable] @@ -471,12 +473,14 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { key_expr, handler: _, undeclare_on_drop: _, + history, } = self; LivelinessSubscriberBuilder { session, key_expr, handler: callback, undeclare_on_drop: false, + history, } } @@ -544,12 +548,36 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { key_expr, handler: _, undeclare_on_drop: _, + history, } = self; LivelinessSubscriberBuilder { session, key_expr, handler, undeclare_on_drop: true, + history, + } + } +} + +#[zenoh_macros::unstable] +impl LivelinessSubscriberBuilder<'_, '_, Handler> { + #[inline] + #[zenoh_macros::unstable] + pub fn history(self, history: bool) -> Self { + let LivelinessSubscriberBuilder { + session, + key_expr, + handler, + undeclare_on_drop, + history: _, + } = self; + LivelinessSubscriberBuilder { + session, + key_expr, + handler, + undeclare_on_drop, + history, } } } @@ -578,7 +606,12 @@ where let (callback, handler) = self.handler.into_handler(); session .0 - .declare_liveliness_subscriber_inner(&key_expr, Locality::default(), callback) + .declare_liveliness_subscriber_inner( + &key_expr, + Locality::default(), + self.history, + callback, + ) .map(|sub_state| Subscriber { inner: SubscriberInner { #[cfg(feature = "unstable")] diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 4247f918a8..38d1ce1584 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -1542,6 +1542,7 @@ impl SessionInner { &self, key_expr: &KeyExpr, origin: Locality, + history: bool, callback: Callback<'static, Sample>, ) -> ZResult> { let mut state = zwrite!(self.state); @@ -1589,7 +1590,11 @@ impl SessionInner { primitives.send_interest(Interest { id, - mode: InterestMode::Future, + mode: if history { + InterestMode::CurrentFuture + } else { + InterestMode::Future + }, options: InterestOptions::KEYEXPRS + InterestOptions::TOKENS, wire_expr: Some(key_expr.to_wire(self).to_owned()), ext_qos: declare::ext::QoSType::DECLARE, From 25a8dbebdc9bd9556b60d1a2c837b24505dc1eb2 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Tue, 10 Sep 2024 22:19:36 +0200 Subject: [PATCH 23/34] refactor: use `IntoHandler` associated const for undeclaration on drop --- zenoh-ext/src/querying_subscriber.rs | 48 ++-------------------------- zenoh/src/api/handlers/callback.rs | 5 +++ zenoh/src/api/handlers/mod.rs | 6 ++++ zenoh/src/api/liveliness.rs | 36 ++------------------- zenoh/src/api/publisher.rs | 22 ++----------- zenoh/src/api/query.rs | 29 +---------------- zenoh/src/api/queryable.rs | 22 ++----------- zenoh/src/api/scouting.rs | 11 +------ zenoh/src/api/session.rs | 2 -- zenoh/src/api/subscriber.rs | 28 ++-------------- 10 files changed, 25 insertions(+), 184 deletions(-) diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index c8a41b4e0a..ce79544540 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -60,32 +60,7 @@ impl<'a, 'b, KeySpace> QueryingSubscriberBuilder<'a, 'b, KeySpace, DefaultHandle where Callback: Fn(Sample) + Send + Sync + 'static, { - let QueryingSubscriberBuilder { - session, - key_expr, - key_space, - reliability, - origin, - query_selector, - query_target, - query_consolidation, - query_accept_replies, - query_timeout, - handler: _, - } = self; - QueryingSubscriberBuilder { - session, - key_expr, - key_space, - reliability, - origin, - query_selector, - query_target, - query_consolidation, - query_accept_replies, - query_timeout, - handler: callback, - } + self.with(callback) } /// Add callback to [`FetchingSubscriber`]. @@ -417,26 +392,7 @@ where where Callback: Fn(Sample) + Send + Sync + 'static, { - let FetchingSubscriberBuilder { - session, - key_expr, - key_space, - reliability, - origin, - fetch, - handler: _, - phantom, - } = self; - FetchingSubscriberBuilder { - session, - key_expr, - key_space, - reliability, - origin, - fetch, - handler: callback, - phantom, - } + self.with(callback) } /// Add callback to [`FetchingSubscriber`]. diff --git a/zenoh/src/api/handlers/callback.rs b/zenoh/src/api/handlers/callback.rs index 4f49e7c41f..26b1e89f28 100644 --- a/zenoh/src/api/handlers/callback.rs +++ b/zenoh/src/api/handlers/callback.rs @@ -30,6 +30,9 @@ where F: Fn(T) + Send + Sync + 'a, { type Handler = (); + + const BACKGROUND: bool = true; + fn into_handler(self) -> (Callback<'a, T>, Self::Handler) { (Dyn::from(self), ()) } @@ -84,6 +87,8 @@ where { type Handler = (); + const BACKGROUND: bool = true; + fn into_handler(self) -> (Callback<'a, Event>, Self::Handler) { (Dyn::from(move |evt| (self.callback)(evt)), ()) } diff --git a/zenoh/src/api/handlers/mod.rs b/zenoh/src/api/handlers/mod.rs index 60ec658a4d..f21d437443 100644 --- a/zenoh/src/api/handlers/mod.rs +++ b/zenoh/src/api/handlers/mod.rs @@ -35,6 +35,12 @@ pub type Dyn = std::sync::Arc; pub trait IntoHandler<'a, T> { type Handler; + /// If it makes sense to still run the callback in background + /// when the handler having been dropped. + /// This boolean may be used to determine if an entity declared + /// with the callback should be undeclared on drop. + const BACKGROUND: bool = false; + fn into_handler(self) -> (Callback<'a, T>, Self::Handler); } diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 24c9d9871d..9c50911b50 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -171,7 +171,6 @@ impl<'a> Liveliness<'a> { session: self.session, key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), handler: DefaultHandler::default(), - undeclare_on_drop: true, history: false, } } @@ -436,7 +435,6 @@ pub struct LivelinessSubscriberBuilder<'a, 'b, Handler> { pub session: &'a Session, pub key_expr: ZResult>, pub handler: Handler, - pub undeclare_on_drop: bool, pub history: bool, } @@ -468,20 +466,7 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Sample) + Send + Sync + 'static, { - let LivelinessSubscriberBuilder { - session, - key_expr, - handler: _, - undeclare_on_drop: _, - history, - } = self; - LivelinessSubscriberBuilder { - session, - key_expr, - handler: callback, - undeclare_on_drop: false, - history, - } + self.with(callback) } /// Receive the samples for this liveliness subscription with a mutable callback. @@ -547,14 +532,12 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { session, key_expr, handler: _, - undeclare_on_drop: _, history, } = self; LivelinessSubscriberBuilder { session, key_expr, handler, - undeclare_on_drop: true, history, } } @@ -569,14 +552,12 @@ impl LivelinessSubscriberBuilder<'_, '_, Handler> { session, key_expr, handler, - undeclare_on_drop, history: _, } = self; LivelinessSubscriberBuilder { session, key_expr, handler, - undeclare_on_drop, history, } } @@ -619,7 +600,7 @@ where session: self.session.downgrade(), state: sub_state, kind: SubscriberKind::LivelinessSubscriber, - undeclare_on_drop: self.undeclare_on_drop, + undeclare_on_drop: !Handler::BACKGROUND, }, handler, }) @@ -696,18 +677,7 @@ impl<'a, 'b> LivelinessGetBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Reply) + Send + Sync + 'static, { - let LivelinessGetBuilder { - session, - key_expr, - timeout, - handler: _, - } = self; - LivelinessGetBuilder { - session, - key_expr, - timeout, - handler: callback, - } + self.with(callback) } /// Receive the replies for this liveliness query with a mutable callback. diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 33f04d0cda..bac7e48bce 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -282,7 +282,6 @@ impl<'a> Publisher<'a> { MatchingListenerBuilder { publisher: self, handler: DefaultHandler::default(), - undeclare_on_drop: true, } } @@ -638,7 +637,6 @@ impl MatchingStatus { pub struct MatchingListenerBuilder<'a, 'b, Handler> { pub(crate) publisher: &'a Publisher<'b>, pub handler: Handler, - pub undeclare_on_drop: bool, } #[zenoh_macros::unstable] @@ -672,16 +670,7 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(MatchingStatus) + Send + Sync + 'static, { - let MatchingListenerBuilder { - publisher, - handler: _, - undeclare_on_drop: _, - } = self; - MatchingListenerBuilder { - publisher, - handler: callback, - undeclare_on_drop: false, - } + self.with(callback) } /// Receive the MatchingStatuses for this listener with a mutable callback. @@ -747,13 +736,8 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { let MatchingListenerBuilder { publisher, handler: _, - undeclare_on_drop: _, } = self; - MatchingListenerBuilder { - publisher, - handler, - undeclare_on_drop: true, - } + MatchingListenerBuilder { publisher, handler } } } @@ -785,7 +769,7 @@ where session: self.publisher.session.clone(), matching_listeners: self.publisher.matching_listeners.clone(), state, - undeclare_on_drop: self.undeclare_on_drop, + undeclare_on_drop: !Handler::BACKGROUND, }, handler, }) diff --git a/zenoh/src/api/query.rs b/zenoh/src/api/query.rs index ed9824d1ab..ee6b08d299 100644 --- a/zenoh/src/api/query.rs +++ b/zenoh/src/api/query.rs @@ -280,34 +280,7 @@ impl<'a, 'b> SessionGetBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Reply) + Send + Sync + 'static, { - let SessionGetBuilder { - session, - selector, - target, - consolidation, - qos, - destination, - timeout, - value, - attachment, - #[cfg(feature = "unstable")] - source_info, - handler: _, - } = self; - SessionGetBuilder { - session, - selector, - target, - consolidation, - qos, - destination, - timeout, - value, - attachment, - #[cfg(feature = "unstable")] - source_info, - handler: callback, - } + self.with(callback) } /// Receive the replies for this query with a mutable callback. diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 9cd3503968..30aa69a0bd 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -608,7 +608,6 @@ pub struct QueryableBuilder<'a, 'b, Handler> { pub(crate) complete: bool, pub(crate) origin: Locality, pub(crate) handler: Handler, - pub(crate) undeclare_on_drop: bool, } impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { @@ -633,22 +632,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Query) + Send + Sync + 'static, { - let QueryableBuilder { - session, - key_expr, - complete, - origin, - handler: _, - undeclare_on_drop: _, - } = self; - QueryableBuilder { - session, - key_expr, - complete, - origin, - handler: callback, - undeclare_on_drop: false, - } + self.with(callback) } /// Receive the queries for this Queryable with a mutable callback. @@ -712,7 +696,6 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler: _, - undeclare_on_drop: _, } = self; QueryableBuilder { session, @@ -720,7 +703,6 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler, - undeclare_on_drop: true, } } @@ -936,7 +918,7 @@ where session_id: session.zid(), session: self.session.downgrade(), state: qable_state, - undeclare_on_drop: self.undeclare_on_drop, + undeclare_on_drop: !Handler::BACKGROUND, }, handler: receiver, }) diff --git a/zenoh/src/api/scouting.rs b/zenoh/src/api/scouting.rs index 4f08530533..671033aab0 100644 --- a/zenoh/src/api/scouting.rs +++ b/zenoh/src/api/scouting.rs @@ -75,16 +75,7 @@ impl ScoutBuilder { where Callback: Fn(Hello) + Send + Sync + 'static, { - let ScoutBuilder { - what, - config, - handler: _, - } = self; - ScoutBuilder { - what, - config, - handler: callback, - } + self.with(callback) } /// Receive the [`Hello`] messages from this scout with a mutable callback. diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 38d1ce1584..20cc06242b 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -740,7 +740,6 @@ impl Session { reliability: Reliability::DEFAULT, origin: Locality::default(), handler: DefaultHandler::default(), - undeclare_on_drop: true, } } @@ -785,7 +784,6 @@ impl Session { complete: false, origin: Locality::default(), handler: DefaultHandler::default(), - undeclare_on_drop: true, } } diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 7571a1b97d..5a414c34f8 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -149,11 +149,6 @@ pub struct SubscriberBuilder<'a, 'b, Handler> { pub handler: Handler, #[cfg(not(feature = "unstable"))] pub(crate) handler: Handler, - - #[cfg(feature = "unstable")] - pub undeclare_on_drop: bool, - #[cfg(not(feature = "unstable"))] - pub(crate) undeclare_on_drop: bool, } impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { @@ -178,24 +173,7 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Sample) + Send + Sync + 'static, { - let SubscriberBuilder { - session, - key_expr, - #[cfg(feature = "unstable")] - reliability, - origin, - handler: _, - undeclare_on_drop: _, - } = self; - SubscriberBuilder { - session, - key_expr, - #[cfg(feature = "unstable")] - reliability, - origin, - handler: callback, - undeclare_on_drop: false, - } + self.with(callback) } /// Receive the samples for this subscription with a mutable callback. @@ -260,7 +238,6 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { reliability, origin, handler: _, - undeclare_on_drop: _, } = self; SubscriberBuilder { session, @@ -269,7 +246,6 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { reliability, origin, handler, - undeclare_on_drop: true, } } } @@ -347,7 +323,7 @@ where session: session.downgrade(), state: sub_state, kind: SubscriberKind::Subscriber, - undeclare_on_drop: self.undeclare_on_drop, + undeclare_on_drop: !Handler::BACKGROUND, }, handler: receiver, }) From 91cf704621f8dd7992230e8aa0dcc02010825077 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Tue, 10 Sep 2024 23:01:49 +0200 Subject: [PATCH 24/34] refactor: remove prelude --- commons/zenoh-config/src/lib.rs | 38 +++++++++++++++++-- examples/examples/z_alloc_shm.rs | 5 +-- examples/examples/z_bytes_shm.rs | 2 +- examples/examples/z_ping.rs | 2 +- examples/examples/z_ping_shm.rs | 3 +- examples/examples/z_pong.rs | 2 +- examples/examples/z_pub_shm.rs | 3 +- examples/examples/z_pub_shm_thr.rs | 3 +- examples/examples/z_pub_thr.rs | 2 +- examples/examples/z_sub_thr.rs | 2 +- plugins/zenoh-backend-example/src/lib.rs | 2 +- plugins/zenoh-backend-traits/src/lib.rs | 2 +- plugins/zenoh-plugin-example/src/lib.rs | 2 +- plugins/zenoh-plugin-rest/src/lib.rs | 2 +- .../tests/operations.rs | 3 +- .../tests/wildcard.rs | 3 +- zenoh-ext/src/group.rs | 3 +- zenoh-ext/src/querying_subscriber.rs | 3 -- zenoh-ext/src/session_ext.rs | 1 - zenoh-ext/src/subscriber_ext.rs | 6 --- zenoh-ext/tests/liveliness.rs | 5 ++- zenoh/src/api/builders/publisher.rs | 4 +- zenoh/src/api/info.rs | 7 ---- zenoh/src/api/key_expr.rs | 1 - zenoh/src/api/liveliness.rs | 20 +--------- zenoh/src/api/publisher.rs | 16 -------- zenoh/src/api/query.rs | 5 +-- zenoh/src/api/queryable.rs | 9 ----- zenoh/src/api/scouting.rs | 18 ++++----- zenoh/src/api/session.rs | 26 ++++--------- zenoh/src/api/subscriber.rs | 9 ----- zenoh/src/lib.rs | 8 +--- zenoh/src/prelude.rs | 19 ++-------- zenoh/tests/acl.rs | 1 - zenoh/tests/attachments.rs | 3 +- zenoh/tests/authentication.rs | 1 - zenoh/tests/bytes.rs | 2 +- zenoh/tests/connection_retry.rs | 6 +-- zenoh/tests/handler.rs | 2 +- zenoh/tests/interceptors.rs | 3 +- zenoh/tests/matching.rs | 2 +- zenohd/src/main.rs | 2 +- 42 files changed, 90 insertions(+), 168 deletions(-) diff --git a/commons/zenoh-config/src/lib.rs b/commons/zenoh-config/src/lib.rs index 2d9ba0beee..b06ba5f69b 100644 --- a/commons/zenoh-config/src/lib.rs +++ b/commons/zenoh-config/src/lib.rs @@ -224,9 +224,8 @@ pub fn client, T: Into>(peers: I) -> Config #[test] fn config_keys() { - use validated_struct::ValidatedMap; let c = Config::default(); - dbg!(c.keys()); + dbg!(Vec::from_iter(c.keys())); } validated_struct::validator! { @@ -659,6 +658,40 @@ fn config_deser() { } impl Config { + pub fn insert<'d, D: serde::Deserializer<'d>>( + &mut self, + key: &str, + value: D, + ) -> Result<(), validated_struct::InsertionError> + where + validated_struct::InsertionError: From, + { + ::insert(self, key, value) + } + + pub fn get( + &self, + key: &str, + ) -> Result<::Accessor, GetError> { + ::get(self, key) + } + + pub fn get_json(&self, key: &str) -> Result { + ::get_json(self, key) + } + + pub fn insert_json5( + &mut self, + key: &str, + value: &str, + ) -> Result<(), validated_struct::InsertionError> { + ::insert_json5(self, key, value) + } + + pub fn keys(&self) -> impl Iterator { + ::keys(self).into_iter() + } + pub fn set_plugin_validator(&mut self, validator: Weak) { self.plugins.validator = validator; } @@ -778,7 +811,6 @@ impl std::fmt::Display for Config { #[test] fn config_from_json() { - use validated_struct::ValidatedMap; let from_str = serde_json::Deserializer::from_str; let mut config = Config::from_deserializer(&mut from_str(r#"{}"#)).unwrap(); config diff --git a/examples/examples/z_alloc_shm.rs b/examples/examples/z_alloc_shm.rs index c955319e27..c7a6689cb8 100644 --- a/examples/examples/z_alloc_shm.rs +++ b/examples/examples/z_alloc_shm.rs @@ -12,12 +12,11 @@ // ZettaScale Zenoh Team, // use zenoh::{ - prelude::*, shm::{ AllocAlignment, BlockOn, Deallocate, Defragment, GarbageCollect, PosixShmProviderBackend, ShmProviderBuilder, POSIX_PROTOCOL_ID, }, - Config, + Config, Wait, }; #[tokio::main] @@ -27,7 +26,7 @@ async fn main() { run().await.unwrap() } -async fn run() -> ZResult<()> { +async fn run() -> zenoh::Result<()> { // create an SHM backend... // NOTE: For extended PosixShmProviderBackend API please check z_posix_shm_provider.rs let backend = PosixShmProviderBackend::builder() diff --git a/examples/examples/z_bytes_shm.rs b/examples/examples/z_bytes_shm.rs index c30710214a..81b1d8518e 100644 --- a/examples/examples/z_bytes_shm.rs +++ b/examples/examples/z_bytes_shm.rs @@ -13,11 +13,11 @@ // use zenoh::{ bytes::ZBytes, - prelude::*, shm::{ zshm, zshmmut, PosixShmProviderBackend, ShmProviderBuilder, ZShm, ZShmMut, POSIX_PROTOCOL_ID, }, + Wait, }; fn main() { diff --git a/examples/examples/z_ping.rs b/examples/examples/z_ping.rs index cd40945ad8..9f715ea153 100644 --- a/examples/examples/z_ping.rs +++ b/examples/examples/z_ping.rs @@ -14,7 +14,7 @@ use std::time::{Duration, Instant}; use clap::Parser; -use zenoh::{bytes::ZBytes, key_expr::keyexpr, prelude::*, qos::CongestionControl, Config}; +use zenoh::{bytes::ZBytes, key_expr::keyexpr, qos::CongestionControl, Config, Wait}; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_ping_shm.rs b/examples/examples/z_ping_shm.rs index bc948af4d0..4ca0ed35a2 100644 --- a/examples/examples/z_ping_shm.rs +++ b/examples/examples/z_ping_shm.rs @@ -17,10 +17,9 @@ use clap::Parser; use zenoh::{ bytes::ZBytes, key_expr::keyexpr, - prelude::*, qos::CongestionControl, shm::{PosixShmProviderBackend, ShmProviderBuilder, POSIX_PROTOCOL_ID}, - Config, + Config, Wait, }; use zenoh_examples::CommonArgs; diff --git a/examples/examples/z_pong.rs b/examples/examples/z_pong.rs index 25c1395bb3..4199968f5d 100644 --- a/examples/examples/z_pong.rs +++ b/examples/examples/z_pong.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // use clap::Parser; -use zenoh::{key_expr::keyexpr, prelude::*, qos::CongestionControl, Config}; +use zenoh::{key_expr::keyexpr, qos::CongestionControl, Config, Wait}; use zenoh_examples::CommonArgs; fn main() { diff --git a/examples/examples/z_pub_shm.rs b/examples/examples/z_pub_shm.rs index 1fe89f9cf8..b2145417ce 100644 --- a/examples/examples/z_pub_shm.rs +++ b/examples/examples/z_pub_shm.rs @@ -14,7 +14,6 @@ use clap::Parser; use zenoh::{ key_expr::KeyExpr, - prelude::*, shm::{ BlockOn, GarbageCollect, PosixShmProviderBackend, ShmProviderBuilder, POSIX_PROTOCOL_ID, }, @@ -25,7 +24,7 @@ use zenoh_examples::CommonArgs; const N: usize = 10; #[tokio::main] -async fn main() -> Result<(), ZError> { +async fn main() -> zenoh::Result<()> { // Initiate logging zenoh::init_log_from_env_or("error"); diff --git a/examples/examples/z_pub_shm_thr.rs b/examples/examples/z_pub_shm_thr.rs index c3385c0b94..7e37867d70 100644 --- a/examples/examples/z_pub_shm_thr.rs +++ b/examples/examples/z_pub_shm_thr.rs @@ -14,10 +14,9 @@ use clap::Parser; use zenoh::{ bytes::ZBytes, - prelude::*, qos::CongestionControl, shm::{PosixShmProviderBackend, ShmProviderBuilder, POSIX_PROTOCOL_ID}, - Config, + Config, Wait, }; use zenoh_examples::CommonArgs; diff --git a/examples/examples/z_pub_thr.rs b/examples/examples/z_pub_thr.rs index 9014f78763..dc18715e2a 100644 --- a/examples/examples/z_pub_thr.rs +++ b/examples/examples/z_pub_thr.rs @@ -17,8 +17,8 @@ use std::convert::TryInto; use clap::Parser; use zenoh::{ bytes::ZBytes, - prelude::*, qos::{CongestionControl, Priority}, + Wait, }; use zenoh_examples::CommonArgs; diff --git a/examples/examples/z_sub_thr.rs b/examples/examples/z_sub_thr.rs index c847a9ad87..bbc4541cd1 100644 --- a/examples/examples/z_sub_thr.rs +++ b/examples/examples/z_sub_thr.rs @@ -14,7 +14,7 @@ use std::time::Instant; use clap::Parser; -use zenoh::{prelude::*, Config}; +use zenoh::{Config, Wait}; use zenoh_examples::CommonArgs; struct Stats { diff --git a/plugins/zenoh-backend-example/src/lib.rs b/plugins/zenoh-backend-example/src/lib.rs index b9e670b799..4899bed6b0 100644 --- a/plugins/zenoh-backend-example/src/lib.rs +++ b/plugins/zenoh-backend-example/src/lib.rs @@ -15,7 +15,7 @@ use std::collections::{hash_map::Entry, HashMap}; use async_trait::async_trait; use tokio::sync::RwLock; -use zenoh::{internal::Value, key_expr::OwnedKeyExpr, prelude::*, time::Timestamp}; +use zenoh::{internal::Value, key_expr::OwnedKeyExpr, time::Timestamp, Result as ZResult}; use zenoh_backend_traits::{ config::{StorageConfig, VolumeConfig}, Capability, History, Persistence, Storage, StorageInsertionResult, StoredData, Volume, diff --git a/plugins/zenoh-backend-traits/src/lib.rs b/plugins/zenoh-backend-traits/src/lib.rs index a75d934050..40b1407fa9 100644 --- a/plugins/zenoh-backend-traits/src/lib.rs +++ b/plugins/zenoh-backend-traits/src/lib.rs @@ -29,7 +29,7 @@ //! ``` //! use std::sync::Arc; //! use async_trait::async_trait; -//! use zenoh::{key_expr::OwnedKeyExpr, prelude::*, time::Timestamp, internal::Value}; +//! use zenoh::{key_expr::OwnedKeyExpr, time::Timestamp, internal::Value}; //! use zenoh_backend_traits::*; //! use zenoh_backend_traits::config::*; //! diff --git a/plugins/zenoh-plugin-example/src/lib.rs b/plugins/zenoh-plugin-example/src/lib.rs index eeba4db2a2..9fc53c1c80 100644 --- a/plugins/zenoh-plugin-example/src/lib.rs +++ b/plugins/zenoh-plugin-example/src/lib.rs @@ -34,8 +34,8 @@ use zenoh::{ zlock, }, key_expr::{keyexpr, KeyExpr}, - prelude::ZResult, sample::Sample, + Result as ZResult, }; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-rest/src/lib.rs b/plugins/zenoh-plugin-rest/src/lib.rs index 5f1d5cf667..90dd6002df 100644 --- a/plugins/zenoh-plugin-rest/src/lib.rs +++ b/plugins/zenoh-plugin-rest/src/lib.rs @@ -44,10 +44,10 @@ use zenoh::{ zerror, }, key_expr::{keyexpr, KeyExpr}, - prelude::*, query::{Parameters, QueryConsolidation, Reply, Selector, ZenohParameters}, sample::{Sample, SampleKind}, session::Session, + Result as ZResult, }; use zenoh_plugin_trait::{plugin_long_version, plugin_version, Plugin, PluginControl}; diff --git a/plugins/zenoh-plugin-storage-manager/tests/operations.rs b/plugins/zenoh-plugin-storage-manager/tests/operations.rs index 483b87e223..c3ddf67d2e 100644 --- a/plugins/zenoh-plugin-storage-manager/tests/operations.rs +++ b/plugins/zenoh-plugin-storage-manager/tests/operations.rs @@ -20,8 +20,7 @@ use std::{borrow::Cow, str::FromStr, thread::sleep}; use tokio::runtime::Runtime; use zenoh::{ - internal::zasync_executor_init, prelude::*, query::Reply, sample::Sample, time::Timestamp, - Config, Session, + internal::zasync_executor_init, query::Reply, sample::Sample, time::Timestamp, Config, Session, }; use zenoh_plugin_trait::Plugin; diff --git a/plugins/zenoh-plugin-storage-manager/tests/wildcard.rs b/plugins/zenoh-plugin-storage-manager/tests/wildcard.rs index 6a6e36b2fd..b4c7ddd8f2 100644 --- a/plugins/zenoh-plugin-storage-manager/tests/wildcard.rs +++ b/plugins/zenoh-plugin-storage-manager/tests/wildcard.rs @@ -21,8 +21,7 @@ use std::{borrow::Cow, str::FromStr, thread::sleep}; // use std::collections::HashMap; use tokio::runtime::Runtime; use zenoh::{ - internal::zasync_executor_init, prelude::*, query::Reply, sample::Sample, time::Timestamp, - Config, Session, + internal::zasync_executor_init, query::Reply, sample::Sample, time::Timestamp, Config, Session, }; use zenoh_plugin_trait::Plugin; diff --git a/zenoh-ext/src/group.rs b/zenoh-ext/src/group.rs index f8de27d662..c842c9eed6 100644 --- a/zenoh-ext/src/group.rs +++ b/zenoh-ext/src/group.rs @@ -29,10 +29,9 @@ use zenoh::{ bytes::ZBytesReader, internal::{bail, Condition, TaskController}, key_expr::{keyexpr, KeyExpr, OwnedKeyExpr}, - prelude::*, pubsub::Publisher, qos::Priority, - Session, + Error as ZError, Result as ZResult, Session, }; const GROUP_PREFIX: &str = "zenoh/ext/net/group"; diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index ce79544540..ffa7f05b23 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -556,7 +556,6 @@ where /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -699,7 +698,6 @@ impl FetchingSubscriber { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -777,7 +775,6 @@ impl Drop for RepliesHandler { /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// # use zenoh::prelude::*; /// # use zenoh_ext::*; /// # /// # let session = zenoh::open(zenoh::config::peer()).await.unwrap(); diff --git a/zenoh-ext/src/session_ext.rs b/zenoh-ext/src/session_ext.rs index 21f2fc5c6e..7c68f88ddb 100644 --- a/zenoh-ext/src/session_ext.rs +++ b/zenoh-ext/src/session_ext.rs @@ -22,7 +22,6 @@ pub trait SessionExt<'s, 'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh::config::ModeDependentValue::Unique; /// use zenoh_ext::SessionExt; /// diff --git a/zenoh-ext/src/subscriber_ext.rs b/zenoh-ext/src/subscriber_ext.rs index 434ec15234..df54ec14f5 100644 --- a/zenoh-ext/src/subscriber_ext.rs +++ b/zenoh-ext/src/subscriber_ext.rs @@ -60,7 +60,6 @@ pub trait SubscriberBuilderExt<'a, 'b, Handler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -104,7 +103,6 @@ pub trait SubscriberBuilderExt<'a, 'b, Handler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -138,7 +136,6 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> for SubscriberBuilde /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -194,7 +191,6 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> for SubscriberBuilde /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -248,7 +244,6 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -307,7 +302,6 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); diff --git a/zenoh-ext/tests/liveliness.rs b/zenoh-ext/tests/liveliness.rs index 294bf5e351..d211505c4c 100644 --- a/zenoh-ext/tests/liveliness.rs +++ b/zenoh-ext/tests/liveliness.rs @@ -15,6 +15,7 @@ use zenoh::{ config::{self, EndPoint, WhatAmI}, sample::SampleKind, + Wait, }; #[tokio::test(flavor = "multi_thread", worker_threads = 4)] @@ -205,7 +206,7 @@ async fn test_liveliness_querying_subscriber_brokered() { async fn test_liveliness_fetching_subscriber_clique() { use std::time::Duration; - use zenoh::{internal::ztimeout, prelude::*}; + use zenoh::internal::ztimeout; use zenoh_ext::SubscriberBuilderExt; const TIMEOUT: Duration = Duration::from_secs(60); @@ -287,7 +288,7 @@ async fn test_liveliness_fetching_subscriber_clique() { async fn test_liveliness_fetching_subscriber_brokered() { use std::time::Duration; - use zenoh::{internal::ztimeout, prelude::*}; + use zenoh::internal::ztimeout; use zenoh_ext::SubscriberBuilderExt; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenoh/src/api/builders/publisher.rs b/zenoh/src/api/builders/publisher.rs index 4b0c3d8459..ba8ac98947 100644 --- a/zenoh/src/api/builders/publisher.rs +++ b/zenoh/src/api/builders/publisher.rs @@ -59,7 +59,7 @@ pub struct PublicationBuilderDelete; /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{bytes::Encoding, prelude::*, qos::CongestionControl}; +/// use zenoh::{bytes::Encoding, qos::CongestionControl}; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// session @@ -239,7 +239,7 @@ impl IntoFuture for PublicationBuilder, PublicationBuil /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{prelude::*, qos::CongestionControl}; +/// use zenoh::qos::CongestionControl; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session diff --git a/zenoh/src/api/info.rs b/zenoh/src/api/info.rs index 0993663996..a63797c86c 100644 --- a/zenoh/src/api/info.rs +++ b/zenoh/src/api/info.rs @@ -28,7 +28,6 @@ use crate::net::runtime::Runtime; /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let zid = session.info().zid().await; @@ -66,7 +65,6 @@ impl<'a> IntoFuture for ZenohIdBuilder<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut routers_zid = session.info().routers_zid().await; @@ -114,7 +112,6 @@ impl<'a> IntoFuture for RoutersZenohIdBuilder<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let zid = session.info().zid().await; @@ -163,7 +160,6 @@ impl<'a> IntoFuture for PeersZenohIdBuilder<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let info = session.info(); @@ -181,7 +177,6 @@ impl SessionInfo { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let zid = session.info().zid().await; @@ -200,7 +195,6 @@ impl SessionInfo { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut routers_zid = session.info().routers_zid().await; @@ -219,7 +213,6 @@ impl SessionInfo { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut peers_zid = session.info().peers_zid().await; diff --git a/zenoh/src/api/key_expr.rs b/zenoh/src/api/key_expr.rs index 6ed0cbcea3..fff40a5286 100644 --- a/zenoh/src/api/key_expr.rs +++ b/zenoh/src/api/key_expr.rs @@ -566,7 +566,6 @@ impl<'a> UndeclarableSealed<&'a Session> for KeyExpr<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let key_expr = session.declare_keyexpr("key/expression").await.unwrap(); diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 9c50911b50..6a6ef0dea5 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -51,7 +51,6 @@ use crate::api::session::WeakSession; /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -66,7 +65,6 @@ use crate::api::session::WeakSession; /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session.liveliness().get("key/**").await.unwrap(); @@ -82,7 +80,7 @@ use crate::api::session::WeakSession; /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{prelude::*, sample::SampleKind}; +/// use zenoh::sample::SampleKind; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session.liveliness().declare_subscriber("key/**").await.unwrap(); @@ -111,7 +109,6 @@ impl<'a> Liveliness<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -146,7 +143,7 @@ impl<'a> Liveliness<'a> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{prelude::*, sample::SampleKind}; + /// use zenoh::sample::SampleKind; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session.liveliness().declare_subscriber("key/expression").await.unwrap(); @@ -185,7 +182,6 @@ impl<'a> Liveliness<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session.liveliness().get("key/expression").await.unwrap(); @@ -225,7 +221,6 @@ impl<'a> Liveliness<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -298,7 +293,6 @@ pub(crate) struct LivelinessTokenState { /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -322,7 +316,6 @@ pub struct LivelinessToken { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -368,7 +361,6 @@ impl LivelinessToken { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -418,7 +410,6 @@ impl Drop for LivelinessToken { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -446,7 +437,6 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -478,7 +468,6 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut n = 0; @@ -508,7 +497,6 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -629,7 +617,6 @@ where /// # #[tokio::main] /// # async fn main() { /// # use std::convert::TryFrom; -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let tokens = session @@ -661,7 +648,6 @@ impl<'a, 'b> LivelinessGetBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session @@ -689,7 +675,6 @@ impl<'a, 'b> LivelinessGetBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut n = 0; @@ -718,7 +703,6 @@ impl<'a, 'b> LivelinessGetBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index bac7e48bce..2b5f437a98 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -81,7 +81,6 @@ impl fmt::Debug for PublisherState { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -96,7 +95,6 @@ impl fmt::Debug for PublisherState { /// # #[tokio::main] /// # async fn main() { /// use futures::StreamExt; -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut subscriber = session.declare_subscriber("key/expression").await.unwrap(); @@ -130,7 +128,6 @@ impl<'a> Publisher<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression") @@ -177,7 +174,6 @@ impl<'a> Publisher<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -208,7 +204,6 @@ impl<'a> Publisher<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -235,7 +230,6 @@ impl<'a> Publisher<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -263,7 +257,6 @@ impl<'a> Publisher<'a> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -291,7 +284,6 @@ impl<'a> Publisher<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -330,7 +322,6 @@ impl<'a> UndeclarableSealed<()> for Publisher<'a> { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -594,7 +585,6 @@ impl TryFrom for Priority { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -615,7 +605,6 @@ impl MatchingStatus { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -647,7 +636,6 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -679,7 +667,6 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let mut n = 0; /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -709,7 +696,6 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -829,7 +815,6 @@ pub(crate) struct MatchingListenerInner { /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); @@ -857,7 +842,6 @@ impl MatchingListener { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression").await.unwrap(); diff --git a/zenoh/src/api/query.rs b/zenoh/src/api/query.rs index ee6b08d299..7203d93f81 100644 --- a/zenoh/src/api/query.rs +++ b/zenoh/src/api/query.rs @@ -178,7 +178,7 @@ impl QueryState { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{prelude::*, query::{ConsolidationMode, QueryTarget}}; +/// use zenoh::{query::{ConsolidationMode, QueryTarget}}; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session @@ -265,7 +265,6 @@ impl<'a, 'b> SessionGetBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session @@ -292,7 +291,6 @@ impl<'a, 'b> SessionGetBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut n = 0; @@ -320,7 +318,6 @@ impl<'a, 'b> SessionGetBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 30aa69a0bd..3d9946a322 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -559,7 +559,6 @@ pub(crate) struct QueryableInner { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session.declare_queryable("key/expression").await.unwrap(); @@ -594,7 +593,6 @@ impl IntoFuture for QueryableUndeclaration { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session.declare_queryable("key/expression").await.unwrap(); @@ -617,7 +615,6 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session @@ -644,7 +641,6 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut n = 0; @@ -672,7 +668,6 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session @@ -740,7 +735,6 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// # #[tokio::main] /// # async fn main() { /// use futures::prelude::*; -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let (tx, rx) = flume::bounded(32); @@ -763,7 +757,6 @@ impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session @@ -794,7 +787,6 @@ impl Queryable { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session.declare_queryable("key/expression") @@ -832,7 +824,6 @@ impl Queryable { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session.declare_queryable("key/expression") diff --git a/zenoh/src/api/scouting.rs b/zenoh/src/api/scouting.rs index 671033aab0..0a41294548 100644 --- a/zenoh/src/api/scouting.rs +++ b/zenoh/src/api/scouting.rs @@ -37,7 +37,7 @@ use crate::{ /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{config::WhatAmI, prelude::*}; +/// use zenoh::config::WhatAmI; /// /// let receiver = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .await @@ -62,7 +62,7 @@ impl ScoutBuilder { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{config::WhatAmI, prelude::*}; + /// use zenoh::config::WhatAmI; /// /// let scout = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .callback(|hello| { println!("{}", hello); }) @@ -87,7 +87,7 @@ impl ScoutBuilder { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{config::WhatAmI, prelude::*}; + /// use zenoh::config::WhatAmI; /// /// let mut n = 0; /// let scout = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) @@ -113,7 +113,7 @@ impl ScoutBuilder { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{config::WhatAmI, prelude::*}; + /// use zenoh::config::WhatAmI; /// /// let receiver = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .with(flume::bounded(32)) @@ -180,7 +180,7 @@ where /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{config::WhatAmI, prelude::*}; +/// use zenoh::config::WhatAmI; /// /// let scout = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .callback(|hello| { println!("{}", hello); }) @@ -200,7 +200,7 @@ impl ScoutInner { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{config::WhatAmI, prelude::*}; + /// use zenoh::config::WhatAmI; /// /// let scout = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .callback(|hello| { println!("{}", hello); }) @@ -235,7 +235,7 @@ impl fmt::Debug for ScoutInner { /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{config::WhatAmI, prelude::*}; +/// use zenoh::config::WhatAmI; /// /// let receiver = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .with(flume::bounded(32)) @@ -268,7 +268,7 @@ impl Scout { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{config::WhatAmI, prelude::*}; + /// use zenoh::config::WhatAmI; /// /// let scout = zenoh::scout(WhatAmI::Router, zenoh::config::default()) /// .with(flume::bounded(32)) @@ -350,7 +350,7 @@ fn _scout( /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{config::WhatAmI, prelude::*}; +/// use zenoh::config::WhatAmI; /// /// let receiver = zenoh::scout(WhatAmI::Peer | WhatAmI::Router, zenoh::config::default()) /// .await diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index 20cc06242b..96fc92c4f3 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -422,7 +422,6 @@ impl fmt::Debug for SessionInner { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// session.put("key/expression", "value").await.unwrap(); @@ -576,7 +575,6 @@ impl Session { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -604,7 +602,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// assert!(!session.is_closed()); @@ -634,7 +631,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let peers = session.config().get("connect/endpoints").unwrap(); @@ -645,7 +641,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let _ = session.config().insert_json5("connect/endpoints", r#"["tcp/127.0.0.1/7447"]"#); @@ -664,7 +659,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let timestamp = session.new_timestamp(); @@ -681,6 +675,12 @@ impl Session { } } } + + /// Wrap the session into an `Arc`. + #[deprecated(since = "1.0.0", note = "use `Session` directly instead")] + pub fn into_arc(self) -> Arc { + Arc::new(self) + } } impl Session { @@ -690,7 +690,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let info = session.info(); @@ -712,7 +711,6 @@ impl Session { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session.declare_subscriber("key/expression") @@ -754,7 +752,6 @@ impl Session { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let queryable = session.declare_queryable("key/expression") @@ -797,7 +794,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let publisher = session.declare_publisher("key/expression") @@ -833,7 +829,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -859,7 +854,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let key_expr = session.declare_keyexpr("key/expression").await.unwrap(); @@ -914,7 +908,7 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::{bytes::Encoding, prelude::*}; + /// use zenoh::bytes::Encoding; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// session @@ -958,7 +952,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// session.delete("key/expression").await.unwrap(); @@ -995,7 +988,6 @@ impl Session { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session.get("key/expression").await.unwrap(); @@ -2670,7 +2662,6 @@ impl crate::net::primitives::EPrimitives for WeakSession { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// # } @@ -2680,7 +2671,7 @@ impl crate::net::primitives::EPrimitives for WeakSession { /// # #[tokio::main] /// # async fn main() { /// use std::str::FromStr; -/// use zenoh::{session::ZenohId, prelude::*}; +/// use zenoh::session::ZenohId; /// /// let mut config = zenoh::config::peer(); /// config.set_id(ZenohId::from_str("221b72df20924c15b8794c6bdb471150").unwrap()); @@ -2708,7 +2699,6 @@ where /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// # } diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 5a414c34f8..8d468b5632 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -76,7 +76,6 @@ pub(crate) struct SubscriberInner { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -114,7 +113,6 @@ impl IntoFuture for SubscriberUndeclaration { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -158,7 +156,6 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -185,7 +182,6 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let mut n = 0; @@ -213,7 +209,6 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -358,7 +353,6 @@ where /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// session @@ -374,7 +368,6 @@ where /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session @@ -402,7 +395,6 @@ impl Subscriber { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session.declare_subscriber("key/expression") @@ -445,7 +437,6 @@ impl Subscriber { /// ``` /// # #[tokio::main] /// # async fn main() { - /// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session.declare_subscriber("key/expression") diff --git a/zenoh/src/lib.rs b/zenoh/src/lib.rs index d650ddb05d..3fa24e3c36 100644 --- a/zenoh/src/lib.rs +++ b/zenoh/src/lib.rs @@ -34,7 +34,6 @@ //! ### Publishing Data //! The example below shows how to produce a value for a key expression. //! ``` -//! use zenoh::prelude::*; //! //! #[tokio::main] //! async fn main() { @@ -48,7 +47,6 @@ //! The example below shows how to consume values for a key expressions. //! ```no_run //! use futures::prelude::*; -//! use zenoh::prelude::*; //! //! #[tokio::main] //! async fn main() { @@ -65,7 +63,6 @@ //! resources whose key match the given *key expression*. //! ``` //! use futures::prelude::*; -//! use zenoh::prelude::*; //! //! #[tokio::main] //! async fn main() { @@ -128,6 +125,7 @@ pub use crate::{ session::{open, Session}, }; +#[deprecated(since = "1.0.0")] pub mod prelude; /// [Key expression](https://github.com/eclipse-zenoh/roadmap/blob/main/rfcs/ALL/Key%20Expressions.md) are Zenoh's address space. @@ -297,7 +295,6 @@ pub mod scouting { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let liveliness = session @@ -312,7 +309,6 @@ pub mod scouting { /// ``` /// # #[tokio::main] /// # async fn main() { -/// use zenoh::prelude::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let replies = session.liveliness().get("key/**").await.unwrap(); @@ -328,7 +324,7 @@ pub mod scouting { /// ```no_run /// # #[tokio::main] /// # async fn main() { -/// use zenoh::{prelude::*, sample::SampleKind}; +/// use zenoh::sample::SampleKind; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); /// let subscriber = session.liveliness().declare_subscriber("key/**").await.unwrap(); diff --git a/zenoh/src/prelude.rs b/zenoh/src/prelude.rs index 02534af650..572788a834 100644 --- a/zenoh/src/prelude.rs +++ b/zenoh/src/prelude.rs @@ -21,20 +21,9 @@ //! Examples: //! //! ``` -//!use zenoh::prelude::*; +//! use zenoh::prelude::*; //! ``` -mod _prelude { - #[zenoh_macros::unstable] - pub use crate::api::selector::ZenohParameters; - pub use crate::{ - api::session::Undeclarable, config::ValidatedMap, Error as ZError, Resolvable, Resolve, - Result as ZResult, - }; -} - -pub use _prelude::*; - #[allow(deprecated)] pub use crate::AsyncResolve; #[allow(deprecated)] @@ -42,16 +31,14 @@ pub use crate::SyncResolve; pub use crate::Wait; /// Prelude to import when using Zenoh's sync API. -#[deprecated(since = "1.0.0", note = "use `zenoh::prelude` instead")] +#[deprecated(since = "1.0.0", note = "use `zenoh::Wait` instead")] pub mod sync { - pub use super::_prelude::*; #[allow(deprecated)] pub use crate::SyncResolve; } /// Prelude to import when using Zenoh's async API. -#[deprecated(since = "1.0.0", note = "use `zenoh::prelude` instead")] +#[deprecated(since = "1.0.0")] pub mod r#async { - pub use super::_prelude::*; #[allow(deprecated)] pub use crate::AsyncResolve; } diff --git a/zenoh/tests/acl.rs b/zenoh/tests/acl.rs index 2505a81983..285e68b254 100644 --- a/zenoh/tests/acl.rs +++ b/zenoh/tests/acl.rs @@ -22,7 +22,6 @@ mod test { use zenoh::{ config, config::{EndPoint, WhatAmI}, - prelude::*, sample::SampleKind, Config, Session, }; diff --git a/zenoh/tests/attachments.rs b/zenoh/tests/attachments.rs index 38b1fea136..dd9e287428 100644 --- a/zenoh/tests/attachments.rs +++ b/zenoh/tests/attachments.rs @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // #![cfg(feature = "unstable")] -use zenoh::{bytes::ZBytes, config::Config, prelude::*}; +use zenoh::{bytes::ZBytes, config::Config, Wait}; #[test] fn attachment_pubsub() { @@ -61,7 +61,6 @@ fn attachment_pubsub() { #[test] fn attachment_queries() { - use zenoh::prelude::*; let zenoh = zenoh::open(Config::default()).wait().unwrap(); let _sub = zenoh .declare_queryable("test/attachment") diff --git a/zenoh/tests/authentication.rs b/zenoh/tests/authentication.rs index f9fb7a3b0e..63ddfcc03c 100644 --- a/zenoh/tests/authentication.rs +++ b/zenoh/tests/authentication.rs @@ -24,7 +24,6 @@ mod test { use zenoh::{ config, config::{EndPoint, WhatAmI}, - prelude::*, Config, Session, }; use zenoh_core::{zlock, ztimeout}; diff --git a/zenoh/tests/bytes.rs b/zenoh/tests/bytes.rs index 34c9837d04..d0b2b66dda 100644 --- a/zenoh/tests/bytes.rs +++ b/zenoh/tests/bytes.rs @@ -14,11 +14,11 @@ #![cfg(all(feature = "shared-memory", feature = "unstable"))] use zenoh::{ bytes::ZBytes, - prelude::*, shm::{ zshm, zshmmut, PosixShmProviderBackend, ShmProviderBuilder, ZShm, ZShmMut, POSIX_PROTOCOL_ID, }, + Wait, }; #[test] diff --git a/zenoh/tests/connection_retry.rs b/zenoh/tests/connection_retry.rs index 78814556f7..6bb655851b 100644 --- a/zenoh/tests/connection_retry.rs +++ b/zenoh/tests/connection_retry.rs @@ -12,11 +12,9 @@ // ZettaScale Zenoh Team, // use zenoh::{ - config::{ConnectionRetryConf, EndPoint}, - prelude::*, - Config, + config::{ConnectionRetryConf, EndPoint, ModeDependent}, + Config, Wait, }; -use zenoh_config::ModeDependent; #[test] fn retry_config_overriding() { diff --git a/zenoh/tests/handler.rs b/zenoh/tests/handler.rs index 640ed33b89..d87917a0dd 100644 --- a/zenoh/tests/handler.rs +++ b/zenoh/tests/handler.rs @@ -13,7 +13,7 @@ // use std::{thread, time::Duration}; -use zenoh::{handlers::RingChannel, prelude::*, Config}; +use zenoh::{handlers::RingChannel, Config, Wait}; #[test] fn pubsub_with_ringbuffer() { diff --git a/zenoh/tests/interceptors.rs b/zenoh/tests/interceptors.rs index 1f3981b66e..57ba51d5ba 100644 --- a/zenoh/tests/interceptors.rs +++ b/zenoh/tests/interceptors.rs @@ -24,8 +24,7 @@ use std::{ use zenoh::{ config::{DownsamplingItemConf, DownsamplingRuleConf, InterceptorFlow}, key_expr::KeyExpr, - prelude::*, - Config, + Config, Wait, }; // Tokio's time granularity on different platforms diff --git a/zenoh/tests/matching.rs b/zenoh/tests/matching.rs index b2a180552d..d7825e85b8 100644 --- a/zenoh/tests/matching.rs +++ b/zenoh/tests/matching.rs @@ -15,7 +15,7 @@ use std::{str::FromStr, time::Duration}; use flume::RecvTimeoutError; -use zenoh::{config, config::Locator, prelude::*, sample::Locality, Session}; +use zenoh::{config, config::Locator, sample::Locality, Result as ZResult, Session}; use zenoh_core::ztimeout; const TIMEOUT: Duration = Duration::from_secs(60); diff --git a/zenohd/src/main.rs b/zenohd/src/main.rs index 9ce0a64333..85a063e3a2 100644 --- a/zenohd/src/main.rs +++ b/zenohd/src/main.rs @@ -18,7 +18,7 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilte #[cfg(feature = "loki")] use url::Url; use zenoh::{ - config::{Config, EndPoint, ModeDependentValue, PermissionsConf, ValidatedMap, WhatAmI}, + config::{Config, EndPoint, ModeDependentValue, PermissionsConf, WhatAmI}, Result, }; use zenoh_util::LibSearchDirs; From 5eac34aef4cfa65c1d14c785171251a60cba05ee Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Tue, 10 Sep 2024 23:24:36 +0200 Subject: [PATCH 25/34] fix: fix config example --- commons/zenoh-config/src/lib.rs | 56 ++++++++++++++++++++++++++--- zenoh/src/net/runtime/adminspace.rs | 5 ++- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/commons/zenoh-config/src/lib.rs b/commons/zenoh-config/src/lib.rs index b06ba5f69b..b57c62edde 100644 --- a/commons/zenoh-config/src/lib.rs +++ b/commons/zenoh-config/src/lib.rs @@ -666,18 +666,18 @@ impl Config { where validated_struct::InsertionError: From, { - ::insert(self, key, value) + ::insert(self, key, value) } pub fn get( &self, key: &str, ) -> Result<::Accessor, GetError> { - ::get(self, key) + ::get(self, key) } pub fn get_json(&self, key: &str) -> Result { - ::get_json(self, key) + ::get_json(self, key) } pub fn insert_json5( @@ -685,11 +685,11 @@ impl Config { key: &str, value: &str, ) -> Result<(), validated_struct::InsertionError> { - ::insert_json5(self, key, value) + ::insert_json5(self, key, value) } pub fn keys(&self) -> impl Iterator { - ::keys(self).into_iter() + ::keys(self).into_iter() } pub fn set_plugin_validator(&mut self, validator: Weak) { @@ -976,6 +976,52 @@ where self.lock().keys() } } +impl Notifier +where + T: for<'a> ValidatedMapAssociatedTypes<'a, Accessor = &'a dyn Any>, +{ + pub fn insert<'d, D: serde::Deserializer<'d>>( + &self, + key: &str, + value: D, + ) -> Result<(), validated_struct::InsertionError> + where + validated_struct::InsertionError: From, + { + self.lock().insert(key, value)?; + self.notify(key); + Ok(()) + } + + pub fn get( + &self, + key: &str, + ) -> Result<::Accessor, GetError> { + let guard = zlock!(self.inner.inner); + // SAFETY: MutexGuard pins the mutex behind which the value is held. + let subref = guard.get(key.as_ref())? as *const _; + Ok(GetGuard { + _guard: guard, + subref, + }) + } + + pub fn get_json(&self, key: &str) -> Result { + self.lock().get_json(key) + } + + pub fn insert_json5( + &self, + key: &str, + value: &str, + ) -> Result<(), validated_struct::InsertionError> { + self.insert(key, &mut json5::Deserializer::from_str(value)?) + } + + pub fn keys(&self) -> impl Iterator { + self.lock().keys().into_iter() + } +} pub struct GetGuard<'a, T> { _guard: MutexGuard<'a, T>, diff --git a/zenoh/src/net/runtime/adminspace.rs b/zenoh/src/net/runtime/adminspace.rs index dc984c2e92..67e699d395 100644 --- a/zenoh/src/net/runtime/adminspace.rs +++ b/zenoh/src/net/runtime/adminspace.rs @@ -19,7 +19,7 @@ use std::{ use serde_json::json; use tracing::{error, trace}; use zenoh_buffers::buffer::SplitBuffer; -use zenoh_config::{unwrap_or_default, wrappers::ZenohId, ConfigValidator, ValidatedMap, WhatAmI}; +use zenoh_config::{unwrap_or_default, wrappers::ZenohId, ConfigValidator, WhatAmI}; use zenoh_core::Wait; #[cfg(feature = "plugins")] use zenoh_plugin_trait::{PluginControl, PluginStatus}; @@ -401,8 +401,7 @@ impl Primitives for AdminSpace { key, json ); - if let Err(e) = (&self.context.runtime.state.config).insert_json5(key, json) - { + if let Err(e) = self.context.runtime.state.config.insert_json5(key, json) { error!( "Error inserting conf value @/{}/{}/config/{} : {} - {}", self.context.runtime.state.zid, From f79df2954063cec0f4332f202724bc3a67744f05 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 00:03:11 +0200 Subject: [PATCH 26/34] fix: fix zenoh-ext examples --- zenoh-ext/src/querying_subscriber.rs | 3 +++ zenoh-ext/src/subscriber_ext.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index ffa7f05b23..e2329ee52d 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -556,6 +556,7 @@ where /// ```no_run /// # #[tokio::main] /// # async fn main() { +/// use zenoh::Wait; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -698,6 +699,7 @@ impl FetchingSubscriber { /// ```no_run /// # #[tokio::main] /// # async fn main() { + /// use zenoh::Wait; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -775,6 +777,7 @@ impl Drop for RepliesHandler { /// ```no_run /// # #[tokio::main] /// # async fn main() { +/// # use zenoh::Wait; /// # use zenoh_ext::*; /// # /// # let session = zenoh::open(zenoh::config::peer()).await.unwrap(); diff --git a/zenoh-ext/src/subscriber_ext.rs b/zenoh-ext/src/subscriber_ext.rs index df54ec14f5..1d63915b15 100644 --- a/zenoh-ext/src/subscriber_ext.rs +++ b/zenoh-ext/src/subscriber_ext.rs @@ -60,6 +60,7 @@ pub trait SubscriberBuilderExt<'a, 'b, Handler> { /// ```no_run /// # #[tokio::main] /// # async fn main() { + /// use zenoh::Wait; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -136,6 +137,7 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> for SubscriberBuilde /// ```no_run /// # #[tokio::main] /// # async fn main() { + /// use zenoh::Wait; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); @@ -244,6 +246,7 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> /// ```no_run /// # #[tokio::main] /// # async fn main() { + /// use zenoh::Wait; /// use zenoh_ext::*; /// /// let session = zenoh::open(zenoh::config::peer()).await.unwrap(); From 83d31d8b2002da5d8ec1ef935b834681891dacd8 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 09:37:49 +0200 Subject: [PATCH 27/34] fix: fix plugins examples --- plugins/zenoh-backend-traits/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/zenoh-backend-traits/src/lib.rs b/plugins/zenoh-backend-traits/src/lib.rs index 40b1407fa9..cd2238dc6a 100644 --- a/plugins/zenoh-backend-traits/src/lib.rs +++ b/plugins/zenoh-backend-traits/src/lib.rs @@ -34,7 +34,7 @@ //! use zenoh_backend_traits::config::*; //! //! #[no_mangle] -//! pub fn create_volume(config: VolumeConfig) -> ZResult> { +//! pub fn create_volume(config: VolumeConfig) -> zenoh::Result> { //! Ok(Box::new(MyVolumeType { config })) //! } //! @@ -62,7 +62,7 @@ //! } //! } //! -//! async fn create_storage(&self, properties: StorageConfig) -> ZResult> { +//! async fn create_storage(&self, properties: StorageConfig) -> zenoh::Result> { //! // The properties are the ones passed via a PUT in the admin space for Storage creation. //! Ok(Box::new(MyStorage::new(properties).await?)) //! } @@ -74,7 +74,7 @@ //! } //! //! impl MyStorage { -//! async fn new(config: StorageConfig) -> ZResult { +//! async fn new(config: StorageConfig) -> zenoh::Result { //! Ok(MyStorage { config }) //! } //! } @@ -88,7 +88,7 @@ //! self.config.to_json_value() //! } //! -//! async fn put(&mut self, key: Option, value: Value, timestamp: Timestamp) -> ZResult { +//! async fn put(&mut self, key: Option, value: Value, timestamp: Timestamp) -> zenoh::Result { //! // the key will be None if it exactly matched with the strip_prefix //! // create a storage specific special structure to store it //! // Store the data with timestamp @@ -99,14 +99,14 @@ //! // return Ok(StorageInsertionResult::Outdated); //! } //! -//! async fn delete(&mut self, key: Option, timestamp: Timestamp) -> ZResult { +//! async fn delete(&mut self, key: Option, timestamp: Timestamp) -> zenoh::Result { //! // @TODO: //! // delete the actual entry from storage //! return Ok(StorageInsertionResult::Deleted); //! } //! //! // When receiving a GET operation -//! async fn get(&mut self, key_expr: Option, parameters: &str) -> ZResult> { +//! async fn get(&mut self, key_expr: Option, parameters: &str) -> zenoh::Result> { //! // @TODO: //! // get the data associated with key_expr and return it //! // NOTE: in case parameters is not empty something smarter should be done with returned data... @@ -114,7 +114,7 @@ //! } //! //! // To get all entries in the datastore -//! async fn get_all_entries(&self) -> ZResult, Timestamp)>> { +//! async fn get_all_entries(&self) -> zenoh::Result, Timestamp)>> { //! // @TODO: get the list of (key, timestamp) in the datastore //! Ok(Vec::new()) //! } From 809212e68880deab31b269891ee57b558b12a87f Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 15:08:03 +0200 Subject: [PATCH 28/34] fix: fix merge --- zenoh/src/api/session.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index a55455aaf3..dbcd650b56 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -734,8 +734,6 @@ impl Session { SubscriberBuilder { session: self, key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), - #[cfg(feature = "unstable")] - reliability: Reliability::DEFAULT, origin: Locality::default(), handler: DefaultHandler::default(), } From e33578f2dda44d529fa1bb3b6ca4c65b39913e1f Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 11 Sep 2024 17:44:03 +0200 Subject: [PATCH 29/34] Fix shm test --- zenoh/tests/shm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenoh/tests/shm.rs b/zenoh/tests/shm.rs index 9d353bcddd..8e1205f711 100644 --- a/zenoh/tests/shm.rs +++ b/zenoh/tests/shm.rs @@ -28,7 +28,7 @@ use zenoh::{ zshm, BlockOn, GarbageCollect, PosixShmProviderBackend, ShmProviderBuilder, POSIX_PROTOCOL_ID, }, - Session, + Session, Wait, }; use zenoh_core::ztimeout; From 88b05ee2a903db1e2c994043483773b24856060b Mon Sep 17 00:00:00 2001 From: Luca Cominardi Date: Wed, 11 Sep 2024 18:17:32 +0200 Subject: [PATCH 30/34] Fix clippy warnings --- examples/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/src/lib.rs b/examples/src/lib.rs index bb6b025b2b..20409b4f85 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -3,7 +3,7 @@ //! Check ../README.md for usage. //! -use zenoh::config::{Config, ValidatedMap}; +use zenoh::config::Config; #[derive(clap::ValueEnum, Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum Wai { From 09317d6eb11fa1808f1479efff47b270ed4088d4 Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 21:25:55 +0200 Subject: [PATCH 31/34] refactor: use builder method for undeclaration on drop --- zenoh-ext/src/querying_subscriber.rs | 76 +++++++++++++++++++++++++--- zenoh-ext/src/subscriber_ext.rs | 4 ++ zenoh/src/api/handlers/callback.rs | 4 -- zenoh/src/api/handlers/mod.rs | 6 --- zenoh/src/api/liveliness.rs | 50 +++++++++++------- zenoh/src/api/publisher.rs | 27 ++++++++-- zenoh/src/api/query.rs | 2 +- zenoh/src/api/queryable.rs | 43 ++++++++++++---- zenoh/src/api/session.rs | 2 + zenoh/src/api/subscriber.rs | 34 +++++++++++-- 10 files changed, 198 insertions(+), 50 deletions(-) diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 97c9e10101..31b058d8c2 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -49,10 +49,17 @@ pub struct QueryingSubscriberBuilder<'a, 'b, KeySpace, Handler> { pub(crate) query_accept_replies: ReplyKeyExpr, pub(crate) query_timeout: Duration, pub(crate) handler: Handler, + pub(crate) undeclare_on_drop: bool, } impl<'a, 'b, KeySpace> QueryingSubscriberBuilder<'a, 'b, KeySpace, DefaultHandler> { /// Add callback to [`FetchingSubscriber`]. + /// + /// Subscriber will not be undeclared when dropped, with the callback running + /// in background until the session is closed. + /// + /// It is in fact just a convenient shortcut for + /// `.with(my_callback).undeclare_on_drop(false)`. #[inline] pub fn callback( self, @@ -61,14 +68,17 @@ impl<'a, 'b, KeySpace> QueryingSubscriberBuilder<'a, 'b, KeySpace, DefaultHandle where Callback: Fn(Sample) + Send + Sync + 'static, { - self.with(callback) + self.with(callback).undeclare_on_drop(false) } /// Add callback to [`FetchingSubscriber`]. /// /// Using this guarantees that your callback will never be called concurrently. /// If your callback is also accepted by the [`callback`](QueryingSubscriberBuilder::callback) - /// method, we suggest you use it instead of `callback_mut` + /// method, we suggest you use it instead of `callback_mut`. + /// + /// Subscriber will not be undeclared when dropped, with the callback running + /// in background until the session is closed. #[inline] pub fn callback_mut( self, @@ -100,6 +110,7 @@ impl<'a, 'b, KeySpace> QueryingSubscriberBuilder<'a, 'b, KeySpace, DefaultHandle query_accept_replies, query_timeout, handler: _, + undeclare_on_drop, } = self; QueryingSubscriberBuilder { session, @@ -112,6 +123,7 @@ impl<'a, 'b, KeySpace> QueryingSubscriberBuilder<'a, 'b, KeySpace, DefaultHandle query_accept_replies, query_timeout, handler, + undeclare_on_drop, } } } @@ -202,6 +214,18 @@ impl<'a, 'b, KeySpace, Handler> QueryingSubscriberBuilder<'a, 'b, KeySpace, Hand self.query_timeout = query_timeout; self } + + /// Set whether the subscriber will be undeclared when dropped. + /// + /// The method is usually used in combination with a callback like in + /// [`callback`](Self::callback) method, or a channel sender. + /// Be careful when using it, as subscribers not undeclared will consume + /// resources until the session is closed. + #[inline] + pub fn undeclare_on_drop(mut self, undeclare_on_drop: bool) -> Self { + self.undeclare_on_drop = undeclare_on_drop; + self + } } impl<'a, KeySpace, Handler> Resolvable for QueryingSubscriberBuilder<'a, '_, KeySpace, Handler> @@ -254,6 +278,7 @@ where .wait(), }, handler: self.handler, + undeclare_on_drop: self.undeclare_on_drop, phantom: std::marker::PhantomData, } .wait() @@ -352,6 +377,7 @@ pub struct FetchingSubscriberBuilder< pub(crate) origin: Locality, pub(crate) fetch: Fetch, pub(crate) handler: Handler, + pub(crate) undeclare_on_drop: bool, pub(crate) phantom: std::marker::PhantomData, } @@ -376,6 +402,7 @@ where origin: self.origin, fetch: self.fetch, handler: self.handler, + undeclare_on_drop: self.undeclare_on_drop, phantom: std::marker::PhantomData, } } @@ -392,6 +419,12 @@ where TryIntoSample: ExtractSample, { /// Add callback to [`FetchingSubscriber`]. + /// + /// Subscriber will not be undeclared when dropped, with the callback running + /// in background until the session is closed. + /// + /// It is in fact just a convenient shortcut for + /// `.with(my_callback).undeclare_on_drop(false)`. #[inline] pub fn callback( self, @@ -400,14 +433,17 @@ where where Callback: Fn(Sample) + Send + Sync + 'static, { - self.with(callback) + self.with(callback).undeclare_on_drop(false) } /// Add callback to [`FetchingSubscriber`]. /// /// Using this guarantees that your callback will never be called concurrently. /// If your callback is also accepted by the [`callback`](FetchingSubscriberBuilder::callback) - /// method, we suggest you use it instead of `callback_mut` + /// method, we suggest you use it instead of `callback_mut`. + /// + /// Subscriber will not be undeclared when dropped, with the callback running + /// in background until the session is closed. #[inline] pub fn callback_mut( self, @@ -442,6 +478,7 @@ where origin, fetch, handler: _, + undeclare_on_drop, phantom, } = self; FetchingSubscriberBuilder { @@ -451,6 +488,7 @@ where origin, fetch, handler, + undeclare_on_drop, phantom, } } @@ -509,6 +547,30 @@ where } } +impl< + 'a, + 'b, + KeySpace, + Handler, + Fetch: FnOnce(Box) -> ZResult<()>, + TryIntoSample, + > FetchingSubscriberBuilder<'a, 'b, KeySpace, Handler, Fetch, TryIntoSample> +where + TryIntoSample: ExtractSample, +{ + /// Set whether the subscriber will be undeclared when dropped. + /// + /// The method is usually used in combination with a callback like in + /// [`callback`](Self::callback) method, or a channel sender. + /// Be careful when using it, as subscribers not undeclared will consume + /// resources until the session is closed. + #[inline] + pub fn undeclare_on_drop(mut self, undeclare_on_drop: bool) -> Self { + self.undeclare_on_drop = undeclare_on_drop; + self + } +} + impl< 'a, KeySpace, @@ -671,14 +733,16 @@ impl FetchingSubscriber { crate::KeySpace::User => conf .session .declare_subscriber(&key_expr) - .callback(sub_callback) + .with(sub_callback) + .undeclare_on_drop(conf.undeclare_on_drop) .allowed_origin(conf.origin) .wait()?, crate::KeySpace::Liveliness => conf .session .liveliness() .declare_subscriber(&key_expr) - .callback(sub_callback) + .with(sub_callback) + .undeclare_on_drop(conf.undeclare_on_drop) .wait()?, }; diff --git a/zenoh-ext/src/subscriber_ext.rs b/zenoh-ext/src/subscriber_ext.rs index 6fd68bdd35..a48c4fe500 100644 --- a/zenoh-ext/src/subscriber_ext.rs +++ b/zenoh-ext/src/subscriber_ext.rs @@ -173,6 +173,7 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> for SubscriberBuilde origin: self.origin, fetch, handler: self.handler, + undeclare_on_drop: true, phantom: std::marker::PhantomData, } } @@ -219,6 +220,7 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> for SubscriberBuilde query_consolidation: QueryConsolidation::from(zenoh::query::ConsolidationMode::None), query_accept_replies: ReplyKeyExpr::default(), query_timeout: Duration::from_secs(10), + undeclare_on_drop: true, handler: self.handler, } } @@ -282,6 +284,7 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> origin: Locality::default(), fetch, handler: self.handler, + undeclare_on_drop: true, phantom: std::marker::PhantomData, } } @@ -327,6 +330,7 @@ impl<'a, 'b, Handler> SubscriberBuilderExt<'a, 'b, Handler> query_consolidation: QueryConsolidation::DEFAULT, query_accept_replies: ReplyKeyExpr::MatchingQuery, query_timeout: Duration::from_secs(10), + undeclare_on_drop: true, handler: self.handler, } } diff --git a/zenoh/src/api/handlers/callback.rs b/zenoh/src/api/handlers/callback.rs index 26b1e89f28..4022fb85da 100644 --- a/zenoh/src/api/handlers/callback.rs +++ b/zenoh/src/api/handlers/callback.rs @@ -31,8 +31,6 @@ where { type Handler = (); - const BACKGROUND: bool = true; - fn into_handler(self) -> (Callback<'a, T>, Self::Handler) { (Dyn::from(self), ()) } @@ -87,8 +85,6 @@ where { type Handler = (); - const BACKGROUND: bool = true; - fn into_handler(self) -> (Callback<'a, Event>, Self::Handler) { (Dyn::from(move |evt| (self.callback)(evt)), ()) } diff --git a/zenoh/src/api/handlers/mod.rs b/zenoh/src/api/handlers/mod.rs index f21d437443..60ec658a4d 100644 --- a/zenoh/src/api/handlers/mod.rs +++ b/zenoh/src/api/handlers/mod.rs @@ -35,12 +35,6 @@ pub type Dyn = std::sync::Arc; pub trait IntoHandler<'a, T> { type Handler; - /// If it makes sense to still run the callback in background - /// when the handler having been dropped. - /// This boolean may be used to determine if an entity declared - /// with the callback should be undeclared on drop. - const BACKGROUND: bool = false; - fn into_handler(self) -> (Callback<'a, T>, Self::Handler); } diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 6a6ef0dea5..0d9a359e75 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -169,6 +169,7 @@ impl<'a> Liveliness<'a> { key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), handler: DefaultHandler::default(), history: false, + undeclare_on_drop: true, } } @@ -427,12 +428,19 @@ pub struct LivelinessSubscriberBuilder<'a, 'b, Handler> { pub key_expr: ZResult>, pub handler: Handler, pub history: bool, + pub undeclare_on_drop: bool, } #[zenoh_macros::unstable] impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { /// Receive the samples for this liveliness subscription with a callback. /// + /// Liveliness subscriber will not be undeclared when dropped, + /// with the callback running in background until the session is closed. + /// + /// It is in fact just a convenient shortcut for + /// `.with(my_callback).undeclare_on_drop(false)`. + /// /// # Examples /// ``` /// # #[tokio::main] @@ -456,13 +464,16 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Sample) + Send + Sync + 'static, { - self.with(callback) + self.with(callback).undeclare_on_drop(false) } /// Receive the samples for this liveliness subscription with a mutable callback. /// /// Using this guarantees that your callback will never be called concurrently. - /// If your callback is also accepted by the [`callback`](LivelinessSubscriberBuilder::callback) method, we suggest you use it instead of `callback_mut` + /// If your callback is also accepted by the [`callback`](LivelinessSubscriberBuilder::callback) method, we suggest you use it instead of `callback_mut`. + /// + /// Liveliness subscriber will not be undeclared when dropped, + /// with the callback running in background until the session is closed. /// /// # Examples /// ``` @@ -521,33 +532,36 @@ impl<'a, 'b> LivelinessSubscriberBuilder<'a, 'b, DefaultHandler> { key_expr, handler: _, history, + undeclare_on_drop, } = self; LivelinessSubscriberBuilder { session, key_expr, handler, history, + undeclare_on_drop, } } } -#[zenoh_macros::unstable] impl LivelinessSubscriberBuilder<'_, '_, Handler> { + /// Set whether the liveliness subscriber will be undeclared when dropped. + /// + /// The method is usually used in combination with a callback like in + /// [`callback`](Self::callback) method, or a channel sender. + /// Be careful when using it, as liveliness subscribers not undeclared will consume + /// resources until the session is closed. + #[inline] + pub fn undeclare_on_drop(mut self, undeclare_on_drop: bool) -> Self { + self.undeclare_on_drop = undeclare_on_drop; + self + } + #[inline] #[zenoh_macros::unstable] - pub fn history(self, history: bool) -> Self { - let LivelinessSubscriberBuilder { - session, - key_expr, - handler, - history: _, - } = self; - LivelinessSubscriberBuilder { - session, - key_expr, - handler, - history, - } + pub fn history(mut self, history: bool) -> Self { + self.history = history; + self } } @@ -588,7 +602,7 @@ where session: self.session.downgrade(), state: sub_state, kind: SubscriberKind::LivelinessSubscriber, - undeclare_on_drop: !Handler::BACKGROUND, + undeclare_on_drop: self.undeclare_on_drop, }, handler, }) @@ -669,7 +683,7 @@ impl<'a, 'b> LivelinessGetBuilder<'a, 'b, DefaultHandler> { /// Receive the replies for this liveliness query with a mutable callback. /// /// Using this guarantees that your callback will never be called concurrently. - /// If your callback is also accepted by the [`callback`](LivelinessGetBuilder::callback) method, we suggest you use it instead of `callback_mut` + /// If your callback is also accepted by the [`callback`](LivelinessGetBuilder::callback) method, we suggest you use it instead of `callback_mut`. /// /// # Examples /// ``` diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index fc614ffb22..2a28ddf47a 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -282,6 +282,7 @@ impl<'a> Publisher<'a> { MatchingListenerBuilder { publisher: self, handler: DefaultHandler::default(), + undeclare_on_drop: true, } } @@ -633,6 +634,7 @@ impl MatchingStatus { pub struct MatchingListenerBuilder<'a, 'b, Handler> { pub(crate) publisher: &'a Publisher<'b>, pub handler: Handler, + pub(crate) undeclare_on_drop: bool, } #[zenoh_macros::unstable] @@ -665,7 +667,7 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(MatchingStatus) + Send + Sync + 'static, { - self.with(callback) + self.with(callback).undeclare_on_drop(false) } /// Receive the MatchingStatuses for this listener with a mutable callback. @@ -729,8 +731,27 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { let MatchingListenerBuilder { publisher, handler: _, + undeclare_on_drop, } = self; - MatchingListenerBuilder { publisher, handler } + MatchingListenerBuilder { + publisher, + handler, + undeclare_on_drop, + } + } +} + +impl MatchingListenerBuilder<'_, '_, Handler> { + /// Set whether the matching listener will be undeclared when dropped. + /// + /// The method is usually used in combination with a callback like in + /// [`callback`](Self::callback) method, or a channel sender. + /// Be careful when using it, as matching listeners not undeclared will consume + /// resources until the publisher is undeclared. + #[inline] + pub fn undeclare_on_drop(mut self, undeclare_on_drop: bool) -> Self { + self.undeclare_on_drop = undeclare_on_drop; + self } } @@ -762,7 +783,7 @@ where session: self.publisher.session.clone(), matching_listeners: self.publisher.matching_listeners.clone(), state, - undeclare_on_drop: !Handler::BACKGROUND, + undeclare_on_drop: self.undeclare_on_drop, }, handler, }) diff --git a/zenoh/src/api/query.rs b/zenoh/src/api/query.rs index 7203d93f81..ae55d5ab8d 100644 --- a/zenoh/src/api/query.rs +++ b/zenoh/src/api/query.rs @@ -285,7 +285,7 @@ impl<'a, 'b> SessionGetBuilder<'a, 'b, DefaultHandler> { /// Receive the replies for this query with a mutable callback. /// /// Using this guarantees that your callback will never be called concurrently. - /// If your callback is also accepted by the [`callback`](crate::session::SessionGetBuilder::callback) method, we suggest you use it instead of `callback_mut` + /// If your callback is also accepted by the [`callback`](crate::session::SessionGetBuilder::callback) method, we suggest you use it instead of `callback_mut`. /// /// # Examples /// ``` diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index 3d9946a322..cd4bf9e04a 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -606,10 +606,17 @@ pub struct QueryableBuilder<'a, 'b, Handler> { pub(crate) complete: bool, pub(crate) origin: Locality, pub(crate) handler: Handler, + pub(crate) undeclare_on_drop: bool, } impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { - /// Receive the queries for this Queryable with a callback. + /// Receive the queries for this queryable with a callback. + /// + /// Queryable will not be undeclared when dropped, with the callback running + /// in background until the session is closed. + /// + /// It is in fact just a convenient shortcut for + /// `.with(my_callback).undeclare_on_drop(false)`. /// /// # Examples /// ``` @@ -629,13 +636,16 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Query) + Send + Sync + 'static, { - self.with(callback) + self.with(callback).undeclare_on_drop(false) } /// Receive the queries for this Queryable with a mutable callback. /// /// Using this guarantees that your callback will never be called concurrently. - /// If your callback is also accepted by the [`callback`](QueryableBuilder::callback) method, we suggest you use it instead of `callback_mut` + /// If your callback is also accepted by the [`callback`](QueryableBuilder::callback) method, we suggest you use it instead of `callback_mut`. + /// + /// Queryable will not be undeclared when dropped, with the callback running + /// in background until the session is closed. /// /// # Examples /// ``` @@ -691,6 +701,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler: _, + undeclare_on_drop, } = self; QueryableBuilder { session, @@ -698,8 +709,18 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { complete, origin, handler, + undeclare_on_drop, } } +} + +impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { + /// Change queryable completeness. + #[inline] + pub fn complete(mut self, complete: bool) -> Self { + self.complete = complete; + self + } /// Restrict the matching queries that will be receive by this [`Queryable`] /// to the ones that have the given [`Locality`](crate::prelude::Locality). @@ -709,12 +730,16 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { self.origin = origin; self } -} -impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { - /// Change queryable completeness. + + /// Set whether the queryable will be undeclared when dropped. + /// + /// The method is usually used in combination with a callback like in + /// [`callback`](Self::callback) method, or a channel sender. + /// Be careful when using it, as queryables not undeclared will consume + /// resources until the session is closed. #[inline] - pub fn complete(mut self, complete: bool) -> Self { - self.complete = complete; + pub fn undeclare_on_drop(mut self, undeclare_on_drop: bool) -> Self { + self.undeclare_on_drop = undeclare_on_drop; self } } @@ -909,7 +934,7 @@ where session_id: session.zid(), session: self.session.downgrade(), state: qable_state, - undeclare_on_drop: !Handler::BACKGROUND, + undeclare_on_drop: self.undeclare_on_drop, }, handler: receiver, }) diff --git a/zenoh/src/api/session.rs b/zenoh/src/api/session.rs index dbcd650b56..b147edbb01 100644 --- a/zenoh/src/api/session.rs +++ b/zenoh/src/api/session.rs @@ -736,6 +736,7 @@ impl Session { key_expr: TryIntoKeyExpr::try_into(key_expr).map_err(Into::into), origin: Locality::default(), handler: DefaultHandler::default(), + undeclare_on_drop: true, } } @@ -779,6 +780,7 @@ impl Session { complete: false, origin: Locality::default(), handler: DefaultHandler::default(), + undeclare_on_drop: true, } } diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index 01960b22e4..d2ce301333 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -142,11 +142,22 @@ pub struct SubscriberBuilder<'a, 'b, Handler> { pub handler: Handler, #[cfg(not(feature = "unstable"))] pub(crate) handler: Handler, + + #[cfg(feature = "unstable")] + pub undeclare_on_drop: bool, + #[cfg(not(feature = "unstable"))] + pub(crate) undeclare_on_drop: bool, } impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { /// Receive the samples for this subscription with a callback. /// + /// Subscriber will not be undeclared when dropped, with the callback running + /// in background until the session is closed. + /// + /// It is in fact just a convenient shortcut for + /// `.with(my_callback).undeclare_on_drop(false)`. + /// /// # Examples /// ``` /// # #[tokio::main] @@ -165,13 +176,16 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { where Callback: Fn(Sample) + Send + Sync + 'static, { - self.with(callback) + self.with(callback).undeclare_on_drop(false) } /// Receive the samples for this subscription with a mutable callback. /// /// Using this guarantees that your callback will never be called concurrently. - /// If your callback is also accepted by the [`callback`](SubscriberBuilder::callback) method, we suggest you use it instead of `callback_mut` + /// If your callback is also accepted by the [`callback`](SubscriberBuilder::callback) method, we suggest you use it instead of `callback_mut`. + /// + /// Subscriber will not be undeclared when dropped, with the callback running + /// in background until the session is closed. /// /// # Examples /// ``` @@ -226,12 +240,14 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { key_expr, origin, handler: _, + undeclare_on_drop, } = self; SubscriberBuilder { session, key_expr, origin, handler, + undeclare_on_drop, } } } @@ -278,6 +294,18 @@ impl<'a, 'b, Handler> SubscriberBuilder<'a, 'b, Handler> { self.origin = origin; self } + + /// Set whether the subscriber will be undeclared when dropped. + /// + /// The method is usually used in combination with a callback like in + /// [`callback`](Self::callback) method, or a channel sender. + /// Be careful when using it, as subscribers not undeclared will consume + /// resources until the session is closed. + #[inline] + pub fn undeclare_on_drop(mut self, undeclare_on_drop: bool) -> Self { + self.undeclare_on_drop = undeclare_on_drop; + self + } } // Push mode @@ -308,7 +336,7 @@ where session: session.downgrade(), state: sub_state, kind: SubscriberKind::Subscriber, - undeclare_on_drop: !Handler::BACKGROUND, + undeclare_on_drop: self.undeclare_on_drop, }, handler: receiver, }) From f83eb8f2c7765c6d33b03ab77f87262ba17a520e Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 21:33:41 +0200 Subject: [PATCH 32/34] fix: remove useless lifetimes --- zenoh-ext/src/querying_subscriber.rs | 22 ++++++++-------------- zenoh/src/api/liveliness.rs | 6 +++--- zenoh/src/api/publisher.rs | 6 +++--- zenoh/src/api/queryable.rs | 2 +- zenoh/src/api/subscriber.rs | 8 ++++---- 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/zenoh-ext/src/querying_subscriber.rs b/zenoh-ext/src/querying_subscriber.rs index 31b058d8c2..9796109510 100644 --- a/zenoh-ext/src/querying_subscriber.rs +++ b/zenoh-ext/src/querying_subscriber.rs @@ -128,7 +128,7 @@ impl<'a, 'b, KeySpace> QueryingSubscriberBuilder<'a, 'b, KeySpace, DefaultHandle } } -impl<'a, 'b, Handler> QueryingSubscriberBuilder<'a, 'b, crate::UserSpace, Handler> { +impl<'b, Handler> QueryingSubscriberBuilder<'_, 'b, crate::UserSpace, Handler> { /// Change the subscription reliability. #[cfg(feature = "unstable")] #[deprecated( @@ -207,7 +207,7 @@ impl<'a, 'b, Handler> QueryingSubscriberBuilder<'a, 'b, crate::UserSpace, Handle } } -impl<'a, 'b, KeySpace, Handler> QueryingSubscriberBuilder<'a, 'b, KeySpace, Handler> { +impl QueryingSubscriberBuilder<'_, '_, KeySpace, Handler> { /// Change the timeout to be used for queries. #[inline] pub fn query_timeout(mut self, query_timeout: Duration) -> Self { @@ -228,7 +228,7 @@ impl<'a, 'b, KeySpace, Handler> QueryingSubscriberBuilder<'a, 'b, KeySpace, Hand } } -impl<'a, KeySpace, Handler> Resolvable for QueryingSubscriberBuilder<'a, '_, KeySpace, Handler> +impl Resolvable for QueryingSubscriberBuilder<'_, '_, KeySpace, Handler> where Handler: IntoHandler<'static, Sample>, Handler::Handler: Send, @@ -285,7 +285,7 @@ where } } -impl<'a, KeySpace, Handler> IntoFuture for QueryingSubscriberBuilder<'a, '_, KeySpace, Handler> +impl IntoFuture for QueryingSubscriberBuilder<'_, '_, KeySpace, Handler> where KeySpace: Into + Clone, Handler: IntoHandler<'static, Sample> + Send, @@ -495,12 +495,10 @@ where } impl< - 'a, - 'b, Handler, Fetch: FnOnce(Box) -> ZResult<()>, TryIntoSample, - > FetchingSubscriberBuilder<'a, 'b, crate::UserSpace, Handler, Fetch, TryIntoSample> + > FetchingSubscriberBuilder<'_, '_, crate::UserSpace, Handler, Fetch, TryIntoSample> where TryIntoSample: ExtractSample, { @@ -548,13 +546,11 @@ where } impl< - 'a, - 'b, KeySpace, Handler, Fetch: FnOnce(Box) -> ZResult<()>, TryIntoSample, - > FetchingSubscriberBuilder<'a, 'b, KeySpace, Handler, Fetch, TryIntoSample> + > FetchingSubscriberBuilder<'_, '_, KeySpace, Handler, Fetch, TryIntoSample> where TryIntoSample: ExtractSample, { @@ -572,12 +568,11 @@ where } impl< - 'a, KeySpace, Handler, Fetch: FnOnce(Box) -> ZResult<()>, TryIntoSample, - > Resolvable for FetchingSubscriberBuilder<'a, '_, KeySpace, Handler, Fetch, TryIntoSample> + > Resolvable for FetchingSubscriberBuilder<'_, '_, KeySpace, Handler, Fetch, TryIntoSample> where Handler: IntoHandler<'static, Sample>, Handler::Handler: Send, @@ -604,12 +599,11 @@ where } impl< - 'a, KeySpace, Handler, Fetch: FnOnce(Box) -> ZResult<()> + Send + Sync, TryIntoSample, - > IntoFuture for FetchingSubscriberBuilder<'a, '_, KeySpace, Handler, Fetch, TryIntoSample> + > IntoFuture for FetchingSubscriberBuilder<'_, '_, KeySpace, Handler, Fetch, TryIntoSample> where KeySpace: Into, Handler: IntoHandler<'static, Sample> + Send, diff --git a/zenoh/src/api/liveliness.rs b/zenoh/src/api/liveliness.rs index 0d9a359e75..58d6ea7a71 100644 --- a/zenoh/src/api/liveliness.rs +++ b/zenoh/src/api/liveliness.rs @@ -575,7 +575,7 @@ where } #[zenoh_macros::unstable] -impl<'a, Handler> Wait for LivelinessSubscriberBuilder<'a, '_, Handler> +impl Wait for LivelinessSubscriberBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, @@ -610,7 +610,7 @@ where } #[zenoh_macros::unstable] -impl<'a, Handler> IntoFuture for LivelinessSubscriberBuilder<'a, '_, Handler> +impl IntoFuture for LivelinessSubscriberBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, @@ -750,7 +750,7 @@ impl<'a, 'b> LivelinessGetBuilder<'a, 'b, DefaultHandler> { } } -impl<'a, 'b, Handler> LivelinessGetBuilder<'a, 'b, Handler> { +impl LivelinessGetBuilder<'_, '_, Handler> { /// Set query timeout. #[inline] pub fn timeout(mut self, timeout: Duration) -> Self { diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 2a28ddf47a..1f3ac479f1 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -756,7 +756,7 @@ impl MatchingListenerBuilder<'_, '_, Handler> { } #[zenoh_macros::unstable] -impl<'a, 'b, Handler> Resolvable for MatchingListenerBuilder<'a, 'b, Handler> +impl Resolvable for MatchingListenerBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, @@ -765,7 +765,7 @@ where } #[zenoh_macros::unstable] -impl<'a, 'b, Handler> Wait for MatchingListenerBuilder<'a, 'b, Handler> +impl Wait for MatchingListenerBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, @@ -791,7 +791,7 @@ where } #[zenoh_macros::unstable] -impl<'a, 'b, Handler> IntoFuture for MatchingListenerBuilder<'a, 'b, Handler> +impl IntoFuture for MatchingListenerBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, MatchingStatus> + Send, Handler::Handler: Send, diff --git a/zenoh/src/api/queryable.rs b/zenoh/src/api/queryable.rs index cd4bf9e04a..951600d1e6 100644 --- a/zenoh/src/api/queryable.rs +++ b/zenoh/src/api/queryable.rs @@ -714,7 +714,7 @@ impl<'a, 'b> QueryableBuilder<'a, 'b, DefaultHandler> { } } -impl<'a, 'b, Handler> QueryableBuilder<'a, 'b, Handler> { +impl QueryableBuilder<'_, '_, Handler> { /// Change queryable completeness. #[inline] pub fn complete(mut self, complete: bool) -> Self { diff --git a/zenoh/src/api/subscriber.rs b/zenoh/src/api/subscriber.rs index d2ce301333..ac5202ed85 100644 --- a/zenoh/src/api/subscriber.rs +++ b/zenoh/src/api/subscriber.rs @@ -252,7 +252,7 @@ impl<'a, 'b> SubscriberBuilder<'a, 'b, DefaultHandler> { } } -impl<'a, 'b, Handler> SubscriberBuilder<'a, 'b, Handler> { +impl SubscriberBuilder<'_, '_, Handler> { /// Change the subscription reliability. #[cfg(feature = "unstable")] #[deprecated( @@ -309,7 +309,7 @@ impl<'a, 'b, Handler> SubscriberBuilder<'a, 'b, Handler> { } // Push mode -impl<'a, Handler> Resolvable for SubscriberBuilder<'a, '_, Handler> +impl Resolvable for SubscriberBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, @@ -317,7 +317,7 @@ where type To = ZResult>; } -impl<'a, Handler> Wait for SubscriberBuilder<'a, '_, Handler> +impl Wait for SubscriberBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, @@ -343,7 +343,7 @@ where } } -impl<'a, Handler> IntoFuture for SubscriberBuilder<'a, '_, Handler> +impl IntoFuture for SubscriberBuilder<'_, '_, Handler> where Handler: IntoHandler<'static, Sample> + Send, Handler::Handler: Send, From acab2bf19004ae8ac3356760f327deeea6f942be Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 21:52:52 +0200 Subject: [PATCH 33/34] fix: add missing unstable flag --- zenoh/src/api/publisher.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zenoh/src/api/publisher.rs b/zenoh/src/api/publisher.rs index 1f3ac479f1..fcd4ce59d3 100644 --- a/zenoh/src/api/publisher.rs +++ b/zenoh/src/api/publisher.rs @@ -741,6 +741,7 @@ impl<'a, 'b> MatchingListenerBuilder<'a, 'b, DefaultHandler> { } } +#[zenoh_macros::unstable] impl MatchingListenerBuilder<'_, '_, Handler> { /// Set whether the matching listener will be undeclared when dropped. /// From 9ff17560d49a9552600cd80f30c86aa190257ecc Mon Sep 17 00:00:00 2001 From: Joseph Perez Date: Wed, 11 Sep 2024 22:02:27 +0200 Subject: [PATCH 34/34] feat: add tuple implementation for IntoHandler --- zenoh/src/api/handlers/callback.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/zenoh/src/api/handlers/callback.rs b/zenoh/src/api/handlers/callback.rs index 4022fb85da..7e609949ef 100644 --- a/zenoh/src/api/handlers/callback.rs +++ b/zenoh/src/api/handlers/callback.rs @@ -36,6 +36,25 @@ where } } +impl<'a, T, F, H> IntoHandler<'a, T> for (F, H) +where + F: Fn(T) + Send + Sync + 'a, +{ + type Handler = H; + + fn into_handler(self) -> (Callback<'a, T>, Self::Handler) { + (Dyn::from(self.0), self.1) + } +} + +impl<'a, T, H> IntoHandler<'a, T> for (Callback<'static, T>, H) { + type Handler = H; + + fn into_handler(self) -> (Callback<'a, T>, Self::Handler) { + self + } +} + impl IntoHandler<'static, T> for (flume::Sender, flume::Receiver) { type Handler = flume::Receiver;