Member presistance improvements (bug #3647)
authorMark Spencer <markster@digium.com>
Thu, 3 Mar 2005 20:31:21 +0000 (20:31 +0000)
committerMark Spencer <markster@digium.com>
Thu, 3 Mar 2005 20:31:21 +0000 (20:31 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5130 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_queue.c
channels/chan_agent.c

index deb3bca..e3f2026 100755 (executable)
@@ -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
  *
- * <pm_family>/<queuename> = <interface>;<penalty>;<paused>;...
+ * <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
  *
  */
 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];
        int value_len = 0;
        int res;
 
        memset(value, 0, sizeof(value));
 
-       if (pm_queue) {
-               cur_member = pm_queue->members;
-               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 (!pm_queue)
+               return;
 
-               if (!ast_strlen_zero(value) && !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);
-               }
+       for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
+               if (!cur_member->dynamic)
+                       continue;
 
+               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)
@@ -1813,7 +1812,7 @@ static int remove_from_queue(char *queuename, char *interface)
        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 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",
                                        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);
 
                                        res = RES_OKAY;
@@ -1904,101 +1903,93 @@ static int set_member_paused(char *queuename, char *interface, int paused)
                return RESULT_FAILURE;
 }
 
-/* Add members saved in the queue members DB file saves
- * created by dump_queue_members(), back into the queues */
+/* Reload dynamic queue members persisted into the astdb */
 static void reload_queue_members(void)
 {
-       char *cur_pm_ptr;       
-       char *pm_queue_name;
-       char *pm_interface;
-       char *pm_penalty_tok;
-       int pm_penalty = 0;
-       char *pm_paused_tok;
-       int pm_paused = 0;
-       struct ast_db_entry *pm_db_tree = NULL;
-       int pm_family_len = 0;
-       struct ast_call_queue *cur_queue = NULL;
+       char *cur_ptr;  
+       char *queue_name;
+       char *member;
+       char *interface;
+       char *penalty_tok;
+       int penalty = 0;
+       char *paused_tok;
+       int paused = 0;
+       struct ast_db_entry *db_tree;
+       struct ast_db_entry *entry;
+       struct ast_call_queue *cur_queue;
        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);
-       /* Each key in 'pm_family' is the name of a specific queue in which
-        * we will reload members into. */
-       while (pm_db_tree) {
-               pm_queue_name = pm_db_tree->key+pm_family_len+2;
+
+       /* Each key in 'pm_family' is the name of a queue */
+       db_tree = ast_db_gettree(pm_family, NULL);
+       for (entry = db_tree; entry; entry = entry->next) {
+
+               queue_name = entry->key + strlen(pm_family) + 2;
 
                cur_queue = queues;
                while (cur_queue) {
                        ast_mutex_lock(&cur_queue->lock);
-                       
-                       if (strcmp(pm_queue_name, cur_queue->name) == 0)
+                       if (!strcmp(queue_name, cur_queue->name))
                                break;
-                       
                        ast_mutex_unlock(&cur_queue->lock);
-                       
                        cur_queue = cur_queue->next;
                }
 
                if (!cur_queue) {
                        /* If the queue no longer exists, remove it from the
                         * database */
-                       ast_db_del(pm_family, pm_queue_name);
-                       pm_db_tree = pm_db_tree->next;
+                       ast_db_del(pm_family, queue_name);
                        continue;
                } else
                        ast_mutex_unlock(&cur_queue->lock);
 
-               if (!ast_db_get(pm_family, pm_queue_name, queue_data, PM_MAX_LEN)) {
-                       cur_pm_ptr = queue_data;
-                       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 (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN))
+                       continue;
 
-                               /* 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] == ';') {
-                                       if (!(pm_paused_tok = strsep(&cur_pm_ptr, ";"))) {
-                                               ast_log(LOG_WARNING, "Error parsing corrupted Queue DB string for '%s' (paused)\n", pm_queue_name);
-                                               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)
-                                       ast_log(LOG_DEBUG, "Reload Members: Queue: %s  Member: %s  Penalty: %d  Paused: %d\n", pm_queue_name, pm_interface, pm_penalty, pm_paused);
-       
-                               if (add_to_queue(pm_queue_name, pm_interface, pm_penalty, pm_paused) == RES_OUTOFMEMORY) {
-                                       ast_log(LOG_ERROR, "Out of Memory when loading queue member from astdb\n");
-                                       break;
-                               }
+                       interface = strsep(&member, ";");
+                       penalty_tok = strsep(&member, ";");
+                       paused_tok = strsep(&member, ";");
+
+                       if (!penalty_tok) {
+                               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 (!paused_tok) {
+                               ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
+                               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);
-       if (pm_db_tree) {
-               ast_db_freetree(pm_db_tree);
-               pm_db_tree = NULL;
+       if (db_tree) {
+               ast_log(LOG_NOTICE, "Queue members sucessfully reloaded from database.\n");
+               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:
                ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", interface, queuename);
                res = 0;
@@ -2916,7 +2907,7 @@ static int manager_add_queue_member(struct mansession *s, struct message *m)
        else
                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:
                astman_send_ack(s, m, "Added interface to queue");
                break;
@@ -3018,7 +3009,7 @@ static int handle_add_queue_member(int fd, int argc, char *argv[])
                penalty = 0;
        }
 
-       switch (add_to_queue(queuename, interface, penalty, 0)) {
+       switch (add_to_queue(queuename, interface, penalty, 0, queue_persistent_members)) {
        case RES_OKAY:
                ast_cli(fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
                return RESULT_SUCCESS;
index 1650bb0..c6b137e 100755 (executable)
@@ -1972,84 +1972,68 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
 }
 
 /* Dump AgentCallbackLogin agents to the database for persistence
- *  (basically copied from dump_queue_members() in apps/app_queue.c)
  */
 
 static void dump_agents(void)
 {
        struct agent_pvt *cur_agent = NULL;
-       cur_agent = agents;
-       while (cur_agent) {
-               if (cur_agent->chan != NULL) {
-                       cur_agent = cur_agent->next;
+
+       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)) {
+                       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 if (option_debug)
+                               ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan);
                } else {
                        /* Delete -  no agent or there is an error */
                        ast_db_del(pa_family, cur_agent->agent);
                }
-               cur_agent = cur_agent->next;
        }
 }
 
 /* Reload the persistent agents from astdb */
 static void reload_agents(void)
 {
-       char *pa_agent_num;
-       struct ast_db_entry *pa_db_tree = NULL;
-       int pa_family_len = 0;
-       struct agent_pvt *cur_agent = NULL;
+       char *agent_num;
+       struct ast_db_entry *db_tree;
+       struct ast_db_entry *entry;
+       struct agent_pvt *cur_agent;
        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);
-       while (pa_db_tree) {
-               pa_agent_num = pa_db_tree->key + pa_family_len + 2;
+       for (entry = db_tree; entry; entry = entry->next) {
+               agent_num = db_tree->key + strlen(pa_family) + 2;
                cur_agent = agents;
                while (cur_agent) {
                        ast_mutex_lock(&cur_agent->lock);
-
-                       if (strcmp(pa_agent_num, cur_agent->agent) == 0)
+                       if (strcmp(agent_num, cur_agent->agent) == 0)
                                break;
-
                        ast_mutex_unlock(&cur_agent->lock);
                        cur_agent = cur_agent->next;
                }
                if (!cur_agent) {
-                       ast_db_del(pa_family, pa_agent_num);
-                       pa_db_tree = pa_db_tree->next;
+                       ast_db_del(pa_family, agent_num);
                        continue;
                } else
                        ast_mutex_unlock(&cur_agent->lock);
-               if (!ast_db_get(pa_family, pa_agent_num, agent_data, 80)) {
-                       if (option_debug) {
-                               ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n",
-                                               cur_agent->agent, agent_data);
-                       }
-                       strncpy(cur_agent->loginchan,agent_data,80);
+               if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) {
+                       if (option_debug)
+                               ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n", cur_agent->agent, agent_data);
+                       strncpy(cur_agent->loginchan, agent_data, sizeof(cur_agent->loginchan)-1);
                        if (cur_agent->loginstart == 0)
                                time(&cur_agent->loginstart);
                        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);
-       if (pa_db_tree) {
-               ast_db_freetree(pa_db_tree);
-               pa_db_tree = NULL;
+       if (db_tree) {
+               ast_log(LOG_NOTICE, "Agents sucessfully reloaded from database.\n");
+               ast_db_freetree(db_tree);
        }
 }