summaryrefslogtreecommitdiff
path: root/apps/app_queue.c
diff options
context:
space:
mode:
authorScott Griepentrog <sgriepentrog@digium.com>2014-06-12 15:50:48 +0000
committerScott Griepentrog <sgriepentrog@digium.com>2014-06-12 15:50:48 +0000
commitfa8c58fefb38424216c4d4ae66f31084bce4e16f (patch)
tree0f1589271d7f6918b808f8ab68c82cc3eee15b89 /apps/app_queue.c
parent70b976f084f624e2efbcfdb6a690f7ada9f151b0 (diff)
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 ........ Merged revisions 415835 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 415836 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@415839 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_queue.c')
-rw-r--r--apps/app_queue.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 17c8c9a9a..8e26135cd 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -2162,7 +2162,7 @@ static struct ast_json *queue_member_blob_create(struct call_queue *q, struct me
* 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;
@@ -2177,7 +2177,7 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena
}
}
- 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);
@@ -2227,8 +2227,12 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena
}
}
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;
}
@@ -3447,7 +3451,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
/* 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");
@@ -5143,7 +5147,7 @@ static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *r
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);
@@ -7806,7 +7810,7 @@ check_turns:
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));