summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-03-14 16:01:13 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-03-14 16:01:13 +0000
commit66718a06f743f7a8e1158a54239c9f9c9d877769 (patch)
tree568785f0beb298edd60c619e40bd06013790f886
parent251868dc57b1b754efb8ec1a3f671ce785d57650 (diff)
res_mwi_external: Clear the stasis cache entry when the external MWI is deleted.
One of the things missing when external MWI support was added was the ability to clear the stasis cache entry of deleted external MWI mailboxes. Review: https://reviewboard.asterisk.org/r/3325/ ........ Merged revisions 410555 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410557 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--include/asterisk/app.h57
-rw-r--r--main/app.c117
-rw-r--r--res/res_mwi_external.c10
3 files changed, 149 insertions, 35 deletions
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index a998ed86d..70cf75270 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -1341,13 +1341,14 @@ int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen def
/*!
* \since 12
* \brief Publish a MWI state update via stasis
- * \param[in] mailbox The number identifying this mailbox
+ *
+ * \param[in] mailbox The mailbox identifier string.
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
* \param[in] new_msgs The number of new messages in this mailbox
* \param[in] old_msgs The number of old messages in this mailbox
+ *
* \retval 0 Success
* \retval -1 Failure
- * \since 12
*/
#define ast_publish_mwi_state(mailbox, context, new_msgs, old_msgs) \
ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, NULL, NULL)
@@ -1355,15 +1356,16 @@ int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen def
/*!
* \since 12
* \brief Publish a MWI state update associated with some channel
- * \param[in] mailbox The number identifying this mailbox
+ *
+ * \param[in] mailbox The mailbox identifier string.
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
* \param[in] new_msgs The number of new messages in this mailbox
* \param[in] old_msgs The number of old messages in this mailbox
* \param[in] channel_id A unique identifier for a channel associated with this
* change in mailbox state
+ *
* \retval 0 Success
* \retval -1 Failure
- * \since 12
*/
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id) \
ast_publish_mwi_state_full(mailbox, context, new_msgs, old_msgs, channel_id, NULL)
@@ -1371,23 +1373,51 @@ int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen def
/*!
* \since 12
* \brief Publish a MWI state update via stasis with all parameters
- * \param[in] mailbox The number identifying this mailbox
+ *
+ * \param[in] mailbox The mailbox identifier string.
* \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
* \param[in] new_msgs The number of new messages in this mailbox
* \param[in] old_msgs The number of old messages in this mailbox
* \param[in] channel_id A unique identifier for a channel associated with this
+ * change in mailbox state
* \param[in] eid The EID of the server that originally published the message
+ *
* \retval 0 Success
* \retval -1 Failure
- * \since 12
*/
int ast_publish_mwi_state_full(
- const char *mailbox,
- const char *context,
- int new_msgs,
- int old_msgs,
- const char *channel_id,
- struct ast_eid *eid);
+ const char *mailbox,
+ const char *context,
+ int new_msgs,
+ int old_msgs,
+ const char *channel_id,
+ struct ast_eid *eid);
+
+/*!
+ * \since 12.2.0
+ * \brief Delete MWI state cached by stasis
+ *
+ * \param[in] mailbox The mailbox identifier string.
+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+#define ast_delete_mwi_state(mailbox, context) \
+ ast_delete_mwi_state_full(mailbox, context, NULL)
+
+/*!
+ * \since 12.2.0
+ * \brief Delete MWI state cached by stasis with all parameters
+ *
+ * \param[in] mailbox The mailbox identifier string.
+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
+ * \param[in] eid The EID of the server that originally published the message
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid);
/*! \addtogroup StasisTopicsAndMessages
* @{
@@ -1421,6 +1451,9 @@ struct ast_mwi_blob {
* \since 12
* \brief Create a \ref ast_mwi_state object
*
+ * \param[in] mailbox The mailbox identifier string.
+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
+ *
* \retval \ref ast_mwi_state object on success
* \retval NULL on error
*/
diff --git a/main/app.c b/main/app.c
index ce0d16cdd..b6c988258 100644
--- a/main/app.c
+++ b/main/app.c
@@ -2821,36 +2821,51 @@ struct ast_mwi_state *ast_mwi_create(const char *mailbox, const char *context)
return mwi_state;
}
-int ast_publish_mwi_state_full(
- const char *mailbox,
- const char *context,
- int new_msgs,
- int old_msgs,
- const char *channel_id,
- struct ast_eid *eid)
+/*!
+ * \internal
+ * \brief Create a MWI state snapshot message.
+ * \since 12.2.0
+ *
+ * \param[in] mailbox The mailbox identifier string.
+ * \param[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
+ * \param[in] new_msgs The number of new messages in this mailbox
+ * \param[in] old_msgs The number of old messages in this mailbox
+ * \param[in] channel_id A unique identifier for a channel associated with this
+ * change in mailbox state
+ * \param[in] eid The EID of the server that originally published the message
+ *
+ * \retval message on success. Use ao2_cleanup() when done with it.
+ * \retval NULL on error.
+ */
+static struct stasis_message *mwi_state_create_message(
+ const char *mailbox,
+ const char *context,
+ int new_msgs,
+ int old_msgs,
+ const char *channel_id,
+ struct ast_eid *eid)
{
- RAII_VAR(struct ast_mwi_state *, mwi_state, NULL, ao2_cleanup);
- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
- struct stasis_topic *mailbox_specific_topic;
+ struct ast_mwi_state *mwi_state;
+ struct stasis_message *message;
mwi_state = ast_mwi_create(mailbox, context);
if (!mwi_state) {
- return -1;
+ return NULL;
}
mwi_state->new_msgs = new_msgs;
mwi_state->old_msgs = old_msgs;
if (!ast_strlen_zero(channel_id)) {
- RAII_VAR(struct stasis_message *, chan_message,
- stasis_cache_get(ast_channel_cache(),
- ast_channel_snapshot_type(),
- channel_id),
- ao2_cleanup);
+ struct stasis_message *chan_message;
+
+ chan_message = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),
+ channel_id);
if (chan_message) {
mwi_state->snapshot = stasis_message_data(chan_message);
ao2_ref(mwi_state->snapshot, +1);
}
+ ao2_cleanup(chan_message);
}
if (eid) {
@@ -2860,16 +2875,34 @@ int ast_publish_mwi_state_full(
}
/*
- * As far as stasis is concerned, all MWI events are internal.
+ * XXX As far as stasis is concerned, all MWI events are local.
*
- * We may in the future want to make MWI aggregate internal/external
+ * We may in the future want to make MWI aggregate local/remote
* message counts similar to how device state aggregates state.
*/
message = stasis_message_create_full(ast_mwi_state_type(), mwi_state, &ast_eid_default);
+ ao2_cleanup(mwi_state);
+ return message;
+}
+
+int ast_publish_mwi_state_full(
+ const char *mailbox,
+ const char *context,
+ int new_msgs,
+ int old_msgs,
+ const char *channel_id,
+ struct ast_eid *eid)
+{
+ struct ast_mwi_state *mwi_state;
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ struct stasis_topic *mailbox_specific_topic;
+
+ message = mwi_state_create_message(mailbox, context, new_msgs, old_msgs, channel_id, eid);
if (!message) {
return -1;
}
+ mwi_state = stasis_message_data(message);
mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);
if (!mailbox_specific_topic) {
return -1;
@@ -2880,6 +2913,54 @@ int ast_publish_mwi_state_full(
return 0;
}
+int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)
+{
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct stasis_message *cached_msg;
+ struct stasis_message *clear_msg;
+ struct ast_mwi_state *mwi_state;
+ struct stasis_topic *mailbox_specific_topic;
+
+ msg = mwi_state_create_message(mailbox, context, 0, 0, NULL, eid);
+ if (!msg) {
+ return -1;
+ }
+
+ mwi_state = stasis_message_data(msg);
+
+ /*
+ * XXX As far as stasis is concerned, all MWI events are local.
+ *
+ * For now, it is assumed that there is only one entity
+ * maintaining the state of a particular mailbox.
+ *
+ * If we ever have multiple MWI event entities maintaining
+ * the same mailbox that wish to delete their cached entry
+ * we will need to do something about the race condition
+ * potential between checking the cache and removing the
+ * cache entry.
+ */
+ cached_msg = stasis_cache_get_by_eid(ast_mwi_state_cache(),
+ ast_mwi_state_type(), mwi_state->uniqueid, &ast_eid_default);
+ if (!cached_msg) {
+ /* Nothing to clear */
+ return -1;
+ }
+ ao2_cleanup(cached_msg);
+
+ mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);
+ if (!mailbox_specific_topic) {
+ return -1;
+ }
+
+ clear_msg = stasis_cache_clear_create(msg);
+ if (clear_msg) {
+ stasis_publish(mailbox_specific_topic, clear_msg);
+ }
+ ao2_cleanup(clear_msg);
+ return 0;
+}
+
static const char *mwi_state_get_id(struct stasis_message *message)
{
if (ast_mwi_state_type() == stasis_message_type(message)) {
diff --git a/res/res_mwi_external.c b/res/res_mwi_external.c
index a7531c5cb..c3fc0eaf4 100644
--- a/res/res_mwi_external.c
+++ b/res/res_mwi_external.c
@@ -123,13 +123,13 @@ static void mwi_observe_delete(const void *obj)
{
const struct ast_mwi_mailbox_object *mailbox = obj;
- if (!mailbox->msgs_new && !mailbox->msgs_old) {
- /* No need to post a count clearing event. */
- return;
+ if (mailbox->msgs_new || mailbox->msgs_old) {
+ /* Post a count clearing event. */
+ ast_publish_mwi_state(ast_sorcery_object_get_id(mailbox), NULL, 0, 0);
}
- /* Post a count clearing event. */
- ast_publish_mwi_state(ast_sorcery_object_get_id(mailbox), NULL, 0, 0);
+ /* Post a cache remove event. */
+ ast_delete_mwi_state(ast_sorcery_object_get_id(mailbox), NULL);
}
static const struct ast_sorcery_observer mwi_observers = {