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

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Aug 27 12:16:11 CDT 2012


Author: rmudgett
Date: Mon Aug 27 12:16:07 2012
New Revision: 371722

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=371722
Log:
Add rbtree dev-mode stats.

Modified:
    team/rmudgett/ao2_red_black/include/asterisk/astobj2.h
    team/rmudgett/ao2_red_black/main/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=371722&r1=371721&r2=371722
==============================================================================
--- team/rmudgett/ao2_red_black/include/asterisk/astobj2.h (original)
+++ team/rmudgett/ao2_red_black/include/asterisk/astobj2.h Mon Aug 27 12:16:07 2012
@@ -1298,6 +1298,18 @@
 #define ao2_container_clone(orig, flags)		__ao2_container_clone(orig, flags)
 
 #endif
+
+/*!
+ * \brief Display statistics of the specified container.
+ * \since 12.0.0
+ *
+ * \param self Container to display statistics.
+ * \param fd File descriptor to send output.
+ * \param prnt Print output callback function to use.
+ *
+ * \return Nothing
+ */
+void ao2_container_stats(struct ao2_container *self, int fd, void (*prnt)(int fd, const char *fmt, ...) __attribute__((format(printf, 2, 3))));
 
 /*!
  * \brief Perform an integrity check on the specified container.

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=371722&r1=371721&r2=371722
==============================================================================
--- team/rmudgett/ao2_red_black/main/astobj2.c (original)
+++ team/rmudgett/ao2_red_black/main/astobj2.c Mon Aug 27 12:16:07 2012
@@ -92,6 +92,12 @@
 	struct __priv_data priv_data;
 	void *user_data[0];
 };
+
+#if defined(AST_DEVMODE)
+#define AO2_DEVMODE_STAT(stat)	stat
+#else
+#define AO2_DEVMODE_STAT(stat)
+#endif	/* defined(AST_DEVMODE) */
 
 #ifdef AO2_DEBUG
 struct ao2_stats {
@@ -1039,7 +1045,7 @@
 			node->is_linked = 1;
 			ast_atomic_fetchadd_int(&self->elements, 1);
 #if defined(AST_DEVMODE)
-			++self->nodes;
+			AO2_DEVMODE_STAT(++self->nodes);
 			switch (self->v_table->type) {
 			case AO2_CONTAINER_RTTI_HASH:
 				hash_ao2_link_node_stat(self, node);
@@ -1761,19 +1767,7 @@
 	return clone;
 }
 
-#if defined(AST_DEVMODE)
-/*!
- * \internal
- * \brief Display statistics of the specified container.
- * \since 12.0.0
- *
- * \param self Container to display statistics.
- * \param fd File descriptor to send output.
- * \param prnt Print output callback function to use.
- *
- * \return Nothing
- */
-static void ao2_container_stats(struct ao2_container *self, int fd, void (*prnt)(int fd, const char *fmt, ...) __attribute__((format(printf, 2, 3))))
+void ao2_container_stats(struct ao2_container *self, int fd, void (*prnt)(int fd, const char *fmt, ...) __attribute__((format(printf, 2, 3))))
 {
 	if (!INTERNAL_OBJ(self) || !self->v_table) {
 		prnt(fd, "Invalid container\n");
@@ -1783,6 +1777,7 @@
 
 	ao2_rdlock(self);
 	prnt(fd, "Number of objects: %d\n", self->elements);
+#if defined(AST_DEVMODE)
 	prnt(fd, "Number of nodes: %d\n", self->nodes);
 	prnt(fd, "Number of empty nodes: %d\n", self->nodes - self->elements);
 	/*
@@ -1798,9 +1793,9 @@
 	if (self->v_table->stats) {
 		self->v_table->stats(self, fd, prnt);
 	}
+#endif	/* defined(AST_DEVMODE) */
 	ao2_unlock(self);
 }
-#endif	/* defined(AST_DEVMODE) */
 
 int ao2_container_check(struct ao2_container *self, enum search_flags flags)
 {
@@ -1975,9 +1970,7 @@
 		bucket = &my_container->buckets[doomed->my_bucket];
 		AST_DLLIST_REMOVE(&bucket->list, doomed, links);
 
-#if defined(AST_DEVMODE)
-		--my_container->common.nodes;
-#endif	/* defined(AST_DEVMODE) */
+		AO2_DEVMODE_STAT(--my_container->common.nodes);
 	}
 
 	/*
@@ -3070,9 +3063,20 @@
 	struct ao2_container common;
 	/*! Root node of the tree.  NULL if the tree is empty. */
 	struct rbtree_node *root;
-/* BUGBUG need to add stats counters for fixup insert left/right cases 1-3 */
-/* BUGBUG need to add stats counters for fixup delete left/right cases 1-4 */
-/* BUGBUG need to add stats counter for delete in middle of tree. */
+#if defined(AST_DEVMODE)
+	struct {
+		/*! Fixup insert left cases 1-3 */
+		int fixup_insert_left[3];
+		/*! Fixup insert right cases 1-3 */
+		int fixup_insert_right[3];
+		/*! Fixup delete left cases 1-4 */
+		int fixup_delete_left[4];
+		/*! Fixup delete right cases 1-4 */
+		int fixup_delete_right[4];
+		/*! Deletion of node with number of children (0-2). */
+		int delete_children[3];
+	} stats;
+#endif	/* defined(AST_DEVMODE) */
 };
 
 /*!
@@ -3561,6 +3565,7 @@
 			ast_assert(sibling != NULL);
 			if (sibling->is_red) {
 				/* Case 1: The child's sibling is red. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_delete_left[0]);
 				sibling->is_red = 0;
 				child->parent->is_red = 1;
 				rb_rotate_left(self, child->parent);
@@ -3570,11 +3575,13 @@
 			if ((!sibling->left || !sibling->left->is_red)
 				&& (!sibling->right || !sibling->right->is_red)) {
 				/* Case 2: The sibling is black and both of its children are black. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_delete_left[1]);
 				sibling->is_red = 1;
 				child = child->parent;
 			} else {
 				if (!sibling->right || !sibling->right->is_red) {
 					/* Case 3: The sibling is black, its left child is red, and its right child is black. */
+					AO2_DEVMODE_STAT(++self->stats.fixup_delete_left[2]);
 					if (sibling->left) {
 						sibling->left->is_red = 0;
 					}
@@ -3584,6 +3591,7 @@
 					ast_assert(sibling != NULL);
 				}
 				/* Case 4: The sibling is black and its right child is red. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_delete_left[3]);
 				sibling->is_red = child->parent->is_red;
 				child->parent->is_red = 0;
 				if (sibling->right) {
@@ -3598,6 +3606,7 @@
 			ast_assert(sibling != NULL);
 			if (sibling->is_red) {
 				/* Case 1: The child's sibling is red. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_delete_right[0]);
 				sibling->is_red = 0;
 				child->parent->is_red = 1;
 				rb_rotate_right(self, child->parent);
@@ -3607,11 +3616,13 @@
 			if ((!sibling->right || !sibling->right->is_red)
 				&& (!sibling->left || !sibling->left->is_red)) {
 				/* Case 2: The sibling is black and both of its children are black. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_delete_right[1]);
 				sibling->is_red = 1;
 				child = child->parent;
 			} else {
 				if (!sibling->left || !sibling->left->is_red) {
 					/* Case 3: The sibling is black, its right child is red, and its left child is black. */
+					AO2_DEVMODE_STAT(++self->stats.fixup_delete_right[2]);
 					if (sibling->right) {
 						sibling->right->is_red = 0;
 					}
@@ -3621,6 +3632,7 @@
 					ast_assert(sibling != NULL);
 				}
 				/* Case 4: The sibling is black and its left child is red. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_delete_right[3]);
 				sibling->is_red = child->parent->is_red;
 				child->parent->is_red = 0;
 				if (sibling->left) {
@@ -3659,6 +3671,7 @@
 		 * Find the next child node and swap it with the doomed node in
 		 * the tree.
 		 */
+		AO2_DEVMODE_STAT(++self->stats.delete_children[2]);
 		next = rb_node_most_left(doomed->right);
 		SWAP(doomed->parent, next->parent);
 		SWAP(doomed->left, next->left);
@@ -3698,6 +3711,11 @@
 		if (!child) {
 			child = doomed->right;
 		}
+	}
+	if (child) {
+		AO2_DEVMODE_STAT(++self->stats.delete_children[1]);
+	} else {
+		AO2_DEVMODE_STAT(++self->stats.delete_children[0]);
 	}
 
 	need_fixup = (!doomed->is_red && !self->common.destroying);
@@ -3732,9 +3750,7 @@
 		}
 	}
 
-#if defined(AST_DEVMODE)
-	--self->common.nodes;
-#endif	/* defined(AST_DEVMODE) */
+	AO2_DEVMODE_STAT(--self->common.nodes);
 }
 
 /*!
@@ -3851,6 +3867,7 @@
 			/* The parent is a left child. */
 			if (g_parent->right && g_parent->right->is_red) {
 				/* Case 1: Push the black down from the grand parent node. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_insert_left[0]);
 				g_parent->right->is_red = 0;
 				g_parent->left->is_red = 0;
 				g_parent->is_red = 1;
@@ -3864,10 +3881,12 @@
 					 *
 					 * Which node is the grand parent does not change.
 					 */
+					AO2_DEVMODE_STAT(++self->stats.fixup_insert_left[1]);
 					node = node->parent;
 					rb_rotate_left(self, node);
 				}
 				/* Case 3: The node is a left child. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_insert_left[2]);
 				node->parent->is_red = 0;
 				g_parent->is_red = 1;
 				rb_rotate_right(self, g_parent);
@@ -3876,6 +3895,7 @@
 			/* The parent is a right child. */
 			if (g_parent->left && g_parent->left->is_red) {
 				/* Case 1: Push the black down from the grand parent node. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_insert_right[0]);
 				g_parent->left->is_red = 0;
 				g_parent->right->is_red = 0;
 				g_parent->is_red = 1;
@@ -3889,10 +3909,12 @@
 					 *
 					 * Which node is the grand parent does not change.
 					 */
+					AO2_DEVMODE_STAT(++self->stats.fixup_insert_right[1]);
 					node = node->parent;
 					rb_rotate_right(self, node);
 				}
 				/* Case 3: The node is a right child. */
+				AO2_DEVMODE_STAT(++self->stats.fixup_insert_right[2]);
 				node->parent->is_red = 0;
 				g_parent->is_red = 1;
 				rb_rotate_left(self, g_parent);
@@ -4588,6 +4610,48 @@
 		ast_assert(0);
 	}
 }
+
+#if defined(AST_DEVMODE)
+/*!
+ * \internal
+ * \brief Display statistics of the specified container.
+ * \since 12.0.0
+ *
+ * \param self Container to display statistics.
+ * \param fd File descriptor to send output.
+ * \param prnt Print output callback function to use.
+ *
+ * \note The container is already locked for reading.
+ *
+ * \return Nothing
+ */
+static void rb_ao2_stats(struct ao2_container_rbtree *self, int fd, void (*prnt)(int fd, const char *fmt, ...) __attribute__((format(printf, 2, 3))))
+{
+	int idx;
+
+	for (idx = 0; idx < ARRAY_LEN(self->stats.fixup_insert_left); ++idx) {
+		prnt(fd, "Number of left insert fixups case %d: %d\n", idx + 1,
+			self->stats.fixup_insert_left[idx]);
+	}
+	for (idx = 0; idx < ARRAY_LEN(self->stats.fixup_insert_right); ++idx) {
+		prnt(fd, "Number of right insert fixups case %d: %d\n", idx + 1,
+			self->stats.fixup_insert_right[idx]);
+	}
+
+	for (idx = 0; idx < ARRAY_LEN(self->stats.delete_children); ++idx) {
+		prnt(fd, "Number of nodes deleted with %d children: %d\n", idx,
+			self->stats.delete_children[idx]);
+	}
+	for (idx = 0; idx < ARRAY_LEN(self->stats.fixup_delete_left); ++idx) {
+		prnt(fd, "Number of left delete fixups case %d: %d\n", idx + 1,
+			self->stats.fixup_delete_left[idx]);
+	}
+	for (idx = 0; idx < ARRAY_LEN(self->stats.fixup_delete_right); ++idx) {
+		prnt(fd, "Number of right delete fixups case %d: %d\n", idx + 1,
+			self->stats.fixup_delete_right[idx]);
+	}
+}
+#endif	/* defined(AST_DEVMODE) */
 
 #if defined(AST_DEVMODE)
 /*!
@@ -4750,6 +4814,7 @@
 	.iterator_next = (ao2_iterator_next_fn) rb_ao2_iterator_next,
 	.destroy = (ao2_container_destroy_fn) rb_ao2_destroy,
 #if defined(AST_DEVMODE)
+	.stats = (ao2_container_statistics) rb_ao2_stats,
 	.integrity = (ao2_container_integrity) rb_ao2_integrity,
 #endif	/* defined(AST_DEVMODE) */
 };




More information about the svn-commits mailing list