40 const char *tag,
const char *
file,
int line,
const char *func)
50 __ao2_ref(node->
obj, -1, tag ?:
"Remove obj from container", file, line, func);
55 if (flags & AO2_UNLINK_NODE_DEC_COUNT) {
57 #if defined(AO2_DEBUG) 59 int empty = container->nodes - container->
elements;
61 if (container->max_empty_nodes < empty) {
62 container->max_empty_nodes = empty;
64 if (container->
v_table->unlink_stat) {
65 container->
v_table->unlink_stat(container, node);
95 const char *tag,
const char *
file,
int line,
const char *func)
106 if (!self->v_table || !self->v_table->new_node || !self->v_table->insert) {
120 node =
self->v_table->new_node(
self, obj_new, tag, file, line, func);
122 #if defined(AO2_DEBUG) 129 switch (self->v_table->insert(
self, node)) {
133 #if defined(AO2_DEBUG) 135 if (self->v_table->link_stat) {
136 self->v_table->link_stat(
self, node);
141 #if defined(AO2_DEBUG) 143 ast_log(
LOG_ERROR,
"Container integrity failed after insert or replace.\n");
154 if (flags & OBJ_NOLOCK) {
176 const char *tag,
const char *
file,
int line,
const char *func)
193 static int cb_true(
void *user_data,
void *arg,
int flags)
201 static int cb_true_data(
void *user_data,
void *arg,
void *data,
int flags)
232 const char *tag,
const char *
file,
int line,
const char *func)
238 void *traversal_state;
249 || !self->v_table->traverse_first || !self->v_table->traverse_next) {
269 NULL,
"OBJ_MULTIPLE return container creation");
270 if (!multi_container) {
273 if (!(multi_iterator =
ast_calloc(1,
sizeof(*multi_iterator)))) {
274 ao2_t_ref(multi_container, -1,
"OBJ_MULTIPLE interator creation failed.");
318 for (node = self->v_table->traverse_first(
self, flags, arg, traversal_state);
320 node =
self->v_table->traverse_next(
self, traversal_state, node)) {
326 match &= cb_withdata(node->
obj, arg, data, flags);
328 match &= cb_default(node->
obj, arg, flags);
351 if (multi_container) {
356 __ao2_link(multi_container, node->
obj, flags, tag, file, line, func);
365 __ao2_ref(ret, 1, tag ?:
"Traversal found object", file, line, func);
372 if (multi_container || (flags & OBJ_NODATA)) {
384 if (self->v_table->traverse_cleanup) {
385 self->v_table->traverse_cleanup(traversal_state);
392 if (flags & OBJ_NOLOCK) {
399 if (multi_container) {
403 "OBJ_MULTIPLE for multiple objects traversal complete.");
404 return multi_iterator;
419 int line,
const char *func)
428 const char *tag,
const char *
file,
int line,
const char *func)
430 void *arged = (
void *) arg;
441 const char *tag,
const char *
file,
int line,
const char *func)
458 while ((proxy =
ao2_find(c, arg, flags | OBJ_NOLOCK))) {
472 if (flags & OBJ_NOLOCK) {
492 ao2_t_ref(c, +1,
"Init iterator with container.");
540 ao2_t_ref(iter->
c, -1,
"Unref iterator in ao2_iterator_destroy");
557 const char *tag,
const char *
file,
int line,
const char *func)
604 __ao2_ref(ret, +1, tag ?:
"Next iterator object.", file, line, func);
642 "container_destruct called");
649 #if defined(AO2_DEBUG) 685 ao2_t_ref(obj, -1,
"Failed to put this object into the dest container.");
692 if (!(flags & OBJ_NOLOCK)) {
738 ao2_t_ref(obj, -1,
"Failed to put this object into the dest container.");
745 if (!(flags & OBJ_NOLOCK)) {
781 if (flags & OBJ_NOLOCK) {
786 __ao2_ref(clone, -1, tag ?:
"Clone creation failed", file, line, func);
795 prnt(where,
"Invalid container\n");
804 prnt(where,
"Container name: %s\n", name);
806 #if defined(AO2_DEBUG) 807 if (self->v_table->dump) {
808 self->v_table->dump(
self, where, prnt, prnt_obj);
812 prnt(where,
"Container dump not available.\n");
814 if (!(flags & OBJ_NOLOCK)) {
822 prnt(where,
"Invalid container\n");
831 prnt(where,
"Container name: %s\n", name);
833 prnt(where,
"Number of objects: %d\n", self->elements);
834 #if defined(AO2_DEBUG) 835 prnt(where,
"Number of nodes: %d\n", self->nodes);
836 prnt(where,
"Number of empty nodes: %d\n", self->nodes - self->elements);
846 prnt(where,
"Maximum empty nodes: %d\n", self->max_empty_nodes);
847 if (self->v_table->stats) {
848 self->v_table->stats(
self, where, prnt);
851 if (!(flags & OBJ_NOLOCK)) {
865 #if defined(AO2_DEBUG) 866 if (!self->v_table->integrity) {
874 res =
self->v_table->integrity(
self);
875 if (!(flags & OBJ_NOLOCK)) {
882 #if defined(AO2_DEBUG) 885 struct ao2_reg_container {
894 struct ao2_reg_partial_key {
901 struct ao2_reg_match {
909 #if defined(AO2_DEBUG) 910 static int ao2_reg_sort_cb(
const void *obj_left,
const void *obj_right,
int flags)
912 const struct ao2_reg_container *reg_left = obj_left;
918 const struct ao2_reg_container *reg_right = obj_right;
920 cmp = strcasecmp(reg_left->name, reg_right->name);
925 const char *
name = obj_right;
927 cmp = strcasecmp(reg_left->name, name);
932 const struct ao2_reg_partial_key *partial_key = obj_right;
934 cmp = strncasecmp(reg_left->name, partial_key->name, partial_key->len);
947 #if defined(AO2_DEBUG) 948 static void ao2_reg_destructor(
void *v_doomed)
950 struct ao2_reg_container *doomed = v_doomed;
952 if (doomed->registered) {
953 ao2_t_ref(doomed->registered, -1,
"Releasing registered container.");
961 #if defined(AO2_DEBUG) 962 struct ao2_reg_container *reg;
971 ao2_t_ref(
self, +1,
"Registering container.");
972 reg->registered =
self;
973 reg->prnt_obj = prnt_obj;
974 strcpy(reg->name, name);
976 if (!
ao2_t_link(reg_containers, reg,
"Save registration object.")) {
980 ao2_t_ref(reg, -1,
"Done registering container.");
987 #if defined(AO2_DEBUG) 989 "Unregister container");
993 #if defined(AO2_DEBUG) 994 static int ao2_complete_reg_cb(
void *obj,
void *arg,
int flags)
996 struct ao2_reg_container *reg = obj;
1006 #if defined(AO2_DEBUG) 1007 static char *complete_container_names(
struct ast_cli_args *
a)
1009 struct ao2_reg_partial_key partial_key;
1015 partial_key.len = strlen(a->
word);
1016 partial_key.name = a->
word;
1018 ao2_complete_reg_cb, &partial_key);
1024 #if defined(AO2_DEBUG) 1036 static void cli_output(
void *where,
const char *fmt, ...) __attribute__((
format(printf, 2, 3)));
1037 static void cli_output(
void *where,
const char *fmt, ...)
1058 #if defined(AO2_DEBUG) 1063 struct ao2_reg_container *reg;
1067 e->
command =
"astobj2 container dump";
1069 "Usage: astobj2 container dump <name>\n" 1070 " Show contents of the container <name>.\n";
1073 return complete_container_names(a);
1085 ao2_t_ref(reg, -1,
"Done with registered container object.");
1087 ast_cli(a->
fd,
"Container '%s' not found.\n", name);
1094 #if defined(AO2_DEBUG) 1099 struct ao2_reg_container *reg;
1103 e->
command =
"astobj2 container stats";
1105 "Usage: astobj2 container stats <name>\n" 1106 " Show statistics about the specified container <name>.\n";
1109 return complete_container_names(a);
1120 ao2_t_ref(reg, -1,
"Done with registered container object.");
1122 ast_cli(a->
fd,
"Container '%s' not found.\n", name);
1129 #if defined(AO2_DEBUG) 1134 struct ao2_reg_container *reg;
1138 e->
command =
"astobj2 container check";
1140 "Usage: astobj2 container check <name>\n" 1141 " Perform a container integrity check on <name>.\n";
1144 return complete_container_names(a);
1154 ast_cli(a->
fd,
"Container check of '%s': %s.\n", name,
1156 ao2_t_ref(reg, -1,
"Done with registered container object.");
1158 ast_cli(a->
fd,
"Container '%s' not found.\n", name);
1165 #if defined(AO2_DEBUG) 1167 AST_CLI_DEFINE(handle_cli_astobj2_container_dump,
"Show container contents"),
1168 AST_CLI_DEFINE(handle_cli_astobj2_container_stats,
"Show container statistics"),
1169 AST_CLI_DEFINE(handle_cli_astobj2_container_check,
"Perform a container integrity check"),
1173 #if defined(AO2_DEBUG) 1174 static void container_cleanup(
void)
1176 ao2_t_ref(reg_containers, -1,
"Releasing container registration container");
1177 reg_containers =
NULL;
1185 #if defined(AO2_DEBUG) 1188 "Container registration container.");
1189 if (!reg_containers) {
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
#define AST_CLI_DEFINE(fn, txt,...)
int ao2_iterator_count(struct ao2_iterator *iter)
Get a count of the iterated container objects.
int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flags, const char *tag, const char *file, int line, const char *func)
Asterisk main include file. File version handling, generic pbx functions.
#define __is_ao2_object(user_data, file, line, func)
ao2_container_destroy_fn destroy
void * __ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
ao2_lock_req
Which lock to request.
static int cb_true_data(void *user_data, void *arg, void *data, int flags)
similar to cb_true, but is an ao2_callback_data_fn instead
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
The arg parameter is a search key, but is not an object.
void container_destruct(void *_c)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Common, private definitions for astobj2.
void * __ao2_unlink(struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func)
descriptor for a cli entry.
int __ao2_link(struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define ao2_callback(c, flags, cb_fn, arg)
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void * __ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line, const char *func)
void ao2_iterator_restart(struct ao2_iterator *iter)
Restart an iteration.
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
static int dup_obj_cb(void *obj, void *arg, int flags)
Assume that the ao2_container is already locked.
#define ao2_t_link(container, obj, tag)
Add an object to a container.
#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag)
Allocate and initialize a list container.
void ao2_iterator_cleanup(struct ao2_iterator *iter)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define ao2_link_flags(container, obj, flags)
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg)
Allocate and initialize an object.
#define ast_strdup(str)
A wrapper for strdup()
int ao2_container_check(struct ao2_container *self, enum search_flags flags)
Perform an integrity check on the specified container.
search_flags
Flags passed to ao2_callback_fn(), ao2_hash_fn(), and ao2_sort_fn() to modify behaviour.
static int cb_true(void *user_data, void *arg, int flags)
special callback that matches all
void ast_cli(int fd, const char *fmt,...)
int() ao2_callback_data_fn(void *obj, void *arg, void *data, int flags)
Type of a generic callback function.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
#define is_ao2_object(user_data)
int ao2_match_by_addr(void *user_data, void *arg, int flags)
another convenience function is a callback that matches on address
int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func)
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
#define ao2_weakproxy_get_object(weakproxy, flags)
#define ao2_ref(o, delta)
const struct ao2_container_methods * v_table
void * __ao2_weakproxy_get_object(void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result
Get the object associated with weakproxy.
#define AO2_DEVMODE_STAT(stat)
struct ao2_container * container
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
void ao2_container_dump(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
Display contents of the specified container.
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static void * internal_ao2_traverse(struct ao2_container *self, enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag, const char *file, int line, const char *func)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
ao2_iterator_next_fn iterator_next
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ao2_container_dup_weakproxy_objs(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy object references associated with src container weakproxies into the dest container.
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
#define ast_calloc(num, len)
A wrapper for calloc()
void * __ao2_weakproxy_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
unsigned int destroying
TRUE if the container is being destroyed.
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
static int dup_weakproxy_cb(void *proxy, void *arg, int flags)
Copy obj associated with a weakproxy into the arg container.
Prototypes for public functions only of internal interest,.
#define AO2_TRAVERSAL_STATE_SIZE
#define ao2_find(container, arg, flags)
void ao2_container_stats(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt)
Display statistics of the specified container.
Assume that the ao2_container is already locked.
The arg parameter is an object of the same type.
Replace objects with duplicate keys in container.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
struct ao2_container * __ao2_container_clone(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
Create a clone/copy of the given container.
Common, private definitions for astobj2 containers.
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
#define ao2_t_find(container, arg, flags, tag)
#define ao2_unlink_flags(container, obj, flags)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Search option field mask.
void() ao2_prnt_obj_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
Print object key.
struct ao2_container * my_container
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
static snd_pcm_format_t format
ao2_container_alloc_empty_clone_fn alloc_empty_clone
Create an empty copy of this container.
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
void * __ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
void * __ao2_callback_data(struct ao2_container *c, enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file, int line, const char *func)