Bug 5936 - Cannot AddQueueMember on realtime queue, if queue not yet loaded (different fix than 1.2)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@8402 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher 2006-01-21 20:32:17 +00:00
parent e040a10d81
commit 41c87ccb97
1 changed files with 90 additions and 59 deletions

View File

@ -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,13 +911,60 @@ 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 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;
/* 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.
This will be two separate database transactions, so we might
see queue parameters as they were before another process
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 NULL;
}
}
ast_mutex_lock(&qlock);
q = find_queue_by_name_rt(queuename, queue_vars, member_config);
if (member_config)
ast_config_destroy(member_config);
if (queue_vars)
ast_variables_destroy(queue_vars);
ast_mutex_unlock(&qlock);
}
return q;
}
static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason)
{
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;
@ -925,35 +972,12 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
int inserted = 0;
enum queue_member_status stat;
/*! \note Load from realtime before taking the global qlock, to avoid blocking all
queue operations while waiting for the DB.
This will be two separate database transactions, so we might
see queue parameters as they were before another process
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;
}
}
q = load_realtime_queue(queuename);
if (!q)
return res;
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;
}
ast_mutex_lock(&q->lock);
/* This is our one */
stat = get_member_status(q, qe->max_penalty);
@ -2452,41 +2476,42 @@ 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);
if (interface_exists(q, interface) == NULL) {
new_member = create_queue_member(interface, penalty, paused);
if (new_member != NULL) {
new_member->dynamic = 1;
new_member->next = q->members;
q->members = new_member;
manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
"Queue: %s\r\n"
"Location: %s\r\n"
"Membership: %s\r\n"
"Penalty: %d\r\n"
"CallsTaken: %d\r\n"
"LastCall: %d\r\n"
"Status: %d\r\n"
"Paused: %d\r\n",
q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
if (new_member != NULL) {
new_member->dynamic = 1;
new_member->next = q->members;
q->members = new_member;
manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
"Queue: %s\r\n"
"Location: %s\r\n"
"Membership: %s\r\n"
"Penalty: %d\r\n"
"CallsTaken: %d\r\n"
"LastCall: %d\r\n"
"Status: %d\r\n"
"Paused: %d\r\n",
q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
new_member->penalty, new_member->calls, (int)new_member->lastcall, new_member->status, new_member->paused);
if (dump)
dump_queue_members(q);
if (dump)
dump_queue_members(q);
res = RES_OKAY;
} else {
res = RES_OUTOFMEMORY;
}
res = RES_OKAY;
} else {
res = RES_EXISTS;
res = RES_OUTOFMEMORY;
}
ast_mutex_unlock(&q->lock);
break;
} else {
res = RES_EXISTS;
}
ast_mutex_unlock(&q->lock);
}
@ -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);