Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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(), __ao2_unlink(), and __find_call().

◆ __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: main/utils.c:2712

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:734

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

Referenced by __ast_format_cache_get(), __find_call(), 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;
99  struct ao2_container_node *node;
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:755
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, make_ari_stubs::file, LOG_ERROR, and OBJ_NOLOCK.

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;
184  flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
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_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ 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_MASK, 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);
448  ast_assert(flags & OBJ_SEARCH_MASK);
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 */
468  ao2_unlink_flags(c, proxy, OBJ_NOLOCK);
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

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 
48  if ((flags & AO2_UNLINK_NODE_UNLINK_OBJECT)
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, and OBJ_NOLOCK.

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 _sip_show_peers(), 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_cdr_generic_unregister(), ast_endpoint_snapshot_create(), ast_get_chan_applicationmap(), ast_get_namedgroups(), 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(), calc_metric(), cc_cli_output_status(), cel_pre_apply_config(), check_events(), check_expiration_thread(), cleanup(), cleanup_module(), cli_display_parking_lot(), cli_fax_show_sessions(), cli_show_modules(), common_identify(), control_command_count(), control_wait(), cpg_confchg_cb(), create_sound_blob(), create_unsolicited_mwi_subscriptions(), device_state_cb(), do_timing(), endelm(), exten_state_pub_data_alloc(), format_ami_aor_handler(), get_device_state_causing_channels(), global_loaded_observer(), grow(), handle_manager_show_events(), handle_registrations(), handle_show_hint(), handle_show_hints(), insert_test_vector(), ip_identify_apply(), load_common(), 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(), 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(), sip_options_apply_aor_configuration(), sip_options_contact_add_task(), sip_options_contact_delete_task(), sip_options_unused_endpoint_state_compositor(), sip_send_all_registers(), sip_show_objects(), sla_in_use(), smdi_load(), sorcery_memory_cache_create(), sorcery_memory_cache_dump(), 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(), stir_shaken_general_get(), 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, and OBJ_NOLOCK.

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_unid_get_container(), 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(), 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, is_ao2_object, name, and OBJ_NOLOCK.

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)
988  ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_SEARCH_KEY,
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(), 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) {
552  ao2_iterator_destroy(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. */
537  ao2_iterator_restart(iter);
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 __find_call(), __iax2_show_peers(), __manager_event_sessions_va(), __queues_show(), __test_cel_generate_peer_str(), _sip_show_peers(), aco_set_defaults(), action_agents(), action_confbridgelistrooms(), action_coreshowchannels(), action_devicestatelist(), action_meetmelist(), action_presencestatelist(), add_ice_to_sdp(), 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_cel_str_to_event_type(), ast_channel_iterator_destroy(), ast_complete_channels(), ast_endpoint_snapshot_create(), ast_format_cache_get_by_codec(), ast_msg_var_iterator_destroy(), ast_multi_channel_blob_get_channels(), ast_pickup_find_by_group(), ast_print_namedgroups(), 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(), attended_transfer_bridge(), auth_observer(), authenticate(), authenticate_reply(), bridge_app_subscribed_involved(), bridge_channel_event_join_leave(), bridge_channel_moving(), bridge_channel_talking(), build_cli_notify(), calendar_query_exec(), cel_generate_peer_str(), check_access(), check_events(), clear_queue(), clear_stats(), cli_complete_endpoint(), cli_complete_notify(), cli_complete_registration(), cli_complete_show(), cli_complete_uri(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_show_channels(), cli_show_modules(), 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_show_sorcery_object(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_user_profile_name(), complete_userno(), conf_queue_dtmf(), config_hook_exec(), configure_parking_extensions(), container_to_json_array(), control_dispatch_all(), control_flush_queue(), control_prestart_dispatch_all(), destroy_pvts(), device_state_cb(), device_state_notify_callbacks(), dialgroup_read(), disable_marked_lots(), dump_queue_members(), 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(), get_device_state_causing_channels(), get_member_status(), 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_files(), handle_cli_moh_unregister_class(), handle_manager_show_events(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), 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(), 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(), manager_iax2_show_peer_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_registry(), manager_sip_peer_status(), 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(), 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(), queue_mwi_event(), 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(), sip_keepalive_all_peers(), sip_options_apply_aor_configuration(), sip_options_cleanup_task(), sip_options_endpoint_unlink_aor_feeders(), sip_outbound_publish_synchronize(), sip_poke_all_peers(), sip_prune_realtime(), sip_send_all_mwi_subscriptions(), sip_send_all_registers(), sip_show_channel(), sip_show_channels(), sip_show_channelstats(), sip_show_history(), sip_show_inuse(), sip_show_mwi(), sip_show_objects(), sip_show_registry(), sip_show_tcp(), sip_show_users(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), 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(), stir_shaken_tab_complete_name(), 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(), unlink_peers_from_tables(), update_queue(), update_realtime_members(), xmpp_pubsub_create_affiliations(), 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 440 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

Referenced by __iax2_show_peers(), __manager_event_sessions_va(), __queues_show(), __test_cel_generate_peer_str(), aco_set_defaults(), action_agents(), action_confbridgelistrooms(), action_coreshowchannels(), action_devicestatelist(), action_meetmelist(), action_presencestatelist(), add_ice_to_sdp(), 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_cel_str_to_event_type(), ast_channel_iterator_all_new(), ast_complete_channels(), ast_endpoint_snapshot_create(), ast_format_cache_get_by_codec(), ast_msg_var_iterator_init(), ast_pickup_find_by_group(), ast_print_namedgroups(), ast_sip_destroy_scheduler(), ast_sip_for_each_contact(), ast_sorcery_objectset_create2(), ast_sorcery_objectset_json_create(), ast_srtp_unprotect(), AST_TEST_DEFINE(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), astobj2_test_1_helper(), attended_transfer_bridge(), auth_observer(), authenticate(), authenticate_reply(), bridge_app_subscribed_involved(), bridge_channel_event_join_leave(), bridge_channel_moving(), bridge_channel_talking(), build_cli_notify(), calendar_query_exec(), cel_generate_peer_str(), check_access(), check_events(), clear_queue(), clear_stats(), cli_complete_endpoint(), cli_complete_notify(), cli_complete_registration(), cli_complete_show(), cli_complete_uri(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_show_channels(), cli_show_modules(), 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_show_sorcery_object(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_user_profile_name(), complete_userno(), conf_queue_dtmf(), config_hook_exec(), configure_parking_extensions(), container_to_json_array(), control_dispatch_all(), control_flush_queue(), control_prestart_dispatch_all(), destroy_pvts(), device_state_cb(), device_state_notify_callbacks(), dialgroup_read(), disable_marked_lots(), dump_queue_members(), 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(), get_device_state_causing_channels(), get_member_status(), 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_files(), handle_cli_moh_unregister_class(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), 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(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), keepalive_transport_thread(), load_users(), local_devicestate(), manager_iax2_show_peer_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_registry(), manager_sip_peer_status(), 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(), 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(), 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(), sip_keepalive_all_peers(), sip_options_apply_aor_configuration(), sip_options_cleanup_task(), sip_options_endpoint_unlink_aor_feeders(), sip_outbound_publish_synchronize(), sip_poke_all_peers(), sip_prune_realtime(), sip_send_all_mwi_subscriptions(), sip_send_all_registers(), sip_show_channel(), sip_show_channels(), sip_show_channelstats(), sip_show_history(), sip_show_inuse(), sip_show_mwi(), sip_show_objects(), sip_show_registry(), sip_show_tcp(), sip_show_users(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), 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(), stir_shaken_tab_complete_name(), 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(), 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(), 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().

◆ container_init()

int container_init ( void  )

Definition at line 1181 of file astobj2_container.c.

1182 {
1183 #if defined(AO2_DEBUG)
1185  AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_reg_sort_cb, NULL,
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:661

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. */
281  if (type == AO2_CALLBACK_WITH_DATA) {
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  */
291  if (type == AO2_CALLBACK_WITH_DATA) {
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. */
324  match = (CMP_MATCH | CMP_STOP);
325  if (type == AO2_CALLBACK_WITH_DATA) {
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:2312
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, and type.

Referenced by __ao2_callback(), and __ao2_callback_data().