[asterisk-commits] irroot: branch irroot/asterisk-trunk-quack-queue r344898 - /team/irroot/aster...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Nov 11 17:51:37 CST 2011
Author: irroot
Date: Fri Nov 11 17:51:34 2011
New Revision: 344898
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=344898
Log:
Reverting change from bitield to flag
cleanups
support AST_DEVICE_BUSY
Modified:
team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c
Modified: team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c?view=diff&rev=344898&r1=344897&r2=344898
==============================================================================
--- team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c (original)
+++ team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c Fri Nov 11 17:51:34 2011
@@ -914,17 +914,6 @@
QUEUE_ADD_MEMBER_DYNAMIC = (1 << 2),
};
-enum callattempt_flags {
- /*! This attempt is busy dialing a user */
- QUEUE_MEMBER_RESERVED = (1 << 0),
- /*! This attempt is bridged */
- QUEUE_MEMBER_ACTIVE = (1 << 1),
- /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
- QUEUE_ATTEMPT_PENDING_CONNECTED = (1 << 2),
- /*! TRUE if caller id is not available for connected line */
- QUEUE_ATTEMPT_CALLERID_ABSENT = (1 << 3),
-};
-
static const struct strategy {
int strategy;
const char *name;
@@ -1047,14 +1036,15 @@
*/
struct callattempt {
- struct ast_channel *chan;
- int stillgoing;
- int metric;
- struct member *member;
- /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
- struct ast_party_connected_line connected;
- /*! Attempt flags */
- unsigned int flags;
+ struct ast_channel *chan; /*! Channel called */
+ int stillgoing; /*! This attempt is valid and active */
+ int metric; /*! Metric calculated according to strategy */
+ struct member *member; /*! Member assosiated with this attempt */
+ struct ast_party_connected_line connected; /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
+ unsigned int reserved:1; /*! Is this attempt been attempted*/
+ unsigned int active:1; /*! Is this attempt active in a call*/
+ unsigned int pending_connected_update:1; /*! TRUE if caller id is not available for connected line*/
+ unsigned int dial_callerid_absent:1; /*! TRUE if caller id is not available for connected line */
struct ast_aoc_decoded *aoc_s_rate_list;
};
@@ -1066,7 +1056,7 @@
int prio; /*!< Our priority */
int last_pos_said; /*!< Last position we told the user */
int ring_when_ringing; /*!< Should we only use ring indication when a channel is ringing? */
- struct timeval last_periodic_announce_time; /*!< The last time we played a periodic announcement */
+ struct timeval last_pannounce_time; /*!< The last time we played a periodic announcement */
int last_periodic_announce_sound; /*!< The last periodic announcement we made */
struct timeval last_pos; /*!< Last time we told the user their position */
int opos; /*!< Where we started in the queue */
@@ -1088,19 +1078,10 @@
/*! \brief keep track of device state changes */
struct mem_state {
- char state_interface[80]; /*!< Technology/Location from which to read devicestate changes */
- int reserved; /*!< This interface is reserved for pending call */
- int active; /*!< This interface is active on a call */
- int status; /*!< Status of queue member */
-};
-
-
-enum member_flags {
- QUEUE_MEMBER_REALTIME = ( 1 << 0), /*!< Is this member realtime? */
- QUEUE_MEMBER_DYNAMIC = ( 1 << 1), /*!< Is this member dynamic? */
- QUEUE_MEMBER_DEAD = (1 << 2), /*!< Used to detect members deleted in realtime */
- QUEUE_MEMBER_PAUSED = (1 << 3), /*!< Are we paused (not accepting calls)? */
- QUEUE_MEMBER_CALLINUSE = ( 1 << 4), /*!< Are we dynamically added? */
+ char state_interface[80]; /*!< Technology/Location from which to read devicestate changes */
+ int reserved; /*!< This interface is reserved for pending call */
+ int active; /*!< This interface is active on a call */
+ int status; /*!< Status of queue member */
};
struct member {
@@ -1113,7 +1094,11 @@
int calls; /*!< Number of calls serviced by this member */
struct timeval lastcall; /*!< When last successful call was hungup */
int lastwrapup; /*!< Last wrapuptime */
- unsigned int flags; /*!< Member Flags */
+ unsigned int dynamic:1; /*!< Is this member dynamic? */
+ unsigned int realtime:1; /*!< Is this member realtime? */
+ unsigned int paused:1; /*!< Are we paused (not accepting calls)? */
+ unsigned int dead:1; /*!< Used to detect members deleted in realtime */
+ unsigned int callinuse:1; /*!< Are we dynamically added? */
struct mem_state *device; /*!< Device information */
};
@@ -1215,8 +1200,8 @@
int periodicannouncefrequency; /*!< How often to play periodic announcement */
int numperiodicannounce; /*!< The number of periodic announcements configured */
int randomperiodicannounce; /*!< Are periodic announcments randomly chosen */
+ int roundingseconds; /*!< How many seconds do we round to? */
int servicelevel; /*!< seconds setting for servicelevel*/
- int roundingseconds; /*!< How many seconds do we round to? */
char monfmt[8]; /*!< Format to use when recording calls */
int montype; /*!< Monitor type Monitor vs. MixMonitor */
int maxlen; /*!< Max number of entries */
@@ -1417,12 +1402,31 @@
struct mem_state *s = m->device;
ao2_lock(s);
- if (s->active && ((s->status == AST_DEVICE_NOT_INUSE) || (s->status == AST_DEVICE_UNKNOWN))) {
- ret = (ast_test_flag(m, QUEUE_MEMBER_CALLINUSE)) ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
- } else if (s->reserved && ((s->status == AST_DEVICE_NOT_INUSE) || (s->status == AST_DEVICE_UNKNOWN))) {
- ret = AST_DEVICE_RINGING;
- } else {
- ret = s->status;
+
+ ret = s->status;
+ switch (s->status) {
+ case AST_DEVICE_INVALID:
+ case AST_DEVICE_UNAVAILABLE:
+ case AST_DEVICE_BUSY:
+ break;
+ case AST_DEVICE_INUSE:
+ case AST_DEVICE_RINGING:
+ case AST_DEVICE_RINGINUSE:
+ case AST_DEVICE_ONHOLD:
+ /* if im active and may not place calls when INUSE im actually BUSY */
+ if ((s->reserved || s->active) && !m->callinuse) {
+ ret = AST_DEVICE_BUSY;
+ break;
+ }
+ break;
+ case AST_DEVICE_NOT_INUSE:
+ case AST_DEVICE_UNKNOWN:
+ /* it seems that i have this device active but the system does not */
+ if (s->active) {
+ ret = (m->callinuse) ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
+ } else if (s->reserved) {
+ ret = (m->callinuse) ? AST_DEVICE_RINGING : AST_DEVICE_BUSY;
+ }
}
ao2_unlock(s);
@@ -1476,6 +1480,7 @@
}
goto default_case;
case AST_DEVICE_INUSE:
+ case AST_DEVICE_BUSY:
if (conditions & QUEUE_EMPTY_INUSE) {
ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
break;
@@ -1495,7 +1500,7 @@
/* Fall-through */
default:
default_case:
- if (ast_test_flag(member, QUEUE_MEMBER_PAUSED) && (conditions & QUEUE_EMPTY_PAUSED)) {
+ if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
break;
} else if ((conditions & QUEUE_EMPTY_WRAPUP) && !ast_tvzero(member->lastcall) && member->lastwrapup && (ast_tvdiff_sec(ast_tvnow(), member->lastcall) <= member->lastwrapup)) {
@@ -1568,11 +1573,8 @@
"Status: %d\r\n"
"Paused: %d\r\n"
"CallInuse: %d\r\n",
- q->name, m->interface, m->membername, s->state_interface,
- (ast_test_flag(m, QUEUE_MEMBER_DYNAMIC)) ? "dynamic" : (ast_test_flag(m, QUEUE_MEMBER_REALTIME)) ? "realtime" : "static",
- m->penalty, m->calls, (int)m->lastcall.tv_sec, s->status,
- ast_test_flag(m, QUEUE_MEMBER_PAUSED) ? 1 : 0,
- ast_test_flag(m, QUEUE_MEMBER_CALLINUSE) ? 1 : 0
+ q->name, m->interface, m->membername, s->state_interface, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
+ m->penalty, m->calls, (int)m->lastcall.tv_sec, s->status, m->paused, m->callinuse
);
ao2_unlock(s);
ao2_unlock(m);
@@ -1790,7 +1792,7 @@
const struct member *mem2 = arg;
const char *uniqueid = (flags & OBJ_POINTER) ? mem2->rt_uniqueid : arg;
- if (ast_test_flag(mem1, QUEUE_MEMBER_REALTIME) && !ast_test_flag(mem1, QUEUE_MEMBER_DEAD) &&
+ if (mem1->realtime && !mem1->dead &&
!strcasecmp(mem1->rt_uniqueid, uniqueid)) {
return CMP_MATCH | CMP_STOP;
}
@@ -1805,10 +1807,8 @@
{
struct member *member = obj;
- if (ast_test_flag(member, QUEUE_MEMBER_REALTIME)) {
- ao2_lock(member);
- ast_set_flag(member, QUEUE_MEMBER_DEAD);
- ao2_unlock(member);
+ if (member->realtime) {
+ member->dead = 1;
return CMP_MATCH;
}
return 0;
@@ -1822,7 +1822,7 @@
struct member *m = obj;
const struct call_queue *q = data;
- if (ast_test_flag(m, QUEUE_MEMBER_DEAD) && ast_test_flag(m, QUEUE_MEMBER_REALTIME)) {
+ if (m->realtime && m->dead) {
ao2_lock(m);
if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
@@ -2030,7 +2030,7 @@
}
q->reload = ast_tvnow();
- q->reload.tv_sec += 86400;
+ q->reload.tv_sec += 86400;
}
/*!
@@ -2382,18 +2382,18 @@
}
if (ast_string_field_init(m, 64)) {
ao2_ref(m, -1);
- ast_log(LOG_WARNING, "Unable to alocate memory\n");
return RES_OUTOFMEMORY;
}
m->device = NULL;
- m->flags = 0;
- ast_set_flag(m, QUEUE_MEMBER_CALLINUSE);
+ m->paused = 0;
+ m->callinuse = 1;
if (memtype & QUEUE_ADD_MEMBER_REALTIME) {
- ast_set_flag(m, QUEUE_MEMBER_REALTIME);
+ m->realtime = 1;
} else if (memtype & QUEUE_ADD_MEMBER_DYNAMIC) {
- ast_set_flag(m, QUEUE_MEMBER_DYNAMIC);
- }
+ m->dynamic = 1;
+ }
+ m->dead = 0;
m->calls = 0;
m->lastcall = ast_tv(0, 0);
m->lastwrapup = 0;
@@ -2404,7 +2404,7 @@
if (memtype & QUEUE_ADD_MEMBER_DYNAMIC) {
/* dynamic members are the lowest priority and cannot overwrite settings from DB*/
- if (ast_test_flag(m, QUEUE_MEMBER_DYNAMIC)) {
+ if (m->dynamic) {
res = RES_EXISTS;
} else {
res = RES_NOT_DYNAMIC;
@@ -2412,31 +2412,31 @@
ao2_unlock(q->data->members);
ao2_ref(m, -1);
return res;
- } else if ((ast_test_flag(m, QUEUE_MEMBER_DYNAMIC) || ast_test_flag(m, QUEUE_MEMBER_REALTIME)) &&
- (memtype & QUEUE_ADD_MEMBER_STATIC)) {
+ } else if ((m->dynamic || m->realtime) && (memtype & QUEUE_ADD_MEMBER_STATIC)) {
/*static members take precedence over all others*/
ao2_lock(m);
- ast_clear_flag(m, QUEUE_MEMBER_DYNAMIC);
- ast_clear_flag(m, QUEUE_MEMBER_REALTIME);
+ m->dynamic = 0;
+ m->realtime = 0;
if (!ast_strlen_zero(m->rt_uniqueid)) {
ast_string_field_set(m, rt_uniqueid, NULL);
}
} else if (memtype & QUEUE_ADD_MEMBER_REALTIME) {
/* realtime takes precedence over dynamic but not static*/
ao2_lock(m);
- if (ast_test_flag(m, QUEUE_MEMBER_DYNAMIC)) {
- ast_clear_flag(m, QUEUE_MEMBER_DYNAMIC);
- ast_set_flag(m, QUEUE_MEMBER_REALTIME);
- } else if (!ast_test_flag(m, QUEUE_MEMBER_REALTIME)) {
+ if (m->dynamic) {
+ m->dynamic = 0;
+ m->realtime = 1;
+ } else if (!m->realtime) {
+ ao2_unlock(m);
ao2_unlock(q->data->members);
- ao2_unlock(m);
ao2_ref(m, -1);
return RES_EXISTS;
}
- ast_clear_flag(m, QUEUE_MEMBER_DEAD);
+ m->dead = 0;
} else {
ao2_lock(m);
}
+ ao2_unlock(q->data->members);
}
for (v = ast_variable_browse(member_config, interface); v; v = v->next) {
@@ -2454,22 +2454,10 @@
dead = 1;
}
} else if (!strcasecmp(v->name, "paused")) {
- if (ast_true(v->value)) {
- ast_set_flag(m, QUEUE_MEMBER_PAUSED);
- } else {
- ast_clear_flag(m, QUEUE_MEMBER_PAUSED);
- }
+ m->paused = abs(ast_true(v->value));
} else if (!strcasecmp(v->name, "callinuse") || !strcasecmp(v->name, "ignorebusy")) {
- if (ast_true(v->value)) {
- ast_set_flag(m, QUEUE_MEMBER_CALLINUSE);
- } else {
- ast_clear_flag(m, QUEUE_MEMBER_CALLINUSE);
- }
- }
- }
-
- if (!link) {
- ao2_unlock(q->data->members);
+ m->callinuse = abs(ast_true(v->value));
+ }
}
if (ast_strlen_zero(st_dev)) {
@@ -2512,31 +2500,29 @@
}
if (!dead && link) {
+ int status = get_device_status(m);
+
/* i have just been born */
if ((ast_strlen_zero(m->membername) || !log_membername_as_agent)) {
ast_queue_log(q->name, source, m->interface, "ADDMEMBER", "%s", "");
} else {
ast_queue_log(q->name, source, m->membername, "ADDMEMBER", "%s", "");
}
- if (ast_test_flag(m, QUEUE_MEMBER_DYNAMIC)) {
- int status = get_device_status(m);
- manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
- "Queue: %s\r\n"
- "Location: %s\r\n"
- "MemberName: %s\r\n"
- "StateInterface: %s\r\n"
- "Membership: %s\r\n"
- "Penalty: %d\r\n"
- "CallsTaken: %d\r\n"
- "LastCall: %d\r\n"
- "Status: %d\r\n"
- "Paused: %d\r\n"
- "CallInuse: %d\r\n",
- q->name, m->interface, m->membername, m->device->state_interface,
- "dynamic",m->penalty, m->calls, (int)m->lastcall.tv_sec,
- status, ast_test_flag(m, QUEUE_MEMBER_PAUSED) ? 1 : 0,
- ast_test_flag(m, QUEUE_MEMBER_CALLINUSE) ? 1 : 0);
- }
+ manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "MemberName: %s\r\n"
+ "StateInterface: %s\r\n"
+ "Membership: %s\r\n"
+ "Penalty: %d\r\n"
+ "CallsTaken: %d\r\n"
+ "LastCall: %d\r\n"
+ "Status: %d\r\n"
+ "Paused: %d\r\n"
+ "CallInuse: %d\r\n",
+ q->name, m->interface, m->membername, m->device->state_interface,
+ m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
+ m->penalty, m->calls, (int)m->lastcall.tv_sec, status, m->paused, m->callinuse);
ao2_link(q->data->members, m);
} else if (dead) {
/* ive failed penalty/uniqueid/devstate failure */
@@ -3213,14 +3199,14 @@
struct mem_state *s;
if (doomed->member) {
- if (doomed->flags & (QUEUE_MEMBER_RESERVED | QUEUE_MEMBER_ACTIVE)) {
+ if (doomed->reserved || doomed->active) {
ao2_lock(doomed->member);
s = doomed->member->device;
ao2_lock(s);
- if (ast_test_flag(doomed, QUEUE_MEMBER_RESERVED)) {
+ if (doomed->reserved) {
s->reserved--;
}
- if (ast_test_flag(doomed, QUEUE_MEMBER_ACTIVE)) {
+ if (doomed->active) {
s->active--;
}
ao2_unlock(s);
@@ -3247,7 +3233,7 @@
}
ast_hangup(outgoing->chan);
ao2_unlink(qe->attempts, outgoing);
- } else {
+ } else if (outgoing != exception) {
ao2_unlink(qe->attempts, outgoing);
}
ast_aoc_destroy_decoded(outgoing->aoc_s_rate_list);
@@ -3282,13 +3268,13 @@
case AST_DEVICE_RINGING:
case AST_DEVICE_RINGINUSE:
case AST_DEVICE_ONHOLD:
- if ((!q->ringinuse) || (!ast_test_flag(mem, QUEUE_MEMBER_CALLINUSE))) {
+ if (!q->ringinuse || !mem->callinuse) {
break;
}
/* else fall through */
case AST_DEVICE_NOT_INUSE:
case AST_DEVICE_UNKNOWN:
- if (!ast_test_flag(mem, QUEUE_MEMBER_PAUSED)) {
+ if (!mem->paused) {
avl++;
}
break;
@@ -3412,10 +3398,12 @@
* Does error checking before attempting to request a channel and call a member.
* This function is only called from ring_one().
* Failure can occur if:
- * - Agent on call
- * - Agent is paused
+ * - Priority by another queue
* - Wrapup time not expired
- * - Priority by another queue
+ * - Member is paused
+ * - Member on call / or is not available for a call
+ * - Channel cannot be created by driver
+ * - Channel cannot be called by driver
*
* \retval 1 on success to reach a free agent
* \retval 0 on failure to get agent.
@@ -3430,20 +3418,32 @@
struct mem_state *s;
int dstat;
+ /* we cannot take this call there is a more urgent call we qualify for */
+ if (use_weight && compare_weight(qe->parent,tmp->member->interface)) {
+ ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->member->interface);
+ if (qe->chan->cdr) {
+ ast_cdr_busy(qe->chan->cdr);
+ }
+ tmp->stillgoing = 0;
+ (*busies)++;
+ return 0;
+ }
+
ao2_lock(tmp->member);
s = tmp->member->device;
- /* on entry here, we know that tmp->chan == NULL */
- if (ast_test_flag(tmp->member, QUEUE_MEMBER_PAUSED)) {
+ if (tmp->member->paused) {
ao2_unlock(tmp->member);
ast_debug(1, "%s paused, can't receive call\n", tmp->member->interface);
if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
}
tmp->stillgoing = 0;
+ (*busies)++;
return 0;
}
+ /* am i still in wrapuptime */
if (tmp->member->lastwrapup && (ast_tvdiff_sec(ast_tvnow(), tmp->member->lastcall) <= tmp->member->lastwrapup)) {
ao2_unlock(tmp->member);
ast_debug(1, "Wrapuptime not yet expired for %s\n", tmp->member->interface);
@@ -3455,47 +3455,30 @@
return 0;
}
- if (!qe->parent->ringinuse || !ast_test_flag(tmp->member, QUEUE_MEMBER_CALLINUSE)) {
- dstat = get_device_status(tmp->member);
- if ((dstat == AST_DEVICE_NOT_INUSE) || (dstat == AST_DEVICE_UNKNOWN)) {
- int newstate = set_queue_member_status(tmp->member);
- if (newstate != dstat) {
- ast_log(AST_LOG_WARNING, "Device (%s) state changed from %s to %s\n",
- tmp->member->interface, ast_devstate2str(dstat), ast_devstate2str(newstate));
- dstat = newstate;
- }
- }
- if ((dstat != AST_DEVICE_NOT_INUSE) && (dstat != AST_DEVICE_UNKNOWN)) {
- ao2_unlock(tmp->member);
- ast_debug(1, "%s in use, can't receive call\n", tmp->member->interface);
- if (qe->chan->cdr) {
- ast_cdr_busy(qe->chan->cdr);
- }
- tmp->stillgoing = 0;
- (*busies)++;
- return 0;
- }
+ /* do not ring a member that is not able to take a call */
+ dstat = get_device_status(tmp->member);
+ if ((dstat == AST_DEVICE_INVALID) ||
+ (dstat == AST_DEVICE_BUSY) ||
+ (dstat == AST_DEVICE_UNAVAILABLE) ||
+ (!qe->parent->ringinuse && (dstat != AST_DEVICE_NOT_INUSE) && (dstat != AST_DEVICE_UNKNOWN))) {
+ ao2_unlock(tmp->member);
+ ast_debug(1, "%s is %s, can't receive call\n", tmp->member->interface, ast_devstate2str(dstat));
+ if (qe->chan->cdr) {
+ ast_cdr_busy(qe->chan->cdr);
+ }
+ tmp->stillgoing = 0;
+ (*busies)++;
+ return 0;
}
/* mark device and call entry reserved */
- if (!ast_test_flag(tmp, QUEUE_MEMBER_RESERVED)) {
+ if (!tmp->reserved) {
ao2_lock(s);
s->reserved++;
ao2_unlock(s);
- ast_set_flag(tmp, QUEUE_MEMBER_RESERVED);
+ tmp->reserved = 1;
}
ao2_unlock(tmp->member);
-
- if (use_weight && compare_weight(qe->parent,tmp->member->interface)) {
- ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->member->interface);
- if (qe->chan->cdr) {
- ast_cdr_busy(qe->chan->cdr);
- }
- tmp->stillgoing = 0;
- (*busies)++;
- return 0;
- }
-
ast_copy_string(tech, tmp->member->interface, sizeof(tech));
if ((location = strchr(tech, '/'))) {
@@ -3522,10 +3505,7 @@
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);
@@ -3548,7 +3528,7 @@
} else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL);
}
- ast_set_flag(tmp, QUEUE_ATTEMPT_CALLERID_ABSENT);
+ tmp->dial_callerid_absent = 1;
}
ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
@@ -3588,20 +3568,22 @@
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->member->interface);
- ast_channel_unlock(tmp->chan);
- ast_channel_unlock(qe->chan);
do_hang(tmp);
(*busies)++;
+ tmp->stillgoing = 0;
set_queue_member_status(tmp->member);
return 0;
} else if (qe->parent->eventwhencalled) {
char vars[2048];
+ ast_channel_lock_both(tmp->chan, qe->chan);
ao2_lock(tmp->member);
manager_event(EVENT_FLAG_AGENT, "AgentCalled",
"Queue: %s\r\n"
@@ -3625,11 +3607,13 @@
S_COR(tmp->chan->connected.id.name.valid, tmp->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)) : "");
+
ao2_unlock(tmp->member);
+ ast_channel_unlock(tmp->chan);
+ ast_channel_unlock(qe->chan);
+
ast_verb(3, "Called %s\n", tmp->member->interface);
}
- ast_channel_unlock(tmp->chan);
- ast_channel_unlock(qe->chan);
return 1;
}
@@ -3668,13 +3652,12 @@
ao2_ref(cur, -1);
}
ao2_iterator_destroy(&aiter);
- ao2_ref(best, -1);
} else {
/* Ring just the best channel */
ast_debug(1, "Trying '%s' with metric %d\n", best->member->interface, best->metric);
ret = ring_entry(qe, best, busies);
- ao2_ref(best, -1);
- }
+ }
+ ao2_ref(best, -1);
/* If we have timed out, break out */
if (!ast_tvzero(qe->expire) && (ast_tvcmp(ast_tvnow(), qe->expire) >= 0)) {
@@ -3688,7 +3671,6 @@
}
/*! \brief Search for best metric and add to Round Robbin queue
- * \note the members container is locked here for new_attempt
*/
static int store_next_rr(struct queue_ent *qe)
{
@@ -3755,7 +3737,7 @@
now = ast_tvnow();
/* Check to see if it is time to announce */
- if (ast_tvdiff_sec(now, qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) {
+ if (ast_tvdiff_sec(now, qe->last_pannounce_time) < qe->parent->periodicannouncefrequency) {
return 0;
}
@@ -3789,11 +3771,11 @@
}
}
- /* update last_periodic_announce_time */
+ /* update last_pannounce_time */
if (qe->parent->relativeperiodicannounce) {
- qe->last_periodic_announce_time = ast_tvnow();
+ qe->last_pannounce_time = ast_tvnow();
} else {
- qe->last_periodic_announce_time = now;
+ qe->last_pannounce_time = now;
}
/* Update the current periodic announcement to the next announcement */
@@ -3863,7 +3845,6 @@
}
}
if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
- ao2_lock(qe->parent->data->members);
ao2_lock(call->member);
if (!(do_set_member_penalty_paused(qe->parent, call->member, 1, 1, "Auto-Pause"))) {
ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
@@ -3872,7 +3853,6 @@
ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", call->member->interface, qe->parent->name);
}
ao2_unlock(call->member);
- ao2_unlock(qe->parent->data->members);
} else {
/* If queue autopause is mode all, just don't send any queue to stop.
* the function will stop in all queues */
@@ -4010,11 +3990,11 @@
if (!peer) {
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
- if (ast_test_flag(o, QUEUE_ATTEMPT_PENDING_CONNECTED)) {
+ if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL);
}
- } else if (!ast_test_flag(o, QUEUE_ATTEMPT_CALLERID_ABSENT)) {
+ } else if (!o->dial_callerid_absent) {
ast_channel_lock(o->chan);
ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
ast_channel_unlock(o->chan);
@@ -4078,10 +4058,8 @@
} 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);
@@ -4164,11 +4142,11 @@
if (!peer) {
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
- if (ast_test_flag(o, QUEUE_ATTEMPT_PENDING_CONNECTED)) {
+ if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected, NULL);
}
- } else if (!ast_test_flag(o, QUEUE_ATTEMPT_CALLERID_ABSENT)) {
+ } else if (!o->dial_callerid_absent) {
ast_channel_lock(o->chan);
ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
ast_channel_unlock(o->chan);
@@ -4253,7 +4231,7 @@
ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
ast_party_connected_line_set(&o->connected, &connected, NULL);
ast_party_connected_line_free(&connected);
- ast_set_flag(o, QUEUE_ATTEMPT_PENDING_CONNECTED);
+ o->pending_connected_update = 1;
} else {
if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
@@ -4287,7 +4265,6 @@
}
ast_frfree(f);
}
- /* hold a ref for the answerd line */
ao2_ref(o, -1);
}
ao2_iterator_destroy(&aiter);
@@ -4661,7 +4638,8 @@
tmp->stillgoing = -1;
tmp->member = mem;/* Place the reference for cur into callattempt. */
- tmp->flags = 0;
+ tmp->dial_callerid_absent = 0;
+ tmp->pending_connected_update =0;
tmp->metric = metric;
return tmp;
@@ -4755,6 +4733,7 @@
(long)ast_tvdiff_sec(ast_tvnow(), callstart), qe->opos);
ao2_unlock(member);
+
update_queue(qe->parent, member, callcompletedinsl, ast_tvdiff_sec(ast_tvnow(), callstart));
/* No need to lock the channels because they are already locked in ast_do_masquerade */
@@ -4840,8 +4819,6 @@
* iteration, we also check the dialed_interfaces datastore to see if we have already attempted calling this
* member. If we have, we do not create a callattempt. This is in place to prevent call forwarding loops. Also
* during each iteration, we calculate a metric to determine which members should be rung when.
- * \note It is too costly to lock and unlock the queue and members for this and the queue and members container
- * Is locked for the whole process.
*
* 3. Call ring_one to place a call to the appropriate member(s)
* 4. Call wait_for_answer to wait for an answer. If no one answers, return.
@@ -5227,6 +5204,7 @@
ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)ast_tvdiff_sec(ast_tvnow(), qe->start));
ao2_unlock(member);
record_abandoned(qe);
+ ao2_unlink(qe->attempts, lpeer);
ao2_ref(lpeer, -1);
ast_hangup(peer);
return -1;
@@ -5250,6 +5228,7 @@
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
record_abandoned(qe);
ast_cdr_failed(qe->chan->cdr);
+ ao2_unlink(qe->attempts, lpeer);
ao2_ref(lpeer, -1);
ast_hangup(peer);
return -1;
@@ -5266,9 +5245,7 @@
if (qe->parent->setinterfacevar) {
ao2_lock(member);
snprintf(interfacevar, sizeof(interfacevar), "MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
- member->interface, member->membername, member->calls, (long)member->lastcall.tv_sec, member->penalty,
- ast_test_flag(member, QUEUE_MEMBER_DYNAMIC),
- ast_test_flag(member, QUEUE_MEMBER_REALTIME));
+ member->interface, member->membername, member->calls, (long)member->lastcall.tv_sec, member->penalty, member->dynamic, member->realtime);
pbx_builtin_setvar_multiple(qe->chan, interfacevar);
pbx_builtin_setvar_multiple(peer, interfacevar);
ao2_unlock(member);
@@ -5536,41 +5513,6 @@
ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
}
qe->handled++;
- ao2_lock(member);
- ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld",
- (long)ast_tvdiff_sec(ast_tvnow(), qe->start), peer->uniqueid,
- (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
- ao2_unlock(member);
-
- 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_cdr_init(newcdr, qe->chan);
- ast_cdr_reset(newcdr, 0);
- ast_channel_lock(qe->chan);
- cdr = ast_cdr_append(cdr, newcdr);
- cdr = cdr->next;
- ast_channel_unlock(qe->chan);
- }
-
- if (update_cdr) {
- ao2_lock(member);
- ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
- ao2_unlock(member);
- }
- }
-
callstart = ast_tvnow();
ao2_lock(member);
@@ -5589,7 +5531,40 @@
(long)ast_tvdiff_sec(callstart, 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_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld",
+ (long)ast_tvdiff_sec(ast_tvnow(), qe->start), peer->uniqueid,
+ (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
ao2_unlock(member);
+
+ 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_cdr_init(newcdr, qe->chan);
+ ast_cdr_reset(newcdr, 0);
+ ast_channel_lock(qe->chan);
+ cdr = ast_cdr_append(cdr, newcdr);
+ cdr = cdr->next;
+ ast_channel_unlock(qe->chan);
+ }
+
+ if (update_cdr) {
+ ao2_lock(member);
+ ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
+ ao2_unlock(member);
+ }
+ }
ast_copy_string(oldcontext, qe->chan->context, sizeof(oldcontext));
ast_copy_string(oldexten, qe->chan->exten, sizeof(oldexten));
@@ -5607,21 +5582,28 @@
ao2_t_ref(qe->parent, 1, "For bridge_config reference");
}
- ast_channel_lock(peer);
+ /* The call was picked up elsewhere log the original interface the channel picking up the call hold time and position */
+ ast_channel_lock_both(peer, qe->chan);
if (ast_channel_datastore_find(peer, &pickup_target_info, NULL)) {
- ast_channel_unlock(peer);
ao2_unlink(qe->attempts, lpeer);
ao2_ref(member, 1);
+ ao2_lock(member);
+ ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "PICKUP", "%s|%s|%ld|%d",
+ member->interface, peer->name, (long)ast_tvdiff_sec(callstart, qe->start), qe->opos);
+ ao2_unlock(member);
ao2_ref(lpeer, -1);
lpeer = NULL;
+ ast_channel_unlock(peer);
+ ast_channel_unlock(qe->chan);
} else {
ast_channel_unlock(peer);
+ ast_channel_unlock(qe->chan);
ao2_lock(member);
ao2_lock(member->device);
member->device->active++;
- ast_set_flag(lpeer, QUEUE_MEMBER_ACTIVE);
- if (ast_test_flag(lpeer, QUEUE_MEMBER_RESERVED)) {
- ast_clear_flag(lpeer, QUEUE_MEMBER_RESERVED);
+ lpeer->active = 1;
+ if (lpeer->reserved) {
+ lpeer->reserved = 0;
member->device->reserved--;
}
ao2_unlock(member->device);
@@ -5690,7 +5672,6 @@
static int wait_a_bit(struct queue_ent *qe)
{
- /* Don't need to hold the lock while we setup the outgoing calls */
int retrywait = qe->parent->retry * 1000;
int res = ast_waitfordigit(qe->chan, retrywait);
@@ -5745,19 +5726,15 @@
mem_iter = ao2_iterator_init(pm_queue->data->members, 0);
while ((cur_member = ao2_iterator_next(&mem_iter))) {
ao2_lock(cur_member);
- if (!ast_test_flag(cur_member, QUEUE_MEMBER_DYNAMIC) ||
- ast_test_flag(cur_member, QUEUE_MEMBER_DEAD)) {
+ if (!cur_member->dynamic || cur_member->dead) {
ao2_unlock(cur_member);
ao2_ref(cur_member, -1);
continue;
}
res = snprintf(value + value_len, sizeof(value) - value_len, "%s%s;%d;%d;%s;%s;%d",
- value_len ? "|" : "", cur_member->interface, cur_member->penalty,
- ast_test_flag(cur_member, QUEUE_MEMBER_PAUSED) ? 1 : 0,
- cur_member->membername, cur_member->device->state_interface,
- ast_test_flag(cur_member, QUEUE_MEMBER_CALLINUSE) ? 1 : 0);
-
+ value_len ? "|" : "", cur_member->interface, cur_member->penalty,cur_member->paused,
+ cur_member->membername, cur_member->device->state_interface, cur_member->callinuse);
ao2_unlock(cur_member);
ao2_ref(cur_member, -1);
@@ -5799,13 +5776,13 @@
ao2_lock(mem);
/* XXX future changes should beware of this assumption!! */
/*Change Penalty on realtime users*/
- if (ast_test_flag(mem, QUEUE_MEMBER_REALTIME) && negative_penalty_invalid) {
+ if (mem->realtime && negative_penalty_invalid) {
update_realtime_member_field(mem, q->name, "penalty", "-1");
- } else if (!ast_test_flag(mem, QUEUE_MEMBER_DYNAMIC)) {
+ } else if (!mem->dynamic) {
ao2_unlock(mem);
ao2_ref(mem, -1);
return RES_NOT_DYNAMIC;
- } else if (ast_test_flag(mem, QUEUE_MEMBER_DYNAMIC)) {
+ } else if (mem->dynamic) {
reload = 1;
}
manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
@@ -5833,12 +5810,8 @@
static int do_set_member_penalty_paused(struct call_queue *q, struct member *mem, int pause, int value, const char *reason)
{
if (pause) {
- if (value) {
- ast_set_flag(mem, QUEUE_MEMBER_PAUSED);
- } else {
- ast_clear_flag(mem, QUEUE_MEMBER_PAUSED);
- }
- if (ast_test_flag(mem, QUEUE_MEMBER_REALTIME) &&
+ mem->paused = (value) ? 1 : 0;
+ if (mem->realtime &&
update_realtime_member_field(mem, q->name, "paused", (value) ? "1" : "0")) {
ast_log(LOG_WARNING, "Failed %spausing realtime member %s queue %s\n",
(value) ? "" : "un", mem->membername, q->name);
@@ -5865,7 +5838,7 @@
}
} else {
mem->penalty = value;
- if (ast_test_flag(mem, QUEUE_MEMBER_REALTIME)) {
+ if (mem->realtime) {
char *rtpenalty;
if (!asprintf(&rtpenalty,"%i", mem->penalty) ||
update_realtime_member_field(mem, q->name, "penalty", rtpenalty)) {
@@ -5883,7 +5856,7 @@
q->name, mem->interface, mem->penalty);
}
- if (ast_test_flag(mem, QUEUE_MEMBER_DYNAMIC) && queue_persistent_members) {
+ if (mem->dynamic && queue_persistent_members) {
dump_queue_members(q);
}
@@ -5906,11 +5879,9 @@
ao2_ref(q, -1);
return RESULT_FAILURE;
}
- ao2_lock(q->data->members);
ao2_lock(mem);
found = !do_set_member_penalty_paused(q, mem, 1, paused, reason);
ao2_unlock(mem);
- ao2_unlock(q->data->members);
ao2_ref(mem, -1);
ao2_ref(q, -1);
return (!found) ? RESULT_FAILURE : RESULT_SUCCESS;
@@ -5925,13 +5896,11 @@
queue_iter = ao2_iterator_init(queues, 0);
while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
if ((mem = interface_exists(q, interface))) {
- ao2_lock(q->data->members);
ao2_lock(mem);
if (!do_set_member_penalty_paused(q, mem, 1, paused, reason)) {
found ++;
}
ao2_unlock(mem);
- ao2_unlock(q->data->members);
ao2_ref(mem, -1);
}
ao2_t_ref(q, -1, "Done with iterator");
@@ -6334,7 +6303,7 @@
);
/* Our queue entry */
struct queue_ent qe = { 0 };
-
+
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
return -1;
@@ -6429,7 +6398,7 @@
qe.min_penalty = min_penalty;
qe.last_pos_said = 0;
qe.last_pos = ast_tv(0, 0);
- qe.last_periodic_announce_time = ast_tvnow();
+ qe.last_pannounce_time = ast_tvnow();
qe.last_periodic_announce_sound = 0;
qe.valid_digits = 0;
@@ -6731,7 +6700,7 @@
ao2_lock(m);
/* Count the agents who are logged in and presently answering calls */
status = get_device_status(m);
- if ((status == AST_DEVICE_NOT_INUSE) && (!ast_test_flag(m, QUEUE_MEMBER_PAUSED))) {
+ if ((status == AST_DEVICE_NOT_INUSE) && (!m->paused)) {
count++;
}
ao2_unlock(m);
@@ -6744,7 +6713,7 @@
ao2_lock(m);
/* Count the agents who are logged in, not paused and not wrapping up */
status = get_device_status(m);
- if ((status == AST_DEVICE_NOT_INUSE) && (!ast_test_flag(m, QUEUE_MEMBER_PAUSED)) &&
+ if ((status == AST_DEVICE_NOT_INUSE) && !m->paused &&
!(!ast_tvzero(m->lastcall) && m->lastwrapup &&
(ast_tvdiff_sec(ast_tvnow(), m->lastcall) <= m->lastwrapup))) {
count++;
@@ -6764,13 +6733,13 @@
} else if (!strcasecmp(args.option, "paused") && !ast_strlen_zero(args.interface) &&
((m = interface_exists(q, args.interface)))) {
ao2_lock(m);
- count = ast_test_flag(m, QUEUE_MEMBER_PAUSED) ? 1 : 0;
+ count = m->paused;
ao2_unlock(m);
ao2_ref(m, -1);
} else if (!strcasecmp(args.option, "callinuse") && !ast_strlen_zero(args.interface) &&
((m = interface_exists(q, args.interface)))) {
ao2_lock(m);
- count = ast_test_flag(m, QUEUE_MEMBER_CALLINUSE) ? 1 : 0;
+ count = m->callinuse;
ao2_unlock(m);
ao2_ref(m, -1);
}
@@ -6844,17 +6813,11 @@
return -1;
}
if (!strcasecmp(args.option, "callinuse")) {
- ao2_lock(q->data->members);
ao2_lock(m);
- if (memvalue) {
- ast_set_flag(m, QUEUE_MEMBER_CALLINUSE);
- } else {
- ast_clear_flag(m, QUEUE_MEMBER_CALLINUSE);
- }
- ao2_unlock(q->data->members);
- if (ast_test_flag(m, QUEUE_MEMBER_REALTIME)) {
+ m->callinuse = (memvalue) ? 1 : 0;
+ if (m->realtime) {
update_realtime_member_field(m, q->name, args.option, value);
- } else if (ast_test_flag(m, QUEUE_MEMBER_DYNAMIC)) {
+ } else if (m->dynamic) {
reload = 1;
}
ao2_unlock(m);
@@ -7274,10 +7237,8 @@
{
struct member *member = obj;
- if (!ast_test_flag(member, QUEUE_MEMBER_DYNAMIC) && !ast_test_flag(member, QUEUE_MEMBER_REALTIME)) {
- ao2_lock(member);
- ast_set_flag(member, QUEUE_MEMBER_DEAD);
- ao2_unlock(member);
+ if (!member->dynamic && !member->realtime) {
+ member->dead = 1;
return CMP_MATCH;
}
@@ -7291,8 +7252,7 @@
{
struct member *member = obj;
- if ((!ast_test_flag(member, QUEUE_MEMBER_DYNAMIC) && !ast_test_flag(member, QUEUE_MEMBER_REALTIME)) &&
- ast_test_flag(member, QUEUE_MEMBER_DEAD)) {
+ if (!member->dynamic && !member->realtime && member->dead) {
return CMP_MATCH;
}
return 0;
@@ -7690,9 +7650,9 @@
}
status = get_device_status(mem);
ast_str_append(&out, 0, "%s%s%s (%s)",
- ast_test_flag(mem, QUEUE_MEMBER_DYNAMIC) ? " (dynamic)" : "",
- ast_test_flag(mem, QUEUE_MEMBER_REALTIME) ? " (realtime)" : "",
- ast_test_flag(mem, QUEUE_MEMBER_PAUSED) ? " (paused)" : "",
+ mem->dynamic ? " (dynamic)" : "",
+ mem->realtime ? " (realtime)" : "",
+ mem->paused ? " (paused)" : "",
ast_devstate2str(status));
if (mem->calls) {
@@ -7889,8 +7849,8 @@
[... 101 lines stripped ...]
More information about the asterisk-commits
mailing list