aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbweschke <bweschke@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-03 20:01:30 +0000
committerbweschke <bweschke@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-03 20:01:30 +0000
commit165047114fbc2f8e592c1623ecf98dcc01ddd9ea (patch)
tree511130a4898434adefb6054f2d2fb0cdce88a2b2
parentb8de621a5e1207b137ccdc10f3f459b7aba0205a (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.txt20
-rw-r--r--apps/app_queue.c75
-rw-r--r--configs/queues.conf.sample27
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
;