[svn-commits] rmudgett: branch rmudgett/ao2_enhancements r370759 - in /team/rmudgett/ao2_en...

SVN commits to the Digium repositories svn-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 svn-commits mailing list