From dd1b4b38cf286d20f059c1f39a7f343a8198a451 Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Wed, 25 Jul 2018 10:32:31 +0000 Subject: [PATCH] devicestate: Don't create topic when change isn't cached. When publishing a device state the change can be marked as being cachable or not. If it is not cached the change is just published to all interested and not stored away for later query. This was not fully taken into account when publishing in stasis. The act of publishing would create a topic for the device even if it may be ephemeral. This change makes it so messages which are not cached won't create a topic for the device. If a topic does already exist it will be published to but otherwise the change will only be published to the device state all topic. ASTERISK-27591 Change-Id: I18da0e8cbb18e79602e731020c46ba4101e59f0a --- include/asterisk/stasis.h | 10 ++++++++++ main/devicestate.c | 24 ++++++++++++++++++++---- main/stasis.c | 13 +++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h index de44206b64..898fad4906 100644 --- a/include/asterisk/stasis.h +++ b/include/asterisk/stasis.h @@ -756,6 +756,16 @@ struct stasis_topic_pool *stasis_topic_pool_create(struct stasis_topic *pooled_t */ struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name); +/*! + * \brief Check if a topic exists in a pool + * \param pool Pool to check + * \param topic_name Name of the topic to check + * \retval 1 exists + * \retval 0 does not exist + * \since 13.23.0 + */ +int stasis_topic_pool_topic_exists(const struct stasis_topic_pool *pool, const char *topic_name); + /*! @} */ /*! \addtogroup StasisTopicsAndMessages diff --git a/main/devicestate.c b/main/devicestate.c index 4bc0bed399..b6650457a8 100644 --- a/main/devicestate.c +++ b/main/devicestate.c @@ -739,7 +739,7 @@ int ast_publish_device_state_full( { RAII_VAR(struct ast_device_state_message *, device_state, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); - struct stasis_topic *device_specific_topic; + struct stasis_topic *topic; ast_assert(!ast_strlen_zero(device)); @@ -758,12 +758,28 @@ int ast_publish_device_state_full( return -1; } - device_specific_topic = ast_device_state_topic(device); - if (!device_specific_topic) { + /* When a device state is to be cached it is likely that something + * external will either be monitoring it or will want to pull the + * information from the cache, so we always publish to the device + * specific topic. Cachable updates traditionally come from such things + * as a SIP or PJSIP device. + * When a device state is not to be cached we only publish to its + * specific topic if something has already created the topic. Publishing + * to its topic otherwise would create the topic, which may not be + * necessary as it could be an ephemeral device. Uncachable updates + * traditionally come from such things as Local channels. + */ + if (cachable || stasis_topic_pool_topic_exists(device_state_topic_pool, device)) { + topic = ast_device_state_topic(device); + } else { + topic = ast_device_state_topic_all(); + } + + if (!topic) { return -1; } - stasis_publish(device_specific_topic, message); + stasis_publish(topic, message); return 0; } diff --git a/main/stasis.c b/main/stasis.c index a668e82eba..20f865eb9a 100644 --- a/main/stasis.c +++ b/main/stasis.c @@ -1198,6 +1198,19 @@ struct stasis_topic *stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, return topic_pool_entry->topic; } +int stasis_topic_pool_topic_exists(const struct stasis_topic_pool *pool, const char *topic_name) +{ + struct topic_pool_entry *topic_pool_entry; + + topic_pool_entry = ao2_find(pool->pool_container, topic_name, OBJ_SEARCH_KEY); + if (!topic_pool_entry) { + return 0; + } + + ao2_ref(topic_pool_entry, -1); + return 1; +} + void stasis_log_bad_type_access(const char *name) { #ifdef AST_DEVMODE -- 2.47.2