Added a membercount variable to call_queue struct which keeps track of the number of logged in members in a particular queue.

This makes it so that the 'n' option for Queue() can act properly depending on which strategy is used. If the strategy is
roundrobin, rrmemory, or ringall, we want to ring each phone once before moving on in the dialplan. However, if any other strategy is
used, we will only ring one phone since it cannot be guaranteed that a different phone will ring on subsequent attempts to ring a phone.

As a side effect of this, the QUEUE_MEMBER_COUNT dialplan function now just reads the membercount variable instead of traversing through
the member list to figure out how many members there are.

Special thanks to blitzrage for helping to test this out.

(closes issue #10127, reported by bcnit, patched by me, tested by blitzrage)



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@76801 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Michelson
2007-07-24 16:26:58 +00:00
parent 3630b5e477
commit ad4eb1b347

View File

@@ -396,6 +396,7 @@ struct call_queue {
int autofill; /*!< Ignore the head call status and ring an available agent */ int autofill; /*!< Ignore the head call status and ring an available agent */
struct member *members; /*!< Head of the list of members */ struct member *members; /*!< Head of the list of members */
int membercount; /*!< Number of members in queue */
struct queue_ent *head; /*!< Head of the list of callers */ struct queue_ent *head; /*!< Head of the list of callers */
AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */ AST_LIST_ENTRY(call_queue) list; /*!< Next call queue */
}; };
@@ -666,6 +667,7 @@ static void init_queue(struct call_queue *q)
q->context[0] = '\0'; q->context[0] = '\0';
q->monfmt[0] = '\0'; q->monfmt[0] = '\0';
q->periodicannouncefrequency = 0; q->periodicannouncefrequency = 0;
q->membercount = 0;
ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next)); ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare)); ast_copy_string(q->sound_thereare, "queue-thereare", sizeof(q->sound_thereare));
ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls)); ast_copy_string(q->sound_calls, "queue-callswaiting", sizeof(q->sound_calls));
@@ -958,6 +960,7 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, const
} else { } else {
q->members = m; q->members = m;
} }
q->membercount++;
} }
} else { } else {
m->dead = 0; /* Do not delete this one. */ m->dead = 0; /* Do not delete this one. */
@@ -980,6 +983,7 @@ static void free_members(struct call_queue *q, int all)
else else
q->members = next; q->members = next;
remove_from_interfaces(curm->interface); remove_from_interfaces(curm->interface);
q->membercount--;
free(curm); free(curm);
} else } else
prev = curm; prev = curm;
@@ -1077,8 +1081,9 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
if (q->strategy == QUEUE_STRATEGY_ROUNDROBIN) if (q->strategy == QUEUE_STRATEGY_ROUNDROBIN)
rr_dep_warning(); rr_dep_warning();
/* Temporarily set non-dynamic members dead so we can detect deleted ones. */ /* Temporarily set non-dynamic members dead so we can detect deleted ones.
for (m = q->members; m; m = m->next) { * Also set the membercount correctly for realtime*/
for (m = q->members; m; m = m->next, q->membercount++) {
if (!m->dynamic) if (!m->dynamic)
m->dead = 1; m->dead = 1;
} }
@@ -1102,6 +1107,7 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
q->members = next_m; q->members = next_m;
} }
remove_from_interfaces(m->interface); remove_from_interfaces(m->interface);
q->membercount--;
free(m); free(m);
} else { } else {
prev_m = m; prev_m = m;
@@ -2348,7 +2354,10 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT); ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
break; break;
case 'n': case 'n':
*go_on = 1; if (qe->parent->strategy == QUEUE_STRATEGY_ROUNDROBIN || qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY)
(*go_on)++;
else
*go_on = qe->parent->membercount;
break; break;
case 'i': case 'i':
forwardsallowed = 0; forwardsallowed = 0;
@@ -2778,10 +2787,12 @@ static int remove_from_queue(const char *queuename, const char *interface)
if ((last_member = interface_exists(q, interface))) { if ((last_member = interface_exists(q, interface))) {
if ((look = q->members) == last_member) { if ((look = q->members) == last_member) {
q->members = last_member->next; q->members = last_member->next;
q->membercount--;
} else { } else {
while (look != NULL) { while (look != NULL) {
if (look->next == last_member) { if (look->next == last_member) {
look->next = last_member->next; look->next = last_member->next;
q->membercount--;
break; break;
} else { } else {
look = look->next; look = look->next;
@@ -2835,6 +2846,7 @@ static int add_to_queue(const char *queuename, const char *interface, const char
new_member->dynamic = 1; new_member->dynamic = 1;
new_member->next = q->members; new_member->next = q->members;
q->members = new_member; q->members = new_member;
q->membercount++;
manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded", manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s\r\n" "Location: %s\r\n"
@@ -3436,7 +3448,7 @@ check_turns:
stat = get_member_status(qe.parent, qe.max_penalty); stat = get_member_status(qe.parent, qe.max_penalty);
/* exit after 'timeout' cycle if 'n' option enabled */ /* exit after 'timeout' cycle if 'n' option enabled */
if (go_on) { if (go_on >= qe.parent->membercount) {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Exiting on time-out cycle\n"); ast_verbose(VERBOSE_PREFIX_3 "Exiting on time-out cycle\n");
ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos); ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
@@ -3535,7 +3547,6 @@ static int queue_function_qac(struct ast_channel *chan, char *cmd, char *data, c
int count = 0; int count = 0;
struct call_queue *q; struct call_queue *q;
struct ast_module_user *lu; struct ast_module_user *lu;
struct member *m;
buf[0] = '\0'; buf[0] = '\0';
@@ -3556,12 +3567,7 @@ static int queue_function_qac(struct ast_channel *chan, char *cmd, char *data, c
AST_LIST_UNLOCK(&queues); AST_LIST_UNLOCK(&queues);
if (q) { if (q) {
for (m = q->members; m; m = m->next) { count = q->membercount;
/* Count the agents who are logged in and presently answering calls */
if ((m->status != AST_DEVICE_UNAVAILABLE) && (m->status != AST_DEVICE_INVALID)) {
count++;
}
}
ast_mutex_unlock(&q->lock); ast_mutex_unlock(&q->lock);
} else } else
ast_log(LOG_WARNING, "queue %s was not found\n", data); ast_log(LOG_WARNING, "queue %s was not found\n", data);
@@ -3814,6 +3820,7 @@ static int reload_queues(void)
newm->next = q->members; newm->next = q->members;
q->members = newm; q->members = newm;
} }
q->membercount++;
} else { } else {
queue_set_param(q, var->name, var->value, var->lineno, 1); queue_set_param(q, var->name, var->value, var->lineno, 1);
} }
@@ -3836,6 +3843,7 @@ static int reload_queues(void)
q->members = next; q->members = next;
remove_from_interfaces(cur->interface); remove_from_interfaces(cur->interface);
q->membercount--;
free(cur); free(cur);
} }