Skip to content
Snippets Groups Projects
astobj2_container.c 31.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_SEARCH_KEY,
    		"Unregister container");
    
    static int ao2_complete_reg_cb(void *obj, void *arg, void *data, int flags)
    {
    	struct ao2_reg_match *which = data;
    
    	/* ao2_reg_sort_cb() has already filtered the search to matching keys */
    	return (which->find_nth < ++which->count) ? (CMP_MATCH | CMP_STOP) : 0;
    }
    
    static char *complete_container_names(struct ast_cli_args *a)
    {
    	struct ao2_reg_partial_key partial_key;
    	struct ao2_reg_match which;
    	struct ao2_reg_container *reg;
    	char *name;
    
    	if (a->pos != 3) {
    		return NULL;
    	}
    
    	partial_key.len = strlen(a->word);
    	partial_key.name = a->word;
    	which.find_nth = a->n;
    	which.count = 0;
    	reg = ao2_t_callback_data(reg_containers, partial_key.len ? OBJ_SEARCH_PARTIAL_KEY : 0,
    		ao2_complete_reg_cb, &partial_key, &which, "Find partial registered container");
    	if (reg) {
    		name = ast_strdup(reg->name);
    		ao2_t_ref(reg, -1, "Done with registered container object.");
    	} else {
    		name = NULL;
    	}
    	return name;
    }
    
    AST_THREADSTORAGE(ao2_out_buf);
    
    /*!
     * \brief Print CLI output.
     * \since 12.0.0
     *
     * \param where User data pointer needed to determine where to put output.
     * \param fmt printf type format string.
     *
     * \return Nothing
     */
    static void cli_output(void *where, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
    static void cli_output(void *where, const char *fmt, ...)
    {
    	int res;
    	struct ast_str *buf;
    	va_list ap;
    
    	buf = ast_str_thread_get(&ao2_out_buf, 256);
    	if (!buf) {
    		return;
    	}
    
    	va_start(ap, fmt);
    	res = ast_str_set_va(&buf, 0, fmt, ap);
    	va_end(ap);
    
    	if (res != AST_DYNSTR_BUILD_FAILED) {
    		ast_cli(*(int *) where, "%s", ast_str_buffer(buf));
    	}
    }
    
    /*! \brief Show container contents - CLI command */
    static char *handle_cli_astobj2_container_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    {
    	const char *name;
    	struct ao2_reg_container *reg;
    
    	switch (cmd) {
    	case CLI_INIT:
    		e->command = "astobj2 container dump";
    		e->usage =
    			"Usage: astobj2 container dump <name>\n"
    			"	Show contents of the container <name>.\n";
    		return NULL;
    	case CLI_GENERATE:
    		return complete_container_names(a);
    	}
    
    	if (a->argc != 4) {
    		return CLI_SHOWUSAGE;
    	}
    
    	name = a->argv[3];
    	reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
    	if (reg) {
    		ao2_container_dump(reg->registered, 0, name, (void *) &a->fd, cli_output,
    			reg->prnt_obj);
    		ao2_t_ref(reg, -1, "Done with registered container object.");
    	} else {
    		ast_cli(a->fd, "Container '%s' not found.\n", name);
    	}
    
    	return CLI_SUCCESS;
    }
    
    /*! \brief Show container statistics - CLI command */
    static char *handle_cli_astobj2_container_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    {
    	const char *name;
    	struct ao2_reg_container *reg;
    
    	switch (cmd) {
    	case CLI_INIT:
    		e->command = "astobj2 container stats";
    		e->usage =
    			"Usage: astobj2 container stats <name>\n"
    			"	Show statistics about the specified container <name>.\n";
    		return NULL;
    	case CLI_GENERATE:
    		return complete_container_names(a);
    	}
    
    	if (a->argc != 4) {
    		return CLI_SHOWUSAGE;
    	}
    
    	name = a->argv[3];
    	reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
    	if (reg) {
    		ao2_container_stats(reg->registered, 0, name, (void *) &a->fd, cli_output);
    		ao2_t_ref(reg, -1, "Done with registered container object.");
    	} else {
    		ast_cli(a->fd, "Container '%s' not found.\n", name);
    	}
    
    	return CLI_SUCCESS;
    }
    
    /*! \brief Show container check results - CLI command */
    static char *handle_cli_astobj2_container_check(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    {
    	const char *name;
    	struct ao2_reg_container *reg;
    
    	switch (cmd) {
    	case CLI_INIT:
    		e->command = "astobj2 container check";
    		e->usage =
    			"Usage: astobj2 container check <name>\n"
    			"	Perform a container integrity check on <name>.\n";
    		return NULL;
    	case CLI_GENERATE:
    		return complete_container_names(a);
    	}
    
    	if (a->argc != 4) {
    		return CLI_SHOWUSAGE;
    	}
    
    	name = a->argv[3];
    	reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
    	if (reg) {
    		ast_cli(a->fd, "Container check of '%s': %s.\n", name,
    			ao2_container_check(reg->registered, 0) ? "failed" : "OK");
    		ao2_t_ref(reg, -1, "Done with registered container object.");
    	} else {
    		ast_cli(a->fd, "Container '%s' not found.\n", name);
    	}
    
    	return CLI_SUCCESS;
    }
    
    static struct ast_cli_entry cli_astobj2[] = {
    	AST_CLI_DEFINE(handle_cli_astobj2_container_dump, "Show container contents"),
    	AST_CLI_DEFINE(handle_cli_astobj2_container_stats, "Show container statistics"),
    	AST_CLI_DEFINE(handle_cli_astobj2_container_check, "Perform a container integrity check"),
    };
    
    static void container_cleanup(void)
    {
    	ao2_t_ref(reg_containers, -1, "Releasing container registration container");
    	reg_containers = NULL;
    
    	ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
    }
    
    	reg_containers = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK,
    		AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_reg_sort_cb, NULL,
    		"Container registration container.");
    	if (!reg_containers) {
    		return -1;
    	}
    
    	ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
    	ast_register_atexit(container_cleanup);