[asterisk-commits] app queue: Add member flag "in call" to prevent reading wron... (asterisk[11])
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jan 12 06:05:17 CST 2016
Joshua Colp has submitted this change and it was merged.
Change subject: app_queue: Add member flag "in_call" to prevent reading wrong lastcall time
......................................................................
app_queue: Add member flag "in_call" to prevent reading wrong lastcall time
Member lastcall time is updated later than member status. There was chance to
check wrapuptime for available member with wrong (old) lastcall time.
New boolean flag "in_call" is set to true right before connecting call, and
reset to false after update of lastcall time. Members with "in_call" set to true
are treat as unavailable.
ASTERISK-19820 #close
Change-Id: I1923230cf9859ee51563a8ed420a0628b4d2e500
---
M apps/app_queue.c
1 file changed, 60 insertions(+), 3 deletions(-)
Approvals:
Kevin Harwell: Looks good to me, but someone else must approve
Anonymous Coward #1000019: Verified
Joshua Colp: Looks good to me, approved
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 981e49f..78ac4c5 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -1208,6 +1208,7 @@
int paused; /*!< Are we paused (not accepting calls)? */
int queuepos; /*!< In what order (pertains to certain strategies) should this member be called? */
time_t lastcall; /*!< When last successful call was hungup */
+ unsigned int in_call:1; /*!< True if member is still in call. (so lastcall is not actual) */
struct call_queue *lastqueue; /*!< Last queue we received a call */
unsigned int dead:1; /*!< Used to detect members deleted in realtime */
unsigned int delme:1; /*!< Flag to delete entry on reload */
@@ -1647,6 +1648,10 @@
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) && member->in_call && q->wrapuptime) {
+ ast_debug(4, "%s is unavailable because still in call, so we can`t check "
+ "wrapuptime (%d)\n", member->membername, q->wrapuptime);
+ break;
} else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
break;
@@ -1721,6 +1726,13 @@
<parameter name="LastCall">
<para>The time this member last took call, expressed in seconds since 00:00, Jan 1, 1970 UTC.</para>
</parameter>
+ <parameter name="InCall">
+ <para>Set to 1 if member is in call. Set to 0 after LastCall time is updated.</para>
+ <enumlist>
+ <enum name="0"/>
+ <enum name="1"/>
+ </enumlist>
+ </parameter>
<parameter name="Status">
<para>The numeric device state status of the queue member.</para>
<enumlist>
@@ -1753,10 +1765,11 @@
"Penalty: %d\r\n"
"CallsTaken: %d\r\n"
"LastCall: %d\r\n"
+ "InCall: %d\r\n"
"Status: %d\r\n"
"Paused: %d\r\n",
q->name, m->interface, m->membername, m->state_interface, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
- m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
+ m->penalty, m->calls, (int)m->lastcall, m->in_call, m->status, m->paused
);
return 0;
@@ -1793,6 +1806,9 @@
}
/* Let wrapuptimes override device state availability */
+ if (q->wrapuptime && mem->in_call) {
+ available = 0; /* member is still in call, cant check wrapuptime to lastcall time */
+ }
if (mem->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < mem->lastcall)) {
available = 0;
}
@@ -2158,6 +2174,7 @@
while ((mem = ao2_iterator_next(&mem_iter))) {
mem->calls = 0;
mem->lastcall = 0;
+ mem->in_call = 0;
ao2_ref(mem, -1);
}
ao2_iterator_destroy(&mem_iter);
@@ -3624,6 +3641,12 @@
return 0;
}
+ if (call->member->in_call && call->lastqueue->wrapuptime) {
+ ast_debug(1, "%s is in call, so not available (wrapuptime %d)\n",
+ call->interface, call->lastqueue->wrapuptime);
+ return 0;
+ }
+
if ((call->lastqueue && call->lastqueue->wrapuptime && (time(NULL) - call->lastcall < call->lastqueue->wrapuptime))
|| (!call->lastqueue && qe->parent->wrapuptime && (time(NULL) - call->lastcall < qe->parent->wrapuptime))) {
ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
@@ -4903,6 +4926,9 @@
time(&mem->lastcall);
mem->calls++;
mem->lastqueue = q;
+ mem->in_call = 0;
+ ast_debug(4, "Marked member %s as NOT in_call. Lastcall time: %ld \n",
+ mem->membername, (long)mem->lastcall);
ao2_ref(mem, -1);
}
ao2_unlock(qtmp);
@@ -4914,6 +4940,9 @@
time(&member->lastcall);
member->calls++;
member->lastqueue = q;
+ member->in_call = 0;
+ ast_debug(4, "Marked member %s as NOT in_call. Lastcall time: %ld \n",
+ member->membername, (long)member->lastcall);
ao2_unlock(q);
}
ao2_lock(q);
@@ -5273,6 +5302,9 @@
struct ao2_iterator memi;
struct ast_datastore *datastore, *transfer_ds;
struct queue_end_bridge *queue_end_bridge = NULL;
+ struct ao2_iterator queue_iter; /* to iterate through all queues (for shared_lastcall)*/
+ struct member *mem;
+ struct call_queue *queuetmp;
ast_channel_lock(qe->chan);
datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
@@ -5905,6 +5937,28 @@
}
}
qe->handled++;
+
+ /** mark member as "in_call" in all queues */
+ if (shared_lastcall) {
+ queue_iter = ao2_iterator_init(queues, 0);
+ while ((queuetmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
+ ao2_lock(queuetmp);
+ if ((mem = ao2_find(queuetmp->members, member, OBJ_POINTER))) {
+ mem->in_call = 1;
+ ast_debug(4, "Marked member %s as in_call \n", mem->membername);
+ ao2_ref(mem, -1);
+ }
+ ao2_unlock(queuetmp);
+ queue_t_unref(queuetmp, "Done with iterator");
+ }
+ ao2_iterator_destroy(&queue_iter);
+ } else {
+ ao2_lock(qe->parent);
+ member->in_call = 1;
+ ast_debug(4, "Marked member %s as in_call \n", member->membername);
+ ao2_unlock(qe->parent);
+ }
+
ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) (time(NULL) - qe->start), ast_channel_uniqueid(peer),
(long)(orig - to > 0 ? (orig - to) / 1000 : 0));
@@ -8455,10 +8509,11 @@
ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
- ast_str_append(&out, 0, "%s%s%s (%s)",
+ ast_str_append(&out, 0, "%s%s%s%s (%s)",
mem->dynamic ? " (dynamic)" : "",
mem->realtime ? " (realtime)" : "",
mem->paused ? " (paused)" : "",
+ mem->in_call ? " (in call)" : "",
ast_devstate2str(mem->status));
if (mem->calls) {
ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
@@ -8817,12 +8872,14 @@
"Penalty: %d\r\n"
"CallsTaken: %d\r\n"
"LastCall: %d\r\n"
+ "IsInCall: %d\r\n"
"Status: %d\r\n"
"Paused: %d\r\n"
"%s"
"\r\n",
q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
- mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
+ mem->penalty, mem->calls, (int)mem->lastcall, mem->in_call, mem->status,
+ mem->paused, idText);
}
ao2_ref(mem, -1);
}
--
To view, visit https://gerrit.asterisk.org/1881
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I1923230cf9859ee51563a8ed420a0628b4d2e500
Gerrit-PatchSet: 3
Gerrit-Project: asterisk
Gerrit-Branch: 11
Gerrit-Owner: Martin Tomec <tomec.martin at gmail.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
More information about the asterisk-commits
mailing list