Asterisk - The Open Source Telephony Project GIT-master-85241bd
Functions
astobj2_container.c File Reference

Functions implementing astobj2 objects. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "astobj2_private.h"
#include "astobj2_container_private.h"
#include "asterisk/cli.h"
Include dependency graph for astobj2_container.c:

Go to the source code of this file.

Functions

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_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)
 
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)
 
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_iterator_next (struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
 
int __ao2_link (struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
 
void * __ao2_unlink (struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func)
 
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)
 
int __container_unlink_node_debug (struct ao2_container_node *node, uint32_t flags, const char *tag, const char *file, int line, const char *func)
 
int ao2_container_check (struct ao2_container *self, enum search_flags flags)
 Perform an integrity check on the specified container. More...
 
int ao2_container_count (struct ao2_container *c)
 Returns the number of elements in a container. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
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. More...
 
void ao2_container_unregister (const char *name)
 Unregister a container for CLI stats and integrity check. More...
 
void ao2_iterator_cleanup (struct ao2_iterator *iter)
 
int ao2_iterator_count (struct ao2_iterator *iter)
 Get a count of the iterated container objects. More...
 
void ao2_iterator_destroy (struct ao2_iterator *iter)
 Destroy a container iterator. More...
 
struct ao2_iterator ao2_iterator_init (struct ao2_container *c, int flags)
 Create an iterator for a container. More...
 
void ao2_iterator_restart (struct ao2_iterator *iter)
 Restart an iteration. More...
 
int ao2_match_by_addr (void *user_data, void *arg, int flags)
 another convenience function is a callback that matches on address More...
 
static int cb_true (void *user_data, void *arg, int flags)
 special callback that matches all More...
 
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 More...
 
void container_destruct (void *_c)
 
int container_init (void)
 
static int dup_obj_cb (void *obj, void *arg, int flags)
 
static int dup_weakproxy_cb (void *proxy, void *arg, int flags)
 Copy obj associated with a weakproxy into the arg container. More...
 
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)
 

Detailed Description

Functions implementing astobj2 objects.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file astobj2_container.c.

Function Documentation

◆ __ao2_callback()

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 
)

Definition at line 410 of file astobj2_container.c.

413{
414 return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, tag, file, line, func);
415}
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)
@ AO2_CALLBACK_DEFAULT
#define NULL
Definition: resample.c:96
static struct test_val c

References AO2_CALLBACK_DEFAULT, c, make_ari_stubs::file, ao2_iterator::flags, internal_ao2_traverse(), and NULL.

Referenced by __ao2_find(), and __ao2_unlink().

◆ __ao2_callback_data()

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 
)

Definition at line 417 of file astobj2_container.c.

420{
421 return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, tag, file, line, func);
422}
@ AO2_CALLBACK_WITH_DATA

References AO2_CALLBACK_WITH_DATA, c, make_ari_stubs::file, ao2_iterator::flags, and internal_ao2_traverse().

◆ __ao2_container_clone()

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 
)

Definition at line 753 of file astobj2_container.c.

754{
755 struct ao2_container *clone;
756 int failed;
757
758 /* Create the clone container with the same properties as the original. */
759 if (!__is_ao2_object(orig, file, line, func)) {
760 return NULL;
761 }
762
763 if (!orig->v_table || !orig->v_table->alloc_empty_clone) {
764 /* Sanity checks. */
765 __ast_assert_failed(0, "invalid container v_table", file, line, func);
766 return NULL;
767 }
768
769 clone = orig->v_table->alloc_empty_clone(orig, tag, file, line, func);
770 if (!clone) {
771 return NULL;
772 }
773
774 /* This test is correct. clone must be locked before calling
775 * ao2_container_dup when the OBJ_NOLOCK flag is set, otherwise
776 * we could have errors in __adjust_lock. */
777 if (flags & OBJ_NOLOCK) {
778 ao2_wrlock(clone);
779 }
780 failed = ao2_container_dup(clone, orig, flags);
781 if (flags & OBJ_NOLOCK) {
782 ao2_unlock(clone);
783 }
784 if (failed) {
785 /* Object copy into the clone container failed. */
786 __ao2_ref(clone, -1, tag ?: "Clone creation failed", file, line, func);
787 clone = NULL;
788 }
789 return clone;
790}
#define ao2_wrlock(a)
Definition: astobj2.h:719
#define ao2_unlock(a)
Definition: astobj2.h:729
int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func)
Definition: astobj2.c:498
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
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.
#define __is_ao2_object(user_data, file, line, func)
ao2_container_alloc_empty_clone_fn alloc_empty_clone
Create an empty copy of this container.
Generic container type.
const struct ao2_container_methods * v_table
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
Definition: utils.c:2816

References __ao2_ref(), __ast_assert_failed(), __is_ao2_object, ao2_container_methods::alloc_empty_clone, ao2_container_dup(), ao2_unlock, ao2_wrlock, make_ari_stubs::file, NULL, OBJ_NOLOCK, and ao2_container::v_table.

◆ __ao2_find()

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 
)

the find function just invokes the default callback with some reasonable flags.

Definition at line 427 of file astobj2_container.c.

429{
430 void *arged = (void *) arg;/* Done to avoid compiler const warning */
431
432 if (!c) {
433 /* Sanity checks. */
434 ast_assert(0);
435 return NULL;
436 }
437 return __ao2_callback(c, flags, c->cmp_fn, arged, tag, file, line, func);
438}
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)
#define ast_assert(a)
Definition: utils.h:739

References __ao2_callback(), ast_assert, c, make_ari_stubs::file, ao2_iterator::flags, and NULL.

Referenced by __ast_format_cache_get(), and _get_mohbyname().

◆ __ao2_iterator_next()

void * __ao2_iterator_next ( struct ao2_iterator iter,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 556 of file astobj2_container.c.

558{
559 enum ao2_lock_req orig_lock;
560 struct ao2_container_node *node;
561 void *ret;
562
563 if (!__is_ao2_object(iter->c, file, line, func)) {
564 return NULL;
565 }
566
567 if (!iter->c->v_table || !iter->c->v_table->iterator_next) {
568 /* Sanity checks. */
569 __ast_assert_failed(0, "invalid iterator container v_table", file, line, func);
570 return NULL;
571 }
572
573 if (iter->complete) {
574 /* Don't return any more objects. */
575 return NULL;
576 }
577
578 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
579 if (iter->flags & AO2_ITERATOR_UNLINK) {
580 orig_lock = __adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
581 } else {
582 orig_lock = __adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
583 }
584 } else {
585 orig_lock = AO2_LOCK_REQ_MUTEX;
586 if (iter->flags & AO2_ITERATOR_UNLINK) {
587 ao2_wrlock(iter->c);
588 } else {
589 ao2_rdlock(iter->c);
590 }
591 }
592
593 node = iter->c->v_table->iterator_next(iter->c, iter->last_node, iter->flags);
594 if (node) {
595 ret = node->obj;
596
597 if (iter->flags & AO2_ITERATOR_UNLINK) {
598 /* Transfer the object ref from the container to the returned object. */
600
601 /* Transfer the container's node ref to the iterator. */
602 } else {
603 /* Bump ref of returned object */
604 __ao2_ref(ret, +1, tag ?: "Next iterator object.", file, line, func);
605
606 /* Bump the container's node ref for the iterator. */
607 ao2_ref(node, +1);
608 }
609 } else {
610 /* The iteration has completed. */
611 iter->complete = 1;
612 ret = NULL;
613 }
614
615 /* Replace the iterator's node */
616 if (iter->last_node) {
617 ao2_ref(iter->last_node, -1);
618 }
619 iter->last_node = node;
620
621 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
622 __adjust_lock(iter->c, orig_lock, 0);
623 } else {
624 ao2_unlock(iter->c);
625 }
626
627 return ret;
628}
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
Definition: astobj2.c:425
#define ao2_rdlock(a)
Definition: astobj2.h:718
ao2_lock_req
Which lock to request.
Definition: astobj2.h:700
@ AO2_LOCK_REQ_MUTEX
Definition: astobj2.h:702
@ AO2_LOCK_REQ_WRLOCK
Definition: astobj2.h:706
@ AO2_LOCK_REQ_RDLOCK
Definition: astobj2.h:704
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
@ AO2_ITERATOR_DONTLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1852
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flags, const char *tag, const char *file, int line, const char *func)
@ AO2_UNLINK_NODE_DEC_COUNT
ao2_iterator_next_fn iterator_next
Generic container node.
int complete
Definition: astobj2.h:1827
struct ao2_container * c
Definition: astobj2.h:1823
void * last_node
Definition: astobj2.h:1825
Definition: test_heap.c:38

References __adjust_lock(), __ao2_ref(), __ast_assert_failed(), __container_unlink_node_debug(), __is_ao2_object, AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_ref, AO2_UNLINK_NODE_DEC_COUNT, ao2_unlock, ao2_wrlock, ao2_iterator::c, ao2_iterator::complete, make_ari_stubs::file, ao2_iterator::flags, ao2_container_methods::iterator_next, ao2_iterator::last_node, NULL, and ao2_container::v_table.

◆ __ao2_link()

int __ao2_link ( struct ao2_container self,
void *  obj_new,
int  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 94 of file astobj2_container.c.

96{
97 int res;
98 enum ao2_lock_req orig_lock;
100
101 if (!__is_ao2_object(obj_new, file, line, func)
102 || !__is_ao2_object(self, file, line, func)) {
103 return 0;
104 }
105
106 if (!self->v_table || !self->v_table->new_node || !self->v_table->insert) {
107 /* Sanity checks. */
108 __ast_assert_failed(0, "invalid container v_table", file, line, func);
109 return 0;
110 }
111
112 if (flags & OBJ_NOLOCK) {
113 orig_lock = __adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
114 } else {
115 ao2_wrlock(self);
116 orig_lock = AO2_LOCK_REQ_MUTEX;
117 }
118
119 res = 0;
120 node = self->v_table->new_node(self, obj_new, tag, file, line, func);
121 if (node) {
122#if defined(AO2_DEBUG)
123 if (ao2_container_check(self, OBJ_NOLOCK)) {
124 ast_log(LOG_ERROR, "Container integrity failed before insert.\n");
125 }
126#endif /* defined(AO2_DEBUG) */
127
128 /* Insert the new node. */
129 switch (self->v_table->insert(self, node)) {
131 node->is_linked = 1;
133#if defined(AO2_DEBUG)
134 AO2_DEVMODE_STAT(++self->nodes);
135 if (self->v_table->link_stat) {
136 self->v_table->link_stat(self, node);
137 }
138#endif /* defined(AO2_DEBUG) */
139 /* Fall through */
141#if defined(AO2_DEBUG)
142 if (ao2_container_check(self, OBJ_NOLOCK)) {
143 ast_log(LOG_ERROR, "Container integrity failed after insert or replace.\n");
144 }
145#endif /* defined(AO2_DEBUG) */
146 res = 1;
147 break;
149 ao2_ref(node, -1);
150 break;
151 }
152 }
153
154 if (flags & OBJ_NOLOCK) {
155 __adjust_lock(self, orig_lock, 0);
156 } else {
157 ao2_unlock(self);
158 }
159
160 return res;
161}
#define ast_log
Definition: astobj2.c:42
int ao2_container_check(struct ao2_container *self, enum search_flags flags)
Perform an integrity check on the specified container.
@ AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED
@ AO2_CONTAINER_INSERT_NODE_REJECTED
@ AO2_CONTAINER_INSERT_NODE_INSERTED
#define AO2_DEVMODE_STAT(stat)
#define LOG_ERROR
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
ao2_container_insert_fn insert
ao2_container_new_node_fn new_node

References __adjust_lock(), __ast_assert_failed(), __is_ao2_object, ao2_container_check(), AO2_CONTAINER_INSERT_NODE_INSERTED, AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED, AO2_CONTAINER_INSERT_NODE_REJECTED, AO2_DEVMODE_STAT, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_WRLOCK, ao2_ref, ao2_unlock, ao2_wrlock, ast_atomic_fetchadd_int(), ast_log, ao2_container::elements, make_ari_stubs::file, ao2_container_methods::insert, LOG_ERROR, ao2_container_methods::new_node, OBJ_NOLOCK, and ao2_container::v_table.

Referenced by internal_ao2_traverse().

◆ __ao2_unlink()

void * __ao2_unlink ( struct ao2_container c,
void *  user_data,
int  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 175 of file astobj2_container.c.

177{
178 if (!__is_ao2_object(user_data, file, line, func)) {
179 /* Sanity checks. */
180 return NULL;
181 }
182
183 flags &= ~OBJ_SEARCH_MASK;
185 __ao2_callback(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
186
187 return NULL;
188}
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_UNLINK
Definition: astobj2.h:1039
int ao2_match_by_addr(void *user_data, void *arg, int flags)
another convenience function is a callback that matches on address

References __ao2_callback(), __is_ao2_object, ao2_match_by_addr(), c, make_ari_stubs::file, NULL, OBJ_NODATA, OBJ_SEARCH_OBJECT, and OBJ_UNLINK.

◆ __ao2_weakproxy_find()

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 
)

Definition at line 440 of file astobj2_container.c.

442{
443 void *proxy;
444 void *obj = NULL;
445 enum ao2_lock_req orig_lock;
446
447 ast_assert(!!c);
449 ast_assert(!(flags & ~(OBJ_SEARCH_MASK | OBJ_NOLOCK)));
450
451 if (flags & OBJ_NOLOCK) {
452 orig_lock = __adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1);
453 } else {
454 orig_lock = AO2_LOCK_REQ_RDLOCK;
455 ao2_rdlock(c);
456 }
457
458 while ((proxy = ao2_find(c, arg, flags | OBJ_NOLOCK))) {
459 obj = __ao2_weakproxy_get_object(proxy, 0, tag ?: __PRETTY_FUNCTION__, file, line, func);
460
461 if (obj) {
462 ao2_ref(proxy, -1);
463 break;
464 }
465
466 /* Upgrade to a write lock */
469 ao2_ref(proxy, -1);
470 }
471
472 if (flags & OBJ_NOLOCK) {
473 /* We'll keep any upgraded lock */
474 __adjust_lock(c, orig_lock, 1);
475 } else {
476 ao2_unlock(c);
477 }
478
479 return obj;
480}
void * __ao2_weakproxy_get_object(void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result
Definition: astobj2.c:889
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072

References __adjust_lock(), __ao2_weakproxy_get_object(), ao2_find, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_ref, ao2_unlink_flags, ao2_unlock, ast_assert, c, make_ari_stubs::file, ao2_iterator::flags, NULL, OBJ_NOLOCK, and OBJ_SEARCH_MASK.

Referenced by __ast_named_lock_get(), and __ast_sorcery_open().

◆ __container_unlink_node_debug()

int __container_unlink_node_debug ( struct ao2_container_node node,
uint32_t  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 39 of file astobj2_container.c.

41{
42 struct ao2_container *container = node->my_container;
43
44 if (container == NULL && (flags & AO2_UNLINK_NODE_DEC_COUNT)) {
45 return 0;
46 }
47
49 && !(flags & AO2_UNLINK_NODE_NOUNREF_OBJECT)) {
50 __ao2_ref(node->obj, -1, tag ?: "Remove obj from container", file, line, func);
51 }
52
53 node->obj = NULL;
54
55 if (flags & AO2_UNLINK_NODE_DEC_COUNT) {
57#if defined(AO2_DEBUG)
58 {
59 int empty = container->nodes - container->elements;
60
61 if (container->max_empty_nodes < empty) {
62 container->max_empty_nodes = empty;
63 }
64 if (container->v_table->unlink_stat) {
65 container->v_table->unlink_stat(container, node);
66 }
67 }
68#endif /* defined(AO2_DEBUG) */
69 }
70
71 if (flags & AO2_UNLINK_NODE_UNREF_NODE) {
72 /* Remove node from container */
73 ao2_ref(node, -1);
74 }
75
76 return 1;
77}
@ AO2_UNLINK_NODE_UNREF_NODE
@ AO2_UNLINK_NODE_UNLINK_OBJECT
@ AO2_UNLINK_NODE_NOUNREF_OBJECT
struct ao2_container * container
Definition: res_fax.c:501

References __ao2_ref(), ao2_ref, AO2_UNLINK_NODE_DEC_COUNT, AO2_UNLINK_NODE_NOUNREF_OBJECT, AO2_UNLINK_NODE_UNLINK_OBJECT, AO2_UNLINK_NODE_UNREF_NODE, ast_atomic_fetchadd_int(), container, ao2_container::elements, make_ari_stubs::file, NULL, and ao2_container::v_table.

Referenced by __ao2_iterator_next(), and internal_ao2_traverse().

◆ ao2_container_check()

int ao2_container_check ( struct ao2_container self,
enum search_flags  flags 
)

Perform an integrity check on the specified container.

Since
12.0.0
Parameters
selfContainer to check integrity.
flagsOBJ_NOLOCK if a lock is already held on the container.
Return values
0on success.
-1on error.

Definition at line 856 of file astobj2_container.c.

857{
858 int res = 0;
859
860 if (!is_ao2_object(self) || !self->v_table) {
861 /* Sanity checks. */
862 ast_assert(0);
863 return -1;
864 }
865#if defined(AO2_DEBUG)
866 if (!self->v_table->integrity) {
867 /* No integrity check available. Assume container is ok. */
868 return 0;
869 }
870
871 if (!(flags & OBJ_NOLOCK)) {
872 ao2_rdlock(self);
873 }
874 res = self->v_table->integrity(self);
875 if (!(flags & OBJ_NOLOCK)) {
876 ao2_unlock(self);
877 }
878#endif /* defined(AO2_DEBUG) */
879 return res;
880}
#define is_ao2_object(user_data)

References ao2_rdlock, ao2_unlock, ast_assert, is_ao2_object, OBJ_NOLOCK, and ao2_container::v_table.

Referenced by __ao2_link(), AST_TEST_DEFINE(), astobj2_test_1_helper(), hash_ao2_node_destructor(), insert_test_duplicates(), insert_test_vector(), rb_ao2_node_destructor(), and test_container_clone().

◆ ao2_container_count()

int ao2_container_count ( struct ao2_container c)

Returns the number of elements in a container.

return the number of elements in the container

Definition at line 34 of file astobj2_container.c.

35{
36 return ast_atomic_fetchadd_int(&c->elements, 0);
37}

References ast_atomic_fetchadd_int(), and c.

Referenced by action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_lock_unlock_helper(), action_mute_unmute_helper(), ami_show_aors(), ami_show_auths(), ami_show_contacts(), ami_show_endpoints(), ami_show_resource_lists(), ao2_iterator_count(), app_is_finished(), ari_show(), ast_active_channels(), ast_ari_applications_list(), ast_bridge_transfer_attended(), ast_bridge_transfer_blind(), ast_cdr_generic_unregister(), ast_endpoint_snapshot_create(), ast_get_chan_applicationmap(), ast_get_namedgroups(), ast_merge_contexts_and_delete(), ast_namedgroups_intersect(), ast_sip_cli_traverse_objects(), ast_sip_initialize_system(), ast_sip_location_retrieve_first_aor_contact_filtered(), ast_sorcery_create(), ast_sorcery_delete(), ast_sorcery_retrieve_by_fields(), ast_sorcery_retrieve_by_prefix(), ast_sorcery_retrieve_by_regex(), ast_sorcery_update(), ast_srtp_unprotect(), AST_TEST_DEFINE(), ast_tone_zone_count(), astobj2_test_1_helper(), auth_observer(), bridges_scrape_cb(), calc_metric(), cc_cli_output_status(), cel_pre_apply_config(), channels_scrape_cb(), check_events(), check_expiration_thread(), cleanup(), cleanup_module(), cli_display_parking_lot(), cli_eprofile_show_all(), cli_fax_show_sessions(), cli_profile_show_all(), cli_show_modules(), cli_show_monitors(), cli_show_tasks(), cli_tn_show_all(), client_config_show_all(), common_identify(), control_command_count(), control_wait(), cpg_confchg_cb(), create_sound_blob(), create_unsolicited_mwi_subscriptions(), device_state_cb(), dial_state_process_bridge_enter(), do_timing(), endelm(), endpoints_scrape_cb(), exten_state_pub_data_alloc(), format_ami_aor_handler(), get_device_state_causing_channels(), global_loaded_observer(), grow(), handle_cli_sound_show(), handle_feature_show(), handle_manager_show_events(), handle_registrations(), handle_show_hint(), handle_show_hints(), insert_test_vector(), ip_identify_apply(), load_common(), locals_show(), match_filter(), member_add_to_queue(), memory_cache_full_update(), memory_cache_populate(), mid_test_sync(), mwi_subscription_established(), native_bridge_is_capable(), native_rtp_bridge_compatible_check(), object_type_loaded_observer(), one_protocol(), parking_lot_remove_if_unused(), pjsip_acf_dial_contacts_read(), presence_state_cb(), print_queue(), process_config(), pthread_timer_open(), publisher_start(), queue_exec(), queue_function_mem_read(), queued_set_size(), queued_task_pushed(), send_unsolicited_mwi_notify(), shrink(), single_state_process_bridge_enter(), sip_options_apply_aor_configuration(), sip_options_contact_add_task(), sip_options_contact_delete_task(), sip_options_unused_endpoint_state_compositor(), sla_in_use(), smdi_load(), sorcery_memory_cache_create(), sorcery_memory_cache_dump(), sorcery_memory_cache_populate(), sorcery_memory_cache_retrieve_multiple(), sorcery_memory_cache_retrieve_prefix(), sorcery_memory_cache_retrieve_regex(), sorcery_memory_cache_show(), sorcery_object_load(), stale_cache_update(), stasis_app_set_global_debug(), stasis_app_to_cli(), system_create_resolver_and_set_nameservers(), test_ao2_iteration(), test_cel_peer_strings_match(), test_container_clone(), test_sub(), threadpool_send_state_changed(), tps_shutdown(), try_calling(), unload_module(), and xmpp_show_clients().

◆ ao2_container_dump()

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.

Since
12.0.0
Parameters
selfContainer to dump.
flagsOBJ_NOLOCK if a lock is already held on the container.
nameContainer name. (NULL if anonymous)
whereUser data needed by prnt to determine where to put output.
prntPrint output callback function to use.
prnt_objCallback function to print the given object's key. (NULL if not available)

Definition at line 792 of file astobj2_container.c.

793{
794 if (!is_ao2_object(self) || !self->v_table) {
795 prnt(where, "Invalid container\n");
796 ast_assert(0);
797 return;
798 }
799
800 if (!(flags & OBJ_NOLOCK)) {
801 ao2_rdlock(self);
802 }
803 if (name) {
804 prnt(where, "Container name: %s\n", name);
805 }
806#if defined(AO2_DEBUG)
807 if (self->v_table->dump) {
808 self->v_table->dump(self, where, prnt, prnt_obj);
809 } else
810#endif /* defined(AO2_DEBUG) */
811 {
812 prnt(where, "Container dump not available.\n");
813 }
814 if (!(flags & OBJ_NOLOCK)) {
815 ao2_unlock(self);
816 }
817}
static const char name[]
Definition: format_mp3.c:68

References ao2_rdlock, ao2_unlock, ast_assert, is_ao2_object, name, OBJ_NOLOCK, and ao2_container::v_table.

Referenced by astobj2_test_1_helper(), and test_traversal_sorted().

◆ ao2_container_dup()

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.

Since
11.0
Parameters
destContainer to copy src object references into.
srcContainer to copy all object references from.
flagsOBJ_NOLOCK if a lock is already held on both containers. Otherwise, the src container is locked first.
Precondition
The dest container must be empty. If the duplication fails, the dest container will be returned empty.
Note
This can potentially be expensive because a malloc is needed for every object in the src container.
Return values
0on success.
-1on error.

Definition at line 673 of file astobj2_container.c.

674{
675 void *obj;
676 int res = 0;
677
678 if (!(flags & OBJ_NOLOCK)) {
679 ao2_rdlock(src);
680 ao2_wrlock(dest);
681 }
682 obj = ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
683 if (obj) {
684 /* Failed to put this obj into the dest container. */
685 ao2_t_ref(obj, -1, "Failed to put this object into the dest container.");
686
687 /* Remove all items from the dest container. */
689 NULL);
690 res = -1;
691 }
692 if (!(flags & OBJ_NOLOCK)) {
693 ao2_unlock(dest);
694 ao2_unlock(src);
695 }
696
697 return res;
698}
#define ao2_t_ref(o, delta, tag)
Definition: astobj2.h:460
#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_MULTIPLE
Definition: astobj2.h:1049
static int dup_obj_cb(void *obj, void *arg, int flags)

References ao2_callback, ao2_rdlock, ao2_t_ref, ao2_unlock, ao2_wrlock, dup_obj_cb(), NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, and OBJ_UNLINK.

Referenced by __ao2_container_clone(), __queues_show(), cli_aor_get_container(), cli_endpoint_get_container(), cli_get_container(), cli_show_monitors(), cli_show_tasks(), cli_unid_get_container(), geoloc_config_list_locations(), geoloc_config_list_profiles(), geoloc_config_show_profiles(), handle_cli_sounds_show(), sip_options_apply_aor_configuration(), stasis_show_topics(), tps_report_taskprocessor_list(), and tps_shutdown().

◆ ao2_container_dup_weakproxy_objs()

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.

Parameters
destContainer to copy src strong object references into.
srcContainer to copy all weak object references from.
flagsOBJ_NOLOCK if a lock is already held on both containers. Otherwise, the src container is locked first.
Precondition
The dest container must be empty. If the duplication fails, the dest container will be returned empty.
Note
This can potentially be expensive because a malloc is needed for every object in the src container.
Every object inside the container is locked by ao2_weakproxy_get_object. Any weakproxy in src with no associated object is ignored.
Return values
0on success.
-1on error.

Definition at line 726 of file astobj2_container.c.

727{
728 void *obj;
729 int res = 0;
730
731 if (!(flags & OBJ_NOLOCK)) {
732 ao2_rdlock(src);
733 ao2_wrlock(dest);
734 }
735 obj = ao2_callback(src, OBJ_NOLOCK, dup_weakproxy_cb, dest);
736 if (obj) {
737 /* Failed to put this obj into the dest container. */
738 ao2_t_ref(obj, -1, "Failed to put this object into the dest container.");
739
740 /* Remove all items from the dest container. */
742 NULL);
743 res = -1;
744 }
745 if (!(flags & OBJ_NOLOCK)) {
746 ao2_unlock(dest);
747 ao2_unlock(src);
748 }
749
750 return res;
751}
static int dup_weakproxy_cb(void *proxy, void *arg, int flags)
Copy obj associated with a weakproxy into the arg container.

References ao2_callback, ao2_rdlock, ao2_t_ref, ao2_unlock, ao2_wrlock, dup_weakproxy_cb(), NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, and OBJ_UNLINK.

Referenced by AST_TEST_DEFINE().

◆ ao2_container_register()

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.

Since
12.0.0
Parameters
nameName to register the container under.
selfContainer to register.
prnt_objCallback function to print the given object's key. (NULL if not available)
Return values
0on success.
-1on error.

Definition at line 958 of file astobj2_container.c.

959{
960 int res = 0;
961#if defined(AO2_DEBUG)
962 struct ao2_reg_container *reg;
963
964 reg = ao2_t_alloc_options(sizeof(*reg) + strlen(name), ao2_reg_destructor,
965 AO2_ALLOC_OPT_LOCK_NOLOCK, "Container registration object.");
966 if (!reg) {
967 return -1;
968 }
969
970 /* Fill in registered entry */
971 ao2_t_ref(self, +1, "Registering container.");
972 reg->registered = self;
973 reg->prnt_obj = prnt_obj;
974 strcpy(reg->name, name);/* safe */
975
976 if (!ao2_t_link(reg_containers, reg, "Save registration object.")) {
977 res = -1;
978 }
979
980 ao2_t_ref(reg, -1, "Done registering container.");
981#endif /* defined(AO2_DEBUG) */
982 return res;
983}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_t_link(container, obj, tag)
Definition: astobj2.h:1534
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg)
Allocate and initialize an object.
Definition: astobj2.h:402

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_t_alloc_options, ao2_t_link, ao2_t_ref, and name.

Referenced by ast_bridging_init(), ast_channels_init(), ast_pbx_init(), load_module(), stasis_caching_topic_create(), stasis_state_manager_create(), and stasis_topic_pool_create().

◆ ao2_container_stats()

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.

Since
12.0.0
Parameters
selfContainer to display statistics.
flagsOBJ_NOLOCK if a lock is already held on the container.
nameContainer name. (NULL if anonymous)
whereUser data needed by prnt to determine where to put output.
prntPrint output callback function to use.

Definition at line 819 of file astobj2_container.c.

820{
821 if (!is_ao2_object(self) || !self->v_table) {
822 prnt(where, "Invalid container\n");
823 ast_assert(0);
824 return;
825 }
826
827 if (!(flags & OBJ_NOLOCK)) {
828 ao2_rdlock(self);
829 }
830 if (name) {
831 prnt(where, "Container name: %s\n", name);
832 }
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);
837 /*
838 * XXX
839 * If the max_empty_nodes count gets out of single digits you
840 * likely have a code path where ao2_iterator_destroy() is not
841 * called.
842 *
843 * Empty nodes do not harm the container but they do make
844 * container operations less efficient.
845 */
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);
849 }
850#endif /* defined(AO2_DEBUG) */
851 if (!(flags & OBJ_NOLOCK)) {
852 ao2_unlock(self);
853 }
854}

References ao2_rdlock, ao2_unlock, ast_assert, ao2_container::elements, is_ao2_object, name, OBJ_NOLOCK, and ao2_container::v_table.

Referenced by astobj2_test_1_helper(), and test_traversal_sorted().

◆ ao2_container_unregister()

void ao2_container_unregister ( const char *  name)

Unregister a container for CLI stats and integrity check.

Since
12.0.0
Parameters
nameName the container is registered under.

Definition at line 985 of file astobj2_container.c.

986{
987#if defined(AO2_DEBUG)
989 "Unregister container");
990#endif /* defined(AO2_DEBUG) */
991}
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1734
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101

References ao2_t_find, name, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by bridge_cleanup(), cdr_engine_shutdown(), channels_shutdown(), load_module(), pbx_shutdown(), stasis_caching_topic_dtor(), state_manager_dtor(), topic_pool_dtor(), and unload_module().

◆ ao2_iterator_cleanup()

void ao2_iterator_cleanup ( struct ao2_iterator iter)

Definition at line 549 of file astobj2_container.c.

550{
551 if (iter) {
553 }
554}
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.

References ao2_iterator_destroy().

Referenced by AST_TEST_DEFINE(), and stasis_app_set_global_debug().

◆ ao2_iterator_count()

int ao2_iterator_count ( struct ao2_iterator iter)

Get a count of the iterated container objects.

Parameters
iterthe iterator to query
Returns
The number of objects in the iterated container

Definition at line 630 of file astobj2_container.c.

631{
632 return ao2_container_count(iter->c);
633}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.

References ao2_container_count(), and ao2_iterator::c.

◆ ao2_iterator_destroy()

void ao2_iterator_destroy ( struct ao2_iterator iter)

Destroy a container iterator.

Parameters
iterthe iterator to destroy

This function will release the container reference held by the iterator and any other resources it may be holding.

Definition at line 534 of file astobj2_container.c.

535{
536 /* Release any last container node reference. */
538
539 /* Release the iterated container reference. */
540 ao2_t_ref(iter->c, -1, "Unref iterator in ao2_iterator_destroy");
541 iter->c = NULL;
542
543 /* Free the malloced iterator. */
544 if (iter->flags & AO2_ITERATOR_MALLOCD) {
545 ast_free(iter);
546 }
547}
#define ast_free(a)
Definition: astmm.h:180
@ AO2_ITERATOR_MALLOCD
Definition: astobj2.h:1857
void ao2_iterator_restart(struct ao2_iterator *iter)
Restart an iteration.

References AO2_ITERATOR_MALLOCD, ao2_iterator_restart(), ao2_t_ref, ast_free, ao2_iterator::c, ao2_iterator::flags, and NULL.

Referenced by __iax2_show_peers(), __manager_event_sessions_va(), __queues_show(), __test_cel_generate_peer_str(), aco_set_defaults(), action_agents(), action_confbridgelistrooms(), action_coreshowchannelmap(), action_coreshowchannels(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_presencestatelist(), add_ice_to_stream(), aeap_tab_complete_name(), agent_show_requested(), agents_post_apply_config(), agents_sweep(), alias_show(), ami_show_registration_contact_statuses(), ao2_iterator_cleanup(), app_to_json(), ari_show_apps(), ast_add_hint(), ast_ari_bridges_list(), ast_ari_channels_list(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_recordings_list_stored(), ast_bridge_channel_kick(), ast_bucket_file_json(), ast_bucket_json(), ast_cdr_setvar(), ast_channel_iterator_destroy(), ast_complete_channels(), ast_endpoint_snapshot_create(), ast_format_cache_get_by_codec(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_destroy(), ast_multi_channel_blob_get_channels(), ast_pickup_find_by_group(), ast_print_namedgroups(), ast_refer_var_iterator_destroy(), ast_sip_destroy_scheduler(), ast_sip_for_each_contact(), ast_sorcery_objectset_create2(), ast_sorcery_objectset_json_create(), ast_srtp_unprotect(), AST_TEST_DEFINE(), ast_var_indications(), ast_var_indications_table(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), astobj2_test_1_helper(), auth_observer(), authenticate(), authenticate_reply(), bridge_app_subscribed_involved(), bridge_channel_event_join_leave(), bridge_channel_moving(), bridge_channel_talking(), bridges_scrape_cb(), build_cli_notify(), calendar_query_exec(), cel_generate_peer_str(), channels_scrape_cb(), check_access(), check_events(), clear_queue(), clear_stats(), cli_complete_endpoint(), cli_complete_notify(), cli_complete_registration(), cli_complete_show(), cli_complete_uri(), cli_console_active(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_show_channels(), cli_show_modules(), cli_show_monitors(), cli_show_tasks(), cli_tps_reset_stats_all(), compare_weight(), complete_bridge_profile_name(), complete_confbridge_name(), complete_config_module(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_menu_name(), complete_mohclass_realtime(), complete_queue(), complete_queue_remove_member(), complete_show_sorcery_object(), complete_user_profile_name(), complete_userno(), conf_queue_dtmf(), config_hook_exec(), config_object_tab_complete_name(), configure_parking_extensions(), container_to_json_array(), control_dispatch_all(), control_flush_queue(), control_prestart_dispatch_all(), coreshowchannelmap_add_connected_channels(), destroy_pvts(), device_state_cb(), device_state_notify_callbacks(), dial_state_process_bridge_enter(), dialgroup_read(), disable_marked_lots(), dump_queue_members(), endpoints_scrape_cb(), event_session_shutdown(), exten_state_publisher_state_cb(), extension_state_cb(), fax_session_tab_complete(), find_queue_by_name_rt(), find_ringing_channel(), find_session(), find_session_by_nonce(), free_members(), generate_or_link_lots_to_configs(), geoloc_config_list_locations(), geoloc_config_list_profiles(), geoloc_config_show_profiles(), get_device_state_causing_channels(), get_member_status(), get_transferee(), get_udp_transport(), get_write_timeout(), handle_bridge_pairings(), handle_bridge_show_all(), handle_chanlist(), handle_cli_confbridge_list(), handle_cli_confbridge_show_bridge_profiles(), handle_cli_confbridge_show_menus(), handle_cli_confbridge_show_user_profiles(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_indication_show(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_moh_unregister_class(), handle_cli_odbc_show(), handle_cli_sound_show(), handle_cli_status(), handle_export_primitives(), handle_kickmanconn(), handle_manager_show_event(), handle_manager_show_events(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_named_acl_cmd(), handle_showmanconn(), handle_skel_show_games(), handle_skel_show_levels(), handle_voicemail_show_aliases(), has_mwi_subscription(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), ip_identify_apply(), is_longest_waiting_caller(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), keepalive_transport_thread(), kill_duplicate_offers(), load_users(), local_devicestate(), locals_show(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), mark_lots_as_disabled(), media_cache_handle_show_item(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), msg_func_write(), mwi_contact_deleted(), mwi_initial_events(), mwi_mailbox_delete_all(), mwi_mailbox_get(), mwi_subscription_mailboxes_str(), num_available_members(), parking_lot_get_space(), pjsip_acf_dial_contacts_read(), pjsip_aor_function_read(), poke_all_peers(), pp_each_user_helper(), presence_state_cb(), presence_state_notify_callbacks(), print_queue(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_mwi_event(), qupd_exec(), reload(), reload_single_queue(), remove_all_configured_parking_lot_extensions(), remove_pending_parking_lot_extensions(), rt_handle_member_record(), set_member_paused(), set_member_value(), set_transfer_variables_all(), show_codecs(), single_state_process_bridge_enter(), sip_options_apply_aor_configuration(), sip_options_cleanup_task(), sip_options_endpoint_unlink_aor_feeders(), sip_options_get_endpoint_state_compositor_state(), sip_outbound_publish_synchronize(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), sla_show_stations(), sla_show_trunks(), sorcery_memory_cache_complete_name(), sorcery_memory_cache_complete_object_name(), stasis_app_mailboxes_to_json(), stasis_app_to_cli(), stasis_show_topics(), stop_streams(), system_create_resolver_and_set_nameservers(), test_ao2_callback_traversal(), test_ao2_iteration(), test_container_clone(), test_expected_duplicates(), topic_complete_name(), tps_report_taskprocessor_list(), tps_taskprocessor_tab_complete(), try_calling(), unbound_config_preapply(), update_queue(), update_realtime_members(), xmpp_pubsub_create_affiliations(), xmpp_show_buddies(), and xmpp_show_clients().

◆ ao2_iterator_init()

struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
)

Create an iterator for a container.

initialize an iterator so we start from the first object

Definition at line 485 of file astobj2_container.c.

486{
487 struct ao2_iterator a = {
488 .c = c,
489 .flags = flags
490 };
491
492 ao2_t_ref(c, +1, "Init iterator with container.");
493
494 return a;
495}
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
static struct test_val a

References a, ao2_t_ref, c, and ao2_iterator::flags.

Referenced by __iax2_show_peers(), __manager_event_sessions_va(), __queues_show(), __test_cel_generate_peer_str(), aco_set_defaults(), action_agents(), action_confbridgelistrooms(), action_coreshowchannelmap(), action_coreshowchannels(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_presencestatelist(), add_ice_to_stream(), aeap_tab_complete_name(), agent_show_requested(), agents_post_apply_config(), alias_show(), ami_show_registration_contact_statuses(), app_to_json(), ari_show_apps(), ast_add_hint(), ast_ari_bridges_list(), ast_ari_channels_list(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_recordings_list_stored(), ast_bridge_channel_kick(), ast_bucket_file_json(), ast_bucket_json(), ast_channel_iterator_all_new(), ast_complete_channels(), ast_endpoint_snapshot_create(), ast_format_cache_get_by_codec(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_init(), ast_pickup_find_by_group(), ast_print_namedgroups(), ast_refer_var_iterator_init(), ast_sip_destroy_scheduler(), ast_sip_for_each_contact(), ast_sorcery_objectset_create2(), ast_sorcery_objectset_json_create(), ast_srtp_unprotect(), AST_TEST_DEFINE(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), astobj2_test_1_helper(), auth_observer(), authenticate(), authenticate_reply(), bridge_app_subscribed_involved(), bridge_channel_event_join_leave(), bridge_channel_moving(), bridge_channel_talking(), bridges_scrape_cb(), build_cli_notify(), calendar_query_exec(), cel_generate_peer_str(), channels_scrape_cb(), check_access(), check_events(), clear_queue(), clear_stats(), cli_complete_endpoint(), cli_complete_notify(), cli_complete_registration(), cli_complete_show(), cli_complete_uri(), cli_console_active(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_show_channels(), cli_show_modules(), cli_show_monitors(), cli_show_tasks(), cli_tps_reset_stats_all(), compare_weight(), complete_bridge_profile_name(), complete_confbridge_name(), complete_config_module(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_menu_name(), complete_mohclass_realtime(), complete_queue(), complete_queue_remove_member(), complete_show_sorcery_object(), complete_user_profile_name(), complete_userno(), conf_queue_dtmf(), config_hook_exec(), config_object_tab_complete_name(), configure_parking_extensions(), container_to_json_array(), control_dispatch_all(), control_flush_queue(), control_prestart_dispatch_all(), coreshowchannelmap_add_connected_channels(), destroy_pvts(), device_state_cb(), device_state_notify_callbacks(), dial_state_process_bridge_enter(), dialgroup_read(), disable_marked_lots(), dump_queue_members(), endpoints_scrape_cb(), event_session_shutdown(), exten_state_publisher_state_cb(), extension_state_cb(), fax_session_tab_complete(), find_queue_by_name_rt(), find_ringing_channel(), find_session(), find_session_by_nonce(), free_members(), generate_or_link_lots_to_configs(), geoloc_config_list_locations(), geoloc_config_list_profiles(), geoloc_config_show_profiles(), get_device_state_causing_channels(), get_member_status(), get_transferee(), get_udp_transport(), get_write_timeout(), handle_bridge_pairings(), handle_bridge_show_all(), handle_chanlist(), handle_cli_confbridge_list(), handle_cli_confbridge_show_bridge_profiles(), handle_cli_confbridge_show_menus(), handle_cli_confbridge_show_user_profiles(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_moh_unregister_class(), handle_cli_odbc_show(), handle_cli_sound_show(), handle_cli_status(), handle_export_primitives(), handle_kickmanconn(), handle_manager_show_event(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_named_acl_cmd(), handle_showmanconn(), handle_skel_show_games(), handle_skel_show_levels(), handle_voicemail_show_aliases(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), internal_ao2_traverse(), ip_identify_apply(), is_longest_waiting_caller(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), keepalive_transport_thread(), load_users(), local_devicestate(), locals_show(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), mark_lots_as_disabled(), media_cache_handle_show_item(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), msg_func_write(), mwi_initial_events(), mwi_mailbox_delete_all(), mwi_mailbox_get(), mwi_subscription_mailboxes_str(), num_available_members(), parking_lot_get_space(), pjsip_acf_dial_contacts_read(), pjsip_aor_function_read(), poke_all_peers(), pp_each_user_helper(), presence_state_notify_callbacks(), print_queue(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), qupd_exec(), reload(), reload_single_queue(), remove_all_configured_parking_lot_extensions(), remove_pending_parking_lot_extensions(), rt_handle_member_record(), set_member_paused(), set_member_value(), set_transfer_variables_all(), show_codecs(), single_state_process_bridge_enter(), sip_options_apply_aor_configuration(), sip_options_cleanup_task(), sip_options_endpoint_unlink_aor_feeders(), sip_options_get_endpoint_state_compositor_state(), sip_outbound_publish_synchronize(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), sla_show_stations(), sla_show_trunks(), sorcery_memory_cache_complete_name(), sorcery_memory_cache_complete_object_name(), stasis_app_mailboxes_to_json(), stasis_app_set_global_debug(), stasis_show_topics(), stop_streams(), system_create_resolver_and_set_nameservers(), test_ao2_iteration(), test_container_clone(), topic_complete_name(), tps_report_taskprocessor_list(), tps_shutdown(), tps_taskprocessor_tab_complete(), try_calling(), unbound_config_preapply(), update_queue(), update_realtime_members(), xmpp_pubsub_create_affiliations(), xmpp_show_buddies(), and xmpp_show_clients().

◆ ao2_iterator_restart()

void ao2_iterator_restart ( struct ao2_iterator iter)

Restart an iteration.

Parameters
iterthe iterator to restart
Note
A restart is not going to have any effect if the iterator was created with the AO2_ITERATOR_UNLINK flag. Any previous objects returned were removed from the container.

Definition at line 497 of file astobj2_container.c.

498{
499 if (!is_ao2_object(iter->c)) {
500 /* Sanity check. */
501 return;
502 }
503
504 /* Release the last container node reference if we have one. */
505 if (iter->last_node) {
506 enum ao2_lock_req orig_lock;
507
508 /*
509 * Do a read lock in case the container node unref does not
510 * destroy the node. If the container node is destroyed then
511 * the lock will be upgraded to a write lock.
512 */
513 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
514 orig_lock = __adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
515 } else {
516 orig_lock = AO2_LOCK_REQ_MUTEX;
517 ao2_rdlock(iter->c);
518 }
519
520 ao2_ref(iter->last_node, -1);
521 iter->last_node = NULL;
522
523 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
524 __adjust_lock(iter->c, orig_lock, 0);
525 } else {
526 ao2_unlock(iter->c);
527 }
528 }
529
530 /* The iteration is no longer complete. */
531 iter->complete = 0;
532}

References __adjust_lock(), AO2_ITERATOR_DONTLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, ao2_rdlock, ao2_ref, ao2_unlock, ao2_iterator::c, ao2_iterator::complete, ao2_iterator::flags, is_ao2_object, ao2_iterator::last_node, and NULL.

Referenced by ao2_iterator_destroy().

◆ ao2_match_by_addr()

int ao2_match_by_addr ( void *  user_data,
void *  arg,
int  flags 
)

another convenience function is a callback that matches on address

A common ao2_callback is one that matches by address.

Definition at line 166 of file astobj2_container.c.

167{
168 return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
169}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028

References CMP_MATCH, and CMP_STOP.

Referenced by __ao2_unlink(), load_module(), and test_container_clone().

◆ cb_true()

static int cb_true ( void *  user_data,
void *  arg,
int  flags 
)
static

special callback that matches all

Definition at line 193 of file astobj2_container.c.

194{
195 return CMP_MATCH;
196}

References CMP_MATCH.

Referenced by internal_ao2_traverse().

◆ cb_true_data()

static int cb_true_data ( void *  user_data,
void *  arg,
void *  data,
int  flags 
)
static

similar to cb_true, but is an ao2_callback_data_fn instead

Definition at line 201 of file astobj2_container.c.

202{
203 return CMP_MATCH;
204}

References CMP_MATCH.

Referenced by internal_ao2_traverse().

◆ container_destruct()

void container_destruct ( void *  _c)

Definition at line 635 of file astobj2_container.c.

636{
637 struct ao2_container *c = _c;
638
639 /* Unlink any stored objects in the container. */
640 c->destroying = 1;
642 "container_destruct called");
643
644 /* Perform any extra container cleanup. */
645 if (c->v_table && c->v_table->destroy) {
646 c->v_table->destroy(c);
647 }
648
649#if defined(AO2_DEBUG)
650 ast_atomic_fetchadd_int(&ao2.total_containers, -1);
651#endif
652}
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
Definition: astobj2.h:1696

References ao2_t_callback, ast_atomic_fetchadd_int(), c, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

Referenced by __ao2_container_alloc_hash(), and __ao2_container_alloc_rbtree().

◆ container_init()

int container_init ( void  )

Definition at line 1181 of file astobj2_container.c.

1182{
1183#if defined(AO2_DEBUG)
1186 "Container registration container.");
1187 if (!reg_containers) {
1188 return -1;
1189 }
1190
1191 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1192 ast_register_cleanup(container_cleanup);
1193#endif /* defined(AO2_DEBUG) */
1194
1195 return 0;
1196}
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_RWLOCK
Definition: astobj2.h:365
#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag)
Definition: astobj2.h:1330
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
Definition: astobj2.h:1211
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ARRAY_LEN(a)
Definition: utils.h:666

References AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_t_container_alloc_list, ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), and NULL.

Referenced by astobj2_init().

◆ dup_obj_cb()

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

Definition at line 666 of file astobj2_container.c.

667{
668 struct ao2_container *dest = arg;
669
670 return ao2_link_flags(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
671}
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554

References ao2_link_flags, CMP_MATCH, CMP_STOP, and OBJ_NOLOCK.

Referenced by ao2_container_dup().

◆ dup_weakproxy_cb()

static int dup_weakproxy_cb ( void *  proxy,
void *  arg,
int  flags 
)
static

Copy obj associated with a weakproxy into the arg container.

Parameters
proxypointer to the weakproxy.
argcallback argument from ao2_callback()
flagsflags from ao2_callback()
Return values
0on success.
CMP_STOP|CMP_MATCHon error.

Definition at line 710 of file astobj2_container.c.

711{
712 void *obj = ao2_weakproxy_get_object(proxy, 0);
713 struct ao2_container *dest = arg;
714 int ret;
715
716 if (!obj) {
717 return 0;
718 }
719
720 ret = ao2_link_flags(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
721 ao2_ref(obj, -1);
722
723 return ret;
724}
#define ao2_weakproxy_get_object(weakproxy, flags)
Get the object associated with weakproxy.
Definition: astobj2.h:621

References ao2_link_flags, ao2_ref, ao2_weakproxy_get_object, CMP_MATCH, CMP_STOP, and OBJ_NOLOCK.

Referenced by ao2_container_dup_weakproxy_objs().

◆ internal_ao2_traverse()

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 
)
static

Definition at line 230 of file astobj2_container.c.

233{
234 void *ret;
235 ao2_callback_fn *cb_default = NULL;
236 ao2_callback_data_fn *cb_withdata = NULL;
237 struct ao2_container_node *node;
238 void *traversal_state;
239
240 enum ao2_lock_req orig_lock;
241 struct ao2_container *multi_container = NULL;
242 struct ao2_iterator *multi_iterator = NULL;
243
244 if (!__is_ao2_object(self, file, line, func)) {
245 return NULL;
246 }
247
248 if (!self->v_table
249 || !self->v_table->traverse_first || !self->v_table->traverse_next) {
250 /* Sanity checks. */
251 __ast_assert_failed(0, "invalid container v_table", file, line, func);
252 return NULL;
253 }
254
255 /*
256 * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
257 * turned off. This if statement checks for the special condition
258 * where multiple items may need to be returned.
259 */
260 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
261 /* we need to return an ao2_iterator with the results,
262 * as there could be more than one. the iterator will
263 * hold the only reference to a container that has all the
264 * matching objects linked into it, so when the iterator
265 * is destroyed, the container will be automatically
266 * destroyed as well.
267 */
269 NULL, "OBJ_MULTIPLE return container creation");
270 if (!multi_container) {
271 return NULL;
272 }
273 if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
274 ao2_t_ref(multi_container, -1, "OBJ_MULTIPLE interator creation failed.");
275 return NULL;
276 }
277 }
278
279 if (!cb_fn) {
280 /* Match everything if no callback match function provided. */
282 cb_withdata = cb_true_data;
283 } else {
284 cb_default = cb_true;
285 }
286 } else {
287 /*
288 * We do this here to avoid the per object casting penalty (even
289 * though that is probably optimized away anyway).
290 */
292 cb_withdata = cb_fn;
293 } else {
294 cb_default = cb_fn;
295 }
296 }
297
298 /* avoid modifications to the content */
299 if (flags & OBJ_NOLOCK) {
300 if (flags & OBJ_UNLINK) {
301 orig_lock = __adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
302 } else {
303 orig_lock = __adjust_lock(self, AO2_LOCK_REQ_RDLOCK, 1);
304 }
305 } else {
306 orig_lock = AO2_LOCK_REQ_MUTEX;
307 if (flags & OBJ_UNLINK) {
308 ao2_wrlock(self);
309 } else {
310 ao2_rdlock(self);
311 }
312 }
313
314 /* Create a buffer for the traversal state. */
315 traversal_state = alloca(AO2_TRAVERSAL_STATE_SIZE);
316
317 ret = NULL;
318 for (node = self->v_table->traverse_first(self, flags, arg, traversal_state);
319 node;
320 node = self->v_table->traverse_next(self, traversal_state, node)) {
321 int match;
322
323 /* Visit the current node. */
326 match &= cb_withdata(node->obj, arg, data, flags);
327 } else {
328 match &= cb_default(node->obj, arg, flags);
329 }
330 if (match == 0) {
331 /* no match, no stop, continue */
332 continue;
333 }
334 if (match == CMP_STOP) {
335 /* no match but stop, we are done */
336 break;
337 }
338
339 /*
340 * CMP_MATCH is set here
341 *
342 * we found the object, performing operations according to flags
343 */
344 if (node->obj) {
345 /* The object is still in the container. */
346 if (!(flags & OBJ_NODATA)) {
347 /*
348 * We are returning the object, record the value. It is
349 * important to handle this case before the unlink.
350 */
351 if (multi_container) {
352 /*
353 * Link the object into the container that will hold the
354 * results.
355 */
356 __ao2_link(multi_container, node->obj, flags, tag, file, line, func);
357 } else {
358 ret = node->obj;
359 /* Returning a single object. */
360 if (!(flags & OBJ_UNLINK)) {
361 /*
362 * Bump the ref count since we are not going to unlink and
363 * transfer the container's object ref to the returned object.
364 */
365 __ao2_ref(ret, 1, tag ?: "Traversal found object", file, line, func);
366 }
367 }
368 }
369
370 if (flags & OBJ_UNLINK) {
372 if (multi_container || (flags & OBJ_NODATA)) {
374 }
375 __container_unlink_node_debug(node, ulflag, tag, file, line, func);
376 }
377 }
378
379 if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
380 /* We found our only (or last) match, so we are done */
381 break;
382 }
383 }
384 if (self->v_table->traverse_cleanup) {
385 self->v_table->traverse_cleanup(traversal_state);
386 }
387 if (node) {
388 /* Unref the node from self->v_table->traverse_first/traverse_next() */
389 ao2_ref(node, -1);
390 }
391
392 if (flags & OBJ_NOLOCK) {
393 __adjust_lock(self, orig_lock, 0);
394 } else {
395 ao2_unlock(self);
396 }
397
398 /* if multi_container was created, we are returning multiple objects */
399 if (multi_container) {
400 *multi_iterator = ao2_iterator_init(multi_container,
402 ao2_t_ref(multi_container, -1,
403 "OBJ_MULTIPLE for multiple objects traversal complete.");
404 return multi_iterator;
405 } else {
406 return ret;
407 }
408}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int() ao2_callback_fn(void *obj, void *arg, int flags)
Type of a generic callback function.
Definition: astobj2.h:1226
int() ao2_callback_data_fn(void *obj, void *arg, void *data, int flags)
Type of a generic callback function.
Definition: astobj2.h:1244
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
int __ao2_link(struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
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
static int cb_true(void *user_data, void *arg, int flags)
special callback that matches all
#define AO2_TRAVERSAL_STATE_SIZE
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2362
static const char type[]
Definition: chan_ooh323.c:109
ao2_container_find_cleanup_fn traverse_cleanup
ao2_container_find_next_fn traverse_next
ao2_container_find_first_fn traverse_first

References __adjust_lock(), __ao2_link(), __ao2_ref(), __ast_assert_failed(), __container_unlink_node_debug(), __is_ao2_object, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CALLBACK_WITH_DATA, ao2_iterator_init(), AO2_ITERATOR_MALLOCD, AO2_ITERATOR_UNLINK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_ref, ao2_t_container_alloc_list, ao2_t_ref, AO2_TRAVERSAL_STATE_SIZE, AO2_UNLINK_NODE_DEC_COUNT, AO2_UNLINK_NODE_UNLINK_OBJECT, AO2_UNLINK_NODE_UNREF_NODE, ao2_unlock, ao2_wrlock, ast_calloc, cb_true(), cb_true_data(), CMP_MATCH, CMP_STOP, make_ari_stubs::file, ao2_iterator::flags, match(), NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, OBJ_UNLINK, ao2_container_methods::traverse_cleanup, ao2_container_methods::traverse_first, ao2_container_methods::traverse_next, type, and ao2_container::v_table.

Referenced by __ao2_callback(), and __ao2_callback_data().