Replace direct access to channel name with accessor functions
[asterisk/asterisk.git] / apps / app_queue.c
index 0e57ec4..ec9ad39 100644 (file)
@@ -224,6 +224,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                        up by another user.</para>
                        <para>This application will return to the dialplan if the queue does not exist, or
                        any of the join options cause the caller to not enter the queue.</para>
+                       <para>This application does not automatically answer and should be preceeded
+                       by an application such as Answer(), Progress(), or Ringing().</para>
                        <para>This application sets the following channel variable upon completion:</para>
                        <variablelist>
                                <variable name="QUEUESTATUS">
@@ -955,6 +957,9 @@ static int negative_penalty_invalid = 0;
 /*! \brief queues.conf [general] option */
 static int log_membername_as_agent = 0;
 
+/*! \brief queues.conf [general] option */
+static int check_state_unknown = 0;
+
 enum queue_result {
        QUEUE_UNKNOWN = 0,
        QUEUE_TIMEOUT = 1,
@@ -1156,6 +1161,8 @@ struct call_queue {
        unsigned int realtime:1;
        unsigned int found:1;
        unsigned int relativeperiodicannounce:1;
+       unsigned int autopausebusy:1;
+       unsigned int autopauseunavail:1;
        enum empty_conditions joinempty;
        enum empty_conditions leavewhenempty;
        int announcepositionlimit;          /*!< How many positions we announce? */
@@ -1191,12 +1198,6 @@ struct call_queue {
        int autofill;                       /*!< Ignore the head call status and ring an available agent */
        
        struct ao2_container *members;             /*!< Head of the list of members */
-       /*! 
-        * \brief Number of members _logged in_
-        * \note There will be members in the members container that are not logged
-        *       in, so this can not simply be replaced with ao2_container_count(). 
-        */
-       int membercount;
        struct queue_ent *head;             /*!< Head of the list of callers */
        AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
        AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
@@ -1447,7 +1448,7 @@ struct statechange {
 };
 
 /*! \brief set a member's status based on device state of that member's state_interface.
- *  
+ *
  * Lock interface list find sc, iterate through each queues queue_member list for member to
  * update state inside queues
 */
@@ -1626,21 +1627,24 @@ static int get_queue_member_status(struct member *cur)
 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
 {
        struct member *cur;
-       
+
        if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
                cur->penalty = penalty;
                cur->paused = paused;
                ast_copy_string(cur->interface, interface, sizeof(cur->interface));
-               if (!ast_strlen_zero(state_interface))
+               if (!ast_strlen_zero(state_interface)) {
                        ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
-               else
+               } else {
                        ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
-               if (!ast_strlen_zero(membername))
+               }
+               if (!ast_strlen_zero(membername)) {
                        ast_copy_string(cur->membername, membername, sizeof(cur->membername));
-               else
+               } else {
                        ast_copy_string(cur->membername, interface, sizeof(cur->membername));
-               if (!strchr(cur->interface, '/'))
+               }
+               if (!strchr(cur->interface, '/')) {
                        ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
+               }
                if (!strncmp(cur->state_interface, "hint:", 5)) {
                        char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
                        char *exten = strsep(&context, "@") + 5;
@@ -1668,22 +1672,29 @@ static int compress_char(const char c)
 static int member_hash_fn(const void *obj, const int flags)
 {
        const struct member *mem = obj;
-       const char *chname = strchr(mem->interface, '/');
+       const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
+       const char *chname = strchr(interface, '/');
        int ret = 0, i;
-       if (!chname)
-               chname = mem->interface;
-       for (i = 0; i < 5 && chname[i]; i++)
+
+       if (!chname) {
+               chname = interface;
+       }
+       for (i = 0; i < 5 && chname[i]; i++) {
                ret += compress_char(chname[i]) << (i * 6);
+       }
        return ret;
 }
 
 static int member_cmp_fn(void *obj1, void *obj2, int flags)
 {
-       struct member *mem1 = obj1, *mem2 = obj2;
-       return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH | CMP_STOP;
+       struct member *mem1 = obj1;
+       struct member *mem2 = obj2;
+       const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
+
+       return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
 }
 
-/*! 
+/*!
  * \brief Initialize Queue default values.
  * \note the queue's lock  must be held before executing this function
 */
@@ -1747,8 +1758,13 @@ static void init_queue(struct call_queue *q)
        ast_string_field_set(q, sound_thanks, "queue-thankyou");
        ast_string_field_set(q, sound_reporthold, "queue-reporthold");
 
-       if ((q->sound_periodicannounce[0] = ast_str_create(32)))
+       if (!q->sound_periodicannounce[0]) {
+               q->sound_periodicannounce[0] = ast_str_create(32);
+       }
+
+       if (q->sound_periodicannounce[0]) {
                ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
+       }
 
        for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
                if (q->sound_periodicannounce[i])
@@ -1779,14 +1795,14 @@ static void clear_queue(struct call_queue *q)
        }
 }
 
-/*! 
+/*!
  * \brief Change queue penalty by adding rule.
  *
- * Check rule for errors with time or fomatting, see if rule is relative to rest 
+ * Check rule for errors with time or fomatting, see if rule is relative to rest
  * of queue, iterate list of rules to find correct insertion point, insert and return.
  * \retval -1 on failure
- * \retval 0 on success 
- * \note Call this with the rule_lists locked 
+ * \retval 0 on success
+ * \note Call this with the rule_lists locked
 */
 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
 {
@@ -2033,6 +2049,10 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
                q->autopause = autopause2int(val);
        } else if (!strcasecmp(param, "autopausedelay")) {
                q->autopausedelay = atoi(val);
+       } else if (!strcasecmp(param, "autopausebusy")) {
+               q->autopausebusy = ast_true(val);
+       } else if (!strcasecmp(param, "autopauseunavail")) {
+               q->autopauseunavail = ast_true(val);
        } else if (!strcasecmp(param, "maxlen")) {
                q->maxlen = atoi(val);
                if (q->maxlen < 0)
@@ -2136,8 +2156,9 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
 
        if (paused_str) {
                paused = atoi(paused_str);
-               if (paused < 0)
+               if (paused < 0) {
                        paused = 0;
+               }
        }
 
        if ((config_val = ast_variable_retrieve(member_config, interface, "ignorebusy"))) {
@@ -2152,8 +2173,9 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
                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)
+                       if (paused_str) {
                                m->paused = paused;
+                       }
                        if (strcasecmp(state_interface, m->state_interface)) {
                                ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
                        }
@@ -2175,14 +2197,13 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
                        m->ignorebusy = ignorebusy;
                        ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
                        if (!log_membername_as_agent) {
-                               ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", "");
+                               ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
                        } else {
-                               ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", "");
+                               ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
                        }
                        ao2_link(q->members, m);
                        ao2_ref(m, -1);
                        m = NULL;
-                       q->membercount++;
                }
        }
 }
@@ -2197,7 +2218,6 @@ static void free_members(struct call_queue *q, int all)
        while ((cur = ao2_iterator_next(&mem_iter))) {
                if (all || !cur->dynamic) {
                        ao2_unlink(q->members, cur);
-                       q->membercount--;
                }
                ao2_ref(cur, -1);
        }
@@ -2239,15 +2259,15 @@ static struct call_queue *alloc_queue(const char *queuename)
  * Check for statically defined queue first, check if deleted RT queue,
  * check for new RT queue, if queue vars are not defined init them with defaults.
  * reload RT queue vars, set RT queue members dead and reload them, return finished queue.
- * \retval the queue, 
+ * \retval the queue,
  * \retval NULL if it doesn't exist.
- * \note Should be called with the "queues" container locked. 
+ * \note Should be called with the "queues" container locked.
 */
 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
 {
        struct ast_variable *v;
        struct call_queue *q, tmpq = {
-               .name = queuename,      
+               .name = queuename,
        };
        struct member *m;
        struct ao2_iterator mem_iter;
@@ -2270,10 +2290,10 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
                                return q;
                        }
                }
-       } else if (!member_config)
+       } else if (!member_config) {
                /* Not found in the list, and it's not realtime ... */
                return NULL;
-
+       }
        /* Check if queue is defined in realtime. */
        if (!queue_vars) {
                /* Delete queue from in-core list if it has been deleted in realtime. */
@@ -2295,12 +2315,12 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
        /* Create a new queue if an in-core entry does not exist yet. */
        if (!q) {
                struct ast_variable *tmpvar = NULL;
-               if (!(q = alloc_queue(queuename)))
+               if (!(q = alloc_queue(queuename))) {
                        return NULL;
+               }
                ao2_lock(q);
                clear_queue(q);
                q->realtime = 1;
-               q->membercount = 0;
                /*Before we initialize the queue, we need to set the strategy, so that linear strategy
                 * will allocate the members properly
                 */
@@ -2316,8 +2336,9 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
                        }
                }
                /* We traversed all variables and didn't find a strategy */
-               if (!tmpvar)
+               if (!tmpvar) {
                        q->strategy = QUEUE_STRATEGY_RINGALL;
+               }
                queues_t_link(queues, q, "Add queue to container");
        }
        init_queue(q);          /* Ensure defaults for all parameters not set explicitly. */
@@ -2340,13 +2361,12 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
                queue_set_param(q, tmp_name, v->value, -1, 0);
        }
 
-       /* Temporarily set realtime members dead so we can detect deleted ones. 
-        * Also set the membercount correctly for realtime*/
+       /* Temporarily set realtime members dead so we can detect deleted ones. */
        mem_iter = ao2_iterator_init(q->members, 0);
        while ((m = ao2_iterator_next(&mem_iter))) {
-               q->membercount++;
-               if (m->realtime)
+               if (m->realtime) {
                        m->dead = 1;
+               }
                ao2_ref(m, -1);
        }
        ao2_iterator_destroy(&mem_iter);
@@ -2365,7 +2385,6 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
                                ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
                        }
                        ao2_unlink(q->members, m);
-                       q->membercount--;
                }
                ao2_ref(m, -1);
        }
@@ -2376,13 +2395,23 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
        return q;
 }
 
-/*! \note Returns a reference to the loaded realtime queue. */
-static struct call_queue *load_realtime_queue(const char *queuename)
+/*!
+ * note  */
+
+/*!
+ * \internal
+ * \brief Returns reference to the named queue. If the queue is realtime, it will load the queue as well.
+ * \param queuename - name of the desired queue
+ *
+ * \retval the queue
+ * \retval NULL if it doesn't exist
+ */
+static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
 {
        struct ast_variable *queue_vars;
        struct ast_config *member_config = NULL;
        struct call_queue *q = NULL, tmpq = {
-               .name = queuename,      
+               .name = queuename,
        };
        int prev_weight = 0;
 
@@ -2413,13 +2442,11 @@ static struct call_queue *load_realtime_queue(const char *queuename)
                        queue_t_unref(q, "Need to find realtime queue");
                }
 
-               ao2_lock(queues);
-
                q = find_queue_by_name_rt(queuename, queue_vars, member_config);
                ast_config_destroy(member_config);
                ast_variables_destroy(queue_vars);
 
-               /* update the use_weight value if the queue's has gained or lost a weight */ 
+               /* update the use_weight value if the queue's has gained or lost a weight */
                if (q) {
                        if (!q->weight && prev_weight) {
                                ast_atomic_fetchadd_int(&use_weight, -1);
@@ -2429,8 +2456,6 @@ static struct call_queue *load_realtime_queue(const char *queuename)
                        }
                }
                /* Other cases will end up with the proper value for use_weight */
-               ao2_unlock(queues);
-
        } else {
                update_realtime_members(q);
        }
@@ -2464,10 +2489,9 @@ static void update_realtime_members(struct call_queue *q)
                return;
        }
 
-       ao2_lock(queues);
        ao2_lock(q);
-       
-       /* Temporarily set realtime  members dead so we can detect deleted ones.*/ 
+
+       /* Temporarily set realtime  members dead so we can detect deleted ones.*/
        mem_iter = ao2_iterator_init(q->members, 0);
        while ((m = ao2_iterator_next(&mem_iter))) {
                if (m->realtime)
@@ -2490,13 +2514,11 @@ static void update_realtime_members(struct call_queue *q)
                                ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
                        }
                        ao2_unlink(q->members, m);
-                       q->membercount--;
                }
                ao2_ref(m, -1);
        }
        ao2_iterator_destroy(&mem_iter);
        ao2_unlock(q);
-       ao2_unlock(queues);
        ast_config_destroy(member_config);
 }
 
@@ -2508,10 +2530,9 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
        int pos = 0;
        int inserted = 0;
 
-       if (!(q = load_realtime_queue(queuename)))
+       if (!(q = find_load_queue_rt_friendly(queuename))) {
                return res;
-
-       ao2_lock(queues);
+       }
        ao2_lock(q);
 
        /* This is our one */
@@ -2520,7 +2541,6 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
                if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) {
                        *reason = QUEUE_JOINEMPTY;
                        ao2_unlock(q);
-                       ao2_unlock(queues);
                        queue_t_unref(q, "Done with realtime queue");
                        return res;
                }
@@ -2575,16 +2595,15 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
                        "Position: %d\r\n"
                        "Count: %d\r\n"
                        "Uniqueid: %s\r\n",
-                       qe->chan->name,
+                       ast_channel_name(qe->chan),
                        S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
                        S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
                        S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
                        S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
                        q->name, qe->pos, q->count, qe->chan->uniqueid );
-               ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
+               ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
        }
        ao2_unlock(q);
-       ao2_unlock(queues);
        queue_t_unref(q, "Done with realtime queue");
 
        return res;
@@ -2771,7 +2790,7 @@ static int say_position(struct queue_ent *qe, int ringing)
 posout:
        if (qe->parent->announceposition) {
                ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
-                       qe->chan->name, qe->parent->name, qe->pos);
+                       ast_channel_name(qe->chan), qe->parent->name, qe->pos);
        }
        if (say_thanks) {
                res = play_file(qe->chan, qe->parent->sound_thanks);
@@ -2822,8 +2841,9 @@ static void leave_queue(struct queue_ent *qe)
        struct penalty_rule *pr_iter;
        int pos = 0;
 
-       if (!(q = qe->parent))
+       if (!(q = qe->parent)) {
                return;
+       }
        queue_t_ref(q, "Copy queue pointer from queue entry");
        ao2_lock(q);
 
@@ -2836,8 +2856,8 @@ static void leave_queue(struct queue_ent *qe)
                        /* Take us out of the queue */
                        ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
                                "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
-                               qe->chan->name, q->name,  q->count, qe->pos, qe->chan->uniqueid);
-                       ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name );
+                               ast_channel_name(qe->chan), q->name,  q->count, qe->pos, qe->chan->uniqueid);
+                       ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
                        /* Take us out of the queue */
                        if (prev)
                                prev->next = current->next;
@@ -2866,7 +2886,7 @@ static void leave_queue(struct queue_ent *qe)
                }
        }
 
-       if (q->dead) {  
+       if (q->dead) {
                /* It's dead and nobody is in it, so kill it */
                queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
        }
@@ -2977,9 +2997,7 @@ static int compare_weight(struct call_queue *rq, struct member *member)
        struct member *mem;
        int found = 0;
        struct ao2_iterator queue_iter;
-       
-       /* q's lock and rq's lock already set by try_calling()
-        * to solve deadlock */
+
        queue_iter = ao2_iterator_init(queues, 0);
        while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
                if (q == rq) { /* don't check myself, could deadlock */
@@ -3099,12 +3117,12 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
        }
 
        if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
-               if ((tmp->member->status == AST_DEVICE_UNKNOWN) || (tmp->member->status == AST_DEVICE_NOT_INUSE)) {
-                       newstate = ast_parse_device_state(tmp->member->interface);
+               if (check_state_unknown && (tmp->member->status == AST_DEVICE_UNKNOWN)) {
+                       newstate = ast_device_state(tmp->member->interface);
                        if (newstate != tmp->member->status) {
-                               ast_log(LOG_ERROR, "Found a channel matching iterface %s while status was %i changed to %i\n",
-                                       tmp->member->interface, tmp->member->status, newstate);
-                               update_status(qe->parent, tmp->member, newstate);
+                               ast_log(LOG_WARNING, "Found a channel matching iterface %s while status was %s changed to %s\n",
+                                       tmp->member->interface, ast_devstate2str(tmp->member->status), ast_devstate2str(newstate));
+                               ast_devstate_changed_literal(newstate, tmp->member->interface);
                        }
                }
                if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
@@ -3139,7 +3157,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
                if (qe->chan->cdr) {
                        ast_cdr_busy(qe->chan->cdr);
                }
-               tmp->stillgoing = 0;    
+               tmp->stillgoing = 0;
 
                ao2_lock(qe->parent);
                update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
@@ -3151,10 +3169,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
                return 0;
        }
 
-       ast_channel_lock(tmp->chan);
-       while (ast_channel_trylock(qe->chan)) {
-               CHANNEL_DEADLOCK_AVOIDANCE(tmp->chan);
-       }
+       ast_channel_lock_both(tmp->chan, qe->chan);
 
        if (qe->cancel_answered_elsewhere) {
                ast_set_flag(tmp->chan, AST_FLAG_ANSWERED_ELSEWHERE);
@@ -3204,7 +3219,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
        if (ast_cdr_isset_unanswered()) {
                /* they want to see the unanswered dial attempts! */
                /* set up the CDR fields on all the CDRs to give sensical information */
-               ast_cdr_setdestchan(tmp->chan->cdr, tmp->chan->name);
+               ast_cdr_setdestchan(tmp->chan->cdr, ast_channel_name(tmp->chan));
                strcpy(tmp->chan->cdr->clid, qe->chan->cdr->clid);
                strcpy(tmp->chan->cdr->channel, qe->chan->cdr->channel);
                strcpy(tmp->chan->cdr->src, qe->chan->cdr->src);
@@ -3217,13 +3232,14 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
                strcpy(tmp->chan->cdr->userfield, qe->chan->cdr->userfield);
        }
 
+       ast_channel_unlock(tmp->chan);
+       ast_channel_unlock(qe->chan);
+
        /* Place the call, but don't wait on the answer */
        if ((res = ast_call(tmp->chan, location, 0))) {
                /* Again, keep going even if there's an error */
                ast_debug(1, "ast call on peer returned %d\n", res);
                ast_verb(3, "Couldn't call %s\n", tmp->interface);
-               ast_channel_unlock(tmp->chan);
-               ast_channel_unlock(qe->chan);
                do_hang(tmp);
                (*busies)++;
                update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
@@ -3231,6 +3247,8 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
        } else if (qe->parent->eventwhencalled) {
                char vars[2048];
 
+               ast_channel_lock_both(tmp->chan, qe->chan);
+
                manager_event(EVENT_FLAG_AGENT, "AgentCalled",
                        "Queue: %s\r\n"
                        "AgentCalled: %s\r\n"
@@ -3246,17 +3264,19 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
                        "Priority: %d\r\n"
                        "Uniqueid: %s\r\n"
                        "%s",
-                       qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
-                       S_COR(tmp->chan->caller.id.number.valid, tmp->chan->caller.id.number.str, "unknown"),
-                       S_COR(tmp->chan->caller.id.name.valid, tmp->chan->caller.id.name.str, "unknown"),
-                       S_COR(tmp->chan->connected.id.number.valid, tmp->chan->connected.id.number.str, "unknown"),
-                       S_COR(tmp->chan->connected.id.name.valid, tmp->chan->connected.id.name.str, "unknown"),
+                       qe->parent->name, tmp->interface, tmp->member->membername, ast_channel_name(qe->chan), ast_channel_name(tmp->chan),
+                       S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),
+                       S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
+                       S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),
+                       S_COR(qe->chan->connected.id.name.valid, qe->chan->connected.id.name.str, "unknown"),
                        qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
                        qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
+
+               ast_channel_unlock(tmp->chan);
+               ast_channel_unlock(qe->chan);
+
                ast_verb(3, "Called %s\n", tmp->interface);
        }
-       ast_channel_unlock(tmp->chan);
-       ast_channel_unlock(qe->chan);
 
        update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
        return 1;
@@ -3372,7 +3392,7 @@ static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
        return 0;
 }
 
-/*! \brief Playback announcement to queued members if peroid has elapsed */
+/*! \brief Playback announcement to queued members if period has elapsed */
 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
 {
        int res = 0;
@@ -3469,7 +3489,7 @@ static void rna(int rnatime, struct queue_ent *qe, char *interface, char *member
                                                "%s",
                                                qe->parent->name,
                                                qe->chan->uniqueid,
-                                               qe->chan->name,
+                                               ast_channel_name(qe->chan),
                                                interface,
                                                membername,
                                                rnatime,
@@ -3484,8 +3504,10 @@ static void rna(int rnatime, struct queue_ent *qe, char *interface, char *member
                                time_t idletime = time(&idletime)-mem->lastcall;
                                if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
                                        ao2_unlock(qe->parent);
+                                       ao2_ref(mem, -1);
                                        return;
                                }
+                               ao2_ref(mem, -1);
                        }
                        ao2_unlock(qe->parent);
                }
@@ -3552,7 +3574,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
        ast_party_connected_line_init(&connected_caller);
 
        ast_channel_lock(qe->chan);
-       inchan_name = ast_strdupa(qe->chan->name);
+       inchan_name = ast_strdupa(ast_channel_name(qe->chan));
        ast_channel_unlock(qe->chan);
 
        starttime = (long) time(NULL);
@@ -3616,7 +3638,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                        char ochan_name[AST_CHANNEL_NAME];
                        if (o->chan) {
                                ast_channel_lock(o->chan);
-                               ast_copy_string(ochan_name, o->chan->name, sizeof(ochan_name));
+                               ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
                                ast_channel_unlock(o->chan);
                        }
                        if (o->stillgoing && (o->chan) &&  (o->chan->_state == AST_STATE_UP)) {
@@ -3688,10 +3710,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                        } else {
                                                struct ast_party_redirecting redirecting;
 
-                                               ast_channel_lock(o->chan);
-                                               while (ast_channel_trylock(in)) {
-                                                       CHANNEL_DEADLOCK_AVOIDANCE(o->chan);
-                                               }
+                                               ast_channel_lock_both(o->chan, in);
                                                ast_channel_inherit_variables(in, o->chan);
                                                ast_channel_datastore_inherit(in, o->chan);
 
@@ -3786,7 +3805,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                                        do_hang(o);
                                                        endtime = (long) time(NULL);
                                                        endtime -= starttime;
-                                                       rna(endtime * 1000, qe, on, membername, 0);
+                                                       rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
                                                        if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
                                                                if (qe->parent->timeoutrestart)
                                                                        *to = orig;
@@ -3804,7 +3823,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
                                                                ast_cdr_busy(in->cdr);
                                                        endtime = (long) time(NULL);
                                                        endtime -= starttime;
-                                                       rna(endtime * 1000, qe, on, membername, 0);
+                                                       rna(endtime * 1000, qe, on, membername, qe->parent->autopauseunavail);
                                                        do_hang(o);
                                                        if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
                                                                if (qe->parent->timeoutrestart)
@@ -3971,10 +3990,10 @@ static int is_our_turn(struct queue_ent *qe)
         * from the front of the queue are valid when autofill is disabled)
         */
        if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
-               ast_debug(1, "It's our turn (%s).\n", qe->chan->name);
+               ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
                res = 1;
        } else {
-               ast_debug(1, "It's not our turn (%s).\n", qe->chan->name);
+               ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
                res = 0;
        }
 
@@ -4005,7 +4024,7 @@ static void update_qe_rule(struct queue_ent *qe)
        pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
        qe->max_penalty = max_penalty;
        qe->min_penalty = min_penalty;
-       ast_debug(3, "Setting max penalty to %d and min penalty to %d for caller %s since %d seconds have elapsed\n", qe->max_penalty, qe->min_penalty, qe->chan->name, qe->pr->time);
+       ast_debug(3, "Setting max penalty to %d and min penalty to %d for caller %s since %d seconds have elapsed\n", qe->max_penalty, qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
        qe->pr = AST_LIST_NEXT(qe->pr, list);
 }
 
@@ -4101,8 +4120,8 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
 
        struct member *mem;
        struct call_queue *qtmp;
-       struct ao2_iterator queue_iter; 
-       
+       struct ao2_iterator queue_iter;
+
        if (shared_lastcall) {
                queue_iter = ao2_iterator_init(queues, 0);
                while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
@@ -4146,7 +4165,8 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
 {
        /* disregarding penalty on too few members? */
-       unsigned char usepenalty = (q->membercount <= q->penaltymemberslimit) ? 0 : 1;
+       int membercount = ao2_container_count(q->members);
+       unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
 
        if (usepenalty) {
                if ((qe->max_penalty && (mem->penalty > qe->max_penalty)) ||
@@ -4155,7 +4175,7 @@ static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct
                }
        } else {
                ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
-                         q->membercount, q->penaltymemberslimit);
+                         membercount, q->penaltymemberslimit);
        }
 
        switch (q->strategy) {
@@ -4249,7 +4269,7 @@ static void send_agent_complete(const struct queue_ent *qe, const char *queuenam
                "TalkTime: %ld\r\n"
                "Reason: %s\r\n"
                "%s",
-               queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
+               queuename, qe->chan->uniqueid, ast_channel_name(peer), member->interface, member->membername,
                (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
                qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
 }
@@ -4376,7 +4396,7 @@ static void end_bridge_callback(void *data)
 }
 
 /*! \brief A large function which calls members, updates statistics, and bridges the caller and a member
- * 
+ *
  * Here is the process of this function
  * 1. Process any options passed to the Queue() application. Options here mean the third argument to Queue()
  * 2. Iterate trough the members of the queue, creating a callattempt corresponding to each member. During this
@@ -4443,7 +4463,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
        struct ao2_iterator memi;
        struct ast_datastore *datastore, *transfer_ds;
        struct queue_end_bridge *queue_end_bridge = NULL;
-       const int need_weight = use_weight;
 
        ast_channel_lock(qe->chan);
        datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
@@ -4499,7 +4518,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                        if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED)
                                (*tries)++;
                        else
-                               *tries = qe->parent->membercount;
+                               *tries = ao2_container_count(qe->parent->members);
                        *noption = 1;
                        break;
                case 'i':
@@ -4526,12 +4545,9 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                qe->cancel_answered_elsewhere = 1;
        }
 
-       /* Hold the lock while we setup the outgoing calls */
-       if (need_weight)
-               ao2_lock(queues);
        ao2_lock(qe->parent);
        ast_debug(1, "%s is trying to call a queue member.\n",
-                                                       qe->chan->name);
+                                                       ast_channel_name(qe->chan));
        ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
        if (!ast_strlen_zero(qe->announce))
                announce = qe->announce;
@@ -4547,8 +4563,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                        ao2_ref(cur, -1);
                        ao2_unlock(qe->parent);
                        ao2_iterator_destroy(&memi);
-                       if (need_weight)
-                               ao2_unlock(queues);
                        goto out;
                }
                if (!datastore) {
@@ -4556,8 +4570,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                                ao2_ref(cur, -1);
                                ao2_unlock(qe->parent);
                                ao2_iterator_destroy(&memi);
-                               if (need_weight)
-                                       ao2_unlock(queues);
                                callattempt_free(tmp);
                                goto out;
                        }
@@ -4566,8 +4578,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                                ao2_ref(cur, -1);
                                ao2_unlock(&qe->parent);
                                ao2_iterator_destroy(&memi);
-                               if (need_weight)
-                                       ao2_unlock(queues);
                                callattempt_free(tmp);
                                goto out;
                        }
@@ -4604,8 +4614,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                                ao2_ref(cur, -1);
                                ao2_unlock(qe->parent);
                                ao2_iterator_destroy(&memi);
-                               if (need_weight)
-                                       ao2_unlock(queues);
                                callattempt_free(tmp);
                                goto out;
                        }
@@ -4668,8 +4676,6 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
        ++qe->pending;
        ao2_unlock(qe->parent);
        ring_one(qe, outgoing, &numbusies);
-       if (need_weight)
-               ao2_unlock(queues);
        lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed, update_connectedline);
        /* The ast_channel_datastore_remove() function could fail here if the
         * datastore was moved to another channel during a masquerade. If this is
@@ -4702,7 +4708,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                        res = digit;
                }
                if (res == -1)
-                       ast_debug(1, "%s: Nobody answered.\n", qe->chan->name);
+                       ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan));
                if (ast_cdr_isset_unanswered()) {
                        /* channel contains the name of one of the outgoing channels
                           in its CDR; zero out this CDR to avoid a dual-posting */
@@ -4769,7 +4775,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                        res2 |= ast_autoservice_stop(qe->chan);
                        if (ast_check_hangup(peer)) {
                                /* Agent must have hung up */
-                               ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", peer->name);
+                               ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", ast_channel_name(peer));
                                ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "AGENTDUMP", "%s", "");
                                if (qe->parent->eventwhencalled)
                                        manager_event(EVENT_FLAG_AGENT, "AgentDump",
@@ -4779,14 +4785,14 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                                                        "Member: %s\r\n"
                                                        "MemberName: %s\r\n"
                                                        "%s",
-                                                       queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
+                                                       queuename, qe->chan->uniqueid, ast_channel_name(peer), member->interface, member->membername,
                                                        qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
                                ast_hangup(peer);
                                ao2_ref(member, -1);
                                goto out;
                        } else if (res2) {
                                /* Caller must have hung up just before being connected*/
-                               ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", peer->name);
+                               ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", ast_channel_name(peer));
                                ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
                                record_abandoned(qe);
                                ast_hangup(peer);
@@ -4801,13 +4807,13 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                        ast_moh_stop(qe->chan);
                /* If appropriate, log that we have a destination channel */
                if (qe->chan->cdr) {
-                       ast_cdr_setdestchan(qe->chan->cdr, peer->name);
+                       ast_cdr_setdestchan(qe->chan->cdr, ast_channel_name(peer));
                }
                /* Make sure channels are compatible */
                res = ast_channel_make_compatible(qe->chan, peer);
                if (res < 0) {
                        ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "SYSCOMPAT", "%s", "");
-                       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
+                       ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(qe->chan), ast_channel_name(peer));
                        record_abandoned(qe);
                        ast_cdr_failed(qe->chan->cdr);
                        ast_hangup(peer);
@@ -5095,8 +5101,34 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                qe->handled++;
                ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld", (long) time(NULL) - qe->start, peer->uniqueid,
                                                                                                        (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
-               if (update_cdr && qe->chan->cdr) 
-                       ast_copy_string(qe->chan->cdr->dstchannel, member->membername, sizeof(qe->chan->cdr->dstchannel));
+
+               if (qe->chan->cdr) {
+                       struct ast_cdr *cdr;
+                       struct ast_cdr *newcdr;
+
+                       /* Only work with the last CDR in the stack*/
+                       cdr = qe->chan->cdr;
+                       while (cdr->next) {
+                               cdr = cdr->next;
+                       }
+
+                       /* If this CDR is not related to us add new one*/
+                       if ((strcasecmp(cdr->uniqueid, qe->chan->uniqueid)) &&
+                           (strcasecmp(cdr->linkedid, qe->chan->uniqueid)) &&
+                           (newcdr = ast_cdr_dup(cdr))) {
+                               ast_channel_lock(qe->chan);
+                               ast_cdr_init(newcdr, qe->chan);
+                               ast_cdr_reset(newcdr, 0);
+                               cdr = ast_cdr_append(cdr, newcdr);
+                               cdr = cdr->next;
+                               ast_channel_unlock(qe->chan);
+                       }
+
+                       if (update_cdr) {
+                               ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
+                       }
+               }
+
                if (qe->parent->eventwhencalled)
                        manager_event(EVENT_FLAG_AGENT, "AgentConnect",
                                        "Queue: %s\r\n"
@@ -5108,7 +5140,7 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
                                        "BridgedChannel: %s\r\n"
                                        "Ringtime: %ld\r\n"
                                        "%s",
-                                       queuename, qe->chan->uniqueid, peer->name, member->interface, member->membername,
+                                       queuename, qe->chan->uniqueid, ast_channel_name(peer), member->interface, member->membername,
                                        (long) time(NULL) - qe->start, peer->uniqueid, (long)(orig - to > 0 ? (orig - to) / 1000 : 0),
                                        qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
                ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
@@ -5196,9 +5228,9 @@ static struct member *interface_exists(struct call_queue *q, const char *interfa
        struct member *mem;
        struct ao2_iterator mem_iter;
 
-       if (!q)
+       if (!q) {
                return NULL;
-
+       }
        mem_iter = ao2_iterator_init(q->members, 0);
        while ((mem = ao2_iterator_next(&mem_iter))) {
                if (!strcasecmp(interface, mem->interface)) {
@@ -5267,14 +5299,13 @@ static void dump_queue_members(struct call_queue *pm_queue)
 static int remove_from_queue(const char *queuename, const char *interface)
 {
        struct call_queue *q, tmpq = {
-               .name = queuename,      
+               .name = queuename,
        };
        struct member *mem, tmpmem;
        int res = RES_NOSUCHQUEUE;
 
        ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
        if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) {
-               ao2_lock(queues);
                ao2_lock(q);
                if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
                        /* XXX future changes should beware of this assumption!! */
@@ -5285,10 +5316,8 @@ static int remove_from_queue(const char *queuename, const char *interface)
                                ao2_ref(mem, -1);
                                ao2_unlock(q);
                                queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
-                               ao2_unlock(queues);
                                return RES_NOT_DYNAMIC;
                        }
-                       q->membercount--;
                        manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
                                "Queue: %s\r\n"
                                "Location: %s\r\n"
@@ -5305,7 +5334,6 @@ static int remove_from_queue(const char *queuename, const char *interface)
                        res = RES_EXISTS;
                }
                ao2_unlock(q);
-               ao2_unlock(queues);
                queue_t_unref(q, "Expiring temporary reference");
        }
 
@@ -5327,17 +5355,15 @@ static int add_to_queue(const char *queuename, const char *interface, const char
 
        /*! \note Ensure the appropriate realtime queue is loaded.  Note that this
         * short-circuits if the queue is already in memory. */
-       if (!(q = load_realtime_queue(queuename)))
+       if (!(q = find_load_queue_rt_friendly(queuename))) {
                return res;
-
-       ao2_lock(queues);
+       }
 
        ao2_lock(q);
        if ((old_member = interface_exists(q, interface)) == NULL) {
                if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) {
                        new_member->dynamic = 1;
                        ao2_link(q->members, new_member);
-                       q->membercount++;
                        manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
                                "Queue: %s\r\n"
                                "Location: %s\r\n"
@@ -5353,13 +5379,14 @@ static int add_to_queue(const char *queuename, const char *interface, const char
                                "dynamic",
                                new_member->penalty, new_member->calls, (int) new_member->lastcall,
                                new_member->status, new_member->paused);
-                       
+
                        ao2_ref(new_member, -1);
                        new_member = NULL;
 
-                       if (dump)
+                       if (dump) {
                                dump_queue_members(q);
-                       
+                       }
+
                        res = RES_OKAY;
                } else {
                        res = RES_OUTOFMEMORY;
@@ -5369,7 +5396,6 @@ static int add_to_queue(const char *queuename, const char *interface, const char
                res = RES_EXISTS;
        }
        ao2_unlock(q);
-       ao2_unlock(queues);
        queue_t_unref(q, "Expiring temporary reference");
 
        return res;
@@ -5401,14 +5427,14 @@ static int set_member_paused(const char *queuename, const char *interface, const
                                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);
                                        ao2_unlock(q);
                                        queue_t_unref(q, "Done with iterator");
                                        continue;
-                               }       
+                               }
                                found++;
                                mem->paused = paused;
 
@@ -5416,7 +5442,7 @@ static int set_member_paused(const char *queuename, const char *interface, const
                                        dump_queue_members(q);
 
                                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"
@@ -5436,13 +5462,13 @@ static int set_member_paused(const char *queuename, const char *interface, const
                                ao2_ref(mem, -1);
                        }
                }
-               
+
                if (!ast_strlen_zero(queuename) && !strcasecmp(queuename, q->name)) {
                        ao2_unlock(q);
                        queue_t_unref(q, "Done with iterator");
                        break;
                }
-               
+
                ao2_unlock(q);
                queue_t_unref(q, "Done with iterator");
        }
@@ -5451,63 +5477,113 @@ static int set_member_paused(const char *queuename, const char *interface, const
        return found ? RESULT_SUCCESS : RESULT_FAILURE;
 }
 
-/* \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues. */
+/*!
+ * \internal
+ * \brief helper function for set_member_penalty - given a queue, sets all member penalties with the interface
+ * \param[in] q queue which is having its member's penalty changed - must be unlocked prior to calling
+ * \param[in] interface String of interface used to search for queue members being changed
+ * \param[in] penalty Value penalty is being changed to for the member.
+ * \retval 0 if the there is no member with interface belonging to q and no change is made
+ * \retval 1 if the there is a member with interface belonging to q and changes are made
+ */
+static int set_member_penalty_help_members(struct call_queue *q, const char *interface, int penalty)
+{
+       struct member *mem;
+       int foundinterface = 0;
+       char rtpenalty[80];
+
+       ao2_lock(q);
+       if ((mem = interface_exists(q, interface))) {
+               foundinterface++;
+               if (!mem->realtime) {
+                       mem->penalty = penalty;
+               } else {
+                       sprintf(rtpenalty, "%i", penalty);
+                       update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
+               }
+               ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
+               manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
+                       "Queue: %s\r\n"
+                       "Location: %s\r\n"
+                       "Penalty: %d\r\n",
+                       q->name, mem->interface, penalty);
+               ao2_ref(mem, -1);
+       }
+       ao2_unlock(q);
+
+       return foundinterface;
+}
+
+/*!
+ * \internal
+ * \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
+ * \param[in] queuename If specified, only act on a member if it belongs to this queue
+ * \param[in] interface Interface of queue member(s) having priority set.
+ * \param[in] penalty Value penalty is being changed to for each member
+ */
 static int set_member_penalty(const char *queuename, const char *interface, int penalty)
 {
        int foundinterface = 0, foundqueue = 0;
        struct call_queue *q;
-       struct member *mem;
-       char rtpenalty[80];
+       struct ast_config *queue_config = NULL;
+       struct ao2_iterator queue_iter;
 
        if (penalty < 0 && !negative_penalty_invalid) {
                ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
                return RESULT_FAILURE;
        }
 
-       if ((q = load_realtime_queue(queuename))) {
-               foundqueue++;
-               ao2_lock(q);
-               if ((mem = interface_exists(q, interface))) {
-                       foundinterface++;
-                       if (!mem->realtime) {
-                               mem->penalty = penalty;
-                       } else {
-                               sprintf(rtpenalty,"%i", penalty);
-                               update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
+       if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
+               if (ast_check_realtime("queues")) {
+                       char *queuename;
+                       queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
+                       if (queue_config) {
+                               for (queuename = ast_category_browse(queue_config, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(queue_config, queuename)) {
+                                       if ((q = find_load_queue_rt_friendly(queuename))) {
+                                               foundqueue++;
+                                               foundinterface += set_member_penalty_help_members(q, interface, penalty);
+                                       }
+                               }
                        }
-                       ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
-                       manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
-                               "Queue: %s\r\n"
-                               "Location: %s\r\n"
-                               "Penalty: %d\r\n",
-                               q->name, mem->interface, penalty);
-                       ao2_ref(mem, -1);
                }
-               ao2_unlock(q);
+
+               /* After hitting realtime queues, go back and get the regular ones. */
+               queue_iter = ao2_iterator_init(queues, 0);
+
+               while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
+                       foundqueue++;
+                       foundinterface += set_member_penalty_help_members(q, interface, penalty);
+               }
+
+       } else { /* We actually have a queuename, so we can just act on the single queue. */
+               if ((q = find_load_queue_rt_friendly(queuename))) {
+                       foundqueue++;
+                       foundinterface += set_member_penalty_help_members(q, interface, penalty);
+               }
        }
 
        if (foundinterface) {
                return RESULT_SUCCESS;
        } else if (!foundqueue) {
-               ast_log (LOG_ERROR, "Invalid queuename\n"); 
+               ast_log (LOG_ERROR, "Invalid queuename\n");
        } else {
                ast_log (LOG_ERROR, "Invalid interface\n");
-       }       
+       }
 
        return RESULT_FAILURE;
 }
 
-/* \brief Gets members penalty. 
- * \return Return the members penalty or RESULT_FAILURE on error. 
+/* \brief Gets members penalty.
+ * \return Return the members penalty or RESULT_FAILURE on error.
 */
 static int get_member_penalty(char *queuename, char *interface)
 {
        int foundqueue = 0, penalty;
        struct call_queue *q, tmpq = {
-               .name = queuename,      
+               .name = queuename,
        };
        struct member *mem;
-       
+
        if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Search for queue"))) {
                foundqueue = 1;
                ao2_lock(q);
@@ -5523,10 +5599,11 @@ static int get_member_penalty(char *queuename, char *interface)
        }
 
        /* some useful debuging */
-       if (foundqueue) 
+       if (foundqueue) {
                ast_log (LOG_ERROR, "Invalid queuename\n");
-       else 
+       } else {
                ast_log (LOG_ERROR, "Invalid interface\n");
+       }
 
        return RESULT_FAILURE;
 }
@@ -5549,8 +5626,6 @@ static void reload_queue_members(void)
        struct call_queue *cur_queue;
        char queue_data[PM_MAX_LEN];
 
-       ao2_lock(queues);
-
        /* 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) {
@@ -5562,10 +5637,11 @@ static void reload_queue_members(void)
                                .name = queue_name,
                        };
                        cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members");
-               }       
+               }
 
-               if (!cur_queue)
-                       cur_queue = load_realtime_queue(queue_name);
+               if (!cur_queue) {
+                       cur_queue = find_load_queue_rt_friendly(queue_name);
+               }
 
                if (!cur_queue) {
                        /* If the queue no longer exists, remove it from the
@@ -5573,7 +5649,7 @@ static void reload_queue_members(void)
                        ast_log(LOG_WARNING, "Error loading persistent queue: '%s': it does not exist\n", queue_name);
                        ast_db_del(pm_family, queue_name);
                        continue;
-               } 
+               }
 
                if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN)) {
                        queue_t_unref(cur_queue, "Expire reload reference");
@@ -5621,7 +5697,6 @@ static void reload_queue_members(void)
                queue_t_unref(cur_queue, "Expire reload reference");
        }
 
-       ao2_unlock(queues);
        if (db_tree) {
                ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
                ast_db_freetree(db_tree);
@@ -5724,7 +5799,7 @@ static int rqm_exec(struct ast_channel *chan, const char *data)
        AST_STANDARD_APP_ARGS(args, parse);
 
        if (ast_strlen_zero(args.interface)) {
-               args.interface = ast_strdupa(chan->name);
+               args.interface = ast_strdupa(ast_channel_name(chan));
                temppos = strrchr(args.interface, '-');
                if (temppos)
                        *temppos = '\0';
@@ -5738,7 +5813,7 @@ static int rqm_exec(struct ast_channel *chan, const char *data)
 
        switch (remove_from_queue(args.queuename, args.interface)) {
        case RES_OKAY:
-               if (!mem || ast_strlen_zero(mem->membername) || !log_membername_as_agent) {
+               if (!mem || ast_strlen_zero(mem->membername)) {
                        ast_queue_log(args.queuename, chan->uniqueid, args.interface, "REMOVEMEMBER", "%s", "");
                } else {
                        ast_queue_log(args.queuename, chan->uniqueid, mem->membername, "REMOVEMEMBER", "%s", "");
@@ -5764,6 +5839,10 @@ static int rqm_exec(struct ast_channel *chan, const char *data)
                break;
        }
 
+       if (mem) {
+               ao2_ref(mem, -1);
+       }
+
        return res;
 }
 
@@ -5792,7 +5871,7 @@ static int aqm_exec(struct ast_channel *chan, const char *data)
        AST_STANDARD_APP_ARGS(args, parse);
 
        if (ast_strlen_zero(args.interface)) {
-               args.interface = ast_strdupa(chan->name);
+               args.interface = ast_strdupa(ast_channel_name(chan));
                temppos = strrchr(args.interface, '-');
                if (temppos)
                        *temppos = '\0';
@@ -5963,10 +6042,10 @@ static int queue_exec(struct ast_channel *chan, const char *data)
        user_priority = pbx_builtin_getvar_helper(chan, "QUEUE_PRIO");
        if (user_priority) {
                if (sscanf(user_priority, "%30d", &prio) == 1) {
-                       ast_debug(1, "%s: Got priority %d from ${QUEUE_PRIO}.\n", chan->name, prio);
+                       ast_debug(1, "%s: Got priority %d from ${QUEUE_PRIO}.\n", ast_channel_name(chan), prio);
                } else {
                        ast_log(LOG_WARNING, "${QUEUE_PRIO}: Invalid value (%s), channel %s.\n",
-                               user_priority, chan->name);
+                               user_priority, ast_channel_name(chan));
                        prio = 0;
                }
        } else {
@@ -5978,10 +6057,10 @@ static int queue_exec(struct ast_channel *chan, const char *data)
 
        if ((max_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MAX_PENALTY"))) {
                if (sscanf(max_penalty_str, "%30d", &max_penalty) == 1) {
-                       ast_debug(1, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", chan->name, max_penalty);
+                       ast_debug(1, "%s: Got max penalty %d from ${QUEUE_MAX_PENALTY}.\n", ast_channel_name(chan), max_penalty);
                } else {
                        ast_log(LOG_WARNING, "${QUEUE_MAX_PENALTY}: Invalid value (%s), channel %s.\n",
-                               max_penalty_str, chan->name);
+                               max_penalty_str, ast_channel_name(chan));
                        max_penalty = 0;
                }
        } else {
@@ -5990,10 +6069,10 @@ static int queue_exec(struct ast_channel *chan, const char *data)
 
        if ((min_penalty_str = pbx_builtin_getvar_helper(chan, "QUEUE_MIN_PENALTY"))) {
                if (sscanf(min_penalty_str, "%30d", &min_penalty) == 1) {
-                       ast_debug(1, "%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", chan->name, min_penalty);
+                       ast_debug(1, "%s: Got min penalty %d from ${QUEUE_MIN_PENALTY}.\n", ast_channel_name(chan), min_penalty);
                } else {
                        ast_log(LOG_WARNING, "${QUEUE_MIN_PENALTY}: Invalid value (%s), channel %s.\n",
-                               min_penalty_str, chan->name);
+                               min_penalty_str, ast_channel_name(chan));
                        min_penalty = 0;
                }
        } else {
@@ -6118,7 +6197,7 @@ check_turns:
                }
 
                /* exit after 'timeout' cycle if 'n' option enabled */
-               if (noption && tries >= qe.parent->membercount) {
+               if (noption && tries >= ao2_container_count(qe.parent->members)) {
                        ast_verb(3, "Exiting on time-out cycle\n");
                        ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
                        record_abandoned(&qe);
@@ -6149,7 +6228,7 @@ check_turns:
                 * of the queue, go and check for our turn again.
                 */
                if (!is_our_turn(&qe)) {
-                       ast_debug(1, "Darn priorities, going back in queue (%s)!\n", qe.chan->name);
+                       ast_debug(1, "Darn priorities, going back in queue (%s)!\n", ast_channel_name(qe.chan));
                        goto check_turns;
                }
        }
@@ -6209,7 +6288,7 @@ static int queue_function_var(struct ast_channel *chan, const char *cmd, char *d
 {
        int res = -1;
        struct call_queue *q, tmpq = {
-               .name = data,   
+               .name = data,
        };
 
        char interfacevar[256] = "";
@@ -6262,7 +6341,7 @@ static int queue_function_exists(struct ast_channel *chan, const char *cmd, char
                ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
                return -1;
        }
-       q = load_realtime_queue(data);
+       q = find_load_queue_rt_friendly(data);
        snprintf(buf, len, "%d", q != NULL? 1 : 0);
        if (q) {
                queue_t_unref(q, "Done with temporary reference in QUEUE_EXISTS()");
@@ -6293,13 +6372,18 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
        buf[0] = '\0';
 
        if (ast_strlen_zero(data)) {
-               ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
+               ast_log(LOG_ERROR, "Missing required argument. %s(<queuename>,<option>[<interface>])\n", cmd);
                return -1;
        }
 
        AST_STANDARD_APP_ARGS(args, data);
 
-       if ((q = load_realtime_queue(args.queuename))) {
+       if (args.argc < 2) {
+               ast_log(LOG_ERROR, "Missing required argument. %s(<queuename>,<option>[<interface>])\n", cmd);
+               return -1;
+       }
+
+       if ((q = find_load_queue_rt_friendly(args.queuename))) {
                ao2_lock(q);
                if (!strcasecmp(args.option, "logged")) {
                        mem_iter = ao2_iterator_init(q->members, 0);
@@ -6335,16 +6419,22 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
                        }
                        ao2_iterator_destroy(&mem_iter);
                } else if (!strcasecmp(args.option, "count") || ast_strlen_zero(args.option)) {
-                       count = q->membercount;
+                       count = ao2_container_count(q->members);
                } else if (!strcasecmp(args.option, "penalty") && !ast_strlen_zero(args.interface) &&
                           ((m = interface_exists(q, args.interface)))) {
                        count = m->penalty;
+                       ao2_ref(m, -1);
                } else if (!strcasecmp(args.option, "paused") && !ast_strlen_zero(args.interface) &&
                           ((m = interface_exists(q, args.interface)))) {
                        count = m->paused;
+                       ao2_ref(m, -1);
                } else if (!strcasecmp(args.option, "ignorebusy") && !ast_strlen_zero(args.interface) &&
                           ((m = interface_exists(q, args.interface)))) {
                        count = m->ignorebusy;
+                       ao2_ref(m, -1);
+               } else {
+                       ast_log(LOG_ERROR, "Unknown option %s provided to %s, valid values are: "
+                               "logged, free, ready, count, penalty, paused, ignorebusy\n", args.option, cmd);
                }
                ao2_unlock(q);
                queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
@@ -6396,7 +6486,7 @@ static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, c
                        ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
                        return -1;
                }
-       } else if ((q = load_realtime_queue(args.queuename))) {
+       } else if ((q = find_load_queue_rt_friendly(args.queuename))) {
                ao2_lock(q);
                if ((m = interface_exists(q, args.interface))) {
                        sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
@@ -6414,13 +6504,20 @@ static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, c
                                }
                        } else {
                                ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ignorebusy are valid\n");
+                               ao2_ref(m, -1);
+                               ao2_unlock(q);
+                               ao2_ref(q, -1);
                                return -1;
                        }
+                       ao2_ref(m, -1);
                } else {
-                       ast_log(LOG_ERROR, "Invalid interface or queue\n");
+                       ao2_unlock(q);
+                       ao2_ref(q, -1);
+                       ast_log(LOG_ERROR, "Invalid interface for queue\n");
                        return -1;
                }
                ao2_unlock(q);
+               ao2_ref(q, -1);
         } else {
                ast_log(LOG_ERROR, "Invalid queue\n");
                return -1;
@@ -6451,7 +6548,7 @@ static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, cha
                return -1;
        }
        
-       if ((q = load_realtime_queue(data))) {
+       if ((q = find_load_queue_rt_friendly(data))) {
                ao2_lock(q);
                mem_iter = ao2_iterator_init(q->members, 0);
                while ((m = ao2_iterator_next(&mem_iter))) {
@@ -6464,8 +6561,9 @@ static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, cha
                ao2_iterator_destroy(&mem_iter);
                ao2_unlock(q);
                queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER_COUNT");
-       } else
+       } else {
                ast_log(LOG_WARNING, "queue %s was not found\n", data);
+       }
 
        snprintf(buf, len, "%d", count);
 
@@ -6477,12 +6575,12 @@ static int queue_function_queuewaitingcount(struct ast_channel *chan, const char
 {
        int count = 0;
        struct call_queue *q, tmpq = {
-               .name = data,   
+               .name = data,
        };
        struct ast_variable *var = NULL;
 
        buf[0] = '\0';
-       
+
        if (ast_strlen_zero(data)) {
                ast_log(LOG_ERROR, "QUEUE_WAITING_COUNT requires an argument: queuename\n");
                return -1;
@@ -6495,7 +6593,7 @@ static int queue_function_queuewaitingcount(struct ast_channel *chan, const char
                queue_t_unref(q, "Done with reference in QUEUE_WAITING_COUNT()");
        } else if ((var = ast_load_realtime("queues", "name", data, SENTINEL))) {
                /* if the queue is realtime but was not found in memory, this
-                * means that the queue had been deleted from memory since it was 
+                * means that the queue had been deleted from memory since it was
                 * "dead." This means it has a 0 waiting count
                 */
                count = 0;
@@ -6512,7 +6610,7 @@ static int queue_function_queuewaitingcount(struct ast_channel *chan, const char
 static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
        struct call_queue *q, tmpq = {
-               .name = data,   
+               .name = data,
        };
        struct member *m;
 
@@ -6725,25 +6823,34 @@ static void queue_set_global_params(struct ast_config *cfg)
                queue_persistent_members = ast_true(general_val);
        }
        autofill_default = 0;
-       if ((general_val = ast_variable_retrieve(cfg, "general", "autofill")))
+       if ((general_val = ast_variable_retrieve(cfg, "general", "autofill"))) {
                autofill_default = ast_true(general_val);
+       }
        montype_default = 0;
        if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) {
                if (!strcasecmp(general_val, "mixmonitor"))
                        montype_default = 1;
        }
        update_cdr = 0;
-       if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr")))
+       if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr"))) {
                update_cdr = ast_true(general_val);
+       }
        shared_lastcall = 0;
-       if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall")))
+       if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall"))) {
                shared_lastcall = ast_true(general_val);
+       }
        negative_penalty_invalid = 0;
-       if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid")))
+       if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid"))) {
                negative_penalty_invalid = ast_true(general_val);
+       }
        log_membername_as_agent = 0;
-       if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent")))
+       if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent"))) {
                log_membername_as_agent = ast_true(general_val);
+       }
+       check_state_unknown = 0;
+       if ((general_val = ast_variable_retrieve(cfg, "general", "check_state_unknown"))) {
+               check_state_unknown = ast_true(general_val);
+       }
 }
 
 /*! \brief reload information pertaining to a single member
@@ -6815,8 +6922,6 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
 
        if (cur) {
                ao2_ref(cur, -1);
-       } else {
-               q->membercount++;
        }
 }
 
@@ -6832,19 +6937,11 @@ static int mark_member_dead(void *obj, void *arg, int flags)
 static int kill_dead_members(void *obj, void *arg, int flags)
 {
        struct member *member = obj;
-       struct call_queue *q = arg;
 
        if (!member->delme) {
-               if (member->dynamic) {
-                       /* dynamic members were not counted toward the member count
-                        * when reloading members from queues.conf, so we do that here
-                        */
-                       q->membercount++;
-               }
                member->status = get_queue_member_status(member);
                return 0;
        } else {
-               q->membercount--;
                return CMP_MATCH;
        }
 }
@@ -6923,7 +7020,6 @@ static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask,
                init_queue(q);
        }
        if (member_reload) {
-               q->membercount = 0;
                ao2_callback(q->members, OBJ_NODATA, mark_member_dead, NULL);
        }
        for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
@@ -7009,12 +7105,12 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena
 
        /* We've made it here, so it looks like we're doing operations on all queues. */
        ao2_lock(queues);
-       
+
        /* Mark all queues as dead for the moment if we're reloading queues.
         * For clarity, we could just be reloading members, in which case we don't want to mess
         * with the other queue parameters at all*/
        if (queue_reload) {
-               ao2_callback(queues, OBJ_NODATA, mark_dead_and_unfound, (char *) queuename);
+               ao2_callback(queues, OBJ_NODATA | OBJ_NOLOCK, mark_dead_and_unfound, (char *) queuename);
        }
 
        /* Chug through config file */
@@ -7031,17 +7127,17 @@ static int reload_queues(int reload, struct ast_flags *mask, const char *queuena
        ast_config_destroy(cfg);
        /* Unref all the dead queues if we were reloading queues */
        if (queue_reload) {
-               ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_queues, (char *) queuename);
+               ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NOLOCK, kill_dead_queues, (char *) queuename);
        }
        ao2_unlock(queues);
        return 0;
 }
-  
+
 /*! \brief Facilitates resetting statistics for a queue
  *
  * This function actually does not reset any statistics, but
  * rather finds a call_queue struct which corresponds to the
- * passed-in queue name and passes that structure to the 
+ * passed-in queue name and passes that structure to the
  * clear_queue function. If no queuename is passed in, then
  * all queues will have their statistics reset.
  *
@@ -7118,11 +7214,12 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
        struct ao2_iterator queue_iter;
        struct ao2_iterator mem_iter;
 
-       if (argc != 2 && argc != 3)
+       if (argc != 2 && argc != 3) {
                return CLI_SHOWUSAGE;
+       }
 
        if (argc == 3)  { /* specific queue */
-               if ((q = load_realtime_queue(argv[2]))) {
+               if ((q = find_load_queue_rt_friendly(argv[2]))) {
                        queue_t_unref(q, "Done with temporary pointer");
                }
        } else if (ast_check_realtime("queues")) {
@@ -7133,7 +7230,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
                char *queuename;
                if (cfg) {
                        for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
-                               if ((q = load_realtime_queue(queuename))) {
+                               if ((q = find_load_queue_rt_friendly(queuename))) {
                                        queue_t_unref(q, "Done with temporary pointer");
                                }
                        }
@@ -7153,7 +7250,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
                 * been deleted from the in-core container
                 */
                if (q->realtime) {
-                       realtime_queue = load_realtime_queue(q->name);
+                       realtime_queue = find_load_queue_rt_friendly(q->name);
                        if (!realtime_queue) {
                                ao2_unlock(q);
                                queue_t_unref(q, "Done with iterator");
@@ -7181,9 +7278,9 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
                        int2strat(q->strategy), q->holdtime, q->talktime, q->weight,
                        q->callscompleted, q->callsabandoned,sl,q->servicelevel);
                do_print(s, fd, ast_str_buffer(out));
-               if (!ao2_container_count(q->members))
+               if (!ao2_container_count(q->members)) {
                        do_print(s, fd, "   No Members");
-               else {
+               } else {
                        struct member *mem;
 
                        do_print(s, fd, "   Members: ");
@@ -7197,33 +7294,35 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
                                        }
                                        ast_str_append(&out, 0, ")");
                                }
-                               if (mem->penalty)
+                               if (mem->penalty) {
                                        ast_str_append(&out, 0, " with penalty %d", mem->penalty);
+                               }
                                ast_str_append(&out, 0, "%s%s%s (%s)",
                                        mem->dynamic ? " (dynamic)" : "",
                                        mem->realtime ? " (realtime)" : "",
                                        mem->paused ? " (paused)" : "",
                                        ast_devstate2str(mem->status));
-                               if (mem->calls)
+                               if (mem->calls) {
                                        ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
                                                mem->calls, (long) (time(NULL) - mem->lastcall));
-                               else
+                               } else {
                                        ast_str_append(&out, 0, " has taken no calls yet");
+                               }
                                do_print(s, fd, ast_str_buffer(out));
                                ao2_ref(mem, -1);
                        }
                        ao2_iterator_destroy(&mem_iter);
                }
-               if (!q->head)
+               if (!q->head) {
                        do_print(s, fd, "   No Callers");
-               else {
+               } else {
                        struct queue_ent *qe;
                        int pos = 1;
 
                        do_print(s, fd, "   Callers: ");
                        for (qe = q->head; qe; qe = qe->next) {
                                ast_str_set(&out, 0, "      %d. %s (wait: %ld:%2.2ld, prio: %d)",
-                                       pos++, qe->chan->name, (long) (now - qe->start) / 60,
+                                       pos++, ast_channel_name(qe->chan), (long) (now - qe->start) / 60,
                                        (long) (now - qe->start) % 60, qe->prio);
                                do_print(s, fd, ast_str_buffer(out));
                        }
@@ -7235,10 +7334,11 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
        ao2_iterator_destroy(&queue_iter);
        ao2_unlock(queues);
        if (!found) {
-               if (argc == 3)
+               if (argc == 3) {
                        ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
-               else
+               } else {
                        ast_str_set(&out, 0, "No queues.");
+               }
                do_print(s, fd, ast_str_buffer(out));
        }
        return CLI_SUCCESS;
@@ -7493,7 +7593,7 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
                                        "Wait: %ld\r\n"
                                        "%s"
                                        "\r\n",
-                                       q->name, pos++, qe->chan->name, qe->chan->uniqueid,
+                                       q->name, pos++, ast_channel_name(qe->chan), qe->chan->uniqueid,
                                        S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),
                                        S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
                                        S_COR(qe->chan->connected.id.number.valid, qe->chan->connected.id.number.str, "unknown"),
@@ -7549,9 +7649,9 @@ static int manager_add_queue_member(struct mansession *s, const struct message *
        switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
        case RES_OKAY:
                if (ast_strlen_zero(membername) || !log_membername_as_agent) {
-                       ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
+                       ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
                } else {
-                       ast_queue_log(queuename, "MANAGER", membername, "ADDMEMBER", "%s", "");
+                       ast_queue_log(queuename, "MANAGER", membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
                }
                astman_send_ack(s, m, "Added interface to queue");
                break;
@@ -7588,7 +7688,7 @@ static int manager_remove_queue_member(struct mansession *s, const struct messag
 
        switch (remove_from_queue(queuename, interface)) {
        case RES_OKAY:
-               if (!mem || ast_strlen_zero(mem->membername) || !log_membername_as_agent) {
+               if (!mem || ast_strlen_zero(mem->membername)) {
                        ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
                } else {
                        ast_queue_log(queuename, "MANAGER", mem->membername, "REMOVEMEMBER", "%s", "");
@@ -7609,6 +7709,10 @@ static int manager_remove_queue_member(struct mansession *s, const struct messag
                break;
        }
 
+       if (mem) {
+               ao2_ref(mem, -1);
+       }
+
        return 0;
 }
 
@@ -7908,17 +8012,19 @@ static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct
        queuename = a->argv[5];
        interface = a->argv[3];
 
-       if (log_membername_as_agent) {
-               mem = find_member_by_queuename_and_interface(queuename, interface);
-       }
-
        switch (remove_from_queue(queuename, interface)) {
        case RES_OKAY:
-               if (!mem || ast_strlen_zero(mem->membername) || !log_membername_as_agent) {
+               if (log_membername_as_agent) {
+                       mem = find_member_by_queuename_and_interface(queuename, interface);
+               }
+               if (!mem || ast_strlen_zero(mem->membername)) {
                        ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
                } else {
                        ast_queue_log(queuename, "CLI", mem->membername, "REMOVEMEMBER", "%s", "");
                }
+               if (mem) {
+                       ao2_ref(mem, -1);
+               }
                ast_cli(a->fd, "Removed interface %s from queue '%s'\n", interface, queuename);
                return CLI_SUCCESS;
        case RES_EXISTS:
@@ -8304,8 +8410,7 @@ static struct ast_cli_entry cli_queue[] = {
        MEMBER(call_queue, rrpos, AST_DATA_INTEGER)                     \
        MEMBER(call_queue, memberdelay, AST_DATA_INTEGER)               \
        MEMBER(call_queue, autofill, AST_DATA_INTEGER)                  \
-       MEMBER(call_queue, members, AST_DATA_CONTAINER)                 \
-       MEMBER(call_queue, membercount, AST_DATA_INTEGER)
+       MEMBER(call_queue, members, AST_DATA_CONTAINER)
 
 AST_DATA_STRUCTURE(call_queue, DATA_EXPORT_CALL_QUEUE);
 
@@ -8373,6 +8478,7 @@ static void queues_data_provider_get_helper(const struct ast_data_search *search
        ast_data_add_structure(call_queue, data_queue, queue);
 
        ast_data_add_str(data_queue, "strategy", int2strat(queue->strategy));
+       ast_data_add_int(data_queue, "membercount", ao2_container_count(queue->members));
 
        /* announce position */
        enum_node = ast_data_add_node(data_queue, "announceposition");
@@ -8474,7 +8580,7 @@ static int queues_data_provider_get(const struct ast_data_search *search,
                for (queuename = ast_category_browse(cfg, NULL);
                                !ast_strlen_zero(queuename);
                                queuename = ast_category_browse(cfg, queuename)) {
-                       if ((queue = load_realtime_queue(queuename))) {
+                       if ((queue = find_load_queue_rt_friendly(queuename))) {
                                queue_unref(queue);
                        }
                }
@@ -8486,7 +8592,7 @@ static int queues_data_provider_get(const struct ast_data_search *search,
        while ((queue = ao2_iterator_next(&i))) {
                ao2_lock(queue);
                if (queue->realtime) {
-                       queue_realtime = load_realtime_queue(queue->name);
+                       queue_realtime = find_load_queue_rt_friendly(queue->name);
                        if (!queue_realtime) {
                                ao2_unlock(queue);
                                queue_unref(queue);
@@ -8650,7 +8756,7 @@ static struct member *find_member_by_queuename_and_interface(const char *queuena
        struct member *mem = NULL;
        struct call_queue *q;
 
-       if ((q = load_realtime_queue(queuename))) {
+       if ((q = find_load_queue_rt_friendly(queuename))) {
                ao2_lock(q);
                mem = ao2_find(q->members, interface, OBJ_KEY);
                ao2_unlock(q);