[asterisk-commits] rmudgett: branch rmudgett/ao2_enhancements r370759 - in /team/rmudgett/ao2_en...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Aug 2 19:50:02 CDT 2012
Author: rmudgett
Date: Thu Aug 2 19:49:58 2012
New Revision: 370759
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=370759
Log:
* Fix callers of the sort_fn to actually pass the expected node objects.
* Add OBJ_PARTIAL_KEY flag support to make the API consistent between
container types when using partial keys. Now multi-bucket hash containers
with a sort_fn can use the filtering ability of the sort function. The
OBJ_CONTINUE flag could have been used with the OBJ_KEY flag, but the
starting location would have been odd because the hash_fn would be
invoked.
* Clean up some comments.
Modified:
team/rmudgett/ao2_enhancements/include/asterisk/astobj2.h
team/rmudgett/ao2_enhancements/main/astobj2.c
Modified: team/rmudgett/ao2_enhancements/include/asterisk/astobj2.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_enhancements/include/asterisk/astobj2.h?view=diff&rev=370759&r1=370758&r2=370759
==============================================================================
--- team/rmudgett/ao2_enhancements/include/asterisk/astobj2.h (original)
+++ team/rmudgett/ao2_enhancements/include/asterisk/astobj2.h Thu Aug 2 19:49:58 2012
@@ -727,6 +727,8 @@
search will be done. If not, a traversal is done.
OBJ_KEY - if set, 'arg', is a search key item that is not an object.
Similar to OBJ_POINTER and mutually exclusive.
+ OBJ_PARTIAL_KEY - if set, 'arg', is a partial search key item that is not an object.
+ Similar to OBJ_KEY and mutually exclusive.
- \b ao2_callback(c, flags, fn, arg)
apply fn(obj, arg) to all objects in the container.
@@ -742,6 +744,8 @@
all the hash table 'buckets'..
OBJ_KEY - if set, 'arg', is a search key item that is not an object.
Similar to OBJ_POINTER and mutually exclusive.
+ OBJ_PARTIAL_KEY - if set, 'arg', is a partial search key item that is not an object.
+ Similar to OBJ_KEY and mutually exclusive.
- fn is a func that returns int, and takes 3 args:
(void *obj, void *arg, int flags);
obj is an object
@@ -806,8 +810,13 @@
CMP_STOP = 0x2, /*!< stop the search now */
};
-/*! \brief
- * Flags passed to ao2_callback(), ao2_hash_fn(), and ao2_sort_fn() to modify its behaviour.
+/*!
+ * \brief Flags passed to ao2_callback_fn(), ao2_hash_fn(), and ao2_sort_fn() to modify behaviour.
+ *
+ * \todo XXX OBJ_POINTER, OBJ_KEY, and OBJ_PARTIAL_KEY need to
+ * be put into a bit field like OBJ_ORDER_MASK since they are
+ * mutually exclusive. This change unfortunately is not
+ * backwards compatible.
*/
enum search_flags {
/*!
@@ -826,25 +835,30 @@
*/
OBJ_MULTIPLE = (1 << 2),
/*!
- * The given obj is an object of the same type as the one being
- * searched for, so use the object's hash and/or sort functions
- * for optimized searching.
- *
- * The matching function is unaffected (i.e. The cb_fn argument
- * to ao2_callback).
+ * \brief The arg parameter is an object of the same type.
+ *
+ * \details
+ * The arg parameter is an object of the same type as the one
+ * being searched for, so use the object's ao2_hash_fn and/or
+ * ao2_sort_fn functions for optimized searching.
+ *
+ * \note The supplied ao2_callback_fn is called after the
+ * container nodes have been filtered by the ao2_hash_fn and/or
+ * ao2_sort_fn functions.
+ *
+ * \note OBJ_POINTER, OBJ_KEY, and OBJ_PARTIAL_KEY are mutually
+ * exclusive.
*/
OBJ_POINTER = (1 << 3),
/*!
- * \brief Continue if a match is not found in the hashed out bucket
+ * \brief Continue if a match is not found.
*
* \details
- * This flag is to be used in combination with the OBJ_POINTER
- * or OBJ_KEY flags. This flag causes the entire container to
- * be searched for an object. The OBJ_POINTER or OBJ_KEY flags
- * just start the search where the search key specifies to
- * start. If the object is not found then the search
- * _continues_ until the search wraps around to the starting
- * point.
+ * This flag forces a whole container search. The OBJ_POINTER,
+ * OBJ_KEY, and OBJ_PARTIAL_KEY flags just specify where to
+ * start the search in the container. If the search is not
+ * stopped early then the search _continues_ until the search
+ * wraps around to the starting point.
*
* Normal searches start where the search key specifies to start
* and end when the search key indicates that the object is not
@@ -854,6 +868,9 @@
* keep searching through the rest of the buckets if a match is
* not found in the starting bucket defined by the hash value on
* the argument.
+ *
+ * \note The supplied ao2_callback_fn is called for every node
+ * in the container from the starting point.
*/
OBJ_CONTINUE = (1 << 4),
/*!
@@ -871,24 +888,47 @@
*/
OBJ_NOLOCK = (1 << 5),
/*!
- * \brief The data is a search key, but is not an object.
+ * \brief The arg parameter is a search key, but is not an object.
*
* \details
* This can be used when you want to be able to pass custom data
- * to the container's stored ao2_hash_fn, ao2_sort_fn, and ao2_find
- * ao2_callback_fn functions that is not a full object, but
- * perhaps just a string.
- *
- * \note OBJ_KEY and OBJ_POINTER are mutually exclusive options.
+ * to the container's stored ao2_hash_fn, ao2_sort_fn, and
+ * ao2_find ao2_callback_fn functions that is not a full object,
+ * but perhaps just a string.
+ *
+ * \note The supplied ao2_callback_fn is called after the
+ * container nodes have been filtered by the ao2_hash_fn and/or
+ * ao2_sort_fn functions.
+ *
+ * \note OBJ_POINTER, OBJ_KEY, and OBJ_PARTIAL_KEY are mutually
+ * exclusive.
*/
OBJ_KEY = (1 << 6),
+ /*!
+ * \brief The arg parameter is a partial search key similar to OBJ_KEY.
+ *
+ * \details
+ * The partial key can be used by the ao2_sort_fn to guide the
+ * search to find a contiguous subset of a sorted container.
+ * For example, a sorted container holds: "A", "B", "Bert",
+ * "Beth", "Earnie". Doing a partial key search with "B" will
+ * find the sorted subset of all held objects starting with "B".
+ *
+ * \note The supplied ao2_callback_fn is called after the
+ * container nodes have been filtered by the ao2_sort_fn
+ * function.
+ *
+ * \note OBJ_POINTER, OBJ_KEY, and OBJ_PARTIAL_KEY are mutually
+ * exclusive.
+ */
+ OBJ_PARTIAL_KEY = (1 << 7),
/*! \brief Traverse order option field mask. */
- OBJ_ORDER_MASK = (3 << 7),
+ OBJ_ORDER_MASK = (0x03 << 8),
/*! \brief Traverse in ascending order (First to last container object) */
- OBJ_ORDER_ASCENDING = (0 << 7),
+ OBJ_ORDER_ASCENDING = (0 << 8),
/*! \brief Traverse in descending order (Last to first container object) */
- OBJ_ORDER_DESCENDING = (1 << 7),
+ OBJ_ORDER_DESCENDING = (1 << 8),
/*!
* \brief Traverse in pre-order (Node then childeren, for tree container)
*
@@ -897,7 +937,7 @@
* hash containers, this also means ascending order because a
* binary tree can degenerate into a list.
*/
- OBJ_ORDER_PRE = (2 << 7),
+ OBJ_ORDER_PRE = (2 << 8),
/*!
* \brief Traverse in post-order (Childeren then node, for tree container)
*
@@ -906,7 +946,7 @@
* hash containers, this also means descending order because a
* binary tree can degenerate into a list.
*/
- OBJ_ORDER_POST = (3 << 7),
+ OBJ_ORDER_POST = (3 << 8),
};
/*!
@@ -974,6 +1014,9 @@
* \param obj pointer to the (user-defined part) of an object.
* \param arg callback argument from ao2_callback()
* \param flags flags from ao2_callback()
+ * OBJ_POINTER - if set, 'arg', is an object.
+ * OBJ_KEY - if set, 'arg', is a search key item that is not an object.
+ * OBJ_PARTIAL_KEY - if set, 'arg', is a partial search key item that is not an object.
*
* The return values are a combination of enum _cb_results.
* Callback functions are used to search or manipulate objects in a container.
@@ -989,6 +1032,9 @@
* \param arg callback argument from ao2_callback()
* \param data arbitrary data from ao2_callback()
* \param flags flags from ao2_callback()
+ * OBJ_POINTER - if set, 'arg', is an object.
+ * OBJ_KEY - if set, 'arg', is a search key item that is not an object.
+ * OBJ_PARTIAL_KEY - if set, 'arg', is a partial search key item that is not an object.
*
* The return values are a combination of enum _cb_results.
* Callback functions are used to search or manipulate objects in a container.
@@ -1000,6 +1046,7 @@
*
* \param obj pointer to the (user-defined part) of an object.
* \param flags flags from ao2_callback()
+ * OBJ_POINTER - if set, 'obj', is an object.
* OBJ_KEY - if set, 'obj', is a search key item that is not an object.
*
* \return Computed hash value.
@@ -1012,7 +1059,9 @@
* \param obj_left pointer to the (user-defined part) of an object.
* \param obj_right pointer to the (user-defined part) of an object.
* \param flags flags from ao2_callback()
+ * OBJ_POINTER - if set, 'obj_right', is an object.
* OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
+ * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
*
* \retval <0 if obj_left < obj_right
* \retval =0 if obj_left == obj_right
@@ -1455,6 +1504,7 @@
* Default is no.
* OBJ_POINTER the pointer is an object pointer
* OBJ_KEY the pointer is to a search key
+ * OBJ_PARTIAL_KEY the pointer is to a partial search key
*
* \note When the returned object is no longer in use, ao2_ref() should
* be used to free the additional reference possibly created by this function.
Modified: team/rmudgett/ao2_enhancements/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_enhancements/main/astobj2.c?view=diff&rev=370759&r1=370758&r2=370759
==============================================================================
--- team/rmudgett/ao2_enhancements/main/astobj2.c (original)
+++ team/rmudgett/ao2_enhancements/main/astobj2.c Thu Aug 2 19:49:58 2012
@@ -1552,7 +1552,7 @@
if (options & AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN) {
if (sort_fn) {
AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&bucket->list, cur, links) {
- cmp = sort_fn(cur, node, OBJ_POINTER);
+ cmp = sort_fn(cur->obj, node->obj, OBJ_POINTER);
if (cmp > 0) {
continue;
}
@@ -1584,7 +1584,7 @@
} else {
if (sort_fn) {
AST_DLLIST_TRAVERSE_SAFE_BEGIN(&bucket->list, cur, links) {
- cmp = sort_fn(cur, node, OBJ_POINTER);
+ cmp = sort_fn(cur->obj, node->obj, OBJ_POINTER);
if (cmp < 0) {
continue;
}
@@ -1804,7 +1804,7 @@
} else {
/* don't know, let's scan all buckets */
start = i = -1;
- sort_fn = NULL;
+ sort_fn = (flags & OBJ_PARTIAL_KEY) ? self->common.sort_fn : NULL;
}
/* determine the search boundaries */
@@ -1871,7 +1871,8 @@
if (sort_fn) {
int cmp;
- cmp = sort_fn(node, arg, flags & (OBJ_POINTER | OBJ_KEY));
+ cmp = sort_fn(node->obj, arg,
+ flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
if (descending) {
if (cmp > 0) {
match = 0;
@@ -2530,10 +2531,10 @@
char name[1];
};
-struct ao2_reg_key {
- /*! Length of partial key match. Zero if exact match. */
+struct ao2_reg_partial_key {
+ /*! Length of partial key match. */
int len;
- /*! Registration key name. */
+ /*! Registration partial key name. */
const char *name;
};
@@ -2552,13 +2553,13 @@
int cmp;
if (flags & OBJ_KEY) {
- const struct ao2_reg_key *key = obj_right;
-
- if (key->len) {
- cmp = strncasecmp(reg_left->name, key->name, key->len);
- } else {
- cmp = strcasecmp(reg_left->name, key->name);
- }
+ const char *name = obj_right;
+
+ cmp = strcasecmp(reg_left->name, name);
+ } else if (flags & OBJ_PARTIAL_KEY) {
+ const struct ao2_reg_partial_key *partial_key = obj_right;
+
+ cmp = strncasecmp(reg_left->name, partial_key->name, partial_key->len);
} else {
const struct ao2_reg_container *reg_right = obj_right;
@@ -2583,11 +2584,9 @@
{
int res = 0;
#if defined(AST_DEVMODE)
- size_t size;
struct ao2_reg_container *reg;
- size = strlen(name);
- reg = ao2_alloc_options(sizeof(*reg) + size, ao2_reg_destructor,
+ reg = ao2_alloc_options(sizeof(*reg) + strlen(name), ao2_reg_destructor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!reg) {
return -1;
@@ -2610,11 +2609,7 @@
void ao2_container_unregister(const char *name)
{
#if defined(AST_DEVMODE)
- struct ao2_reg_key key;
-
- key.len = 0;
- key.name = name;
- ao2_find(reg_containers, &key, OBJ_UNLINK | OBJ_NODATA | OBJ_KEY);
+ ao2_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_KEY);
#endif /* defined(AST_DEVMODE) */
}
@@ -2631,7 +2626,7 @@
#if defined(AST_DEVMODE)
static char *complete_container_names(struct ast_cli_args *a)
{
- struct ao2_reg_key key;
+ struct ao2_reg_partial_key partial_key;
struct ao2_reg_match which;
struct ao2_reg_container *reg;
char *name;
@@ -2640,11 +2635,12 @@
return NULL;
}
- key.len = strlen(a->word);
- key.name = a->word;
+ partial_key.len = strlen(a->word);
+ partial_key.name = a->word;
which.find_nth = a->n;
which.count = 0;
- reg = ao2_callback_data(reg_containers, OBJ_KEY, ao2_complete_reg_cb, &key, &which);
+ reg = ao2_callback_data(reg_containers, partial_key.len ? OBJ_PARTIAL_KEY : 0,
+ ao2_complete_reg_cb, &partial_key, &which);
if (reg) {
name = ast_strdup(reg->name);
ao2_ref(reg, -1);
@@ -2661,7 +2657,6 @@
{
const char *name;
struct ao2_reg_container *reg;
- struct ao2_reg_key key;
switch (cmd) {
case CLI_INIT:
@@ -2679,9 +2674,7 @@
}
name = a->argv[3];
- key.len = 0;
- key.name = name;
- reg = ao2_find(reg_containers, &key, OBJ_KEY);
+ reg = ao2_find(reg_containers, name, OBJ_KEY);
if (reg) {
ao2_container_stats(reg->registered, a->fd, ast_cli);
ao2_ref(reg, -1);
@@ -2699,7 +2692,6 @@
{
const char *name;
struct ao2_reg_container *reg;
- struct ao2_reg_key key;
switch (cmd) {
case CLI_INIT:
@@ -2717,9 +2709,7 @@
}
name = a->argv[3];
- key.len = 0;
- key.name = name;
- reg = ao2_find(reg_containers, &key, OBJ_KEY);
+ reg = ao2_find(reg_containers, name, OBJ_KEY);
if (reg) {
ast_cli(a->fd, "Container check of '%s': %s.\n", name,
ao2_container_check(reg->registered, 0) ? "failed" : "OK");
More information about the asterisk-commits
mailing list