diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs index 24e91d998..d14c0719d 100644 --- a/build-resources/opaque-types/src/lib.rs +++ b/build-resources/opaque-types/src/lib.rs @@ -14,6 +14,7 @@ use zenoh::{ config::Config, handlers::{FifoChannelHandler, RingChannelHandler}, key_expr::KeyExpr, + liveliness::LivelinessToken, pubsub::{Publisher, Subscriber}, query::{Query, Queryable, Reply, ReplyError}, sample::Sample, @@ -23,10 +24,8 @@ use zenoh::{ }; #[cfg(feature = "unstable")] use zenoh::{ - matching::MatchingListener, query::Querier, sample::SourceInfo, - session::EntityGlobalId, + matching::MatchingListener, query::Querier, sample::SourceInfo, session::EntityGlobalId, }; -use zenoh::liveliness::LivelinessToken; #[cfg(all(feature = "shared-memory", feature = "unstable"))] use zenoh::{ shm::zshm, shm::zshmmut, shm::AllocLayout, shm::ChunkAllocResult, shm::ChunkDescriptor, @@ -159,6 +158,51 @@ get_opaque_type_data!( ze_loaned_querying_subscriber_t ); +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief An owned Zenoh advanced subscriber. +/// +/// In addition to receiving the data it is subscribed to, +/// it is also able to receive notifications regarding missed samples and/or automatically recover them. +get_opaque_type_data!( + Option>, + ze_owned_advanced_subscriber_t +); +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief A loaned Zenoh advanced subscriber. +get_opaque_type_data!( + zenoh_ext::AdvancedSubscriber<()>, + ze_loaned_advanced_subscriber_t +); +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief An owned Zenoh sample miss listener. Missed samples can only be detected from advanced publishers, enabling sample miss detection. +/// +/// A listener that sends notification when the advanced subscriber misses a sample . +/// Dropping the corresponding subscriber, also drops the listener. +get_opaque_type_data!( + Option>, + ze_owned_sample_miss_listener_t +); + +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief An owned Zenoh advanced publisher. +/// +/// In addition to publishing the data, +/// it also maintains the storage, allowing matching subscribers to retrive missed samples. +get_opaque_type_data!( + Option>, + ze_owned_advanced_publisher_t +); +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief A loaned Zenoh advanced publisher. +get_opaque_type_data!( + zenoh_ext::AdvancedPublisher<'static>, + ze_loaned_advanced_publisher_t +); /// A Zenoh-allocated key expression . /// /// Key expressions can identify a single key or a set of keys. @@ -197,7 +241,10 @@ get_opaque_type_data!(Session, z_loaned_session_t); #[cfg(feature = "unstable")] /// An owned Close handle -get_opaque_type_data!(Option>>, zc_owned_concurrent_close_handle_t); +get_opaque_type_data!( + Option>>, + zc_owned_concurrent_close_handle_t +); /// An owned Zenoh configuration. get_opaque_type_data!(Option, z_owned_config_t); diff --git a/docs/api.rst b/docs/api.rst index f121e8150..e1e2a063d 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -95,121 +95,6 @@ Functions Common ====== -Serialization / Deserialization -------------------------------- -Types -^^^^^ -.. doxygenstruct:: z_owned_bytes_t -.. doxygenstruct:: z_loaned_bytes_t -.. doxygenstruct:: z_bytes_reader_t -.. doxygenstruct:: z_owned_bytes_writer_t -.. doxygenstruct:: z_loaned_bytes_writer_t -.. doxygenstruct:: ze_owned_serializer_t -.. doxygenstruct:: ze_loaned_serializer_t -.. doxygenstruct:: ze_deserializer_t - -Functions -^^^^^^^^^ -.. doxygenfunction:: z_bytes_len -.. doxygenfunction:: z_bytes_copy_from_slice -.. doxygenfunction:: z_bytes_from_slice -.. doxygenfunction:: z_bytes_copy_from_buf -.. doxygenfunction:: z_bytes_from_buf -.. doxygenfunction:: z_bytes_from_static_buf -.. doxygenfunction:: z_bytes_copy_from_string -.. doxygenfunction:: z_bytes_from_string -.. doxygenfunction:: z_bytes_copy_from_str -.. doxygenfunction:: z_bytes_from_str -.. doxygenfunction:: z_bytes_from_static_str -.. doxygenfunction:: z_bytes_to_slice -.. doxygenfunction:: z_bytes_to_string - -.. doxygenfunction:: ze_serialize_slice -.. doxygenfunction:: ze_serialize_buf -.. doxygenfunction:: ze_serialize_string -.. doxygenfunction:: ze_serialize_str -.. doxygenfunction:: ze_serialize_substr -.. doxygenfunction:: ze_serialize_uint8 -.. doxygenfunction:: ze_serialize_uint16 -.. doxygenfunction:: ze_serialize_uint32 -.. doxygenfunction:: ze_serialize_uint64 -.. doxygenfunction:: ze_serialize_int8 -.. doxygenfunction:: ze_serialize_int16 -.. doxygenfunction:: ze_serialize_int32 -.. doxygenfunction:: ze_serialize_int64 -.. doxygenfunction:: ze_serialize_float -.. doxygenfunction:: ze_serialize_double -.. doxygenfunction:: ze_serialize_bool - -.. doxygenfunction:: ze_deserialize_slice -.. doxygenfunction:: ze_deserialize_string -.. doxygenfunction:: ze_deserialize_uint8 -.. doxygenfunction:: ze_deserialize_uint16 -.. doxygenfunction:: ze_deserialize_uint32 -.. doxygenfunction:: ze_deserialize_uint64 -.. doxygenfunction:: ze_deserialize_int8 -.. doxygenfunction:: ze_deserialize_int16 -.. doxygenfunction:: ze_deserialize_int32 -.. doxygenfunction:: ze_deserialize_int64 -.. doxygenfunction:: ze_deserialize_float -.. doxygenfunction:: ze_deserialize_double -.. doxygenfunction:: ze_deserialize_bool - -.. doxygenfunction:: z_bytes_empty -.. doxygenfunction:: z_bytes_clone -.. doxygenfunction:: z_bytes_loan -.. doxygenfunction:: z_bytes_loan_mut -.. doxygenfunction:: z_bytes_drop - -.. doxygenfunction:: z_bytes_get_reader -.. doxygenfunction:: z_bytes_reader_read -.. doxygenfunction:: z_bytes_reader_seek -.. doxygenfunction:: z_bytes_reader_tell -.. doxygenfunction:: z_bytes_reader_remaining - -.. doxygenfunction:: z_bytes_writer_empty -.. doxygenfunction:: z_bytes_writer_finish -.. doxygenfunction:: z_bytes_writer_write_all -.. doxygenfunction:: z_bytes_writer_append - -.. doxygenfunction:: ze_serializer_empty -.. doxygenfunction:: ze_serializer_finish -.. doxygenfunction:: ze_serializer_serialize_slice -.. doxygenfunction:: ze_serializer_serialize_buf -.. doxygenfunction:: ze_serializer_serialize_string -.. doxygenfunction:: ze_serializer_serialize_str -.. doxygenfunction:: ze_serializer_serialize_substr -.. doxygenfunction:: ze_serializer_serialize_uint8 -.. doxygenfunction:: ze_serializer_serialize_uint16 -.. doxygenfunction:: ze_serializer_serialize_uint32 -.. doxygenfunction:: ze_serializer_serialize_uint64 -.. doxygenfunction:: ze_serializer_serialize_int8 -.. doxygenfunction:: ze_serializer_serialize_int16 -.. doxygenfunction:: ze_serializer_serialize_int32 -.. doxygenfunction:: ze_serializer_serialize_int64 -.. doxygenfunction:: ze_serializer_serialize_float -.. doxygenfunction:: ze_serializer_serialize_double -.. doxygenfunction:: ze_serializer_serialize_bool -.. doxygenfunction:: ze_serializer_serialize_sequence_length - -.. doxygenfunction:: ze_deserializer_from_bytes -.. doxygenfunction:: ze_deserializer_is_done -.. doxygenfunction:: ze_deserializer_deserialize_slice -.. doxygenfunction:: ze_deserializer_deserialize_string -.. doxygenfunction:: ze_deserializer_deserialize_uint8 -.. doxygenfunction:: ze_deserializer_deserialize_uint16 -.. doxygenfunction:: ze_deserializer_deserialize_uint32 -.. doxygenfunction:: ze_deserializer_deserialize_uint64 -.. doxygenfunction:: ze_deserializer_deserialize_int8 -.. doxygenfunction:: ze_deserializer_deserialize_int16 -.. doxygenfunction:: ze_deserializer_deserialize_int32 -.. doxygenfunction:: ze_deserializer_deserialize_int64 -.. doxygenfunction:: ze_deserializer_deserialize_float -.. doxygenfunction:: ze_deserializer_deserialize_double -.. doxygenfunction:: ze_deserializer_deserialize_bool -.. doxygenfunction:: ze_deserializer_deserialize_sequence_length - - Key expression -------------- @@ -385,6 +270,50 @@ Functions .. doxygenfunction:: z_timestamp_id .. doxygenfunction:: z_timestamp_ntp64_time + +Payload +------- +Types +^^^^^ +.. doxygenstruct:: z_owned_bytes_t +.. doxygenstruct:: z_loaned_bytes_t +.. doxygenstruct:: z_bytes_reader_t +.. doxygenstruct:: z_owned_bytes_writer_t +.. doxygenstruct:: z_loaned_bytes_writer_t + +Functions +^^^^^^^^^ +.. doxygenfunction:: z_bytes_len +.. doxygenfunction:: z_bytes_copy_from_slice +.. doxygenfunction:: z_bytes_from_slice +.. doxygenfunction:: z_bytes_copy_from_buf +.. doxygenfunction:: z_bytes_from_buf +.. doxygenfunction:: z_bytes_from_static_buf +.. doxygenfunction:: z_bytes_copy_from_string +.. doxygenfunction:: z_bytes_from_string +.. doxygenfunction:: z_bytes_copy_from_str +.. doxygenfunction:: z_bytes_from_str +.. doxygenfunction:: z_bytes_from_static_str +.. doxygenfunction:: z_bytes_to_slice +.. doxygenfunction:: z_bytes_to_string + +.. doxygenfunction:: z_bytes_empty +.. doxygenfunction:: z_bytes_clone +.. doxygenfunction:: z_bytes_loan +.. doxygenfunction:: z_bytes_loan_mut +.. doxygenfunction:: z_bytes_drop + +.. doxygenfunction:: z_bytes_get_reader +.. doxygenfunction:: z_bytes_reader_read +.. doxygenfunction:: z_bytes_reader_seek +.. doxygenfunction:: z_bytes_reader_tell +.. doxygenfunction:: z_bytes_reader_remaining + +.. doxygenfunction:: z_bytes_writer_empty +.. doxygenfunction:: z_bytes_writer_finish +.. doxygenfunction:: z_bytes_writer_write_all +.. doxygenfunction:: z_bytes_writer_append + System ====== @@ -876,12 +805,194 @@ Functions .. doxygenfunction:: z_liveliness_token_options_default .. doxygenfunction:: z_liveliness_get_options_default -Publication Cache -================= +Logging +======= Types ----- +.. doxygenstruct:: zc_owned_closure_log_t +.. doxygenstruct:: zc_loaned_closure_log_t +.. doxygenenum:: zc_log_severity_t + +Functions +--------- + +.. doxygenfunction:: zc_try_init_log_from_env +.. doxygenfunction:: zc_init_log_from_env_or +.. doxygenfunction:: zc_init_log_with_callback + +.. doxygenfunction:: zc_closure_log_call +.. doxygenfunction:: zc_closure_log_loan +.. doxygenfunction:: zc_closure_log_drop +.. doxygenfunction:: zc_closure_log + + +Other +===== + +Functions +--------- +.. doxygenfunction:: zc_stop_z_runtime +.. doxygenfunction:: zc_cleanup_orphaned_shm_segments + +Ext +=== + +Serialization / Deserialization +------------------------------- +Types +^^^^^ +.. doxygenstruct:: ze_owned_serializer_t +.. doxygenstruct:: ze_loaned_serializer_t +.. doxygenstruct:: ze_deserializer_t + +Functions +^^^^^^^^^ +.. doxygenfunction:: ze_serialize_slice +.. doxygenfunction:: ze_serialize_buf +.. doxygenfunction:: ze_serialize_string +.. doxygenfunction:: ze_serialize_str +.. doxygenfunction:: ze_serialize_substr +.. doxygenfunction:: ze_serialize_uint8 +.. doxygenfunction:: ze_serialize_uint16 +.. doxygenfunction:: ze_serialize_uint32 +.. doxygenfunction:: ze_serialize_uint64 +.. doxygenfunction:: ze_serialize_int8 +.. doxygenfunction:: ze_serialize_int16 +.. doxygenfunction:: ze_serialize_int32 +.. doxygenfunction:: ze_serialize_int64 +.. doxygenfunction:: ze_serialize_float +.. doxygenfunction:: ze_serialize_double +.. doxygenfunction:: ze_serialize_bool + +.. doxygenfunction:: ze_deserialize_slice +.. doxygenfunction:: ze_deserialize_string +.. doxygenfunction:: ze_deserialize_uint8 +.. doxygenfunction:: ze_deserialize_uint16 +.. doxygenfunction:: ze_deserialize_uint32 +.. doxygenfunction:: ze_deserialize_uint64 +.. doxygenfunction:: ze_deserialize_int8 +.. doxygenfunction:: ze_deserialize_int16 +.. doxygenfunction:: ze_deserialize_int32 +.. doxygenfunction:: ze_deserialize_int64 +.. doxygenfunction:: ze_deserialize_float +.. doxygenfunction:: ze_deserialize_double +.. doxygenfunction:: ze_deserialize_bool + +.. doxygenfunction:: ze_serializer_empty +.. doxygenfunction:: ze_serializer_finish +.. doxygenfunction:: ze_serializer_serialize_slice +.. doxygenfunction:: ze_serializer_serialize_buf +.. doxygenfunction:: ze_serializer_serialize_string +.. doxygenfunction:: ze_serializer_serialize_str +.. doxygenfunction:: ze_serializer_serialize_substr +.. doxygenfunction:: ze_serializer_serialize_uint8 +.. doxygenfunction:: ze_serializer_serialize_uint16 +.. doxygenfunction:: ze_serializer_serialize_uint32 +.. doxygenfunction:: ze_serializer_serialize_uint64 +.. doxygenfunction:: ze_serializer_serialize_int8 +.. doxygenfunction:: ze_serializer_serialize_int16 +.. doxygenfunction:: ze_serializer_serialize_int32 +.. doxygenfunction:: ze_serializer_serialize_int64 +.. doxygenfunction:: ze_serializer_serialize_float +.. doxygenfunction:: ze_serializer_serialize_double +.. doxygenfunction:: ze_serializer_serialize_bool +.. doxygenfunction:: ze_serializer_serialize_sequence_length + +.. doxygenfunction:: ze_deserializer_from_bytes +.. doxygenfunction:: ze_deserializer_is_done +.. doxygenfunction:: ze_deserializer_deserialize_slice +.. doxygenfunction:: ze_deserializer_deserialize_string +.. doxygenfunction:: ze_deserializer_deserialize_uint8 +.. doxygenfunction:: ze_deserializer_deserialize_uint16 +.. doxygenfunction:: ze_deserializer_deserialize_uint32 +.. doxygenfunction:: ze_deserializer_deserialize_uint64 +.. doxygenfunction:: ze_deserializer_deserialize_int8 +.. doxygenfunction:: ze_deserializer_deserialize_int16 +.. doxygenfunction:: ze_deserializer_deserialize_int32 +.. doxygenfunction:: ze_deserializer_deserialize_int64 +.. doxygenfunction:: ze_deserializer_deserialize_float +.. doxygenfunction:: ze_deserializer_deserialize_double +.. doxygenfunction:: ze_deserializer_deserialize_bool +.. doxygenfunction:: ze_deserializer_deserialize_sequence_length + +Advanced Publisher +------------------ + +Types +^^^^^ + +.. doxygenstruct:: ze_owned_advanced_publisher_t +.. doxygenstruct:: ze_loaned_advanced_publisher_t + +.. doxygenstruct:: ze_advanced_publisher_cache_options_t + :members: +.. doxygenstruct:: ze_advanced_publisher_options_t + :members: +.. doxygenstruct:: ze_advanced_publisher_put_options_t + :members: +.. doxygenstruct:: ze_advanced_publisher_delete_options_t + :members: + +Functions +^^^^^^^^^ +.. doxygenfunction:: ze_declare_advanced_publisher +.. doxygenfunction:: ze_undeclare_advanced_publisher +.. doxygenfunction:: ze_advanced_publisher_put +.. doxygenfunction:: ze_advanced_publisher_delete +.. doxygenfunction:: ze_advanced_publisher_keyexpr +.. doxygenfunction:: ze_advanced_publisher_id + +.. doxygenfunction:: ze_advanced_publisher_loan +.. doxygenfunction:: ze_advanced_publisher_drop + +.. doxygenfunction:: ze_advanced_publisher_options_default +.. doxygenfunction:: ze_advanced_publisher_cache_options_default +.. doxygenfunction:: ze_advanced_publisher_put_options_default +.. doxygenfunction:: ze_advanced_publisher_delete_options_default + +.. doxygenfunction:: ze_advanced_publisher_get_matching_status +.. doxygenfunction:: ze_advanced_publisher_declare_matching_listener +.. doxygenfunction:: ze_advanced_publisher_declare_background_matching_listener + +Advanced Subscriber +------------------- + +Types +^^^^^ +.. doxygenstruct:: ze_owned_advanced_subscriber_t +.. doxygenstruct:: ze_loaned_advanced_subscriber_t + +.. doxygenstruct:: ze_advanced_subscriber_history_options_t + :members: +.. doxygenstruct:: ze_advanced_subscriber_recovery_options_t + :members: +.. doxygenstruct:: ze_advanced_subscriber_options_t + :members: + +Functions +^^^^^^^^^ + +.. doxygenfunction:: ze_declare_advanced_subscriber +.. doxygenfunction:: ze_declare_background_advanced_subscriber +.. doxygenfunction:: ze_undeclare_advanced_subscriber + +.. doxygenfunction:: ze_advanced_subscriber_detect_publishers +.. doxygenfunction:: ze_advanced_subscriber_detect_publishers_background + +.. doxygenfunction:: ze_advanced_subscriber_drop + +.. doxygenfunction:: ze_advanced_subscriber_history_options_default +.. doxygenfunction:: ze_advanced_subscriber_recovery_options_default +.. doxygenfunction:: ze_advanced_subscriber_options_default + +Publication Cache (deprecated) +------------------------------ + +Types +^^^^^ + .. doxygenstruct:: ze_owned_publication_cache_t .. doxygenstruct:: ze_loaned_publication_cache_t .. doxygenstruct:: ze_publication_cache_options_t @@ -889,7 +1000,7 @@ Types .. doxygenenum:: zc_locality_t Functions ---------- +^^^^^^^^^ .. doxygenfunction:: ze_declare_publication_cache .. doxygenfunction:: ze_undeclare_publication_cache @@ -901,11 +1012,11 @@ Functions .. doxygenfunction:: ze_publication_cache_options_default -Querying Subscriber -=================== +Querying Subscriber (deprecated) +-------------------------------- Types ------ +^^^^^ .. doxygenstruct:: ze_owned_querying_subscriber_t .. doxygenstruct:: ze_loaned_querying_subscriber_t @@ -913,7 +1024,7 @@ Types :members: Functions ---------- +^^^^^^^^^ .. doxygenfunction:: ze_declare_querying_subscriber .. doxygenfunction:: ze_undeclare_querying_subscriber @@ -923,34 +1034,3 @@ Functions .. doxygenfunction:: ze_querying_subscriber_drop .. doxygenfunction:: ze_querying_subscriber_options_default - -Logging -======= - -Types ------ - -.. doxygenstruct:: zc_owned_closure_log_t -.. doxygenstruct:: zc_loaned_closure_log_t -.. doxygenenum:: zc_log_severity_t - -Functions ---------- - -.. doxygenfunction:: zc_try_init_log_from_env -.. doxygenfunction:: zc_init_log_from_env_or -.. doxygenfunction:: zc_init_log_with_callback - -.. doxygenfunction:: zc_closure_log_call -.. doxygenfunction:: zc_closure_log_loan -.. doxygenfunction:: zc_closure_log_drop -.. doxygenfunction:: zc_closure_log - - -Other -===== - -Functions ---------- -.. doxygenfunction:: zc_stop_z_runtime -.. doxygenfunction:: zc_cleanup_orphaned_shm_segments diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d1996f5f7..40b5d5810 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -24,8 +24,8 @@ foreach(file ${files}) # Exclude Liveliness and zenoh-ext examples if unstable api feature is disabled if(NOT(ZENOHC_BUILD_WITH_UNSTABLE_API)) if( - (${target} MATCHES "^.*_pub_cache.*$") - OR (${target} MATCHES "^.*_query_sub.*$") + (${target} MATCHES "^.*_advanced_sub.*$") + OR (${target} MATCHES "^.*_advanced_pub.*$") OR (${target} MATCHES "^.*_querier.*$") ) continue() diff --git a/examples/z_pub_cache.c b/examples/z_advanced_pub.c similarity index 54% rename from examples/z_pub_cache.c rename to examples/z_advanced_pub.c index 55ff93930..025245710 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_advanced_pub.c @@ -1,5 +1,5 @@ // -// Copyright (c) 2023 ZettaScale Technology +// Copyright (c) 2024 ZettaScale Technology // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License 2.0 which is available at @@ -22,11 +22,9 @@ #define DEFAULT_HISTORY 1 struct args_t { - char* keyexpr; // -k, --key - char* value; // -v, --value - unsigned int history; // -i, --history - bool complete; // -o, --complete - char* prefix; // -x, --prefix + char* keyexpr; // -k, --key + char* value; // -p, --payload + size_t history; // -i, --history }; struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); @@ -48,54 +46,52 @@ int main(int argc, char** argv) { exit(-1); } - ze_publication_cache_options_t pub_cache_opts; - ze_publication_cache_options_default(&pub_cache_opts); - pub_cache_opts.history = args.history; - pub_cache_opts.queryable_complete = args.complete; - z_view_keyexpr_t prefix; - if (args.prefix != NULL) { - z_view_keyexpr_from_str(&prefix, args.prefix); - pub_cache_opts.queryable_prefix = z_loan(prefix); - } - - printf("Declaring publication cache on '%s'...\n", args.keyexpr); - ze_owned_publication_cache_t pub_cache; + printf("Declaring AdvancedPublisher on '%s'...\n", args.keyexpr); + ze_owned_advanced_publisher_t pub; z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, args.keyexpr); - if (ze_declare_publication_cache(z_loan(s), &pub_cache, z_loan(ke), &pub_cache_opts) != Z_OK) { - printf("Unable to declare publication cache for key expression!\n"); + ze_advanced_publisher_options_t pub_opts; + ze_advanced_publisher_options_default(&pub_opts); + ze_advanced_publisher_cache_options_t cache_options; + ze_advanced_publisher_cache_options_default(&cache_options); + cache_options.max_samples = args.history; + pub_opts.cache = &cache_options; + pub_opts.publisher_detection = true; + pub_opts.sample_miss_detection = true; + + if (ze_declare_advanced_publisher(z_loan(s), &pub, z_loan(ke), &pub_opts) < 0) { + printf("Unable to declare AdvancedPublisher for key expression!\n"); exit(-1); } printf("Press CTRL-C to quit...\n"); - char buf[256]; + char buf[256] = {}; for (int idx = 0; 1; ++idx) { z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, args.value); - printf("Putting Data ('%s': '%s')...\n", args.keyexpr, buf); + printf("Put Data ('%s': '%s')...\n", args.keyexpr, buf); + ze_advanced_publisher_put_options_t options; + ze_advanced_publisher_put_options_default(&options); + z_owned_bytes_t payload; z_bytes_copy_from_str(&payload, buf); - - z_put(z_loan(s), z_loan(ke), z_move(payload), NULL); + ze_advanced_publisher_put(z_loan(pub), z_move(payload), &options); } - z_drop(z_move(pub_cache)); + z_drop(z_move(pub)); z_drop(z_move(s)); - return 0; } void print_help() { printf( "\ - Usage: z_pub_cache [OPTIONS]\n\n\ + Usage: z_advanced_pub [OPTIONS]\n\n\ Options:\n\ -k, --key (optional, string, default='%s'): The key expression to write to\n\ - -v, --value (optional, string, default='%s'): The value to write\n\ - -i, --history (optional, int, default='%d'): The number of publications to keep in cache\n\ - -o, --complete (optional): Set `complete` option to true. This means that this queryable is ultimate data source, no need to scan other queryables.\n\ - -x, --prefix (optional, string, default=NULL): An optional queryable prefix\n.", + -p, --payload (optional, string, default='%s'): The value to write\n\ + -i, --history (optional, string, default=%d): The number of publications to keep in cache\n", DEFAULT_KEYEXPR, DEFAULT_VALUE, DEFAULT_HISTORY); printf(COMMON_HELP); } @@ -104,15 +100,13 @@ struct args_t parse_args(int argc, char** argv, z_owned_config_t* config) { _Z_CHECK_HELP; struct args_t args; _Z_PARSE_ARG(args.keyexpr, "k", "key", (char*), (char*)DEFAULT_KEYEXPR); - _Z_PARSE_ARG(args.value, "v", "value", (char*), (char*)DEFAULT_VALUE); - _Z_PARSE_ARG(args.history, "i", "history", atoi, DEFAULT_HISTORY); - args.complete = _Z_CHECK_FLAG("o") || _Z_CHECK_FLAG("complete"); - _Z_PARSE_ARG(args.prefix, "x", "prefix", (char*), NULL); + _Z_PARSE_ARG(args.value, "p", "payload", (char*), (char*)DEFAULT_VALUE); + _Z_PARSE_ARG(args.history, "i", "hisotry", atoi, DEFAULT_HISTORY); parse_zenoh_common_args(argc, argv, config); - const char* arg = check_unknown_opts(argc, argv); - if (arg) { - printf("Unknown option %s\n", arg); + const char* unknown_arg = check_unknown_opts(argc, argv); + if (unknown_arg) { + printf("Unknown option %s\n", unknown_arg); exit(-1); } char** pos_args = parse_pos_args(argc, argv, 1); diff --git a/examples/z_query_sub.c b/examples/z_advanced_sub.c similarity index 64% rename from examples/z_query_sub.c rename to examples/z_advanced_sub.c index 5e14611c2..00d2c1bac 100644 --- a/examples/z_query_sub.c +++ b/examples/z_advanced_sub.c @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 ZettaScale Technology +// Copyright (c) 2024 ZettaScale Technology // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License 2.0 which is available at @@ -20,7 +20,6 @@ struct args_t { char* keyexpr; // -k, --key - char* query; // -q, --query }; struct args_t parse_args(int argc, char** argv, z_owned_config_t* config); @@ -38,6 +37,15 @@ void data_handler(z_loaned_sample_t* sample, void* arg) { z_drop(z_move(payload_string)); } +void miss_handler(const ze_miss_t* miss, void* arg) { + z_id_t id = z_entity_global_id_zid(&miss->source); + z_owned_string_t id_string; + z_id_to_string(&id, &id_string); + printf(">> [Subscriber] Missed %d samples from '%.*s' !!!", miss->nb, (int)z_string_len(z_loan(id_string)), + z_string_data(z_loan(id_string))); + z_drop(z_move(id_string)); +} + int main(int argc, char** argv) { zc_init_log_from_env_or("error"); @@ -54,21 +62,31 @@ int main(int argc, char** argv) { z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, args.keyexpr); - ze_querying_subscriber_options_t sub_opts; - ze_querying_subscriber_options_default(&sub_opts); - z_view_keyexpr_t query; - if (args.query != NULL) { - z_view_keyexpr_from_str(&query, args.query); - sub_opts.query_selector = z_loan(query); - } + ze_advanced_subscriber_options_t sub_opts; + ze_advanced_subscriber_options_default(&sub_opts); + + ze_advanced_subscriber_history_options_t sub_history_options; + ze_advanced_subscriber_history_options_default(&sub_history_options); + sub_history_options.detect_late_publishers = true; + + ze_advanced_subscriber_recovery_options_t sub_recovery_options; + ze_advanced_subscriber_recovery_options_default(&sub_recovery_options); + sub_recovery_options.periodic_queries_period_ms = 1000; + sub_opts.history = &sub_history_options; + sub_opts.recovery = &sub_recovery_options; + sub_opts.subscriber_detection = true; + z_owned_closure_sample_t callback; z_closure(&callback, data_handler, NULL, NULL); - printf("Declaring querying subscriber on '%s'...\n", args.keyexpr); - ze_owned_querying_subscriber_t sub; - if (ze_declare_querying_subscriber(z_loan(s), &sub, z_loan(ke), z_move(callback), &sub_opts) < 0) { - printf("Unable to declare querying subscriber.\n"); + printf("Declaring AdvancedSubscriber on '%s'...\n", args.keyexpr); + ze_owned_advanced_subscriber_t sub; + if (ze_declare_advanced_subscriber(z_loan(s), &sub, z_loan(ke), z_move(callback), &sub_opts) < 0) { + printf("Unable to declare advanced subscriber.\n"); exit(-1); } + ze_owned_closure_miss_t miss_callback; + z_closure(&miss_callback, miss_handler, NULL, NULL); + ze_advanced_subscriber_declare_background_sample_miss_listener(z_loan(sub), z_move(miss_callback)); printf("Press CTRL-C to quit...\n"); while (1) { @@ -95,10 +113,9 @@ const char* kind_to_str(z_sample_kind_t kind) { void print_help() { printf( "\ - Usage: z_query_sub [OPTIONS]\n\n\ + Usage: z_advanced_sub [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression to subscribe to\n\ - -q, --query (optional, string, default=NULL): The selector to use for queries (by default it's same as 'KEY' option)\n", + -k, --key (optional, string, default='%s'): The key expression to subscribe to\n", DEFAULT_KEYEXPR); printf(COMMON_HELP); } diff --git a/examples/z_delete.c b/examples/z_delete.c index 3974c8582..423ba2761 100644 --- a/examples/z_delete.c +++ b/examples/z_delete.c @@ -54,7 +54,7 @@ void print_help() { "\ Usage: z_delete [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression to write to\n", + -k, --key (optional, string, default='%s'): The key expression to write to\n", DEFAULT_KEYEXPR); printf(COMMON_HELP); } diff --git a/examples/z_get_liveliness.c b/examples/z_get_liveliness.c index 42e3588dc..b51acd5a9 100644 --- a/examples/z_get_liveliness.c +++ b/examples/z_get_liveliness.c @@ -76,7 +76,7 @@ void print_help() { "\ Usage: z_get_liveliness [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression to query\n\ + -k, --key (optional, string, default='%s'): The key expression to query\n\ -o, --timeout (optional, number, default = '%d'): Query timeout in milliseconds\n", DEFAULT_KEYEXPR, DEFAULT_TIMEOUT_MS); printf(COMMON_HELP); diff --git a/examples/z_liveliness.c b/examples/z_liveliness.c index cac5dc918..bae66feee 100644 --- a/examples/z_liveliness.c +++ b/examples/z_liveliness.c @@ -69,7 +69,7 @@ void print_help() { "\ Usage: z_liveliness [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression for the liveliness token\n", + -k, --key (optional, string, default='%s'): The key expression for the liveliness token\n", DEFAULT_KEYEXPR); printf(COMMON_HELP); } diff --git a/examples/z_pull.c b/examples/z_pull.c index 93cbe7db1..0554bd291 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -105,7 +105,7 @@ void print_help() { "\ Usage: z_pull [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression to subscribe to\n\ + -k, --key (optional, string, default='%s'): The key expression to subscribe to\n\ -s, --size (optional, number, default='%d'): The size of the ring buffer\n\ -i, --interval (optional, number, default='%d'): The interval for pulling the ringbuffer.\n", DEFAULT_KEYEXPR, DEFAULT_RING_BUFFER_SIZE, DEFAULT_PULL_INTERVAL); diff --git a/examples/z_sub.c b/examples/z_sub.c index 3fe255070..9aeea58b8 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -98,7 +98,7 @@ void print_help() { "\ Usage: z_sub [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression to subscribe to\n", + -k, --key (optional, string, default='%s'): The key expression to subscribe to\n", DEFAULT_KEYEXPR); printf(COMMON_HELP); } diff --git a/examples/z_sub_liveliness.c b/examples/z_sub_liveliness.c index 89361d4df..a9b7813b7 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -84,7 +84,7 @@ void print_help() { "\ Usage: z_sub_liveliness [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression matching liveliness tokens to subscribe to\n\ + -k, --key (optional, string, default='%s'): The key expression matching liveliness tokens to subscribe to\n\ --history (optional): Get historical liveliness tokens.\n", DEFAULT_KEYEXPR); printf(COMMON_HELP); diff --git a/examples/z_sub_shm.c b/examples/z_sub_shm.c index 6b4a2427a..c04ddbd22 100644 --- a/examples/z_sub_shm.c +++ b/examples/z_sub_shm.c @@ -126,7 +126,7 @@ void print_help() { "\ Usage: z_sub_shm [OPTIONS]\n\n\ Options:\n\ - -k, --key (optional, string, default='%s'): The key expression to subscribe to\n", + -k, --key (optional, string, default='%s'): The key expression to subscribe to\n", DEFAULT_KEYEXPR); printf(COMMON_HELP); } diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index bce0fe31c..fdb80aeba 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -396,10 +396,19 @@ typedef struct z_queryable_options_t { * Options passed to the `z_declare_subscriber()` function. */ typedef struct z_subscriber_options_t { +#if !defined(Z_FEATURE_UNSTABLE_API) /** * Dummy field to avoid having fieldless struct */ uint8_t _0; +#endif +#if defined(Z_FEATURE_UNSTABLE_API) + /** + * Restricts the matching publications that will be received by this Subscribers to the ones + * that have the compatible allowed_destination. + */ + enum zc_locality_t allowed_origin; +#endif } z_subscriber_options_t; typedef struct z_moved_encoding_t { struct z_owned_encoding_t _this; @@ -421,7 +430,7 @@ typedef struct z_publisher_options_t { */ enum z_priority_t priority; /** - * If true, Zenoh will not wait to batch this message with others to reduce the bandwith. + * If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; #if defined(Z_FEATURE_UNSTABLE_API) @@ -466,7 +475,7 @@ typedef struct z_querier_options_t { */ enum z_congestion_control_t congestion_control; /** - * If true, Zenoh will not wait to batch the querier queries with others to reduce the bandwith. + * If set to ``true``, the querier queries will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; #if defined(Z_FEATURE_UNSTABLE_API) @@ -508,7 +517,7 @@ typedef struct z_delete_options_t { */ enum z_priority_t priority; /** - * If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + * If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; /** @@ -569,7 +578,7 @@ typedef struct z_get_options_t { */ enum z_congestion_control_t congestion_control; /** - * If true, Zenoh will not wait to batch this message with others to reduce the bandwith. + * If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; #if defined(Z_FEATURE_UNSTABLE_API) @@ -709,7 +718,7 @@ typedef struct z_put_options_t { */ enum z_priority_t priority; /** - * If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + * If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; /** @@ -797,7 +806,7 @@ typedef struct z_query_reply_options_t { */ enum z_priority_t priority; /** - * If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + * If set to ``true``, this reply will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; /** @@ -831,7 +840,7 @@ typedef struct z_query_reply_del_options_t { */ enum z_priority_t priority; /** - * If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + * If set to ``true``, this reply will not be batched. This usually has a positive impact on latency but negative impact on throughput. */ bool is_express; /** @@ -995,6 +1004,225 @@ typedef struct zc_moved_shm_client_list_t { } zc_moved_shm_client_list_t; /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Setting for advanced publisher's cache. The cache allows advanced subscribers to recover history and/or lost samples. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_publisher_cache_options_t { + /** + * Number of samples to keep for each resource + */ + size_t max_samples; + /** + * The congestion control to apply to replies. + */ + enum z_congestion_control_t congestion_control; + /** + * The priority of replies. + */ + enum z_priority_t priority; + /** + * If set to ``true``, this cache replies will not be batched. This usually has a positive impact on latency but negative impact on throughput. + */ + bool is_express; +} ze_advanced_publisher_cache_options_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Represents the set of options that can be applied to the delete operation by a previously declared advanced publisher, + * whenever issued via `ze_advanced_publisher_delete()`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_publisher_delete_options_t { + /** + * Base delete options. + */ + struct z_publisher_delete_options_t delete_options; +} ze_advanced_publisher_delete_options_t; +#endif +typedef struct ze_moved_advanced_publisher_t { + struct ze_owned_advanced_publisher_t _this; +} ze_moved_advanced_publisher_t; +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Options passed to the `ze_declare_advanced_publisher()` function. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_publisher_options_t { + /** + * Base publisher options. + */ + struct z_publisher_options_t publisher_options; + /** + * Optional settings for publisher cache. + */ + struct ze_advanced_publisher_cache_options_t *cache; + /** + * Allow matching Subscribers to detect lost samples and optionally ask for retransimission. + * + * Retransmission can only be done if history is enabled on subscriber side. + */ + bool sample_miss_detection; + /** + * Allow this publisher to be detected through liveliness. + */ + bool publisher_detection; + /** + * An optional key expression to be added to the liveliness token key expression. + * It can be used to convey meta data. + */ + struct z_loaned_keyexpr_t *publisher_detection_metadata; +} ze_advanced_publisher_options_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Options passed to the `ze_advanced_publisher_put()` function. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_publisher_put_options_t { + /** + * Base put options. + */ + struct z_publisher_put_options_t put_options; +} ze_advanced_publisher_put_options_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief A struct that represent missed samples. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_miss_t { + /** + * The source of missed samples. + */ + struct z_entity_global_id_t source; + /** + * The number of missed samples. + */ + uint32_t nb; +} ze_miss_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief A sample miss-processing closure. + * + * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_owned_closure_miss_t { + void *_context; + void (*_call)(const struct ze_miss_t *matching_status, void *context); + void (*_drop)(void *context); +} ze_owned_closure_miss_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Moved closure. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_moved_closure_miss_t { + struct ze_owned_closure_miss_t _this; +} ze_moved_closure_miss_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief An owned Zenoh sample miss listener. Missed samples can only be detected from advanced publishers, enabling sample miss detection. + * + * A listener that sends notification when the advanced subscriber misses a sample . + * Dropping the corresponding subscriber, also drops the listener. + */ +typedef struct ALIGN(8) ze_owned_sample_miss_listener_t { + uint8_t _0[16]; +} ze_owned_sample_miss_listener_t; +typedef struct ze_moved_advanced_subscriber_t { + struct ze_owned_advanced_subscriber_t _this; +} ze_moved_advanced_subscriber_t; +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Settings for retrievieng historical data for Advanced Subscriber. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_subscriber_history_options_t { + /** + * Enable detection of late joiner publishers and query for their historical data. + * Late joiner detection can only be achieved for Publishers that enable publisher_detection. + * History can only be retransmitted by Publishers that enable caching. + */ + bool detect_late_publishers; + /** + * Number of samples to query for each resource. ``0`` corresponds to no limit on number of samples. + */ + size_t max_samples; + /** + * Maximum age of samples to query. ``0`` corresponds to no limit on samples' age. + */ + uint64_t max_age_ms; +} ze_advanced_subscriber_history_options_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Settings for recovering lost messages for Advanced Subscriber. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_subscriber_recovery_options_t { + /** + * Period for queries for not yet received Samples. + * + * These queries allow to retrieve the last Sample(s) if the last Sample(s) is/are lost. + * So it is useful for sporadic publications but useless for periodic publications + * with a period smaller or equal to this period. + * Retransmission can only be achieved by Publishers that also activate retransmission. + */ + uint64_t periodic_queries_period_ms; +} ze_advanced_subscriber_recovery_options_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Options passed to the `ze_declare_advanced_subscriber()` function. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_advanced_subscriber_options_t { + /** + * Base subscriber options. + */ + struct z_subscriber_options_t subscriber_options; + /** + * Optional settings for querying historical data. History can only be retransmitted by Publishers that enable caching. + * Querying historical data is disabled if the value is ``NULL``. + */ + struct ze_advanced_subscriber_history_options_t *history; + /** + * Optional settings for retransmission of detected lost Samples. Retransmission of lost samples can only be done by Publishers that enable + * caching and sample_miss_detection. + * Retransmission is disabled if the value is ``NULL``. + */ + struct ze_advanced_subscriber_recovery_options_t *recovery; + /** + * Timeout to be used for history and recovery queries. + * Default value will be used if set to ``0``. + */ + uint64_t query_timeout_ms; + /** + * Allow this subscriber to be detected through liveliness. + */ + bool subscriber_detection; + /** + * An optional key expression to be added to the liveliness token key expression. + * It can be used to convey meta data. + */ + struct z_loaned_keyexpr_t *subscriber_detection_metadata; +} ze_advanced_subscriber_options_t; +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Loaned closure. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +typedef struct ze_loaned_closure_miss_t { + size_t _0[3]; +} ze_loaned_closure_miss_t; +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Options passed to the `ze_declare_publication_cache()` function. */ #if defined(Z_FEATURE_UNSTABLE_API) @@ -1024,7 +1252,7 @@ typedef struct ze_publication_cache_options_t { } ze_publication_cache_options_t; #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief A set of options that can be applied to a querying subscriber, * upon its declaration via `ze_declare_querying_subscriber()`. * @@ -1074,6 +1302,9 @@ typedef struct ALIGN(8) ze_loaned_publication_cache_t { typedef struct ze_moved_querying_subscriber_t { struct ze_owned_querying_subscriber_t _this; } ze_moved_querying_subscriber_t; +typedef struct ze_moved_sample_miss_listener_t { + struct ze_owned_sample_miss_listener_t _this; +} ze_moved_sample_miss_listener_t; typedef struct ze_moved_serializer_t { struct ze_owned_serializer_t _this; } ze_moved_serializer_t; @@ -1797,7 +2028,7 @@ z_result_t z_declare_background_queryable(const struct z_loaned_session_t *sessi * @param session: The zenoh session. * @param key_expr: The key expression to subscribe. * @param callback: The callback function that will be called each time a data matching the subscribed expression is received. - * @param _options: The options to be passed to the subscriber declaration. + * @param options: The options to be passed to the subscriber declaration. * * @return 0 in case of success, negative error code otherwise. */ @@ -1805,10 +2036,10 @@ ZENOHC_API z_result_t z_declare_background_subscriber(const struct z_loaned_session_t *session, const struct z_loaned_keyexpr_t *key_expr, struct z_moved_closure_sample_t *callback, - struct z_subscriber_options_t *_options); + struct z_subscriber_options_t *options); /** * Constructs and declares a key expression on the network. This reduces key key expression to a numerical id, - * which allows to save the bandwith, when passing key expression between Zenoh entities. + * which allows to save the bandwitdth, when passing key expression between Zenoh entities. * * @param session: Session on which to declare key expression. * @param declared_key_expr: An uninitialized location in memory where key expression will be constructed. @@ -1881,7 +2112,7 @@ z_result_t z_declare_queryable(const struct z_loaned_session_t *session, * @param subscriber: An uninitialized location in memory, where subscriber will be constructed. * @param key_expr: The key expression to subscribe. * @param callback: The callback function that will be called each time a data matching the subscribed expression is received. - * @param _options: The options to be passed to the subscriber declaration. + * @param options: The options to be passed to the subscriber declaration. * * @return 0 in case of success, negative error code otherwise (in this case subscriber will be in its gravestone state). */ @@ -1890,7 +2121,7 @@ z_result_t z_declare_subscriber(const struct z_loaned_session_t *session, struct z_owned_subscriber_t *subscriber, const struct z_loaned_keyexpr_t *key_expr, struct z_moved_closure_sample_t *callback, - struct z_subscriber_options_t *_options); + struct z_subscriber_options_t *options); /** * Sends request to delete data on specified key expression (used when working with Zenoh storages ). * @@ -3252,7 +3483,7 @@ ZENOHC_API enum z_priority_t z_priority_default(void); */ ZENOHC_API z_result_t z_publisher_delete(const struct z_loaned_publisher_t *publisher, - const struct z_publisher_delete_options_t *options); + struct z_publisher_delete_options_t *options); /** * Constructs the default values for the delete operation via a publisher entity. */ @@ -5175,6 +5406,358 @@ z_result_t zc_undeclare_matching_listener(struct zc_moved_matching_listener_t *t #endif /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs the default value for `ze_advanced_publisher_cache_options_t`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_publisher_cache_options_default(struct ze_advanced_publisher_cache_options_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Declares a matching listener, registering a callback for notifying subscribers matching with a given advanced publisher. + * The callback will be run in the background until the corresponding publisher is dropped. + * + * @param publisher: An advanced publisher to associate with matching listener. + * @param callback: A closure that will be called every time the matching status of the publisher changes (If last subscriber disconnects or when the first subscriber connects). + * + * @return 0 in case of success, negative error code otherwise. + */ +#if (defined(Z_FEATURE_UNSTABLE_API) && defined(Z_FEATURE_UNSTABLE_API)) +ZENOHC_API +z_result_t ze_advanced_publisher_declare_background_matching_listener(const struct ze_loaned_advanced_publisher_t *publisher, + struct zc_moved_closure_matching_status_t *callback); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs matching listener, registering a callback for notifying subscribers matching with a given advanced publisher. + * + * @param publisher: An advanced publisher to associate with matching listener. + * @param matching_listener: An uninitialized memory location where matching listener will be constructed. The matching listener's callback will be automatically dropped when the publisher is dropped. + * @param callback: A closure that will be called every time the matching status of the publisher changes (If last subscriber disconnects or when the first subscriber connects). + * + * @return 0 in case of success, negative error code otherwise. + */ +#if (defined(Z_FEATURE_UNSTABLE_API) && defined(Z_FEATURE_UNSTABLE_API)) +ZENOHC_API +z_result_t ze_advanced_publisher_declare_matching_listener(const struct ze_loaned_advanced_publisher_t *publisher, + struct zc_owned_matching_listener_t *matching_listener, + struct zc_moved_closure_matching_status_t *callback); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Sends a `DELETE` message onto the advanced publisher's key expression. + * + * @return 0 in case of success, negative error code in case of failure. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_advanced_publisher_delete(const struct ze_loaned_advanced_publisher_t *publisher, + struct ze_advanced_publisher_delete_options_t *options); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Constructs the default values for the delete operation via an advanced publisher entity. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_publisher_delete_options_default(struct ze_advanced_publisher_delete_options_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Frees memory and resets advanced_publisher to its gravestone state. + * This is equivalent to calling `z_undeclare_publisher()` and discarding its return value. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_publisher_drop(struct ze_moved_advanced_publisher_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Gets advanced publisher matching status - i.e. if there are any subscribers matching its key expression. + * + * @return 0 in case of success, negative error code otherwise (in this case matching_status is not updated). + */ +#if (defined(Z_FEATURE_UNSTABLE_API) && defined(Z_FEATURE_UNSTABLE_API)) +ZENOHC_API +z_result_t ze_advanced_publisher_get_matching_status(const struct ze_loaned_advanced_publisher_t *this_, + struct zc_matching_status_t *matching_status); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Returns the ID of the advanced publisher. + */ +#if (defined(Z_FEATURE_UNSTABLE_API) && defined(Z_FEATURE_UNSTABLE_API)) +ZENOHC_API +struct z_entity_global_id_t ze_advanced_publisher_id(const struct ze_loaned_advanced_publisher_t *publisher); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Returns the key expression of the publisher. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +const struct z_loaned_keyexpr_t *ze_advanced_publisher_keyexpr(const struct ze_loaned_advanced_publisher_t *publisher); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Borrows advanced publisher. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +const struct ze_loaned_advanced_publisher_t *ze_advanced_publisher_loan(const struct ze_owned_advanced_publisher_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Mutably borrows advanced publisher. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +struct ze_loaned_advanced_publisher_t *ze_advanced_publisher_loan_mut(struct ze_owned_advanced_publisher_t *this_); +#endif +/** + * Constructs the default value for `z_publisher_options_t`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_publisher_options_default(struct ze_advanced_publisher_options_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Sends a `PUT` message onto the advanced publisher's key expression, transfering the payload ownership. + * + * The payload and all owned options fields are consumed upon function return. + * + * @param this_: The advanced publisher. + * @param payload: The data to publish. Will be consumed. + * @param options: The advanced publisher put options. All owned fields will be consumed. + * + * @return 0 in case of success, negative error values in case of failure. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_advanced_publisher_put(const struct ze_loaned_advanced_publisher_t *this_, + struct z_moved_bytes_t *payload, + struct ze_advanced_publisher_put_options_t *options); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Constructs the default value for `ze_advanced_publisher_put_options_t`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_publisher_put_options_default(struct ze_advanced_publisher_put_options_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Declares a sample miss listener, registering a callback for notifying subscriber about missed samples. + * The callback will be run in the background until the corresponding subscriber is dropped. + * + * @param subscriber: A subscriber to associate with sample miss listener. + * @param callback: A closure that will be called every time the sample miss is detected. + * + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_advanced_subscriber_declare_background_sample_miss_listener(const struct ze_loaned_advanced_subscriber_t *subscriber, + struct ze_moved_closure_miss_t *callback); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs sample miss listener, registering a callback for notifying subscriber about missed samples. + * + * @param subscriber: A subscriber to associate with sample miss listener. + * @param sample_miss_listener: An uninitialized memory location where sample miss listener will be constructed. The sample miss listener's callback will be automatically dropped when the subscriber is dropped. + * @param callback: A closure that will be called every time the sample miss is detected. + * + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_advanced_subscriber_declare_sample_miss_listener(const struct ze_loaned_advanced_subscriber_t *subscriber, + struct ze_owned_sample_miss_listener_t *sample_miss_listener, + struct ze_moved_closure_miss_t *callback); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Declares a subscriber on liveliness tokens for matching publishers detection. Only advanced publishers. enabling publisher detection can be detected. + * + * @param subscriber: The advanced subscriber instance. + * @param liveliness_subscriber: An uninitialized memory location where liveliness subscriber will be constructed. + * @param callback: The callback function that will be called each time a liveliness token status is changed. + * @param options: The options to be passed to the liveliness subscriber declaration. + * + * @return 0 in case of success, negative error values otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_advanced_subscriber_detect_publishers(const struct ze_loaned_advanced_subscriber_t *subscriber, + struct z_owned_subscriber_t *liveliness_subscriber, + struct z_moved_closure_sample_t *callback, + struct z_liveliness_subscriber_options_t *options); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Declares a background subscriber on liveliness tokens of matching publishers. Subscriber callback will be called to process the messages, + * until the corresponding session is closed or dropped. Only advanced publishers. enabling publisher detection can be detected. + * @param subscriber: The advanced subscriber instance. + * @param callback: The callback function that will be called each time a liveliness token status is changed. + * @param options: The options to be passed to the liveliness subscriber declaration. + * + * @return 0 in case of success, negative error values otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_advanced_subscriber_detect_publishers_background(const struct ze_loaned_advanced_subscriber_t *subscriber, + struct z_moved_closure_sample_t *callback, + struct z_liveliness_subscriber_options_t *options); +#endif +/** + * Undeclares advanced subscriber callback and resets it to its gravestone state. + * This is equivalent to calling `ze_undeclare_advanced_subscriber()` and discarding its return value. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_subscriber_drop(struct ze_moved_advanced_subscriber_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs the default value for `ze_advanced_subscriber_history_options_t`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_subscriber_history_options_default(struct ze_advanced_subscriber_history_options_t *this_); +#endif +/** + * Borrows subscriber. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +const struct ze_loaned_advanced_subscriber_t *ze_advanced_subscriber_loan(const struct ze_owned_advanced_subscriber_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs the default value for `ze_advanced_subscriber_options_t`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_subscriber_options_default(struct ze_advanced_subscriber_options_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs the default value for `ze_advanced_subscriber_recovery_options_t`. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_advanced_subscriber_recovery_options_default(struct ze_advanced_subscriber_recovery_options_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * + * Closures are not guaranteed not to be called concurrently. + * + * It is guaranteed that: + * - `call` will never be called once `drop` has started. + * - `drop` will only be called **once**, and **after every** `call` has ended. + * - The two previous guarantees imply that `call` and `drop` are never called concurrently. + * @brief Constructs closure. + * @param this_: uninitialized memory location where new closure will be constructed. + * @param call: a closure body. + * @param drop: an optional function to be called once on closure drop. + * @param context: closure context. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_closure_miss(struct ze_owned_closure_miss_t *this_, + void (*call)(const struct ze_miss_t *matching_status, void *context), + void (*drop)(void *context), + void *context); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Calls the closure. Calling an uninitialized closure is a no-op. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_closure_miss_call(const struct ze_loaned_closure_miss_t *closure, + const struct ze_miss_t *mathing_status); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Drops the closure, resetting it to its gravestone state. Droping an uninitialized closure is a no-op. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_closure_miss_drop(struct ze_moved_closure_miss_t *closure_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Borrows closure. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +const struct ze_loaned_closure_miss_t *ze_closure_miss_loan(const struct ze_owned_closure_miss_t *closure); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Constructs and declares an advanced publisher for the given key expression. + * + * Data can be put and deleted with this publisher with the help of the + * `ze_advanced_publisher_put()` and `ze_advanced_publisher_delete()` functions. + * + * @param session: The Zenoh session. + * @param publisher: An uninitialized location in memory where advanced publisher will be constructed. + * @param key_expr: The key expression to publish to. + * @param options: Additional options for the advanced publisher. + * + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_declare_advanced_publisher(const struct z_loaned_session_t *session, + struct ze_owned_advanced_publisher_t *publisher, + const struct z_loaned_keyexpr_t *key_expr, + struct ze_advanced_publisher_options_t *options); +#endif +/** + * Constructs and declares an advanced subscriber for a given key expression. Dropping subscriber undeclares its callback. + * + * @param session: The zenoh session. + * @param subscriber: An uninitialized location in memory, where advanced subscriber will be constructed. + * @param key_expr: The key expression to subscribe. + * @param callback: The callback function that will be called each time a data matching the subscribed expression is received. + * @param options: The options to be passed to the subscriber declaration. + * + * @return 0 in case of success, negative error code otherwise (in this case subscriber will be in its gravestone state). + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_declare_advanced_subscriber(const struct z_loaned_session_t *session, + struct ze_owned_advanced_subscriber_t *subscriber, + const struct z_loaned_keyexpr_t *key_expr, + struct z_moved_closure_sample_t *callback, + struct ze_advanced_subscriber_options_t *options); +#endif +/** + * Constructs and declares a background advanced subscriber. Subscriber callback will be called to process the messages, + * until the corresponding session is closed or dropped. + * + * @param session: The zenoh session. + * @param key_expr: The key expression to subscribe. + * @param callback: The callback function that will be called each time a data matching the subscribed expression is received. + * @param options: The options to be passed to the subscriber declaration. + * + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_declare_background_advanced_subscriber(const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_moved_closure_sample_t *callback, + struct ze_advanced_subscriber_options_t *options); +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Declares a background publication cache. It will function in background until the corresponding session is closed or dropped. * * @param session: A Zenoh session. @@ -5190,7 +5773,7 @@ z_result_t ze_declare_background_publication_cache(const struct z_loaned_session struct ze_publication_cache_options_t *options); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Declares a background querying subscriber for a given key expression. Subscriber callback will be called to process the messages, * until the corresponding session is closed or dropped. * @@ -5209,7 +5792,7 @@ z_result_t ze_declare_background_querying_subscriber(const struct z_loaned_sessi struct ze_querying_subscriber_options_t *options); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Constructs and declares a publication cache. * * @param session: A Zenoh session. @@ -5227,7 +5810,7 @@ z_result_t ze_declare_publication_cache(const struct z_loaned_session_t *session struct ze_publication_cache_options_t *options); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Constructs and declares a querying subscriber for a given key expression. * * @param session: A Zenoh session. @@ -5421,22 +6004,66 @@ struct ze_deserializer_t ze_deserializer_from_bytes(const struct z_loaned_bytes_ ZENOHC_API bool ze_deserializer_is_done(const struct ze_deserializer_t *this_); /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. - * @brief Returns ``true`` if publication cache is valid, ``false`` otherwise. + * Returns ``true`` if advanced publisher is valid, ``false`` otherwise. */ #if defined(Z_FEATURE_UNSTABLE_API) ZENOHC_API -bool ze_internal_publication_cache_check(const struct ze_owned_publication_cache_t *this_); +bool ze_internal_advanced_publisher_check(const struct ze_owned_advanced_publisher_t *this_); #endif /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. - * @brief Constructs a publication cache in a gravestone state. + * Constructs an advanced publisher in a gravestone state. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_internal_advanced_publisher_null(struct ze_owned_advanced_publisher_t *this_); +#endif +/** + * Returns ``true`` if advanced subscriber is valid, ``false`` otherwise. */ #if defined(Z_FEATURE_UNSTABLE_API) ZENOHC_API -void ze_internal_publication_cache_null(struct ze_owned_publication_cache_t *this_); +bool ze_internal_advanced_subscriber_check(const struct ze_owned_advanced_subscriber_t *this_); +#endif +/** + * Constructs a subscriber in a gravestone state. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API void ze_internal_advanced_subscriber_null(struct ze_owned_advanced_subscriber_t *this_); #endif /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Returns ``true`` if closure is valid, ``false`` if it is in gravestone state. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +bool ze_internal_closure_miss_check(const struct ze_owned_closure_miss_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs a null value of 'ze_owned_closure_miss_t' type + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_internal_closure_miss_null(struct ze_owned_closure_miss_t *this_); +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_publisher. + * @brief Returns ``true`` if publication cache is valid, ``false`` otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +bool ze_internal_publication_cache_check(const struct ze_owned_publication_cache_t *this_); +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_publisher. + * @brief Constructs a publication cache in a gravestone state. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API void ze_internal_publication_cache_null(struct ze_owned_publication_cache_t *this_); +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Returns ``true`` if querying subscriber is valid, ``false`` otherwise. */ #if defined(Z_FEATURE_UNSTABLE_API) @@ -5449,6 +6076,22 @@ bool ze_internal_querying_subscriber_check(const struct ze_owned_querying_subscr #if defined(Z_FEATURE_UNSTABLE_API) ZENOHC_API void ze_internal_querying_subscriber_null(struct ze_owned_querying_subscriber_t *this_); #endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Checks the sample_miss listener is for the gravestone state + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +bool ze_internal_sample_miss_listener_check(const struct ze_owned_sample_miss_listener_t *this_); +#endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Constructs an empty sample miss listener. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_internal_sample_miss_listener_null(struct ze_owned_sample_miss_listener_t *this_); +#endif /** * @brief Returns ``true`` if `this_` is in a valid state, ``false`` if it is in a gravestone state. */ @@ -5458,16 +6101,15 @@ ZENOHC_API bool ze_internal_serializer_check(const struct ze_owned_serializer_t */ ZENOHC_API void ze_internal_serializer_null(struct ze_owned_serializer_t *this_); /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Drops publication cache and resets it to its gravestone state. * This is equivalent to calling `ze_undeclare_publication_cache()` and discarding its return value. */ #if defined(Z_FEATURE_UNSTABLE_API) -ZENOHC_API -void ze_publication_cache_drop(struct ze_moved_publication_cache_t *this_); +ZENOHC_API void ze_publication_cache_drop(struct ze_moved_publication_cache_t *this_); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Returns the key expression of the publication cache. */ #if defined(Z_FEATURE_UNSTABLE_API) @@ -5475,7 +6117,7 @@ ZENOHC_API const struct z_loaned_keyexpr_t *ze_publication_cache_keyexpr(const struct ze_loaned_publication_cache_t *this_); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Borrows publication cache. */ #if defined(Z_FEATURE_UNSTABLE_API) @@ -5483,15 +6125,14 @@ ZENOHC_API const struct ze_loaned_publication_cache_t *ze_publication_cache_loan(const struct ze_owned_publication_cache_t *this_); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_publisher. * @brief Constructs the default value for `ze_publication_cache_options_t`. */ #if defined(Z_FEATURE_UNSTABLE_API) -ZENOHC_API -void ze_publication_cache_options_default(struct ze_publication_cache_options_t *this_); +ZENOHC_API void ze_publication_cache_options_default(struct ze_publication_cache_options_t *this_); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Undeclares querying subscriber callback and resets it to its gravestone state. * This is equivalent to calling `ze_undeclare_querying_subscriber()` and discarding its return value. */ @@ -5500,7 +6141,7 @@ ZENOHC_API void ze_querying_subscriber_drop(struct ze_moved_querying_subscriber_t *this_); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Make querying subscriber perform an additional query on a specified selector. * The queried samples will be merged with the received publications and made available in the subscriber callback. * @return 0 in case of success, negative error code otherwise. @@ -5512,7 +6153,7 @@ z_result_t ze_querying_subscriber_get(const struct ze_loaned_querying_subscriber struct z_get_options_t *options); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Borrows querying subscriber. */ #if defined(Z_FEATURE_UNSTABLE_API) @@ -5520,13 +6161,21 @@ ZENOHC_API const struct ze_loaned_querying_subscriber_t *ze_querying_subscriber_loan(const struct ze_owned_querying_subscriber_t *this_); #endif /** - * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Constructs the default value for `ze_querying_subscriber_options_t`. */ #if defined(Z_FEATURE_UNSTABLE_API) ZENOHC_API void ze_querying_subscriber_options_default(struct ze_querying_subscriber_options_t *this_); #endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Undeclares the given sample miss listener, droping and invalidating it. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +void ze_sample_miss_listener_drop(struct ze_moved_sample_miss_listener_t *this_); +#endif /** * @brief Serializes a bool. */ @@ -5757,15 +6406,34 @@ z_result_t ze_serializer_serialize_uint8(struct ze_loaned_serializer_t *this_, uint8_t val); /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. - * @brief Undeclares publication cache. + * @brief Undeclares the given advanced publisher. + * * @return 0 in case of success, negative error code otherwise. */ #if defined(Z_FEATURE_UNSTABLE_API) ZENOHC_API -z_result_t ze_undeclare_publication_cache(struct ze_moved_publication_cache_t *this_); +z_result_t ze_undeclare_advanced_publisher(struct ze_moved_advanced_publisher_t *this_); #endif /** * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * Undeclares the advanced subscriber. + * + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_undeclare_advanced_subscriber(struct ze_moved_advanced_subscriber_t *this_); +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_publisher. + * @brief Undeclares publication cache. + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API z_result_t ze_undeclare_publication_cache(struct ze_moved_publication_cache_t *this_); +#endif +/** + * @warning This API is deprecated. Please use ze_advanced_subscriber. * @brief Undeclares the given querying subscriber. * * @return 0 in case of success, negative error code otherwise. @@ -5774,3 +6442,12 @@ z_result_t ze_undeclare_publication_cache(struct ze_moved_publication_cache_t *t ZENOHC_API z_result_t ze_undeclare_querying_subscriber(struct ze_moved_querying_subscriber_t *this_); #endif +/** + * @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + * @brief Undeclares the given sample miss listener, droping and invalidating it. + * @return 0 in case of success, negative error code otherwise. + */ +#if defined(Z_FEATURE_UNSTABLE_API) +ZENOHC_API +z_result_t ze_undeclare_sample_miss_listener(struct ze_moved_sample_miss_listener_t *this_); +#endif diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index 62b5462a0..aae0c0509 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -51,8 +51,12 @@ static inline zc_moved_closure_matching_status_t* zc_closure_matching_status_mov static inline zc_moved_concurrent_close_handle_t* zc_concurrent_close_handle_move(zc_owned_concurrent_close_handle_t* x) { return (zc_moved_concurrent_close_handle_t*)(x); } static inline zc_moved_matching_listener_t* zc_matching_listener_move(zc_owned_matching_listener_t* x) { return (zc_moved_matching_listener_t*)(x); } static inline zc_moved_shm_client_list_t* zc_shm_client_list_move(zc_owned_shm_client_list_t* x) { return (zc_moved_shm_client_list_t*)(x); } +static inline ze_moved_advanced_publisher_t* ze_advanced_publisher_move(ze_owned_advanced_publisher_t* x) { return (ze_moved_advanced_publisher_t*)(x); } +static inline ze_moved_advanced_subscriber_t* ze_advanced_subscriber_move(ze_owned_advanced_subscriber_t* x) { return (ze_moved_advanced_subscriber_t*)(x); } +static inline ze_moved_closure_miss_t* ze_closure_miss_move(ze_owned_closure_miss_t* x) { return (ze_moved_closure_miss_t*)(x); } static inline ze_moved_publication_cache_t* ze_publication_cache_move(ze_owned_publication_cache_t* x) { return (ze_moved_publication_cache_t*)(x); } static inline ze_moved_querying_subscriber_t* ze_querying_subscriber_move(ze_owned_querying_subscriber_t* x) { return (ze_moved_querying_subscriber_t*)(x); } +static inline ze_moved_sample_miss_listener_t* ze_sample_miss_listener_move(ze_owned_sample_miss_listener_t* x) { return (ze_moved_sample_miss_listener_t*)(x); } static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x) { return (ze_moved_serializer_t*)(x); } @@ -102,6 +106,9 @@ static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x zc_owned_closure_log_t : zc_closure_log_loan, \ zc_owned_closure_matching_status_t : zc_closure_matching_status_loan, \ zc_owned_shm_client_list_t : zc_shm_client_list_loan, \ + ze_owned_advanced_publisher_t : ze_advanced_publisher_loan, \ + ze_owned_advanced_subscriber_t : ze_advanced_subscriber_loan, \ + ze_owned_closure_miss_t : ze_closure_miss_loan, \ ze_owned_publication_cache_t : ze_publication_cache_loan, \ ze_owned_querying_subscriber_t : ze_querying_subscriber_loan, \ ze_owned_serializer_t : ze_serializer_loan \ @@ -126,6 +133,7 @@ static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x z_owned_shm_mut_t : z_shm_mut_loan_mut, \ z_owned_string_array_t : z_string_array_loan_mut, \ zc_owned_shm_client_list_t : zc_shm_client_list_loan_mut, \ + ze_owned_advanced_publisher_t : ze_advanced_publisher_loan_mut, \ ze_owned_serializer_t : ze_serializer_loan_mut \ )(&this_) @@ -178,8 +186,12 @@ static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x zc_moved_concurrent_close_handle_t* : zc_concurrent_close_handle_drop, \ zc_moved_matching_listener_t* : zc_matching_listener_drop, \ zc_moved_shm_client_list_t* : zc_shm_client_list_drop, \ + ze_moved_advanced_publisher_t* : ze_advanced_publisher_drop, \ + ze_moved_advanced_subscriber_t* : ze_advanced_subscriber_drop, \ + ze_moved_closure_miss_t* : ze_closure_miss_drop, \ ze_moved_publication_cache_t* : ze_publication_cache_drop, \ ze_moved_querying_subscriber_t* : ze_querying_subscriber_drop, \ + ze_moved_sample_miss_listener_t* : ze_sample_miss_listener_drop, \ ze_moved_serializer_t* : ze_serializer_drop \ )(this_) @@ -232,8 +244,12 @@ static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x zc_owned_concurrent_close_handle_t : zc_concurrent_close_handle_move, \ zc_owned_matching_listener_t : zc_matching_listener_move, \ zc_owned_shm_client_list_t : zc_shm_client_list_move, \ + ze_owned_advanced_publisher_t : ze_advanced_publisher_move, \ + ze_owned_advanced_subscriber_t : ze_advanced_subscriber_move, \ + ze_owned_closure_miss_t : ze_closure_miss_move, \ ze_owned_publication_cache_t : ze_publication_cache_move, \ ze_owned_querying_subscriber_t : ze_querying_subscriber_move, \ + ze_owned_sample_miss_listener_t : ze_sample_miss_listener_move, \ ze_owned_serializer_t : ze_serializer_move \ )(&this_) @@ -286,8 +302,12 @@ static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x zc_owned_concurrent_close_handle_t* : zc_internal_concurrent_close_handle_null, \ zc_owned_matching_listener_t* : zc_internal_matching_listener_null, \ zc_owned_shm_client_list_t* : zc_internal_shm_client_list_null, \ + ze_owned_advanced_publisher_t* : ze_internal_advanced_publisher_null, \ + ze_owned_advanced_subscriber_t* : ze_internal_advanced_subscriber_null, \ + ze_owned_closure_miss_t* : ze_internal_closure_miss_null, \ ze_owned_publication_cache_t* : ze_internal_publication_cache_null, \ ze_owned_querying_subscriber_t* : ze_internal_querying_subscriber_null, \ + ze_owned_sample_miss_listener_t* : ze_internal_sample_miss_listener_null, \ ze_owned_serializer_t* : ze_internal_serializer_null \ )(this_) @@ -338,8 +358,12 @@ static inline void zc_closure_matching_status_take(zc_owned_closure_matching_sta static inline void zc_concurrent_close_handle_take(zc_owned_concurrent_close_handle_t* this_, zc_moved_concurrent_close_handle_t* x) { *this_ = x->_this; zc_internal_concurrent_close_handle_null(&x->_this); } static inline void zc_matching_listener_take(zc_owned_matching_listener_t* this_, zc_moved_matching_listener_t* x) { *this_ = x->_this; zc_internal_matching_listener_null(&x->_this); } static inline void zc_shm_client_list_take(zc_owned_shm_client_list_t* this_, zc_moved_shm_client_list_t* x) { *this_ = x->_this; zc_internal_shm_client_list_null(&x->_this); } +static inline void ze_advanced_publisher_take(ze_owned_advanced_publisher_t* this_, ze_moved_advanced_publisher_t* x) { *this_ = x->_this; ze_internal_advanced_publisher_null(&x->_this); } +static inline void ze_advanced_subscriber_take(ze_owned_advanced_subscriber_t* this_, ze_moved_advanced_subscriber_t* x) { *this_ = x->_this; ze_internal_advanced_subscriber_null(&x->_this); } +static inline void ze_closure_miss_take(ze_owned_closure_miss_t* closure_, ze_moved_closure_miss_t* x) { *closure_ = x->_this; ze_internal_closure_miss_null(&x->_this); } static inline void ze_publication_cache_take(ze_owned_publication_cache_t* this_, ze_moved_publication_cache_t* x) { *this_ = x->_this; ze_internal_publication_cache_null(&x->_this); } static inline void ze_querying_subscriber_take(ze_owned_querying_subscriber_t* this_, ze_moved_querying_subscriber_t* x) { *this_ = x->_this; ze_internal_querying_subscriber_null(&x->_this); } +static inline void ze_sample_miss_listener_take(ze_owned_sample_miss_listener_t* this_, ze_moved_sample_miss_listener_t* x) { *this_ = x->_this; ze_internal_sample_miss_listener_null(&x->_this); } static inline void ze_serializer_take(ze_owned_serializer_t* this_, ze_moved_serializer_t* x) { *this_ = x->_this; ze_internal_serializer_null(&x->_this); } @@ -392,8 +416,12 @@ static inline void ze_serializer_take(ze_owned_serializer_t* this_, ze_moved_ser zc_owned_concurrent_close_handle_t* : zc_concurrent_close_handle_take, \ zc_owned_matching_listener_t* : zc_matching_listener_take, \ zc_owned_shm_client_list_t* : zc_shm_client_list_take, \ + ze_owned_advanced_publisher_t* : ze_advanced_publisher_take, \ + ze_owned_advanced_subscriber_t* : ze_advanced_subscriber_take, \ + ze_owned_closure_miss_t* : ze_closure_miss_take, \ ze_owned_publication_cache_t* : ze_publication_cache_take, \ ze_owned_querying_subscriber_t* : ze_querying_subscriber_take, \ + ze_owned_sample_miss_listener_t* : ze_sample_miss_listener_take, \ ze_owned_serializer_t* : ze_serializer_take \ )(this_, x) @@ -446,8 +474,12 @@ static inline void ze_serializer_take(ze_owned_serializer_t* this_, ze_moved_ser zc_owned_concurrent_close_handle_t : zc_internal_concurrent_close_handle_check, \ zc_owned_matching_listener_t : zc_internal_matching_listener_check, \ zc_owned_shm_client_list_t : zc_internal_shm_client_list_check, \ + ze_owned_advanced_publisher_t : ze_internal_advanced_publisher_check, \ + ze_owned_advanced_subscriber_t : ze_internal_advanced_subscriber_check, \ + ze_owned_closure_miss_t : ze_internal_closure_miss_check, \ ze_owned_publication_cache_t : ze_internal_publication_cache_check, \ ze_owned_querying_subscriber_t : ze_internal_querying_subscriber_check, \ + ze_owned_sample_miss_listener_t : ze_internal_sample_miss_listener_check, \ ze_owned_serializer_t : ze_internal_serializer_check \ )(&this_) @@ -458,7 +490,8 @@ static inline void ze_serializer_take(ze_owned_serializer_t* this_, ze_moved_ser const z_loaned_closure_reply_t* : z_closure_reply_call, \ const z_loaned_closure_sample_t* : z_closure_sample_call, \ const z_loaned_closure_zid_t* : z_closure_zid_call, \ - const zc_loaned_closure_matching_status_t* : zc_closure_matching_status_call \ + const zc_loaned_closure_matching_status_t* : zc_closure_matching_status_call, \ + const ze_loaned_closure_miss_t* : ze_closure_miss_call \ )(closure, hello) typedef void(*z_closure_drop_callback_t)(void *context); @@ -469,6 +502,7 @@ typedef void(*z_closure_sample_callback_t)(z_loaned_sample_t *sample, void *cont typedef void(*z_closure_zid_callback_t)(const z_id_t *z_id, void *context); typedef void(*zc_closure_log_callback_t)(zc_log_severity_t severity, const z_loaned_string_t *msg, void *context); typedef void(*zc_closure_matching_status_callback_t)(const zc_matching_status_t *matching_status, void *context); +typedef void(*ze_closure_miss_callback_t)(const ze_miss_t *matching_status, void *context); #define z_closure(this_, call, drop, context) \ _Generic((this_), \ @@ -478,7 +512,8 @@ typedef void(*zc_closure_matching_status_callback_t)(const zc_matching_status_t z_owned_closure_sample_t* : z_closure_sample, \ z_owned_closure_zid_t* : z_closure_zid, \ zc_owned_closure_log_t* : zc_closure_log, \ - zc_owned_closure_matching_status_t* : zc_closure_matching_status \ + zc_owned_closure_matching_status_t* : zc_closure_matching_status, \ + ze_owned_closure_miss_t* : ze_closure_miss \ )(this_, call, drop, context) #define z_try_recv(this_, query) \ @@ -568,8 +603,12 @@ static inline zc_moved_closure_matching_status_t* zc_closure_matching_status_mov static inline zc_moved_concurrent_close_handle_t* zc_concurrent_close_handle_move(zc_owned_concurrent_close_handle_t* x) { return reinterpret_cast(x); } static inline zc_moved_matching_listener_t* zc_matching_listener_move(zc_owned_matching_listener_t* x) { return reinterpret_cast(x); } static inline zc_moved_shm_client_list_t* zc_shm_client_list_move(zc_owned_shm_client_list_t* x) { return reinterpret_cast(x); } +static inline ze_moved_advanced_publisher_t* ze_advanced_publisher_move(ze_owned_advanced_publisher_t* x) { return reinterpret_cast(x); } +static inline ze_moved_advanced_subscriber_t* ze_advanced_subscriber_move(ze_owned_advanced_subscriber_t* x) { return reinterpret_cast(x); } +static inline ze_moved_closure_miss_t* ze_closure_miss_move(ze_owned_closure_miss_t* x) { return reinterpret_cast(x); } static inline ze_moved_publication_cache_t* ze_publication_cache_move(ze_owned_publication_cache_t* x) { return reinterpret_cast(x); } static inline ze_moved_querying_subscriber_t* ze_querying_subscriber_move(ze_owned_querying_subscriber_t* x) { return reinterpret_cast(x); } +static inline ze_moved_sample_miss_listener_t* ze_sample_miss_listener_move(ze_owned_sample_miss_listener_t* x) { return reinterpret_cast(x); } static inline ze_moved_serializer_t* ze_serializer_move(ze_owned_serializer_t* x) { return reinterpret_cast(x); } @@ -618,6 +657,9 @@ inline const z_loaned_string_t* z_loan(const z_view_string_t& this_) { return z_ inline const zc_loaned_closure_log_t* z_loan(const zc_owned_closure_log_t& closure) { return zc_closure_log_loan(&closure); }; inline const zc_loaned_closure_matching_status_t* z_loan(const zc_owned_closure_matching_status_t& closure) { return zc_closure_matching_status_loan(&closure); }; inline const zc_loaned_shm_client_list_t* z_loan(const zc_owned_shm_client_list_t& this_) { return zc_shm_client_list_loan(&this_); }; +inline const ze_loaned_advanced_publisher_t* z_loan(const ze_owned_advanced_publisher_t& this_) { return ze_advanced_publisher_loan(&this_); }; +inline const ze_loaned_advanced_subscriber_t* z_loan(const ze_owned_advanced_subscriber_t& this_) { return ze_advanced_subscriber_loan(&this_); }; +inline const ze_loaned_closure_miss_t* z_loan(const ze_owned_closure_miss_t& closure) { return ze_closure_miss_loan(&closure); }; inline const ze_loaned_publication_cache_t* z_loan(const ze_owned_publication_cache_t& this_) { return ze_publication_cache_loan(&this_); }; inline const ze_loaned_querying_subscriber_t* z_loan(const ze_owned_querying_subscriber_t& this_) { return ze_querying_subscriber_loan(&this_); }; inline const ze_loaned_serializer_t* z_loan(const ze_owned_serializer_t& this_) { return ze_serializer_loan(&this_); }; @@ -640,6 +682,7 @@ inline z_loaned_shm_t* z_loan_mut(z_owned_shm_t& this_) { return z_shm_loan_mut( inline z_loaned_shm_mut_t* z_loan_mut(z_owned_shm_mut_t& this_) { return z_shm_mut_loan_mut(&this_); }; inline z_loaned_string_array_t* z_loan_mut(z_owned_string_array_t& this_) { return z_string_array_loan_mut(&this_); }; inline zc_loaned_shm_client_list_t* z_loan_mut(zc_owned_shm_client_list_t& this_) { return zc_shm_client_list_loan_mut(&this_); }; +inline ze_loaned_advanced_publisher_t* z_loan_mut(ze_owned_advanced_publisher_t& this_) { return ze_advanced_publisher_loan_mut(&this_); }; inline ze_loaned_serializer_t* z_loan_mut(ze_owned_serializer_t& this_) { return ze_serializer_loan_mut(&this_); }; @@ -690,8 +733,12 @@ inline void z_drop(zc_moved_closure_matching_status_t* closure_) { zc_closure_ma inline void z_drop(zc_moved_concurrent_close_handle_t* this_) { zc_concurrent_close_handle_drop(this_); }; inline void z_drop(zc_moved_matching_listener_t* this_) { zc_matching_listener_drop(this_); }; inline void z_drop(zc_moved_shm_client_list_t* this_) { zc_shm_client_list_drop(this_); }; +inline void z_drop(ze_moved_advanced_publisher_t* this_) { ze_advanced_publisher_drop(this_); }; +inline void z_drop(ze_moved_advanced_subscriber_t* this_) { ze_advanced_subscriber_drop(this_); }; +inline void z_drop(ze_moved_closure_miss_t* closure_) { ze_closure_miss_drop(closure_); }; inline void z_drop(ze_moved_publication_cache_t* this_) { ze_publication_cache_drop(this_); }; inline void z_drop(ze_moved_querying_subscriber_t* this_) { ze_querying_subscriber_drop(this_); }; +inline void z_drop(ze_moved_sample_miss_listener_t* this_) { ze_sample_miss_listener_drop(this_); }; inline void z_drop(ze_moved_serializer_t* this_) { ze_serializer_drop(this_); }; @@ -742,8 +789,12 @@ inline zc_moved_closure_matching_status_t* z_move(zc_owned_closure_matching_stat inline zc_moved_concurrent_close_handle_t* z_move(zc_owned_concurrent_close_handle_t& this_) { return zc_concurrent_close_handle_move(&this_); }; inline zc_moved_matching_listener_t* z_move(zc_owned_matching_listener_t& this_) { return zc_matching_listener_move(&this_); }; inline zc_moved_shm_client_list_t* z_move(zc_owned_shm_client_list_t& this_) { return zc_shm_client_list_move(&this_); }; +inline ze_moved_advanced_publisher_t* z_move(ze_owned_advanced_publisher_t& this_) { return ze_advanced_publisher_move(&this_); }; +inline ze_moved_advanced_subscriber_t* z_move(ze_owned_advanced_subscriber_t& this_) { return ze_advanced_subscriber_move(&this_); }; +inline ze_moved_closure_miss_t* z_move(ze_owned_closure_miss_t& closure_) { return ze_closure_miss_move(&closure_); }; inline ze_moved_publication_cache_t* z_move(ze_owned_publication_cache_t& this_) { return ze_publication_cache_move(&this_); }; inline ze_moved_querying_subscriber_t* z_move(ze_owned_querying_subscriber_t& this_) { return ze_querying_subscriber_move(&this_); }; +inline ze_moved_sample_miss_listener_t* z_move(ze_owned_sample_miss_listener_t& this_) { return ze_sample_miss_listener_move(&this_); }; inline ze_moved_serializer_t* z_move(ze_owned_serializer_t& this_) { return ze_serializer_move(&this_); }; @@ -794,8 +845,12 @@ inline void z_internal_null(zc_owned_closure_matching_status_t* this_) { zc_inte inline void z_internal_null(zc_owned_concurrent_close_handle_t* this_) { zc_internal_concurrent_close_handle_null(this_); }; inline void z_internal_null(zc_owned_matching_listener_t* this_) { zc_internal_matching_listener_null(this_); }; inline void z_internal_null(zc_owned_shm_client_list_t* this_) { zc_internal_shm_client_list_null(this_); }; +inline void z_internal_null(ze_owned_advanced_publisher_t* this_) { ze_internal_advanced_publisher_null(this_); }; +inline void z_internal_null(ze_owned_advanced_subscriber_t* this_) { ze_internal_advanced_subscriber_null(this_); }; +inline void z_internal_null(ze_owned_closure_miss_t* this_) { ze_internal_closure_miss_null(this_); }; inline void z_internal_null(ze_owned_publication_cache_t* this_) { ze_internal_publication_cache_null(this_); }; inline void z_internal_null(ze_owned_querying_subscriber_t* this_) { ze_internal_querying_subscriber_null(this_); }; +inline void z_internal_null(ze_owned_sample_miss_listener_t* this_) { ze_internal_sample_miss_listener_null(this_); }; inline void z_internal_null(ze_owned_serializer_t* this_) { ze_internal_serializer_null(this_); }; static inline void z_alloc_layout_take(z_owned_alloc_layout_t* this_, z_moved_alloc_layout_t* x) { *this_ = x->_this; z_internal_alloc_layout_null(&x->_this); } @@ -845,8 +900,12 @@ static inline void zc_closure_matching_status_take(zc_owned_closure_matching_sta static inline void zc_concurrent_close_handle_take(zc_owned_concurrent_close_handle_t* this_, zc_moved_concurrent_close_handle_t* x) { *this_ = x->_this; zc_internal_concurrent_close_handle_null(&x->_this); } static inline void zc_matching_listener_take(zc_owned_matching_listener_t* this_, zc_moved_matching_listener_t* x) { *this_ = x->_this; zc_internal_matching_listener_null(&x->_this); } static inline void zc_shm_client_list_take(zc_owned_shm_client_list_t* this_, zc_moved_shm_client_list_t* x) { *this_ = x->_this; zc_internal_shm_client_list_null(&x->_this); } +static inline void ze_advanced_publisher_take(ze_owned_advanced_publisher_t* this_, ze_moved_advanced_publisher_t* x) { *this_ = x->_this; ze_internal_advanced_publisher_null(&x->_this); } +static inline void ze_advanced_subscriber_take(ze_owned_advanced_subscriber_t* this_, ze_moved_advanced_subscriber_t* x) { *this_ = x->_this; ze_internal_advanced_subscriber_null(&x->_this); } +static inline void ze_closure_miss_take(ze_owned_closure_miss_t* closure_, ze_moved_closure_miss_t* x) { *closure_ = x->_this; ze_internal_closure_miss_null(&x->_this); } static inline void ze_publication_cache_take(ze_owned_publication_cache_t* this_, ze_moved_publication_cache_t* x) { *this_ = x->_this; ze_internal_publication_cache_null(&x->_this); } static inline void ze_querying_subscriber_take(ze_owned_querying_subscriber_t* this_, ze_moved_querying_subscriber_t* x) { *this_ = x->_this; ze_internal_querying_subscriber_null(&x->_this); } +static inline void ze_sample_miss_listener_take(ze_owned_sample_miss_listener_t* this_, ze_moved_sample_miss_listener_t* x) { *this_ = x->_this; ze_internal_sample_miss_listener_null(&x->_this); } static inline void ze_serializer_take(ze_owned_serializer_t* this_, ze_moved_serializer_t* x) { *this_ = x->_this; ze_internal_serializer_null(&x->_this); } @@ -992,12 +1051,24 @@ inline void z_take(zc_owned_matching_listener_t* this_, zc_moved_matching_listen inline void z_take(zc_owned_shm_client_list_t* this_, zc_moved_shm_client_list_t* x) { zc_shm_client_list_take(this_, x); }; +inline void z_take(ze_owned_advanced_publisher_t* this_, ze_moved_advanced_publisher_t* x) { + ze_advanced_publisher_take(this_, x); +}; +inline void z_take(ze_owned_advanced_subscriber_t* this_, ze_moved_advanced_subscriber_t* x) { + ze_advanced_subscriber_take(this_, x); +}; +inline void z_take(ze_owned_closure_miss_t* closure_, ze_moved_closure_miss_t* x) { + ze_closure_miss_take(closure_, x); +}; inline void z_take(ze_owned_publication_cache_t* this_, ze_moved_publication_cache_t* x) { ze_publication_cache_take(this_, x); }; inline void z_take(ze_owned_querying_subscriber_t* this_, ze_moved_querying_subscriber_t* x) { ze_querying_subscriber_take(this_, x); }; +inline void z_take(ze_owned_sample_miss_listener_t* this_, ze_moved_sample_miss_listener_t* x) { + ze_sample_miss_listener_take(this_, x); +}; inline void z_take(ze_owned_serializer_t* this_, ze_moved_serializer_t* x) { ze_serializer_take(this_, x); }; @@ -1050,8 +1121,12 @@ inline bool z_internal_check(const zc_owned_closure_matching_status_t& this_) { inline bool z_internal_check(const zc_owned_concurrent_close_handle_t& this_) { return zc_internal_concurrent_close_handle_check(&this_); }; inline bool z_internal_check(const zc_owned_matching_listener_t& this_) { return zc_internal_matching_listener_check(&this_); }; inline bool z_internal_check(const zc_owned_shm_client_list_t& this_) { return zc_internal_shm_client_list_check(&this_); }; +inline bool z_internal_check(const ze_owned_advanced_publisher_t& this_) { return ze_internal_advanced_publisher_check(&this_); }; +inline bool z_internal_check(const ze_owned_advanced_subscriber_t& this_) { return ze_internal_advanced_subscriber_check(&this_); }; +inline bool z_internal_check(const ze_owned_closure_miss_t& this_) { return ze_internal_closure_miss_check(&this_); }; inline bool z_internal_check(const ze_owned_publication_cache_t& this_) { return ze_internal_publication_cache_check(&this_); }; inline bool z_internal_check(const ze_owned_querying_subscriber_t& this_) { return ze_internal_querying_subscriber_check(&this_); }; +inline bool z_internal_check(const ze_owned_sample_miss_listener_t& this_) { return ze_internal_sample_miss_listener_check(&this_); }; inline bool z_internal_check(const ze_owned_serializer_t& this_) { return ze_internal_serializer_check(&this_); }; @@ -1073,6 +1148,9 @@ inline void z_call(const z_loaned_closure_zid_t* closure, const z_id_t* z_id) { inline void z_call(const zc_loaned_closure_matching_status_t* closure, const zc_matching_status_t* mathing_status) { zc_closure_matching_status_call(closure, mathing_status); }; +inline void z_call(const ze_loaned_closure_miss_t* closure, const ze_miss_t* mathing_status) { + ze_closure_miss_call(closure, mathing_status); +}; extern "C" using z_closure_drop_callback_t = void(void* context); extern "C" using z_closure_hello_callback_t = void(z_loaned_hello_t *hello, void *context); @@ -1082,6 +1160,7 @@ extern "C" using z_closure_sample_callback_t = void(z_loaned_sample_t *sample, v extern "C" using z_closure_zid_callback_t = void(const z_id_t *z_id, void *context); extern "C" using zc_closure_log_callback_t = void(zc_log_severity_t severity, const z_loaned_string_t *msg, void *context); extern "C" using zc_closure_matching_status_callback_t = void(const zc_matching_status_t *matching_status, void *context); +extern "C" using ze_closure_miss_callback_t = void(const ze_miss_t *matching_status, void *context); inline void z_closure(z_owned_closure_hello_t* this_, z_closure_hello_callback_t* call, z_closure_drop_callback_t* drop, void* context) { @@ -1111,6 +1190,10 @@ inline void z_closure(zc_owned_closure_matching_status_t* this_, zc_closure_matc z_closure_drop_callback_t* drop, void* context) { zc_closure_matching_status(this_, call, drop, context); }; +inline void z_closure(ze_owned_closure_miss_t* this_, ze_closure_miss_callback_t* call, + z_closure_drop_callback_t* drop, void* context) { + ze_closure_miss(this_, call, drop, context); +}; inline z_result_t z_try_recv(const z_loaned_fifo_handler_query_t* this_, z_owned_query_t* query) { @@ -1280,6 +1363,12 @@ template<> struct z_loaned_to_owned_type_t template<> struct z_owned_to_loaned_type_t { typedef zc_loaned_closure_matching_status_t type; }; template<> struct z_loaned_to_owned_type_t { typedef zc_owned_shm_client_list_t type; }; template<> struct z_owned_to_loaned_type_t { typedef zc_loaned_shm_client_list_t type; }; +template<> struct z_loaned_to_owned_type_t { typedef ze_owned_advanced_publisher_t type; }; +template<> struct z_owned_to_loaned_type_t { typedef ze_loaned_advanced_publisher_t type; }; +template<> struct z_loaned_to_owned_type_t { typedef ze_owned_advanced_subscriber_t type; }; +template<> struct z_owned_to_loaned_type_t { typedef ze_loaned_advanced_subscriber_t type; }; +template<> struct z_loaned_to_owned_type_t { typedef ze_owned_closure_miss_t type; }; +template<> struct z_owned_to_loaned_type_t { typedef ze_loaned_closure_miss_t type; }; template<> struct z_loaned_to_owned_type_t { typedef ze_owned_publication_cache_t type; }; template<> struct z_owned_to_loaned_type_t { typedef ze_loaned_publication_cache_t type; }; template<> struct z_loaned_to_owned_type_t { typedef ze_owned_querying_subscriber_t type; }; diff --git a/splitguide.yaml b/splitguide.yaml index 056d89cc6..21aa74bcc 100644 --- a/splitguide.yaml +++ b/splitguide.yaml @@ -39,6 +39,10 @@ zenoh_opaque.h: - z_loaned_querier_t!#unstable - ze_owned_querying_subscriber_t!#unstable - ze_loaned_querying_subscriber_t!#unstable + - ze_owned_advanced_subscriber_t!#unstable + - ze_loaned_advanced_subscriber_t!#unstable + - ze_owned_advanced_publisher_t!#unstable + - ze_loaned_advanced_publisher_t!#unstable - z_owned_keyexpr_t! - z_view_keyexpr_t! - z_loaned_keyexpr_t! @@ -120,4 +124,3 @@ zenoh_opaque.h: - z_owned_ring_handler_reply_t! - z_loaned_ring_handler_reply_t! - zc_owned_concurrent_close_handle_t!#unstable - diff --git a/src/advanced_publisher.rs b/src/advanced_publisher.rs new file mode 100644 index 000000000..7309cc76d --- /dev/null +++ b/src/advanced_publisher.rs @@ -0,0 +1,464 @@ +// +// Copyright (c) 2017, 2022 ZettaScale Technology. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh team, +// + +use std::mem::MaybeUninit; + +use zenoh::{ + handlers::Callback, + matching::MatchingStatus, + qos::{CongestionControl, Priority}, + session::SessionClosedError, + Wait, +}; +use zenoh_ext::{AdvancedPublisherBuilderExt, CacheConfig}; + +use crate::{ + _apply_pubisher_delete_options, _apply_pubisher_put_options, _declare_publisher_inner, + result::{self}, + transmute::{IntoCType, LoanedCTypeRef, RustTypeRef, RustTypeRefUninit, TakeRustType}, + z_congestion_control_t, z_entity_global_id_t, z_loaned_keyexpr_t, z_loaned_session_t, + z_moved_bytes_t, z_priority_t, z_publisher_delete_options_t, z_publisher_options_t, + z_publisher_put_options_t, zc_closure_matching_status_call, zc_closure_matching_status_loan, + zc_matching_status_t, zc_moved_closure_matching_status_t, zc_owned_matching_listener_t, +}; + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Setting for advanced publisher's cache. The cache allows advanced subscribers to recover history and/or lost samples. +#[repr(C)] +pub struct ze_advanced_publisher_cache_options_t { + /// Number of samples to keep for each resource + pub max_samples: usize, + /// The congestion control to apply to replies. + pub congestion_control: z_congestion_control_t, + /// The priority of replies. + pub priority: z_priority_t, + /// If set to ``true``, this cache replies will not be batched. This usually has a positive impact on latency but negative impact on throughput. + pub is_express: bool, +} + +impl Default for ze_advanced_publisher_cache_options_t { + fn default() -> Self { + Self { + max_samples: 1, + congestion_control: CongestionControl::default().into(), + priority: Priority::default().into(), + is_express: false, + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs the default value for `ze_advanced_publisher_cache_options_t`. +#[no_mangle] +pub extern "C" fn ze_advanced_publisher_cache_options_default( + this: &mut MaybeUninit, +) { + this.write(ze_advanced_publisher_cache_options_t::default()); +} + +impl From<&ze_advanced_publisher_cache_options_t> for CacheConfig { + fn from(val: &ze_advanced_publisher_cache_options_t) -> CacheConfig { + let mut c = CacheConfig::default(); + c = c.max_samples(val.max_samples); + let qos = zenoh_ext::RepliesConfig::default() + .congestion_control(val.congestion_control.into()) + .express(val.is_express) + .priority(val.priority.into()); + c = c.replies_config(qos); + c + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Options passed to the `ze_declare_advanced_publisher()` function. +#[repr(C)] +pub struct ze_advanced_publisher_options_t { + /// Base publisher options. + pub publisher_options: z_publisher_options_t, + /// Optional settings for publisher cache. + pub cache: Option<&'static mut ze_advanced_publisher_cache_options_t>, + /// Allow matching Subscribers to detect lost samples and optionally ask for retransimission. + /// + /// Retransmission can only be done if history is enabled on subscriber side. + pub sample_miss_detection: bool, + /// Allow this publisher to be detected through liveliness. + pub publisher_detection: bool, + /// An optional key expression to be added to the liveliness token key expression. + /// It can be used to convey meta data. + pub publisher_detection_metadata: Option<&'static mut z_loaned_keyexpr_t>, +} + +/// Constructs the default value for `z_publisher_options_t`. +#[no_mangle] +pub extern "C" fn ze_advanced_publisher_options_default( + this_: &mut MaybeUninit, +) { + this_.write(ze_advanced_publisher_options_t { + publisher_options: z_publisher_options_t::default(), + cache: None, + sample_miss_detection: false, + publisher_detection: false, + publisher_detection_metadata: None, + }); +} + +pub use crate::opaque_types::{ + ze_loaned_advanced_publisher_t, ze_moved_advanced_publisher_t, ze_owned_advanced_publisher_t, +}; +decl_c_type!( + owned(ze_owned_advanced_publisher_t, option zenoh_ext::AdvancedPublisher<'static>), + loaned(ze_loaned_advanced_publisher_t), +); + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Constructs and declares an advanced publisher for the given key expression. +/// +/// Data can be put and deleted with this publisher with the help of the +/// `ze_advanced_publisher_put()` and `ze_advanced_publisher_delete()` functions. +/// +/// @param session: The Zenoh session. +/// @param publisher: An uninitialized location in memory where advanced publisher will be constructed. +/// @param key_expr: The key expression to publish to. +/// @param options: Additional options for the advanced publisher. +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_declare_advanced_publisher( + session: &'static z_loaned_session_t, + publisher: &'static mut MaybeUninit, + key_expr: &'static z_loaned_keyexpr_t, + mut options: Option<&'static mut ze_advanced_publisher_options_t>, +) -> result::z_result_t { + let this = publisher.as_rust_type_mut_uninit(); + let p = _declare_publisher_inner( + session, + key_expr, + options.as_mut().map(|o| &mut o.publisher_options), + ); + let mut p = p.advanced(); + if let Some(options) = options { + if options.publisher_detection { + p = p.publisher_detection(); + } + if options.sample_miss_detection { + p = p.sample_miss_detection(); + } + if let Some(pub_detection_metadata) = &options.publisher_detection_metadata { + p = p.publisher_detection_metadata(pub_detection_metadata.as_rust_type_ref()); + } + if let Some(cache) = &options.cache { + p = p.cache((&**cache).into()); + } + } + match p.wait() { + Err(e) => { + tracing::error!("{}", e); + this.write(None); + result::Z_EGENERIC + } + Ok(publisher) => { + this.write(Some(publisher)); + result::Z_OK + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Constructs an advanced publisher in a gravestone state. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_internal_advanced_publisher_null( + this_: &mut MaybeUninit, +) { + this_.as_rust_type_mut_uninit().write(None); +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Returns ``true`` if advanced publisher is valid, ``false`` otherwise. +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +pub extern "C" fn ze_internal_advanced_publisher_check( + this_: &ze_owned_advanced_publisher_t, +) -> bool { + this_.as_rust_type_ref().is_some() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Borrows advanced publisher. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn ze_advanced_publisher_loan( + this_: &ze_owned_advanced_publisher_t, +) -> &ze_loaned_advanced_publisher_t { + this_ + .as_rust_type_ref() + .as_ref() + .unwrap_unchecked() + .as_loaned_c_type_ref() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Mutably borrows advanced publisher. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn ze_advanced_publisher_loan_mut( + this: &mut ze_owned_advanced_publisher_t, +) -> &mut ze_loaned_advanced_publisher_t { + this.as_rust_type_mut() + .as_mut() + .unwrap_unchecked() + .as_loaned_c_type_mut() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Options passed to the `ze_advanced_publisher_put()` function. +#[repr(C)] +pub struct ze_advanced_publisher_put_options_t { + /// Base put options. + put_options: z_publisher_put_options_t, +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Constructs the default value for `ze_advanced_publisher_put_options_t`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_advanced_publisher_put_options_default( + this: &mut MaybeUninit, +) { + this.write(ze_advanced_publisher_put_options_t { + put_options: z_publisher_put_options_t::default(), + }); +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Sends a `PUT` message onto the advanced publisher's key expression, transfering the payload ownership. +/// +/// The payload and all owned options fields are consumed upon function return. +/// +/// @param this_: The advanced publisher. +/// @param payload: The data to publish. Will be consumed. +/// @param options: The advanced publisher put options. All owned fields will be consumed. +/// +/// @return 0 in case of success, negative error values in case of failure. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn ze_advanced_publisher_put( + this: &ze_loaned_advanced_publisher_t, + payload: &mut z_moved_bytes_t, + options: Option<&mut ze_advanced_publisher_put_options_t>, +) -> result::z_result_t { + let publisher = this.as_rust_type_ref(); + let payload = payload.take_rust_type(); + let mut put = publisher.put(payload); + if let Some(options) = options { + put = _apply_pubisher_put_options(put, &mut options.put_options); + } + match put.wait() { + Ok(_) => result::Z_OK, + Err(e) if e.downcast_ref::().is_some() => result::Z_ESESSION_CLOSED, + Err(e) => { + tracing::error!("{}", e); + result::Z_EGENERIC + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Represents the set of options that can be applied to the delete operation by a previously declared advanced publisher, +/// whenever issued via `ze_advanced_publisher_delete()`. +#[repr(C)] +pub struct ze_advanced_publisher_delete_options_t { + /// Base delete options. + pub delete_options: z_publisher_delete_options_t, +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Constructs the default values for the delete operation via an advanced publisher entity. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_advanced_publisher_delete_options_default( + this: &mut MaybeUninit, +) { + this.write(ze_advanced_publisher_delete_options_t { + delete_options: z_publisher_delete_options_t::default(), + }); +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Sends a `DELETE` message onto the advanced publisher's key expression. +/// +/// @return 0 in case of success, negative error code in case of failure. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_advanced_publisher_delete( + publisher: &ze_loaned_advanced_publisher_t, + options: Option<&mut ze_advanced_publisher_delete_options_t>, +) -> result::z_result_t { + let publisher = publisher.as_rust_type_ref(); + let mut del = publisher.delete(); + if let Some(options) = options { + del = _apply_pubisher_delete_options(del, &mut options.delete_options) + } + if let Err(e) = del.wait() { + tracing::error!("{}", e); + result::Z_EGENERIC + } else { + result::Z_OK + } +} +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Returns the ID of the advanced publisher. +#[no_mangle] +pub extern "C" fn ze_advanced_publisher_id( + publisher: &ze_loaned_advanced_publisher_t, +) -> z_entity_global_id_t { + publisher.as_rust_type_ref().id().into_c_type() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Returns the key expression of the publisher. +#[no_mangle] +pub extern "C" fn ze_advanced_publisher_keyexpr( + publisher: &ze_loaned_advanced_publisher_t, +) -> &z_loaned_keyexpr_t { + publisher + .as_rust_type_ref() + .key_expr() + .as_loaned_c_type_ref() +} + +#[cfg(feature = "unstable")] +fn _advanced_publisher_matching_listener_declare_inner<'a>( + publisher: &'a ze_loaned_advanced_publisher_t, + callback: &mut zc_moved_closure_matching_status_t, +) -> zenoh::matching::MatchingListenerBuilder<'a, Callback> { + let publisher = publisher.as_rust_type_ref(); + let callback = callback.take_rust_type(); + let listener = publisher + .matching_listener() + .callback_mut(move |matching_status| { + let status = zc_matching_status_t { + matching: matching_status.matching(), + }; + zc_closure_matching_status_call(zc_closure_matching_status_loan(&callback), &status); + }); + listener +} + +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs matching listener, registering a callback for notifying subscribers matching with a given advanced publisher. +/// +/// @param publisher: An advanced publisher to associate with matching listener. +/// @param matching_listener: An uninitialized memory location where matching listener will be constructed. The matching listener's callback will be automatically dropped when the publisher is dropped. +/// @param callback: A closure that will be called every time the matching status of the publisher changes (If last subscriber disconnects or when the first subscriber connects). +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn ze_advanced_publisher_declare_matching_listener( + publisher: &'static ze_loaned_advanced_publisher_t, + matching_listener: &mut MaybeUninit, + callback: &mut zc_moved_closure_matching_status_t, +) -> result::z_result_t { + let this = matching_listener.as_rust_type_mut_uninit(); + let listener = _advanced_publisher_matching_listener_declare_inner(publisher, callback); + match listener.wait() { + Ok(listener) => { + this.write(Some(listener)); + result::Z_OK + } + Err(e) => { + this.write(None); + tracing::error!("{}", e); + result::Z_EGENERIC + } + } +} + +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Declares a matching listener, registering a callback for notifying subscribers matching with a given advanced publisher. +/// The callback will be run in the background until the corresponding publisher is dropped. +/// +/// @param publisher: An advanced publisher to associate with matching listener. +/// @param callback: A closure that will be called every time the matching status of the publisher changes (If last subscriber disconnects or when the first subscriber connects). +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn ze_advanced_publisher_declare_background_matching_listener( + publisher: &'static ze_loaned_advanced_publisher_t, + callback: &mut zc_moved_closure_matching_status_t, +) -> result::z_result_t { + let listener = _advanced_publisher_matching_listener_declare_inner(publisher, callback); + match listener.background().wait() { + Ok(_) => result::Z_OK, + Err(e) => { + tracing::error!("{}", e); + result::Z_EGENERIC + } + } +} + +#[cfg(feature = "unstable")] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Gets advanced publisher matching status - i.e. if there are any subscribers matching its key expression. +/// +/// @return 0 in case of success, negative error code otherwise (in this case matching_status is not updated). +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_advanced_publisher_get_matching_status( + this: &'static ze_loaned_advanced_publisher_t, + matching_status: &mut MaybeUninit, +) -> result::z_result_t { + match this.as_rust_type_ref().matching_status().wait() { + Ok(s) => { + matching_status.write(zc_matching_status_t { + matching: s.matching(), + }); + result::Z_OK + } + Err(e) => { + tracing::error!("{}", e); + result::Z_ENETWORK + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Frees memory and resets advanced_publisher to its gravestone state. +/// This is equivalent to calling `z_undeclare_publisher()` and discarding its return value. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_advanced_publisher_drop(this: &mut ze_moved_advanced_publisher_t) { + std::mem::drop(this.take_rust_type()) +} + +#[no_mangle] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Undeclares the given advanced publisher. +/// +/// @return 0 in case of success, negative error code otherwise. +pub extern "C" fn ze_undeclare_advanced_publisher( + this_: &mut ze_moved_advanced_publisher_t, +) -> result::z_result_t { + if let Some(p) = this_.take_rust_type() { + if let Err(e) = p.undeclare().wait() { + tracing::error!("{}", e); + return result::Z_ENETWORK; + } + } + result::Z_OK +} diff --git a/src/advanced_subscriber.rs b/src/advanced_subscriber.rs new file mode 100644 index 000000000..6312e229b --- /dev/null +++ b/src/advanced_subscriber.rs @@ -0,0 +1,492 @@ +// +// Copyright (c) 2024 ZettaScale Technology. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh team, +// + +use std::{mem::MaybeUninit, time::Duration}; + +use zenoh::{handlers::Callback, liveliness::LivelinessSubscriberBuilder, sample::Sample, Wait}; +use zenoh_ext::{AdvancedSubscriberBuilderExt, HistoryConfig, RecoveryConfig, SampleMissListener}; + +use crate::{ + _declare_subscriber_inner, result, + transmute::{IntoCType, LoanedCTypeRef, RustTypeRef, RustTypeRefUninit, TakeRustType}, + z_closure_sample_call, z_closure_sample_loan, z_entity_global_id_t, + z_liveliness_subscriber_options_t, z_loaned_keyexpr_t, z_loaned_session_t, + z_moved_closure_sample_t, z_owned_subscriber_t, z_subscriber_options_t, ze_closure_miss_call, + ze_closure_miss_loan, ze_loaned_advanced_subscriber_t, ze_moved_advanced_subscriber_t, + ze_moved_closure_miss_t, ze_moved_sample_miss_listener_t, ze_owned_advanced_subscriber_t, + ze_owned_sample_miss_listener_t, +}; + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Settings for retrievieng historical data for Advanced Subscriber. +#[repr(C)] +#[derive(Default)] +pub struct ze_advanced_subscriber_history_options_t { + /// Enable detection of late joiner publishers and query for their historical data. + /// Late joiner detection can only be achieved for Publishers that enable publisher_detection. + /// History can only be retransmitted by Publishers that enable caching. + pub detect_late_publishers: bool, + /// Number of samples to query for each resource. ``0`` corresponds to no limit on number of samples. + pub max_samples: usize, + /// Maximum age of samples to query. ``0`` corresponds to no limit on samples' age. + pub max_age_ms: u64, +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs the default value for `ze_advanced_subscriber_history_options_t`. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_history_options_default( + this: &mut MaybeUninit, +) { + this.write(ze_advanced_subscriber_history_options_t::default()); +} + +impl From<&ze_advanced_subscriber_history_options_t> for HistoryConfig { + fn from(val: &ze_advanced_subscriber_history_options_t) -> Self { + let mut h = HistoryConfig::default(); + if val.detect_late_publishers { + h = h.detect_late_publishers(); + } + if val.max_samples > 0 { + h = h.max_samples(val.max_samples) + } + if val.max_age_ms > 0 { + h = h.max_age(val.max_age_ms as f64 / 1000.0f64) + } + h + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Settings for recovering lost messages for Advanced Subscriber. +#[repr(C)] +#[derive(Default)] +pub struct ze_advanced_subscriber_recovery_options_t { + /// Period for queries for not yet received Samples. + /// + /// These queries allow to retrieve the last Sample(s) if the last Sample(s) is/are lost. + /// So it is useful for sporadic publications but useless for periodic publications + /// with a period smaller or equal to this period. + /// Retransmission can only be achieved by Publishers that also activate retransmission. + pub periodic_queries_period_ms: u64, +} + +impl From<&ze_advanced_subscriber_recovery_options_t> for RecoveryConfig { + fn from(val: &ze_advanced_subscriber_recovery_options_t) -> RecoveryConfig { + let mut r = RecoveryConfig::default(); + if val.periodic_queries_period_ms > 0 { + r = r.periodic_queries(Some(Duration::from_millis(val.periodic_queries_period_ms))); + } + r + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs the default value for `ze_advanced_subscriber_recovery_options_t`. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_recovery_options_default( + this: &mut MaybeUninit, +) { + this.write(ze_advanced_subscriber_recovery_options_t::default()); +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Options passed to the `ze_declare_advanced_subscriber()` function. +#[repr(C)] +pub struct ze_advanced_subscriber_options_t { + /// Base subscriber options. + pub subscriber_options: z_subscriber_options_t, + /// Optional settings for querying historical data. History can only be retransmitted by Publishers that enable caching. + /// Querying historical data is disabled if the value is ``NULL``. + pub history: Option<&'static mut ze_advanced_subscriber_history_options_t>, + /// Optional settings for retransmission of detected lost Samples. Retransmission of lost samples can only be done by Publishers that enable + /// caching and sample_miss_detection. + /// Retransmission is disabled if the value is ``NULL``. + pub recovery: Option<&'static mut ze_advanced_subscriber_recovery_options_t>, + /// Timeout to be used for history and recovery queries. + /// Default value will be used if set to ``0``. + pub query_timeout_ms: u64, + /// Allow this subscriber to be detected through liveliness. + pub subscriber_detection: bool, + /// An optional key expression to be added to the liveliness token key expression. + /// It can be used to convey meta data. + pub subscriber_detection_metadata: Option<&'static mut z_loaned_keyexpr_t>, +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs the default value for `ze_advanced_subscriber_options_t`. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_options_default( + this: &mut MaybeUninit, +) { + this.write(ze_advanced_subscriber_options_t { + subscriber_options: z_subscriber_options_t::default(), + history: None, + recovery: None, + query_timeout_ms: 0, + subscriber_detection: false, + subscriber_detection_metadata: None, + }); +} + +fn _declare_advanced_subscriber_inner( + session: &'static z_loaned_session_t, + key_expr: &'static z_loaned_keyexpr_t, + callback: &mut z_moved_closure_sample_t, + mut options: Option<&'static mut ze_advanced_subscriber_options_t>, +) -> zenoh_ext::AdvancedSubscriberBuilder<'static, 'static, 'static, Callback> { + let sub = _declare_subscriber_inner( + session, + key_expr, + callback, + options.as_mut().map(|o| &mut o.subscriber_options), + ); + let mut sub = sub.advanced(); + if let Some(options) = options { + if options.query_timeout_ms > 0 { + sub = sub.query_timeout(Duration::from_millis(options.query_timeout_ms)); + } + if options.subscriber_detection { + sub = sub.subscriber_detection() + } + if let Some(sub_detection_metadata) = &options.subscriber_detection_metadata { + sub = sub.subscriber_detection_metadata(sub_detection_metadata.as_rust_type_ref()); + } + if let Some(history) = &options.history { + sub = sub.history((&**history).into()); + } + if let Some(recovery) = &options.recovery { + sub = sub.recovery((&**recovery).into()); + } + } + sub +} + +decl_c_type!( + owned(ze_owned_advanced_subscriber_t, option zenoh_ext::AdvancedSubscriber<()>), + loaned(ze_loaned_advanced_subscriber_t), +); + +/// Constructs a subscriber in a gravestone state. +#[no_mangle] +pub extern "C" fn ze_internal_advanced_subscriber_null( + this_: &mut MaybeUninit, +) { + this_.as_rust_type_mut_uninit().write(None); +} + +/// Borrows subscriber. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn ze_advanced_subscriber_loan( + this_: &ze_owned_advanced_subscriber_t, +) -> &ze_loaned_advanced_subscriber_t { + this_ + .as_rust_type_ref() + .as_ref() + .unwrap_unchecked() + .as_loaned_c_type_ref() +} + +/// Undeclares advanced subscriber callback and resets it to its gravestone state. +/// This is equivalent to calling `ze_undeclare_advanced_subscriber()` and discarding its return value. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_drop(this_: &mut ze_moved_advanced_subscriber_t) { + std::mem::drop(this_.take_rust_type()) +} + +/// Returns ``true`` if advanced subscriber is valid, ``false`` otherwise. +#[no_mangle] +pub extern "C" fn ze_internal_advanced_subscriber_check( + this_: &ze_owned_advanced_subscriber_t, +) -> bool { + this_.as_rust_type_ref().is_some() +} + +/// Constructs and declares an advanced subscriber for a given key expression. Dropping subscriber undeclares its callback. +/// +/// @param session: The zenoh session. +/// @param subscriber: An uninitialized location in memory, where advanced subscriber will be constructed. +/// @param key_expr: The key expression to subscribe. +/// @param callback: The callback function that will be called each time a data matching the subscribed expression is received. +/// @param options: The options to be passed to the subscriber declaration. +/// +/// @return 0 in case of success, negative error code otherwise (in this case subscriber will be in its gravestone state). +#[no_mangle] +pub extern "C" fn ze_declare_advanced_subscriber( + session: &'static z_loaned_session_t, + subscriber: &'static mut MaybeUninit, + key_expr: &'static z_loaned_keyexpr_t, + callback: &'static mut z_moved_closure_sample_t, + options: Option<&'static mut ze_advanced_subscriber_options_t>, +) -> result::z_result_t { + let this = subscriber.as_rust_type_mut_uninit(); + let s = _declare_advanced_subscriber_inner(session, key_expr, callback, options); + match s.wait() { + Ok(sub) => { + this.write(Some(sub)); + result::Z_OK + } + Err(e) => { + tracing::error!("{}", e); + this.write(None); + result::Z_EGENERIC + } + } +} + +/// Constructs and declares a background advanced subscriber. Subscriber callback will be called to process the messages, +/// until the corresponding session is closed or dropped. +/// +/// @param session: The zenoh session. +/// @param key_expr: The key expression to subscribe. +/// @param callback: The callback function that will be called each time a data matching the subscribed expression is received. +/// @param options: The options to be passed to the subscriber declaration. +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn ze_declare_background_advanced_subscriber( + session: &'static z_loaned_session_t, + key_expr: &'static z_loaned_keyexpr_t, + callback: &'static mut z_moved_closure_sample_t, + options: Option<&'static mut ze_advanced_subscriber_options_t>, +) -> result::z_result_t { + let subscriber = _declare_advanced_subscriber_inner(session, key_expr, callback, options); + match subscriber.background().wait() { + Ok(_) => result::Z_OK, + Err(e) => { + tracing::error!("{}", e); + result::Z_EGENERIC + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// Undeclares the advanced subscriber. +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn ze_undeclare_advanced_subscriber( + this_: &mut ze_moved_advanced_subscriber_t, +) -> result::z_result_t { + if let Some(s) = this_.take_rust_type() { + if let Err(e) = s.undeclare().wait() { + tracing::error!("{}", e); + return result::Z_EGENERIC; + } + } + result::Z_OK +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief A struct that represent missed samples. +#[repr(C)] +pub struct ze_miss_t { + /// The source of missed samples. + pub source: z_entity_global_id_t, + /// The number of missed samples. + pub nb: u32, +} + +decl_c_type!( + owned(ze_owned_sample_miss_listener_t, option SampleMissListener<()>), +); + +#[no_mangle] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs an empty sample miss listener. +pub extern "C" fn ze_internal_sample_miss_listener_null( + this_: &mut MaybeUninit, +) { + this_.as_rust_type_mut_uninit().write(None); +} + +#[no_mangle] +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Checks the sample_miss listener is for the gravestone state +pub extern "C" fn ze_internal_sample_miss_listener_check( + this_: &ze_owned_sample_miss_listener_t, +) -> bool { + this_.as_rust_type_ref().is_some() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Undeclares the given sample miss listener, droping and invalidating it. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_sample_miss_listener_drop(this: &mut ze_moved_sample_miss_listener_t) { + std::mem::drop(this.take_rust_type()) +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Undeclares the given sample miss listener, droping and invalidating it. +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn ze_undeclare_sample_miss_listener( + this: &mut ze_moved_sample_miss_listener_t, +) -> result::z_result_t { + if let Some(m) = this.take_rust_type() { + if let Err(e) = m.undeclare().wait() { + tracing::error!("{}", e); + return result::Z_ENETWORK; + } + } + result::Z_OK +} + +fn _advanced_subscriber_sample_miss_listener_declare_inner<'a>( + subscriber: &'a ze_loaned_advanced_subscriber_t, + callback: &mut ze_moved_closure_miss_t, +) -> zenoh_ext::SampleMissListenerBuilder<'a, Callback> { + let subscriber = subscriber.as_rust_type_ref(); + let callback = callback.take_rust_type(); + let listener = subscriber.sample_miss_listener().callback_mut(move |miss| { + let miss = ze_miss_t { + source: miss.source().into_c_type(), + nb: miss.nb(), + }; + ze_closure_miss_call(ze_closure_miss_loan(&callback), &miss); + }); + listener +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs sample miss listener, registering a callback for notifying subscriber about missed samples. +/// +/// @param subscriber: A subscriber to associate with sample miss listener. +/// @param sample_miss_listener: An uninitialized memory location where sample miss listener will be constructed. The sample miss listener's callback will be automatically dropped when the subscriber is dropped. +/// @param callback: A closure that will be called every time the sample miss is detected. +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_declare_sample_miss_listener( + subscriber: &'static ze_loaned_advanced_subscriber_t, + sample_miss_listener: &mut MaybeUninit, + callback: &mut ze_moved_closure_miss_t, +) -> result::z_result_t { + let this = sample_miss_listener.as_rust_type_mut_uninit(); + let listener = _advanced_subscriber_sample_miss_listener_declare_inner(subscriber, callback); + match listener.wait() { + Ok(listener) => { + this.write(Some(listener)); + result::Z_OK + } + Err(e) => { + this.write(None); + tracing::error!("{}", e); + result::Z_EGENERIC + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Declares a sample miss listener, registering a callback for notifying subscriber about missed samples. +/// The callback will be run in the background until the corresponding subscriber is dropped. +/// +/// @param subscriber: A subscriber to associate with sample miss listener. +/// @param callback: A closure that will be called every time the sample miss is detected. +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_declare_background_sample_miss_listener( + subscriber: &'static ze_loaned_advanced_subscriber_t, + callback: &mut ze_moved_closure_miss_t, +) -> result::z_result_t { + let listener = _advanced_subscriber_sample_miss_listener_declare_inner(subscriber, callback); + match listener.background().wait() { + Ok(_) => result::Z_OK, + Err(e) => { + tracing::error!("{}", e); + result::Z_EGENERIC + } + } +} + +fn _advanced_subscriber_detect_publishers_inner( + subscriber: &'static ze_loaned_advanced_subscriber_t, + callback: &'static mut z_moved_closure_sample_t, + options: Option<&'static mut z_liveliness_subscriber_options_t>, +) -> LivelinessSubscriberBuilder<'static, 'static, Callback> { + let subscriber = subscriber.as_rust_type_ref(); + let callback = callback.take_rust_type(); + let sub = subscriber + .detect_publishers() + .history(options.is_some_and(|o| o.history)) + .callback(move |sample| { + let mut owned_sample = Some(sample); + z_closure_sample_call(z_closure_sample_loan(&callback), unsafe { + owned_sample + .as_mut() + .unwrap_unchecked() + .as_loaned_c_type_mut() + }) + }); + sub +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Declares a subscriber on liveliness tokens for matching publishers detection. Only advanced publishers. enabling publisher detection can be detected. +/// +/// @param subscriber: The advanced subscriber instance. +/// @param liveliness_subscriber: An uninitialized memory location where liveliness subscriber will be constructed. +/// @param callback: The callback function that will be called each time a liveliness token status is changed. +/// @param options: The options to be passed to the liveliness subscriber declaration. +/// +/// @return 0 in case of success, negative error values otherwise. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_detect_publishers( + subscriber: &'static ze_loaned_advanced_subscriber_t, + liveliness_subscriber: &mut MaybeUninit, + callback: &'static mut z_moved_closure_sample_t, + options: Option<&'static mut z_liveliness_subscriber_options_t>, +) -> result::z_result_t { + let liveliness_subscriber = liveliness_subscriber.as_rust_type_mut_uninit(); + let builder = _advanced_subscriber_detect_publishers_inner(subscriber, callback, options); + match builder.wait() { + Ok(s) => { + liveliness_subscriber.write(Some(s)); + result::Z_OK + } + Err(e) => { + tracing::error!("Failed to subscribe to liveliness: {e}"); + liveliness_subscriber.write(None); + result::Z_EGENERIC + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Declares a background subscriber on liveliness tokens of matching publishers. Subscriber callback will be called to process the messages, +/// until the corresponding session is closed or dropped. Only advanced publishers. enabling publisher detection can be detected. +/// @param subscriber: The advanced subscriber instance. +/// @param callback: The callback function that will be called each time a liveliness token status is changed. +/// @param options: The options to be passed to the liveliness subscriber declaration. +/// +/// @return 0 in case of success, negative error values otherwise. +#[no_mangle] +pub extern "C" fn ze_advanced_subscriber_detect_publishers_background( + subscriber: &'static ze_loaned_advanced_subscriber_t, + callback: &'static mut z_moved_closure_sample_t, + options: Option<&'static mut z_liveliness_subscriber_options_t>, +) -> result::z_result_t { + let builder = _advanced_subscriber_detect_publishers_inner(subscriber, callback, options); + match builder.background().wait() { + Ok(_) => result::Z_OK, + Err(e) => { + tracing::error!("Failed to subscribe to liveliness: {e}"); + result::Z_EGENERIC + } + } +} diff --git a/src/closures/miss_closure.rs b/src/closures/miss_closure.rs new file mode 100644 index 000000000..511eef29c --- /dev/null +++ b/src/closures/miss_closure.rs @@ -0,0 +1,169 @@ +// +// Copyright (c) 2017, 2024 ZettaScale Technology. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh team, +// +use std::mem::MaybeUninit; + +use libc::c_void; + +use crate::{ + transmute::{LoanedCTypeRef, OwnedCTypeRef, TakeRustType}, + ze_miss_t, +}; +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief A sample miss-processing closure. +/// +/// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. +#[repr(C)] +pub struct ze_owned_closure_miss_t { + _context: *mut c_void, + _call: Option, + _drop: Option, +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Loaned closure. +#[repr(C)] +pub struct ze_loaned_closure_miss_t { + _0: [usize; 3], +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Moved closure. +#[repr(C)] +pub struct ze_moved_closure_miss_t { + _this: ze_owned_closure_miss_t, +} + +decl_c_type!( + owned(ze_owned_closure_miss_t), + loaned(ze_loaned_closure_miss_t), + moved(ze_moved_closure_miss_t), +); + +impl Default for ze_owned_closure_miss_t { + fn default() -> Self { + ze_owned_closure_miss_t { + _context: std::ptr::null_mut(), + _call: None, + _drop: None, + } + } +} + +impl ze_owned_closure_miss_t { + pub fn is_empty(&self) -> bool { + self._call.is_none() && self._drop.is_none() && self._context.is_null() + } +} +unsafe impl Send for ze_owned_closure_miss_t {} +unsafe impl Sync for ze_owned_closure_miss_t {} +impl Drop for ze_owned_closure_miss_t { + fn drop(&mut self) { + if let Some(drop) = self._drop { + drop(self._context) + } + } +} +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Constructs a null value of 'ze_owned_closure_miss_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn ze_internal_closure_miss_null( + this: *mut MaybeUninit, +) { + (*this).write(ze_owned_closure_miss_t::default()); +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Returns ``true`` if closure is valid, ``false`` if it is in gravestone state. +#[no_mangle] +pub extern "C" fn ze_internal_closure_miss_check(this: &ze_owned_closure_miss_t) -> bool { + !this.is_empty() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Calls the closure. Calling an uninitialized closure is a no-op. +#[no_mangle] +pub extern "C" fn ze_closure_miss_call( + closure: &ze_loaned_closure_miss_t, + mathing_status: &ze_miss_t, +) { + let closure = closure.as_owned_c_type_ref(); + match closure._call { + Some(call) => call(mathing_status, closure._context), + None => { + tracing::error!("Attempted to call an uninitialized closure!"); + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Drops the closure, resetting it to its gravestone state. Droping an uninitialized closure is a no-op. +#[no_mangle] +pub extern "C" fn ze_closure_miss_drop(closure_: &mut ze_moved_closure_miss_t) { + let _ = closure_.take_rust_type(); +} + +impl From for ze_owned_closure_miss_t { + fn from(f: F) -> Self { + let this = Box::into_raw(Box::new(f)) as _; + extern "C" fn call(response: &ze_miss_t, this: *mut c_void) { + let this = unsafe { &*(this as *const F) }; + this(response) + } + extern "C" fn drop(this: *mut c_void) { + std::mem::drop(unsafe { Box::from_raw(this as *mut F) }) + } + ze_owned_closure_miss_t { + _context: this, + _call: Some(call::), + _drop: Some(drop::), + } + } +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @brief Borrows closure. +#[no_mangle] +pub extern "C" fn ze_closure_miss_loan( + closure: &ze_owned_closure_miss_t, +) -> &ze_loaned_closure_miss_t { + closure.as_loaned_c_type_ref() +} + +/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// +/// Closures are not guaranteed not to be called concurrently. +/// +/// It is guaranteed that: +/// - `call` will never be called once `drop` has started. +/// - `drop` will only be called **once**, and **after every** `call` has ended. +/// - The two previous guarantees imply that `call` and `drop` are never called concurrently. +/// @brief Constructs closure. +/// @param this_: uninitialized memory location where new closure will be constructed. +/// @param call: a closure body. +/// @param drop: an optional function to be called once on closure drop. +/// @param context: closure context. +#[no_mangle] +pub extern "C" fn ze_closure_miss( + this: &mut MaybeUninit, + call: Option, + drop: Option, + context: *mut c_void, +) { + this.write(ze_owned_closure_miss_t { + _context: context, + _call: call, + _drop: drop, + }); +} diff --git a/src/closures/mod.rs b/src/closures/mod.rs index 29b33867b..13e82ef2b 100644 --- a/src/closures/mod.rs +++ b/src/closures/mod.rs @@ -42,3 +42,8 @@ mod log_closure; pub use matching_status_closure::*; #[cfg(feature = "unstable")] mod matching_status_closure; + +#[cfg(feature = "unstable")] +pub use miss_closure::*; +#[cfg(feature = "unstable")] +mod miss_closure; diff --git a/src/get.rs b/src/get.rs index 7ec363d14..4ccffc41b 100644 --- a/src/get.rs +++ b/src/get.rs @@ -159,7 +159,7 @@ pub struct z_get_options_t { pub encoding: Option<&'static mut z_moved_encoding_t>, /// The congestion control to apply when routing the query. pub congestion_control: z_congestion_control_t, - /// If true, Zenoh will not wait to batch this message with others to reduce the bandwith. + /// If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, #[cfg(feature = "unstable")] /// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. diff --git a/src/keyexpr.rs b/src/keyexpr.rs index 651cecd67..42db04533 100644 --- a/src/keyexpr.rs +++ b/src/keyexpr.rs @@ -458,7 +458,7 @@ pub unsafe extern "C" fn z_keyexpr_as_view_string( } /// Constructs and declares a key expression on the network. This reduces key key expression to a numerical id, -/// which allows to save the bandwith, when passing key expression between Zenoh entities. +/// which allows to save the bandwitdth, when passing key expression between Zenoh entities. /// /// @param session: Session on which to declare key expression. /// @param declared_key_expr: An uninitialized location in memory where key expression will be constructed. diff --git a/src/lib.rs b/src/lib.rs index 3e5ede75a..8354d993c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,14 @@ pub use publication_cache::*; mod querying_subscriber; #[cfg(feature = "unstable")] pub use querying_subscriber::*; +#[cfg(feature = "unstable")] +mod advanced_subscriber; +#[cfg(feature = "unstable")] +pub use advanced_subscriber::*; +#[cfg(feature = "unstable")] +mod advanced_publisher; +#[cfg(feature = "unstable")] +pub use advanced_publisher::*; #[cfg(all(feature = "shared-memory", feature = "unstable"))] pub mod context; diff --git a/src/liveliness.rs b/src/liveliness.rs index 87742ceef..ef8ee41b2 100644 --- a/src/liveliness.rs +++ b/src/liveliness.rs @@ -130,7 +130,7 @@ pub extern "C" fn z_liveliness_undeclare_token( #[repr(C)] pub struct z_liveliness_subscriber_options_t { /// If true, subscriber will receive the state change notifications for liveliness tokens that were declared before its declaration. - history: bool, + pub history: bool, } /// @brief Constucts default value for `z_liveliness_declare_subscriber_options_t`. diff --git a/src/publication_cache.rs b/src/publication_cache.rs index 464adbe85..9d1ab3b59 100644 --- a/src/publication_cache.rs +++ b/src/publication_cache.rs @@ -26,7 +26,7 @@ use crate::{ #[cfg(feature = "unstable")] use crate::{zc_locality_default, zc_locality_t}; -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Options passed to the `ze_declare_publication_cache()` function. #[repr(C)] pub struct ze_publication_cache_options_t { @@ -43,7 +43,7 @@ pub struct ze_publication_cache_options_t { pub resources_limit: usize, } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Constructs the default value for `ze_publication_cache_options_t`. #[no_mangle] pub extern "C" fn ze_publication_cache_options_default( @@ -96,7 +96,7 @@ fn _declare_publication_cache_inner<'a, 'b, 'c>( p } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Constructs and declares a publication cache. /// /// @param session: A Zenoh session. @@ -127,7 +127,7 @@ pub extern "C" fn ze_declare_publication_cache( } } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Declares a background publication cache. It will function in background until the corresponding session is closed or dropped. /// /// @param session: A Zenoh session. @@ -151,7 +151,7 @@ pub extern "C" fn ze_declare_background_publication_cache( } } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Constructs a publication cache in a gravestone state. #[no_mangle] #[allow(clippy::missing_safety_doc)] @@ -161,7 +161,7 @@ pub extern "C" fn ze_internal_publication_cache_null( this_.as_rust_type_mut_uninit().write(None); } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Returns ``true`` if publication cache is valid, ``false`` otherwise. #[no_mangle] #[allow(clippy::missing_safety_doc)] @@ -171,7 +171,7 @@ pub extern "C" fn ze_internal_publication_cache_check( this_.as_rust_type_ref().is_some() } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Drops publication cache and resets it to its gravestone state. /// This is equivalent to calling `ze_undeclare_publication_cache()` and discarding its return value. #[no_mangle] @@ -180,7 +180,7 @@ pub extern "C" fn ze_publication_cache_drop(this: &mut ze_moved_publication_cach std::mem::drop(this.take_rust_type()) } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Returns the key expression of the publication cache. #[no_mangle] pub extern "C" fn ze_publication_cache_keyexpr( @@ -189,7 +189,7 @@ pub extern "C" fn ze_publication_cache_keyexpr( this_.as_rust_type_ref().key_expr().as_loaned_c_type_ref() } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Borrows publication cache. #[no_mangle] #[allow(clippy::missing_safety_doc)] @@ -203,7 +203,7 @@ pub unsafe extern "C" fn ze_publication_cache_loan( .as_loaned_c_type_ref() } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_publisher. /// @brief Undeclares publication cache. /// @return 0 in case of success, negative error code otherwise. #[no_mangle] diff --git a/src/publisher.rs b/src/publisher.rs index ce604593c..963d5222e 100644 --- a/src/publisher.rs +++ b/src/publisher.rs @@ -17,7 +17,8 @@ use std::mem::MaybeUninit; #[cfg(feature = "unstable")] use zenoh::{handlers::Callback, matching::MatchingStatus}; use zenoh::{ - pubsub::Publisher, + internal::traits::{EncodingBuilderTrait, SampleBuilderTrait, TimestampBuilderTrait}, + pubsub::{Publisher, PublisherBuilder}, qos::{CongestionControl, Priority}, session::SessionClosedError, Wait, @@ -39,7 +40,6 @@ use crate::{ }; #[cfg(feature = "unstable")] use crate::{z_moved_source_info_t, zc_matching_status_t, zc_owned_matching_listener_t}; - /// Options passed to the `z_declare_publisher()` function. #[repr(C)] pub struct z_publisher_options_t { @@ -49,7 +49,7 @@ pub struct z_publisher_options_t { pub congestion_control: z_congestion_control_t, /// The priority of messages from this publisher. pub priority: z_priority_t, - /// If true, Zenoh will not wait to batch this message with others to reduce the bandwith. + /// If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, #[cfg(feature = "unstable")] /// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. @@ -63,19 +63,25 @@ pub struct z_publisher_options_t { pub allowed_destination: zc_locality_t, } +impl Default for z_publisher_options_t { + fn default() -> Self { + Self { + encoding: None, + congestion_control: CongestionControl::default().into(), + priority: Priority::default().into(), + is_express: false, + #[cfg(feature = "unstable")] + reliability: z_reliability_default(), + #[cfg(feature = "unstable")] + allowed_destination: zc_locality_default(), + } + } +} + /// Constructs the default value for `z_publisher_options_t`. #[no_mangle] pub extern "C" fn z_publisher_options_default(this_: &mut MaybeUninit) { - this_.write(z_publisher_options_t { - encoding: None, - congestion_control: CongestionControl::default().into(), - priority: Priority::default().into(), - is_express: false, - #[cfg(feature = "unstable")] - reliability: z_reliability_default(), - #[cfg(feature = "unstable")] - allowed_destination: zc_locality_default(), - }); + this_.write(z_publisher_options_t::default()); } pub use crate::opaque_types::{z_loaned_publisher_t, z_moved_publisher_t, z_owned_publisher_t}; @@ -84,26 +90,11 @@ decl_c_type!( loaned(z_loaned_publisher_t), ); -/// Constructs and declares a publisher for the given key expression. -/// -/// Data can be put and deleted with this publisher with the help of the -/// `z_publisher_put()` and `z_publisher_delete()` functions. -/// -/// @param session: The Zenoh session. -/// @param publisher: An uninitialized location in memory where publisher will be constructed. -/// @param key_expr: The key expression to publish. -/// @param options: Additional options for the publisher. -/// -/// @return 0 in case of success, negative error code otherwise. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_declare_publisher( - session: &z_loaned_session_t, - publisher: &mut MaybeUninit, - key_expr: &z_loaned_keyexpr_t, +pub(crate) fn _declare_publisher_inner( + session: &'static z_loaned_session_t, + key_expr: &'static z_loaned_keyexpr_t, options: Option<&mut z_publisher_options_t>, -) -> result::z_result_t { - let this = publisher.as_rust_type_mut_uninit(); +) -> PublisherBuilder<'static, 'static> { let session = session.as_rust_type_ref(); let key_expr = key_expr.as_rust_type_ref().clone().into_owned(); let mut p = session.declare_publisher(key_expr); @@ -122,6 +113,29 @@ pub extern "C" fn z_declare_publisher( p = p.encoding(encoding.take_rust_type()); } } + p +} + +/// Constructs and declares a publisher for the given key expression. +/// +/// Data can be put and deleted with this publisher with the help of the +/// `z_publisher_put()` and `z_publisher_delete()` functions. +/// +/// @param session: The Zenoh session. +/// @param publisher: An uninitialized location in memory where publisher will be constructed. +/// @param key_expr: The key expression to publish. +/// @param options: Additional options for the publisher. +/// +/// @return 0 in case of success, negative error code otherwise. +#[no_mangle] +pub extern "C" fn z_declare_publisher( + session: &'static z_loaned_session_t, + publisher: &'static mut MaybeUninit, + key_expr: &'static z_loaned_keyexpr_t, + options: Option<&'static mut z_publisher_options_t>, +) -> result::z_result_t { + let this = publisher.as_rust_type_mut_uninit(); + let p = _declare_publisher_inner(session, key_expr, options); match p.wait() { Err(e) => { tracing::error!("{}", e); @@ -137,13 +151,11 @@ pub extern "C" fn z_declare_publisher( /// Constructs a publisher in a gravestone state. #[no_mangle] -#[allow(clippy::missing_safety_doc)] pub extern "C" fn z_internal_publisher_null(this_: &mut MaybeUninit) { this_.as_rust_type_mut_uninit().write(None); } /// Returns ``true`` if publisher is valid, ``false`` otherwise. -#[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_internal_publisher_check(this_: &z_owned_publisher_t) -> bool { this_.as_rust_type_ref().is_some() @@ -174,6 +186,7 @@ pub unsafe extern "C" fn z_publisher_loan_mut( /// Options passed to the `z_publisher_put()` function. #[repr(C)] +#[derive(Default)] pub struct z_publisher_put_options_t { /// The encoding of the data to publish. pub encoding: Option<&'static mut z_moved_encoding_t>, @@ -203,6 +216,29 @@ pub extern "C" fn z_publisher_put_options_default( }); } +pub(crate) fn _apply_pubisher_put_options< + T: SampleBuilderTrait + TimestampBuilderTrait + EncodingBuilderTrait, +>( + builder: T, + options: &mut z_publisher_put_options_t, +) -> T { + let mut builder = builder; + if let Some(encoding) = options.encoding.take() { + builder = builder.encoding(encoding.take_rust_type()); + }; + #[cfg(feature = "unstable")] + if let Some(source_info) = options.source_info.take() { + builder = builder.source_info(source_info.take_rust_type()); + }; + if let Some(attachment) = options.attachment.take() { + builder = builder.attachment(attachment.take_rust_type()); + } + if let Some(timestamp) = options.timestamp { + builder = builder.timestamp(Some(*timestamp.as_rust_type_ref())); + } + builder +} + /// Sends a `PUT` message onto the publisher's key expression, transfering the payload ownership. /// /// @@ -224,19 +260,7 @@ pub unsafe extern "C" fn z_publisher_put( let payload = payload.take_rust_type(); let mut put = publisher.put(payload); if let Some(options) = options { - if let Some(encoding) = options.encoding.take() { - put = put.encoding(encoding.take_rust_type()); - }; - #[cfg(feature = "unstable")] - if let Some(source_info) = options.source_info.take() { - put = put.source_info(source_info.take_rust_type()); - }; - if let Some(attachment) = options.attachment.take() { - put = put.attachment(attachment.take_rust_type()); - } - if let Some(timestamp) = options.timestamp { - put = put.timestamp(Some(*timestamp.as_rust_type_ref())); - } + put = _apply_pubisher_put_options(put, options); } match put.wait() { @@ -252,6 +276,7 @@ pub unsafe extern "C" fn z_publisher_put( /// Represents the set of options that can be applied to the delete operation by a previously declared publisher, /// whenever issued via `z_publisher_delete()`. #[repr(C)] +#[derive(Default)] pub struct z_publisher_delete_options_t { /// The timestamp of this message. pub timestamp: Option<&'static z_timestamp_t>, @@ -263,8 +288,20 @@ pub struct z_publisher_delete_options_t { pub extern "C" fn z_publisher_delete_options_default( this: &mut MaybeUninit, ) { - this.write(z_publisher_delete_options_t { timestamp: None }); + this.write(z_publisher_delete_options_t::default()); } + +pub(crate) fn _apply_pubisher_delete_options( + builder: T, + options: &mut z_publisher_delete_options_t, +) -> T { + let mut builder = builder; + if let Some(timestamp) = options.timestamp { + builder = builder.timestamp(Some(*timestamp.as_rust_type_ref())); + } + builder +} + /// Sends a `DELETE` message onto the publisher's key expression. /// /// @return 0 in case of success, negative error code in case of failure. @@ -272,14 +309,12 @@ pub extern "C" fn z_publisher_delete_options_default( #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_publisher_delete( publisher: &z_loaned_publisher_t, - options: Option<&z_publisher_delete_options_t>, + options: Option<&mut z_publisher_delete_options_t>, ) -> result::z_result_t { let publisher = publisher.as_rust_type_ref(); let mut del = publisher.delete(); if let Some(options) = options { - if let Some(timestamp) = options.timestamp { - del = del.timestamp(Some(*timestamp.as_rust_type_ref())); - } + del = _apply_pubisher_delete_options(del, options); } if let Err(e) = del.wait() { tracing::error!("{}", e); diff --git a/src/put.rs b/src/put.rs index da21a095b..c27eb0f28 100644 --- a/src/put.rs +++ b/src/put.rs @@ -38,7 +38,7 @@ pub struct z_put_options_t { pub congestion_control: z_congestion_control_t, /// The priority of this message. pub priority: z_priority_t, - /// If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + /// If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, /// The timestamp of this message. pub timestamp: Option<&'static mut z_timestamp_t>, @@ -143,7 +143,7 @@ pub struct z_delete_options_t { pub congestion_control: z_congestion_control_t, /// The priority of the delete message. pub priority: z_priority_t, - /// If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + /// If set to ``true``, this message will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, /// The timestamp of this message. pub timestamp: Option<&'static mut z_timestamp_t>, diff --git a/src/querier.rs b/src/querier.rs index 785721566..984b26da0 100644 --- a/src/querier.rs +++ b/src/querier.rs @@ -50,7 +50,7 @@ pub struct z_querier_options_t { pub consolidation: z_query_consolidation_t, /// The congestion control to apply when routing the querier queries. pub congestion_control: z_congestion_control_t, - /// If true, Zenoh will not wait to batch the querier queries with others to reduce the bandwith. + /// If set to ``true``, the querier queries will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, #[cfg(feature = "unstable")] /// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. diff --git a/src/queryable.rs b/src/queryable.rs index 5a537e1bd..4799d3583 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -121,7 +121,7 @@ pub struct z_query_reply_options_t { pub congestion_control: z_congestion_control_t, /// The priority of the reply. pub priority: z_priority_t, - /// If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + /// If set to ``true``, this reply will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, /// The timestamp of the reply. pub timestamp: Option<&'static mut z_timestamp_t>, @@ -177,7 +177,7 @@ pub struct z_query_reply_del_options_t { pub congestion_control: z_congestion_control_t, /// The priority of the reply. pub priority: z_priority_t, - /// If true, Zenoh will not wait to batch this operation with others to reduce the bandwith. + /// If set to ``true``, this reply will not be batched. This usually has a positive impact on latency but negative impact on throughput. pub is_express: bool, /// The timestamp of the reply. pub timestamp: Option<&'static mut z_timestamp_t>, diff --git a/src/querying_subscriber.rs b/src/querying_subscriber.rs index aa13be223..7a34fa355 100644 --- a/src/querying_subscriber.rs +++ b/src/querying_subscriber.rs @@ -48,7 +48,7 @@ pub extern "C" fn ze_internal_querying_subscriber_null( this.as_rust_type_mut_uninit().write(None); } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief A set of options that can be applied to a querying subscriber, /// upon its declaration via `ze_declare_querying_subscriber()`. /// @@ -71,7 +71,7 @@ pub struct ze_querying_subscriber_options_t { query_timeout_ms: u64, } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Constructs the default value for `ze_querying_subscriber_options_t`. #[no_mangle] pub extern "C" fn ze_querying_subscriber_options_default( @@ -130,7 +130,7 @@ unsafe fn _declare_querying_subscriber_inner<'a, 'b>( }); sub } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Constructs and declares a querying subscriber for a given key expression. /// /// @param session: A Zenoh session. @@ -165,7 +165,7 @@ pub unsafe extern "C" fn ze_declare_querying_subscriber( } } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Declares a background querying subscriber for a given key expression. Subscriber callback will be called to process the messages, /// until the corresponding session is closed or dropped. /// @@ -193,7 +193,7 @@ pub unsafe extern "C" fn ze_declare_background_querying_subscriber( } } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Make querying subscriber perform an additional query on a specified selector. /// The queried samples will be merged with the received publications and made available in the subscriber callback. /// @return 0 in case of success, negative error code otherwise. @@ -258,7 +258,7 @@ pub unsafe extern "C" fn ze_querying_subscriber_get( result::Z_OK } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Undeclares querying subscriber callback and resets it to its gravestone state. /// This is equivalent to calling `ze_undeclare_querying_subscriber()` and discarding its return value. #[no_mangle] @@ -266,7 +266,7 @@ pub extern "C" fn ze_querying_subscriber_drop(this_: &mut ze_moved_querying_subs std::mem::drop(this_.take_rust_type()) } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Returns ``true`` if querying subscriber is valid, ``false`` otherwise. #[no_mangle] pub extern "C" fn ze_internal_querying_subscriber_check( @@ -275,7 +275,7 @@ pub extern "C" fn ze_internal_querying_subscriber_check( this_.as_rust_type_ref().is_some() } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Borrows querying subscriber. #[no_mangle] #[allow(clippy::missing_safety_doc)] @@ -288,7 +288,7 @@ pub unsafe extern "C" fn ze_querying_subscriber_loan( .as_loaned_c_type_ref() } -/// @warning This API has been marked as unstable: it works as advertised, but it may be changed in a future release. +/// @warning This API is deprecated. Please use ze_advanced_subscriber. /// @brief Undeclares the given querying subscriber. /// /// @return 0 in case of success, negative error code otherwise. diff --git a/src/subscriber.rs b/src/subscriber.rs index 60aa5c57b..542d78069 100644 --- a/src/subscriber.rs +++ b/src/subscriber.rs @@ -28,6 +28,9 @@ use crate::{ transmute::{LoanedCTypeRef, RustTypeRef, RustTypeRefUninit, TakeRustType}, z_closure_sample_call, z_closure_sample_loan, z_loaned_session_t, z_moved_closure_sample_t, }; +#[cfg(feature = "unstable")] +use crate::{zc_locality_default, zc_locality_t}; + decl_c_type!( owned(z_owned_subscriber_t, option Subscriber<()>), loaned(z_loaned_subscriber_t), @@ -54,26 +57,43 @@ pub unsafe extern "C" fn z_subscriber_loan(this_: &z_owned_subscriber_t) -> &z_l #[allow(non_camel_case_types)] #[repr(C)] pub struct z_subscriber_options_t { + #[cfg(not(feature = "unstable"))] /// Dummy field to avoid having fieldless struct pub _0: u8, + #[cfg(feature = "unstable")] + /// Restricts the matching publications that will be received by this Subscribers to the ones + /// that have the compatible allowed_destination. + pub allowed_origin: zc_locality_t, +} + +impl Default for z_subscriber_options_t { + fn default() -> Self { + Self { + #[cfg(not(feature = "unstable"))] + _0: Default::default(), + #[cfg(feature = "unstable")] + allowed_origin: zc_locality_default(), + } + } } /// Constructs the default value for `z_subscriber_options_t`. #[no_mangle] pub extern "C" fn z_subscriber_options_default(this_: &mut MaybeUninit) { - this_.write(z_subscriber_options_t { _0: 0 }); + this_.write(z_subscriber_options_t::default()); } -fn _declare_subscriber_inner<'a, 'b>( +#[allow(unused_variables, unused_mut)] +pub(crate) fn _declare_subscriber_inner<'a, 'b>( session: &'a z_loaned_session_t, key_expr: &'b z_loaned_keyexpr_t, callback: &mut z_moved_closure_sample_t, - _options: Option<&mut z_subscriber_options_t>, + options: Option<&mut z_subscriber_options_t>, ) -> SubscriberBuilder<'a, 'b, Callback> { let session = session.as_rust_type_ref(); let key_expr = key_expr.as_rust_type_ref(); let callback = callback.take_rust_type(); - let subscriber = session + let mut subscriber = session .declare_subscriber(key_expr) .callback(move |sample| { let mut owned_sample = Some(sample); @@ -84,6 +104,10 @@ fn _declare_subscriber_inner<'a, 'b>( .as_loaned_c_type_mut() }) }); + #[cfg(feature = "unstable")] + if let Some(options) = options { + subscriber = subscriber.allowed_origin(options.allowed_origin.into()); + } subscriber } @@ -93,7 +117,7 @@ fn _declare_subscriber_inner<'a, 'b>( /// @param subscriber: An uninitialized location in memory, where subscriber will be constructed. /// @param key_expr: The key expression to subscribe. /// @param callback: The callback function that will be called each time a data matching the subscribed expression is received. -/// @param _options: The options to be passed to the subscriber declaration. +/// @param options: The options to be passed to the subscriber declaration. /// /// @return 0 in case of success, negative error code otherwise (in this case subscriber will be in its gravestone state). #[no_mangle] @@ -102,10 +126,10 @@ pub extern "C" fn z_declare_subscriber( subscriber: &mut MaybeUninit, key_expr: &z_loaned_keyexpr_t, callback: &mut z_moved_closure_sample_t, - _options: Option<&mut z_subscriber_options_t>, + options: Option<&mut z_subscriber_options_t>, ) -> result::z_result_t { let this = subscriber.as_rust_type_mut_uninit(); - let s = _declare_subscriber_inner(session, key_expr, callback, _options); + let s = _declare_subscriber_inner(session, key_expr, callback, options); match s.wait() { Ok(sub) => { this.write(Some(sub)); @@ -125,7 +149,7 @@ pub extern "C" fn z_declare_subscriber( /// @param session: The zenoh session. /// @param key_expr: The key expression to subscribe. /// @param callback: The callback function that will be called each time a data matching the subscribed expression is received. -/// @param _options: The options to be passed to the subscriber declaration. +/// @param options: The options to be passed to the subscriber declaration. /// /// @return 0 in case of success, negative error code otherwise. #[no_mangle] @@ -133,9 +157,9 @@ pub extern "C" fn z_declare_background_subscriber( session: &z_loaned_session_t, key_expr: &z_loaned_keyexpr_t, callback: &mut z_moved_closure_sample_t, - _options: Option<&mut z_subscriber_options_t>, + options: Option<&mut z_subscriber_options_t>, ) -> result::z_result_t { - let subscriber = _declare_subscriber_inner(session, key_expr, callback, _options); + let subscriber = _declare_subscriber_inner(session, key_expr, callback, options); match subscriber.background().wait() { Ok(_) => result::Z_OK, Err(e) => { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 964c56e6e..d1043527a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,10 +14,10 @@ foreach(file ${files}) continue() endif() endif() - - # Exclude zenoh-ext tests if unstable api feature is disabled + + # Exclude zenoh-ext tests if unstable api feature is disabled if(NOT(ZENOHC_BUILD_WITH_UNSTABLE_API)) - if(${target} MATCHES "^.*_query_sub_test.*$") + if((${target} MATCHES "^.*_advanced_pub_sub.*$") OR (${target} MATCHES "^.*_pub_cache_query_sub.*$")) continue() endif() endif() diff --git a/tests/z_int_advanced_pub_sub_test.c b/tests/z_int_advanced_pub_sub_test.c new file mode 100644 index 000000000..bbafea630 --- /dev/null +++ b/tests/z_int_advanced_pub_sub_test.c @@ -0,0 +1,188 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#include "z_int_helpers.h" + +#ifdef VALID_PLATFORM + +#include + +#include "zenoh.h" + +const char *const SEM_NAME_PUB = "/z_int_test_sync_sem_pub"; +sem_t *sem_pub; +const char *const SEM_NAME_SUB = "/z_int_test_sync_sem_sub"; +sem_t *sem_sub; + +const char *const keyexpr = "test/key"; +const char *const values[] = {"test_value_1", "test_value_2", "test_value_3", + "test_value_4", "test_value_5", "test_value_6"}; +const size_t values_count = sizeof(values) / sizeof(values[0]); + +int run_publisher() { + z_owned_config_t config; + z_config_default(&config); + if (zc_config_insert_json5(z_loan_mut(config), Z_CONFIG_ADD_TIMESTAMP_KEY, "true") < 0) { + perror("Unable to configure timestamps!"); + return -1; + } + + z_owned_session_t s; + if (z_open(&s, z_move(config), NULL), 0) { + perror("Unable to open session!"); + return -1; + } + + printf("Declaring AdvancedPublisher on '%s'...\n", keyexpr); + ze_owned_advanced_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + + ze_advanced_publisher_options_t pub_opts; + ze_advanced_publisher_options_default(&pub_opts); + ze_advanced_publisher_cache_options_t cache_options; + ze_advanced_publisher_cache_options_default(&cache_options); + cache_options.max_samples = values_count; + pub_opts.cache = &cache_options; + pub_opts.publisher_detection = true; + pub_opts.sample_miss_detection = true; + + if (ze_declare_advanced_publisher(z_loan(s), &pub, z_loan(ke), &pub_opts) < 0) { + printf("Unable to declare AdvancedPublisher for key expression!\n"); + exit(-1); + } + + // values for cache + for (int i = 0; i < values_count / 2; ++i) { + z_owned_bytes_t payload; + z_bytes_from_static_str(&payload, values[i]); + ze_advanced_publisher_put(z_loan(pub), z_move(payload), NULL); + } + + SEM_POST(sem_pub); + printf("wait: sem_sub\n"); + SEM_WAIT(sem_sub); + z_sleep_s(1); + + // values for subscribe + for (int i = values_count / 2; i < values_count; ++i) { + z_owned_bytes_t payload; + z_bytes_from_static_str(&payload, values[i]); + ze_advanced_publisher_put(z_loan(pub), z_move(payload), NULL); + } + + printf("wait: sem_sub\n"); + SEM_WAIT(sem_sub); + + z_drop(z_move(pub)); + z_drop(z_move(s)); + + return 0; +} + +void data_handler(z_loaned_sample_t *sample, void *arg) { + static int val_num = 0; + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + if (strncmp(keyexpr, z_string_data(z_loan(keystr)), z_string_len(z_loan(keystr)))) { + perror("Unexpected key received"); + exit(-1); + } + z_owned_string_t payload_str; + z_bytes_to_string(z_sample_payload(sample), &payload_str); + + const z_loaned_source_info_t *info = z_sample_source_info(sample); + z_owned_string_t id_string; + z_entity_global_id_t global_id = z_source_info_id(info); + z_id_t z_id = z_entity_global_id_zid(&global_id); + z_id_to_string(&z_id, &id_string); + + printf("Received: '%.*s'; id=%.*s; sn=%u\n", (int)z_string_len(z_loan(payload_str)), + z_string_data(z_loan(payload_str)), (int)z_string_len(z_loan(id_string)), z_string_data(z_loan(id_string)), + z_source_info_sn(info)); + ASSERT_STR_STRING_EQUAL(values[val_num], z_loan(payload_str)); + z_drop(z_move(payload_str)); + z_drop(z_move(id_string)); + + printf("data_handler: %i\n", val_num); + if (++val_num == values_count) { + SEM_POST(sem_sub); + exit(0); + }; +} + +int run_subscriber() { + printf("wait: sem_pub\n"); + SEM_WAIT(sem_pub); + + z_owned_config_t config; + z_config_default(&config); + + z_owned_session_t s; + if (z_open(&s, z_move(config), NULL) < 0) { + perror("Unable to open session!"); + return -1; + } + + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + + ze_advanced_subscriber_options_t sub_opts; + ze_advanced_subscriber_options_default(&sub_opts); + + ze_advanced_subscriber_history_options_t sub_history_options; + ze_advanced_subscriber_history_options_default(&sub_history_options); + sub_history_options.detect_late_publishers = true; + + ze_advanced_subscriber_recovery_options_t sub_recovery_options; + ze_advanced_subscriber_recovery_options_default(&sub_recovery_options); + sub_recovery_options.periodic_queries_period_ms = 1000; + sub_opts.history = &sub_history_options; + sub_opts.recovery = &sub_recovery_options; + sub_opts.subscriber_detection = true; + + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler, NULL, NULL); + printf("Declaring AdvancedSubscriber on '%s'...\n", keyexpr); + ze_owned_advanced_subscriber_t sub; + if (ze_declare_advanced_subscriber(z_loan(s), &sub, z_loan(ke), z_move(callback), &sub_opts) < 0) { + printf("Unable to declare advanced subscriber.\n"); + exit(-1); + } + + SEM_POST(sem_sub); + z_sleep_s(10); + + z_drop(z_move(sub)); + z_drop(z_move(s)); + + return -1; +} + +int main() { + SEM_INIT(sem_pub, SEM_NAME_PUB); + SEM_INIT(sem_sub, SEM_NAME_SUB); + + func_ptr_t funcs[] = {run_publisher, run_subscriber}; + assert(run_timeouted_test(funcs, 2, 10) == 0); + + SEM_DROP(sem_pub, SEM_NAME_PUB); + SEM_DROP(sem_sub, SEM_NAME_SUB); + + return 0; +} + +#else +int main() { return 0; } +#endif // VALID_PLATFORM diff --git a/tests/z_int_helpers.h b/tests/z_int_helpers.h index 51b117c3a..d01bd40db 100644 --- a/tests/z_int_helpers.h +++ b/tests/z_int_helpers.h @@ -163,3 +163,12 @@ int run_timeouted_test(func_ptr_t functions[], int num_functions, int timeout_se exit(-1); \ } \ } while (0) + +#define ASSERT_STR_STRING_EQUAL(str, string) \ + do { \ + if (strlen(str) != z_string_len(string) || \ + strncmp(str, (const char *)z_string_data(string), (int)z_string_len(string))) { \ + fprintf(stderr, "Check failed: '%s' != '%.*s'\n", str, (int)z_string_len(string), z_string_data(string)); \ + exit(-1); \ + } \ + } while (0)