]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
media_cache: Don't lock when curl the remote file
authorAndre Barbosa <andre.emanuel.barbosa@gmail.com>
Thu, 5 Aug 2021 16:55:33 +0000 (17:55 +0100)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Fri, 20 Aug 2021 14:36:32 +0000 (09:36 -0500)
When playing a remote sound file, which is not in cache, first we need
to download it with ast_bucket_file_retrieve.

This can take a while if the remote host is slow. The current CURL
timeout is 180secs, so in extreme situations, it can take 3 minutes to
return.

Because ast_media_cache_retrieve has a lock on all function, while we
are waiting for the delayed download, Asterisk is not able to play any
more files, even the files already cached locally.

ASTERISK-29544 #close

Change-Id: I8d4142b463ae4a1d4c41bff2bf63324821567408

main/media_cache.c

index 1899fb453f943a324fe773f076d24bb303a0bea8..7e1cbe3762dda97caf4181f91a17d96f55790faf 100644 (file)
@@ -157,13 +157,15 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name,
        char *file_path, size_t len)
 {
        struct ast_bucket_file *bucket_file;
+       struct ast_bucket_file *tmp_bucket_file;
        char *ext;
-       SCOPED_AO2LOCK(media_lock, media_cache);
-
        if (ast_strlen_zero(uri)) {
                return -1;
        }
 
+       ao2_lock(media_cache);
+       ast_debug(5, "Looking for media at local cache, file: %s\n", uri);
+
        /* First, retrieve from the ao2 cache here. If we find a bucket_file
         * matching the requested URI, ask the appropriate backend if it is
         * stale. If not; return it.
@@ -179,6 +181,7 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name,
                        ao2_ref(bucket_file, -1);
 
                        ast_debug(5, "Returning media at local file: %s\n", file_path);
+                       ao2_unlock(media_cache);
                        return 0;
                }
 
@@ -187,6 +190,10 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name,
                ast_bucket_file_delete(bucket_file);
                ao2_ref(bucket_file, -1);
        }
+       /* We unlock to retrieve the file, because it can take a long time;
+        * and we don't want to lock access to cached files while waiting
+        */
+       ao2_unlock(media_cache);
 
        /* Either this is new or the resource is stale; do a full retrieve
         * from the appropriate bucket_file backend
@@ -197,6 +204,21 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name,
                return -1;
        }
 
+       /* we lock again, before updating cache */
+       ao2_lock(media_cache);
+
+       /* We can have duplicated buckets here, we check if already exists
+        * before saving
+        */
+       tmp_bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_NOLOCK);
+       if (tmp_bucket_file) {
+               ao2_ref(tmp_bucket_file, -1);
+               ast_bucket_file_delete(bucket_file);
+               ao2_ref(bucket_file, -1);
+               ao2_unlock(media_cache);
+               return 0;
+       }
+
        /* We can manipulate the 'immutable' bucket_file here, as we haven't
         * let anyone know of its existence yet
         */
@@ -210,6 +232,7 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name,
        ao2_ref(bucket_file, -1);
 
        ast_debug(5, "Returning media at local file: %s\n", file_path);
+       ao2_unlock(media_cache);
 
        return 0;
 }