--- 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-14 16:57:55.000000000 -0700 @@ -153,6 +153,8 @@ #define PM_MAX_LEN 2048 /* queues.conf [general] option */ static int queue_persistent_members = 0; +/* queues.conf per-queue weight option */ +static int use_weight = 0; /* We define a customer "local user" structure because we use it not only for keeping track of what is in use but @@ -241,6 +243,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 +710,62 @@ return update_status(q, member, status); } +static int compare_weight(struct ast_call_queue *req_q, struct localuser *req_user, char *qname) +{ + /* 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(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; + strncpy(qname, q->name, sizeof(qname) - 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; + char qname[80] = ""; + + if (use_weight) { /* fast path */ + if (compare_weight(qe->parent,tmp,qname)) { + ast_verbose(VERBOSE_PREFIX_3 "Attempt (%s: %s/%s) delayed by higher priority queue (%s).\n", qe->parent->name, tmp->tech, tmp->numsubst, qname); + 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 +2363,9 @@ 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); + use_weight++; } else { ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queue.conf\n", cat, var->name, var->lineno); } @@ -2435,8 +2493,8 @@ sl = 0; if(q->callscompleted > 0) sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); - ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), C:%d, A:%d, SL:%2.1f%% within %ds\n", - q->name, q->count, max, int2strat(q->strategy), q->holdtime, q->callscompleted, q->callsabandoned,sl,q->servicelevel); + ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds\n", + q->name, q->count, max, int2strat(q->strategy), q->holdtime, q->weight, q->callscompleted, q->callsabandoned,sl,q->servicelevel); if (q->members) { ast_cli(fd, " Members: \n"); for (mem = q->members; mem; mem = mem->next) {