Member presistance improvements (bug #3647)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5130 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer 2005-03-03 20:31:21 +00:00
parent 74a28969a4
commit 418eefb9dc
2 changed files with 109 additions and 134 deletions

View file

@ -1730,42 +1730,41 @@ static struct member *create_queue_node(char *interface, int penalty, int paused
/* Dump all members in a specific queue to the databse /* Dump all members in a specific queue to the databse
* *
* <pm_family>/<queuename> = <interface>;<penalty>;<paused>;... * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
* *
*/ */
static void dump_queue_members(struct ast_call_queue *pm_queue) static void dump_queue_members(struct ast_call_queue *pm_queue)
{ {
struct member *cur_member = NULL; struct member *cur_member;
char value[PM_MAX_LEN]; char value[PM_MAX_LEN];
int value_len = 0; int value_len = 0;
int res; int res;
memset(value, 0, sizeof(value)); memset(value, 0, sizeof(value));
if (pm_queue) { if (!pm_queue)
cur_member = pm_queue->members; return;
while (cur_member) {
if (cur_member->dynamic) {
value_len = strlen(value);
res = snprintf(value+value_len, sizeof(value)-value_len, "%s;%d;%d;", cur_member->interface, cur_member->penalty, cur_member->paused);
if (res != strlen(value + value_len)) {
ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
break;
}
}
cur_member = cur_member->next;
}
if (!ast_strlen_zero(value) && !cur_member) { for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
if (ast_db_put(pm_family, pm_queue->name, value)) if (!cur_member->dynamic)
ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n"); continue;
} else {
/* Delete the entry if the queue is empty or there is an error */
ast_db_del(pm_family, pm_queue->name);
}
res = snprintf(value + value_len, sizeof(value) - value_len, "%s;%d;%d%s",
cur_member->interface, cur_member->penalty, cur_member->paused,
cur_member->next ? "|" : "");
if (res != strlen(value + value_len)) {
ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
break;
}
value_len += res;
} }
if (value_len && !cur_member) {
if (ast_db_put(pm_family, pm_queue->name, value))
ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
} else
/* Delete the entry if the queue is empty or there is an error */
ast_db_del(pm_family, pm_queue->name);
} }
static int remove_from_queue(char *queuename, char *interface) static int remove_from_queue(char *queuename, char *interface)
@ -1813,7 +1812,7 @@ static int remove_from_queue(char *queuename, char *interface)
return res; return res;
} }
static int add_to_queue(char *queuename, char *interface, int penalty, int paused) static int add_to_queue(char *queuename, char *interface, int penalty, int paused, int dump)
{ {
struct ast_call_queue *q; struct ast_call_queue *q;
struct member *new_member; struct member *new_member;
@ -1842,7 +1841,7 @@ static int add_to_queue(char *queuename, char *interface, int penalty, int pause
q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static", q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
new_member->penalty, new_member->calls, new_member->lastcall, new_member->status, new_member->paused); new_member->penalty, new_member->calls, new_member->lastcall, new_member->status, new_member->paused);
if (queue_persistent_members) if (dump)
dump_queue_members(q); dump_queue_members(q);
res = RES_OKAY; res = RES_OKAY;
@ -1904,101 +1903,93 @@ static int set_member_paused(char *queuename, char *interface, int paused)
return RESULT_FAILURE; return RESULT_FAILURE;
} }
/* Add members saved in the queue members DB file saves /* Reload dynamic queue members persisted into the astdb */
* created by dump_queue_members(), back into the queues */
static void reload_queue_members(void) static void reload_queue_members(void)
{ {
char *cur_pm_ptr; char *cur_ptr;
char *pm_queue_name; char *queue_name;
char *pm_interface; char *member;
char *pm_penalty_tok; char *interface;
int pm_penalty = 0; char *penalty_tok;
char *pm_paused_tok; int penalty = 0;
int pm_paused = 0; char *paused_tok;
struct ast_db_entry *pm_db_tree = NULL; int paused = 0;
int pm_family_len = 0; struct ast_db_entry *db_tree;
struct ast_call_queue *cur_queue = NULL; struct ast_db_entry *entry;
struct ast_call_queue *cur_queue;
char queue_data[PM_MAX_LEN]; char queue_data[PM_MAX_LEN];
pm_db_tree = ast_db_gettree(pm_family, NULL);
pm_family_len = strlen(pm_family);
ast_mutex_lock(&qlock); ast_mutex_lock(&qlock);
/* Each key in 'pm_family' is the name of a specific queue in which
* we will reload members into. */ /* Each key in 'pm_family' is the name of a queue */
while (pm_db_tree) { db_tree = ast_db_gettree(pm_family, NULL);
pm_queue_name = pm_db_tree->key+pm_family_len+2; for (entry = db_tree; entry; entry = entry->next) {
queue_name = entry->key + strlen(pm_family) + 2;
cur_queue = queues; cur_queue = queues;
while (cur_queue) { while (cur_queue) {
ast_mutex_lock(&cur_queue->lock); ast_mutex_lock(&cur_queue->lock);
if (!strcmp(queue_name, cur_queue->name))
if (strcmp(pm_queue_name, cur_queue->name) == 0)
break; break;
ast_mutex_unlock(&cur_queue->lock); ast_mutex_unlock(&cur_queue->lock);
cur_queue = cur_queue->next; cur_queue = cur_queue->next;
} }
if (!cur_queue) { if (!cur_queue) {
/* If the queue no longer exists, remove it from the /* If the queue no longer exists, remove it from the
* database */ * database */
ast_db_del(pm_family, pm_queue_name); ast_db_del(pm_family, queue_name);
pm_db_tree = pm_db_tree->next;
continue; continue;
} else } else
ast_mutex_unlock(&cur_queue->lock); ast_mutex_unlock(&cur_queue->lock);
if (!ast_db_get(pm_family, pm_queue_name, queue_data, PM_MAX_LEN)) { if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN))
cur_pm_ptr = queue_data; continue;
while ((pm_interface = strsep(&cur_pm_ptr, ";"))) {
/* On the last iteration, pm_interface is a pointer to an empty string. Don't report a spurious error. */
if (pm_interface[0] == 0)
break;
if (!(pm_penalty_tok = strsep(&cur_pm_ptr, ";"))) {
ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (penalty)\n", pm_queue_name);
break;
}
pm_penalty = strtol(pm_penalty_tok, NULL, 10);
if (errno == ERANGE) {
ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", pm_penalty_tok);
break;
}
/* If ptr[1] is ';', the string is 1 char long and can't be an interface */ cur_ptr = queue_data;
while ((member = strsep(&cur_ptr, "|"))) {
if (ast_strlen_zero(member))
continue;
if (cur_pm_ptr[1] == ';') { interface = strsep(&member, ";");
if (!(pm_paused_tok = strsep(&cur_pm_ptr, ";"))) { penalty_tok = strsep(&member, ";");
ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (paused)\n", pm_queue_name); paused_tok = strsep(&member, ";");
break;
}
pm_paused = strtol(pm_paused_tok, NULL, 10);
if ((errno == ERANGE) || (pm_paused < 0 || pm_paused > 1)) {
ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", pm_paused_tok);
break;
}
} else if (option_debug)
ast_verbose(VERBOSE_PREFIX_3 "Found old-format queue member %s:%s\n", pm_queue_name, pm_interface);
if (option_debug) if (!penalty_tok) {
ast_log(LOG_DEBUG, "Reload Members: Queue: %s Member: %s Penalty: %d Paused: %d\n", pm_queue_name, pm_interface, pm_penalty, pm_paused); ast_log(LOG_WARNING, "Error parsing persisent member string for '%s' (penalty)\n", queue_name);
break;
}
penalty = strtol(penalty_tok, NULL, 10);
if (errno == ERANGE) {
ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
break;
}
if (add_to_queue(pm_queue_name, pm_interface, pm_penalty, pm_paused) == RES_OUTOFMEMORY) { if (!paused_tok) {
ast_log(LOG_ERROR, "Out of Memory when loading queue member from astdb\n"); ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
break; break;
} }
paused = strtol(paused_tok, NULL, 10);
if ((errno == ERANGE) || paused < 0 || paused > 1) {
ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
break;
}
if (option_debug)
ast_log(LOG_DEBUG, "Reload Members: Queue: %s Member: %s Penalty: %d Paused: %d\n", queue_name, interface, penalty, paused);
if (add_to_queue(queue_name, interface, penalty, paused, 0) == RES_OUTOFMEMORY) {
ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
break;
} }
} }
pm_db_tree = pm_db_tree->next;
} }
ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
ast_mutex_unlock(&qlock); ast_mutex_unlock(&qlock);
if (pm_db_tree) { if (db_tree) {
ast_db_freetree(pm_db_tree); ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
pm_db_tree = NULL; ast_db_freetree(db_tree);
} }
} }
@ -2200,7 +2191,7 @@ static int aqm_exec(struct ast_channel *chan, void *data)
} }
} }
switch (add_to_queue(queuename, interface, penalty, 0)) { switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) {
case RES_OKAY: case RES_OKAY:
ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename); ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
res = 0; res = 0;
@ -2916,7 +2907,7 @@ static int manager_add_queue_member(struct mansession *s, struct message *m)
else else
paused = abs(ast_true(paused_s)); paused = abs(ast_true(paused_s));
switch (add_to_queue(queuename, interface, penalty, paused)) { switch (add_to_queue(queuename, interface, penalty, paused, queue_persistent_members)) {
case RES_OKAY: case RES_OKAY:
astman_send_ack(s, m, "Added interface to queue"); astman_send_ack(s, m, "Added interface to queue");
break; break;
@ -3018,7 +3009,7 @@ static int handle_add_queue_member(int fd, int argc, char *argv[])
penalty = 0; penalty = 0;
} }
switch (add_to_queue(queuename, interface, penalty, 0)) { switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) {
case RES_OKAY: case RES_OKAY:
ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename); ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
return RESULT_SUCCESS; return RESULT_SUCCESS;

View file

@ -1972,84 +1972,68 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
} }
/* Dump AgentCallbackLogin agents to the database for persistence /* Dump AgentCallbackLogin agents to the database for persistence
* (basically copied from dump_queue_members() in apps/app_queue.c)
*/ */
static void dump_agents(void) static void dump_agents(void)
{ {
struct agent_pvt *cur_agent = NULL; struct agent_pvt *cur_agent = NULL;
cur_agent = agents;
while (cur_agent) {
if (cur_agent->chan != NULL) {
cur_agent = cur_agent->next;
continue;
}
if (!ast_strlen_zero(cur_agent->loginchan)) {
if (ast_db_put(pa_family, cur_agent->agent, cur_agent->loginchan)) {
ast_log(LOG_WARNING, "failed to create persistent entry!\n");
} else {
if (option_debug) {
ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n",
cur_agent->agent, cur_agent->loginchan);
}
}
for (cur_agent = agents; cur_agent; cur_agent = cur_agent->next) {
if (cur_agent->chan)
continue;
if (!ast_strlen_zero(cur_agent->loginchan)) {
if (ast_db_put(pa_family, cur_agent->agent, cur_agent->loginchan))
ast_log(LOG_WARNING, "failed to create persistent entry!\n");
else if (option_debug)
ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan);
} else { } else {
/* Delete - no agent or there is an error */ /* Delete - no agent or there is an error */
ast_db_del(pa_family, cur_agent->agent); ast_db_del(pa_family, cur_agent->agent);
} }
cur_agent = cur_agent->next;
} }
} }
/* Reload the persistent agents from astdb */ /* Reload the persistent agents from astdb */
static void reload_agents(void) static void reload_agents(void)
{ {
char *pa_agent_num; char *agent_num;
struct ast_db_entry *pa_db_tree = NULL; struct ast_db_entry *db_tree;
int pa_family_len = 0; struct ast_db_entry *entry;
struct agent_pvt *cur_agent = NULL; struct agent_pvt *cur_agent;
char agent_data[80]; char agent_data[80];
pa_db_tree = ast_db_gettree(pa_family, NULL); db_tree = ast_db_gettree(pa_family, NULL);
pa_family_len = strlen(pa_family);
ast_mutex_lock(&agentlock); ast_mutex_lock(&agentlock);
while (pa_db_tree) { for (entry = db_tree; entry; entry = entry->next) {
pa_agent_num = pa_db_tree->key + pa_family_len + 2; agent_num = db_tree->key + strlen(pa_family) + 2;
cur_agent = agents; cur_agent = agents;
while (cur_agent) { while (cur_agent) {
ast_mutex_lock(&cur_agent->lock); ast_mutex_lock(&cur_agent->lock);
if (strcmp(agent_num, cur_agent->agent) == 0)
if (strcmp(pa_agent_num, cur_agent->agent) == 0)
break; break;
ast_mutex_unlock(&cur_agent->lock); ast_mutex_unlock(&cur_agent->lock);
cur_agent = cur_agent->next; cur_agent = cur_agent->next;
} }
if (!cur_agent) { if (!cur_agent) {
ast_db_del(pa_family, pa_agent_num); ast_db_del(pa_family, agent_num);
pa_db_tree = pa_db_tree->next;
continue; continue;
} else } else
ast_mutex_unlock(&cur_agent->lock); ast_mutex_unlock(&cur_agent->lock);
if (!ast_db_get(pa_family, pa_agent_num, agent_data, 80)) { if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) {
if (option_debug) { if (option_debug)
ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n", ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n", cur_agent->agent, agent_data);
cur_agent->agent, agent_data); strncpy(cur_agent->loginchan, agent_data, sizeof(cur_agent->loginchan)-1);
}
strncpy(cur_agent->loginchan,agent_data,80);
if (cur_agent->loginstart == 0) if (cur_agent->loginstart == 0)
time(&cur_agent->loginstart); time(&cur_agent->loginstart);
ast_device_state_changed("Agent/%s", cur_agent->agent); ast_device_state_changed("Agent/%s", cur_agent->agent);
} }
pa_db_tree = pa_db_tree->next;
} }
ast_log(LOG_NOTICE, "Agents sucessfully reloaded from database.\n");
ast_mutex_unlock(&agentlock); ast_mutex_unlock(&agentlock);
if (pa_db_tree) { if (db_tree) {
ast_db_freetree(pa_db_tree); ast_log(LOG_NOTICE, "Agents sucessfully reloaded from database.\n");
pa_db_tree = NULL; ast_db_freetree(db_tree);
} }
} }