[asterisk-commits] mmichelson: branch 1.4 r109713 - /branches/1.4/apps/app_queue.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 18 15:52:16 CDT 2008


Author: mmichelson
Date: Tue Mar 18 15:52:15 2008
New Revision: 109713

URL: http://svn.digium.com/view/asterisk?view=rev&rev=109713
Log:
This patch makes it so that all queue member status changes are handled through device state
code. This removes several problems people were seeing where their queue members would get into
an "unknown" state. Huge props go to atis on this one since he was the one who found the code
section that was causing the problem and proposed the solution. I just wrote what he suggested :)

(closes issue #12127)
Reported by: atis
Patches:
      12127v3.patch uploaded by putnopvut (license 60)
Tested by: atis, jvandal


Modified:
    branches/1.4/apps/app_queue.c

Modified: branches/1.4/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/apps/app_queue.c?view=diff&rev=109713&r1=109712&r2=109713
==============================================================================
--- branches/1.4/apps/app_queue.c (original)
+++ branches/1.4/apps/app_queue.c Tue Mar 18 15:52:15 2008
@@ -572,65 +572,32 @@
 	int state;
 	char dev[0];
 };
-/*! \brief set a member's status based on device state of that member's interface*/
-static void *handle_statechange(struct statechange *sc)
-{
-	struct call_queue *q;
+
+static int update_status(const char *interface, const int status)
+{
 	struct member *cur;
 	struct ao2_iterator mem_iter;
-	struct member_interface *curint;
-	char *loc;
-	char *technology;
-
-	technology = ast_strdupa(sc->dev);
-	loc = strchr(technology, '/');
-	if (loc) {
-		*loc++ = '\0';
-	} else {
-		return NULL;
-	}
-
-	AST_LIST_LOCK(&interfaces);
-	AST_LIST_TRAVERSE(&interfaces, curint, list) {
-		char *interface;
-		char *slash_pos;
-		interface = ast_strdupa(curint->interface);
-		if ((slash_pos = strchr(interface, '/')))
-			if ((slash_pos = strchr(slash_pos + 1, '/')))
-				*slash_pos = '\0';
-
-		if (!strcasecmp(interface, sc->dev))
-			break;
-	}
-	AST_LIST_UNLOCK(&interfaces);
-
-	if (!curint) {
-		if (option_debug > 2)
-			ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state));
-		return NULL;
-	}
-
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
+	struct call_queue *q;
+
 	AST_LIST_LOCK(&queues);
 	AST_LIST_TRAVERSE(&queues, q, list) {
 		ast_mutex_lock(&q->lock);
 		mem_iter = ao2_iterator_init(q->members, 0);
 		while ((cur = ao2_iterator_next(&mem_iter))) {
-			char *interface;
+			char *tmp_interface;
 			char *slash_pos;
-			interface = ast_strdupa(cur->interface);
-			if ((slash_pos = strchr(interface, '/')))
+			tmp_interface = ast_strdupa(cur->interface);
+			if ((slash_pos = strchr(tmp_interface, '/')))
 				if ((slash_pos = strchr(slash_pos + 1, '/')))
 					*slash_pos = '\0';
 
-			if (strcasecmp(sc->dev, interface)) {
+			if (strcasecmp(interface, tmp_interface)) {
 				ao2_ref(cur, -1);
 				continue;
 			}
 
-			if (cur->status != sc->state) {
-				cur->status = sc->state;
+			if (cur->status != status) {
+				cur->status = status;
 				if (q->maskmemberstatus) {
 					ao2_ref(cur, -1);
 					continue;
@@ -654,6 +621,49 @@
 		ast_mutex_unlock(&q->lock);
 	}
 	AST_LIST_UNLOCK(&queues);
+
+	return 0;
+}
+
+/*! \brief set a member's status based on device state of that member's interface*/
+static void *handle_statechange(struct statechange *sc)
+{
+	struct member_interface *curint;
+	char *loc;
+	char *technology;
+
+	technology = ast_strdupa(sc->dev);
+	loc = strchr(technology, '/');
+	if (loc) {
+		*loc++ = '\0';
+	} else {
+		return NULL;
+	}
+
+	AST_LIST_LOCK(&interfaces);
+	AST_LIST_TRAVERSE(&interfaces, curint, list) {
+		char *interface;
+		char *slash_pos;
+		interface = ast_strdupa(curint->interface);
+		if ((slash_pos = strchr(interface, '/')))
+			if ((slash_pos = strchr(slash_pos + 1, '/')))
+				*slash_pos = '\0';
+
+		if (!strcasecmp(interface, sc->dev))
+			break;
+	}
+	AST_LIST_UNLOCK(&interfaces);
+
+	if (!curint) {
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state));
+		return NULL;
+	}
+
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
+
+	update_status(sc->dev, sc->state);
 
 	return NULL;
 }
@@ -1685,54 +1695,6 @@
 	}
 }
 
-static int update_status(struct call_queue *q, struct member *member, int status)
-{
-	struct member *cur;
-	struct ao2_iterator mem_iter;
-
-	/* Since a reload could have taken place, we have to traverse the list to
-		be sure it's still valid */
-	ast_mutex_lock(&q->lock);
-	mem_iter = ao2_iterator_init(q->members, 0);
-	while ((cur = ao2_iterator_next(&mem_iter))) {
-		if (member != cur) {
-			ao2_ref(cur, -1);
-			continue;
-		}
-
-		cur->status = status;
-		if (!q->maskmemberstatus) {
-			manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
-				"Queue: %s\r\n"
-				"Location: %s\r\n"
-				"MemberName: %s\r\n"
-				"Membership: %s\r\n"
-				"Penalty: %d\r\n"
-				"CallsTaken: %d\r\n"
-				"LastCall: %d\r\n"
-				"Status: %d\r\n"
-				"Paused: %d\r\n",
-				q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static",
-				cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
-		}
-		ao2_ref(cur, -1);
-	}
-	ast_mutex_unlock(&q->lock);
-	return 0;
-}
-
-static int update_dial_status(struct call_queue *q, struct member *member, int status)
-{
-	if (status == AST_CAUSE_BUSY)
-		status = AST_DEVICE_BUSY;
-	else if (status == AST_CAUSE_UNREGISTERED)
-		status = AST_DEVICE_UNAVAILABLE;
-	else if (status == AST_CAUSE_NOSUCHDRIVER)
-		status = AST_DEVICE_INVALID;
-	else
-		status = AST_DEVICE_UNKNOWN;
-	return update_status(q, member, status);
-}
 
 /* traverse all defined queues which have calls waiting and contain this member
    return 0 if no other queue has precedence (higher weight) or 1 if found  */
@@ -1869,7 +1831,8 @@
 		if (qe->chan->cdr)
 			ast_cdr_busy(qe->chan->cdr);
 		tmp->stillgoing = 0;
-		update_dial_status(qe->parent, tmp->member, status);
+
+		update_status(tmp->member->interface, ast_device_state(tmp->member->interface));
 
 		ast_mutex_lock(&qe->parent->lock);
 		qe->parent->rrpos++;
@@ -1877,8 +1840,7 @@
 
 		(*busies)++;
 		return 0;
-	} else if (status != tmp->oldstatus)
-		update_dial_status(qe->parent, tmp->member, status);
+	}
 	
 	tmp->chan->appl = "AppQueue";
 	tmp->chan->data = "(Outgoing Line)";
@@ -2208,8 +2170,6 @@
 						ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
 					/* Setup parameters */
 					o->chan = ast_request(tech, in->nativeformats, stuff, &status);
-					if (status != o->oldstatus)
-						update_dial_status(qe->parent, o->member, status);						
 					if (!o->chan) {
 						ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
 						o->stillgoing = 0;
@@ -2788,8 +2748,8 @@
 	else
 		to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
 	++qe->pending;
+	ast_mutex_unlock(&qe->parent->lock);
 	ring_one(qe, outgoing, &numbusies);
-	ast_mutex_unlock(&qe->parent->lock);
 	if (use_weight)
 		AST_LIST_UNLOCK(&queues);
 	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);




More information about the asterisk-commits mailing list