Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 34874) +++ apps/app_queue.c (working copy) @@ -351,6 +351,8 @@ unsigned int strategy:3; unsigned int maskmemberstatus:1; unsigned int realtime:1; + unsigned int escalate_if_not_available:1; /*!< we escalate over penalty if current member is not available */ + unsigned int last_member_not_available:1; /*!< to determinate if we should add penalty priority or not */ int announcefrequency; /*!< How often to announce their position */ int periodicannouncefrequency; /*!< How often to play periodic announcement */ int roundingseconds; /*!< How many seconds do we round to? */ @@ -791,6 +793,8 @@ ast_copy_string(q->sound_reporthold, val, sizeof(q->sound_reporthold)); } else if (!strcasecmp(param, "announce-frequency")) { q->announcefrequency = atoi(val); + } else if (!strcasecmp(param, "escalate-if-not-available")) { + q->escalate_if_not_available = ast_true(val); } else if (!strcasecmp(param, "announce-round-seconds")) { q->roundingseconds = atoi(val); if (q->roundingseconds>60 || q->roundingseconds<0) { @@ -2149,13 +2153,14 @@ static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp) { - if (mem->penalty > qe->max_penalty) + if (mem->penalty > qe->max_penalty && qe->max_penalty) return -1; switch (q->strategy) { case QUEUE_STRATEGY_RINGALL: /* Everyone equal, except for penalty */ - tmp->metric = mem->penalty * 1000000; + if (q->last_member_not_available == 0) + tmp->metric = mem->penalty * 1000000; break; case QUEUE_STRATEGY_ROUNDROBIN: if (!pos) { @@ -2178,22 +2183,26 @@ q->wrapped = 1; tmp->metric = pos; } - tmp->metric += mem->penalty * 1000000; + if (q->last_member_not_available == 0) + tmp->metric += mem->penalty * 1000000; break; case QUEUE_STRATEGY_RANDOM: tmp->metric = ast_random() % 1000; - tmp->metric += mem->penalty * 1000000; + if (q->last_member_not_available == 0) + tmp->metric += mem->penalty * 1000000; break; case QUEUE_STRATEGY_FEWESTCALLS: tmp->metric = mem->calls; - tmp->metric += mem->penalty * 1000000; + if (q->last_member_not_available == 0) + tmp->metric += mem->penalty * 1000000; break; case QUEUE_STRATEGY_LEASTRECENT: if (!mem->lastcall) tmp->metric = 0; else tmp->metric = 1000000 - (time(NULL) - mem->lastcall); - tmp->metric += mem->penalty * 1000000; + if (q->last_member_not_available == 0) + tmp->metric += mem->penalty * 1000000; break; default: ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy); @@ -2302,7 +2311,7 @@ XXX If we're forcibly removed, these outgoing calls won't get hung up XXX */ tmp->q_next = outgoing; - outgoing = tmp; + outgoing = tmp; /* If this line is up, don't try anybody else */ if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP)) break; @@ -2332,6 +2341,14 @@ } else { res = digit; } + + if (qe->parent->escalate_if_not_available == 1) { + /* set the flag to ignore penalty on next ring */ + ast_mutex_lock(&qe->parent->lock); + qe->parent->last_member_not_available = 1; + ast_mutex_unlock(&qe->parent->lock); + } + if (option_debug) ast_log(LOG_DEBUG, "%s: Nobody answered.\n", qe->chan->name); } else { /* peer is valid */ @@ -2344,6 +2361,14 @@ if (!strcmp(peer->tech->type, "Zap")) ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0); /* Update parameters for the queue */ + + if (qe->parent->escalate_if_not_available == 1) { + /* next time we respect penalty */ + ast_mutex_lock(&qe->parent->lock); + qe->parent->last_member_not_available = 0; + ast_mutex_unlock(&qe->parent->lock); + } + recalc_holdtime(qe); member = lpeer->member; hangupcalls(outgoing, peer);