diff options
-rw-r--r-- | include/asterisk/stasis.h | 34 | ||||
-rw-r--r-- | main/bridging.c | 23 | ||||
-rw-r--r-- | main/channel.c | 23 | ||||
-rw-r--r-- | main/endpoints.c | 36 | ||||
-rw-r--r-- | main/stasis_cache.c | 55 | ||||
-rw-r--r-- | main/stasis_channels.c | 5 | ||||
-rw-r--r-- | tests/test_stasis.c | 4 |
7 files changed, 109 insertions, 71 deletions
diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h index fdc629324..6a55d0926 100644 --- a/include/asterisk/stasis.h +++ b/include/asterisk/stasis.h @@ -502,31 +502,11 @@ struct stasis_cache_update { }; /*! - * \brief Cache clear message. - */ -struct stasis_cache_clear { - /*! Type of object being cleared from the cache */ - struct stasis_message_type *type; - /*! Id of the object being cleared from the cache */ - char id[]; -}; - -/*! - * \brief Message type for \ref stasis_cache_clear. + * \brief Message type for clearing a message from a stasis cache. * \since 12 */ struct stasis_message_type *stasis_cache_clear_type(void); -/*! - * \brief A message which instructs the caching topic to remove an entry from its cache. - * \param type Message type. - * \param id Unique id of the snapshot to clear. - * \return Message which, when sent to the \a topic, will clear the item from the cache. - * \return \c NULL on error. - * \since 12 - */ -struct stasis_message *stasis_cache_clear_create(struct stasis_message_type *type, const char *id); - /*! @} */ /*! @{ */ @@ -538,6 +518,18 @@ struct stasis_message *stasis_cache_clear_create(struct stasis_message_type *typ struct stasis_caching_topic; /*! + * \brief A message which instructs the caching topic to remove an entry from its cache. + * + * \param message Message representative of the cache entry that should be cleared. + * This will become the data held in the stasis_cache_clear message. + * + * \return Message which, when sent to the \a topic, will clear the item from the cache. + * \return \c NULL on error. + * \since 12 + */ +struct stasis_message *stasis_cache_clear_create(struct stasis_message *message); + +/*! * \brief Callback extract a unique identity from a snapshot message. * * This identity is unique to the underlying object of the snapshot, such as the diff --git a/main/bridging.c b/main/bridging.c index d5d17ae9e..6a21c0b64 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -1283,17 +1283,32 @@ static void bridge_handle_actions(struct ast_bridge *bridge) } } +static struct stasis_message *create_bridge_snapshot_message(struct ast_bridge *bridge) +{ + RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup); + snapshot = ast_bridge_snapshot_create(bridge); + if (!snapshot) { + return NULL; + } + + return stasis_message_create(ast_bridge_snapshot_type(), snapshot); +} + static void destroy_bridge(void *obj) { struct ast_bridge *bridge = obj; - RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); + RAII_VAR(struct stasis_message *, clear_msg, NULL, ao2_cleanup); ast_debug(1, "Bridge %s: actually destroying %s bridge, nobody wants it anymore\n", bridge->uniqueid, bridge->v_table->name); - msg = stasis_cache_clear_create(ast_bridge_snapshot_type(), bridge->uniqueid); - if (msg) { - stasis_publish(ast_bridge_topic(bridge), msg); + clear_msg = create_bridge_snapshot_message(bridge); + if (clear_msg) { + RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); + msg = stasis_cache_clear_create(clear_msg); + if (msg) { + stasis_publish(ast_bridge_topic(bridge), msg); + } } /* Do any pending actions in the context of destruction. */ diff --git a/main/channel.c b/main/channel.c index 4adff953c..f3aabd04a 100644 --- a/main/channel.c +++ b/main/channel.c @@ -817,11 +817,28 @@ int ast_str2cause(const char *name) return -1; } +static struct stasis_message *create_channel_snapshot_message(struct ast_channel *channel) +{ + RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); + snapshot = ast_channel_snapshot_create(channel); + if (!snapshot) { + return NULL; + } + + return stasis_message_create(ast_channel_snapshot_type(), snapshot); +} + static void publish_cache_clear(struct ast_channel *chan) { RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + RAII_VAR(struct stasis_message *, clear_msg, NULL, ao2_cleanup); - message = stasis_cache_clear_create(ast_channel_snapshot_type(), ast_channel_uniqueid(chan)); + clear_msg = create_channel_snapshot_message(chan); + if (!clear_msg) { + return; + } + + message = stasis_cache_clear_create(clear_msg); stasis_publish(ast_channel_topic(chan), message); } @@ -1161,6 +1178,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char } ast_channel_internal_finalize(tmp); + ast_publish_channel_state(tmp); return tmp; } @@ -2369,6 +2387,8 @@ static void ast_channel_destructor(void *obj) char device_name[AST_CHANNEL_NAME]; struct ast_callid *callid; + publish_cache_clear(chan); + if (ast_channel_internal_is_finalized(chan)) { ast_cel_report_event(chan, AST_CEL_CHANNEL_END, NULL, NULL, NULL); ast_cel_check_retire_linkedid(chan); @@ -2884,7 +2904,6 @@ int ast_hangup(struct ast_channel *chan) ast_cc_offer(chan); ast_publish_channel_state(chan); - publish_cache_clear(chan); if (ast_channel_cdr(chan) && !ast_test_flag(ast_channel_cdr(chan), AST_CDR_FLAG_BRIDGED) && !ast_test_flag(ast_channel_cdr(chan), AST_CDR_FLAG_POST_DISABLED) && diff --git a/main/endpoints.c b/main/endpoints.c index c2d0577f9..a5d50cfde 100644 --- a/main/endpoints.c +++ b/main/endpoints.c @@ -145,18 +145,25 @@ static void endpoint_channel_snapshot(void *data, } } +/*! \brief Handler for channel snapshot cache clears */ static void endpoint_cache_clear(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message) { struct ast_endpoint *endpoint = data; - struct stasis_cache_clear *clear = stasis_message_data(message); + struct stasis_message *clear_msg = stasis_message_data(message); + struct ast_channel_snapshot *clear_snapshot; + + if (stasis_message_type(clear_msg) != ast_channel_snapshot_type()) { + return; + } + + clear_snapshot = stasis_message_data(clear_msg); ast_assert(endpoint != NULL); - ast_assert(clear != NULL); ao2_lock(endpoint); - ao2_find(endpoint->channel_ids, clear->id, OBJ_POINTER | OBJ_NODATA | OBJ_UNLINK); + ast_str_container_remove(endpoint->channel_ids, clear_snapshot->uniqueid); ao2_unlock(endpoint); endpoint_publish_snapshot(endpoint); } @@ -247,17 +254,32 @@ const char *ast_endpoint_get_tech(const struct ast_endpoint *endpoint) return endpoint->tech; } +static struct stasis_message *create_endpoint_snapshot_message(struct ast_endpoint *endpoint) +{ + RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup); + snapshot = ast_endpoint_snapshot_create(endpoint); + if (!snapshot) { + return NULL; + } + + return stasis_message_create(ast_endpoint_snapshot_type(), snapshot); +} + void ast_endpoint_shutdown(struct ast_endpoint *endpoint) { - RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + RAII_VAR(struct stasis_message *, clear_msg, NULL, ao2_cleanup); if (endpoint == NULL) { return; } - message = stasis_cache_clear_create(ast_endpoint_snapshot_type(), endpoint->id); - if (message) { - stasis_publish(endpoint->topic, message); + clear_msg = create_endpoint_snapshot_message(endpoint); + if (clear_msg) { + RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + message = stasis_cache_clear_create(clear_msg); + if (message) { + stasis_publish(endpoint->topic, message); + } } /* Bump refcount to hold on to the router */ diff --git a/main/stasis_cache.c b/main/stasis_cache.c index ac34959db..546ad4998 100644 --- a/main/stasis_cache.c +++ b/main/stasis_cache.c @@ -262,30 +262,11 @@ struct ao2_container *stasis_cache_dump(struct stasis_caching_topic *caching_top STASIS_MESSAGE_TYPE_DEFN(stasis_cache_clear_type); STASIS_MESSAGE_TYPE_DEFN(stasis_cache_update_type); -static void cache_clear_dtor(void *obj) +struct stasis_message *stasis_cache_clear_create(struct stasis_message *id_message) { - struct stasis_cache_clear *ev = obj; - ao2_cleanup(ev->type); - ev->type = NULL; -} - -struct stasis_message *stasis_cache_clear_create(struct stasis_message_type *type, const char *id) -{ - RAII_VAR(struct stasis_cache_clear *, ev, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); - ev = ao2_alloc(sizeof(*ev) + strlen(id) + 1, cache_clear_dtor); - if (!ev) { - return NULL; - } - - /* strcpy safe */ - strcpy(ev->id, id); - ao2_ref(type, +1); - ev->type = type; - - msg = stasis_message_create(stasis_cache_clear_type(), ev); - + msg = stasis_message_create(stasis_cache_clear_type(), id_message); if (!msg) { return NULL; } @@ -363,21 +344,25 @@ static void caching_topic_exec(void *data, struct stasis_subscription *sub, stru if (stasis_cache_clear_type() == stasis_message_type(message)) { RAII_VAR(struct stasis_message *, old_snapshot, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, update, NULL, ao2_cleanup); - struct stasis_cache_clear *clear = stasis_message_data(message); - ast_assert(clear->type != NULL); - ast_assert(clear->id != NULL); - old_snapshot = cache_put(caching_topic, clear->type, clear->id, NULL); - if (old_snapshot) { - update = update_create(topic, old_snapshot, NULL); - stasis_publish(caching_topic->topic, update); - } else { - /* While this could be a problem, it's very likely to - * happen with message forwarding */ - ast_debug(1, - "Attempting to remove an item from the cache that isn't there: %s %s\n", - stasis_message_type_name(clear->type), clear->id); + struct stasis_message *clear_msg = stasis_message_data(message); + const char *clear_id = caching_topic->id_fn(clear_msg); + struct stasis_message_type *clear_type = stasis_message_type(clear_msg); + + ast_assert(clear_type != NULL); + + if (clear_id) { + old_snapshot = cache_put(caching_topic, clear_type, clear_id, NULL); + if (old_snapshot) { + update = update_create(topic, old_snapshot, NULL); + stasis_publish(caching_topic->topic, update); + return; + } + + ast_log(LOG_ERROR, + "Attempting to remove an item from the %s cache that isn't there: %s %s\n", + stasis_topic_name(caching_topic->topic), stasis_message_type_name(clear_type), clear_id); + return; } - return; } id = caching_topic->id_fn(message); diff --git a/main/stasis_channels.c b/main/stasis_channels.c index 52b6ef4ce..65e9f917d 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -131,6 +131,11 @@ struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *cha { RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); + /* no snapshots for dummy channels */ + if (!ast_channel_tech(chan)) { + return NULL; + } + snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor); if (!snapshot || ast_string_field_init(snapshot, 1024)) { return NULL; diff --git a/tests/test_stasis.c b/tests/test_stasis.c index 8f81378ab..915226d29 100644 --- a/tests/test_stasis.c +++ b/tests/test_stasis.c @@ -716,7 +716,7 @@ AST_TEST_DEFINE(cache) ao2_ref(test_message2_2, -1); /* Clear snapshot 1 */ - test_message1_clear = stasis_cache_clear_create(cache_type, "1"); + test_message1_clear = stasis_cache_clear_create(test_message1_1); ast_test_validate(test, NULL != test_message1_clear); stasis_publish(topic, test_message1_clear); @@ -811,7 +811,7 @@ AST_TEST_DEFINE(cache_dump) } /* Clear snapshot 1 */ - test_message1_clear = stasis_cache_clear_create(cache_type, "1"); + test_message1_clear = stasis_cache_clear_create(test_message1_1); ast_test_validate(test, NULL != test_message1_clear); stasis_publish(topic, test_message1_clear); |