[asterisk-dev] app_queue, ringinuse, joinempty combination problems

Wolfgang Pichler wpichler at yosd.at
Wed Jan 21 11:00:50 CST 2009


Mark Michelson schrieb:
> Wolfgang Pichler wrote:
>   
>> Hi all,
>>
>> i have a queue configured (realtime) with ringinuse=no and 
>> joinempty=strict    (running asterisk 1.4.21.1)
>>
>> What i wanted to achive with this is - when there are all queue members 
>> already on the phone - then don't join the queue (and this should work 
>> with this config options if i am not wrong)
>>
>> But calls will join the queue - regardless if there is a free member or not
>>
>> so i have taken a look at the code - function join_queue
>>
>> there you can read
>>
>>         /* This is our one */
>>         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 || stat == QUEUE_NO_MEMBERS))
>>                 *reason = QUEUE_JOINUNAVAIL;
>>         else if (q->maxlen && (q->count >= q->maxlen))
>>                 *reason = QUEUE_FULL;
>>         else {
>>
>>  - so when QUEUE_EMPTY_STRICT is set - and the get_member_status 
>> function does return QUEUE_NO_REACHABLE_MEMBERS or QUEUE_NO_MEMBERS then 
>> it will return with JOINUNAVAIL
>>
>> if i look at the get_member_status function - i can see the following
>>
>> static enum queue_member_status get_member_status(struct call_queue *q, 
>> int max_penalty)
>> {
>>         struct member *member;
>>         struct ao2_iterator mem_iter;
>>         enum queue_member_status result = QUEUE_NO_MEMBERS;
>>
>>         ast_mutex_lock(&q->lock);
>>         mem_iter = ao2_iterator_init(q->members, 0);
>>         while ((member = ao2_iterator_next(&mem_iter))) {
>>                 if (max_penalty && (member->penalty > max_penalty)) {
>>                         ao2_ref(member, -1);
>>                         continue;
>>                 }
>>
>>                 if (member->paused) {
>>                         ao2_ref(member, -1);
>>                         continue;
>>                 }
>>
>>                 switch (member->status) {
>>                 case AST_DEVICE_INVALID:
>>                         /* nothing to do */
>>                         ao2_ref(member, -1);
>>                         break;
>>                 case AST_DEVICE_UNAVAILABLE:
>>                         result = QUEUE_NO_REACHABLE_MEMBERS;
>>                         ao2_ref(member, -1);
>>                         break;
>>                 default:
>>                         ast_mutex_unlock(&q->lock);
>>                         ao2_ref(member, -1);
>>                         return QUEUE_NORMAL;
>>                 }
>>         }
>>
>>         ast_mutex_unlock(&q->lock);
>>         return result;
>> }
>>
>> it does handle corrent the min max penalty and the paused members. Also 
>> if a member is unavailable or invalid it does not count the member as 
>> available member - but it does ignore members which have an active call 
>> (and ringinuse=yes - so the member has to get considered as unavailable) !!
>>
>> For me this seems to be wrong - what are you thinking about this ?
>>
>> I think adding something like this in the while loop before the switch 
>> would make it handle it correct...
>>
>>         if (!q->ringinuse && (member->status != AST_DEVICE_NOT_INUSE) && 
>> (member->status != AST_DEVICE_UNKNOWN)) {
>>                         ao2_ref(member, -1);
>>                         continue;
>>         }
>>
>>
>> regards,
>> Wolfgang
>>
>>     
>
> Hi Wolfgang,
>
> I can see where you're coming from here, because the queues.conf.sample file 
> mentions that if all queue members are "unavailable" then the caller will not be 
> able to join the queue if joinempty=strict is set. The problem is that what 
> constitutes a member as "unavailable" is not well-defined in the queues.conf 
> file. This corresponds to the device state value AST_DEVICE_UNAVAILABLE. This 
> state is most typically used for Agent channels which are members of a queue but 
> not logged in. By having joinempty=strict, the setting pretty much means to only 
> allow a call to enter the queue if there is at least one unpaused member who is 
> logged into the queue and whose penalty is below the maximum.
>
> The ringinuse option really has no bearing on the joinempty option, and I would 
> find it a bit odd if it did since they govern two separate operations of queues. 
>   ringinuse only affects callers already in a queue, whereas joinempty is used 
> to determine who can enter a queue in the first place. If there were a joinempty 
> option which specified that "in use" members should be a reason not to join the 
> queue, then that would be the way to go with this.
>
> In Asterisk 1.4, there is no convenient way to do what you are trying to do, 
> aside from patching the code as you have done. However, in Asterisk trunk the 
> joinempty option has been modified immensely. In addition to allowing the old 
> yes, no, strict, and loose options, joinempty also allows for a 
> comma-separated-list of conditions to be used when testing for member 
> availability so that you have much more fine-grained control over when a caller 
> should or should not be allowed to join a queue. All of this information is 
> specified in detail in the queues.conf.sample file in trunk.
>
> Mark Michelson
>
> _______________________________________________
> --Bandwidth and Colocation Provided by http://www.api-digital.com--
>
> asterisk-dev mailing list
> To UNSUBSCRIBE or update options visit:
>    http://lists.digium.com/mailman/listinfo/asterisk-dev
>   
Hi,

thanks Mark for the detailed description why it is working now as it is 
working now...

Maybe the documentation should get updated to include this as hint,

Using trunk is not an option for me - because i have to implement it on 
my main production machine. I think i will check for available members 
before the call enters the queue to get around it.

Why wasn't this patch http://bugs.digium.com/view.php?id=10652 not 
included in the 1.4 release series - it is not really a new feature...

regards,
Wolfgang



More information about the asterisk-dev mailing list