summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_queue.c134
1 files changed, 97 insertions, 37 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 323309f87..8d1512399 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -2395,8 +2395,18 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
return q;
}
-/*! \note Returns a reference to the loaded realtime queue. */
-static struct call_queue *load_realtime_queue(const char *queuename)
+/*!
+ * note */
+
+/*!
+ * \internal
+ * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
+ * \param queuename - name of the desired queue
+ *
+ * \retval the queue
+ * \retval NULL if it doesn't exist
+ */
+static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
{
struct ast_variable *queue_vars;
struct ast_config *member_config = NULL;
@@ -2520,7 +2530,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
int pos = 0;
int inserted = 0;
- if (!(q = load_realtime_queue(queuename))) {
+ if (!(q = find_load_queue_rt_friendly(queuename))) {
return res;
}
ao2_lock(q);
@@ -5345,7 +5355,7 @@ static int add_to_queue(const char *queuename, const char *interface, const char
/*! \note Ensure the appropriate realtime queue is loaded. Note that this
* short-circuits if the queue is already in memory. */
- if (!(q = load_realtime_queue(queuename))) {
+ if (!(q = find_load_queue_rt_friendly(queuename))) {
return res;
}
@@ -5467,45 +5477,95 @@ static int set_member_paused(const char *queuename, const char *interface, const
return found ? RESULT_SUCCESS : RESULT_FAILURE;
}
-/* \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues. */
+/*!
+ * \internal
+ * \brief helper function for set_member_penalty - given a queue, sets all member penalties with the interface
+ * \param[in] q queue which is having its member's penalty changed - must be unlocked prior to calling
+ * \param[in] interface String of interface used to search for queue members being changed
+ * \param[in] penalty Value penalty is being changed to for the member.
+ * \retval 0 if the there is no member with interface belonging to q and no change is made
+ * \retval 1 if the there is a member with interface belonging to q and changes are made
+ */
+static int set_member_penalty_help_members(struct call_queue *q, const char *interface, int penalty)
+{
+ struct member *mem;
+ int foundinterface = 0;
+ char rtpenalty[80];
+
+ ao2_lock(q);
+ if ((mem = interface_exists(q, interface))) {
+ foundinterface++;
+ if (!mem->realtime) {
+ mem->penalty = penalty;
+ } else {
+ sprintf(rtpenalty, "%i", penalty);
+ update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
+ }
+ ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
+ manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "Penalty: %d\r\n",
+ q->name, mem->interface, penalty);
+ ao2_ref(mem, -1);
+ }
+ ao2_unlock(q);
+
+ return foundinterface;
+}
+
+/*!
+ * \internal
+ * \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
+ * \param[in] queuename If specified, only act on a member if it belongs to this queue
+ * \param[in] interface Interface of queue member(s) having priority set.
+ * \param[in] penalty Value penalty is being changed to for each member
+ */
static int set_member_penalty(const char *queuename, const char *interface, int penalty)
{
int foundinterface = 0, foundqueue = 0;
struct call_queue *q;
- struct member *mem;
- char rtpenalty[80];
+ struct ast_config *queue_config = NULL;
+ struct ao2_iterator queue_iter;
if (penalty < 0 && !negative_penalty_invalid) {
ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
return RESULT_FAILURE;
}
- if ((q = load_realtime_queue(queuename))) {
- foundqueue++;
- ao2_lock(q);
- if ((mem = interface_exists(q, interface))) {
- foundinterface++;
- if (!mem->realtime) {
- mem->penalty = penalty;
- } else {
- sprintf(rtpenalty,"%i", penalty);
- update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
+ if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
+ if (ast_check_realtime("queues")) {
+ char *queuename;
+ queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
+ if (queue_config) {
+ for (queuename = ast_category_browse(queue_config, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(queue_config, queuename)) {
+ if ((q = find_load_queue_rt_friendly(queuename))) {
+ foundqueue++;
+ foundinterface += set_member_penalty_help_members(q, interface, penalty);
+ }
+ }
}
- ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
- manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
- "Queue: %s\r\n"
- "Location: %s\r\n"
- "Penalty: %d\r\n",
- q->name, mem->interface, penalty);
- ao2_ref(mem, -1);
}
- ao2_unlock(q);
+
+ /* After hitting realtime queues, go back and get the regular ones. */
+ queue_iter = ao2_iterator_init(queues, 0);
+
+ while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
+ foundqueue++;
+ foundinterface += set_member_penalty_help_members(q, interface, penalty);
+ }
+
+ } else { /* We actually have a queuename, so we can just act on the single queue. */
+ if ((q = find_load_queue_rt_friendly(queuename))) {
+ foundqueue++;
+ foundinterface += set_member_penalty_help_members(q, interface, penalty);
+ }
}
if (foundinterface) {
return RESULT_SUCCESS;
} else if (!foundqueue) {
- ast_log (LOG_ERROR, "Invalid queuename\n");
+ ast_log (LOG_ERROR, "Invalid queuename\n");
} else {
ast_log (LOG_ERROR, "Invalid interface\n");
}
@@ -5580,7 +5640,7 @@ static void reload_queue_members(void)
}
if (!cur_queue) {
- cur_queue = load_realtime_queue(queue_name);
+ cur_queue = find_load_queue_rt_friendly(queue_name);
}
if (!cur_queue) {
@@ -6281,7 +6341,7 @@ static int queue_function_exists(struct ast_channel *chan, const char *cmd, char
ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
return -1;
}
- q = load_realtime_queue(data);
+ q = find_load_queue_rt_friendly(data);
snprintf(buf, len, "%d", q != NULL? 1 : 0);
if (q) {
queue_t_unref(q, "Done with temporary reference in QUEUE_EXISTS()");
@@ -6318,7 +6378,7 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
AST_STANDARD_APP_ARGS(args, data);
- if ((q = load_realtime_queue(args.queuename))) {
+ if ((q = find_load_queue_rt_friendly(args.queuename))) {
ao2_lock(q);
if (!strcasecmp(args.option, "logged")) {
mem_iter = ao2_iterator_init(q->members, 0);
@@ -6418,7 +6478,7 @@ static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, c
ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
return -1;
}
- } else if ((q = load_realtime_queue(args.queuename))) {
+ } else if ((q = find_load_queue_rt_friendly(args.queuename))) {
ao2_lock(q);
if ((m = interface_exists(q, args.interface))) {
sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
@@ -6480,7 +6540,7 @@ static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, cha
return -1;
}
- if ((q = load_realtime_queue(data))) {
+ if ((q = find_load_queue_rt_friendly(data))) {
ao2_lock(q);
mem_iter = ao2_iterator_init(q->members, 0);
while ((m = ao2_iterator_next(&mem_iter))) {
@@ -7151,7 +7211,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
}
if (argc == 3) { /* specific queue */
- if ((q = load_realtime_queue(argv[2]))) {
+ if ((q = find_load_queue_rt_friendly(argv[2]))) {
queue_t_unref(q, "Done with temporary pointer");
}
} else if (ast_check_realtime("queues")) {
@@ -7162,7 +7222,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
char *queuename;
if (cfg) {
for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
- if ((q = load_realtime_queue(queuename))) {
+ if ((q = find_load_queue_rt_friendly(queuename))) {
queue_t_unref(q, "Done with temporary pointer");
}
}
@@ -7182,7 +7242,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
* been deleted from the in-core container
*/
if (q->realtime) {
- realtime_queue = load_realtime_queue(q->name);
+ realtime_queue = find_load_queue_rt_friendly(q->name);
if (!realtime_queue) {
ao2_unlock(q);
queue_t_unref(q, "Done with iterator");
@@ -8512,7 +8572,7 @@ static int queues_data_provider_get(const struct ast_data_search *search,
for (queuename = ast_category_browse(cfg, NULL);
!ast_strlen_zero(queuename);
queuename = ast_category_browse(cfg, queuename)) {
- if ((queue = load_realtime_queue(queuename))) {
+ if ((queue = find_load_queue_rt_friendly(queuename))) {
queue_unref(queue);
}
}
@@ -8524,7 +8584,7 @@ static int queues_data_provider_get(const struct ast_data_search *search,
while ((queue = ao2_iterator_next(&i))) {
ao2_lock(queue);
if (queue->realtime) {
- queue_realtime = load_realtime_queue(queue->name);
+ queue_realtime = find_load_queue_rt_friendly(queue->name);
if (!queue_realtime) {
ao2_unlock(queue);
queue_unref(queue);
@@ -8688,7 +8748,7 @@ static struct member *find_member_by_queuename_and_interface(const char *queuena
struct member *mem = NULL;
struct call_queue *q;
- if ((q = load_realtime_queue(queuename))) {
+ if ((q = find_load_queue_rt_friendly(queuename))) {
ao2_lock(q);
mem = ao2_find(q->members, interface, OBJ_KEY);
ao2_unlock(q);