[asterisk-commits] mmichelson: branch group/CCSS r227830 - /team/group/CCSS/main/ccss.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Nov 4 15:04:41 CST 2009


Author: mmichelson
Date: Wed Nov  4 15:04:38 2009
New Revision: 227830

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=227830
Log:
A couple of changes for ast_cc_monitor_failed taskprocessor callback.

The logic was just garbage before. it should work as it is supposed to now.
In addition, the cc_monitor_failed internal function will check if the current
state is CC_RECALLING. If it is, then the monitor failure will be ignored since
the call will result in the proper destructors being called.


Modified:
    team/group/CCSS/main/ccss.c

Modified: team/group/CCSS/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=227830&r1=227829&r2=227830
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Wed Nov  4 15:04:38 2009
@@ -2909,61 +2909,66 @@
 	int core_id;
 };
 
-static int pass_failure_up(struct ast_cc_monitor *monitor, struct ast_cc_monitor_link *parent_link, const int core_id)
-{
-	struct ast_cc_monitor *parent_monitor = cc_ref(parent_link->parent, "Ref parent monitor");
-	struct ast_cc_monitor_link *link_iter;
-
-	/* First things first, kill the link */
-	destroy_link(parent_link);
-
-	/* Next determine if the parent monitor also needs to pass info up. If the parent monitor
-	 * has no more links left with this core ID, then it means that it should also pass the
-	 * failure up.
-	 */
-	AST_LIST_TRAVERSE(&parent_monitor->child_links, link_iter, next_child) {
-		if (link_iter->core_id == core_id) {
-			break;
-		}
-	}
-
-	cc_unref(monitor, "Killed the link to the failed monitor. Unref it");
-
-	if (link_iter) {
-		/* There are still child links with this core ID, so this
-		 * monitor should not pass a failure up the tree
-		 */
-		cc_unref(parent_monitor, "Still child links available. Unref our local reference");
-		return 0;
-	}
-
-	if (parent_monitor->interface->monitor_class == AST_CC_ROOT_MONITOR) {
+static int pass_failure_up(struct ast_cc_monitor *monitor, const int core_id)
+{
+	struct ast_cc_monitor *parent_monitor = NULL;
+	struct ast_cc_monitor_link *child_link_iter;
+	struct ast_cc_monitor_link *parent_link_iter;
+
+	if (monitor->interface->monitor_class == AST_CC_ROOT_MONITOR) {
 		/* We've reached the top of the tree, which means that what may have
 		 * started as a localized failure has progressed to a global one instead.
 		 */
-		cc_unref(parent_monitor, "Parent is the root. Unref our local reference");
+		ast_log_dynamic_level(cc_logger_level, "All monitors for core %d have failed\n", core_id);
+		cc_unref(monitor, "monitor is the root. failure has reached the top");
 		return ast_cc_failed(core_id, "All monitors have failed");
 	}
 
-	/* The parent monitor is an extension monitor who no longer has any children with
-	 * this core_id. We need to pass the failure up to the next parent monitor in the tree.
-	 */
-	AST_LIST_TRAVERSE(&parent_monitor->parent_links, link_iter, next_parent) {
-		if (link_iter->core_id == core_id) {
+	/* Since this is not the root monitor, there SHOULD be a parent link with the
+	 * correct core_id. We need to cut it away.
+	 */
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&monitor->parent_links, parent_link_iter, next_parent) {
+		if (parent_link_iter->core_id == core_id) {
+			parent_monitor = cc_ref(parent_link_iter->parent, "Found a parent monitor perhaps");
+			AST_LIST_REMOVE_CURRENT(next_parent);
+			parent_link_iter->child->callbacks->cancel_available_timer(parent_link_iter->parent, 
+					core_id, &parent_link_iter->child_avail_id);
+			destroy_link(parent_link_iter);
 			break;
 		}
 	}
-
-	if (!link_iter) {
-		/* The parent monitor doesn't have a parent link with our core_id? WHAT?! */
-		cc_unref(parent_monitor, "Parent didn't have an upstream link with proper core ID. Unref");
-		return -1;
-	}
-
-	/* This invocation of pass_failure_up will result in the parent_monitor 
-	 * being unreffed properly, so we don't have to do it here.
-	 */
-	pass_failure_up(parent_monitor, link_iter, core_id);
+	AST_LIST_TRAVERSE_SAFE_END;
+
+	/* If this assertion fails, something is terribly wrong */
+	ast_assert(parent_monitor != NULL);
+
+	if (AST_LIST_EMPTY(&monitor->child_links) && AST_LIST_EMPTY(&monitor->parent_links)) {
+		/* No more links have references to this monitor, so unlink it */
+		ao2_t_unlink(cc_monitors, monitor, "Failed monitor is an orphan. Unlink it");
+	}
+
+	cc_unref(monitor, "Monitor failure has been taken care of. Unref");
+
+	/* Next determine if the parent monitor also needs to pass info up. If the parent monitor
+	 * has no more child links left with this core ID, then it means that it should also pass the
+	 * failure up.
+	 */
+	AST_LIST_TRAVERSE(&parent_monitor->child_links, child_link_iter, next_child) {
+		if (child_link_iter->core_id == core_id) {
+			/* There are still child links with this core ID, so this
+			 * monitor should not pass a failure up the tree
+			 */
+			cc_unref(parent_monitor, "Still child links available. Unref our local reference");
+			return 0;
+		}
+	}
+
+	/* The parent monitor is a monitor who no longer has any children with
+	 * this core_id. We need to pass the failure up to the next parent monitor in the tree.
+	 * This invocation of pass_failure_up will unref the parent_monitor. We don't need
+	 * to do it ourselves.
+	 */
+	pass_failure_up(parent_monitor, core_id);
 
 	return 0;
 }
@@ -2973,22 +2978,30 @@
 	struct cc_monitor_failure_data *failure_data = data;
 	int core_id = failure_data->core_id;
 	struct ast_cc_monitor *monitor = failure_data->monitor;
-	struct ast_cc_monitor_link *parent_link;
+	struct cc_core_instance *core_instance = find_cc_core_instance(core_id);
 
 	ast_free(failure_data);
 
-	AST_LIST_TRAVERSE(&monitor->parent_links, parent_link, next_parent) {
-		if (parent_link->core_id == core_id) {
-			break;
-		}
-	}
-
-	if (!parent_link) {
-		cc_unref(monitor, "Can't find a parent link to report failure on. Unref monitor.");
-		return -1;
-	}
-
-	return pass_failure_up(monitor, parent_link, core_id);
+	if (!core_instance) {
+		/* Odd */
+		cc_unref(monitor, "Couldn't find a matching core_instance. Unref monitor");
+		return -1;
+	}
+
+	if (core_instance->current_state == CC_RECALLING) {
+		/* If a monitor reports failure while the core is in the recalling state,
+		 * then that actually likely means that the downstream entity has sent
+		 * us a message to tear things down, but that CC actually completed successfully
+		 * at that point. Since we know that the core_instance will be destroyed when
+		 * CC completes here, we can simply ignore this and let things get destroyed
+		 * naturally
+		 */
+		ast_log_dynamic_level(cc_logger_level, "Ignoring monitor failure since we are in the recalling state\n");
+		cc_unref(monitor, "In recall state, no need to propagate failure. Unref");
+		return 0;
+	}
+
+	return pass_failure_up(monitor, core_id);
 }
 
 int ast_cc_monitor_failed(int core_id, const char *const monitor_name, const char * const monitor_type)




More information about the asterisk-commits mailing list