<p>Kevin Harwell <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/11466">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Kevin Harwell: Looks good to me, approved; Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_voicemail: Remove dependency on the stasis cache<br><br>app_voicemail utilized the stasis cache when polling mailboxes for MWI. This<br>caused a memory leak (items were not being appropriately removed from the<br>cache), and subsequent slowdown in system processing. This patch removes the<br>stasis cache dependency, thus alleviating the memory leak. It does this by<br>utilizing the new MWI API that better manages state lifetime.<br><br>ASTERISK-28443<br>ASTERISK-27121<br><br>Change-Id: Ie89fedaca81ea1fd03d150d9d3a1ef3d53740e46<br>---<br>M apps/app_voicemail.c<br>1 file changed, 90 insertions(+), 221 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c</span><br><span>index c0edd44..5603bb5 100644</span><br><span>--- a/apps/app_voicemail.c</span><br><span>+++ b/apps/app_voicemail.c</span><br><span>@@ -1016,43 +1016,8 @@</span><br><span> static pthread_t poll_thread = AST_PTHREADT_NULL;</span><br><span> static unsigned char poll_thread_run;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Subscription to MWI event subscription changes */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_subscription *mwi_sub_sub;</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%);">- * \brief An MWI subscription</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This is so we can keep track of which mailboxes are subscribed to.</span><br><span style="color: hsl(0, 100%, 40%);">- * This way, we know which mailboxes to poll when the pollmailboxes</span><br><span style="color: hsl(0, 100%, 40%);">- * option is being used.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct mwi_sub {</span><br><span style="color: hsl(0, 100%, 40%);">-   AST_RWLIST_ENTRY(mwi_sub) entry;</span><br><span style="color: hsl(0, 100%, 40%);">-        int old_urgent;</span><br><span style="color: hsl(0, 100%, 40%);">- int old_new;</span><br><span style="color: hsl(0, 100%, 40%);">-    int old_old;</span><br><span style="color: hsl(0, 100%, 40%);">-    char *uniqueid;</span><br><span style="color: hsl(0, 100%, 40%);">- char mailbox[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%);">-struct mwi_sub_task {</span><br><span style="color: hsl(0, 100%, 40%);">- const char *mailbox;</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *context;</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *uniqueid;</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%);">-static void mwi_sub_task_dtor(struct mwi_sub_task *mwist)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_free((void *) mwist->mailbox);</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_free((void *) mwist->context);</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_free((void *) mwist->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_free(mwist);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static struct ast_taskprocessor *mwi_subscription_tps;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static AST_RWLIST_HEAD_STATIC(mwi_subs, mwi_sub);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct alias_mailbox_mapping {</span><br><span>   char *alias;</span><br><span>         char *mailbox;</span><br><span>@@ -6316,7 +6281,7 @@</span><br><span>       return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void run_externnotify(char *context, char *extension, const char *flag)</span><br><span style="color: hsl(120, 100%, 40%);">+static void run_externnotify(const char *context, const char *extension, const char *flag)</span><br><span> {</span><br><span>  char arguments[255];</span><br><span>         char ext_context[256] = "";</span><br><span>@@ -13197,38 +13162,29 @@</span><br><span>    AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"),</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void poll_subscribed_mailbox(struct mwi_sub *mwi_sub)</span><br><span style="color: hsl(120, 100%, 40%);">+static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)</span><br><span> {</span><br><span>     int new = 0, old = 0, urgent = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   inboxcount2(mwi_sub->mailbox, &urgent, &new, &old);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!mwi_state) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* This should only occur due to allocation failure of a default mwi state object */</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%);">+   inboxcount2(mwi_state->uniqueid, &urgent, &new, &old);</span><br><span> </span><br><span> #ifdef IMAP_STORAGE</span><br><span>     if (imap_poll_logout) {</span><br><span style="color: hsl(0, 100%, 40%);">-         imap_logout(mwi_sub->mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+             imap_logout(mwi_state->uniqueid);</span><br><span>         }</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (urgent != mwi_sub->old_urgent || new != mwi_sub->old_new || old != mwi_sub->old_old) {</span><br><span style="color: hsl(0, 100%, 40%);">-             mwi_sub->old_urgent = urgent;</span><br><span style="color: hsl(0, 100%, 40%);">-                mwi_sub->old_new = new;</span><br><span style="color: hsl(0, 100%, 40%);">-              mwi_sub->old_old = old;</span><br><span style="color: hsl(0, 100%, 40%);">-              queue_mwi_event(NULL, mwi_sub->mailbox, urgent, new, old);</span><br><span style="color: hsl(0, 100%, 40%);">-           run_externnotify(NULL, mwi_sub->mailbox, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (urgent != mwi_state->urgent_msgs || new != mwi_state->new_msgs || old != mwi_state->old_msgs) {</span><br><span style="color: hsl(120, 100%, 40%);">+          queue_mwi_event(NULL, mwi_state->uniqueid, urgent, new, old);</span><br><span style="color: hsl(120, 100%, 40%);">+              run_externnotify(NULL, mwi_state->uniqueid, NULL);</span><br><span>        }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void poll_subscribed_mailboxes(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct mwi_sub *mwi_sub;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        AST_RWLIST_RDLOCK(&mwi_subs);</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (!ast_strlen_zero(mwi_sub->mailbox)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    poll_subscribed_mailbox(mwi_sub);</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_RWLIST_UNLOCK(&mwi_subs);</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span> }</span><br><span> </span><br><span> static void *mb_poll_thread(void *data)</span><br><span>@@ -13237,6 +13193,12 @@</span><br><span>             struct timespec ts = { 0, };</span><br><span>                 struct timeval wait;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+              ast_mwi_state_callback_subscribed(poll_subscribed_mailbox, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!poll_thread_run) {</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%);">+</span><br><span>          wait = ast_tvadd(ast_tvnow(), ast_samp2tv(poll_freq, 1));</span><br><span>            ts.tv_sec = wait.tv_sec;</span><br><span>             ts.tv_nsec = wait.tv_usec * 1000;</span><br><span>@@ -13244,22 +13206,11 @@</span><br><span>                ast_mutex_lock(&poll_lock);</span><br><span>              ast_cond_timedwait(&poll_cond, &poll_lock, &ts);</span><br><span>                 ast_mutex_unlock(&poll_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!poll_thread_run)</span><br><span style="color: hsl(0, 100%, 40%);">-                   break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          poll_subscribed_mailboxes();</span><br><span>         }</span><br><span> </span><br><span>        return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_sub_destroy(struct mwi_sub *mwi_sub)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_free(mwi_sub->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(mwi_sub);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #ifdef IMAP_STORAGE</span><br><span> static void imap_logout(const char *mailbox_id)</span><br><span> {</span><br><span>@@ -13295,157 +13246,74 @@</span><br><span>      vmstate_delete(vms);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void imap_close_subscribed_mailboxes(void)</span><br><span style="color: hsl(120, 100%, 40%);">+static int imap_close_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      struct mwi_sub *mwi_sub;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        AST_RWLIST_RDLOCK(&mwi_subs);</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (!ast_strlen_zero(mwi_sub->mailbox)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    imap_logout(mwi_sub->mailbox);</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (mwi_state && !ast_strlen_zero(mwi_state->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          imap_logout(mwi_state->uniqueid);</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_UNLOCK(&mwi_subs);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int handle_unsubscribe(void *datap)</span><br><span style="color: hsl(120, 100%, 40%);">+static int mwi_handle_unsubscribe2(void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   struct mwi_sub *mwi_sub;</span><br><span style="color: hsl(0, 100%, 40%);">-        char *uniqueid = datap;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_mwi_state *mwi_state = data;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     AST_RWLIST_WRLOCK(&mwi_subs);</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_TRAVERSE_SAFE_BEGIN(&mwi_subs, mwi_sub, entry) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (!strcmp(mwi_sub->uniqueid, uniqueid)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  AST_LIST_REMOVE_CURRENT(entry);</span><br><span style="color: hsl(0, 100%, 40%);">-                 /* Don't break here since a duplicate uniqueid</span><br><span style="color: hsl(0, 100%, 40%);">-                       * may have been added as a result of a cache dump. */</span><br><span style="color: hsl(120, 100%, 40%);">+        /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Go ahead and clear the implicit MWI publisher here to avoid a leak. If a backing</span><br><span style="color: hsl(120, 100%, 40%);">+    * configuration is available it'll re-initialize (reset the cached state) on its</span><br><span style="color: hsl(120, 100%, 40%);">+  * next publish.</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_delete_mwi_state_full(mwi_state->uniqueid, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef IMAP_STORAGE</span><br><span style="color: hsl(0, 100%, 40%);">-                 imap_logout(mwi_sub->mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+     imap_close_subscribed_mailbox(mwi_state, NULL);</span><br><span> #endif</span><br><span style="color: hsl(0, 100%, 40%);">-                       mwi_sub_destroy(mwi_sub);</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_RWLIST_TRAVERSE_SAFE_END</span><br><span style="color: hsl(0, 100%, 40%);">-    AST_RWLIST_UNLOCK(&mwi_subs);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_free(uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_ref(mwi_state, -1);</span><br><span>      return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int handle_subscribe(void *datap)</span><br><span style="color: hsl(120, 100%, 40%);">+static void mwi_handle_unsubscribe(const char *id, struct ast_mwi_subscriber *sub)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     unsigned int len;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct mwi_sub *mwi_sub;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct mwi_sub_task *p = datap;</span><br><span style="color: hsl(120, 100%, 40%);">+       void *data = ast_mwi_subscriber_data(sub);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  len = sizeof(*mwi_sub) + 1;</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!ast_strlen_zero(p->mailbox))</span><br><span style="color: hsl(0, 100%, 40%);">-            len += strlen(p->mailbox);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!ast_strlen_zero(p->context))</span><br><span style="color: hsl(0, 100%, 40%);">-            len += strlen(p->context) + 1; /* Allow for seperator */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!(mwi_sub = ast_calloc(1, len)))</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%);">-      mwi_sub->uniqueid = ast_strdup(p->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!ast_strlen_zero(p->mailbox))</span><br><span style="color: hsl(0, 100%, 40%);">-            strcpy(mwi_sub->mailbox, p->mailbox);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!ast_strlen_zero(p->context)) {</span><br><span style="color: hsl(0, 100%, 40%);">-          strcat(mwi_sub->mailbox, "@");</span><br><span style="color: hsl(0, 100%, 40%);">-             strcat(mwi_sub->mailbox, p->context);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Don't bump data's reference. We'll just use the one returned above */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ast_taskprocessor_push(mwi_subscription_tps, mwi_handle_unsubscribe2, data) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* A reference was returned for data when retrieving, so remove it on error */</span><br><span style="color: hsl(120, 100%, 40%);">+                ao2_ref(data, -1);</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        AST_RWLIST_WRLOCK(&mwi_subs);</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_INSERT_TAIL(&mwi_subs, mwi_sub, entry);</span><br><span style="color: hsl(0, 100%, 40%);">-  AST_RWLIST_UNLOCK(&mwi_subs);</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_sub_task_dtor(p);</span><br><span style="color: hsl(0, 100%, 40%);">-   poll_subscribed_mailbox(mwi_sub);</span><br><span style="color: hsl(120, 100%, 40%);">+static int mwi_handle_subscribe2(void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    poll_subscribed_mailbox(data, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+  ao2_ref(data, -1);</span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_unsub_event_cb(struct stasis_subscription_change *change)</span><br><span style="color: hsl(120, 100%, 40%);">+static void mwi_handle_subscribe(const char *id, struct ast_mwi_subscriber *sub)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      char *uniqueid = ast_strdup(change->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+     void *data = ast_mwi_subscriber_data(sub);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  if (!uniqueid) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "Unable to allocate memory for uniqueid\n");</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_taskprocessor_push(mwi_subscription_tps, handle_unsubscribe, uniqueid) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_free(uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Don't bump data's reference. We'll just use the one returned above */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (ast_taskprocessor_push(mwi_subscription_tps, mwi_handle_subscribe2, data) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* A reference was returned for data when retrieving, so remove it on error */</span><br><span style="color: hsl(120, 100%, 40%);">+                ao2_ref(data, -1);</span><br><span>   }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_sub_event_cb(struct stasis_subscription_change *change)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      struct mwi_sub_task *mwist;</span><br><span style="color: hsl(0, 100%, 40%);">-     const char *topic;</span><br><span style="color: hsl(0, 100%, 40%);">-      char *context;</span><br><span style="color: hsl(0, 100%, 40%);">-  char *mailbox;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  mwist = ast_calloc(1, (sizeof(*mwist)));</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!mwist) {</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* The topic name is prefixed with "mwi:all/" as this is a pool topic */</span><br><span style="color: hsl(0, 100%, 40%);">-      topic = stasis_topic_name(change->topic) + 8;</span><br><span style="color: hsl(0, 100%, 40%);">-        if (separate_mailbox(ast_strdupa(topic), &mailbox, &context)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_free(mwist);</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       mwist->mailbox = ast_strdup(mailbox);</span><br><span style="color: hsl(0, 100%, 40%);">-        mwist->context = ast_strdup(context);</span><br><span style="color: hsl(0, 100%, 40%);">-        mwist->uniqueid = ast_strdup(change->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_taskprocessor_push(mwi_subscription_tps, handle_subscribe, mwist) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             mwi_sub_task_dtor(mwist);</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void mwi_event_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        struct stasis_subscription_change *change;</span><br><span style="color: hsl(0, 100%, 40%);">-      /* Only looking for subscription change notices here */</span><br><span style="color: hsl(0, 100%, 40%);">- if (stasis_message_type(msg) != stasis_subscription_change_type()) {</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%);">-       change = stasis_message_data(msg);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (change->topic == ast_mwi_topic_all()) {</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!strcmp(change->description, "Subscribe")) {</span><br><span style="color: hsl(0, 100%, 40%);">-           mwi_sub_event_cb(change);</span><br><span style="color: hsl(0, 100%, 40%);">-       } else if (!strcmp(change->description, "Unsubscribe")) {</span><br><span style="color: hsl(0, 100%, 40%);">-          mwi_unsub_event_cb(change);</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int dump_cache(void *obj, void *arg, int flags)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct stasis_message *msg = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-       mwi_event_cb(NULL, NULL, msg);</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(120, 100%, 40%);">+struct ast_mwi_observer mwi_observer = {</span><br><span style="color: hsl(120, 100%, 40%);">+  .on_subscribe = mwi_handle_subscribe,</span><br><span style="color: hsl(120, 100%, 40%);">+ .on_unsubscribe = mwi_handle_unsubscribe,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span> </span><br><span> static void start_poll_thread(void)</span><br><span> {</span><br><span>        int errcode;</span><br><span style="color: hsl(0, 100%, 40%);">-    mwi_sub_sub = stasis_subscribe(ast_mwi_topic_all(), mwi_event_cb, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (mwi_sub_sub) {</span><br><span style="color: hsl(0, 100%, 40%);">-              struct ao2_container *cached = stasis_cache_dump(ast_mwi_state_cache(), stasis_subscription_change_type());</span><br><span style="color: hsl(0, 100%, 40%);">-             if (cached) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   ao2_callback(cached, OBJ_MULTIPLE | OBJ_NODATA, dump_cache, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-               ao2_cleanup(cached);</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_mwi_add_observer(&mwi_observer);</span><br><span> </span><br><span>         poll_thread_run = 1;</span><br><span> </span><br><span>@@ -13458,15 +13326,14 @@</span><br><span> {</span><br><span>    poll_thread_run = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        mwi_sub_sub = stasis_unsubscribe_and_join(mwi_sub_sub);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>      ast_mutex_lock(&poll_lock);</span><br><span>      ast_cond_signal(&poll_cond);</span><br><span>     ast_mutex_unlock(&poll_lock);</span><br><span> </span><br><span>        pthread_join(poll_thread, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>     poll_thread = AST_PTHREADT_NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_mwi_remove_observer(&mwi_observer);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -13590,38 +13457,40 @@</span><br><span> </span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int manager_voicemail_refresh(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(120, 100%, 40%);">+static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     const char *context = astman_get_header(m, "Context");</span><br><span style="color: hsl(0, 100%, 40%);">-        const char *mailbox = astman_get_header(m, "Mailbox");</span><br><span style="color: hsl(0, 100%, 40%);">-        struct mwi_sub *mwi_sub;</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *context = astman_get_header(data, "Context");</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *mailbox = astman_get_header(data, "Mailbox");</span><br><span>  const char *at;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     AST_RWLIST_RDLOCK(&mwi_subs);</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_TRAVERSE(&mwi_subs, mwi_sub, entry) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (!ast_strlen_zero(mwi_sub->mailbox)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    if (</span><br><span style="color: hsl(0, 100%, 40%);">-                            /* First case: everything matches */</span><br><span style="color: hsl(0, 100%, 40%);">-                            (ast_strlen_zero(context) && ast_strlen_zero(mailbox)) ||</span><br><span style="color: hsl(0, 100%, 40%);">-                               /* Second case: match the mailbox only */</span><br><span style="color: hsl(0, 100%, 40%);">-                               (ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                       (at = strchr(mwi_sub->mailbox, '@')) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                      strncmp(mailbox, mwi_sub->mailbox, at - mwi_sub->mailbox) == 0) ||</span><br><span style="color: hsl(0, 100%, 40%);">-                                /* Third case: match the context only */</span><br><span style="color: hsl(0, 100%, 40%);">-                                (!ast_strlen_zero(context) && ast_strlen_zero(mailbox) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                       (at = strchr(mwi_sub->mailbox, '@')) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                      strcmp(context, at + 1) == 0) ||</span><br><span style="color: hsl(0, 100%, 40%);">-                                /* Final case: match an exact specified mailbox */</span><br><span style="color: hsl(0, 100%, 40%);">-                              (!ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                      (at = strchr(mwi_sub->mailbox, '@')) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                      strncmp(mailbox, mwi_sub->mailbox, at - mwi_sub->mailbox) == 0 &&</span><br><span style="color: hsl(0, 100%, 40%);">-                                 strcmp(context, at + 1) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(mwi_state->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* First case: everything matches */</span><br><span style="color: hsl(120, 100%, 40%);">+                  (ast_strlen_zero(context) && ast_strlen_zero(mailbox)) ||</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Second case: match the mailbox only */</span><br><span style="color: hsl(120, 100%, 40%);">+                     (ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                      (at = strchr(mwi_state->uniqueid, '@')) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                         strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0) ||</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* Third case: match the context only */</span><br><span style="color: hsl(120, 100%, 40%);">+                      (!ast_strlen_zero(context) && ast_strlen_zero(mailbox) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                      (at = strchr(mwi_state->uniqueid, '@')) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                         strcmp(context, at + 1) == 0) ||</span><br><span style="color: hsl(120, 100%, 40%);">+                     /* Final case: match an exact specified mailbox */</span><br><span style="color: hsl(120, 100%, 40%);">+                    (!ast_strlen_zero(context) && !ast_strlen_zero(mailbox) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                     (at = strchr(mwi_state->uniqueid, '@')) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                         strncmp(mailbox, mwi_state->uniqueid, at - mwi_state->uniqueid) == 0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+                         strcmp(context, at + 1) == 0)</span><br><span>                       ) {</span><br><span style="color: hsl(0, 100%, 40%);">-                             poll_subscribed_mailbox(mwi_sub);</span><br><span style="color: hsl(0, 100%, 40%);">-                       }</span><br><span style="color: hsl(120, 100%, 40%);">+                     poll_subscribed_mailbox(mwi_state, NULL);</span><br><span>            }</span><br><span>    }</span><br><span style="color: hsl(0, 100%, 40%);">-       AST_RWLIST_UNLOCK(&mwi_subs);</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%);">+static int manager_voicemail_refresh(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_mwi_state_callback_all(manager_match_mailbox, (void *)m);</span><br><span>        astman_send_ack(s, m, "Refresh sent");</span><br><span>     return RESULT_SUCCESS;</span><br><span> }</span><br><span>@@ -13943,7 +13812,7 @@</span><br><span>        strcpy(listen_control_stop_key, DEFAULT_LISTEN_CONTROL_STOP_KEY);</span><br><span> </span><br><span> #ifdef IMAP_STORAGE</span><br><span style="color: hsl(0, 100%, 40%);">-    imap_close_subscribed_mailboxes();</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);</span><br><span> #endif</span><br><span> </span><br><span>       /* Free all the users structure */</span><br><span>@@ -15326,7 +15195,7 @@</span><br><span>         ast_unload_realtime("voicemail_data");</span><br><span> </span><br><span> #ifdef IMAP_STORAGE</span><br><span style="color: hsl(0, 100%, 40%);">-     imap_close_subscribed_mailboxes();</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_mwi_state_callback_all(imap_close_subscribed_mailbox, NULL);</span><br><span> #endif</span><br><span>   free_vm_users();</span><br><span>     free_vm_zones();</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/11466">change 11466</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/c/asterisk/+/11466"/><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-Change-Id: Ie89fedaca81ea1fd03d150d9d3a1ef3d53740e46 </div>
<div style="display:none"> Gerrit-Change-Number: 11466 </div>
<div style="display:none"> Gerrit-PatchSet: 7 </div>
<div style="display:none"> Gerrit-Owner: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>