--- asterisk/configs/queues.conf.sample 2004-12-05 22:54:16.000000000 -0700 +++ asterisk-20041213/configs/queues.conf.sample 2004-12-13 16:37:46.000000000 -0700 @@ -141,6 +141,11 @@ ; ; memberdelay = 0 ; +; If a member is in multiple queues, a higher weight queue with calls waiting will always deliver +; its calls to the member first. This is a 'queue priority' type of thing. +; +; weight = 0 +; ; Each member of this call queue is listed on a separate line in ; the form technology/dialstring. "member" means a normal member of a ; queue. An optional penalty may be specified after a comma, such that --- asterisk/apps/app_queue.c 2004-12-05 22:54:16.000000000 -0700 +++ asterisk-20041213/apps/app_queue.c 2004-12-13 17:32:19.000000000 -0700 @@ -241,6 +241,7 @@ int dead; /* Whether this queue is dead or not */ int retry; /* Retry calling everyone after this amount of time */ int timeout; /* How long to wait for an answer */ + int weight; /* This queue's respective weight */ /* Queue strategy things */ @@ -707,10 +708,57 @@ return update_status(q, member, status); } +static int compare_weight(struct ast_call_queue *req_q, struct localuser *req_user) +{ + /* traverse all defined queues which have calls waiting and contain this member + return 0 if no other queue has precedence (higher weight) or 1 if found */ + struct ast_call_queue *q; + struct member *mem; + int found = 0, weight = 0, calls = 0; + char name[80]; + + strncpy(name, req_q->name, sizeof(req_q->name) - 1); + weight = req_q->weight; + calls = req_q->count; + + ast_mutex_lock(&qlock); + for (q = queues; q; q = q->next) { /* spin queues */ + ast_mutex_lock(&q->lock); + if (!strcasecmp(q->name, name)) { /* don't check myself */ + ast_mutex_unlock(&q->lock); + continue; + } + if (q->count && q->members) { /* check only if calls waiting and has members */ + for (mem = q->members; mem; mem = mem->next) { /* spin members */ + if (!strcasecmp(mem->tech, req_user->tech) && !strcmp(mem->loc, req_user->numsubst)) { + ast_log(LOG_DEBUG, "Found matching member %s/%s in queue '%s'\n", mem->tech, mem->loc, q->name); + if (q->weight > weight) { + ast_log(LOG_DEBUG, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, name, weight, calls); + found = 1; + break; /* stop looking for more members */ + } + } + } + } + ast_mutex_unlock(&q->lock); + if (found) + break; + } + ast_mutex_unlock(&qlock); + return found; +} + static int ring_entry(struct queue_ent *qe, struct localuser *tmp) { int res; int status; + if (compare_weight(qe->parent,tmp)) { + ast_verbose(VERBOSE_PREFIX_3 "Call attempt usurped by heavier weight queue.\n"); + if (qe->chan->cdr) + ast_cdr_busy(qe->chan->cdr); + tmp->stillgoing = 0; + return 0; + } if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) { ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s/%s\n", tmp->tech, tmp->numsubst); if (qe->chan->cdr) @@ -2308,6 +2356,8 @@ q->reportholdtime = ast_true(var->value); } else if (!strcasecmp(var->name, "memberdelay")) { q->memberdelay = atoi(var->value); + } else if (!strcasecmp(var->name, "weight")) { + q->weight = atoi(var->value); } else { ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queue.conf\n", cat, var->name, var->lineno); }