Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Macros | Functions | Variables
media_cache.c File Reference

An in-memory media cache. More...

#include "asterisk.h"
#include <sys/stat.h>
#include "asterisk/config.h"
#include "asterisk/bucket.h"
#include "asterisk/astdb.h"
#include "asterisk/cli.h"
#include "asterisk/file.h"
#include "asterisk/media_cache.h"
Include dependency graph for media_cache.c:

Go to the source code of this file.

Macros

#define AO2_BUCKETS   61
 
#define AST_DB_FAMILY   "MediaCache"
 
#define AST_DB_FAMILY_LEN   12
 
#define FORMAT_ROW   "%-40s\n\t%-40s\n"
 
#define FORMAT_ROW   "\t%20s: %-40.40s\n"
 

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...
 
static void bucket_file_update_path (struct ast_bucket_file *bucket_file, const char *preferred_file_name)
 
static char * cli_complete_uri (const char *word)
 
static char * media_cache_handle_create_item (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * media_cache_handle_delete_item (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * media_cache_handle_refresh_item (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * media_cache_handle_show_all (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * media_cache_handle_show_item (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void media_cache_item_del_from_astdb (struct ast_bucket_file *bucket_file)
 
static int media_cache_item_populate_from_astdb (const char *uri, const char *hash)
 
static void media_cache_item_sync_to_astdb (struct ast_bucket_file *bucket_file)
 
static void media_cache_populate_from_astdb (void)
 
static int media_cache_prnt_summary (void *obj, void *arg, int flags)
 
static void media_cache_remove_from_astdb (const char *uri, const char *hash)
 
static void media_cache_shutdown (void)
 
static int metadata_sync_to_astdb (void *obj, void *arg, int flags)
 

Variables

static struct ast_cli_entry cli_media_cache []
 
static struct ao2_containermedia_cache
 

Detailed Description

An in-memory media cache.

Author
Matt Jordan <mjordan@digium.com> 

Definition in file media_cache.c.

Macro Definition Documentation

◆ AO2_BUCKETS

#define AO2_BUCKETS   61

Number of buckets in the ao2 container holding our media items

Definition at line 48 of file media_cache.c.

◆ AST_DB_FAMILY

#define AST_DB_FAMILY   "MediaCache"

The name of the AstDB family holding items in the cache.

Definition at line 42 of file media_cache.c.

◆ AST_DB_FAMILY_LEN

#define AST_DB_FAMILY_LEN   12

Length of 'MediaCache' + 2 '/' characters

Definition at line 45 of file media_cache.c.

◆ FORMAT_ROW [1/2]

#define FORMAT_ROW   "%-40s\n\t%-40s\n"

◆ FORMAT_ROW [2/2]

#define FORMAT_ROW   "\t%20s: %-40.40s\n"

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

◆ bucket_file_update_path()

static void bucket_file_update_path ( struct ast_bucket_file bucket_file,
const char *  preferred_file_name 
)
static

Definition at line 133 of file media_cache.c.

135{
136 if (!ast_strlen_zero(preferred_file_name) && strcmp(bucket_file->path, preferred_file_name)) {
137 /* Use the preferred file name if available */
138 rename(bucket_file->path, preferred_file_name);
139 ast_copy_string(bucket_file->path, preferred_file_name,
140 sizeof(bucket_file->path));
141 } else if (!strchr(bucket_file->path, '.')) {
142 struct ast_bucket_metadata *ext =
143 ast_bucket_file_metadata_get(bucket_file, "ext");
144
145 if (ext) {
146 char *new_path;
147 if (ast_asprintf(&new_path, "%s%s", bucket_file->path, ext->value) != -1) {
148 rename(bucket_file->path, new_path);
149 ast_copy_string(bucket_file->path, new_path, sizeof(bucket_file->path));
150 ast_free(new_path);
151 }
152 ao2_ref(ext, -1);
153 }
154 }
155}
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
struct ast_bucket_metadata * ast_bucket_file_metadata_get(struct ast_bucket_file *file, const char *name)
Retrieve a metadata attribute from a file.
Definition: bucket.c:359

References ao2_ref, ast_asprintf, ast_bucket_file_metadata_get(), ast_copy_string(), ast_free, ast_strlen_zero(), ext, and ast_bucket_file::path.

Referenced by ast_media_cache_retrieve().

◆ cli_complete_uri()

static char * cli_complete_uri ( const char *  word)
static

Definition at line 501 of file media_cache.c.

502{
503 struct ast_bucket_file *bucket_file;
504 struct ao2_iterator it_media_items;
505 int wordlen = strlen(word);
506
507 it_media_items = ao2_iterator_init(media_cache, 0);
508 while ((bucket_file = ao2_iterator_next(&it_media_items))) {
509 if (!strncasecmp(word, ast_sorcery_object_get_id(bucket_file), wordlen)) {
511 }
512 ao2_ref(bucket_file, -1);
513 }
514 ao2_iterator_destroy(&it_media_items);
515
516 return NULL;
517}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2758
short word
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_completion_add(), ast_sorcery_object_get_id(), ast_strdup, media_cache, and NULL.

Referenced by media_cache_handle_delete_item(), media_cache_handle_refresh_item(), and media_cache_handle_show_item().

◆ media_cache_handle_create_item()

static char * media_cache_handle_create_item ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 622 of file media_cache.c.

623{
624 switch (cmd) {
625 case CLI_INIT:
626 e->command = "media cache create";
627 e->usage =
628 "Usage: media cache create <uri> <file>\n"
629 " Create an item in the media cache by associating a local media file with\n"
630 " some URI.\n";
631 return NULL;
632 case CLI_GENERATE:
633 return NULL;
634 }
635
636 if (a->argc != 5) {
637 return CLI_SHOWUSAGE;
638 }
639
640 if (ast_media_cache_create_or_update(a->argv[3], a->argv[4], NULL)) {
641 ast_cli(a->fd, "Unable to create '%s' associated with local file '%s'\n",
642 a->argv[3], a->argv[4]);
643 } else {
644 ast_cli(a->fd, "Created '%s' for '%s' in the media cache\n",
645 a->argv[3], a->argv[4]);
646 }
647
648 return CLI_SUCCESS;
649}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
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
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ast_cli(), ast_media_cache_create_or_update(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ media_cache_handle_delete_item()

static char * media_cache_handle_delete_item ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 563 of file media_cache.c.

564{
565 switch (cmd) {
566 case CLI_INIT:
567 e->command = "media cache delete";
568 e->usage =
569 "Usage: media cache delete <uri>\n"
570 " Delete an item from the media cache.\n\n"
571 " Note that this will also remove any local storage of the media associated\n"
572 " with the URI, and will inform the backend supporting the URI scheme that\n"
573 " it should remove the item.\n";
574 return NULL;
575 case CLI_GENERATE:
576 return a->pos == e->args ? cli_complete_uri(a->word) : NULL;
577 }
578
579 if (a->argc != 4) {
580 return CLI_SHOWUSAGE;
581 }
582
583 if (ast_media_cache_delete(a->argv[3])) {
584 ast_cli(a->fd, "Unable to delete '%s'\n", a->argv[3]);
585 } else {
586 ast_cli(a->fd, "Deleted '%s' from the media cache\n", a->argv[3]);
587 }
588
589 return CLI_SUCCESS;
590}
static char * cli_complete_uri(const char *word)
Definition: media_cache.c:501
int ast_media_cache_delete(const char *uri)
Remove an item from the media cache.
Definition: media_cache.c:347
int args
This gets set in ast_cli_register()
Definition: cli.h:185

References a, ast_cli_entry::args, ast_cli(), ast_media_cache_delete(), cli_complete_uri(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ media_cache_handle_refresh_item()

static char * media_cache_handle_refresh_item ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 592 of file media_cache.c.

593{
594 char file_path[PATH_MAX];
595
596 switch (cmd) {
597 case CLI_INIT:
598 e->command = "media cache refresh";
599 e->usage =
600 "Usage: media cache refresh <uri>\n"
601 " Ask for a refresh of a particular URI.\n\n"
602 " If the item does not already exist in the media cache, the item will be\n"
603 " populated from the backend supporting the URI scheme.\n";
604 return NULL;
605 case CLI_GENERATE:
606 return a->pos == e->args ? cli_complete_uri(a->word) : NULL;
607 }
608
609 if (a->argc != 4) {
610 return CLI_SHOWUSAGE;
611 }
612
613 if (ast_media_cache_retrieve(a->argv[3], NULL, file_path, sizeof(file_path))) {
614 ast_cli(a->fd, "Unable to refresh '%s'\n", a->argv[3]);
615 } else {
616 ast_cli(a->fd, "Refreshed '%s' to local storage '%s'\n", a->argv[3], file_path);
617 }
618
619 return CLI_SUCCESS;
620}
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

References a, ast_cli_entry::args, ast_cli(), ast_media_cache_retrieve(), cli_complete_uri(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, PATH_MAX, and ast_cli_entry::usage.

◆ media_cache_handle_show_all()

static char * media_cache_handle_show_all ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 473 of file media_cache.c.

474{
475 switch (cmd) {
476 case CLI_INIT:
477 e->command = "media cache show all";
478 e->usage =
479 "Usage: media cache show all\n"
480 " Display a summary of all current items in the media cache.\n";
481 return NULL;
482 case CLI_GENERATE:
483 return NULL;
484 }
485
486 if (a->argc != 4) {
487 return CLI_SHOWUSAGE;
488 }
489
490 ast_cli(a->fd, "URI\n\tLocal File\n");
491 ast_cli(a->fd, "---------------\n");
493
494 return CLI_SUCCESS;
495}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
static int media_cache_prnt_summary(void *obj, void *arg, int flags)
Definition: media_cache.c:461

References a, ao2_callback, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, media_cache, media_cache_prnt_summary(), NULL, OBJ_MULTIPLE, OBJ_NODATA, and ast_cli_entry::usage.

◆ media_cache_handle_show_item()

static char * media_cache_handle_show_item ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 519 of file media_cache.c.

520{
521#define FORMAT_ROW "\t%20s: %-40.40s\n"
522 struct ast_bucket_file *bucket_file;
523 struct ao2_iterator it_metadata;
524 struct ast_bucket_metadata *metadata;
525
526 switch (cmd) {
527 case CLI_INIT:
528 e->command = "media cache show";
529 e->usage =
530 "Usage: media cache show <uri>\n"
531 " Display all information about a particular item in the media cache.\n";
532 return NULL;
533 case CLI_GENERATE:
534 return a->pos == e->args ? cli_complete_uri(a->word) : NULL;
535 }
536
537 if (a->argc != 4) {
538 return CLI_SHOWUSAGE;
539 }
540
541 bucket_file = ao2_find(media_cache, a->argv[3], OBJ_SEARCH_KEY);
542 if (!bucket_file) {
543 ast_cli(a->fd, "Unable to find '%s' in the media cache\n", a->argv[3]);
544 return CLI_SUCCESS;
545 }
546
547 ast_cli(a->fd, "URI: %s\n", ast_sorcery_object_get_id(bucket_file));
548 ast_cli(a->fd, "%s\n", "----------------------------------------");
549 ast_cli(a->fd, FORMAT_ROW, "Path", bucket_file->path);
550
551 it_metadata = ao2_iterator_init(bucket_file->metadata, 0);
552 while ((metadata = ao2_iterator_next(&it_metadata))) {
553 ast_cli(a->fd, FORMAT_ROW, metadata->name, metadata->value);
554 ao2_ref(metadata, -1);
555 }
556 ao2_iterator_destroy(&it_metadata);
557
558 ao2_ref(bucket_file, -1);
559#undef FORMAT_ROW
560 return CLI_SUCCESS;
561}
#define FORMAT_ROW
const char * name
Name of the attribute.
Definition: bucket.h:49

References a, ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_entry::args, ast_cli(), ast_sorcery_object_get_id(), cli_complete_uri(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, FORMAT_ROW, media_cache, ast_bucket_file::metadata, ast_bucket_metadata::name, NULL, OBJ_SEARCH_KEY, ast_bucket_file::path, ast_cli_entry::usage, and ast_bucket_metadata::value.

◆ media_cache_item_del_from_astdb()

static void media_cache_item_del_from_astdb ( struct ast_bucket_file bucket_file)
static

Definition at line 114 of file media_cache.c.

115{
116 char *hash_value;
117
118 if (ast_db_get_allocated(AST_DB_FAMILY, ast_sorcery_object_get_id(bucket_file), &hash_value)) {
119 return;
120 }
121
122 ast_db_deltree(hash_value, NULL);
124 ast_free(hash_value);
125}
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
Definition: main/db.c:437
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:476
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: main/db.c:536
#define AST_DB_FAMILY
Definition: media_cache.c:42

References ast_db_del(), ast_db_deltree(), AST_DB_FAMILY, ast_db_get_allocated(), ast_free, ast_sorcery_object_get_id(), and NULL.

Referenced by ast_media_cache_delete().

◆ media_cache_item_populate_from_astdb()

static int media_cache_item_populate_from_astdb ( const char *  uri,
const char *  hash 
)
static

Definition at line 389 of file media_cache.c.

390{
391 struct ast_bucket_file *bucket_file;
392 struct ast_db_entry *db_tree;
393 struct ast_db_entry *db_entry;
394 struct stat st;
395
396 bucket_file = ast_bucket_file_alloc(uri);
397 if (!bucket_file) {
398 return -1;
399 }
400
401 db_tree = ast_db_gettree(hash, NULL);
402 for (db_entry = db_tree; db_entry; db_entry = db_entry->next) {
403 const char *key = strchr(db_entry->key + 1, '/');
404
405 if (ast_strlen_zero(key)) {
406 continue;
407 }
408 key++;
409
410 if (!strcasecmp(key, "path")) {
411 strcpy(bucket_file->path, db_entry->data);
412
413 if (stat(bucket_file->path, &st)) {
414 ast_log(LOG_WARNING, "Unable to obtain information for file %s for URI %s\n",
415 bucket_file->path, uri);
416 ao2_ref(bucket_file, -1);
417 ast_db_freetree(db_tree);
418 return -1;
419 }
420 } else {
421 ast_bucket_file_metadata_set(bucket_file, key, db_entry->data);
422 }
423 }
424 ast_db_freetree(db_tree);
425
426 if (ast_strlen_zero(bucket_file->path)) {
427 ao2_ref(bucket_file, -1);
428 ast_log(LOG_WARNING, "Failed to restore media cache item for '%s' from AstDB: no 'path' specified\n",
429 uri);
430 return -1;
431 }
432
433 ao2_link(media_cache, bucket_file);
434 ao2_ref(bucket_file, -1);
435
436 return 0;
437}
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: main/db.c:610
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition: main/db.c:677
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
char data[0]
Definition: astdb.h:34

References ao2_link, ao2_ref, ast_bucket_file_alloc(), ast_bucket_file_metadata_set(), ast_db_freetree(), ast_db_gettree(), ast_log, ast_strlen_zero(), ast_db_entry::data, ast_db_entry::key, LOG_WARNING, media_cache, ast_db_entry::next, NULL, and ast_bucket_file::path.

Referenced by media_cache_populate_from_astdb().

◆ media_cache_item_sync_to_astdb()

static void media_cache_item_sync_to_astdb ( struct ast_bucket_file bucket_file)
static

Definition at line 96 of file media_cache.c.

97{
98 char hash[41]; /* 40 character SHA1 hash */
99
100 ast_sha1_hash(hash, ast_sorcery_object_get_id(bucket_file));
101 if (ast_db_put(AST_DB_FAMILY, ast_sorcery_object_get_id(bucket_file), hash)) {
102 return;
103 }
104
105 ast_db_put(hash, "path", bucket_file->path);
107}
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:342
void ast_bucket_file_metadata_callback(struct ast_bucket_file *file, ao2_callback_fn cb, void *arg)
Execute a callback function on the metadata associated with a file.
Definition: bucket.c:364
static int metadata_sync_to_astdb(void *obj, void *arg, int flags)
Definition: media_cache.c:81
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: utils.c:266

References ast_bucket_file_metadata_callback(), AST_DB_FAMILY, ast_db_put(), ast_sha1_hash(), ast_sorcery_object_get_id(), metadata_sync_to_astdb(), and ast_bucket_file::path.

Referenced by ast_media_cache_create_or_update(), and ast_media_cache_retrieve().

◆ media_cache_populate_from_astdb()

static void media_cache_populate_from_astdb ( void  )
static

Definition at line 443 of file media_cache.c.

444{
445 struct ast_db_entry *db_entry;
446 struct ast_db_entry *db_tree;
447
449 for (db_entry = db_tree; db_entry; db_entry = db_entry->next) {
451 media_cache_remove_from_astdb(db_entry->key, db_entry->data);
452 }
453 }
454 ast_db_freetree(db_tree);
455}
#define AST_DB_FAMILY_LEN
Definition: media_cache.c:45
static int media_cache_item_populate_from_astdb(const char *uri, const char *hash)
Definition: media_cache.c:389
static void media_cache_remove_from_astdb(const char *uri, const char *hash)
Definition: media_cache.c:375

References AST_DB_FAMILY, AST_DB_FAMILY_LEN, ast_db_freetree(), ast_db_gettree(), ast_db_entry::data, ast_db_entry::key, media_cache_item_populate_from_astdb(), media_cache_remove_from_astdb(), ast_db_entry::next, and NULL.

Referenced by ast_media_cache_init().

◆ media_cache_prnt_summary()

static int media_cache_prnt_summary ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 461 of file media_cache.c.

462{
463#define FORMAT_ROW "%-40s\n\t%-40s\n"
464 struct ast_bucket_file *bucket_file = obj;
465 struct ast_cli_args *a = arg;
466
467 ast_cli(a->fd, FORMAT_ROW, ast_sorcery_object_get_id(bucket_file), bucket_file->path);
468
469#undef FORMAT_ROW
470 return CMP_MATCH;
471}
@ CMP_MATCH
Definition: astobj2.h:1027

References a, ast_cli(), ast_sorcery_object_get_id(), CMP_MATCH, FORMAT_ROW, and ast_bucket_file::path.

Referenced by media_cache_handle_show_all().

◆ media_cache_remove_from_astdb()

static void media_cache_remove_from_astdb ( const char *  uri,
const char *  hash 
)
static

◆ media_cache_shutdown()

static void media_cache_shutdown ( void  )
static

Definition at line 663 of file media_cache.c.

664{
667
669}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), cli_media_cache, media_cache, and NULL.

Referenced by ast_media_cache_init().

◆ metadata_sync_to_astdb()

static int metadata_sync_to_astdb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 81 of file media_cache.c.

82{
83 struct ast_bucket_metadata *metadata = obj;
84 const char *hash = arg;
85
86 ast_db_put(hash, metadata->name, metadata->value);
87
88 return 0;
89}

References ast_db_put(), ast_bucket_metadata::name, and ast_bucket_metadata::value.

Referenced by media_cache_item_sync_to_astdb().

Variable Documentation

◆ cli_media_cache

struct ast_cli_entry cli_media_cache[]
static

Definition at line 651 of file media_cache.c.

Referenced by ast_media_cache_init(), and media_cache_shutdown().

◆ media_cache

struct ao2_container* media_cache
static