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)
void * __ao2_callback_data (struct ao2_container *c, enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data)
void * __ao2_callback_data_debug (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)
void * __ao2_callback_debug (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)
struct ao2_container__ao2_container_clone (struct ao2_container *orig, enum search_flags flags)
 Create a clone/copy of the given container.
struct ao2_container__ao2_container_clone_debug (struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug)
void * __ao2_find (struct ao2_container *c, const void *arg, enum search_flags flags)
void * __ao2_find_debug (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)
void * __ao2_iterator_next_debug (struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
int __ao2_link (struct ao2_container *c, void *obj_new, int flags)
int __ao2_link_debug (struct ao2_container *c, 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)
void * __ao2_unlink_debug (struct ao2_container *c, void *user_data, int 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.
int ao2_container_count (struct ao2_container *c)
 Returns the number of elements in a container.
void ao2_container_dump (struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
 Display contents of the specified container.
int ao2_container_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.
int ao2_container_register (const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
 Register a container for CLI stats and integrity check.
void ao2_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.
void ao2_container_unregister (const char *name)
 Unregister a container for CLI stats and integrity check.
void ao2_iterator_cleanup (struct ao2_iterator *iter)
int ao2_iterator_count (struct ao2_iterator *iter)
 Get a count of the iterated container objects.
void ao2_iterator_destroy (struct ao2_iterator *iter)
 Destroy a container iterator.
struct ao2_iterator ao2_iterator_init (struct ao2_container *c, int flags)
 Create an iterator for a container.
void ao2_iterator_restart (struct ao2_iterator *iter)
 Restart an iteration.
int ao2_match_by_addr (void *user_data, void *arg, int flags)
 another convenience function is a callback that matches on address
static int cb_true (void *user_data, void *arg, int flags)
 special callback that matches all
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
void container_destruct (void *_c)
void container_destruct_debug (void *_c)
int container_init (void)
static int dup_obj_cb (void *obj, void *arg, int flags)
static void * internal_ao2_iterator_next (struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
static int internal_ao2_link (struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
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 <rmudgett@digium.com>

Definition in file astobj2_container.c.


Function Documentation

void* __ao2_callback ( struct ao2_container c,
enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg 
)

Definition at line 449 of file astobj2_container.c.

References AO2_CALLBACK_DEFAULT, internal_ao2_traverse(), and NULL.

Referenced by __ao2_find(), __ao2_unlink(), ao2_container_dup(), and container_destruct().

00451 {
00452    return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, NULL, NULL, 0, NULL);
00453 }

void* __ao2_callback_data ( struct ao2_container c,
enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data 
)

Definition at line 462 of file astobj2_container.c.

References AO2_CALLBACK_WITH_DATA, internal_ao2_traverse(), and NULL.

00464 {
00465    return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, NULL, NULL, 0, NULL);
00466 }

void* __ao2_callback_data_debug ( 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 455 of file astobj2_container.c.

References AO2_CALLBACK_WITH_DATA, and internal_ao2_traverse().

00458 {
00459    return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, tag, file, line, func);
00460 }

void* __ao2_callback_debug ( 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 442 of file astobj2_container.c.

References AO2_CALLBACK_DEFAULT, internal_ao2_traverse(), and NULL.

Referenced by __ao2_find_debug(), __ao2_unlink_debug(), __find_call(), and container_destruct_debug().

00445 {
00446    return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, tag, file, line, func);
00447 }

struct ao2_container* __ao2_container_clone ( struct ao2_container orig,
enum search_flags  flags 
) [read]

Create a clone/copy of the given container.

Since:
11.0
Parameters:
orig Container to copy all object references from.
flags OBJ_NOLOCK if a lock is already held on the container.
Note:
This can potentially be expensive because a malloc is needed for every object in the orig container.
Return values:
Clone container on success.
NULL on error.

Definition at line 739 of file astobj2_container.c.

References ao2_container_methods::alloc_empty_clone, ao2_container_dup(), ao2_t_ref, ao2_unlock, ao2_wrlock, ast_assert, is_ao2_object(), NULL, OBJ_NOLOCK, and ao2_container::v_table.

00740 {
00741    struct ao2_container *clone;
00742    int failed;
00743 
00744    /* Create the clone container with the same properties as the original. */
00745    if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) {
00746       /* Sanity checks. */
00747       ast_assert(0);
00748       return NULL;
00749    }
00750    clone = orig->v_table->alloc_empty_clone(orig);
00751    if (!clone) {
00752       return NULL;
00753    }
00754 
00755    if (flags & OBJ_NOLOCK) {
00756       ao2_wrlock(clone);
00757    }
00758    failed = ao2_container_dup(clone, orig, flags);
00759    if (flags & OBJ_NOLOCK) {
00760       ao2_unlock(clone);
00761    }
00762    if (failed) {
00763       /* Object copy into the clone container failed. */
00764       ao2_t_ref(clone, -1, "Clone creation failed.");
00765       clone = NULL;
00766    }
00767    return clone;
00768 }

struct ao2_container* __ao2_container_clone_debug ( struct ao2_container orig,
enum search_flags  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func,
int  ref_debug 
) [read]

Definition at line 770 of file astobj2_container.c.

References __ao2_ref_debug(), ao2_container_methods::alloc_empty_clone_debug, ao2_container_dup(), ao2_t_ref, ao2_unlock, ao2_wrlock, ast_assert, is_ao2_object(), NULL, OBJ_NOLOCK, and ao2_container::v_table.

00771 {
00772    struct ao2_container *clone;
00773    int failed;
00774 
00775    /* Create the clone container with the same properties as the original. */
00776    if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) {
00777       /* Sanity checks. */
00778       ast_assert(0);
00779       return NULL;
00780    }
00781    clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug);
00782    if (!clone) {
00783       return NULL;
00784    }
00785 
00786    if (flags & OBJ_NOLOCK) {
00787       ao2_wrlock(clone);
00788    }
00789    failed = ao2_container_dup(clone, orig, flags);
00790    if (flags & OBJ_NOLOCK) {
00791       ao2_unlock(clone);
00792    }
00793    if (failed) {
00794       /* Object copy into the clone container failed. */
00795       if (ref_debug) {
00796          __ao2_ref_debug(clone, -1, tag, file, line, func);
00797       } else {
00798          ao2_t_ref(clone, -1, "Clone creation failed.");
00799       }
00800       clone = NULL;
00801    }
00802    return clone;
00803 }

void* __ao2_find ( struct ao2_container c,
const void *  arg,
enum search_flags  flags 
)

Definition at line 484 of file astobj2_container.c.

References __ao2_callback(), ast_assert, ao2_container::cmp_fn, and NULL.

Referenced by _get_mohbyname().

00485 {
00486    void *arged = (void *) arg;/* Done to avoid compiler const warning */
00487 
00488    if (!c) {
00489       /* Sanity checks. */
00490       ast_assert(0);
00491       return NULL;
00492    }
00493    return __ao2_callback(c, flags, c->cmp_fn, arged);
00494 }

void* __ao2_find_debug ( 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 471 of file astobj2_container.c.

References __ao2_callback_debug(), ast_assert, ao2_container::cmp_fn, and NULL.

Referenced by __ast_format_cache_get_debug(), __find_call(), and _get_mohbyname().

00473 {
00474    void *arged = (void *) arg;/* Done to avoid compiler const warning */
00475 
00476    if (!c) {
00477       /* Sanity checks. */
00478       ast_assert(0);
00479       return NULL;
00480    }
00481    return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
00482 }

void* __ao2_iterator_next ( struct ao2_iterator iter  ) 

Definition at line 646 of file astobj2_container.c.

References internal_ao2_iterator_next(), and NULL.

00647 {
00648    return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00649 }

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

Definition at line 641 of file astobj2_container.c.

References internal_ao2_iterator_next().

00642 {
00643    return internal_ao2_iterator_next(iter, tag, file, line, func);
00644 }

int __ao2_link ( struct ao2_container c,
void *  obj_new,
int  flags 
)

Definition at line 169 of file astobj2_container.c.

References internal_ao2_link(), and NULL.

Referenced by dup_obj_cb(), and internal_ao2_traverse().

00170 {
00171    return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00172 }

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

Definition at line 164 of file astobj2_container.c.

References internal_ao2_link().

Referenced by internal_ao2_traverse().

00165 {
00166    return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
00167 }

void* __ao2_unlink ( struct ao2_container c,
void *  user_data,
int  flags 
)

Definition at line 202 of file astobj2_container.c.

References __ao2_callback(), ao2_match_by_addr(), ast_assert, is_ao2_object(), NULL, OBJ_NODATA, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_UNLINK.

00203 {
00204    if (!is_ao2_object(user_data)) {
00205       /* Sanity checks. */
00206       ast_assert(0);
00207       return NULL;
00208    }
00209 
00210    flags &= ~OBJ_SEARCH_MASK;
00211    flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
00212    __ao2_callback(c, flags, ao2_match_by_addr, user_data);
00213 
00214    return NULL;
00215 }

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

Definition at line 186 of file astobj2_container.c.

References __ao2_callback_debug(), ao2_match_by_addr(), ast_assert, is_ao2_object(), NULL, OBJ_NODATA, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_UNLINK.

00188 {
00189    if (!is_ao2_object(user_data)) {
00190       /* Sanity checks. */
00191       ast_assert(0);
00192       return NULL;
00193    }
00194 
00195    flags &= ~OBJ_SEARCH_MASK;
00196    flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
00197    __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
00198 
00199    return NULL;
00200 }

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 41 of file astobj2_container.c.

References __ao2_ref(), __ao2_ref_debug(), ao2_t_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, empty, ao2_container_node::my_container, NULL, ao2_container_node::obj, and ao2_container::v_table.

Referenced by internal_ao2_iterator_next(), and internal_ao2_traverse().

00043 {
00044    struct ao2_container *container = node->my_container;
00045 
00046    if (container == NULL && (flags & AO2_UNLINK_NODE_DEC_COUNT)) {
00047       return 0;
00048    }
00049 
00050    if ((flags & AO2_UNLINK_NODE_UNLINK_OBJECT)
00051       && !(flags & AO2_UNLINK_NODE_NOUNREF_OBJECT)) {
00052       if (tag) {
00053          __ao2_ref_debug(node->obj, -1, tag, file, line, func);
00054       } else {
00055          ao2_t_ref(node->obj, -1, "Remove obj from container");
00056       }
00057    }
00058 
00059    node->obj = NULL;
00060 
00061    if (flags & AO2_UNLINK_NODE_DEC_COUNT) {
00062       ast_atomic_fetchadd_int(&container->elements, -1);
00063 #if defined(AO2_DEBUG)
00064       {
00065          int empty = container->nodes - container->elements;
00066 
00067          if (container->max_empty_nodes < empty) {
00068             container->max_empty_nodes = empty;
00069          }
00070          if (container->v_table->unlink_stat) {
00071             container->v_table->unlink_stat(container, node);
00072          }
00073       }
00074 #endif   /* defined(AO2_DEBUG) */
00075    }
00076 
00077    if (flags & AO2_UNLINK_NODE_UNREF_NODE) {
00078       /* Remove node from container */
00079       __ao2_ref(node, -1);
00080    }
00081 
00082    return 1;
00083 }

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:
self Container to check integrity.
flags OBJ_NOLOCK if a lock is already held on the container.
Return values:
0 on success.
-1 on error.

Definition at line 869 of file astobj2_container.c.

References ao2_rdlock, ao2_unlock, ast_assert, is_ao2_object(), and OBJ_NOLOCK.

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

00870 {
00871    int res = 0;
00872 
00873    if (!is_ao2_object(self) || !self->v_table) {
00874       /* Sanity checks. */
00875       ast_assert(0);
00876       return -1;
00877    }
00878 #if defined(AO2_DEBUG)
00879    if (!self->v_table->integrity) {
00880       /* No ingetrigy check available.  Assume container is ok. */
00881       return 0;
00882    }
00883 
00884    if (!(flags & OBJ_NOLOCK)) {
00885       ao2_rdlock(self);
00886    }
00887    res = self->v_table->integrity(self);
00888    if (!(flags & OBJ_NOLOCK)) {
00889       ao2_unlock(self);
00890    }
00891 #endif   /* defined(AO2_DEBUG) */
00892    return res;
00893 }

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 36 of file astobj2_container.c.

References ast_atomic_fetchadd_int(), and ao2_container::elements.

Referenced by __ast_data_register(), __ast_manager_event_multichan(), __queues_show(), _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_endpoints(), ami_show_resource_lists(), ao2_iterator_count(), app_is_finished(), ari_show(), ast_active_channels(), ast_ari_applications_list(), ast_ari_websocket_events_event_websocket(), ast_bridge_transfer_attended(), ast_bridge_transfer_blind(), ast_cdr_unregister(), ast_data_search_match(), 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(), ast_sorcery_create(), ast_sorcery_delete(), 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(), cleanup(), cli_display_parking_lot(), cli_fax_show_sessions(), cli_tps_report(), control_command_count(), control_wait(), create_local_sdp(), create_sound_blob(), data_odbc_provider_handler(), data_provider_release(), data_provider_release_all(), device_state_cb(), dial_state_process_bridge_enter(), do_timing(), endelm(), format_ami_aor_handler(), get_device_state_causing_channels(), global_loaded_observer(), grow(), handle_cli_sound_show(), handle_feature_show(), handle_negotiated_sdp(), handle_registrations(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), insert_test_vector(), ip_identify(), load_common(), locals_show(), lock_broker(), match_filter(), meetme_data_provider_get(), member_add_to_queue(), mid_test_sync(), mwi_subscription_mailboxes_str(), native_bridge_is_capable(), native_rtp_bridge_compatible(), object_type_loaded_observer(), one_protocol(), parking_lot_remove_if_unused(), pjsip_acf_dial_contacts_read(), presence_state_cb(), process_config(), pthread_timer_open(), queue_exec(), queue_function_mem_read(), queued_set_size(), queued_task_pushed(), queues_data_provider_get_helper(), rx_task(), send_unsolicited_mwi_notify(), shrink(), single_state_process_bridge_enter(), sip_send_all_registers(), sip_show_objects(), sla_in_use(), smdi_load(), sorcery_object_load(), system_create_resolver_and_set_nameservers(), test_ao2_iteration(), test_cel_peer_strings_match(), test_container_clone(), test_sub(), threadpool_send_state_changed(), try_calling(), unload_module(), and xmpp_show_clients().

00037 {
00038    return ast_atomic_fetchadd_int(&c->elements, 0);
00039 }

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:
self Container to dump.
flags OBJ_NOLOCK if a lock is already held on the container.
name Container name. (NULL if anonymous)
where User data needed by prnt to determine where to put output.
prnt Print output callback function to use.
prnt_obj Callback function to print the given object's key. (NULL if not available)
Returns:
Nothing

Definition at line 805 of file astobj2_container.c.

References ao2_rdlock, ao2_unlock, ast_assert, is_ao2_object(), and OBJ_NOLOCK.

Referenced by astobj2_test_1_helper(), and test_traversal_sorted().

00806 {
00807    if (!is_ao2_object(self) || !self->v_table) {
00808       prnt(where, "Invalid container\n");
00809       ast_assert(0);
00810       return;
00811    }
00812 
00813    if (!(flags & OBJ_NOLOCK)) {
00814       ao2_rdlock(self);
00815    }
00816    if (name) {
00817       prnt(where, "Container name: %s\n", name);
00818    }
00819 #if defined(AO2_DEBUG)
00820    if (self->v_table->dump) {
00821       self->v_table->dump(self, where, prnt, prnt_obj);
00822    } else
00823 #endif   /* defined(AO2_DEBUG) */
00824    {
00825       prnt(where, "Container dump not available.\n");
00826    }
00827    if (!(flags & OBJ_NOLOCK)) {
00828       ao2_unlock(self);
00829    }
00830 }

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:
dest Container to copy src object references into.
src Container to copy all object references from.
flags OBJ_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:
0 on success.
-1 on error.

Definition at line 712 of file astobj2_container.c.

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(), __ao2_container_clone_debug(), cli_aor_get_container(), cli_endpoint_get_container(), and cli_get_container().

00713 {
00714    void *obj;
00715    int res = 0;
00716 
00717    if (!(flags & OBJ_NOLOCK)) {
00718       ao2_rdlock(src);
00719       ao2_wrlock(dest);
00720    }
00721    obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
00722    if (obj) {
00723       /* Failed to put this obj into the dest container. */
00724       ao2_t_ref(obj, -1, "Failed to put this object into the dest container.");
00725 
00726       /* Remove all items from the dest container. */
00727       __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
00728          NULL);
00729       res = -1;
00730    }
00731    if (!(flags & OBJ_NOLOCK)) {
00732       ao2_unlock(dest);
00733       ao2_unlock(src);
00734    }
00735 
00736    return res;
00737 }

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:
name Name to register the container under.
self Container to register.
prnt_obj Callback function to print the given object's key. (NULL if not available)
Return values:
0 on success.
-1 on error.

Definition at line 971 of file astobj2_container.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_t_alloc_options, ao2_t_link, and ao2_t_ref.

Referenced by ast_bridging_init(), ast_cdr_engine_init(), and ast_channels_init().

00972 {
00973    int res = 0;
00974 #if defined(AO2_DEBUG)
00975    struct ao2_reg_container *reg;
00976 
00977    reg = ao2_t_alloc_options(sizeof(*reg) + strlen(name), ao2_reg_destructor,
00978       AO2_ALLOC_OPT_LOCK_NOLOCK, "Container registration object.");
00979    if (!reg) {
00980       return -1;
00981    }
00982 
00983    /* Fill in registered entry */
00984    ao2_t_ref(self, +1, "Registering container.");
00985    reg->registered = self;
00986    reg->prnt_obj = prnt_obj;
00987    strcpy(reg->name, name);/* safe */
00988 
00989    if (!ao2_t_link(reg_containers, reg, "Save registration object.")) {
00990       res = -1;
00991    }
00992 
00993    ao2_t_ref(reg, -1, "Done registering container.");
00994 #endif   /* defined(AO2_DEBUG) */
00995    return res;
00996 }

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:
self Container to display statistics.
flags OBJ_NOLOCK if a lock is already held on the container.
name Container name. (NULL if anonymous)
where User data needed by prnt to determine where to put output.
prnt Print output callback function to use.
Returns:
Nothing

Definition at line 832 of file astobj2_container.c.

References ao2_rdlock, ao2_unlock, ast_assert, is_ao2_object(), and OBJ_NOLOCK.

Referenced by astobj2_test_1_helper(), and test_traversal_sorted().

00833 {
00834    if (!is_ao2_object(self) || !self->v_table) {
00835       prnt(where, "Invalid container\n");
00836       ast_assert(0);
00837       return;
00838    }
00839 
00840    if (!(flags & OBJ_NOLOCK)) {
00841       ao2_rdlock(self);
00842    }
00843    if (name) {
00844       prnt(where, "Container name: %s\n", name);
00845    }
00846    prnt(where, "Number of objects: %d\n", self->elements);
00847 #if defined(AO2_DEBUG)
00848    prnt(where, "Number of nodes: %d\n", self->nodes);
00849    prnt(where, "Number of empty nodes: %d\n", self->nodes - self->elements);
00850    /*
00851     * XXX
00852     * If the max_empty_nodes count gets out of single digits you
00853     * likely have a code path where ao2_iterator_destroy() is not
00854     * called.
00855     *
00856     * Empty nodes do not harm the container but they do make
00857     * container operations less efficient.
00858     */
00859    prnt(where, "Maximum empty nodes: %d\n", self->max_empty_nodes);
00860    if (self->v_table->stats) {
00861       self->v_table->stats(self, where, prnt);
00862    }
00863 #endif   /* defined(AO2_DEBUG) */
00864    if (!(flags & OBJ_NOLOCK)) {
00865       ao2_unlock(self);
00866    }
00867 }

void ao2_container_unregister ( const char *  name  ) 

Unregister a container for CLI stats and integrity check.

Since:
12.0.0
Parameters:
name Name the container is registered under.
Returns:
Nothing

Definition at line 998 of file astobj2_container.c.

References ao2_t_find, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by bridge_cleanup(), cdr_engine_shutdown(), and channels_shutdown().

00999 {
01000 #if defined(AO2_DEBUG)
01001    ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_SEARCH_KEY,
01002       "Unregister container");
01003 #endif   /* defined(AO2_DEBUG) */
01004 }

void ao2_iterator_cleanup ( struct ao2_iterator iter  ) 

Definition at line 558 of file astobj2_container.c.

References ao2_iterator_destroy().

Referenced by create_local_sdp(), and handle_negotiated_sdp().

00559 {
00560    if (iter) {
00561       ao2_iterator_destroy(iter);
00562    }
00563 }

int ao2_iterator_count ( struct ao2_iterator iter  ) 

Get a count of the iterated container objects.

Parameters:
iter the iterator to query
Return values:
The number of objects in the iterated container

Definition at line 651 of file astobj2_container.c.

References ao2_container_count(), and ao2_iterator::c.

Referenced by create_local_sdp(), and handle_negotiated_sdp().

00652 {
00653    return ao2_container_count(iter->c);
00654 }

void ao2_iterator_destroy ( struct ao2_iterator iter  ) 

Destroy a container iterator.

Parameters:
iter the iterator to destroy
Return values:
none This function will release the container reference held by the iterator and any other resources it may be holding.

Definition at line 543 of file astobj2_container.c.

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

Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __find_call(), __iax2_show_peers(), __queues_show(), __test_cel_generate_peer_str(), _sip_show_peers(), aco_set_defaults(), action_agents(), action_confbridgelistrooms(), action_coreshowchannels(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_presencestatelist(), add_ice_to_sdp(), add_ice_to_stream(), agent_show_requested(), agents_post_apply_config(), agents_sweep(), alias_show(), ao2_iterator_cleanup(), app_to_json(), 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_data_iterator_end(), ast_data_search_match(), ast_endpoint_snapshot_create(), 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_sip_for_each_contact(), ast_sorcery_objectset_create2(), ast_sorcery_objectset_json_create(), ast_sorcery_retrieve_by_fields(), ast_sorcery_retrieve_by_id(), ast_sorcery_retrieve_by_regex(), 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(), 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_console_active(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_show_channels(), cli_tps_report(), compare_weight(), complete_bridge_profile_name(), complete_bridge_stasis(), complete_confbridge_name(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_menu_name(), complete_queue(), complete_queue_remove_member(), 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_prestart_dispatch_all(), data_filter_find(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), destroy_pvts(), device_state_cb(), dial_state_process_bridge_enter(), dialgroup_read(), disable_marked_lots(), dump_queue_members(), endpoint_receives_unsolicited_mwi_for_mailbox(), 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_transferee(), 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_odbc_show(), handle_cli_sound_show(), handle_cli_status(), 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(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), 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(), manager_show_registry(), manager_sip_peer_status(), mark_lots_as_disabled(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), msg_func_write(), multihomed_get_udp_transport(), mwi_initial_events(), mwi_mailbox_delete_all(), mwi_mailbox_get(), mwi_subscription_mailboxes_str(), num_available_members(), parking_lot_get_space(), peers_data_provider_get(), pjsip_acf_dial_contacts_read(), pjsip_aor_function_read(), poke_all_peers(), pp_each_user_helper(), presence_state_cb(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), remove_all_configured_parking_lot_extensions(), remove_pending_parking_lot_extensions(), rt_handle_member_record(), session_shutdown(), set_member_paused(), set_member_value(), set_transfer_variables_all(), show_codecs(), single_state_process_bridge_enter(), sip_keepalive_all_peers(), 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_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_stations(), sla_show_trunks(), stasis_app_mailboxes_to_json(), stop_streams(), system_create_resolver_and_set_nameservers(), test_ao2_callback_traversal(), test_ao2_iteration(), test_container_clone(), test_expected_duplicates(), tps_taskprocessor_tab_complete(), try_calling(), unbound_config_preapply(), unload_module(), update_queue(), update_realtime_members(), users_data_provider_get(), xmpp_pubsub_create_affiliations(), xmpp_show_buddies(), and xmpp_show_clients().

00544 {
00545    /* Release any last container node reference. */
00546    ao2_iterator_restart(iter);
00547 
00548    /* Release the iterated container reference. */
00549    ao2_t_ref(iter->c, -1, "Unref iterator in ao2_iterator_destroy");
00550    iter->c = NULL;
00551 
00552    /* Free the malloced iterator. */
00553    if (iter->flags & AO2_ITERATOR_MALLOCD) {
00554       ast_free(iter);
00555    }
00556 }

struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
) [read]

Create an iterator for a container.

initialize an iterator so we start from the first object

Definition at line 499 of file astobj2_container.c.

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

Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), __test_cel_generate_peer_str(), aco_set_defaults(), action_agents(), action_confbridgelistrooms(), action_coreshowchannels(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_presencestatelist(), add_ice_to_sdp(), add_ice_to_stream(), agent_show_requested(), agents_post_apply_config(), alias_show(), app_to_json(), 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_data_iterator_init(), ast_data_search_match(), ast_endpoint_snapshot_create(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_init(), ast_pickup_find_by_group(), ast_print_namedgroups(), ast_sip_for_each_contact(), ast_sorcery_objectset_create2(), ast_sorcery_objectset_json_create(), ast_sorcery_retrieve_by_fields(), ast_sorcery_retrieve_by_id(), ast_sorcery_retrieve_by_regex(), 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(), 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_console_active(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_show_channels(), cli_tps_report(), compare_weight(), complete_bridge_profile_name(), complete_bridge_stasis(), complete_confbridge_name(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_menu_name(), complete_queue(), complete_queue_remove_member(), 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_prestart_dispatch_all(), data_filter_find(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), destroy_pvts(), device_state_cb(), dial_state_process_bridge_enter(), dialgroup_read(), disable_marked_lots(), dump_queue_members(), 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_transferee(), 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_odbc_show(), handle_cli_sound_show(), handle_cli_status(), 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(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), internal_ao2_traverse(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), 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(), manager_show_registry(), manager_sip_peer_status(), mark_lots_as_disabled(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), msg_func_write(), multihomed_get_udp_transport(), mwi_initial_events(), mwi_mailbox_delete_all(), mwi_mailbox_get(), mwi_subscription_mailboxes_str(), num_available_members(), parking_lot_get_space(), peers_data_provider_get(), pjsip_acf_dial_contacts_read(), pjsip_aor_function_read(), poke_all_peers(), pp_each_user_helper(), presence_state_cb(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), remove_all_configured_parking_lot_extensions(), remove_pending_parking_lot_extensions(), rt_handle_member_record(), session_shutdown(), set_member_paused(), set_member_value(), set_transfer_variables_all(), show_codecs(), single_state_process_bridge_enter(), sip_keepalive_all_peers(), 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_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_stations(), sla_show_trunks(), stasis_app_mailboxes_to_json(), stop_streams(), system_create_resolver_and_set_nameservers(), test_ao2_iteration(), test_container_clone(), tps_taskprocessor_tab_complete(), try_calling(), unbound_config_preapply(), unload_module(), update_queue(), update_realtime_members(), users_data_provider_get(), xmpp_pubsub_create_affiliations(), xmpp_show_buddies(), and xmpp_show_clients().

00500 {
00501    struct ao2_iterator a = {
00502       .c = c,
00503       .flags = flags
00504    };
00505 
00506    ao2_t_ref(c, +1, "Init iterator with container.");
00507 
00508    return a;
00509 }

void ao2_iterator_restart ( struct ao2_iterator iter  ) 

Restart an iteration.

Parameters:
iter the 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.
Return values:
none 

Definition at line 511 of file astobj2_container.c.

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

Referenced by ao2_iterator_destroy().

00512 {
00513    /* Release the last container node reference if we have one. */
00514    if (iter->last_node) {
00515       enum ao2_lock_req orig_lock;
00516 
00517       /*
00518        * Do a read lock in case the container node unref does not
00519        * destroy the node.  If the container node is destroyed then
00520        * the lock will be upgraded to a write lock.
00521        */
00522       if (iter->flags & AO2_ITERATOR_DONTLOCK) {
00523          orig_lock = __adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
00524       } else {
00525          orig_lock = AO2_LOCK_REQ_MUTEX;
00526          ao2_rdlock(iter->c);
00527       }
00528 
00529       __ao2_ref(iter->last_node, -1);
00530       iter->last_node = NULL;
00531 
00532       if (iter->flags & AO2_ITERATOR_DONTLOCK) {
00533          __adjust_lock(iter->c, orig_lock, 0);
00534       } else {
00535          ao2_unlock(iter->c);
00536       }
00537    }
00538 
00539    /* The iteration is no longer complete. */
00540    iter->complete = 0;
00541 }

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 177 of file astobj2_container.c.

References CMP_MATCH, and CMP_STOP.

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

00178 {
00179    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00180 }

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

special callback that matches all

Definition at line 220 of file astobj2_container.c.

References CMP_MATCH.

Referenced by internal_ao2_traverse().

00221 {
00222    return CMP_MATCH;
00223 }

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 228 of file astobj2_container.c.

References CMP_MATCH.

Referenced by internal_ao2_traverse().

00229 {
00230    return CMP_MATCH;
00231 }

void container_destruct ( void *  _c  ) 

Definition at line 656 of file astobj2_container.c.

References __ao2_callback(), ast_atomic_fetchadd_int(), ao2_container_methods::destroy, ao2_container::destroying, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and ao2_container::v_table.

Referenced by __ao2_container_alloc_hash(), __ao2_container_alloc_hash_debug(), __ao2_container_alloc_rbtree(), and __ao2_container_alloc_rbtree_debug().

00657 {
00658    struct ao2_container *c = _c;
00659 
00660    /* Unlink any stored objects in the container. */
00661    c->destroying = 1;
00662    __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00663 
00664    /* Perform any extra container cleanup. */
00665    if (c->v_table && c->v_table->destroy) {
00666       c->v_table->destroy(c);
00667    }
00668 
00669 #if defined(AO2_DEBUG)
00670    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00671 #endif
00672 }

void container_destruct_debug ( void *  _c  ) 

Definition at line 674 of file astobj2_container.c.

References __ao2_callback_debug(), ast_atomic_fetchadd_int(), ao2_container_methods::destroy, ao2_container::destroying, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and ao2_container::v_table.

Referenced by __ao2_container_alloc_hash_debug(), and __ao2_container_alloc_rbtree_debug().

00675 {
00676    struct ao2_container *c = _c;
00677 
00678    /* Unlink any stored objects in the container. */
00679    c->destroying = 1;
00680    __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
00681       "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
00682 
00683    /* Perform any extra container cleanup. */
00684    if (c->v_table && c->v_table->destroy) {
00685       c->v_table->destroy(c);
00686    }
00687 
00688 #if defined(AO2_DEBUG)
00689    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00690 #endif
00691 }

int container_init ( void   ) 

Definition at line 1203 of file astobj2_container.c.

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().

01204 {
01205 #if defined(AO2_DEBUG)
01206    reg_containers = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK,
01207       AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_reg_sort_cb, NULL,
01208       "Container registration container.");
01209    if (!reg_containers) {
01210       return -1;
01211    }
01212 
01213    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01214    ast_register_cleanup(container_cleanup);
01215 #endif   /* defined(AO2_DEBUG) */
01216 
01217    return 0;
01218 }

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

Definition at line 705 of file astobj2_container.c.

References __ao2_link(), CMP_MATCH, CMP_STOP, and OBJ_NOLOCK.

Referenced by ao2_container_dup().

00706 {
00707    struct ao2_container *dest = arg;
00708 
00709    return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
00710 }

static void* internal_ao2_iterator_next ( struct ao2_iterator iter,
const char *  tag,
const char *  file,
int  line,
const char *  func 
) [static]

Definition at line 568 of file astobj2_container.c.

References __adjust_lock(), __ao2_ref(), __ao2_ref_debug(), __container_unlink_node_debug(), AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_t_ref, AO2_UNLINK_NODE_DEC_COUNT, ao2_unlock, ao2_wrlock, ast_assert, ao2_iterator::c, ao2_iterator::complete, ao2_iterator::flags, is_ao2_object(), ao2_container_methods::iterator_next, ao2_iterator::last_node, NULL, ao2_container_node::obj, and ao2_container::v_table.

Referenced by __ao2_iterator_next(), and __ao2_iterator_next_debug().

00569 {
00570    enum ao2_lock_req orig_lock;
00571    struct ao2_container_node *node;
00572    void *ret;
00573 
00574    if (!is_ao2_object(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) {
00575       /* Sanity checks. */
00576       ast_assert(0);
00577       return NULL;
00578    }
00579 
00580    if (iter->complete) {
00581       /* Don't return any more objects. */
00582       return NULL;
00583    }
00584 
00585    if (iter->flags & AO2_ITERATOR_DONTLOCK) {
00586       if (iter->flags & AO2_ITERATOR_UNLINK) {
00587          orig_lock = __adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
00588       } else {
00589          orig_lock = __adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
00590       }
00591    } else {
00592       orig_lock = AO2_LOCK_REQ_MUTEX;
00593       if (iter->flags & AO2_ITERATOR_UNLINK) {
00594          ao2_wrlock(iter->c);
00595       } else {
00596          ao2_rdlock(iter->c);
00597       }
00598    }
00599 
00600    node = iter->c->v_table->iterator_next(iter->c, iter->last_node, iter->flags);
00601    if (node) {
00602       ret = node->obj;
00603 
00604       if (iter->flags & AO2_ITERATOR_UNLINK) {
00605          /* Transfer the object ref from the container to the returned object. */
00606          __container_unlink_node_debug(node, AO2_UNLINK_NODE_DEC_COUNT, tag, file, line, func);
00607 
00608          /* Transfer the container's node ref to the iterator. */
00609       } else {
00610          /* Bump ref of returned object */
00611          if (tag) {
00612             __ao2_ref_debug(ret, +1, tag, file, line, func);
00613          } else {
00614             ao2_t_ref(ret, +1, "Next iterator object.");
00615          }
00616 
00617          /* Bump the container's node ref for the iterator. */
00618          __ao2_ref(node, +1);
00619       }
00620    } else {
00621       /* The iteration has completed. */
00622       iter->complete = 1;
00623       ret = NULL;
00624    }
00625 
00626    /* Replace the iterator's node */
00627    if (iter->last_node) {
00628       __ao2_ref(iter->last_node, -1);
00629    }
00630    iter->last_node = node;
00631 
00632    if (iter->flags & AO2_ITERATOR_DONTLOCK) {
00633       __adjust_lock(iter->c, orig_lock, 0);
00634    } else {
00635       ao2_unlock(iter->c);
00636    }
00637 
00638    return ret;
00639 }

static int internal_ao2_link ( struct ao2_container self,
void *  obj_new,
int  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
) [static]

Definition at line 100 of file astobj2_container.c.

References __adjust_lock(), __ao2_ref(), 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_unlock, ao2_wrlock, ast_assert, ast_atomic_fetchadd_int(), ast_log, is_ao2_object(), ao2_container_node::is_linked, LOG_ERROR, and OBJ_NOLOCK.

Referenced by __ao2_link(), and __ao2_link_debug().

00101 {
00102    int res;
00103    enum ao2_lock_req orig_lock;
00104    struct ao2_container_node *node;
00105 
00106    if (!is_ao2_object(obj_new) || !is_ao2_object(self)
00107       || !self->v_table || !self->v_table->new_node || !self->v_table->insert) {
00108       /* Sanity checks. */
00109       ast_assert(0);
00110       return 0;
00111    }
00112 
00113    if (flags & OBJ_NOLOCK) {
00114       orig_lock = __adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
00115    } else {
00116       ao2_wrlock(self);
00117       orig_lock = AO2_LOCK_REQ_MUTEX;
00118    }
00119 
00120    res = 0;
00121    node = self->v_table->new_node(self, obj_new, tag, file, line, func);
00122    if (node) {
00123 #if defined(AO2_DEBUG)
00124       if (ao2_container_check(self, OBJ_NOLOCK)) {
00125          ast_log(LOG_ERROR, "Container integrity failed before insert.\n");
00126       }
00127 #endif   /* defined(AO2_DEBUG) */
00128 
00129       /* Insert the new node. */
00130       switch (self->v_table->insert(self, node)) {
00131       case AO2_CONTAINER_INSERT_NODE_INSERTED:
00132          node->is_linked = 1;
00133          ast_atomic_fetchadd_int(&self->elements, 1);
00134 #if defined(AO2_DEBUG)
00135          AO2_DEVMODE_STAT(++self->nodes);
00136          if (self->v_table->link_stat) {
00137             self->v_table->link_stat(self, node);
00138          }
00139 #endif   /* defined(AO2_DEBUG) */
00140          /* Fall through */
00141       case AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED:
00142 #if defined(AO2_DEBUG)
00143          if (ao2_container_check(self, OBJ_NOLOCK)) {
00144             ast_log(LOG_ERROR, "Container integrity failed after insert or replace.\n");
00145          }
00146 #endif   /* defined(AO2_DEBUG) */
00147          res = 1;
00148          break;
00149       case AO2_CONTAINER_INSERT_NODE_REJECTED:
00150          __ao2_ref(node, -1);
00151          break;
00152       }
00153    }
00154 
00155    if (flags & OBJ_NOLOCK) {
00156       __adjust_lock(self, orig_lock, 0);
00157    } else {
00158       ao2_unlock(self);
00159    }
00160 
00161    return res;
00162 }

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 257 of file astobj2_container.c.

References __adjust_lock(), __ao2_link(), __ao2_link_debug(), __ao2_ref(), __ao2_ref_debug(), __container_unlink_node_debug(), 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_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_assert, ast_calloc, cb_true(), cb_true_data(), CMP_MATCH, CMP_STOP, is_ao2_object(), match(), NULL, ao2_container_node::obj, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, and OBJ_UNLINK.

Referenced by __ao2_callback(), __ao2_callback_data(), __ao2_callback_data_debug(), and __ao2_callback_debug().

00260 {
00261    void *ret;
00262    ao2_callback_fn *cb_default = NULL;
00263    ao2_callback_data_fn *cb_withdata = NULL;
00264    struct ao2_container_node *node;
00265    void *traversal_state;
00266 
00267    enum ao2_lock_req orig_lock;
00268    struct ao2_container *multi_container = NULL;
00269    struct ao2_iterator *multi_iterator = NULL;
00270 
00271    if (!is_ao2_object(self) || !self->v_table || !self->v_table->traverse_first
00272       || !self->v_table->traverse_next) {
00273       /* Sanity checks. */
00274       ast_assert(0);
00275       return NULL;
00276    }
00277 
00278    /*
00279     * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
00280     * turned off.  This if statement checks for the special condition
00281     * where multiple items may need to be returned.
00282     */
00283    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
00284       /* we need to return an ao2_iterator with the results,
00285        * as there could be more than one. the iterator will
00286        * hold the only reference to a container that has all the
00287        * matching objects linked into it, so when the iterator
00288        * is destroyed, the container will be automatically
00289        * destroyed as well.
00290        */
00291       multi_container = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL,
00292          NULL, "OBJ_MULTIPLE return container creation");
00293       if (!multi_container) {
00294          return NULL;
00295       }
00296       if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
00297          ao2_t_ref(multi_container, -1, "OBJ_MULTIPLE interator creation failed.");
00298          return NULL;
00299       }
00300    }
00301 
00302    if (!cb_fn) {
00303       /* Match everything if no callback match function provided. */
00304       if (type == AO2_CALLBACK_WITH_DATA) {
00305          cb_withdata = cb_true_data;
00306       } else {
00307          cb_default = cb_true;
00308       }
00309    } else {
00310       /*
00311        * We do this here to avoid the per object casting penalty (even
00312        * though that is probably optimized away anyway).
00313        */
00314       if (type == AO2_CALLBACK_WITH_DATA) {
00315          cb_withdata = cb_fn;
00316       } else {
00317          cb_default = cb_fn;
00318       }
00319    }
00320 
00321    /* avoid modifications to the content */
00322    if (flags & OBJ_NOLOCK) {
00323       if (flags & OBJ_UNLINK) {
00324          orig_lock = __adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
00325       } else {
00326          orig_lock = __adjust_lock(self, AO2_LOCK_REQ_RDLOCK, 1);
00327       }
00328    } else {
00329       orig_lock = AO2_LOCK_REQ_MUTEX;
00330       if (flags & OBJ_UNLINK) {
00331          ao2_wrlock(self);
00332       } else {
00333          ao2_rdlock(self);
00334       }
00335    }
00336 
00337    /* Create a buffer for the traversal state. */
00338    traversal_state = alloca(AO2_TRAVERSAL_STATE_SIZE);
00339 
00340    ret = NULL;
00341    for (node = self->v_table->traverse_first(self, flags, arg, traversal_state);
00342       node;
00343       node = self->v_table->traverse_next(self, traversal_state, node)) {
00344       int match;
00345 
00346       /* Visit the current node. */
00347       match = (CMP_MATCH | CMP_STOP);
00348       if (type == AO2_CALLBACK_WITH_DATA) {
00349          match &= cb_withdata(node->obj, arg, data, flags);
00350       } else {
00351          match &= cb_default(node->obj, arg, flags);
00352       }
00353       if (match == 0) {
00354          /* no match, no stop, continue */
00355          continue;
00356       }
00357       if (match == CMP_STOP) {
00358          /* no match but stop, we are done */
00359          break;
00360       }
00361 
00362       /*
00363        * CMP_MATCH is set here
00364        *
00365        * we found the object, performing operations according to flags
00366        */
00367       if (node->obj) {
00368          /* The object is still in the container. */
00369          if (!(flags & OBJ_NODATA)) {
00370             /*
00371              * We are returning the object, record the value.  It is
00372              * important to handle this case before the unlink.
00373              */
00374             if (multi_container) {
00375                /*
00376                 * Link the object into the container that will hold the
00377                 * results.
00378                 */
00379                if (tag) {
00380                   __ao2_link_debug(multi_container, node->obj, flags,
00381                      tag, file, line, func);
00382                } else {
00383                   __ao2_link(multi_container, node->obj, flags);
00384                }
00385             } else {
00386                ret = node->obj;
00387                /* Returning a single object. */
00388                if (!(flags & OBJ_UNLINK)) {
00389                   /*
00390                    * Bump the ref count since we are not going to unlink and
00391                    * transfer the container's object ref to the returned object.
00392                    */
00393                   if (tag) {
00394                      __ao2_ref_debug(ret, 1, tag, file, line, func);
00395                   } else {
00396                      ao2_t_ref(ret, 1, "Traversal found object");
00397                   }
00398                }
00399             }
00400          }
00401 
00402          if (flags & OBJ_UNLINK) {
00403             int ulflag = AO2_UNLINK_NODE_UNREF_NODE | AO2_UNLINK_NODE_DEC_COUNT;
00404             if (multi_container || (flags & OBJ_NODATA)) {
00405                ulflag |= AO2_UNLINK_NODE_UNLINK_OBJECT;
00406             }
00407             __container_unlink_node_debug(node, ulflag, tag, file, line, func);
00408          }
00409       }
00410 
00411       if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
00412          /* We found our only (or last) match, so we are done */
00413          break;
00414       }
00415    }
00416    if (self->v_table->traverse_cleanup) {
00417       self->v_table->traverse_cleanup(traversal_state);
00418    }
00419    if (node) {
00420       /* Unref the node from self->v_table->traverse_first/traverse_next() */
00421       __ao2_ref(node, -1);
00422    }
00423 
00424    if (flags & OBJ_NOLOCK) {
00425       __adjust_lock(self, orig_lock, 0);
00426    } else {
00427       ao2_unlock(self);
00428    }
00429 
00430    /* if multi_container was created, we are returning multiple objects */
00431    if (multi_container) {
00432       *multi_iterator = ao2_iterator_init(multi_container,
00433          AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
00434       ao2_t_ref(multi_container, -1,
00435          "OBJ_MULTIPLE for multiple objects traversal complete.");
00436       return multi_iterator;
00437    } else {
00438       return ret;
00439    }
00440 }


Generated on Thu Apr 16 06:29:01 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6