Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Functions
media_cache.h File Reference

An in-memory media cache. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int ast_media_cache_create_or_update (const char *uri, const char *file_path, struct ast_variable *metadata)
 Create/update a cached media item. More...
 
int ast_media_cache_delete (const char *uri)
 Remove an item from the media cache. More...
 
int ast_media_cache_exists (const char *uri)
 Check if an item exists in the cache. More...
 
int ast_media_cache_init (void)
 Initialize the media cache. More...
 
int ast_media_cache_retrieve (const char *uri, const char *preferred_file_name, char *file_path, size_t len)
 Retrieve an item from the cache. More...
 
int ast_media_cache_retrieve_metadata (const char *uri, const char *key, char *value, size_t len)
 Retrieve metadata from an item in the cache. More...
 

Detailed Description

An in-memory media cache.

Definition in file media_cache.h.

Function Documentation

◆ ast_media_cache_create_or_update()

int ast_media_cache_create_or_update ( const char *  uri,
const char *  file_path,
struct ast_variable metadata 
)

Create/update a cached media item.

Parameters
uriThe unique URI for the media item to store in the cache
file_pathFull path to the media file to be cached
metadataMetadata to store with the cached item
Return values
0The item was cached
-1An error occurred when creating/updating the item

Example Usage:

int res;
res = ast_media_cache_create_or_update("http://localhost/foo.wav",
"/tmp/foo.wav", NULL);
int ast_media_cache_create_or_update(const char *uri, const char *file_path, struct ast_variable *metadata)
Create/update a cached media item.
Definition: media_cache.c:268
#define NULL
Definition: resample.c:96
Note
This method will overwrite whatever has been provided by the Bucket File API backend.

While ast_media_cache_retrieve is used to retrieve media from some Bucket File API provider, this method allows for overwriting what is provided by a backend with some local media. This is useful for reconstructing or otherwise associating local media with a remote URI, deferring updating of the media from the backend to some later retrieval.

Definition at line 268 of file media_cache.c.

270{
271 struct ast_bucket_file *bucket_file;
272 struct ast_variable *it_metadata;
273 struct stat st;
274 char tmp[128];
275 char *ext;
276 char *file_path_ptr;
277 int created = 0;
278 SCOPED_AO2LOCK(media_lock, media_cache);
279
280 if (ast_strlen_zero(file_path) || ast_strlen_zero(uri)) {
281 return -1;
282 }
283 file_path_ptr = ast_strdupa(file_path);
284
285 if (stat(file_path, &st)) {
286 ast_log(LOG_WARNING, "Unable to obtain information for file %s for URI %s\n",
287 file_path, uri);
288 return -1;
289 }
290
291 bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_NOLOCK);
292 if (bucket_file) {
293 struct ast_bucket_file *clone;
294
295 clone = ast_bucket_file_clone(bucket_file);
296 if (!clone) {
297 ao2_ref(bucket_file, -1);
298 return -1;
299 }
300
301 /* Remove the old bucket_file. We'll replace it if we succeed below. */
303 ao2_ref(bucket_file, -1);
304
305 bucket_file = clone;
306 } else {
307 bucket_file = ast_bucket_file_alloc(uri);
308 if (!bucket_file) {
309 ast_log(LOG_WARNING, "Failed to create file storage for %s and %s\n",
310 uri, file_path);
311 return -1;
312 }
313 created = 1;
314 }
315
316 strcpy(bucket_file->path, file_path);
317 bucket_file->created.tv_sec = st.st_ctime;
318 bucket_file->modified.tv_sec = st.st_mtime;
319
320 snprintf(tmp, sizeof(tmp), "%ld", (long)st.st_atime);
321 ast_bucket_file_metadata_set(bucket_file, "accessed", tmp);
322
323 snprintf(tmp, sizeof(tmp), "%jd", (intmax_t)st.st_size);
324 ast_bucket_file_metadata_set(bucket_file, "size", tmp);
325
326 ext = strrchr(file_path_ptr, '.');
327 if (ext) {
328 ast_bucket_file_metadata_set(bucket_file, "ext", ext + 1);
329 }
330
331 for (it_metadata = metadata; it_metadata; it_metadata = it_metadata->next) {
332 ast_bucket_file_metadata_set(bucket_file, it_metadata->name, it_metadata->value);
333 }
334
335 if (created && ast_bucket_file_create(bucket_file)) {
336 ast_log(LOG_WARNING, "Failed to create media for %s\n", uri);
337 ao2_ref(bucket_file, -1);
338 return -1;
339 }
341
343 ao2_ref(bucket_file, -1);
344 return 0;
345}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
static int tmp()
Definition: bt_open.c:389
struct ast_bucket_file * ast_bucket_file_clone(struct ast_bucket_file *file)
Clone a bucket file.
Definition: bucket.c:810
int ast_bucket_file_metadata_set(struct ast_bucket_file *file, const char *name, const char *value)
Set a metadata attribute on a file to a specific value.
Definition: bucket.c:334
struct ast_bucket_file * ast_bucket_file_alloc(const char *uri)
Allocate a new bucket file.
Definition: bucket.c:663
int ast_bucket_file_create(struct ast_bucket_file *file)
Create a new bucket file in backend storage.
Definition: bucket.c:725
const char * ext
Definition: http.c:150
#define LOG_WARNING
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
static struct ao2_container * media_cache
Definition: media_cache.c:51
static void media_cache_item_sync_to_astdb(struct ast_bucket_file *bucket_file)
Definition: media_cache.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
struct timeval modified
When this file was last modified.
Definition: bucket.h:91
struct timeval created
When this file was created.
Definition: bucket.h:89
struct ao2_container * metadata
Container of metadata attributes about file.
Definition: bucket.h:93
char path[PATH_MAX]
Local path to this file.
Definition: bucket.h:95
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References ao2_find, ao2_link_flags, ao2_ref, ao2_unlink_flags, ast_bucket_file_alloc(), ast_bucket_file_clone(), ast_bucket_file_create(), ast_bucket_file_metadata_set(), ast_log, ast_strdupa, ast_strlen_zero(), ast_bucket_file::created, ext, LOG_WARNING, media_cache, media_cache_item_sync_to_astdb(), ast_bucket_file::metadata, ast_bucket_file::modified, ast_variable::name, ast_variable::next, OBJ_NOLOCK, OBJ_SEARCH_KEY, ast_bucket_file::path, SCOPED_AO2LOCK, tmp(), and ast_variable::value.

Referenced by AST_TEST_DEFINE(), and media_cache_handle_create_item().

◆ ast_media_cache_delete()

int ast_media_cache_delete ( const char *  uri)

Remove an item from the media cache.

Parameters
uriThe unique URI for the media item to store in the cache
Return values
0success
-1error

Example Usage:

int res;
res = ast_media_cache_delete("http://localhost/foo.wav");
int ast_media_cache_delete(const char *uri)
Remove an item from the media cache.
Definition: media_cache.c:347

This removes an item completely from the media cache. Any files local on disk associated with the item are deleted as well.

Note
It is up to the Bucket File API implementation whether or not this affects any non-local storage

Definition at line 347 of file media_cache.c.

348{
349 struct ast_bucket_file *bucket_file;
350 int res;
351
352 if (ast_strlen_zero(uri)) {
353 return -1;
354 }
355
356 bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_UNLINK);
357 if (!bucket_file) {
358 return -1;
359 }
360
361 res = ast_bucket_file_delete(bucket_file);
363
364 ao2_ref(bucket_file, -1);
365
366 return res;
367}
@ OBJ_UNLINK
Definition: astobj2.h:1039
int ast_bucket_file_delete(struct ast_bucket_file *file)
Delete a bucket file from backend storage.
Definition: bucket.c:844
static void media_cache_item_del_from_astdb(struct ast_bucket_file *bucket_file)
Definition: media_cache.c:114

References ao2_find, ao2_ref, ast_bucket_file_delete(), ast_strlen_zero(), media_cache, media_cache_item_del_from_astdb(), OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by media_cache_handle_delete_item().

◆ ast_media_cache_exists()

int ast_media_cache_exists ( const char *  uri)

Check if an item exists in the cache.

Parameters
uriThe unique URI for the media item
Return values
0uri does not exist in cache
1uri does exist in cache

Definition at line 53 of file media_cache.c.

54{
55 struct ast_bucket_file *bucket_file;
56
57 if (ast_strlen_zero(uri)) {
58 return 0;
59 }
60
61 bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY);
62 if (bucket_file) {
63 ao2_ref(bucket_file, -1);
64 return 1;
65 }
66
67 /* Check to see if any bucket implementation could return this item */
68 bucket_file = ast_bucket_file_retrieve(uri);
69 if (bucket_file) {
70 ao2_ref(bucket_file, -1);
71 return 1;
72 }
73
74 return 0;
75}
struct ast_bucket_file * ast_bucket_file_retrieve(const char *uri)
Retrieve a bucket file.
Definition: bucket.c:815

References ao2_find, ao2_ref, ast_bucket_file_retrieve(), ast_strlen_zero(), media_cache, and OBJ_SEARCH_KEY.

Referenced by AST_TEST_DEFINE().

◆ ast_media_cache_init()

int ast_media_cache_init ( void  )

Initialize the media cache.

Note
This should only be called once, during Asterisk initialization
Return values
0success
-1error

Definition at line 671 of file media_cache.c.

672{
674
677 if (!media_cache) {
678 return -1;
679 }
680
682 return -1;
683 }
684
686
687 return 0;
688}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void media_cache_populate_from_astdb(void)
Definition: media_cache.c:443
static void media_cache_shutdown(void)
Definition: media_cache.c:663
static struct ast_cli_entry cli_media_cache[]
Definition: media_cache.c:651
#define AO2_BUCKETS
Definition: media_cache.c:48
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2459
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2470
#define ARRAY_LEN(a)
Definition: utils.h:666

References AO2_ALLOC_OPT_LOCK_MUTEX, AO2_BUCKETS, ao2_container_alloc_hash, ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), ast_sorcery_object_id_compare(), ast_sorcery_object_id_hash(), cli_media_cache, media_cache, media_cache_populate_from_astdb(), media_cache_shutdown(), and NULL.

Referenced by asterisk_daemon().

◆ ast_media_cache_retrieve()

int ast_media_cache_retrieve ( const char *  uri,
const char *  preferred_file_name,
char *  file_path,
size_t  len 
)

Retrieve an item from the cache.

Parameters
uriThe unique URI for the media item
preferred_file_nameThe preferred name for the file storing the media once it is retrieved. Can be NULL.
file_pathBuffer to store the full path to the media in the cache
lenThe length of the buffer pointed to by file_path
Return values
0The item was retrieved successfully
-1The item could not be retrieved

Example Usage:

char media[PATH_MAX];
int res;
res = ast_media_cache_retrieve("http://localhost/foo.wav", NULL,
media, sizeof(media));
#define PATH_MAX
Definition: asterisk.h:40
int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name, char *file_path, size_t len)
Retrieve an item from the cache.
Definition: media_cache.c:157

Retrieving an item will cause the Bucket File API Bucket backend associated with the URI scheme in uri to be queried. If the Bucket backend does not require an update, the cached information is used to find the file associated with uri, and file_path is populated with the location of the media file associated with uri.

If the item is not in the cache, the item will be retrieved using the Bucket File API backend. When this occurs, if preferred_file_name is given, it will be used as the destination file for the retrieval. When retrieval of the media from the backend is complete, file_path is then populated as before.

Definition at line 157 of file media_cache.c.

159{
160 struct ast_bucket_file *bucket_file;
161 struct ast_bucket_file *tmp_bucket_file;
162 char *ext;
163 if (ast_strlen_zero(uri)) {
164 return -1;
165 }
166
168 ast_debug(5, "Looking for media at local cache, file: %s\n", uri);
169
170 /* First, retrieve from the ao2 cache here. If we find a bucket_file
171 * matching the requested URI, ask the appropriate backend if it is
172 * stale. If not; return it.
173 */
174 bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_NOLOCK);
175 if (bucket_file) {
176 if (!ast_bucket_file_is_stale(bucket_file)
177 && ast_file_is_readable(bucket_file->path)) {
178 ast_copy_string(file_path, bucket_file->path, len);
179 if ((ext = strrchr(file_path, '.'))) {
180 *ext = '\0';
181 }
182 ao2_ref(bucket_file, -1);
183
184 ast_debug(5, "Returning media at local file: %s\n", file_path);
186 return 0;
187 }
188
189 /* Stale! Remove the item completely, as we're going to replace it next */
191 ast_bucket_file_delete(bucket_file);
192 ao2_ref(bucket_file, -1);
193 }
194 /* We unlock to retrieve the file, because it can take a long time;
195 * and we don't want to lock access to cached files while waiting
196 */
198
199 /* Either this is new or the resource is stale; do a full retrieve
200 * from the appropriate bucket_file backend
201 */
202 bucket_file = ast_bucket_file_retrieve(uri);
203 if (!bucket_file) {
204 ast_debug(2, "Failed to obtain media at '%s'\n", uri);
205 return -1;
206 }
207
208 /* we lock again, before updating cache */
210
211 /* We can have duplicated buckets here, we check if already exists
212 * before saving
213 */
214 tmp_bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_NOLOCK);
215 if (tmp_bucket_file) {
216 ao2_ref(tmp_bucket_file, -1);
217 ast_bucket_file_delete(bucket_file);
218 ao2_ref(bucket_file, -1);
220 return 0;
221 }
222
223 /* We can manipulate the 'immutable' bucket_file here, as we haven't
224 * let anyone know of its existence yet
225 */
226 bucket_file_update_path(bucket_file, preferred_file_name);
228 ast_copy_string(file_path, bucket_file->path, len);
229 if ((ext = strrchr(file_path, '.'))) {
230 *ext = '\0';
231 }
233 ao2_ref(bucket_file, -1);
234
235 ast_debug(5, "Returning media at local file: %s\n", file_path);
237
238 return 0;
239}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
int ast_bucket_file_is_stale(struct ast_bucket_file *file)
Retrieve whether or not the backing datastore views the bucket file as stale.
Definition: bucket.c:824
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_debug(level,...)
Log a DEBUG message.
static void bucket_file_update_path(struct ast_bucket_file *bucket_file, const char *preferred_file_name)
Definition: media_cache.c:133
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: utils.c:3107

References ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ast_bucket_file_delete(), ast_bucket_file_is_stale(), ast_bucket_file_retrieve(), ast_copy_string(), ast_debug, ast_file_is_readable(), ast_strlen_zero(), bucket_file_update_path(), ext, len(), media_cache, media_cache_item_sync_to_astdb(), OBJ_NOLOCK, OBJ_SEARCH_KEY, and ast_bucket_file::path.

Referenced by AST_TEST_DEFINE(), fileexists_test(), and media_cache_handle_refresh_item().

◆ ast_media_cache_retrieve_metadata()

int ast_media_cache_retrieve_metadata ( const char *  uri,
const char *  key,
char *  value,
size_t  len 
)

Retrieve metadata from an item in the cache.

Parameters
uriThe unique URI for the media item
keyThe key of the metadata to retrieve
valueBuffer to store the value in
lenThe length of the buffer pointed to by value
Return values
0The metadata was retrieved successfully
-1The metadata could not be retrieved

Example Usage:

int res;
char file_size[32];
res = ast_media_cache_retrieve_metadata("http://localhost/foo.wav", "size",
file_size, sizeof(file_size));
int ast_media_cache_retrieve_metadata(const char *uri, const char *key, char *value, size_t len)
Retrieve metadata from an item in the cache.
Definition: media_cache.c:241

Definition at line 241 of file media_cache.c.

243{
244 struct ast_bucket_file *bucket_file;
245 struct ast_bucket_metadata *metadata;
246
247 if (ast_strlen_zero(uri) || ast_strlen_zero(key) || !value) {
248 return -1;
249 }
250
251 bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY);
252 if (!bucket_file) {
253 return -1;
254 }
255
256 metadata = ao2_find(bucket_file->metadata, key, OBJ_SEARCH_KEY);
257 if (!metadata) {
258 ao2_ref(bucket_file, -1);
259 return -1;
260 }
261 ast_copy_string(value, metadata->value, len);
262
263 ao2_ref(metadata, -1);
264 ao2_ref(bucket_file, -1);
265 return 0;
266}
Bucket metadata structure, AO2 key value pair.
Definition: bucket.h:47
const char * value
Value of the attribute.
Definition: bucket.h:51
int value
Definition: syslog.c:37

References ao2_find, ao2_ref, ast_copy_string(), ast_strlen_zero(), len(), media_cache, ast_bucket_file::metadata, OBJ_SEARCH_KEY, ast_bucket_metadata::value, and value.

Referenced by AST_TEST_DEFINE().