mirror of https://github.com/sipwise/asterisk.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
6.0 KiB
192 lines
6.0 KiB
--- apps/app_queue.c 2009-02-06 12:10:44.000000000 +0100
|
|
+++ apps/app_queue.c 2009-02-06 12:14:49.000000000 +0100
|
|
@@ -119,7 +119,8 @@
|
|
QUEUE_STRATEGY_LEASTRECENT,
|
|
QUEUE_STRATEGY_FEWESTCALLS,
|
|
QUEUE_STRATEGY_RANDOM,
|
|
- QUEUE_STRATEGY_RRMEMORY
|
|
+ QUEUE_STRATEGY_RRMEMORY,
|
|
+ QUEUE_STRATEGY_LINEAR
|
|
};
|
|
|
|
static struct strategy {
|
|
@@ -132,6 +133,7 @@
|
|
{ QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
|
|
{ QUEUE_STRATEGY_RANDOM, "random" },
|
|
{ QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
|
|
+ { QUEUE_STRATEGY_LINEAR, "linear" }
|
|
};
|
|
|
|
#define DEFAULT_RETRY 5
|
|
@@ -346,6 +348,8 @@
|
|
int handled; /*!< Whether our call was handled */
|
|
int pending; /*!< Non-zero if we are attempting to call a member */
|
|
int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
|
|
+ int linpos; /*!< If using linear strategy, position in queue */
|
|
+ int linwrapped; /*!< Is the linpos wrapped? */
|
|
time_t start; /*!< When we started holding */
|
|
time_t expire; /*!< When this entry should expire (time out of queue) */
|
|
struct ast_channel *chan; /*!< Our channel */
|
|
@@ -841,8 +845,16 @@
|
|
q->eventwhencalled = 0;
|
|
q->weight = 0;
|
|
q->timeoutrestart = 0;
|
|
- if (!q->members)
|
|
- q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
|
|
+ if(!q->members) {
|
|
+ if(q->strategy == QUEUE_STRATEGY_LINEAR) {
|
|
+ /*linear strategy depnds on order, so only use one hash bucket */
|
|
+ q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
|
|
+ ast_log(LOG_NOTICE, "Using linear strategy.\n");
|
|
+ } else {
|
|
+ q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
|
|
+ ast_log(LOG_NOTICE, "Strategy is NOT linear.\n");
|
|
+ }
|
|
+ }
|
|
q->membercount = 0;
|
|
q->found = 1;
|
|
ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next));
|
|
@@ -1239,6 +1251,30 @@
|
|
ast_mutex_lock(&q->lock);
|
|
clear_queue(q);
|
|
q->realtime = 1;
|
|
+
|
|
+ /* manwe & saghul FTW!!*/
|
|
+
|
|
+ /*Before we initialize the queue, we need to set the strategy, so that linear strategy
|
|
+ * will allocate the members properly
|
|
+ */
|
|
+ struct ast_variable *tmpvar = NULL;
|
|
+ for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
|
|
+ if (!strcasecmp(tmpvar->name, "strategy")) {
|
|
+ q->strategy = strat2int(tmpvar->value);
|
|
+ if (q->strategy < 0) {
|
|
+ ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
|
|
+ tmpvar->value, q->name);
|
|
+ q->strategy = QUEUE_STRATEGY_RINGALL;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ /* We traversed all variables and didn't find a strategy */
|
|
+ if (!tmpvar)
|
|
+ q->strategy = QUEUE_STRATEGY_RINGALL;
|
|
+
|
|
+ /* /manwe & saghul FTW!! */
|
|
+
|
|
AST_LIST_INSERT_HEAD(&queues, q, list);
|
|
}
|
|
init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
|
|
@@ -1857,6 +1893,8 @@
|
|
qe->parent->rrpos++;
|
|
ast_mutex_unlock(&qe->parent->lock);
|
|
|
|
+ qe->linpos++;
|
|
+
|
|
(*busies)++;
|
|
return 0;
|
|
}
|
|
@@ -1987,7 +2025,7 @@
|
|
return ret;
|
|
}
|
|
|
|
-static int store_next(struct queue_ent *qe, struct callattempt *outgoing)
|
|
+static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
|
|
{
|
|
struct callattempt *best = find_best(outgoing);
|
|
|
|
@@ -2011,6 +2049,30 @@
|
|
return 0;
|
|
}
|
|
|
|
+static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
|
|
+{
|
|
+ struct callattempt *best = find_best(outgoing);
|
|
+
|
|
+ if (best) {
|
|
+ /* Ring just the best channel */
|
|
+ if (option_debug)
|
|
+ ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
|
|
+ qe->linpos = best->metric % 1000;
|
|
+ } else {
|
|
+ /* Just increment rrpos */
|
|
+ if (qe->linwrapped) {
|
|
+ /* No more channels, start over */
|
|
+ qe->linpos = 0;
|
|
+ } else {
|
|
+ /* Prioritize next entry */
|
|
+ qe->linpos++;
|
|
+ }
|
|
+ }
|
|
+ qe->linwrapped = 0;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int say_periodic_announcement(struct queue_ent *qe)
|
|
{
|
|
int res = 0;
|
|
@@ -2553,6 +2615,17 @@
|
|
}
|
|
tmp->metric += mem->penalty * 1000000;
|
|
break;
|
|
+ case QUEUE_STRATEGY_LINEAR:
|
|
+ if (pos < qe->linpos) {
|
|
+ tmp->metric = 1000 + pos;
|
|
+ } else {
|
|
+ if (pos > qe->linpos)
|
|
+ /* Indicate there is another priority */
|
|
+ qe->linwrapped = 1;
|
|
+ tmp->metric = pos;
|
|
+ }
|
|
+ tmp->metric += mem->penalty * 1000000;
|
|
+ break;
|
|
case QUEUE_STRATEGY_RANDOM:
|
|
tmp->metric = ast_random() % 1000;
|
|
tmp->metric += mem->penalty * 1000000;
|
|
@@ -2774,7 +2847,7 @@
|
|
ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
|
|
break;
|
|
case 'n':
|
|
- if (qe->parent->strategy == QUEUE_STRATEGY_ROUNDROBIN || qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY)
|
|
+ if (qe->parent->strategy == QUEUE_STRATEGY_ROUNDROBIN || qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR)
|
|
(*tries)++;
|
|
else
|
|
*tries = qe->parent->membercount;
|
|
@@ -2916,7 +2989,10 @@
|
|
ast_channel_unlock(qe->chan);
|
|
ast_mutex_lock(&qe->parent->lock);
|
|
if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) {
|
|
- store_next(qe, outgoing);
|
|
+ store_next_rr(qe, outgoing);
|
|
+ }
|
|
+ if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
|
|
+ store_next_lin(qe, outgoing);
|
|
}
|
|
ast_mutex_unlock(&qe->parent->lock);
|
|
peer = lpeer ? lpeer->chan : NULL;
|
|
@@ -4351,6 +4427,23 @@
|
|
ast_mutex_unlock(&q->lock);
|
|
continue;
|
|
}
|
|
+ /* manwe & saghul FTW!! */
|
|
+
|
|
+ /* Due to the fact that the "linear" strategy will have a different allocation
|
|
+ * scheme for queue members, we must devise the queue's strategy before other initializations
|
|
+ */
|
|
+ const char *tmpvar = NULL;
|
|
+ if ((tmpvar = ast_variable_retrieve(cfg, cat, "strategy"))) {
|
|
+ q->strategy = strat2int(tmpvar);
|
|
+ if (q->strategy < 0) {
|
|
+ ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
|
|
+ tmpvar, q->name);
|
|
+ q->strategy = QUEUE_STRATEGY_RINGALL;
|
|
+ }
|
|
+ } else
|
|
+ q->strategy = QUEUE_STRATEGY_RINGALL;
|
|
+ /* /manwe & saghul FTW!! */
|
|
+
|
|
/* Re-initialize the queue, and clear statistics */
|
|
init_queue(q);
|
|
clear_queue(q);
|