<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10227">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">bridges: Remove reliance on stasis caching<br><br>* The bridging core no longer uses the stasis cache for bridge<br> snapshots. Bridge snapshots are now stored in an rbtree<br> container in stasis_bridges.c<br><br>* The following APIs are no longer available since the stasis cache<br> is no longer used:<br> ast_bridge_topic_cached()<br> ast_bridge_topic_all_cached()<br><br>* A topic pool is now used for individual bridge topics.<br><br>* The ast_bridge_cache() function now returns an ao2_container of<br> ast_bridge_snapshots rather than a container of stasis_messages<br> therefore you can't (and don't need to) call stasis_cache<br> functions on it.<br><br>* The ast_bridge_topic_all() function now returns a normal topic<br> not a cached one so you can't use stasis cache functions on it<br> either.<br><br>* The ast_bridge_snapshot_type() stasis message now has the<br> ast_bridge_snapshot_update structure as it's data. It contains<br> the last snapshot and the new one.<br><br>* ast_bridge_snapshot_get_latest() still returns the latest<br> snapshot.<br><br>* cdr, cel, manager and ari have been updated to use the new<br> arrangement.<br><br>Change-Id: I7049b80efa88676ce5c4666f818fa18ad1985369<br>---<br>M CHANGES<br>M UPGRADE.txt<br>M apps/confbridge/confbridge_manager.c<br>M include/asterisk/bridge.h<br>M include/asterisk/stasis_bridges.h<br>M main/Makefile<br>M main/bridge.c<br>M main/cdr.c<br>M main/cel.c<br>M main/manager_bridges.c<br>M main/stasis_bridges.c<br>M res/ari/resource_bridges.c<br>M res/stasis/app.c<br>13 files changed, 321 insertions(+), 212 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/27/10227/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/CHANGES b/CHANGES</span><br><span>index 26748f7..c2a99d0 100644</span><br><span>--- a/CHANGES</span><br><span>+++ b/CHANGES</span><br><span>@@ -9,6 +9,25 @@</span><br><span> ==============================================================================</span><br><span> </span><br><span> ------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+--- Functionality changes from Asterisk 16 to Asterisk 17 --------------------</span><br><span style="color: hsl(120, 100%, 40%);">+------------------------------------------------------------------------------</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Bridging</span><br><span style="color: hsl(120, 100%, 40%);">+------------------</span><br><span style="color: hsl(120, 100%, 40%);">+ * The bridging core no longer uses the stasis cache for bridge snapshots.</span><br><span style="color: hsl(120, 100%, 40%);">+ The following APIs are no longer available:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_topic_cached()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_topic_all_cached()</span><br><span style="color: hsl(120, 100%, 40%);">+ The ast_bridge_cache() function now returns an ao2_container of</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_snapshots rather than a container of stasis_messages</span><br><span style="color: hsl(120, 100%, 40%);">+ therefore you can't call stasis_cache functions on it.</span><br><span style="color: hsl(120, 100%, 40%);">+ The ast_bridge_topic_all() function now returns a normal topic,</span><br><span style="color: hsl(120, 100%, 40%);">+ not a cached one so you can't use stasis cache functions on it either.</span><br><span style="color: hsl(120, 100%, 40%);">+ The ast_bridge_snapshot_type() stasis message now has the</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_snapshot_update structure as it's data.</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_snapshot_get_latest() still returns the latest snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+------------------------------------------------------------------------------</span><br><span> --- Functionality changes from Asterisk 15 to Asterisk 16 --------------------</span><br><span> ------------------------------------------------------------------------------</span><br><span> </span><br><span>diff --git a/UPGRADE.txt b/UPGRADE.txt</span><br><span>index b7bbf3b..13de3eb 100644</span><br><span>--- a/UPGRADE.txt</span><br><span>+++ b/UPGRADE.txt</span><br><span>@@ -25,3 +25,19 @@</span><br><span> === UPGRADE-16.txt -- Upgrade info for 15 to 16</span><br><span> ===========================================================</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+New in 17.0.0:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Bridging</span><br><span style="color: hsl(120, 100%, 40%);">+------------------</span><br><span style="color: hsl(120, 100%, 40%);">+ * The bridging core no longer uses the stasis cache for bridge snapshots.</span><br><span style="color: hsl(120, 100%, 40%);">+ The following APIs are no longer available:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_topic_cached()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_topic_all_cached()</span><br><span style="color: hsl(120, 100%, 40%);">+ The ast_bridge_cache() function now returns an ao2_container of</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_snapshots rather than a container of stasis_messages</span><br><span style="color: hsl(120, 100%, 40%);">+ therefore you can't call stasis_cache functions on it.</span><br><span style="color: hsl(120, 100%, 40%);">+ The ast_bridge_topic_all() function now returns a normal topic,</span><br><span style="color: hsl(120, 100%, 40%);">+ not a cached one so you can't use stasis cache functions on it either.</span><br><span style="color: hsl(120, 100%, 40%);">+ The ast_bridge_snapshot_type() stasis message now has the</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_snapshot_update structure as it's data.</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_snapshot_get_latest() still returns the latest snapshot.</span><br><span>diff --git a/apps/confbridge/confbridge_manager.c b/apps/confbridge/confbridge_manager.c</span><br><span>index 51112ba..bd8c5a1 100644</span><br><span>--- a/apps/confbridge/confbridge_manager.c</span><br><span>+++ b/apps/confbridge/confbridge_manager.c</span><br><span>@@ -769,7 +769,7 @@</span><br><span> STASIS_MESSAGE_TYPE_INIT(confbridge_welcome_type);</span><br><span> </span><br><span> bridge_state_router = stasis_message_router_create(</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_topic_all_cached());</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_topic_all());</span><br><span> </span><br><span> if (!bridge_state_router) {</span><br><span> return -1;</span><br><span>diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h</span><br><span>index 3584085..c39b4f7 100644</span><br><span>--- a/include/asterisk/bridge.h</span><br><span>+++ b/include/asterisk/bridge.h</span><br><span>@@ -307,7 +307,7 @@</span><br><span> /*! Private information unique to the bridge technology */</span><br><span> void *tech_pvt;</span><br><span> /*! Per-bridge topics */</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_cp_single *topics;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_topic *topic;</span><br><span> /*! Call ID associated with the bridge */</span><br><span> ast_callid callid;</span><br><span> /*! Linked list of channels participating in the bridge */</span><br><span>diff --git a/include/asterisk/stasis_bridges.h b/include/asterisk/stasis_bridges.h</span><br><span>index a455a5b..d56c083 100644</span><br><span>--- a/include/asterisk/stasis_bridges.h</span><br><span>+++ b/include/asterisk/stasis_bridges.h</span><br><span>@@ -64,6 +64,21 @@</span><br><span> enum ast_bridge_video_mode_type video_mode;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_bridge_snapshot_update {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *old_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *new_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.24</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 15.6</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.1</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Delete a bridge snapshot from the cache</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uniqueid The bridge's uniqueid</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_bridge_cache_delete_snapshot(const char *uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span> * \since 12</span><br><span> * \brief Generate a snapshot of the bridge state. This is an ao2 object, so</span><br><span>@@ -101,22 +116,6 @@</span><br><span> </span><br><span> /*!</span><br><span> * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief A topic which publishes the events for a particular bridge.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \ref ast_bridge_snapshot messages are replaced with stasis_cache_update</span><br><span style="color: hsl(0, 100%, 40%);">- * messages.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * If the given \a bridge is \c NULL, ast_bridge_topic_all_cached() is returned.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param bridge Bridge for which to get a topic or \c NULL.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval Topic for bridge's events.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval ast_bridge_topic_all() if \a bridge is \c NULL.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_bridge_topic_cached(struct ast_bridge *bridge);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span> * \brief A topic which publishes the events for all bridges.</span><br><span> * \retval Topic for all bridge events.</span><br><span> */</span><br><span>@@ -124,19 +123,10 @@</span><br><span> </span><br><span> /*!</span><br><span> * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief A caching topic which caches \ref ast_bridge_snapshot messages from</span><br><span style="color: hsl(0, 100%, 40%);">- * ast_bridge_events_all(void).</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval Caching topic for all bridge events.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_bridge_topic_all_cached(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span> * \brief Backend cache for ast_bridge_topic_all_cached().</span><br><span> * \retval Cache of \ref ast_bridge_snapshot.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_cache *ast_bridge_cache(void);</span><br><span style="color: hsl(120, 100%, 40%);">+struct ao2_container *ast_bridge_cache(void);</span><br><span> </span><br><span> /*!</span><br><span> * \since 12</span><br><span>@@ -511,6 +501,17 @@</span><br><span> </span><br><span> /*!</span><br><span> * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.24</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 15.6</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.1</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Clean up bridge cache and publish destroy</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param bridge The bridge to clean up</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void bridge_topics_destroy(struct ast_bridge *bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span> * \brief Initialize the stasis bridging topic and message types</span><br><span> * \retval 0 on success</span><br><span> * \retval -1 on failure</span><br><span>diff --git a/main/Makefile b/main/Makefile</span><br><span>index 1cb2c25..a22a1ad 100644</span><br><span>--- a/main/Makefile</span><br><span>+++ b/main/Makefile</span><br><span>@@ -167,6 +167,7 @@</span><br><span> sched.o: _ASTCFLAGS+=$(call get_menuselect_cflags,DEBUG_SCHEDULER DUMP_SCHEDULER)</span><br><span> tcptls.o: _ASTCFLAGS+=$(OPENSSL_INCLUDE) -Wno-deprecated-declarations</span><br><span> uuid.o: _ASTCFLAGS+=$(UUID_INCLUDE)</span><br><span style="color: hsl(120, 100%, 40%);">+stasis.o: _ASTCFLAGS+=$(call get_menuselect_cflags,AO2_DEBUG)</span><br><span> </span><br><span> </span><br><span> OBJS:=$(sort $(OBJS))</span><br><span>diff --git a/main/bridge.c b/main/bridge.c</span><br><span>index 2b347fd..9af26ee 100644</span><br><span>--- a/main/bridge.c</span><br><span>+++ b/main/bridge.c</span><br><span>@@ -650,25 +650,6 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_message *create_bridge_snapshot_message(struct ast_bridge *bridge)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_bridge_snapshot_type()) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_lock(bridge);</span><br><span style="color: hsl(0, 100%, 40%);">- snapshot = ast_bridge_snapshot_create(bridge);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_unlock(bridge);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return stasis_message_create(ast_bridge_snapshot_type(), snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static void destroy_bridge(void *obj)</span><br><span> {</span><br><span> struct ast_bridge *bridge = obj;</span><br><span>@@ -677,17 +658,7 @@</span><br><span> bridge->uniqueid, bridge->v_table->name);</span><br><span> </span><br><span> if (bridge->construction_completed) {</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, clear_msg, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- clear_msg = create_bridge_snapshot_message(bridge);</span><br><span style="color: hsl(0, 100%, 40%);">- if (clear_msg) {</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- msg = stasis_cache_clear_create(clear_msg);</span><br><span style="color: hsl(0, 100%, 40%);">- if (msg) {</span><br><span style="color: hsl(0, 100%, 40%);">- stasis_publish(ast_bridge_topic(bridge), msg);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_topics_destroy(bridge);</span><br><span> }</span><br><span> </span><br><span> /* Do any pending actions in the context of destruction. */</span><br><span>@@ -726,8 +697,6 @@</span><br><span> </span><br><span> cleanup_video_mode(bridge);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- stasis_cp_single_unsubscribe(bridge->topics);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> ast_string_field_free_memory(bridge);</span><br><span> }</span><br><span> </span><br><span>@@ -5069,20 +5038,18 @@</span><br><span> int wordlen = strlen(word);</span><br><span> struct ao2_container *cached_bridges;</span><br><span> struct ao2_iterator iter;</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_message *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *snapshot;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- cached_bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type());</span><br><span style="color: hsl(120, 100%, 40%);">+ cached_bridges = ast_bridge_cache();</span><br><span> if (!cached_bridges) {</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span> iter = ao2_iterator_init(cached_bridges, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {</span><br><span> if (!strncasecmp(word, snapshot->uniqueid, wordlen)) {</span><br><span> if (ast_cli_completion_add(ast_strdup(snapshot->uniqueid))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(msg, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(snapshot, -1);</span><br><span> break;</span><br><span> }</span><br><span> }</span><br><span>@@ -5098,9 +5065,9 @@</span><br><span> #define FORMAT_HDR "%-36s %5s %-15s %s\n"</span><br><span> #define FORMAT_ROW "%-36s %5u %-15s %s\n"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ao2_container *, cached_bridges, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ao2_container *cached_bridges;</span><br><span> struct ao2_iterator iter;</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_message *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *snapshot;</span><br><span> </span><br><span> switch (cmd) {</span><br><span> case CLI_INIT:</span><br><span>@@ -5113,7 +5080,7 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- cached_bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type());</span><br><span style="color: hsl(120, 100%, 40%);">+ cached_bridges = ast_bridge_cache();</span><br><span> if (!cached_bridges) {</span><br><span> ast_cli(a->fd, "Failed to retrieve cached bridges\n");</span><br><span> return CLI_SUCCESS;</span><br><span>@@ -5122,9 +5089,7 @@</span><br><span> ast_cli(a->fd, FORMAT_HDR, "Bridge-ID", "Chans", "Type", "Technology");</span><br><span> </span><br><span> iter = ao2_iterator_init(cached_bridges, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {</span><br><span> ast_cli(a->fd, FORMAT_ROW,</span><br><span> snapshot->uniqueid,</span><br><span> snapshot->num_channels,</span><br><span>@@ -5132,6 +5097,8 @@</span><br><span> S_OR(snapshot->technology, "<unknown>"));</span><br><span> }</span><br><span> ao2_iterator_destroy(&iter);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(cached_bridges, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return CLI_SUCCESS;</span><br><span> </span><br><span> #undef FORMAT_HDR</span><br><span>@@ -5159,7 +5126,6 @@</span><br><span> </span><br><span> static char *handle_bridge_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);</span><br><span> struct ast_bridge_snapshot *snapshot;</span><br><span> </span><br><span> switch (cmd) {</span><br><span>@@ -5180,18 +5146,17 @@</span><br><span> return CLI_SHOWUSAGE;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- msg = stasis_cache_get(ast_bridge_cache(), ast_bridge_snapshot_type(), a->argv[2]);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshot = ast_bridge_snapshot_get_latest(a->argv[2]);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!snapshot) {</span><br><span> ast_cli(a->fd, "Bridge '%s' not found\n", a->argv[2]);</span><br><span> return CLI_SUCCESS;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snapshot = stasis_message_data(msg);</span><br><span> ast_cli(a->fd, "Id: %s\n", snapshot->uniqueid);</span><br><span> ast_cli(a->fd, "Type: %s\n", S_OR(snapshot->subclass, "<unknown>"));</span><br><span> ast_cli(a->fd, "Technology: %s\n", S_OR(snapshot->technology, "<unknown>"));</span><br><span> ast_cli(a->fd, "Num-Channels: %u\n", snapshot->num_channels);</span><br><span> ao2_callback(snapshot->channels, OBJ_NODATA, bridge_show_specific_print_channel, a);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(snapshot, -1);</span><br><span> </span><br><span> return CLI_SUCCESS;</span><br><span> }</span><br><span>diff --git a/main/cdr.c b/main/cdr.c</span><br><span>index 1c47e24..0ffb9cd 100644</span><br><span>--- a/main/cdr.c</span><br><span>+++ b/main/cdr.c</span><br><span>@@ -4306,7 +4306,7 @@</span><br><span> if (!channel_subscription) {</span><br><span> return -1;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- bridge_subscription = stasis_forward_all(ast_bridge_topic_all_cached(), cdr_topic);</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_subscription = stasis_forward_all(ast_bridge_topic_all(), cdr_topic);</span><br><span> if (!bridge_subscription) {</span><br><span> return -1;</span><br><span> }</span><br><span>diff --git a/main/cel.c b/main/cel.c</span><br><span>index 0ec728e..738589f 100644</span><br><span>--- a/main/cel.c</span><br><span>+++ b/main/cel.c</span><br><span>@@ -1460,7 +1460,7 @@</span><br><span> }</span><br><span> </span><br><span> cel_bridge_forwarder = stasis_forward_all(</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_topic_all_cached(),</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_topic_all(),</span><br><span> cel_aggregation_topic);</span><br><span> if (!cel_bridge_forwarder) {</span><br><span> return -1;</span><br><span>diff --git a/main/manager_bridges.c b/main/manager_bridges.c</span><br><span>index b7059f4..40007d4 100644</span><br><span>--- a/main/manager_bridges.c</span><br><span>+++ b/main/manager_bridges.c</span><br><span>@@ -330,22 +330,15 @@</span><br><span> struct stasis_message *message)</span><br><span> {</span><br><span> RAII_VAR(struct ast_str *, bridge_event_string, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_cache_update *update;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *old_snapshot;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *new_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update;</span><br><span> size_t i;</span><br><span> </span><br><span> update = stasis_message_data(message);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(ast_bridge_snapshot_type() == update->type);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- old_snapshot = stasis_message_data(update->old_snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">- new_snapshot = stasis_message_data(update->new_snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> for (i = 0; i < ARRAY_LEN(bridge_monitors); ++i) {</span><br><span> RAII_VAR(struct ast_manager_event_blob *, event, NULL, ao2_cleanup);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- event = bridge_monitors[i](old_snapshot, new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ event = bridge_monitors[i](update->old_snapshot, update->new_snapshot);</span><br><span> if (!event) {</span><br><span> continue;</span><br><span> }</span><br><span>@@ -354,7 +347,7 @@</span><br><span> if (!bridge_event_string) {</span><br><span> bridge_event_string =</span><br><span> ast_manager_build_bridge_state_string(</span><br><span style="color: hsl(0, 100%, 40%);">- new_snapshot ? new_snapshot : old_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ update->new_snapshot ? update->new_snapshot : update->old_snapshot);</span><br><span> if (!bridge_event_string) {</span><br><span> return;</span><br><span> }</span><br><span>@@ -461,7 +454,7 @@</span><br><span> </span><br><span> static int send_bridge_list_item_cb(void *obj, void *arg, void *data, int flags)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *snapshot = stasis_message_data(obj);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *snapshot = obj;</span><br><span> struct mansession *s = arg;</span><br><span> struct bridge_list_data *list_data = data;</span><br><span> RAII_VAR(struct ast_str *, bridge_info, ast_manager_build_bridge_state_string(snapshot), ast_free);</span><br><span>@@ -498,7 +491,7 @@</span><br><span> ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- bridges = stasis_cache_dump(ast_bridge_cache(), ast_bridge_snapshot_type());</span><br><span style="color: hsl(120, 100%, 40%);">+ bridges = ast_bridge_cache();</span><br><span> if (!bridges) {</span><br><span> astman_send_error(s, m, "Internal error");</span><br><span> return -1;</span><br><span>@@ -564,7 +557,6 @@</span><br><span> const char *id = astman_get_header(m, "ActionID");</span><br><span> const char *bridge_uniqueid = astman_get_header(m, "BridgeUniqueid");</span><br><span> RAII_VAR(struct ast_str *, id_text, ast_str_create(128), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);</span><br><span> RAII_VAR(struct ast_str *, bridge_info, NULL, ast_free);</span><br><span> struct ast_bridge_snapshot *snapshot;</span><br><span> struct bridge_list_data list_data;</span><br><span>@@ -583,13 +575,7 @@</span><br><span> ast_str_set(&id_text, 0, "ActionID: %s\r\n", id);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- msg = stasis_cache_get(ast_bridge_cache(), ast_bridge_snapshot_type(), bridge_uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Specified BridgeUniqueid not found");</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snapshot = stasis_message_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshot = ast_bridge_snapshot_get_latest(bridge_uniqueid);</span><br><span> bridge_info = ast_manager_build_bridge_state_string(snapshot);</span><br><span> if (!bridge_info) {</span><br><span> astman_send_error(s, m, "Internal error");</span><br><span>@@ -706,7 +692,7 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- bridge_topic = ast_bridge_topic_all_cached();</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_topic = ast_bridge_topic_all();</span><br><span> if (!bridge_topic) {</span><br><span> return -1;</span><br><span> }</span><br><span>@@ -721,7 +707,7 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ret |= stasis_message_router_add_cache_update(bridge_state_router,</span><br><span style="color: hsl(120, 100%, 40%);">+ ret |= stasis_message_router_add(bridge_state_router,</span><br><span> ast_bridge_snapshot_type(), bridge_snapshot_update, NULL);</span><br><span> </span><br><span> ret |= stasis_message_router_add(bridge_state_router,</span><br><span>diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c</span><br><span>index 59b9685..d07fb1e 100644</span><br><span>--- a/main/stasis_bridges.c</span><br><span>+++ b/main/stasis_bridges.c</span><br><span>@@ -155,7 +155,8 @@</span><br><span> struct stasis_message *msg,</span><br><span> const struct stasis_message_sanitizer *sanitize);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_cp_all *bridge_cache_all;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_topic *bridge_topic_all;</span><br><span style="color: hsl(120, 100%, 40%);">+static struct stasis_topic_pool *bridge_topic_pool;</span><br><span> </span><br><span> /*!</span><br><span> * @{ \brief Define bridge message types.</span><br><span>@@ -175,33 +176,16 @@</span><br><span> .to_ami = attended_transfer_to_ami);</span><br><span> /*! @} */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_cache *ast_bridge_cache(void)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ao2_container *bridge_cache;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ao2_container *ast_bridge_cache(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return stasis_cp_all_cache(bridge_cache_all);</span><br><span style="color: hsl(120, 100%, 40%);">+ return ao2_bump(bridge_cache);</span><br><span> }</span><br><span> </span><br><span> struct stasis_topic *ast_bridge_topic_all(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return stasis_cp_all_topic(bridge_cache_all);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_bridge_topic_all_cached(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return stasis_cp_all_topic_cached(bridge_cache_all);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-int bridge_topics_init(struct ast_bridge *bridge)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(bridge->uniqueid)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Bridge id initialization required\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- bridge->topics = stasis_cp_single_create(bridge_cache_all,</span><br><span style="color: hsl(0, 100%, 40%);">- bridge->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!bridge->topics) {</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ return bridge_topic_all;</span><br><span> }</span><br><span> </span><br><span> struct stasis_topic *ast_bridge_topic(struct ast_bridge *bridge)</span><br><span>@@ -210,16 +194,7 @@</span><br><span> return ast_bridge_topic_all();</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return stasis_cp_single_topic(bridge->topics);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_topic *ast_bridge_topic_cached(struct ast_bridge *bridge)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (!bridge) {</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_bridge_topic_all_cached();</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return stasis_cp_single_topic_cached(bridge->topics);</span><br><span style="color: hsl(120, 100%, 40%);">+ return bridge->topic;</span><br><span> }</span><br><span> </span><br><span> /*! \brief Destructor for bridge snapshots */</span><br><span>@@ -292,44 +267,158 @@</span><br><span> return snapshot;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void ast_bridge_publish_state(struct ast_bridge *bridge)</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_bridge_cache_delete_snapshot(const char *uniqueid)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *snapshot;</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_message *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_find(bridge_cache, uniqueid, OBJ_SEARCH_KEY | OBJ_NODATA | OBJ_UNLINK);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_bridge_snapshot_type()) {</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(120, 100%, 40%);">+static void bridge_snapshot_update_dtor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Update: %p Old: %s New: %s\n", update,</span><br><span style="color: hsl(120, 100%, 40%);">+ update->old_snapshot ? update->old_snapshot->uniqueid : "<none>",</span><br><span style="color: hsl(120, 100%, 40%);">+ update->new_snapshot ? update->new_snapshot->uniqueid : "<none>");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(update->old_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(update->new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_bridge_snapshot_update *bridge_snapshot_update_create(</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *old, struct ast_bridge_snapshot *new)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ update = ao2_alloc_options(sizeof(*update), bridge_snapshot_update_dtor,</span><br><span style="color: hsl(120, 100%, 40%);">+ AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!update) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+ update->old_snapshot = old;</span><br><span style="color: hsl(120, 100%, 40%);">+ update->new_snapshot = new;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Update: %p Old: %s New: %s\n", update,</span><br><span style="color: hsl(120, 100%, 40%);">+ update->old_snapshot ? update->old_snapshot->uniqueid : "<none>",</span><br><span style="color: hsl(120, 100%, 40%);">+ update->new_snapshot ? update->new_snapshot->uniqueid : "<none>");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return update;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int bridge_topics_init(struct ast_bridge *bridge)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(bridge->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Bridge id initialization required\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge->topic = stasis_topic_pool_get_topic(bridge_topic_pool, bridge->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bridge->topic) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void bridge_topics_destroy(struct ast_bridge *bridge)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *old_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message *msg;</span><br><span> </span><br><span> ast_assert(bridge != NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- snapshot = ast_bridge_snapshot_create(bridge);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ old_snapshot = ast_bridge_snapshot_get_latest(bridge->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!old_snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ old_snapshot = ast_bridge_snapshot_create(bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!old_snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_bridge_cache_delete_snapshot(bridge->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ update = bridge_snapshot_update_create(old_snapshot, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!update) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(old_snapshot, -1);</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- msg = stasis_message_create(ast_bridge_snapshot_type(), snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = stasis_message_create(ast_bridge_snapshot_type(), update);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(update, -1);</span><br><span> if (!msg) {</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span> stasis_publish(ast_bridge_topic(bridge), msg);</span><br><span> ao2_ref(msg, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_topic_pool_delete_topic(bridge_topic_pool, stasis_topic_name(ast_bridge_topic(bridge)));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_bridge_publish_state(struct ast_bridge *bridge)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *new_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *old_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(bridge != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ new_snapshot = ast_bridge_snapshot_create(bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!new_snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ old_snapshot = ast_bridge_snapshot_get_latest(bridge->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We're transferring the snapshot references to the update */</span><br><span style="color: hsl(120, 100%, 40%);">+ update = bridge_snapshot_update_create(old_snapshot, new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!update) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(old_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(new_snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = stasis_message_create(ast_bridge_snapshot_type(), update);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(update, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The link of the new automatically replaces the old */</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_link(bridge_cache, new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_publish(ast_bridge_topic(bridge), msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(msg, -1);</span><br><span> }</span><br><span> </span><br><span> static void bridge_publish_state_from_blob(struct ast_bridge *bridge,</span><br><span> struct ast_bridge_blob *obj)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *old_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update;</span><br><span> struct stasis_message *msg;</span><br><span> </span><br><span> ast_assert(obj != NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- msg = stasis_message_create(ast_bridge_snapshot_type(), obj->bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+ old_snapshot = ast_bridge_snapshot_get_latest(bridge->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We're transferring only the old snapshot reference to the update */</span><br><span style="color: hsl(120, 100%, 40%);">+ update = bridge_snapshot_update_create(old_snapshot, ao2_bump(obj->bridge));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!update) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(old_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(obj->bridge, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = stasis_message_create(ast_bridge_snapshot_type(), update);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(update, -1);</span><br><span> if (!msg) {</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* The link of the new automatically replaces the old */</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_link(bridge_cache, obj->bridge);</span><br><span> stasis_publish(ast_bridge_topic(bridge), msg);</span><br><span> ao2_ref(msg, -1);</span><br><span> }</span><br><span>@@ -1252,35 +1341,15 @@</span><br><span> </span><br><span> struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_message *message;</span><br><span> struct ast_bridge_snapshot *snapshot;</span><br><span> </span><br><span> ast_assert(!ast_strlen_zero(uniqueid));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- message = stasis_cache_get(ast_bridge_cache(),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_snapshot_type(),</span><br><span style="color: hsl(0, 100%, 40%);">- uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!message) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snapshot = ao2_bump(stasis_message_data(message));</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(message, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshot = ao2_find(bridge_cache, uniqueid, OBJ_SEARCH_KEY);</span><br><span> </span><br><span> return snapshot;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief snapshot ID getter for caching topic */</span><br><span style="color: hsl(0, 100%, 40%);">-static const char *bridge_snapshot_get_id(struct stasis_message *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *snapshot;</span><br><span style="color: hsl(0, 100%, 40%);">- if (stasis_message_type(msg) != ast_bridge_snapshot_type()) {</span><br><span style="color: hsl(0, 100%, 40%);">- return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- snapshot = stasis_message_data(msg);</span><br><span style="color: hsl(0, 100%, 40%);">- return snapshot->uniqueid;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static void stasis_bridging_cleanup(void)</span><br><span> {</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);</span><br><span>@@ -1290,8 +1359,73 @@</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(bridge_cache_all);</span><br><span style="color: hsl(0, 100%, 40%);">- bridge_cache_all = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(bridge_topic_pool);</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_topic_pool = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(bridge_topic_all);</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_topic_all = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_container_unregister("bridge_snapshots");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(bridge_cache);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Bridge ao2 container sort function.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12.0.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param obj_left pointer to the (user-defined part) of an object.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param obj_right pointer to the (user-defined part) of an object.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param flags flags from ao2_callback()</span><br><span style="color: hsl(120, 100%, 40%);">+ * OBJ_POINTER - if set, 'obj_right', is an object.</span><br><span style="color: hsl(120, 100%, 40%);">+ * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.</span><br><span style="color: hsl(120, 100%, 40%);">+ * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval <0 if obj_left < obj_right</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval =0 if obj_left == obj_right</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval >0 if obj_left > obj_right</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int bridge_snapshot_sort_cmp(const void *obj_left, const void *obj_right, int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_bridge_snapshot *bridge_left = obj_left;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct ast_bridge_snapshot *bridge_right = obj_right;</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *right_key = obj_right;</span><br><span style="color: hsl(120, 100%, 40%);">+ int cmp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ case OBJ_POINTER:</span><br><span style="color: hsl(120, 100%, 40%);">+ right_key = bridge_right->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Fall through */</span><br><span style="color: hsl(120, 100%, 40%);">+ case OBJ_KEY:</span><br><span style="color: hsl(120, 100%, 40%);">+ cmp = strcmp(bridge_left->uniqueid, right_key);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case OBJ_PARTIAL_KEY:</span><br><span style="color: hsl(120, 100%, 40%);">+ cmp = strncmp(bridge_left->uniqueid, right_key, strlen(right_key));</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return cmp;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Print bridge object key (name).</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 12.0.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param v_obj A pointer to the object we want the key printed.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param where User data needed by prnt to determine where to put output.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param prnt Print output callback function to use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return Nothing</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void bridge_snapshot_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *bridge = v_obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bridge) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ prnt(where, "%s %s chans:%u",</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge->uniqueid, bridge->technology, bridge->num_channels);</span><br><span> }</span><br><span> </span><br><span> int ast_stasis_bridging_init(void)</span><br><span>@@ -1300,10 +1434,19 @@</span><br><span> </span><br><span> ast_register_cleanup(stasis_bridging_cleanup);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",</span><br><span style="color: hsl(0, 100%, 40%);">- bridge_snapshot_get_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_cache = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,</span><br><span style="color: hsl(120, 100%, 40%);">+ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, bridge_snapshot_sort_cmp, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bridge_cache) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_container_register("bridge_cache", bridge_cache, bridge_snapshot_prnt_obj);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!bridge_cache_all) {</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_topic_all = stasis_topic_create("ast_bridge_topic_all");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bridge_topic_all) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ bridge_topic_pool = stasis_topic_pool_create(bridge_topic_all);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bridge_topic_pool) {</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span>diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c</span><br><span>index 9808288..738acdd 100644</span><br><span>--- a/res/ari/resource_bridges.c</span><br><span>+++ b/res/ari/resource_bridges.c</span><br><span>@@ -884,22 +884,12 @@</span><br><span> struct ast_ari_bridges_list_args *args,</span><br><span> struct ast_ari_response *response)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);</span><br><span> RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);</span><br><span> RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);</span><br><span> struct ao2_iterator i;</span><br><span> void *obj;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- cache = ast_bridge_cache();</span><br><span style="color: hsl(0, 100%, 40%);">- if (!cache) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_ari_response_error(</span><br><span style="color: hsl(0, 100%, 40%);">- response, 500, "Internal Server Error",</span><br><span style="color: hsl(0, 100%, 40%);">- "Message bus not initialized");</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_ref(cache, +1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snapshots = stasis_cache_dump(cache, ast_bridge_snapshot_type());</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshots = ast_bridge_cache();</span><br><span> if (!snapshots) {</span><br><span> ast_ari_response_alloc_failed(response);</span><br><span> return;</span><br><span>@@ -913,17 +903,19 @@</span><br><span> </span><br><span> i = ao2_iterator_init(snapshots, 0);</span><br><span> while ((obj = ao2_iterator_next(&i))) {</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot *snapshot = obj;</span><br><span> struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(snapshot, -1);</span><br><span> if (!json_bridge || ast_json_array_append(json, json_bridge)) {</span><br><span> ao2_iterator_destroy(&i);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(snapshots, -1);</span><br><span> ast_ari_response_alloc_failed(response);</span><br><span> return;</span><br><span> }</span><br><span> }</span><br><span> ao2_iterator_destroy(&i);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(snapshots, -1);</span><br><span> </span><br><span> ast_ari_response_ok(response, ast_json_ref(json));</span><br><span> }</span><br><span>diff --git a/res/stasis/app.c b/res/stasis/app.c</span><br><span>index 18ac7d6..7ca7210 100644</span><br><span>--- a/res/stasis/app.c</span><br><span>+++ b/res/stasis/app.c</span><br><span>@@ -182,12 +182,8 @@</span><br><span> forwards->topic_forward = stasis_forward_all(ast_bridge_topic(bridge),</span><br><span> app->topic);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- forwards->topic_cached_forward = stasis_forward_all(</span><br><span style="color: hsl(0, 100%, 40%);">- bridge ? ast_bridge_topic_cached(bridge) : ast_bridge_topic_all_cached(),</span><br><span style="color: hsl(0, 100%, 40%);">- app->topic);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if ((!forwards->topic_forward && bridge) || !forwards->topic_cached_forward) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* Half-subscribed is a bad thing */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!forwards->topic_forward && bridge) {</span><br><span> forwards_unsubscribe(forwards);</span><br><span> ao2_ref(forwards, -1);</span><br><span> return NULL;</span><br><span>@@ -689,33 +685,23 @@</span><br><span> {</span><br><span> struct ast_json *json = NULL;</span><br><span> struct stasis_app *app = data;</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_cache_update *update;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *new_snapshot;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_snapshot *old_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_bridge_snapshot_update *update;</span><br><span> const struct timeval *tv;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(stasis_message_type(message) == stasis_cache_update_type());</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> update = stasis_message_data(message);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_assert(update->type == ast_bridge_snapshot_type());</span><br><span style="color: hsl(120, 100%, 40%);">+ tv = stasis_message_timestamp(message);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- new_snapshot = stasis_message_data(update->new_snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">- old_snapshot = stasis_message_data(update->old_snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">- tv = update->new_snapshot ?</span><br><span style="color: hsl(0, 100%, 40%);">- stasis_message_timestamp(update->new_snapshot) :</span><br><span style="color: hsl(0, 100%, 40%);">- stasis_message_timestamp(message);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!new_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">- json = simple_bridge_event("BridgeDestroyed", old_snapshot, tv);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!old_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">- json = simple_bridge_event("BridgeCreated", new_snapshot, tv);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (new_snapshot && old_snapshot</span><br><span style="color: hsl(0, 100%, 40%);">- && strcmp(new_snapshot->video_source_id, old_snapshot->video_source_id)) {</span><br><span style="color: hsl(0, 100%, 40%);">- json = simple_bridge_event("BridgeVideoSourceChanged", new_snapshot, tv);</span><br><span style="color: hsl(0, 100%, 40%);">- if (json && !ast_strlen_zero(old_snapshot->video_source_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!update->new_snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ json = simple_bridge_event("BridgeDestroyed", update->old_snapshot, tv);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!update->old_snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ json = simple_bridge_event("BridgeCreated", update->new_snapshot, tv);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (update->new_snapshot && update->old_snapshot</span><br><span style="color: hsl(120, 100%, 40%);">+ && strcmp(update->new_snapshot->video_source_id, update->old_snapshot->video_source_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ json = simple_bridge_event("BridgeVideoSourceChanged", update->new_snapshot, tv);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (json && !ast_strlen_zero(update->old_snapshot->video_source_id)) {</span><br><span> ast_json_object_set(json, "old_video_source_id",</span><br><span style="color: hsl(0, 100%, 40%);">- ast_json_string_create(old_snapshot->video_source_id));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_json_string_create(update->old_snapshot->video_source_id));</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -724,8 +710,8 @@</span><br><span> ast_json_unref(json);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!new_snapshot && old_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">- unsubscribe(app, "bridge", old_snapshot->uniqueid, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!update->new_snapshot && update->old_snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+ unsubscribe(app, "bridge", update->old_snapshot->uniqueid, 1);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span>@@ -984,7 +970,7 @@</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- res |= stasis_message_router_add_cache_update(app->router,</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= stasis_message_router_add(app->router,</span><br><span> ast_bridge_snapshot_type(), sub_bridge_update_handler, app);</span><br><span> </span><br><span> res |= stasis_message_router_add_cache_update(app->router,</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10227">change 10227</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10227"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I7049b80efa88676ce5c4666f818fa18ad1985369 </div>
<div style="display:none"> Gerrit-Change-Number: 10227 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>