From f8e7d2c88e5613fda53a98370d32855ba3a01450 Mon Sep 17 00:00:00 2001 From: markster Date: Fri, 7 Jan 2005 04:05:22 +0000 Subject: Merge weight option (bug #3038) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4698 f38db490-d61c-443f-a65b-d21fe96a405b --- apps/app_queue.c | 71 +++++++++++++++++++++++++++++++++++++++++++--- configs/queues.conf.sample | 6 ++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/apps/app_queue.c b/apps/app_queue.c index c1b89d6e0..3ff353454 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -154,6 +154,9 @@ static const char *pm_family = "/Queue/PersistentMembers"; #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) @@ -248,6 +251,7 @@ struct ast_call_queue { 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 */ int rrpos; /* Round Robin - position */ @@ -712,13 +716,66 @@ static int update_dial_status(struct ast_call_queue *q, struct member *member, i 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)) { if (option_debug) ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface); @@ -2128,6 +2185,7 @@ static void reload_queues(void) return; } ast_mutex_lock(&qlock); + use_weight=0; /* Mark all queues as dead for the moment */ q = queues; while(q) { @@ -2281,6 +2339,10 @@ static void reload_queues(void) 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); + if (q->weight) + 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); } @@ -2403,8 +2465,8 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show) 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) { @@ -2511,10 +2573,11 @@ static int manager_queues_status( struct mansession *s, struct message *m ) "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) diff --git a/configs/queues.conf.sample b/configs/queues.conf.sample index 7d80c2cc1..172a6f80f 100755 --- a/configs/queues.conf.sample +++ b/configs/queues.conf.sample @@ -60,6 +60,12 @@ persistentmembers = yes ; ;retry = 5 ; +; Weight of queue - when compared to other queues, higher weights get +; first shot at available channels when the same channel is included in +; more than one queue. +; +;weight=0 +; ; After a successful call, how long to wait before sending a potentially ; free member another call (default is 0, or no delay) ; -- cgit v1.2.3