mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	media cache: Add CLI commands
This patch adds five CLI commands for the media cache: * 'media cache show all' - display a summary of all items in the media cache. * 'media cache show <uri>' - display detailed information about a single item in the media cache. * 'media cache delete <uri>' - remove an item from the media cache, and inform the bucket backend for the URI scheme to remove the item as well. * 'media cache refresh <uri>' - refresh a URI. If the item does not exist in the media cache, the bucket backend will pull down the media associated with the URI and create the item in the cache. * 'media cache create <uri>' - create an item in the media cache from some local media storage. Note that the bucket backend for the URI scheme must still permit the item creation. Change-Id: Id1c5707a3b8e2d96b56e4691a46a936cd171f4ae
This commit is contained in:
		| @@ -36,6 +36,7 @@ ASTERISK_REGISTER_FILE() | ||||
| #include "asterisk/config.h" | ||||
| #include "asterisk/bucket.h" | ||||
| #include "asterisk/astdb.h" | ||||
| #include "asterisk/cli.h" | ||||
| #include "asterisk/media_cache.h" | ||||
|  | ||||
| /*! The name of the AstDB family holding items in the cache. */ | ||||
| @@ -176,7 +177,7 @@ static void media_cache_item_del_from_astdb(struct ast_bucket_file *bucket_file) | ||||
| 	} | ||||
|  | ||||
| 	ast_db_deltree(hash_value, NULL); | ||||
| 	ast_db_del(AST_DB_FAMILY, hash_value); | ||||
| 	ast_db_del(AST_DB_FAMILY, ast_sorcery_object_get_id(bucket_file)); | ||||
| 	ast_free(hash_value); | ||||
| } | ||||
|  | ||||
| @@ -376,16 +377,6 @@ int ast_media_cache_delete(const char *uri) | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief Shutdown the media cache | ||||
|  */ | ||||
| static void media_cache_shutdown(void) | ||||
| { | ||||
| 	ao2_ref(media_cache, -1); | ||||
| 	media_cache = NULL; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief Remove a media cache item from the AstDB | ||||
| @@ -474,6 +465,229 @@ static void media_cache_populate_from_astdb(void) | ||||
| 	ast_db_freetree(db_tree); | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief ao2 callback function for \ref media_cache_handle_show_all | ||||
|  */ | ||||
| static int media_cache_prnt_summary(void *obj, void *arg, int flags) | ||||
| { | ||||
| #define FORMAT_ROW "%-40s\n\t%-40s\n" | ||||
| 	struct ast_bucket_file *bucket_file = obj; | ||||
| 	struct ast_cli_args *a = arg; | ||||
|  | ||||
| 	ast_cli(a->fd, FORMAT_ROW, ast_sorcery_object_get_id(bucket_file), bucket_file->path); | ||||
|  | ||||
| #undef FORMAT_ROW | ||||
| 	return CMP_MATCH; | ||||
| } | ||||
|  | ||||
| static char *media_cache_handle_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| 	switch (cmd) { | ||||
| 	case CLI_INIT: | ||||
| 		e->command = "media cache show all"; | ||||
| 		e->usage = | ||||
| 			"Usage: media cache show all\n" | ||||
| 			"       Display a summary of all current items\n" | ||||
| 			"       in the media cache.\n"; | ||||
| 		return NULL; | ||||
| 	case CLI_GENERATE: | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (a->argc != 4) { | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	ast_cli(a->fd, "URI\n\tLocal File\n"); | ||||
| 	ast_cli(a->fd, "---------------\n"); | ||||
| 	ao2_callback(media_cache, OBJ_NODATA | OBJ_MULTIPLE, media_cache_prnt_summary, a); | ||||
|  | ||||
| 	return CLI_SUCCESS; | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief CLI tab completion function for URIs | ||||
|  */ | ||||
| static char *cli_complete_uri(const char *word, int state) | ||||
| { | ||||
| 	struct ast_bucket_file *bucket_file; | ||||
| 	struct ao2_iterator it_media_items; | ||||
| 	int wordlen = strlen(word); | ||||
| 	int which = 0; | ||||
| 	char *result = NULL; | ||||
|  | ||||
| 	it_media_items = ao2_iterator_init(media_cache, 0); | ||||
| 	while ((bucket_file = ao2_iterator_next(&it_media_items))) { | ||||
| 		if (!strncasecmp(word, ast_sorcery_object_get_id(bucket_file), wordlen) | ||||
| 			&& ++which > state) { | ||||
| 			result = ast_strdup(ast_sorcery_object_get_id(bucket_file)); | ||||
| 		} | ||||
| 		ao2_ref(bucket_file, -1); | ||||
| 		if (result) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	ao2_iterator_destroy(&it_media_items); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static char *media_cache_handle_show_item(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| #define FORMAT_ROW "\t%20s: %-40.40s\n" | ||||
| 	struct ast_bucket_file *bucket_file; | ||||
| 	struct ao2_iterator it_metadata; | ||||
| 	struct ast_bucket_metadata *metadata; | ||||
|  | ||||
| 	switch (cmd) { | ||||
| 	case CLI_INIT: | ||||
| 		e->command = "media cache show"; | ||||
| 		e->usage = | ||||
| 			"Usage: media cache show <uri>\n" | ||||
| 			"       Display all information about a particular\n" | ||||
| 			"       item in the media cache.\n"; | ||||
| 		return NULL; | ||||
| 	case CLI_GENERATE: | ||||
| 		return cli_complete_uri(a->word, a->n); | ||||
| 	} | ||||
|  | ||||
| 	if (a->argc != 4) { | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	bucket_file = ao2_find(media_cache, a->argv[3], OBJ_SEARCH_KEY); | ||||
| 	if (!bucket_file) { | ||||
| 		ast_cli(a->fd, "Unable to find '%s' in the media cache\n", a->argv[3]); | ||||
| 		return CLI_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	ast_cli(a->fd, "URI: %s\n", ast_sorcery_object_get_id(bucket_file)); | ||||
| 	ast_cli(a->fd, "%s\n", "----------------------------------------"); | ||||
| 	ast_cli(a->fd, FORMAT_ROW, "Path", bucket_file->path); | ||||
|  | ||||
| 	it_metadata = ao2_iterator_init(bucket_file->metadata, 0); | ||||
| 	while ((metadata = ao2_iterator_next(&it_metadata))) { | ||||
| 		ast_cli(a->fd, FORMAT_ROW, metadata->name, metadata->value); | ||||
| 		ao2_ref(metadata, -1); | ||||
| 	} | ||||
| 	ao2_iterator_destroy(&it_metadata); | ||||
|  | ||||
| 	ao2_ref(bucket_file, -1); | ||||
| #undef FORMAT_ROW | ||||
| 	return CLI_SUCCESS; | ||||
| } | ||||
|  | ||||
| static char *media_cache_handle_delete_item(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| 	switch (cmd) { | ||||
| 	case CLI_INIT: | ||||
| 		e->command = "media cache delete"; | ||||
| 		e->usage = | ||||
| 			"Usage: media cache delete <uri>\n" | ||||
| 			"       Delete an item from the media cache.\n" | ||||
| 			"       Note that this will also remove any local\n" | ||||
| 			"       storage of the media associated with the URI,\n" | ||||
| 			"       and will inform the backend supporting the URI\n" | ||||
| 			"       scheme that it should remove the item.\n"; | ||||
| 		return NULL; | ||||
| 	case CLI_GENERATE: | ||||
| 		return cli_complete_uri(a->word, a->n); | ||||
| 	} | ||||
|  | ||||
| 	if (a->argc != 4) { | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_media_cache_delete(a->argv[3])) { | ||||
| 		ast_cli(a->fd, "Unable to delete '%s'\n", a->argv[3]); | ||||
| 	} else { | ||||
| 		ast_cli(a->fd, "Deleted '%s' from the media cache\n", a->argv[3]); | ||||
| 	} | ||||
|  | ||||
| 	return CLI_SUCCESS; | ||||
| } | ||||
|  | ||||
| static char *media_cache_handle_refresh_item(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| 	char file_path[PATH_MAX]; | ||||
|  | ||||
| 	switch (cmd) { | ||||
| 	case CLI_INIT: | ||||
| 		e->command = "media cache refresh"; | ||||
| 		e->usage = | ||||
| 			"Usage: media cache refresh <uri>\n" | ||||
| 			"       Ask for a refresh of a particular URI.\n" | ||||
| 			"       If the item does not already exist in the\n" | ||||
| 			"       media cache, the item will be populated from\n" | ||||
| 			"       the backend supporting the URI scheme.\n"; | ||||
| 		return NULL; | ||||
| 	case CLI_GENERATE: | ||||
| 		return cli_complete_uri(a->word, a->n); | ||||
| 	} | ||||
|  | ||||
| 	if (a->argc != 4) { | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_media_cache_retrieve(a->argv[3], NULL, file_path, sizeof(file_path))) { | ||||
| 		ast_cli(a->fd, "Unable to refresh '%s'\n", a->argv[3]); | ||||
| 	} else { | ||||
| 		ast_cli(a->fd, "Refreshed '%s' to local storage '%s'\n", a->argv[3], file_path); | ||||
| 	} | ||||
|  | ||||
| 	return CLI_SUCCESS; | ||||
| } | ||||
|  | ||||
| static char *media_cache_handle_create_item(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||
| { | ||||
| 	switch (cmd) { | ||||
| 	case CLI_INIT: | ||||
| 		e->command = "media cache create"; | ||||
| 		e->usage = | ||||
| 			"Usage: media cache create <uri> <file>\n" | ||||
| 			"       Create an item in the media cache by associating\n" | ||||
| 			"       a local media file with some URI.\n"; | ||||
| 		return NULL; | ||||
| 	case CLI_GENERATE: | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (a->argc != 5) { | ||||
| 		return CLI_SHOWUSAGE; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_media_cache_create_or_update(a->argv[3], a->argv[4], NULL)) { | ||||
| 		ast_cli(a->fd, "Unable to create '%s' associated with local file '%s'\n", | ||||
| 			a->argv[3], a->argv[4]); | ||||
| 	} else { | ||||
| 		ast_cli(a->fd, "Created '%s' for '%s' in the media cache\n", | ||||
| 			a->argv[3], a->argv[4]); | ||||
| 	} | ||||
|  | ||||
| 	return CLI_SUCCESS; | ||||
| } | ||||
|  | ||||
| static struct ast_cli_entry cli_media_cache[] = { | ||||
| 	AST_CLI_DEFINE(media_cache_handle_show_all, "Show all items in the media cache"), | ||||
| 	AST_CLI_DEFINE(media_cache_handle_show_item, "Show a single item in the media cache"), | ||||
| 	AST_CLI_DEFINE(media_cache_handle_delete_item, "Remove an item from the media cache"), | ||||
| 	AST_CLI_DEFINE(media_cache_handle_refresh_item, "Refresh an item in the media cache"), | ||||
| 	AST_CLI_DEFINE(media_cache_handle_create_item, "Create an item in the media cache"), | ||||
| }; | ||||
|  | ||||
| /*! | ||||
|  * \internal | ||||
|  * \brief Shutdown the media cache | ||||
|  */ | ||||
| static void media_cache_shutdown(void) | ||||
| { | ||||
| 	ao2_ref(media_cache, -1); | ||||
| 	media_cache = NULL; | ||||
|  | ||||
| 	ast_cli_unregister_multiple(cli_media_cache, ARRAY_LEN(cli_media_cache)); | ||||
| } | ||||
|  | ||||
| int ast_media_cache_init(void) | ||||
| { | ||||
| 	ast_register_atexit(media_cache_shutdown); | ||||
| @@ -484,6 +698,11 @@ int ast_media_cache_init(void) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_cli_register_multiple(cli_media_cache, ARRAY_LEN(cli_media_cache))) { | ||||
| 		ao2_ref(media_cache, -1); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	media_cache_populate_from_astdb(); | ||||
|  | ||||
| 	return 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user