Asterisk - The Open Source Telephony Project  21.4.1
Functions
media_cache.h File Reference

An in-memory media cache. More...

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

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:

1 int res;
2 
3 res = ast_media_cache_create_or_update("http://localhost/foo.wav",
4  "/tmp/foo.wav", NULL);
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.

References 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_strdupa, ast_bucket_file::created, ast_bucket_file::modified, ast_variable::name, ast_variable::next, OBJ_NOLOCK, OBJ_SEARCH_KEY, ast_bucket_file::path, SCOPED_AO2LOCK, and ast_variable::value.

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. */
302  ao2_unlink_flags(media_cache, bucket_file, OBJ_NOLOCK);
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  }
340  media_cache_item_sync_to_astdb(bucket_file);
341 
342  ao2_link_flags(media_cache, bucket_file, OBJ_NOLOCK);
343  ao2_ref(bucket_file, -1);
344  return 0;
345 }
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:1101
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:1063
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
struct ast_bucket_file * ast_bucket_file_alloc(const char *uri)
Allocate a new bucket file.
Definition: bucket.c:663
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
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct ast_bucket_file * ast_bucket_file_clone(struct ast_bucket_file *file)
Clone a bucket file.
Definition: bucket.c:810
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
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
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:

1 int res;
2 
3 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 Bucket File API implementation whether or not this affects any non-local storage

Definition at line 347 of file media_cache.c.

References ao2_ref, ast_bucket_file_delete(), OBJ_SEARCH_KEY, and OBJ_UNLINK.

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);
362  media_cache_item_del_from_astdb(bucket_file);
363 
364  ao2_ref(bucket_file, -1);
365 
366  return res;
367 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
static struct ao2_container * media_cache
Definition: media_cache.c:51
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ast_bucket_file_delete(struct ast_bucket_file *file)
Delete a bucket file from backend storage.
Definition: bucket.c:844
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
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_ref, ast_bucket_file_retrieve(), and OBJ_SEARCH_KEY.

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:1101
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 ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
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.

References AO2_ALLOC_OPT_LOCK_MUTEX, AO2_BUCKETS, ao2_container_alloc_hash, ast_cli_register_multiple, ast_register_cleanup(), ast_sorcery_object_id_compare(), and ast_sorcery_object_id_hash().

672 {
673  ast_register_cleanup(media_cache_shutdown);
674 
677  if (!media_cache) {
678  return -1;
679  }
680 
681  if (ast_cli_register_multiple(cli_media_cache, ARRAY_LEN(cli_media_cache))) {
682  return -1;
683  }
684 
685  media_cache_populate_from_astdb();
686 
687  return 0;
688 }
#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:2464
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
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)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2475
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:

1 char media[PATH_MAX];
2 int res;
3 
4 res = ast_media_cache_retrieve("http://localhost/foo.wav", NULL,
5  media, sizeof(media));

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.

References 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(), OBJ_NOLOCK, OBJ_SEARCH_KEY, and ast_bucket_file::path.

Referenced by fileexists_test().

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 
167  ao2_lock(media_cache);
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);
185  ao2_unlock(media_cache);
186  return 0;
187  }
188 
189  /* Stale! Remove the item completely, as we're going to replace it next */
190  ao2_unlink_flags(media_cache, bucket_file, OBJ_NOLOCK);
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  */
197  ao2_unlock(media_cache);
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 */
209  ao2_lock(media_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);
219  ao2_unlock(media_cache);
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);
227  media_cache_item_sync_to_astdb(bucket_file);
228  ast_copy_string(file_path, bucket_file->path, len);
229  if ((ext = strrchr(file_path, '.'))) {
230  *ext = '\0';
231  }
232  ao2_link_flags(media_cache, bucket_file, OBJ_NOLOCK);
233  ao2_ref(bucket_file, -1);
234 
235  ast_debug(5, "Returning media at local file: %s\n", file_path);
236  ao2_unlock(media_cache);
237 
238  return 0;
239 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
Definition: utils.c:3107
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:1063
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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
#define ast_debug(level,...)
Log a DEBUG message.
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
char path[PATH_MAX]
Local path to this file.
Definition: bucket.h:95
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:

1 int res;
2 char file_size[32];
3 
4 res = ast_media_cache_retrieve_metadata("http://localhost/foo.wav", "size",
5  file_size, sizeof(file_size));

Definition at line 241 of file media_cache.c.

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

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 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
static struct ao2_container * media_cache
Definition: media_cache.c:51
const char * value
Value of the attribute.
Definition: bucket.h:51
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Bucket file structure, contains reference to file and information about it.
Definition: bucket.h:78
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
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425