[asterisk-commits] sgriepentrog: branch certified-11.6 r415867 - in /certified/branches/11.6: ./...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jun 12 11:27:40 CDT 2014


Author: sgriepentrog
Date: Thu Jun 12 11:27:36 2014
New Revision: 415867

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=415867
Log:
app_queue: delayed state can cause early leavewhenempty ringing

In app_queue, device state changes arrive in event messages and
update the queue member status value.  That value is checked in
get_member_status() to decide that the caller should leave when
there are no available members.  Although event messages can be
delayed by other activity, there is no adverse affect by lagged
status except in one specific case: there is only one available
member, it was just rung, and leavewhenempty is enabled set for
ringing members.  This change adds a direct check of the device
state only under this condition where the caller may be dropped
incorrectly, resolving this issue without affecting performance
of app_queue normally.

AST-1248 #close
Review: https://reviewboard.asterisk.org/r/3595/
Reported by: Thomas Arimont
........

Merged revisions 415833 from http://svn.asterisk.org/svn/asterisk/branches/1.8

Modified:
    certified/branches/11.6/   (props changed)
    certified/branches/11.6/apps/app_queue.c

Propchange: certified/branches/11.6/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: certified/branches/11.6/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.6/apps/app_queue.c?view=diff&rev=415867&r1=415866&r2=415867
==============================================================================
--- certified/branches/11.6/apps/app_queue.c (original)
+++ certified/branches/11.6/apps/app_queue.c Thu Jun 12 11:27:36 2014
@@ -1542,7 +1542,7 @@
  * is available, the function immediately returns 0. If no members are available,
  * then -1 is returned.
  */
-static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions)
+static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions, int devstate)
 {
 	struct member *member;
 	struct ao2_iterator mem_iter;
@@ -1557,7 +1557,7 @@
 			}
 		}
 
-		switch (member->status) {
+		switch (devstate ? ast_device_state(member->state_interface) : member->status) {
 		case AST_DEVICE_INVALID:
 			if (conditions & QUEUE_EMPTY_INVALID) {
 				ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
@@ -1607,8 +1607,12 @@
 		}
 	}
 	ao2_iterator_destroy(&mem_iter);
-
 	ao2_unlock(q);
+
+	if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
+		/* member state still may be RINGING due to lag in event message - check again with device state */
+		return get_member_status(q, max_penalty, min_penalty, conditions, 1);
+	}
 	return -1;
 }
 
@@ -2917,7 +2921,7 @@
 	/* This is our one */
 	if (q->joinempty) {
 		int status = 0;
-		if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) {
+		if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty, 0))) {
 			*reason = QUEUE_JOINEMPTY;
 			ao2_unlock(q);
 			queue_t_unref(q, "Done with realtime queue");
@@ -4733,7 +4737,7 @@
 		if (qe->parent->leavewhenempty) {
 			int status = 0;
 
-			if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty))) {
+			if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty, 0))) {
 				*reason = QUEUE_LEAVEEMPTY;
 				ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
 				leave_queue(qe);
@@ -7130,7 +7134,7 @@
 
 		if (qe.parent->leavewhenempty) {
 			int status = 0;
-			if ((status = get_member_status(qe.parent, qe.max_penalty, qe.min_penalty, qe.parent->leavewhenempty))) {
+			if ((status = get_member_status(qe.parent, qe.max_penalty, qe.min_penalty, qe.parent->leavewhenempty, 0))) {
 				record_abandoned(&qe);
 				reason = QUEUE_LEAVEEMPTY;
 				ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe.pos, qe.opos, (long)(time(NULL) - qe.start));




More information about the asterisk-commits mailing list