mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-18 07:48:14 +00:00
Split caching out from the stasis_caching_topic.
In working with res_stasis, I discovered a significant limitation to
the current structure of stasis_caching_topics: you cannot subscribe
to cache updates for a single channel/bridge/endpoint/etc.
To address this, this patch splits the cache away from the
stasis_caching_topic, making it a first class object. The stasis_cache
object is shared amongst individual stasis_caching_topics that are
created per channel/endpoint/etc. These are still forwarded to global
whatever_all_cached topics, so their use from most of the code does
not change.
In making these changes, I noticed that we frequently used a similar
pattern for bridges, endpoints and channels:
single_topic ----------------> all_topic
^
|
single_topic_cached ----+----> all_topic_cached
|
+----> cache
This pattern was extracted as the 'Stasis Caching Pattern', defined in
stasis_caching_pattern.h. This avoids a lot of duplicate code between
the different domain objects.
Since the cache is now disassociated from its upstream caching topics,
this also necessitated a change to how the 'guaranteed' flag worked
for retrieving from a cache. The code for handling the caching
guarantee was extracted into a 'stasis_topic_wait' function, which
works for any stasis_topic.
(closes issue ASTERISK-22002)
Review: https://reviewboard.asterisk.org/r/2672/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395954 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -33,6 +33,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/astobj2.h"
|
||||
#include "asterisk/stasis.h"
|
||||
#include "asterisk/stasis_cache_pattern.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/stasis_bridges.h"
|
||||
#include "asterisk/stasis_channels.h"
|
||||
@@ -361,6 +362,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *message);
|
||||
static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *message);
|
||||
|
||||
static struct stasis_cp_all *bridge_cache_all;
|
||||
|
||||
/*!
|
||||
* @{ \brief Define bridge message types.
|
||||
*/
|
||||
@@ -372,14 +375,52 @@ STASIS_MESSAGE_TYPE_DEFN(ast_blind_transfer_type, .to_ami = blind_transfer_to_am
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_attended_transfer_type, .to_ami = attended_transfer_to_ami);
|
||||
/*! @} */
|
||||
|
||||
/*! \brief Aggregate topic for bridge messages */
|
||||
static struct stasis_topic *bridge_topic_all;
|
||||
struct stasis_cache *ast_bridge_cache(void)
|
||||
{
|
||||
return stasis_cp_all_cache(bridge_cache_all);
|
||||
}
|
||||
|
||||
/*! \brief Caching aggregate topic for bridge snapshots */
|
||||
static struct stasis_caching_topic *bridge_topic_all_cached;
|
||||
struct stasis_topic *ast_bridge_topic_all(void)
|
||||
{
|
||||
return stasis_cp_all_topic(bridge_cache_all);
|
||||
}
|
||||
|
||||
/*! \brief Topic pool for individual bridge topics */
|
||||
static struct stasis_topic_pool *bridge_topic_pool;
|
||||
struct stasis_topic *ast_bridge_topic_all_cached(void)
|
||||
{
|
||||
return stasis_cp_all_topic_cached(bridge_cache_all);
|
||||
}
|
||||
|
||||
int bridge_topics_init(struct ast_bridge *bridge)
|
||||
{
|
||||
if (ast_strlen_zero(bridge->uniqueid)) {
|
||||
ast_log(LOG_ERROR, "Bridge id initialization required\n");
|
||||
return -1;
|
||||
}
|
||||
bridge->topics = stasis_cp_single_create(bridge_cache_all,
|
||||
bridge->uniqueid);
|
||||
if (!bridge->topics) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct stasis_topic *ast_bridge_topic(struct ast_bridge *bridge)
|
||||
{
|
||||
if (!bridge) {
|
||||
return ast_bridge_topic_all();
|
||||
}
|
||||
|
||||
return stasis_cp_single_topic(bridge->topics);
|
||||
}
|
||||
|
||||
struct stasis_topic *ast_bridge_topic_cached(struct ast_bridge *bridge)
|
||||
{
|
||||
if (!bridge) {
|
||||
return ast_bridge_topic_all_cached();
|
||||
}
|
||||
|
||||
return stasis_cp_single_topic_cached(bridge->topics);
|
||||
}
|
||||
|
||||
/*! \brief Destructor for bridge snapshots */
|
||||
static void bridge_snapshot_dtor(void *obj)
|
||||
@@ -425,25 +466,6 @@ struct ast_bridge_snapshot *ast_bridge_snapshot_create(struct ast_bridge *bridge
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
struct stasis_topic *ast_bridge_topic(struct ast_bridge *bridge)
|
||||
{
|
||||
struct stasis_topic *bridge_topic = stasis_topic_pool_get_topic(bridge_topic_pool, bridge->uniqueid);
|
||||
if (!bridge_topic) {
|
||||
return ast_bridge_topic_all();
|
||||
}
|
||||
return bridge_topic;
|
||||
}
|
||||
|
||||
struct stasis_topic *ast_bridge_topic_all(void)
|
||||
{
|
||||
return bridge_topic_all;
|
||||
}
|
||||
|
||||
struct stasis_caching_topic *ast_bridge_topic_all_cached(void)
|
||||
{
|
||||
return bridge_topic_all_cached;
|
||||
}
|
||||
|
||||
void ast_bridge_publish_state(struct ast_bridge *bridge)
|
||||
{
|
||||
RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
|
||||
@@ -464,7 +486,8 @@ void ast_bridge_publish_state(struct ast_bridge *bridge)
|
||||
stasis_publish(ast_bridge_topic(bridge), msg);
|
||||
}
|
||||
|
||||
static void bridge_publish_state_from_blob(struct ast_bridge_blob *obj)
|
||||
static void bridge_publish_state_from_blob(struct ast_bridge *bridge,
|
||||
struct ast_bridge_blob *obj)
|
||||
{
|
||||
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
|
||||
|
||||
@@ -475,7 +498,7 @@ static void bridge_publish_state_from_blob(struct ast_bridge_blob *obj)
|
||||
return;
|
||||
}
|
||||
|
||||
stasis_publish(stasis_topic_pool_get_topic(bridge_topic_pool, obj->bridge->uniqueid), msg);
|
||||
stasis_publish(ast_bridge_topic(bridge), msg);
|
||||
}
|
||||
|
||||
/*! \brief Destructor for bridge merge messages */
|
||||
@@ -597,7 +620,7 @@ void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *cha
|
||||
|
||||
/* enter blob first, then state */
|
||||
stasis_publish(ast_bridge_topic(bridge), msg);
|
||||
bridge_publish_state_from_blob(stasis_message_data(msg));
|
||||
bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
|
||||
}
|
||||
|
||||
void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *chan)
|
||||
@@ -610,7 +633,7 @@ void ast_bridge_publish_leave(struct ast_bridge *bridge, struct ast_channel *cha
|
||||
}
|
||||
|
||||
/* state first, then leave blob (opposite of enter, preserves nesting of events) */
|
||||
bridge_publish_state_from_blob(stasis_message_data(msg));
|
||||
bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
|
||||
stasis_publish(ast_bridge_topic(bridge), msg);
|
||||
}
|
||||
|
||||
@@ -1043,7 +1066,7 @@ struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
|
||||
|
||||
ast_assert(!ast_strlen_zero(uniqueid));
|
||||
|
||||
message = stasis_cache_get(ast_bridge_topic_all_cached(),
|
||||
message = stasis_cache_get(ast_bridge_cache(),
|
||||
ast_bridge_snapshot_type(),
|
||||
uniqueid);
|
||||
if (!message) {
|
||||
@@ -1058,23 +1081,6 @@ struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
static void stasis_bridging_cleanup(void)
|
||||
{
|
||||
ao2_cleanup(bridge_topic_all);
|
||||
bridge_topic_all = NULL;
|
||||
bridge_topic_all_cached = stasis_caching_unsubscribe_and_join(
|
||||
bridge_topic_all_cached);
|
||||
ao2_cleanup(bridge_topic_pool);
|
||||
bridge_topic_pool = NULL;
|
||||
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
|
||||
}
|
||||
|
||||
/*! \brief snapshot ID getter for caching topic */
|
||||
static const char *bridge_snapshot_get_id(struct stasis_message *msg)
|
||||
{
|
||||
@@ -1086,21 +1092,38 @@ static const char *bridge_snapshot_get_id(struct stasis_message *msg)
|
||||
return snapshot->uniqueid;
|
||||
}
|
||||
|
||||
static void stasis_bridging_cleanup(void)
|
||||
{
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_snapshot_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_bridge_merge_message_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_entered_bridge_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_left_bridge_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_blind_transfer_type);
|
||||
STASIS_MESSAGE_TYPE_CLEANUP(ast_attended_transfer_type);
|
||||
|
||||
ao2_cleanup(bridge_cache_all);
|
||||
bridge_cache_all = NULL;
|
||||
}
|
||||
|
||||
int ast_stasis_bridging_init(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
ast_register_cleanup(stasis_bridging_cleanup);
|
||||
|
||||
STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
|
||||
STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
|
||||
STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
|
||||
STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
|
||||
STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
|
||||
STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
|
||||
bridge_topic_all = stasis_topic_create("ast_bridge_topic_all");
|
||||
bridge_topic_all_cached = stasis_caching_topic_create(bridge_topic_all, bridge_snapshot_get_id);
|
||||
bridge_topic_pool = stasis_topic_pool_create(bridge_topic_all);
|
||||
bridge_cache_all = stasis_cp_all_create("ast_bridge_topic_all",
|
||||
bridge_snapshot_get_id);
|
||||
|
||||
return !bridge_topic_all
|
||||
|| !bridge_topic_all_cached
|
||||
|| !bridge_topic_pool ? -1 : 0;
|
||||
if (!bridge_cache_all) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_snapshot_type);
|
||||
res |= STASIS_MESSAGE_TYPE_INIT(ast_bridge_merge_message_type);
|
||||
res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_entered_bridge_type);
|
||||
res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_left_bridge_type);
|
||||
res |= STASIS_MESSAGE_TYPE_INIT(ast_blind_transfer_type);
|
||||
res |= STASIS_MESSAGE_TYPE_INIT(ast_attended_transfer_type);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user