/*! \brief queues.conf [general] option */
static int log_membername_as_agent;
+/*! \brief queues.conf [general] option */
+static int force_longest_waiting_caller;
+
/*! \brief name of the ringinuse field in the realtime database */
static char *realtime_ringinuse_field;
return found;
}
+static int is_longest_waiting_caller(struct queue_ent *caller, struct member *member)
+{
+ struct call_queue *q;
+ struct member *mem;
+ int is_longest_waiting = 1;
+ struct ao2_iterator queue_iter;
+ struct queue_ent *ch;
+
+ queue_iter = ao2_iterator_init(queues, 0);
+ while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
+ if (q == caller->parent) { /* don't check myself, could deadlock */
+ queue_t_unref(q, "Done with iterator");
+ continue;
+ }
+ ao2_lock(q);
+ /*
+ * If the other queue has equal weight, see if we should let that handle
+ * their call first. If weights are not equal, compare_weights will step in.
+ */
+ if (q->weight == caller->parent->weight && q->count && q->members) {
+ if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
+ ast_debug(2, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
+
+ /* Does this queue have a caller that's been waiting longer? */
+ ch = q->head;
+ while (ch) {
+ /* If ch->pending, the other call (which may be waiting for a longer period of time),
+ * is already ringing at another agent. Ignore such callers; otherwise, all agents
+ * will be unused until the first caller is picked up.
+ */
+ if (ch->start < caller->start && !ch->pending) {
+ ast_debug(1, "Queue %s has a call at position %i that's been waiting longer (%li vs %li)\n",
+ q->name, ch->pos, ch->start, caller->start);
+ is_longest_waiting = 0;
+ break;
+ }
+ ch = ch->next;
+ }
+ }
+ }
+ ao2_unlock(q);
+ queue_t_unref(q, "Done with iterator");
+ if (!is_longest_waiting) {
+ break;
+ }
+ }
+ ao2_iterator_destroy(&queue_iter);
+ return is_longest_waiting;
+}
+
/*! \brief common hangup actions */
static void do_hang(struct callattempt *o)
{
return 0;
}
+ if (force_longest_waiting_caller && !is_longest_waiting_caller(qe, memberp)) {
+ ast_debug(1, "Another caller was waiting longer; delaying call to %s:%s\n",
+ qe->parent->name, call->interface);
+ return 0;
+ }
+
if (!memberp->ringinuse) {
struct member *mem;
shared_lastcall = 0;
negative_penalty_invalid = 0;
log_membername_as_agent = 0;
+ force_longest_waiting_caller = 0;
}
/*! Set the global queue parameters as defined in the "general" section of queues.conf */
if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent"))) {
log_membername_as_agent = ast_true(general_val);
}
+ if ((general_val = ast_variable_retrieve(cfg, "general", "force_longest_waiting_caller"))) {
+ force_longest_waiting_caller = ast_true(general_val);
+ }
}
/*! \brief reload information pertaining to a single member