diff options
author | bweschke <bweschke@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-05-03 20:01:30 +0000 |
---|---|---|
committer | bweschke <bweschke@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-05-03 20:01:30 +0000 |
commit | 165047114fbc2f8e592c1623ecf98dcc01ddd9ea (patch) | |
tree | 511130a4898434adefb6054f2d2fb0cdce88a2b2 | |
parent | b8de621a5e1207b137ccdc10f3f459b7aba0205a (diff) |
Fix autofill behavior in app_queue and document it's functionality in queues.conf.sample and UPGRADE.txt
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@24543 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | UPGRADE.txt | 20 | ||||
-rw-r--r-- | apps/app_queue.c | 75 | ||||
-rw-r--r-- | configs/queues.conf.sample | 27 |
3 files changed, 108 insertions, 14 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt index e6c52bff0..b6539d60e 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -73,6 +73,26 @@ Applications: queue member channel that is taking the call. This is useful when trying to link recording filenames back to a particular call from the queue. +* The old/current behavior of app_queue has a serial type behavior + in that the queue will make all waiting callers wait in the queue + even if there is more than one available member ready to take + calls until the head caller is connected with the member they + were trying to get to. The next waiting caller in line then + becomes the head caller, and they are then connected with the + next available member and all available members and waiting callers + waits while this happens. This cycle continues until there are + no more available members or waiting callers, whichever comes first. + The new behavior, enabled by setting autofill=yes in queues.conf + either at the [general] level to default for all queues or + to set on a per-queue level, makes sure that when the waiting + callers are connecting with available members in a parallel fashion + until there are no more available members or no more waiting callers, + whichever comes first. This is probably more along the lines of how + one would expect a queue should work and in most cases, you will want + to enable this new behavior. If you do not specify or comment out this + option, it will default to "no" to keep backward compatability with the old + behavior. + Manager: * After executing the 'status' manager action, the "Status" manager events diff --git a/apps/app_queue.c b/apps/app_queue.c index 092aa7094..5beb4b5fd 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -234,6 +234,9 @@ static int queue_persistent_members = 0; /*! \brief queues.conf per-queue weight option */ static int use_weight = 0; +/*! \brief queues.conf [general] option */ +static int autofill_default = 0; + enum queue_result { QUEUE_UNKNOWN = 0, QUEUE_TIMEOUT = 1, @@ -575,6 +578,7 @@ static void init_queue(struct ast_call_queue *q) q->roundingseconds = 0; /* Default - don't announce seconds */ q->servicelevel = 0; q->ringinuse = 1; + q->autofill = autofill_default; q->moh[0] = '\0'; q->announce[0] = '\0'; q->context[0] = '\0'; @@ -1860,25 +1864,75 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte } return peer; + } static int is_our_turn(struct queue_ent *qe) { struct queue_ent *ch; + struct member *cur; + int avl = 0; + int idx = 0; int res; - /* Atomically read the parent head -- does not need a lock */ - ch = qe->parent->head; - /* If we are now at the top of the head, break out */ - if ((ch == qe) || (qe->parent->autofill)) { - if (option_debug) - ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); - res = 1; + if (!qe->parent->autofill) { + + /* Atomically read the parent head -- does not need a lock */ + ch = qe->parent->head; + /* If we are now at the top of the head, break out */ + if ((ch == qe) || (qe->parent->autofill)) { + if (option_debug) + ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); + res = 1; + } else { + if (option_debug) + ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); + res = 0; + } + } else { + + /* This needs a lock. How many members are available to be served? */ + + ast_mutex_lock(&qe->parent->lock); + + ch = qe->parent->head; + cur = qe->parent->members; + + while (cur) { + if (cur->status == 1) + avl++; + cur = cur->next; + } + if (option_debug) - ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); - res = 0; + ast_log(LOG_DEBUG, "There are %d available members.\n", avl); + + if (qe->parent->strategy == 1) { + if (option_debug) + ast_log(LOG_DEBUG, "Even though there are %d available members, the strategy is ringall so only the head call is allowed in!\n", avl); + avl = 1; + } + + while ((idx < avl) && (ch) && (ch != qe)) { + idx++; + ch = ch->next; + } + + /* If the queue entry is within avl [the number of available members] calls from the top ... */ + if (ch && idx < avl) { + if (option_debug) + ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); + res = 1; + } else { + if (option_debug) + ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); + res = 0; + } + + ast_mutex_unlock(&qe->parent->lock); } + return res; } @@ -3302,6 +3356,9 @@ static void reload_queues(void) queue_persistent_members = 0; if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) queue_persistent_members = ast_true(general_val); + autofill_default = 0; + if ((general_val = ast_variable_retrieve(cfg, "general", "autofill"))) + autofill_default = ast_true(general_val); } else { /* Define queue */ /* Look for an existing one */ AST_LIST_TRAVERSE(&queues, q, list) { diff --git a/configs/queues.conf.sample b/configs/queues.conf.sample index ff00964e6..31aa24514 100644 --- a/configs/queues.conf.sample +++ b/configs/queues.conf.sample @@ -8,6 +8,25 @@ ; read into their recorded queues. Default is 'yes'. ; persistentmembers = yes +; +; AutoFill Behavior +; The old/current behavior of the queue has a serial type behavior +; in that the queue will make all waiting callers wait in the queue +; even if there is more than one available member ready to take +; calls until the head caller is connected with the member they +; were trying to get to. The next waiting caller in line then +; becomes the head caller, and they are then connected with the +; next available member and all available members and waiting callers +; waits while this happens. The new behavior, enabled by setting +; autofill=yes makes sure that when the waiting callers are connecting +; with available members in a parallel fashion until there are +; no more available members or no more waiting callers. This is +; probably more along the lines of how a queue should work and +; in most cases, you will want to enable this behavior. If you +; do not specify or comment out this option, it will default to no +; to keep backward compatability with the old behavior. +; +autofill = yes ; ; Note that a timeout to fail out of a queue may be passed as part of ; an application call from extensions.conf: @@ -73,11 +92,9 @@ persistentmembers = yes ;wrapuptime=15 ; ; Autofill will follow queue strategy but push multiple calls through -; at same time. WARNING: By setting this to yes, if you have a number -; of calls waiting in queue, and only a single member becoming available -; at a time, it is more than likely NOT going to be the caller that's -; been waiting the longest that will get assigned to this newly available -; queue member. +; at same time until there are no more waiting callers or no more +; available members. The per-queue setting of autofill allows you +; to override the default setting on an individual queue level. ; ;autofill=yes ; |