Asterisk - The Open Source Telephony Project  18.5.0
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);
Note
This method will overwrite whatever has been provided by the AstBucket Bucket File API backend.

While ast_media_cache_retrieve is used to retrieve media from some AstBucket 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 285 of file media_cache.c.

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_item_sync_to_astdb(), 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().

287 {
288  struct ast_bucket_file *bucket_file;
289  struct ast_variable *it_metadata;
290  struct stat st;
291  char tmp[128];
292  char *ext;
293  char *file_path_ptr;
294  int created = 0;
295  SCOPED_AO2LOCK(media_lock, media_cache);
296 
297  if (ast_strlen_zero(file_path) || ast_strlen_zero(uri)) {
298  return -1;
299  }
300  file_path_ptr = ast_strdupa(file_path);
301 
302  if (stat(file_path, &st)) {
303  ast_log(LOG_WARNING, "Unable to obtain information for file %s for URI %s\n",
304  file_path, uri);
305  return -1;
306  }
307 
308  bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_NOLOCK);
309  if (bucket_file) {
310  struct ast_bucket_file *clone;
311 
312  clone = ast_bucket_file_clone(bucket_file);
313  if (!clone) {
314  ao2_ref(bucket_file, -1);
315  return -1;
316  }
317 
318  /* Remove the old bucket_file. We'll replace it if we succeed below. */
319  ao2_unlink_flags(media_cache, bucket_file, OBJ_NOLOCK);
320  ao2_ref(bucket_file, -1);
321 
322  bucket_file = clone;
323  } else {
324  bucket_file = ast_bucket_file_alloc(uri);
325  if (!bucket_file) {
326  ast_log(LOG_WARNING, "Failed to create file storage for %s and %s\n",
327  uri, file_path);
328  return -1;
329  }
330  created = 1;
331  }
332 
333  strcpy(bucket_file->path, file_path);
334  bucket_file->created.tv_sec = st.st_ctime;
335  bucket_file->modified.tv_sec = st.st_mtime;
336 
337  snprintf(tmp, sizeof(tmp), "%ld", (long)st.st_atime);
338  ast_bucket_file_metadata_set(bucket_file, "accessed", tmp);
339 
340  snprintf(tmp, sizeof(tmp), "%jd", (intmax_t)st.st_size);
341  ast_bucket_file_metadata_set(bucket_file, "size", tmp);
342 
343  ext = strrchr(file_path_ptr, '.');
344  if (ext) {
345  ast_bucket_file_metadata_set(bucket_file, "ext", ext + 1);
346  }
347 
348  for (it_metadata = metadata; it_metadata; it_metadata = it_metadata->next) {
349  ast_bucket_file_metadata_set(bucket_file, it_metadata->name, it_metadata->value);
350  }
351 
352  if (created && ast_bucket_file_create(bucket_file)) {
353  ast_log(LOG_WARNING, "Failed to create media for %s\n", uri);
354  ao2_ref(bucket_file, -1);
355  return -1;
356  }
357  media_cache_item_sync_to_astdb(bucket_file);
358 
359  ao2_link_flags(media_cache, bucket_file, OBJ_NOLOCK);
360  ao2_ref(bucket_file, -1);
361  return 0;
362 }
struct ast_variable * next
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
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
static struct ao2_container * media_cache
Definition: media_cache.c:51
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
struct ast_bucket_file * ast_bucket_file_alloc(const char *uri)
Allocate a new bucket file.
Definition: bucket.c:663
const char * ext
Definition: http.c:147
struct timeval modified
When this file was last modified.
Definition: bucket.h:91
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct timeval created
When this file was created.
Definition: bucket.h:89
#define ast_log
Definition: astobj2.c:42
struct ast_bucket_file * ast_bucket_file_clone(struct ast_bucket_file *file)
Clone a bucket file.
Definition: bucket.c:810
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
static void media_cache_item_sync_to_astdb(struct ast_bucket_file *bucket_file)
Definition: media_cache.c:96
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
char path[PATH_MAX]
Local path to this file.
Definition: bucket.h:95
int ast_bucket_file_create(struct ast_bucket_file *file)
Create a new bucket file in backend storage.
Definition: bucket.c:725

◆ 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");

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 AstBucket Bucket File API implementation whether or not this affects any non-local storage

Definition at line 364 of file media_cache.c.

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

Referenced by media_cache_handle_delete_item().

365 {
366  struct ast_bucket_file *bucket_file;
367  int res;
368 
369  if (ast_strlen_zero(uri)) {
370  return -1;
371  }
372 
373  bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_UNLINK);
374  if (!bucket_file) {
375  return -1;
376  }
377 
378  res = ast_bucket_file_delete(bucket_file);
379  media_cache_item_del_from_astdb(bucket_file);
380 
381  ao2_ref(bucket_file, -1);
382 
383  return res;
384 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static struct ao2_container * media_cache
Definition: media_cache.c:51
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ 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.

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

Referenced by AST_TEST_DEFINE().

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 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct ast_bucket_file * ast_bucket_file_retrieve(const char *uri)
Retrieve a bucket file.
Definition: bucket.c:815
static struct ao2_container * media_cache
Definition: media_cache.c:51
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ 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 688 of file media_cache.c.

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(), media_cache_populate_from_astdb(), media_cache_shutdown(), and NULL.

Referenced by asterisk_daemon().

689 {
691 
694  if (!media_cache) {
695  return -1;
696  }
697 
699  return -1;
700  }
701 
703 
704  return 0;
705 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#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
static struct ao2_container * media_cache
Definition: media_cache.c:51
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry cli_media_cache[]
Definition: media_cache.c:668
static void media_cache_shutdown(void)
Definition: media_cache.c:680
#define NULL
Definition: resample.c:96
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2470
static void media_cache_populate_from_astdb(void)
Definition: media_cache.c:460

◆ 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));

Retrieving an item will cause the AstBucket 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 AstBucket 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 197 of file media_cache.c.

References ao2_find, ao2_link_flags, ao2_ref, ao2_unlink_flags, 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, media_cache_item_sync_to_astdb(), OBJ_NOLOCK, OBJ_SEARCH_KEY, ast_bucket_file::path, and SCOPED_AO2LOCK.

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

199 {
200  struct ast_bucket_file *bucket_file;
201  char *ext;
202  SCOPED_AO2LOCK(media_lock, media_cache);
203 
204  if (ast_strlen_zero(uri)) {
205  return -1;
206  }
207 
208  /* First, retrieve from the ao2 cache here. If we find a bucket_file
209  * matching the requested URI, ask the appropriate backend if it is
210  * stale. If not; return it.
211  */
212  bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY | OBJ_NOLOCK);
213  if (bucket_file) {
214  if (!ast_bucket_file_is_stale(bucket_file)
215  && ast_file_is_readable(bucket_file->path)) {
216  ast_copy_string(file_path, bucket_file->path, len);
217  if ((ext = strrchr(file_path, '.'))) {
218  *ext = '\0';
219  }
220  ao2_ref(bucket_file, -1);
221 
222  ast_debug(5, "Returning media at local file: %s\n", file_path);
223  return 0;
224  }
225 
226  /* Stale! Remove the item completely, as we're going to replace it next */
227  ao2_unlink_flags(media_cache, bucket_file, OBJ_NOLOCK);
228  ast_bucket_file_delete(bucket_file);
229  ao2_ref(bucket_file, -1);
230  }
231 
232  /* Either this is new or the resource is stale; do a full retrieve
233  * from the appropriate bucket_file backend
234  */
235  bucket_file = ast_bucket_file_retrieve(uri);
236  if (!bucket_file) {
237  ast_debug(2, "Failed to obtain media at '%s'\n", uri);
238  return -1;
239  }
240 
241  /* We can manipulate the 'immutable' bucket_file here, as we haven't
242  * let anyone know of its existence yet
243  */
244  bucket_file_update_path(bucket_file, preferred_file_name);
245  media_cache_item_sync_to_astdb(bucket_file);
246  ast_copy_string(file_path, bucket_file->path, len);
247  if ((ext = strrchr(file_path, '.'))) {
248  *ext = '\0';
249  }
250  ao2_link_flags(media_cache, bucket_file, OBJ_NOLOCK);
251  ao2_ref(bucket_file, -1);
252 
253  ast_debug(5, "Returning media at local file: %s\n", file_path);
254 
255  return 0;
256 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static void bucket_file_update_path(struct ast_bucket_file *bucket_file, const char *preferred_file_name)
Definition: media_cache.c:150
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: main/utils.c:2855
struct ast_bucket_file * ast_bucket_file_retrieve(const char *uri)
Retrieve a bucket file.
Definition: bucket.c:815
static struct ao2_container * media_cache
Definition: media_cache.c:51
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
const char * ext
Definition: http.c:147
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_bucket_file_delete(struct ast_bucket_file *file)
Delete a bucket file from backend storage.
Definition: bucket.c:844
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
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
static void media_cache_item_sync_to_astdb(struct ast_bucket_file *bucket_file)
Definition: media_cache.c:96
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
char path[PATH_MAX]
Local path to this file.
Definition: bucket.h:95

◆ 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));

Definition at line 258 of file media_cache.c.

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

Referenced by AST_TEST_DEFINE().

260 {
261  struct ast_bucket_file *bucket_file;
262  struct ast_bucket_metadata *metadata;
263 
264  if (ast_strlen_zero(uri) || ast_strlen_zero(key) || !value) {
265  return -1;
266  }
267 
268  bucket_file = ao2_find(media_cache, uri, OBJ_SEARCH_KEY);
269  if (!bucket_file) {
270  return -1;
271  }
272 
273  metadata = ao2_find(bucket_file->metadata, key, OBJ_SEARCH_KEY);
274  if (!metadata) {
275  ao2_ref(bucket_file, -1);
276  return -1;
277  }
278  ast_copy_string(value, metadata->value, len);
279 
280  ao2_ref(metadata, -1);
281  ao2_ref(bucket_file, -1);
282  return 0;
283 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static struct ao2_container * media_cache
Definition: media_cache.c:51
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * value
Value of the attribute.
Definition: bucket.h:51
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ao2_container * metadata
Container of metadata attributes about file.
Definition: bucket.h:93
Bucket metadata structure, AO2 key value pair.
Definition: bucket.h:47
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401