From 2c54f151715227b98ac615a63ff4eb271200fda4 Mon Sep 17 00:00:00 2001 From: Jeff Peeler Date: Thu, 20 Jan 2011 17:04:08 +0000 Subject: [PATCH] Add new queue strategy to preserve behavior for when queue members moved to ao2. Add queue strategy called "rrordered" to mimic old behavior from when queue members were stored in a linked list. ABE-2707 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@303007 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_queue.c | 57 ++++++++++++++++++++++++++++++++++---- configs/queues.conf.sample | 2 ++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/apps/app_queue.c b/apps/app_queue.c index 5c691297dc..428a8fa469 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -119,7 +119,8 @@ enum { QUEUE_STRATEGY_LEASTRECENT, QUEUE_STRATEGY_FEWESTCALLS, QUEUE_STRATEGY_RANDOM, - QUEUE_STRATEGY_RRMEMORY + QUEUE_STRATEGY_RRMEMORY, + QUEUE_STRATEGY_RRORDERED, }; static struct strategy { @@ -132,6 +133,7 @@ static struct strategy { { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" }, { QUEUE_STRATEGY_RANDOM, "random" }, { QUEUE_STRATEGY_RRMEMORY, "rrmemory" }, + { QUEUE_STRATEGY_RRORDERED, "rrordered" }, }; #define DEFAULT_RETRY 5 @@ -884,8 +886,13 @@ static void init_queue(struct call_queue *q) 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_RRORDERED) { + q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn); + } else { + q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn); + } + } q->membercount = 0; q->found = 1; ast_copy_string(q->sound_next, "queue-youarenext", sizeof(q->sound_next)); @@ -1279,12 +1286,34 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as /* Create a new queue if an in-core entry does not exist yet. */ if (!q) { + struct ast_variable *tmpvar; if (!(q = alloc_queue(queuename))) return NULL; ao2_lock(q); clear_queue(q); q->realtime = 1; AST_LIST_INSERT_HEAD(&queues, q, list); + + /* Due to the fact that the "rrordered" strategy will have a different allocation + * scheme for queue members, we must devise the queue's strategy before other initializations. + * To be specific, the rrordered strategy needs to function like a linked list, meaning the ao2 + * container used will have only a single bucket instead of the typical number. + */ + 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; + } } init_queue(q); /* Ensure defaults for all parameters not set explicitly. */ @@ -2650,6 +2679,7 @@ static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct q->wrapped = 0; } /* Fall through */ + case QUEUE_STRATEGY_RRORDERED: case QUEUE_STRATEGY_RRMEMORY: if (pos < q->rrpos) { tmp->metric = 1000 + pos; @@ -2883,7 +2913,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce 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_RRORDERED) (*tries)++; else *tries = qe->parent->membercount; @@ -3030,7 +3060,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce } ast_channel_unlock(qe->chan); ao2_lock(qe->parent); - if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY) { + if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) { store_next(qe, outgoing); } ao2_unlock(qe->parent); @@ -4517,6 +4547,7 @@ static int reload_queues(void) } else new = 0; if (q) { + const char *tmpvar; if (!new) ao2_lock(q); /* Check if a queue with this name already exists */ @@ -4526,6 +4557,22 @@ static int reload_queues(void) ao2_unlock(q); continue; } + + /* Due to the fact that the "rrordered" strategy will have a different allocation + * scheme for queue members, we must devise the queue's strategy before other initializations. + * To be specific, the rrordered strategy needs to function like a linked list, meaning the ao2 + * container used will have only a single bucket instead of the typical number. + */ + 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; + } + /* Re-initialize the queue, and clear statistics */ init_queue(q); clear_queue(q); diff --git a/configs/queues.conf.sample b/configs/queues.conf.sample index 532e240dbd..4631a6eec3 100644 --- a/configs/queues.conf.sample +++ b/configs/queues.conf.sample @@ -74,6 +74,8 @@ monitor-type = MixMonitor ; fewestcalls - ring the one with fewest completed calls from this queue ; random - ring random interface ; rrmemory - round robin with memory, remember where we left off last ring pass +; rrordered - same as rrmemory, except the queue member order from config file + is preserved ; ;strategy = ringall ; -- 2.47.2