<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10922">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">media_index.c: Refactored so it doesn't cache the index<br><br>Testing revealed that the cache added no benefit but that it could<br>consume excessive memory.<br><br>Two new index related functions were created:<br>ast_sounds_get_index_for_file() and ast_media_index_update_for_file()<br>which restrict index updating to specific sound files.<br><br>The original ast_sounds_get_index() and ast_media_index_update()<br>calls are still available but since they no longer cache the results<br>internally, developers should re-use an index they may already have<br>instead of calling ast_sounds_get_index() repeatedly.  If information<br>for only a single file is needed, ast_sounds_get_index_for_file()<br>should be called instead of ast_sounds_get_index().<br><br>The media_index directory scan code was elimininated in favor of<br>using the existing ast_file_read_dirs() function.<br><br>Since there's no more cache, ast_sounds_index_init now only<br>registers the sounds cli commands instead of generating the<br>initial index and subscribing to stasis format register/unregister<br>messages.<br><br>ast_sounds_reindex() is now a no-op but left for backwards<br>compatibility.<br><br>loader.c no longer registers "sounds" as a special reload target.<br><br>Both the sounds cli commands and the sounds ari resources were<br>refactored to only call ast_sounds_get_index() once per invocation<br>and to use ast_sounds_get_index_for_file() when a specific sound<br>file is requested.<br><br>Change-Id: I1cef327ba1b0648d85d218b70ce469ad07f4aa8d<br>---<br>M CHANGES<br>M include/asterisk/media_index.h<br>M include/asterisk/sounds_index.h<br>M main/loader.c<br>M main/media_index.c<br>M main/sounds.c<br>M res/ari/resource_sounds.c<br>7 files changed, 279 insertions(+), 207 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/22/10922/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/CHANGES b/CHANGES</span><br><span>index da58f29..5cd3d4c 100644</span><br><span>--- a/CHANGES</span><br><span>+++ b/CHANGES</span><br><span>@@ -17,6 +17,19 @@</span><br><span>  * Added "send_contact_status_on_update_registration" global configuration option</span><br><span>    to enable sending AMI ContactStatus event when a device refreshes its registration.</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+Core</span><br><span style="color: hsl(120, 100%, 40%);">+------------------</span><br><span style="color: hsl(120, 100%, 40%);">+ * Reworked the media indexer so it doesn't cache the index.  Testing revealed</span><br><span style="color: hsl(120, 100%, 40%);">+   that the cache added no benefit but that it could consume excessive memory.</span><br><span style="color: hsl(120, 100%, 40%);">+   Two new index related functions were created: ast_sounds_get_index_for_file()</span><br><span style="color: hsl(120, 100%, 40%);">+   and ast_media_index_update_for_file() which restrict index updating to</span><br><span style="color: hsl(120, 100%, 40%);">+   specific sound files.  The original ast_sounds_get_index() and</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_media_index_update() calls are still available but since they no longer</span><br><span style="color: hsl(120, 100%, 40%);">+   cache the results internally, developers should re-use an index they may</span><br><span style="color: hsl(120, 100%, 40%);">+   already have instead of calling ast_sounds_get_index() repeatedly.  If</span><br><span style="color: hsl(120, 100%, 40%);">+   information for only a single file is needed, ast_sounds_get_index_for_file()</span><br><span style="color: hsl(120, 100%, 40%);">+   should be called instead of ast_sounds_get_index().</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> Features</span><br><span> ------------------</span><br><span>  * Before Asterisk 12, when using the automon or automixmon features defined</span><br><span>diff --git a/include/asterisk/media_index.h b/include/asterisk/media_index.h</span><br><span>index 40fb721..f3a95a6 100644</span><br><span>--- a/include/asterisk/media_index.h</span><br><span>+++ b/include/asterisk/media_index.h</span><br><span>@@ -101,6 +101,26 @@</span><br><span>  */</span><br><span> int ast_media_index_update(struct ast_media_index *index,</span><br><span>       const char *variant);</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%);">+ * \brief Update a media index for a specific sound file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.25.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param index Media index in which to query information</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param variant Media variant for which to get the description</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param filename Sound file name without extension</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note If filename is NULL, this function will act as</span><br><span style="color: hsl(120, 100%, 40%);">+ * \ref ast_media_index_update and add all sound files to the index.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval non-zero on error</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return zero on success</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_media_index_update_for_file(struct ast_media_index *index,</span><br><span style="color: hsl(120, 100%, 40%);">+      const char *variant, const char *filename);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #if defined(__cplusplus) || defined(c_plusplus)</span><br><span> }</span><br><span> #endif</span><br><span>diff --git a/include/asterisk/sounds_index.h b/include/asterisk/sounds_index.h</span><br><span>index d7eb053..dad54a0 100644</span><br><span>--- a/include/asterisk/sounds_index.h</span><br><span>+++ b/include/asterisk/sounds_index.h</span><br><span>@@ -34,9 +34,11 @@</span><br><span> </span><br><span> /*!</span><br><span>  * \brief Reload the sounds index</span><br><span style="color: hsl(120, 100%, 40%);">+ * \deprecated</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval zero on success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval non-zero on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function is a NoOp and will be removed in a future release.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval zero</span><br><span>  */</span><br><span> int ast_sounds_reindex(void);</span><br><span> </span><br><span>@@ -48,6 +50,19 @@</span><br><span>  */</span><br><span> struct ast_media_index *ast_sounds_get_index(void);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get the index for a specific sound file</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.25.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param filename Sound file name without extension</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval sounds index (must be ao2_cleanup()'ed)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval NULL on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_media_index *ast_sounds_get_index_for_file(const char *filename);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #if defined(__cplusplus) || defined(c_plusplus)</span><br><span> }</span><br><span> #endif</span><br><span>diff --git a/main/loader.c b/main/loader.c</span><br><span>index ff6b282..da8fcf2 100644</span><br><span>--- a/main/loader.c</span><br><span>+++ b/main/loader.c</span><br><span>@@ -56,7 +56,6 @@</span><br><span> #include "asterisk/vector.h"</span><br><span> #include "asterisk/app.h"</span><br><span> #include "asterisk/test.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/sounds_index.h"</span><br><span> #include "asterisk/cli.h"</span><br><span> </span><br><span> #include <dlfcn.h></span><br><span>@@ -376,7 +375,6 @@</span><br><span>      { "logger",      logger_reload },</span><br><span>  { "manager",     reload_manager },</span><br><span>         { "plc",         ast_plc_reload },</span><br><span style="color: hsl(0, 100%, 40%);">-    { "sounds",      ast_sounds_reindex },</span><br><span>     { "udptl",       ast_udptl_reload },</span><br><span>       { NULL,          NULL }</span><br><span> };</span><br><span>diff --git a/main/media_index.c b/main/media_index.c</span><br><span>index 2d1bc6b..67396e7 100644</span><br><span>--- a/main/media_index.c</span><br><span>+++ b/main/media_index.c</span><br><span>@@ -380,7 +380,8 @@</span><br><span> static int process_description_file(struct ast_media_index *index,</span><br><span>       const char *subdir,</span><br><span>  const char *variant_str,</span><br><span style="color: hsl(0, 100%, 40%);">-        const char *filename)</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *filename,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *match_filename)</span><br><span> {</span><br><span>     RAII_VAR(struct ast_str *, description_file_path, ast_str_create(64), ast_free);</span><br><span>     RAII_VAR(struct ast_str *, cumulative_description, ast_str_create(64), ast_free);</span><br><span>@@ -450,16 +451,21 @@</span><br><span>                    if (file_id_persist && !ast_strlen_zero(ast_str_buffer(cumulative_description))) {</span><br><span>                           struct media_variant *variant;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                              variant = alloc_variant(index, file_id_persist, variant_str);</span><br><span style="color: hsl(0, 100%, 40%);">-                           if (!variant) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                 res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                                /*</span><br><span style="color: hsl(120, 100%, 40%);">+                             * If we were only searching for a specific sound filename</span><br><span style="color: hsl(120, 100%, 40%);">+                             * don't include others.</span><br><span style="color: hsl(120, 100%, 40%);">+                           */</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (ast_strlen_zero(match_filename) || strcmp(match_filename, file_id_persist) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        variant = alloc_variant(index, file_id_persist, variant_str);</span><br><span style="color: hsl(120, 100%, 40%);">+                                 if (!variant) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                               res = -1;</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%);">+                                     ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));</span><br><span style="color: hsl(120, 100%, 40%);">+                                   ao2_ref(variant, -1);</span><br><span>                                }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>                          ast_str_reset(cumulative_description);</span><br><span style="color: hsl(0, 100%, 40%);">-                          ao2_ref(variant, -1);</span><br><span>                        }</span><br><span> </span><br><span>                        ast_free(file_id_persist);</span><br><span>@@ -473,12 +479,18 @@</span><br><span>   if (file_id_persist && !ast_strlen_zero(ast_str_buffer(cumulative_description))) {</span><br><span>           struct media_variant *variant;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-              variant = alloc_variant(index, file_id_persist, variant_str);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (variant) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));</span><br><span style="color: hsl(0, 100%, 40%);">-                     ao2_ref(variant, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-           } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        res = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+             /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If we were only searching for a specific sound filename</span><br><span style="color: hsl(120, 100%, 40%);">+             * don't include others.</span><br><span style="color: hsl(120, 100%, 40%);">+           */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ast_strlen_zero(match_filename) || strcmp(match_filename, file_id_persist) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        variant = alloc_variant(index, file_id_persist, variant_str);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (variant) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                ast_string_field_set(variant, description, ast_str_buffer(cumulative_description));</span><br><span style="color: hsl(120, 100%, 40%);">+                           ao2_ref(variant, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                 } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              res = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span>            }</span><br><span>    }</span><br><span> </span><br><span>@@ -487,110 +499,121 @@</span><br><span>      return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief process an individual file listing */</span><br><span style="color: hsl(0, 100%, 40%);">-static int process_file(struct ast_media_index *index, const char *variant_str, const char *subdir, const char *filename)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  RAII_VAR(char *, filename_stripped, ast_strdup(filename), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-    char *ext;</span><br><span style="color: hsl(120, 100%, 40%);">+struct read_dirs_data {</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *search_filename;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t search_filename_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *search_variant;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_media_index *index;</span><br><span style="color: hsl(120, 100%, 40%);">+        size_t dirname_len;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!filename_stripped) {</span><br><span style="color: hsl(0, 100%, 40%);">-               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+static int read_dirs_cb(const char *dir_name, const char *filename, void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct read_dirs_data *data = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+    char *ext;</span><br><span style="color: hsl(120, 100%, 40%);">+    size_t match_len;</span><br><span style="color: hsl(120, 100%, 40%);">+     char *match;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t match_base_len;</span><br><span style="color: hsl(120, 100%, 40%);">+        char *subdirs = (char *)dir_name + data->dirname_len;</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%);">+     * Example:</span><br><span style="color: hsl(120, 100%, 40%);">+    * From the filesystem:</span><br><span style="color: hsl(120, 100%, 40%);">+        *        index's base_dir = "/var/lib/asterisk/sounds"</span><br><span style="color: hsl(120, 100%, 40%);">+  *        search_variant = "en"</span><br><span style="color: hsl(120, 100%, 40%);">+      *        search directory base = "/var/lib/asterisk/sounds/en"</span><br><span style="color: hsl(120, 100%, 40%);">+      *        dirname_len = 27</span><br><span style="color: hsl(120, 100%, 40%);">+     *    current dir_name = "/var/lib/asterisk/sounds/en/digits"</span><br><span style="color: hsl(120, 100%, 40%);">+        *    subdirs =                                     "/digits"</span><br><span style="color: hsl(120, 100%, 40%);">+        *    filename = "1.ulaw"</span><br><span style="color: hsl(120, 100%, 40%);">+    *</span><br><span style="color: hsl(120, 100%, 40%);">+     * From the search criteria:</span><br><span style="color: hsl(120, 100%, 40%);">+   *    search_filename = "digits/1"</span><br><span style="color: hsl(120, 100%, 40%);">+   *    search_filename_len = 8</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%);">+ if (*subdirs == '/') {</span><br><span style="color: hsl(120, 100%, 40%);">+                subdirs++;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ext = strrchr(filename_stripped, '.');</span><br><span style="color: hsl(120, 100%, 40%);">+        /* subdirs = "digits" */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  match_len = strlen(subdirs) + strlen(filename) + 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   match = ast_alloca(match_len);</span><br><span style="color: hsl(120, 100%, 40%);">+        snprintf(match, match_len, "%s%s%s", subdirs,</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_strlen_zero(subdirs) ? "" : "/", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* match = discovered filename relative to language = "digits/1.ulaw" */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  ext = strrchr(match, '.');</span><br><span>   if (!ext) {</span><br><span style="color: hsl(0, 100%, 40%);">-             /* file has no extension */</span><br><span>          return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   *ext++ = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!strcmp(ext, "txt")) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (process_description_file(index, subdir, variant_str, filename)) {</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%);">-       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (process_media_file(index, variant_str, subdir, filename_stripped, ext)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* ext = ".ulaw" */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (data->search_filename_len > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            match_base_len = ext - match;</span><br><span style="color: hsl(120, 100%, 40%);">+         /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * match_base_len = length of "digits/1" = 8 which</span><br><span style="color: hsl(120, 100%, 40%);">+           * happens to match the length of search_filename.</span><br><span style="color: hsl(120, 100%, 40%);">+             * However if the discovered filename was 11.ulaw</span><br><span style="color: hsl(120, 100%, 40%);">+              * it would be length of "digits/11" = 9.</span><br><span style="color: hsl(120, 100%, 40%);">+            * We need to use the larger during the compare to</span><br><span style="color: hsl(120, 100%, 40%);">+             * make sure we don't match just search_filename</span><br><span style="color: hsl(120, 100%, 40%);">+           * as a substring of the discovered filename.</span><br><span style="color: hsl(120, 100%, 40%);">+          */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (data->search_filename_len > match_base_len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       match_base_len = data->search_filename_len;</span><br><span>               }</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* We always process txt files because they should contain description. */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (strcmp(ext, ".txt") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (process_description_file(data->index, NULL, data->search_variant,</span><br><span style="color: hsl(120, 100%, 40%);">+                   match, data->search_filename)) {</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%);">+     } else if (data->search_filename_len == 0</span><br><span style="color: hsl(120, 100%, 40%);">+          || strncmp(data->search_filename, match, match_base_len      ) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             *ext = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+          ext++;</span><br><span style="color: hsl(120, 100%, 40%);">+                process_media_file(data->index, data->search_variant, NULL, match, ext);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief internal function for updating the index, recursive */</span><br><span style="color: hsl(0, 100%, 40%);">-static int media_index_update(struct ast_media_index *index,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *variant,</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *subdir)</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_media_index_update_for_file(struct ast_media_index *index,</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *variant, const char *filename)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct dirent* dent;</span><br><span style="color: hsl(0, 100%, 40%);">-    DIR* srcdir;</span><br><span style="color: hsl(0, 100%, 40%);">-    RAII_VAR(struct ast_str *, index_dir, ast_str_create(64), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-    RAII_VAR(struct ast_str *, statfile, ast_str_create(64), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-     int res = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct timeval start;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timeval end;</span><br><span style="color: hsl(120, 100%, 40%);">+   int64_t elapsed;</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       size_t dirname_len = strlen(index->base_dir) + strlen(S_OR(variant, "")) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct read_dirs_data data = {</span><br><span style="color: hsl(120, 100%, 40%);">+                .search_filename = S_OR(filename, ""),</span><br><span style="color: hsl(120, 100%, 40%);">+              .search_filename_len = strlen(S_OR(filename, "")),</span><br><span style="color: hsl(120, 100%, 40%);">+          .search_variant = S_OR(variant, ""),</span><br><span style="color: hsl(120, 100%, 40%);">+                .index = index,</span><br><span style="color: hsl(120, 100%, 40%);">+               .dirname_len = dirname_len,</span><br><span style="color: hsl(120, 100%, 40%);">+   };</span><br><span style="color: hsl(120, 100%, 40%);">+    char *search_dir = ast_alloca(dirname_len + 1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!index_dir) {</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%);">+     sprintf(search_dir, "%s%s%s", index->base_dir, ast_strlen_zero(variant) ? "" : "/",</span><br><span style="color: hsl(120, 100%, 40%);">+          data.search_variant);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       ast_str_set(&index_dir, 0, "%s", index->base_dir);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!ast_strlen_zero(variant)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_str_append(&index_dir, 0, "/%s", variant);</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!ast_strlen_zero(subdir)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_str_append(&index_dir, 0, "/%s", subdir);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(120, 100%, 40%);">+     gettimeofday(&start, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = ast_file_read_dirs(search_dir, read_dirs_cb, &data, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+     gettimeofday(&end, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ elapsed = ast_tvdiff_us(end, start);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_debug(1, "Media for language '%s' indexed in %8.6f seconds\n", data.search_variant, elapsed / 1E6);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   srcdir = opendir(ast_str_buffer(index_dir));</span><br><span style="color: hsl(0, 100%, 40%);">-    if (srcdir == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(LOG_ERROR, "Failed to open %s: %s\n", ast_str_buffer(index_dir), strerror(errno));</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       while((dent = readdir(srcdir)) != NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-               struct stat st;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       continue;</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_str_reset(statfile);</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_str_set(&statfile, 0, "%s/%s", ast_str_buffer(index_dir), dent->d_name);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-           if (stat(ast_str_buffer(statfile), &st) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   ast_log(LOG_WARNING, "Failed to stat %s: %s\n", ast_str_buffer(statfile), strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">-                   continue;</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 (S_ISDIR(st.st_mode)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      if (ast_strlen_zero(subdir)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                          res = media_index_update(index, variant, dent->d_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                      } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                RAII_VAR(struct ast_str *, new_subdir, ast_str_create(64), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_str_set(&new_subdir, 0, "%s/%s", subdir, dent->d_name);</span><br><span style="color: hsl(0, 100%, 40%);">-                            res = media_index_update(index, variant, ast_str_buffer(new_subdir));</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 (res) {</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%);">-                       continue;</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 (!S_ISREG(st.st_mode)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     continue;</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 (process_file(index, variant, subdir, dent->d_name)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    res = -1;</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%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       closedir(srcdir);</span><br><span style="color: hsl(0, 100%, 40%);">-       return res;</span><br><span style="color: hsl(120, 100%, 40%);">+   return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int ast_media_index_update(struct ast_media_index *index,</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *variant)</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_media_index_update(struct ast_media_index *index, const char *variant)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       return media_index_update(index, variant, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      return ast_media_index_update_for_file(index, variant, NULL);</span><br><span> }</span><br><span>diff --git a/main/sounds.c b/main/sounds.c</span><br><span>index 6fec48e..c3666ed 100644</span><br><span>--- a/main/sounds.c</span><br><span>+++ b/main/sounds.c</span><br><span>@@ -45,10 +45,6 @@</span><br><span> /*! \brief The number of buckets to be used for storing language-keyed objects */</span><br><span> #define LANGUAGE_BUCKETS 7</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_media_index *sounds_index;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct stasis_message_router *sounds_system_router;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /*! \brief Get the languages in which sound files are available */</span><br><span> static struct ao2_container *get_languages(void)</span><br><span> {</span><br><span>@@ -97,52 +93,8 @@</span><br><span>    return lang_dirs;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Callback to process an individual language directory or subdirectory */</span><br><span style="color: hsl(0, 100%, 40%);">-static int update_index_cb(void *obj, void *arg, int flags)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        char *lang = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_media_index *index = arg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ast_media_index_update(index, lang)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              return CMP_MATCH;</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(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-AST_MUTEX_DEFINE_STATIC(reload_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int ast_sounds_reindex(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    RAII_VAR(struct ast_str *, sounds_dir, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ao2_container *, languages, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(char *, failed_index, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-      RAII_VAR(struct ast_media_index *, new_index, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_media_index *old_index;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      SCOPED_MUTEX(lock, &reload_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   old_index = sounds_index;</span><br><span style="color: hsl(0, 100%, 40%);">-       languages = get_languages();</span><br><span style="color: hsl(0, 100%, 40%);">-    sounds_dir = ast_str_create(64);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!languages || !sounds_dir) {</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_str_set(&sounds_dir, 0, "%s/sounds", ast_config_AST_DATA_DIR);</span><br><span style="color: hsl(0, 100%, 40%);">-        new_index = ast_media_index_create(ast_str_buffer(sounds_dir));</span><br><span style="color: hsl(0, 100%, 40%);">- if (!new_index) {</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       failed_index = ao2_callback(languages, 0, update_index_cb, new_index);</span><br><span style="color: hsl(0, 100%, 40%);">-  if (failed_index) {</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ao2_ref(new_index, +1);</span><br><span style="color: hsl(0, 100%, 40%);">- sounds_index = new_index;</span><br><span style="color: hsl(0, 100%, 40%);">-       ao2_cleanup(old_index);</span><br><span>      return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -154,13 +106,13 @@</span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int show_sound_info_cb(void *obj, void *arg, int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+static int show_sound_info_cb(void *obj, void *arg, void *data, int flags)</span><br><span> {</span><br><span>    char *language = obj;</span><br><span>        struct ast_cli_args *a = arg;</span><br><span>        struct ast_format *format;</span><br><span>   int formats_shown = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  RAII_VAR(struct ast_media_index *, local_index, ast_sounds_get_index(), ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_media_index *local_index = data;</span><br><span>  struct ast_format_cap *cap;</span><br><span>  const char *description = ast_media_get_description(local_index, a->argv[3], language);</span><br><span> </span><br><span>@@ -203,13 +155,23 @@</span><br><span>       }</span><br><span> </span><br><span>        if (a->argc == 3) {</span><br><span style="color: hsl(0, 100%, 40%);">-          RAII_VAR(struct ao2_container *, sound_files, ast_media_get_media(sounds_index), ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+                struct ast_media_index *sounds_index = ast_sounds_get_index();</span><br><span style="color: hsl(120, 100%, 40%);">+                struct ao2_container *sound_files;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!sounds_index) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  return CLI_FAILURE;</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%);">+           sound_files = ast_media_get_media(sounds_index);</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_ref(sounds_index, -1);</span><br><span>           if (!sound_files) {</span><br><span>                  return CLI_FAILURE;</span><br><span>          }</span><br><span> </span><br><span>                ast_cli(a->fd, "Available audio files:\n");</span><br><span>             ao2_callback(sound_files, OBJ_MULTIPLE | OBJ_NODATA, show_sounds_cb, a);</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_ref(sound_files, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          return CLI_SUCCESS;</span><br><span>  }</span><br><span> </span><br><span>@@ -222,6 +184,7 @@</span><br><span>  int length;</span><br><span>  struct ao2_iterator it_sounds;</span><br><span>       char *filename;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_media_index *sounds_index;</span><br><span>        struct ao2_container *sound_files;</span><br><span> </span><br><span>       switch (cmd) {</span><br><span>@@ -236,7 +199,13 @@</span><br><span>                        return NULL;</span><br><span>                 }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         sounds_index = ast_sounds_get_index();</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!sounds_index) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          sound_files = ast_media_get_media(sounds_index);</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_ref(sounds_index, -1);</span><br><span>           if (!sound_files) {</span><br><span>                  return NULL;</span><br><span>                 }</span><br><span>@@ -259,14 +228,26 @@</span><br><span>    }</span><br><span> </span><br><span>        if (a->argc == 4) {</span><br><span style="color: hsl(0, 100%, 40%);">-          RAII_VAR(struct ao2_container *, variants, ast_media_get_variants(sounds_index, a->argv[3]), ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+         struct ao2_container *variants;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             sounds_index = ast_sounds_get_index_for_file(a->argv[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!sounds_index) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  return NULL;</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%);">+           variants = ast_media_get_variants(sounds_index, a->argv[3]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>            if (!variants || !ao2_container_count(variants)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    ao2_ref(sounds_index, -1);</span><br><span>                   ast_cli(a->fd, "ERROR: File %s not found in index\n", a->argv[3]);</span><br><span>                   return CLI_FAILURE;</span><br><span>          }</span><br><span> </span><br><span>                ast_cli(a->fd, "Indexed Information for %s:\n", a->argv[3]);</span><br><span style="color: hsl(0, 100%, 40%);">-            ao2_callback(variants, OBJ_MULTIPLE | OBJ_NODATA, show_sound_info_cb, a);</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_callback_data(variants, OBJ_MULTIPLE | OBJ_NODATA, show_sound_info_cb, a, sounds_index);</span><br><span style="color: hsl(120, 100%, 40%);">+          ao2_ref(sounds_index, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+            ao2_ref(variants, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>             return CLI_SUCCESS;</span><br><span>  }</span><br><span> </span><br><span>@@ -281,60 +262,72 @@</span><br><span> </span><br><span> static void sounds_cleanup(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      stasis_message_router_unsubscribe_and_join(sounds_system_router);</span><br><span style="color: hsl(0, 100%, 40%);">-       sounds_system_router = NULL;</span><br><span>         ast_cli_unregister_multiple(cli_sounds, ARRAY_LEN(cli_sounds));</span><br><span style="color: hsl(0, 100%, 40%);">- ao2_cleanup(sounds_index);</span><br><span style="color: hsl(0, 100%, 40%);">-      sounds_index = 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%);">-static void format_update_cb(void *data, struct stasis_subscription *sub,</span><br><span style="color: hsl(0, 100%, 40%);">-  struct stasis_message *message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        /* Reindexing during shutdown is pointless. */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!ast_shutting_down()) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_sounds_reindex();</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span> }</span><br><span> </span><br><span> int ast_sounds_index_init(void)</span><br><span> {</span><br><span>   int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ast_sounds_reindex()) {</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%);">-       res |= ast_cli_register_multiple(cli_sounds, ARRAY_LEN(cli_sounds));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        sounds_system_router = stasis_message_router_create(ast_system_topic());</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!sounds_system_router) {</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%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_format_register_type()) {</span><br><span style="color: hsl(0, 100%, 40%);">-               res |= stasis_message_router_add(</span><br><span style="color: hsl(0, 100%, 40%);">-                       sounds_system_router,</span><br><span style="color: hsl(0, 100%, 40%);">-                   ast_format_register_type(),</span><br><span style="color: hsl(0, 100%, 40%);">-                     format_update_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-                       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%);">-       if (ast_format_unregister_type()) {</span><br><span style="color: hsl(0, 100%, 40%);">-             res |= stasis_message_router_add(</span><br><span style="color: hsl(0, 100%, 40%);">-                       sounds_system_router,</span><br><span style="color: hsl(0, 100%, 40%);">-                   ast_format_unregister_type(),</span><br><span style="color: hsl(0, 100%, 40%);">-                   format_update_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-                       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(120, 100%, 40%);">+     res = ast_cli_register_multiple(cli_sounds, ARRAY_LEN(cli_sounds));</span><br><span>  if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            return 1;</span><br><span>    }</span><br><span> </span><br><span>        ast_register_cleanup(sounds_cleanup);</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Callback to process an individual language directory or subdirectory */</span><br><span style="color: hsl(120, 100%, 40%);">+static int update_index_cb(void *obj, void *arg, void *data, int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *lang = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+     char *filename = data;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_media_index *index = arg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ast_media_index_update_for_file(index, lang, filename)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return CMP_MATCH;</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> struct ast_media_index *ast_sounds_get_index(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       return ao2_bump(sounds_index);</span><br><span style="color: hsl(120, 100%, 40%);">+        return ast_sounds_get_index_for_file(NULL);</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%);">+struct ast_media_index *ast_sounds_get_index_for_file(const char *filename)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_str *sounds_dir = ast_str_create(64);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ao2_container *languages;</span><br><span style="color: hsl(120, 100%, 40%);">+      char *failed_index;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_media_index *new_index;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!sounds_dir) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return NULL;</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%);">+   ast_str_set(&sounds_dir, 0, "%s/sounds", ast_config_AST_DATA_DIR);</span><br><span style="color: hsl(120, 100%, 40%);">+      new_index = ast_media_index_create(ast_str_buffer(sounds_dir));</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_free(sounds_dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!new_index) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</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%);">+   languages = get_languages();</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!languages) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_ref(new_index, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</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%);">+   failed_index = ao2_callback_data(languages, 0, update_index_cb, new_index, (void *)filename);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(languages, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (failed_index) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ao2_ref(new_index, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+               new_index = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_cleanup(failed_index);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return new_index;</span><br><span> }</span><br><span>diff --git a/res/ari/resource_sounds.c b/res/ari/resource_sounds.c</span><br><span>index 76a4d94..0f52a22 100644</span><br><span>--- a/res/ari/resource_sounds.c</span><br><span>+++ b/res/ari/resource_sounds.c</span><br><span>@@ -42,13 +42,13 @@</span><br><span> };</span><br><span> </span><br><span> /*! \brief Add format/lang pairs to the array embedded in the sound object */</span><br><span style="color: hsl(0, 100%, 40%);">-static int add_format_information_cb(void *obj, void *arg, int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+static int add_format_information_cb(void *obj, void *arg, void *data, int flags)</span><br><span> {</span><br><span>        char *language = obj;</span><br><span>        struct lang_format_info *args = arg;</span><br><span>         int idx;</span><br><span>     RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-      RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_media_index *sounds_index = data;</span><br><span> </span><br><span>     if (!sounds_index) {</span><br><span>                 return CMP_STOP;</span><br><span>@@ -97,14 +97,13 @@</span><br><span> </span><br><span> /*! \brief Generate a Sound structure as documented in sounds.json for the specified filename */</span><br><span> static struct ast_json *create_sound_blob(const char *filename,</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_ari_sounds_list_args *args)</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_ari_sounds_list_args *args, struct ast_media_index *sounds_index)</span><br><span> {</span><br><span>    RAII_VAR(struct ast_json *, sound, NULL, ast_json_unref);</span><br><span>    RAII_VAR(struct ao2_container *, languages, NULL, ao2_cleanup);</span><br><span>      const char *description;</span><br><span>     struct ast_json *format_lang_list;</span><br><span>   struct lang_format_info info;</span><br><span style="color: hsl(0, 100%, 40%);">-   RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);</span><br><span> </span><br><span>   if (!sounds_index) {</span><br><span>                 return NULL;</span><br><span>@@ -150,7 +149,7 @@</span><br><span>   if (args) {</span><br><span>          info.format_filter = args->format;</span><br><span>        }</span><br><span style="color: hsl(0, 100%, 40%);">-       ao2_callback(languages, OBJ_NODATA, add_format_information_cb, &info);</span><br><span style="color: hsl(120, 100%, 40%);">+    ao2_callback_data(languages, OBJ_NODATA, add_format_information_cb, &info, sounds_index);</span><br><span> </span><br><span>    /* no format/lang pairs for this sound so nothing to return */</span><br><span>       if (!ast_json_array_size(format_lang_list)) {</span><br><span>@@ -160,13 +159,18 @@</span><br><span>        return ast_json_ref(sound);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct sounds_cb_data {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_ari_sounds_list_args *args;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_media_index *index;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Generate a Sound structure and append it to the output blob */</span><br><span> static int append_sound_cb(void *obj, void *arg, void *data, int flags)</span><br><span> {</span><br><span>    struct ast_json *sounds_array = arg;</span><br><span>         char *filename = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_ari_sounds_list_args *args = data;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_json *sound_blob = create_sound_blob(filename, args);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct sounds_cb_data *cb_data = data;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_json *sound_blob = create_sound_blob(filename, cb_data->args, cb_data->index);</span><br><span>      if (!sound_blob) {</span><br><span>           return 0;</span><br><span>    }</span><br><span>@@ -182,6 +186,10 @@</span><br><span>     RAII_VAR(struct ao2_container *, sound_files, NULL, ao2_cleanup);</span><br><span>    struct ast_json *sounds_blob;</span><br><span>        RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+        struct sounds_cb_data cb_data = {</span><br><span style="color: hsl(120, 100%, 40%);">+             .args = args,</span><br><span style="color: hsl(120, 100%, 40%);">+         .index = sounds_index,</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span> </span><br><span>       if (!sounds_index) {</span><br><span>                 ast_ari_response_error(response, 500, "Internal Error", "Sounds index not available");</span><br><span>@@ -200,7 +208,7 @@</span><br><span>             return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ao2_callback_data(sound_files, OBJ_NODATA, append_sound_cb, sounds_blob, args);</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_callback_data(sound_files, OBJ_NODATA, append_sound_cb, sounds_blob, &cb_data);</span><br><span> </span><br><span>  if (!ast_json_array_size(sounds_blob)) {</span><br><span>             ast_ari_response_error(response, 404, "Not Found", "No sounds found that matched the query");</span><br><span>@@ -216,8 +224,10 @@</span><br><span>     struct ast_ari_response *response)</span><br><span> {</span><br><span>      struct ast_json *sound_blob;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_media_index *sounds_index = ast_sounds_get_index_for_file(args->sound_id);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    sound_blob = create_sound_blob(args->sound_id, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      sound_blob = create_sound_blob(args->sound_id, NULL, sounds_index);</span><br><span style="color: hsl(120, 100%, 40%);">+        ao2_cleanup(sounds_index);</span><br><span>   if (!sound_blob) {</span><br><span>           ast_ari_response_error(response, 404, "Not Found", "Sound not found");</span><br><span>           return;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10922">change 10922</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/10922"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I1cef327ba1b0648d85d218b70ce469ad07f4aa8d </div>
<div style="display:none"> Gerrit-Change-Number: 10922 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>