Add 'loose' option to joinempty and leavewhenempty which is almost exactly like ...
authorJoshua Colp <jcolp@digium.com>
Mon, 13 Nov 2006 18:23:55 +0000 (18:23 +0000)
committerJoshua Colp <jcolp@digium.com>
Mon, 13 Nov 2006 18:23:55 +0000 (18:23 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@47567 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
apps/app_queue.c
configs/queues.conf.sample

diff --git a/CHANGES b/CHANGES
index 586555f..26ece87 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -59,3 +59,5 @@ Changes since Asterisk 1.4-beta was branched:
     setqueueentryvar options for each queue, see queues.conf.sample for details.
   * Brazilian Portuguese (pt-BR) in VM, and say.c was added via patch from cfassoni.
   * CID matching information is now shown when doing 'dialplan show'.
+  * app_queue now has a 'loose' option which is almost exactly like 'strict' except it
+     does not count paused queue members as unavailable.
index 77ab091..bdc5eef 100644 (file)
@@ -338,6 +338,7 @@ static AST_LIST_HEAD_STATIC(interfaces, member_interface);
 /* values used in multi-bit flags in call_queue */
 #define QUEUE_EMPTY_NORMAL 1
 #define QUEUE_EMPTY_STRICT 2
+#define QUEUE_EMPTY_LOOSE 3
 #define ANNOUNCEHOLDTIME_ALWAYS 1
 #define ANNOUNCEHOLDTIME_ONCE 2
 #define QUEUE_EVENT_VARIABLES 3
@@ -488,6 +489,7 @@ static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, st
 enum queue_member_status {
        QUEUE_NO_MEMBERS,
        QUEUE_NO_REACHABLE_MEMBERS,
+       QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS,
        QUEUE_NORMAL
 };
 
@@ -501,18 +503,22 @@ static enum queue_member_status get_member_status(struct call_queue *q, int max_
                if (max_penalty && (member->penalty > max_penalty))
                        continue;
 
-               if (member->paused) continue;
-
                switch (member->status) {
                case AST_DEVICE_INVALID:
                        /* nothing to do */
                        break;
                case AST_DEVICE_UNAVAILABLE:
-                       result = QUEUE_NO_REACHABLE_MEMBERS;
+                       if (result != QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS) 
+                               result = QUEUE_NO_REACHABLE_MEMBERS;
                        break;
                default:
-                       ast_mutex_unlock(&q->lock);
-                       return QUEUE_NORMAL;
+                       if (member->paused) {
+                               result = QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS;
+                       } else {
+                               ast_mutex_unlock(&q->lock);
+                               return QUEUE_NORMAL;
+                       }
+                       break;
                }
        }
        
@@ -903,14 +909,18 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
                        q->strategy = QUEUE_STRATEGY_RINGALL;
                }
        } else if (!strcasecmp(param, "joinempty")) {
-               if (!strcasecmp(val, "strict"))
+               if (!strcasecmp(val, "loose"))
+                       q->joinempty = QUEUE_EMPTY_LOOSE;
+               else if (!strcasecmp(val, "strict"))
                        q->joinempty = QUEUE_EMPTY_STRICT;
                else if (ast_true(val))
                        q->joinempty = QUEUE_EMPTY_NORMAL;
                else
                        q->joinempty = 0;
        } else if (!strcasecmp(param, "leavewhenempty")) {
-               if (!strcasecmp(val, "strict"))
+               if (!strcasecmp(val, "loose"))
+                       q->leavewhenempty = QUEUE_EMPTY_LOOSE;
+               else if (!strcasecmp(val, "strict"))
                        q->leavewhenempty = QUEUE_EMPTY_STRICT;
                else if (ast_true(val))
                        q->leavewhenempty = QUEUE_EMPTY_NORMAL;
@@ -1189,7 +1199,9 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
        stat = get_member_status(q, qe->max_penalty);
        if (!q->joinempty && (stat == QUEUE_NO_MEMBERS))
                *reason = QUEUE_JOINEMPTY;
-       else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
+       else if ((q->joinempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS))
+               *reason = QUEUE_JOINUNAVAIL;
+       else if ((q->joinempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS))
                *reason = QUEUE_JOINUNAVAIL;
        else if (q->maxlen && (q->count >= q->maxlen))
                *reason = QUEUE_FULL;
@@ -2207,7 +2219,13 @@ static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *r
                }
 
                /* leave the queue if no reachable agents, if enabled */
-               if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
+               if ((qe->parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
+                       *reason = QUEUE_LEAVEUNAVAIL;
+                       ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
+                       leave_queue(qe);
+                       break;
+               }
+               if ((qe->parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
                        *reason = QUEUE_LEAVEUNAVAIL;
                        ast_queue_log(qe->parent->name, qe->chan->uniqueid, "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
                        leave_queue(qe);
@@ -3532,7 +3550,13 @@ check_turns:
                                }
 
                                /* leave the queue if no reachable agents, if enabled */
-                               if ((qe.parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
+                               if ((qe.parent->leavewhenempty == QUEUE_EMPTY_STRICT) && (stat == QUEUE_NO_REACHABLE_MEMBERS || stat == QUEUE_NO_UNPAUSED_REACHABLE_MEMBERS)) {
+                                       record_abandoned(&qe);
+                                       reason = QUEUE_LEAVEUNAVAIL;
+                                       res = 0;
+                                       break;
+                               }
+                               if ((qe.parent->leavewhenempty == QUEUE_EMPTY_LOOSE) && (stat == QUEUE_NO_REACHABLE_MEMBERS)) {
                                        record_abandoned(&qe);
                                        reason = QUEUE_LEAVEUNAVAIL;
                                        res = 0;
index c9f3f96..a1238e5 100644 (file)
@@ -254,6 +254,8 @@ monitor-type = MixMonitor
 ; no     - callers cannot join a queue with no members
 ; strict - callers cannot join a queue with no members or only unavailable
 ;          members
+; loose  - same as strict, but paused queue members do not count as unavailable
+;          
 ;
 ; ----------------------- TYPE MIXMONITOR OPTIONS -----------------------------
 ;