Index: apps/app_queue.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_queue.c,v retrieving revision 1.40 diff -u -r1.40 app_queue.c --- apps/app_queue.c 19 Nov 2003 21:56:45 -0000 1.40 +++ apps/app_queue.c 31 Jan 2004 13:09:25 -0000 @@ -170,6 +170,15 @@ struct member *members; /* Member channels to be tried */ struct queue_ent *head; /* Start of the actual queue */ struct ast_call_queue *next; /* Next call queue */ + struct ast_call_queue *slave; /* a slave queue delivers no calls until we are empty */ + struct ast_call_queue *master; /* a master queue */ + char master_name[80]; /* the name of the master queue used in the config */ + int master_ratio; /* the number of calls the master queue must let through before we deliver calls + * if the master isnt empty. 0 means never let through calls if master isnt empty + */ + int master_count; /* number of calls left before we get through - initialized at master_ratio and + * decreased at each call the master gets + */ }; static struct ast_call_queue *queues = NULL; @@ -284,6 +293,12 @@ } ast_mutex_unlock(&qlock); free_members(q, 1); + if (q->master) { + q->master->slave = NULL; + } + if (q->slave) { + q->slave->master = NULL; + } free(q); } @@ -635,6 +650,15 @@ if (user->member == cur) { time(&cur->lastcall); cur->calls++; + /* + * If we have a slave-queue and it waits for us to + * complete calls we update it + */ + if (q->slave) { + if (q->slave->master_count > 0) { + q->slave->master_count--; + } + } break; } cur = cur->next; @@ -711,6 +735,54 @@ int x=0; char *announce = NULL; char digit = 0; + struct ast_call_queue *tmp_queue; + + /* check our priorities */ + tmp_queue = qe->parent; + ast_verbose(VERBOSE_PREFIX_3 "Trying to get some answer from queue %s\n", tmp_queue->name); + /* recurse through all our masters and their masters */ + while (tmp_queue->master) { + /* if this master has calls waiting */ + if (tmp_queue->master->count) { + /* if we _never_ let through calls with a busy master */ + if (!tmp_queue->master_ratio) { + ast_verbose(VERBOSE_PREFIX_3 "%s's master (%s) has count = %d - this call will wait\n", + tmp_queue->name, + tmp_queue->master->name, + tmp_queue->master->count); + return 0; + /* if we let through calls at a lower rate */ + } else if (tmp_queue->master_count) { + ast_verbose(VERBOSE_PREFIX_3 "%s's master (%s) has count = %d and has to let %d calls through before us\n", + tmp_queue->name, + tmp_queue->master->name, + tmp_queue->master->count, + tmp_queue->master_count); + return 0; + } else { + ast_verbose(VERBOSE_PREFIX_3 "%s's master (%s) has count = %d - but this is %s's turn!\n", + tmp_queue->name, + tmp_queue->master->name, + tmp_queue->master->count, + tmp_queue->name); + } + } + /* does our master have a master? */ + if (tmp_queue->master->master) { + ast_verbose(VERBOSE_PREFIX_3 "%s's master (%s) has a master, checking grand master (%s)\n", + tmp_queue->name, + tmp_queue->master->name, + tmp_queue->master->master->name); + } + tmp_queue = tmp_queue->master; + } + + /* reseting the number of calls our master has to take before our turn */ + tmp_queue = qe->parent; + if (tmp_queue->master) { + tmp_queue->master_count = tmp_queue->master_ratio; + } + /* Hold the lock while we setup the outgoing calls */ ast_mutex_lock(&qe->parent->lock); cur = qe->parent->members; @@ -1193,7 +1265,7 @@ static void reload_queues(void) { - struct ast_call_queue *q, *ql, *qn; + struct ast_call_queue *q, *ql, *qn, *q2; struct ast_config *cfg; char *cat, *tmp; struct ast_variable *var; @@ -1242,6 +1314,8 @@ q->retry = 0; q->timeout = -1; q->maxlen = 0; + q->master_ratio = 0; + q->master_count = 0; free_members(q, 0); strcpy(q->moh, ""); strcpy(q->announce, ""); @@ -1292,6 +1366,10 @@ q->timeout = atoi(var->value); } else if (!strcasecmp(var->name, "retry")) { q->retry = atoi(var->value); + } else if (!strcasecmp(var->name, "master")) { + strncpy(q->master_name, var->value, sizeof(q->master_name) - 1); + } else if (!strcasecmp(var->name, "masterratio")) { + q->master_ratio = atoi(var->value); } else if (!strcasecmp(var->name, "maxlen")) { q->maxlen = atoi(var->value); } else if (!strcasecmp(var->name, "strategy")) { @@ -1326,12 +1404,28 @@ ql = NULL; while(q) { qn = q->next; + if (q->master_name) { + q2 = queues; + while (q2) { + if (!strcmp(q->master_name, q2->name)) { + q->master = q2; + q2->slave = q; + } + q2 = q2->next; + } + } if (q->dead) { if (ql) ql->next = q->next; else queues = q->next; if (!q->count) { + if (q->master) { + q->master->slave = NULL; + } + if (q->slave) { + q->slave->master = NULL; + } free(q); } else ast_log(LOG_WARNING, "XXX Leaking a litttle memory :( XXX\n");