Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 117023) +++ apps/app_queue.c (working copy) @@ -384,6 +384,7 @@ struct call_queue *lastqueue; /*!< Last queue we received a call */ unsigned int dead:1; /*!< Used to detect members deleted in realtime */ unsigned int delme:1; /*!< Flag to delete entry on reload */ + char rt_uniqueid[80]; /*!< Unique id of realtime member entry */ }; struct member_interface { @@ -1309,11 +1310,13 @@ * Search for member in queue, if found update penalty/paused state, * if no memeber exists create one flag it as a RT member and add to queue member list. */ -static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface) +static void rt_handle_member_record(struct call_queue *q, char *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface) { - struct member *m, tmpmem; + struct member *m; + struct ao2_iterator mem_iter; int penalty = 0; int paused = 0; + int found = 0; if (penalty_str) { penalty = atoi(penalty_str); @@ -1327,32 +1330,39 @@ paused = 0; } - /* Find the member, or the place to put a new one. */ - ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface)); - m = ao2_find(q->members, &tmpmem, OBJ_POINTER); + /* Find member by realtime uniqueid and update */ + mem_iter = ao2_iterator_init(q->members, 0); + while ((m = ao2_iterator_next(&mem_iter))) { + if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) { + m->dead = 0; /* Do not delete this one. */ + ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid)); + if (paused_str) + m->paused = paused; + if (strcasecmp(state_interface, m->state_interface)) { + remove_from_interfaces(m->state_interface); + ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface)); + add_to_interfaces(m->state_interface); + } + m->penalty = penalty; + found = 1; + ao2_ref(m, -1); + break; + } + ao2_ref(m, -1); + } - /* Create a new one if not found, else update penalty */ - if (!m) { + /* Create a new member */ + if (!found) { if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) { m->dead = 0; m->realtime = 1; + ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid)); add_to_interfaces(m->state_interface); ao2_link(q->members, m); ao2_ref(m, -1); m = NULL; q->membercount++; } - } else { - m->dead = 0; /* Do not delete this one. */ - if (paused_str) - m->paused = paused; - if (strcasecmp(state_interface, m->state_interface)) { - remove_from_interfaces(m->state_interface); - ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface)); - add_to_interfaces(m->state_interface); - } - m->penalty = penalty; - ao2_ref(m, -1); } } @@ -1521,6 +1531,7 @@ while ((interface = ast_category_browse(member_config, interface))) { rt_handle_member_record(q, interface, + ast_variable_retrieve(member_config, interface, "uniqueid"), S_OR(ast_variable_retrieve(member_config, interface, "membername"),interface), ast_variable_retrieve(member_config, interface, "penalty"), ast_variable_retrieve(member_config, interface, "paused"), @@ -1590,23 +1601,18 @@ static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value) { - struct ast_variable *var; int ret = -1; - if (!(var = ast_load_realtime("queue_members", "interface", mem->interface, "queue_name", queue_name, NULL))) - return ret; - while (var) { - if (!strcmp(var->name, "uniqueid")) - break; - var = var->next; - } - if (var && !ast_strlen_zero(var->value)) { - if ((ast_update_realtime("queue_members", "uniqueid", var->value, field, value, NULL)) > -1) - ret = 0; - } + if (ast_strlen_zero(mem->rt_uniqueid)) + return ret; + + if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, NULL)) > 0) + ret = 0; + return ret; } + static void update_realtime_members(struct call_queue *q) { struct ast_config *member_config = NULL; @@ -1632,6 +1638,7 @@ while ((interface = ast_category_browse(member_config, interface))) { rt_handle_member_record(q, interface, + ast_variable_retrieve(member_config, interface, "uniqueid"), S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface), ast_variable_retrieve(member_config, interface, "penalty"), ast_variable_retrieve(member_config, interface, "paused"), @@ -3869,6 +3876,7 @@ struct call_queue *q; struct member *mem; struct ao2_iterator queue_iter; + int failed; /* Special event for when all queues are paused - individual events still generated */ /* XXX In all other cases, we use the membername, but since this affects all queues, we cannot */ @@ -3880,37 +3888,48 @@ ao2_lock(q); if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) { if ((mem = interface_exists(q, interface))) { - found++; if (mem->paused == paused) { ast_debug(1, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface); } - mem->paused = paused; - if (queue_persistent_members) - dump_queue_members(q); + failed = 0; + if (mem->realtime) { + failed = update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0"); + } + + if (failed) { + ast_log(LOG_WARNING, "Failed %spausing realtime queue member %s:%s\n", (paused ? "" : "un"), q->name, interface); + } else { + found++; + mem->paused = paused; - if (mem->realtime) - update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0"); + if (queue_persistent_members) + dump_queue_members(q); - ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, "")); + ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, "")); - if (!ast_strlen_zero(reason)) { - manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused", - "Queue: %s\r\n" - "Location: %s\r\n" - "MemberName: %s\r\n" - "Paused: %d\r\n" - "Reason: %s\r\n", - q->name, mem->interface, mem->membername, paused, reason); - } else { - manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused", - "Queue: %s\r\n" - "Location: %s\r\n" - "MemberName: %s\r\n" - "Paused: %d\r\n", - q->name, mem->interface, mem->membername, paused); + if (!ast_strlen_zero(reason)) { + manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused", + "Queue: %s\r\n" + "Location: %s\r\n" + "MemberName: %s\r\n" + "Paused: %d\r\n" + "Reason: %s\r\n", + q->name, mem->interface, mem->membername, paused, reason); + } else { + manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused", + "Queue: %s\r\n" + "Location: %s\r\n" + "MemberName: %s\r\n" + "Paused: %d\r\n", + q->name, mem->interface, mem->membername, paused); + } } ao2_ref(mem, -1); + + if (!ast_strlen_zero(queuename) && found) { + break; + } } } ao2_unlock(q);