aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-03-18 21:03:52 +0000
committermmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b>2008-03-18 21:03:52 +0000
commitc71f7444d4e88060fc279feaf2bb548a28ba4fa6 (patch)
tree846baf2340c7c3e1de9afa5eee21227d813b6fa7
parent954998fda6278dc47c4899f1f1889eb38061e571 (diff)
Merged revisions 109714 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ................ r109714 | mmichelson | 2008-03-18 15:59:02 -0500 (Tue, 18 Mar 2008) | 20 lines Merged revisions 109713 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r109713 | mmichelson | 2008-03-18 15:52:15 -0500 (Tue, 18 Mar 2008) | 12 lines This patch makes it so that all queue member status changes are handled through device state code. This removes several problems people were seeing where their queue members would get into an "unknown" state. Huge props go to atis on this one since he was the one who found the code section that was causing the problem and proposed the solution. I just wrote what he suggested :) (closes issue #12127) Reported by: atis Patches: 12127v3.patch uploaded by putnopvut (license 60) Tested by: atis, jvandal ........ ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@109716 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_queue.c150
1 files changed, 55 insertions, 95 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index ca109f9b6..b8a084491 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -675,63 +675,31 @@ struct statechange {
* Lock interface list find sc, iterate through each queues queue_member list for member to
* update state inside queues
*/
-static void *handle_statechange(struct statechange *sc)
+static int update_status(const char *interface, const int status)
{
- struct call_queue *q;
struct member *cur;
- struct ao2_iterator mem_iter;
- struct member_interface *curint;
- struct ao2_iterator queue_iter;
- char *loc;
- char *technology;
-
- technology = ast_strdupa(sc->dev);
- loc = strchr(technology, '/');
- if (loc) {
- *loc++ = '\0';
- } else {
- return NULL;
- }
-
- AST_LIST_LOCK(&interfaces);
- AST_LIST_TRAVERSE(&interfaces, curint, list) {
- char *interface;
- char *slash_pos;
- interface = ast_strdupa(curint->interface);
- if ((slash_pos = strchr(interface, '/')))
- if ((slash_pos = strchr(slash_pos + 1, '/')))
- *slash_pos = '\0';
-
- if (!strcasecmp(interface, sc->dev))
- break;
- }
- AST_LIST_UNLOCK(&interfaces);
-
- if (!curint) {
- ast_debug(3, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state));
- return NULL;
- }
+ struct ao2_iterator mem_iter, queue_iter;
+ struct call_queue *q;
- ast_debug(1, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
queue_iter = ao2_iterator_init(queues, 0);
while ((q = ao2_iterator_next(&queue_iter))) {
ao2_lock(q);
mem_iter = ao2_iterator_init(q->members, 0);
while ((cur = ao2_iterator_next(&mem_iter))) {
- char *interface;
+ char *tmp_interface;
char *slash_pos;
- interface = ast_strdupa(cur->state_interface);
+ tmp_interface = ast_strdupa(cur->state_interface);
if ((slash_pos = strchr(interface, '/')))
if ((slash_pos = strchr(slash_pos + 1, '/')))
*slash_pos = '\0';
- if (strcasecmp(sc->dev, interface)) {
+ if (strcasecmp(interface, tmp_interface)) {
ao2_ref(cur, -1);
continue;
}
- if (cur->status != sc->state) {
- cur->status = sc->state;
+ if (cur->status != status) {
+ cur->status = status;
if (q->maskmemberstatus) {
ao2_ref(cur, -1);
continue;
@@ -756,6 +724,49 @@ static void *handle_statechange(struct statechange *sc)
ao2_unlock(q);
}
+ return 0;
+}
+
+/*! \brief set a member's status based on device state of that member's interface*/
+static void *handle_statechange(struct statechange *sc)
+{
+ struct member_interface *curint;
+ char *loc;
+ char *technology;
+
+ technology = ast_strdupa(sc->dev);
+ loc = strchr(technology, '/');
+ if (loc) {
+ *loc++ = '\0';
+ } else {
+ return NULL;
+ }
+
+ AST_LIST_LOCK(&interfaces);
+ AST_LIST_TRAVERSE(&interfaces, curint, list) {
+ char *interface;
+ char *slash_pos;
+ interface = ast_strdupa(curint->interface);
+ if ((slash_pos = strchr(interface, '/')))
+ if ((slash_pos = strchr(slash_pos + 1, '/')))
+ *slash_pos = '\0';
+
+ if (!strcasecmp(interface, sc->dev))
+ break;
+ }
+ AST_LIST_UNLOCK(&interfaces);
+
+ if (!curint) {
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state));
+ return NULL;
+ }
+
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state));
+
+ update_status(sc->dev, sc->state);
+
return NULL;
}
@@ -1984,55 +1995,6 @@ static void hangupcalls(struct callattempt *outgoing, struct ast_channel *except
}
}
-static int update_status(struct call_queue *q, struct member *member, int status)
-{
- struct member *cur;
- struct ao2_iterator mem_iter;
-
- /* Since a reload could have taken place, we have to traverse the list to
- be sure it's still valid */
- ao2_lock(q);
- mem_iter = ao2_iterator_init(q->members, 0);
- while ((cur = ao2_iterator_next(&mem_iter))) {
- if (member != cur) {
- ao2_ref(cur, -1);
- continue;
- }
-
- cur->status = status;
- if (!q->maskmemberstatus) {
- manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
- "Queue: %s\r\n"
- "Location: %s\r\n"
- "MemberName: %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",
- q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static",
- cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused);
- }
- ao2_ref(cur, -1);
- }
- ao2_unlock(q);
- return 0;
-}
-
-static int update_dial_status(struct call_queue *q, struct member *member, int status)
-{
- if (status == AST_CAUSE_BUSY)
- status = AST_DEVICE_BUSY;
- else if (status == AST_CAUSE_UNREGISTERED)
- status = AST_DEVICE_UNAVAILABLE;
- else if (status == AST_CAUSE_NOSUCHDRIVER)
- status = AST_DEVICE_INVALID;
- else
- status = AST_DEVICE_UNKNOWN;
- return update_status(q, member, status);
-}
-
/*!
* \brief traverse all defined queues which have calls waiting and contain this member
* \retval 0 if no other queue has precedence (higher weight)
@@ -2189,7 +2151,8 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
if (qe->chan->cdr)
ast_cdr_busy(qe->chan->cdr);
tmp->stillgoing = 0;
- update_dial_status(qe->parent, tmp->member, status);
+
+ update_status(tmp->member->state_interface, ast_device_state(tmp->member->state_interface));
ao2_lock(qe->parent);
qe->parent->rrpos++;
@@ -2199,8 +2162,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
(*busies)++;
return 0;
- } else if (status != tmp->oldstatus)
- update_dial_status(qe->parent, tmp->member, status);
+ }
tmp->chan->appl = "AppQueue";
tmp->chan->data = "(Outgoing Line)";
@@ -2567,8 +2529,6 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
/* Setup parameters */
o->chan = ast_request(tech, in->nativeformats, stuff, &status);
- if (status != o->oldstatus)
- update_dial_status(qe->parent, o->member, status);
if (!o->chan) {
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
o->stillgoing = 0;
@@ -3281,8 +3241,8 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
orig = to;
++qe->pending;
- ring_one(qe, outgoing, &numbusies);
ao2_unlock(qe->parent);
+ ring_one(qe, outgoing, &numbusies);
if (use_weight)
ao2_unlock(queues);
lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);