--- asterisk/apps/app_queue.c 2004-12-20 09:20:38.000000000 -0700 +++ asterisk-20041222/apps/app_queue.c 2004-12-23 00:02:11.000000000 -0700 @@ -153,6 +153,9 @@ #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; + #define QUEUE_FLAG_RINGBACKONLY (1 << 0) #define QUEUE_FLAG_MUSICONHOLD (1 << 1) @@ -247,6 +250,7 @@ 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 */ @@ -708,13 +712,66 @@ 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->interface, req_user->interface)) { + ast_log(LOG_DEBUG, "Found matching member %s in queue '%s'\n", mem->interface, 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 tech[256]; char *location; + char qname[80] = ""; + if (use_weight) { /* fast path */ + if (compare_weight(qe->parent,tmp,qname)) { + ast_verbose(VERBOSE_PREFIX_3 "Attempt (%s: %s) delayed by higher priority queue (%s).\n", qe->parent->name, tmp->interface, 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\n", tmp->interface); if (qe->chan->cdr) @@ -2267,6 +2363,9 @@ ast_set2_flag(q, ast_true(var->value), QUEUE_FLAG_REPORTHOLDTIME); } 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); } @@ -2389,8 +2488,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) { @@ -2496,10 +2595,11 @@ "Abandoned: %d\r\n" "ServiceLevel: %d\r\n" "ServicelevelPerf: %2.1f\r\n" + "Weight: %d\r\n" "%s" "\r\n", q->name, q->maxlen, q->count, q->holdtime, q->callscompleted, - q->callsabandoned, q->servicelevel, sl, idText); + q->callsabandoned, q->servicelevel, sl, q->weight, idText); /* List Queue Members */ for (mem = q->members; mem; mem = mem->next)