|
|
|
@ -791,8 +791,7 @@ static void rt_handle_member_record(struct ast_call_queue *q, char *interface, c
|
|
|
|
|
|
|
|
|
|
/*!\brief Reload a single queue via realtime.
|
|
|
|
|
\return Return the queue, or NULL if it doesn't exist.
|
|
|
|
|
\note Should be called with the global qlock locked.
|
|
|
|
|
When found, the queue is returned with q->lock locked. */
|
|
|
|
|
\note Should be called with the global qlock locked. */
|
|
|
|
|
static struct ast_call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
|
|
|
|
|
{
|
|
|
|
|
struct ast_variable *v;
|
|
|
|
@ -818,6 +817,7 @@ static struct ast_call_queue *find_queue_by_name_rt(const char *queuename, struc
|
|
|
|
|
ast_mutex_unlock(&q->lock);
|
|
|
|
|
return NULL;
|
|
|
|
|
} else {
|
|
|
|
|
ast_mutex_unlock(&q->lock);
|
|
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -911,20 +911,27 @@ static struct ast_call_queue *find_queue_by_name_rt(const char *queuename, struc
|
|
|
|
|
m = next_m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_mutex_unlock(&q->lock);
|
|
|
|
|
|
|
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
|
|
|
|
|
static struct ast_call_queue *load_realtime_queue(char *queuename)
|
|
|
|
|
{
|
|
|
|
|
struct ast_variable *queue_vars = NULL;
|
|
|
|
|
struct ast_config *member_config = NULL;
|
|
|
|
|
struct ast_call_queue *q;
|
|
|
|
|
struct queue_ent *cur, *prev = NULL;
|
|
|
|
|
int res = -1;
|
|
|
|
|
int pos = 0;
|
|
|
|
|
int inserted = 0;
|
|
|
|
|
enum queue_member_status stat;
|
|
|
|
|
|
|
|
|
|
/* Find the queue in the in-core list first. */
|
|
|
|
|
ast_mutex_lock(&qlock);
|
|
|
|
|
for (q = queues; q; q = q->next) {
|
|
|
|
|
if (!strcasecmp(q->name, queuename)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&qlock);
|
|
|
|
|
|
|
|
|
|
if (!q) {
|
|
|
|
|
/*! \note Load from realtime before taking the global qlock, to avoid blocking all
|
|
|
|
|
queue operations while waiting for the DB.
|
|
|
|
|
|
|
|
|
@ -933,28 +940,45 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
|
|
|
|
|
changed the queue and member list as it was after the change.
|
|
|
|
|
Thus we might see an empty member list when a queue is
|
|
|
|
|
deleted. In practise, this is unlikely to cause a problem. */
|
|
|
|
|
|
|
|
|
|
queue_vars = ast_load_realtime("queues", "name", queuename, NULL);
|
|
|
|
|
if (queue_vars) {
|
|
|
|
|
member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, NULL);
|
|
|
|
|
if (!member_config) {
|
|
|
|
|
ast_log(LOG_ERROR, "no queue_members defined in your config (extconfig.conf).\n");
|
|
|
|
|
return res;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&qlock);
|
|
|
|
|
|
|
|
|
|
q = find_queue_by_name_rt(queuename, queue_vars, member_config);
|
|
|
|
|
/* Note: If found, find_queue_by_name_rt() returns with q->lock locked. */
|
|
|
|
|
if (member_config)
|
|
|
|
|
ast_config_destroy(member_config);
|
|
|
|
|
if (queue_vars)
|
|
|
|
|
ast_variables_destroy(queue_vars);
|
|
|
|
|
|
|
|
|
|
if (!q) {
|
|
|
|
|
ast_mutex_unlock(&qlock);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
|
|
|
|
|
{
|
|
|
|
|
struct ast_call_queue *q;
|
|
|
|
|
struct queue_ent *cur, *prev = NULL;
|
|
|
|
|
int res = -1;
|
|
|
|
|
int pos = 0;
|
|
|
|
|
int inserted = 0;
|
|
|
|
|
enum queue_member_status stat;
|
|
|
|
|
|
|
|
|
|
q = load_realtime_queue(queuename);
|
|
|
|
|
if (!q)
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&qlock);
|
|
|
|
|
ast_mutex_lock(&q->lock);
|
|
|
|
|
|
|
|
|
|
/* This is our one */
|
|
|
|
|
stat = get_member_status(q, qe->max_penalty);
|
|
|
|
|
if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
|
|
|
|
@ -2452,10 +2476,14 @@ static int add_to_queue(char *queuename, char *interface, int penalty, int pause
|
|
|
|
|
struct member *new_member;
|
|
|
|
|
int res = RES_NOSUCHQUEUE;
|
|
|
|
|
|
|
|
|
|
/* \note Ensure the appropriate realtime queue is loaded. Note that this
|
|
|
|
|
* short-circuits if the queue is already in memory. */
|
|
|
|
|
q = load_realtime_queue(queuename);
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&qlock);
|
|
|
|
|
for (q = queues ; q ; q = q->next) {
|
|
|
|
|
|
|
|
|
|
if (q) {
|
|
|
|
|
ast_mutex_lock(&q->lock);
|
|
|
|
|
if (!strcmp(q->name, queuename)) {
|
|
|
|
|
if (interface_exists(q, interface) == NULL) {
|
|
|
|
|
new_member = create_queue_member(interface, penalty, paused);
|
|
|
|
|
|
|
|
|
@ -2486,9 +2514,6 @@ static int add_to_queue(char *queuename, char *interface, int penalty, int pause
|
|
|
|
|
res = RES_EXISTS;
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&q->lock);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&q->lock);
|
|
|
|
|
}
|
|
|
|
|
ast_mutex_unlock(&qlock);
|
|
|
|
|
return res;
|
|
|
|
@ -3411,7 +3436,13 @@ static int __queues_show(int manager, int fd, int argc, char **argv, int queue_s
|
|
|
|
|
time(&now);
|
|
|
|
|
if ((!queue_show && argc != 2) || (queue_show && argc != 3))
|
|
|
|
|
return RESULT_SHOWUSAGE;
|
|
|
|
|
|
|
|
|
|
/* We only want to load realtime queues when a specific queue is asked for. */
|
|
|
|
|
if (queue_show)
|
|
|
|
|
load_realtime_queue(argv[2]);
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&qlock);
|
|
|
|
|
|
|
|
|
|
q = queues;
|
|
|
|
|
if (!q) {
|
|
|
|
|
ast_mutex_unlock(&qlock);
|
|
|
|
|