Index: apps/app_queue.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_queue.c,v retrieving revision 1.159 diff -u -r1.159 app_queue.c --- apps/app_queue.c 31 Aug 2005 20:16:47 -0000 1.159 +++ apps/app_queue.c 1 Sep 2005 17:50:38 -0000 @@ -306,6 +306,11 @@ int count; /* How many entries */ int maxlen; /* Max number of entries */ + /* Dynamic max number of entries = min(maxlen,members*maxpct+actives*maxactpct+availables*maxavlpct+paused*maxpaupct) */ + int maxpct; /* Dynamic max number of entries. Members contribution (%) */ + int maxactpct; /* Dynamic max number of entries. Active members contribution (%) */ + int maxavlpct; /* Dynamic max number of entries. Available Members contribution (%) */ + int maxpaupct; /* Dynamic max number of entries. Paused Members contribution (%) */ int wrapuptime; /* Wrapup Time */ int retry; /* Retry calling everyone after this amount of time */ @@ -521,6 +526,10 @@ q->retry = DEFAULT_RETRY; q->timeout = -1; q->maxlen = 0; + q->maxpct = 0; + q->maxactpct = 0; + q->maxavlpct = 0; + q->maxpaupct = 0; q->announcefrequency = 0; q->announceholdtime = 0; q->roundingseconds = 0; /* Default - don't announce seconds */ @@ -627,6 +636,14 @@ q->maxlen = atoi(val); if (q->maxlen < 0) q->maxlen = 0; + } else if (!strcasecmp(param, "maxpct")) { + q->maxpct = atoi(val); + } else if (!strcasecmp(param, "maxactpct")) { + q->maxactpct = atoi(val); + } else if (!strcasecmp(param, "maxavlpct")) { + q->maxavlpct = atoi(val); + } else if (!strcasecmp(param, "maxpaupct")) { + q->maxpaupct = atoi(val); } else if (!strcasecmp(param, "servicelevel")) { q->servicelevel= atoi(val); } else if (!strcasecmp(param, "strategy")) { @@ -838,6 +855,69 @@ return q; } +static int calc_maxlen(struct ast_call_queue *q) +{ + /* Iterate over members to detemine states */ + struct member *curm; + int members = 0; + int actives = 0; + int availables = 0; + int paused = 0; + int res = 0; + + if ((q->maxpct) || (q->maxactpct) || (q->maxavlpct) || (q->maxpaupct)) + { + curm = q->members; + while(curm) { + switch (curm->status) + { + case AST_DEVICE_UNKNOWN: + case AST_DEVICE_NOT_INUSE: + members++; + actives++; + if (curm->paused) + paused++; + availables++; + break; + case AST_DEVICE_INVALID: + /* an invalid member is not counted at all */ + break; + case AST_DEVICE_UNAVAILABLE: + members++; + break; + default: + /* all others states (inuse, ringing...) members are active but not availables */ + members++; + actives++; + if (curm->paused) + paused++; + } + curm = curm->next; + } + + res = (members * q->maxpct + actives * q->maxactpct + availables * q->maxavlpct + paused * q->maxpaupct) / 100; + + /* minimum should be 1 as 0 mean unlimited */ + if (res<=0) + return 1; + + /* if maxlen is defined, it's an absolute maximum */ + if ((q->maxlen) && (res>q->maxlen)) + return q->maxlen; + + return res; + } + else + return q->maxlen; +} + +static int is_queue_full(struct ast_call_queue *q) +{ + int maxlen = calc_maxlen(q); + + return (maxlen) && (q->count >= maxlen); +} + static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason) { struct ast_variable *queue_vars = NULL; @@ -880,7 +960,7 @@ *reason = QUEUE_JOINEMPTY; else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) *reason = QUEUE_JOINUNAVAIL; - else if (q->maxlen && (q->count >= q->maxlen)) + else if (is_queue_full(q)) *reason = QUEUE_FULL; else { /* There's space for us, put us at the right position inside @@ -3165,6 +3245,7 @@ int pos; time_t now; char max_buf[80]; + int maxlen; char *max; size_t max_left; float sl = 0; @@ -3198,15 +3279,21 @@ max_buf[0] = '\0'; max = max_buf; max_left = sizeof(max_buf); - if (q->maxlen) - ast_build_string(&max, &max_left, "%d", q->maxlen); + maxlen = calc_maxlen(q); + if (maxlen) + { + if ((q->maxpct) || (q->maxactpct) || (q->maxavlpct) || (q->maxpaupct)) + ast_build_string(&max, &max_left, "%d dynamic", maxlen); + else + ast_build_string(&max, &max_left, "%d", maxlen); + } else ast_build_string(&max, &max_left, "unlimited"); 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), 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); + q->name, q->count, max_buf, 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) { @@ -3225,7 +3312,7 @@ mem->calls, (long)(time(NULL) - mem->lastcall)); } else ast_build_string(&max, &max_left, " has taken no calls yet"); - ast_cli(fd, " %s%s\n", mem->interface, max); + ast_cli(fd, " %s%s\n", mem->interface, max_buf); } } else ast_cli(fd, " No Members\n"); Index: configs/queues.conf.sample =================================================================== RCS file: /usr/cvsroot/asterisk/configs/queues.conf.sample,v retrieving revision 1.30 diff -u -r1.30 queues.conf.sample --- configs/queues.conf.sample 31 Jul 2005 22:07:58 -0000 1.30 +++ configs/queues.conf.sample 1 Sep 2005 17:50:39 -0000 @@ -75,6 +75,16 @@ ; ;maxlen = 0 ; +; Dynamic maximum number of people waiting in the queue (computed if one value is not 0) +; Value might be negatives. If the result is <=0 then the maxlen will be 1 +; dynmaxlen = (maxpct * valids members + maxactpct * actives members + +; maxavlpct * availables members + maxpaupct * paused active members) / 100 +; +;maxpct = 0 +;maxactpct = 0 +;maxavlpct = 0 +;maxpaupct = 0 +; ; ; How often to announce queue position and/or estimated holdtime to caller (0=off) ;