Optimize the update_realtime_member_field function by not having
authorMark Michelson <mmichelson@digium.com>
Wed, 21 May 2008 18:31:05 +0000 (18:31 +0000)
committerMark Michelson <mmichelson@digium.com>
Wed, 21 May 2008 18:31:05 +0000 (18:31 +0000)
to query the database for the member and instead using a cached
uniqueid.

Special thanks to atis for creating this and for keeping it up
to date with necessary changes

(closes issue #11896)
Reported by: atis
Patches:
      realtime_uniqueid_v6.patch uploaded by atis (license 242)
Tested by: atis

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@117517 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_queue.c

index eb22bbb..0e9ed74 100644 (file)
@@ -384,6 +384,7 @@ struct member {
        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 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
  * 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 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, const
                        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);
-
-       /* Create a new one if not found, else update penalty */
-       if (!m) {
+       /* 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 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 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
 
        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 struct call_queue *load_realtime_queue(const char *queuename)
 
 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 @@ static void update_realtime_members(struct call_queue *q)
 
        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 @@ static int set_member_paused(const char *queuename, const char *interface, const
        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,18 +3888,26 @@ static int set_member_paused(const char *queuename, const char *interface, const
                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);
                                }
+
+                               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);
+                                       ao2_ref(mem, -1);
+                                       continue;
+                               }       
+                               found++;
                                mem->paused = paused;
 
                                if (queue_persistent_members)
                                        dump_queue_members(q);
 
-                               if (mem->realtime)
-                                       update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0");
-
                                ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, ""));
                                
                                if (!ast_strlen_zero(reason)) {
@@ -3915,6 +3931,10 @@ static int set_member_paused(const char *queuename, const char *interface, const
                }
                ao2_unlock(q);
                queue_unref(q);
+               
+               if (!ast_strlen_zero(queuename) && found) {
+                       break;
+               }
        }
 
        return found ? RESULT_SUCCESS : RESULT_FAILURE;