[svn-commits] rmudgett: branch rmudgett/ao2_red_black r371822 - in /team/rmudgett/ao2_red_b...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Aug 28 17:04:53 CDT 2012


Author: rmudgett
Date: Tue Aug 28 17:04:48 2012
New Revision: 371822

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=371822
Log:
* Add CLI command "astobj2 container dump <name>"

* Make ao2_container_dump() useable by the unit test framework.

Modified:
    team/rmudgett/ao2_red_black/include/asterisk/astobj2.h
    team/rmudgett/ao2_red_black/main/astobj2.c
    team/rmudgett/ao2_red_black/main/channel.c
    team/rmudgett/ao2_red_black/tests/test_astobj2.c

Modified: team/rmudgett/ao2_red_black/include/asterisk/astobj2.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_red_black/include/asterisk/astobj2.h?view=diff&rev=371822&r1=371821&r2=371822
==============================================================================
--- team/rmudgett/ao2_red_black/include/asterisk/astobj2.h (original)
+++ team/rmudgett/ao2_red_black/include/asterisk/astobj2.h Tue Aug 28 17:04:48 2012
@@ -1315,6 +1315,33 @@
 typedef void (ao2_prnt_fn)(void *where, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
 
 /*!
+ * \brief Print object key.
+ * \since 12.0.0
+ *
+ * \param v_obj A pointer to the object we want the key printed.
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ *
+ * \return Nothing
+ */
+typedef void (ao2_prnt_obj_fn)(void *v_obj, void *where, ao2_prnt_fn *prnt);
+
+/*!
+ * \brief Display contents of the specified container.
+ * \since 12.0.0
+ *
+ * \param self Container to dump.
+ * \param flags OBJ_NOLOCK if a lock is already held on the container.
+ * \param name Container name.  (NULL if anonymous)
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
+ *
+ * \return Nothing
+ */
+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);
+
+/*!
  * \brief Display statistics of the specified container.
  * \since 12.0.0
  *
@@ -1346,11 +1373,12 @@
  *
  * \param name Name to register the container under.
  * \param self Container to register.
+ * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
  *
  * \retval 0 on success.
  * \retval -1 on error.
  */
-int ao2_container_register(const char *name, struct ao2_container *self);
+int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj);
 
 /*!
  * \brief Unregister a container for CLI stats and integrity check.

Modified: team/rmudgett/ao2_red_black/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_red_black/main/astobj2.c?view=diff&rev=371822&r1=371821&r2=371822
==============================================================================
--- team/rmudgett/ao2_red_black/main/astobj2.c (original)
+++ team/rmudgett/ao2_red_black/main/astobj2.c Tue Aug 28 17:04:48 2012
@@ -888,6 +888,18 @@
  * \retval NULL on error or no more nodes in the container.
  */
 typedef struct ao2_container_node *(*ao2_iterator_next_fn)(struct ao2_container *self, struct ao2_container_node *prev, enum ao2_iterator_flags flags);
+
+/*!
+ * \brief Display contents of the specified container.
+ *
+ * \param self Container to dump.
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
+ *
+ * \return Nothing
+ */
+typedef void (*ao2_container_display)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj);
 
 /*!
  * \brief Display statistics of the specified container.
@@ -937,6 +949,8 @@
 	/*! Find the next iteration element in the container. */
 	ao2_iterator_next_fn iterator_next;
 #if defined(AST_DEVMODE)
+	/*! Display container contents. (Method for debug purposes) */
+	ao2_container_display dump;
 	/*! Display container debug statistics. (Method for debug purposes) */
 	ao2_container_statistics stats;
 	/*! Perform an integrity check on the container. (Method for debug purposes) */
@@ -1807,6 +1821,33 @@
 	return clone;
 }
 
+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)
+{
+	if (!INTERNAL_OBJ(self) || !self->v_table) {
+		prnt(where, "Invalid container\n");
+		ast_assert(0);
+		return;
+	}
+
+	if (!(flags & OBJ_NOLOCK)) {
+		ao2_rdlock(self);
+	}
+	if (name) {
+		prnt(where, "Container name: %s\n", name);
+	}
+#if defined(AST_DEVMODE)
+	if (self->v_table->dump) {
+		self->v_table->dump(self, where, prnt, prnt_obj);
+	} else
+#endif	/* defined(AST_DEVMODE) */
+	{
+		prnt(where, "Container dump not available.\n");
+	}
+	if (!(flags & OBJ_NOLOCK)) {
+		ao2_unlock(self);
+	}
+}
+
 void ao2_container_stats(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt)
 {
 	if (!INTERNAL_OBJ(self) || !self->v_table) {
@@ -2764,6 +2805,60 @@
 #if defined(AST_DEVMODE)
 /*!
  * \internal
+ * \brief Display contents of the specified container.
+ * \since 12.0.0
+ *
+ * \param self Container to dump.
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
+ *
+ * \return Nothing
+ */
+static void hash_ao2_dump(struct ao2_container_hash *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
+{
+#define FORMAT  "%6s, %16s, %16s, %16s, %16s, %s\n"
+#define FORMAT2 "%6d, %16p, %16p, %16p, %16p, "
+
+	int bucket;
+	int suppressed_buckets = 0;
+	struct hash_bucket_node *node;
+
+	prnt(where, "Number of buckets: %d\n\n", self->n_buckets);
+
+	prnt(where, FORMAT, "Bucket", "Node", "Prev", "Next", "Obj", "Key");
+	for (bucket = 0; bucket < self->n_buckets; ++bucket) {
+		node = AST_DLLIST_FIRST(&self->buckets[bucket].list);
+		if (node) {
+			suppressed_buckets = 0;
+			do {
+				prnt(where, FORMAT2,
+					bucket,
+					node,
+					AST_DLLIST_PREV(node, links),
+					AST_DLLIST_NEXT(node, links),
+					node->common.obj);
+				if (node->common.obj && prnt_obj) {
+					prnt_obj(node->common.obj, where, prnt);
+				}
+				prnt(where, "\n");
+
+				node = AST_DLLIST_NEXT(node, links);
+			} while (node);
+		} else if (!suppressed_buckets) {
+			suppressed_buckets = 1;
+			prnt(where, "...\n");
+		}
+	}
+
+#undef FORMAT
+#undef FORMAT2
+}
+#endif	/* defined(AST_DEVMODE) */
+
+#if defined(AST_DEVMODE)
+/*!
+ * \internal
  * \brief Display statistics of the specified container.
  * \since 12.0.0
  *
@@ -2788,9 +2883,9 @@
 	prnt(where, FORMAT, "Bucket", "Objects", "Max");
 	for (bucket = 0; bucket < self->n_buckets; ++bucket) {
 		if (self->buckets[bucket].max_elements) {
+			suppressed_buckets = 0;
 			prnt(where, FORMAT2, bucket, self->buckets[bucket].elements,
 				self->buckets[bucket].max_elements);
-			suppressed_buckets = 0;
 		} else if (!suppressed_buckets) {
 			suppressed_buckets = 1;
 			prnt(where, "...\n");
@@ -2971,6 +3066,7 @@
 	.iterator_next = (ao2_iterator_next_fn) hash_ao2_iterator_next,
 	.destroy = (ao2_container_destroy_fn) hash_ao2_destroy,
 #if defined(AST_DEVMODE)
+	.dump = (ao2_container_display) hash_ao2_dump,
 	.stats = (ao2_container_statistics) hash_ao2_stats,
 	.integrity = (ao2_container_integrity) hash_ao2_integrity,
 #endif	/* defined(AST_DEVMODE) */
@@ -3539,30 +3635,6 @@
 	node->parent = child;
 	child->right = node;
 }
-
-#if 0
-/*!
- * \internal
- * \brief Dump the tree structure.
- * \since 12.0.0
- *
- * \param self Container to operate upon.
- * \param header What is being dumped.
- *
- * \return Nothing
- */
-static void rb_dump(struct ao2_container_rbtree *self, const char *header)
-{
-	struct rbtree_node *node;
-
-	printf("%s\n", header);
-	printf("%16s, %16s, %16s, %16s, %c, %16s\n", "Node", "Parent", "Left", "Right", 'T', "Obj");
-	for (node = self->root; node; node = rb_node_pre(node)) {
-		printf("%16p, %16p, %16p, %16p, %c, %16p\n",
-			node, node->parent, node->left, node->right, node->is_red ? 'R' : 'B', node->common.obj);
-	}
-}
-#endif
 
 /*!
  * \internal
@@ -3919,9 +3991,6 @@
 			ast_log(LOG_ERROR, "Container integrity failed before node deletion.\n");
 		}
 #endif	/* defined(AO2_DEBUG) && defined(AST_DEVMODE) */
-//BUGBUG
-//		rb_dump(my_container, "Pre deletion");
-//		printf("%16p Deleting node\n", doomed);
 		rb_delete_node(my_container, doomed);
 #if defined(AO2_DEBUG) && defined(AST_DEVMODE)
 		if (!my_container->common.destroying
@@ -4767,6 +4836,46 @@
 		ast_assert(0);
 	}
 }
+
+#if defined(AST_DEVMODE)
+/*!
+ * \internal
+ * \brief Display contents of the specified container.
+ * \since 12.0.0
+ *
+ * \param self Container to dump.
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
+ *
+ * \return Nothing
+ */
+static void rb_ao2_dump(struct ao2_container_rbtree *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
+{
+#define FORMAT  "%16s, %16s, %16s, %16s, %5s, %16s, %s\n"
+#define FORMAT2 "%16p, %16p, %16p, %16p, %5s, %16p, "
+
+	struct rbtree_node *node;
+
+	prnt(where, FORMAT, "Node", "Parent", "Left", "Right", "Color", "Obj", "Key");
+	for (node = self->root; node; node = rb_node_pre(node)) {
+		prnt(where, FORMAT2,
+			node,
+			node->parent,
+			node->left,
+			node->right,
+			node->is_red ? "Red" : "Black",
+			node->common.obj);
+		if (node->common.obj && prnt_obj) {
+			prnt_obj(node->common.obj, where, prnt);
+		}
+		prnt(where, "\n");
+	}
+
+#undef FORMAT
+#undef FORMAT2
+}
+#endif	/* defined(AST_DEVMODE) */
 
 #if defined(AST_DEVMODE)
 /*!
@@ -5032,6 +5141,7 @@
 	.iterator_next = (ao2_iterator_next_fn) rb_ao2_iterator_next,
 	.destroy = (ao2_container_destroy_fn) rb_ao2_destroy,
 #if defined(AST_DEVMODE)
+	.dump = (ao2_container_display) rb_ao2_dump,
 	.stats = (ao2_container_statistics) rb_ao2_stats,
 	.integrity = (ao2_container_integrity) rb_ao2_integrity,
 #endif	/* defined(AST_DEVMODE) */
@@ -5244,6 +5354,8 @@
 struct ao2_reg_container {
 	/*! Registered container pointer. */
 	struct ao2_container *registered;
+	/*! Callback function to print the given object's key. (NULL if not available) */
+	ao2_prnt_obj_fn *prnt_obj;
 	/*! Name container registered under. */
 	char name[1];
 };
@@ -5297,7 +5409,7 @@
 }
 #endif	/* defined(AST_DEVMODE) */
 
-int ao2_container_register(const char *name, struct ao2_container *self)
+int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
 {
 	int res = 0;
 #if defined(AST_DEVMODE)
@@ -5312,6 +5424,7 @@
 	/* Fill in registered entry */
 	ao2_ref(self, +1);
 	reg->registered = self;
+	reg->prnt_obj = prnt_obj;
 	strcpy(reg->name, name);/* safe */
 
 	if (!ao2_link(reg_containers, reg)) {
@@ -5403,6 +5516,42 @@
 #endif	/* defined(AST_DEVMODE) */
 
 #if defined(AST_DEVMODE)
+/*! \brief Show container contents - CLI command */
+static char *handle_cli_astobj2_container_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	const char *name;
+	struct ao2_reg_container *reg;
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "astobj2 container dump";
+		e->usage =
+			"Usage: astobj2 container dump <name>\n"
+			"	Show contents of the container <name>.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return complete_container_names(a);
+	}
+
+	if (a->argc != 4) {
+		return CLI_SHOWUSAGE;
+	}
+
+	name = a->argv[3];
+	reg = ao2_find(reg_containers, name, OBJ_KEY);
+	if (reg) {
+		ao2_container_dump(reg->registered, 0, name, (void *) &a->fd, cli_output,
+			reg->prnt_obj);
+		ao2_ref(reg, -1);
+	} else {
+		ast_cli(a->fd, "Container '%s' not found.\n", name);
+	}
+
+	return CLI_SUCCESS;
+}
+#endif	/* defined(AST_DEVMODE) */
+
+#if defined(AST_DEVMODE)
 /*! \brief Show container statistics - CLI command */
 static char *handle_cli_astobj2_container_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
@@ -5480,6 +5629,7 @@
 	AST_CLI_DEFINE(handle_astobj2_test, "Test astobj2"),
 #endif /* defined(AO2_DEBUG) */
 #if defined(AST_DEVMODE)
+	AST_CLI_DEFINE(handle_cli_astobj2_container_dump, "Show container contents"),
 	AST_CLI_DEFINE(handle_cli_astobj2_container_stats, "Show container statistics"),
 	AST_CLI_DEFINE(handle_cli_astobj2_container_check, "Perform a container integrity check"),
 #endif	/* defined(AST_DEVMODE) */

Modified: team/rmudgett/ao2_red_black/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_red_black/main/channel.c?view=diff&rev=371822&r1=371821&r2=371822
==============================================================================
--- team/rmudgett/ao2_red_black/main/channel.c (original)
+++ team/rmudgett/ao2_red_black/main/channel.c Tue Aug 28 17:04:48 2012
@@ -8485,12 +8485,33 @@
 	AST_DATA_ENTRY("/asterisk/core/channeltypes", &channeltypes_provider),
 };
 
+/*!
+ * \internal
+ * \brief Print channel object key (name).
+ * \since 12.0.0
+ *
+ * \param v_obj A pointer to the object we want the key printed.
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ *
+ * \return Nothing
+ */
+static void prnt_channel_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
+{
+	struct ast_channel *chan = v_obj;
+
+	if (!chan) {
+		return;
+	}
+	prnt(where, "%s", ast_channel_name(chan));
+}
+
 void ast_channels_init(void)
 {
 	channels = ao2_container_alloc(NUM_CHANNEL_BUCKETS,
 			ast_channel_hash_cb, ast_channel_cmp_cb);
 	if (channels) {
-		ao2_container_register("channels", channels);
+		ao2_container_register("channels", channels, prnt_channel_key);
 	}
 
 	ast_cli_register_multiple(cli_channel, ARRAY_LEN(cli_channel));

Modified: team/rmudgett/ao2_red_black/tests/test_astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ao2_red_black/tests/test_astobj2.c?view=diff&rev=371822&r1=371821&r2=371822
==============================================================================
--- team/rmudgett/ao2_red_black/tests/test_astobj2.c (original)
+++ team/rmudgett/ao2_red_black/tests/test_astobj2.c Tue Aug 28 17:04:48 2012
@@ -202,6 +202,27 @@
 
 		return test_left->i - test_right->i;
 	}
+}
+
+/*!
+ * \internal
+ * \brief Print test object key.
+ * \since 12.0.0
+ *
+ * \param v_obj A pointer to the object we want the key printed.
+ * \param where User data needed by prnt to determine where to put output.
+ * \param prnt Print output callback function to use.
+ *
+ * \return Nothing
+ */
+static void test_prnt_obj(void *v_obj, void *where, ao2_prnt_fn *prnt)
+{
+	struct test_obj *obj = v_obj;
+
+	if (!obj) {
+		return;
+	}
+	prnt(where, "%6d-%d", obj->i, obj->dup_number);
 }
 
 /*!
@@ -732,6 +753,7 @@
 		ast_test_status_update(test, "container integrity check failed\n");
 		res = AST_TEST_FAIL;
 	}
+	ao2_container_dump(c1, 0, "BUGBUG c1", (void *) test, (ao2_prnt_fn *) ast_test_debug, test_prnt_obj);
 	ao2_container_stats(c1, 0, "BUGBUG c1", (void *) test, (ao2_prnt_fn *) ast_test_debug);
 
 cleanup:




More information about the svn-commits mailing list