dect
/
asterisk
Archived
13
0
Fork 0

Commit "distrotech" app_queue changes to Trunk

* Added general option negative_penalty_invalid default off. when set
   members are seen as invalid/logged out when there penalty is negative.  
   for realtime members when set remove from queue will set penalty to -1.  
 * Added queue option autopausedelay when autopause is enabled it will be
   delayed for this number of seconds since last successful call if there
   was no prior call the agent will be autopaused immediately.
 * Added member option ignorebusy this when set and ringinuse is not   
   will allow per member control of multiple calls as ringinuse does for
   the Queue.
  
 - Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members
 - QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty.

(closes issue ASTERISK-17421)
(closes issue ASTERISK-17391)
Reported by: irroot
Tested by: irroot, jrose
Review: https://reviewboard.asterisk.org/r/1119/


git-svn-id: http://svn.digium.com/svn/asterisk/trunk@325483 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
irroot 2011-06-29 06:39:26 +00:00
parent 8cd91d244e
commit f4e69acdf3
4 changed files with 290 additions and 94 deletions

View File

@ -439,6 +439,15 @@ Queue changes
supports sending the event arguments to 5 individual fields, although it
will fallback to the previous data definition, if the new table layout is
not found.
* Added general option negative_penalty_invalid default off. when set
members are seen as invalid/logged out when there penalty is negative.
for realtime members when set remove from queue will set penalty to -1.
* Added queue option autopausedelay when autopause is enabled it will be
delayed for this number of seconds since last successful call if there
was no prior call the agent will be autopaused immediately.
* Added member option ignorebusy this when set and ringinuse is not
will allow per member control of multiple calls as ringinuse does for
the Queue.
mISDN channel driver (chan_misdn) changes
----------------------------------------

View File

@ -50,5 +50,9 @@ pbx_lua:
- the autoservice now defaults to being on by default
- autoservice_start() and autoservice_start() no longer return a value.
Queue:
- Mark QUEUE_MEMBER_PENALTY Deprecated it never worked for realtime members
- QUEUE_MEMBER is now R/W supporting setting paused, ignorebusy and penalty.
===========================================================
===========================================================

View File

@ -521,11 +521,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<enum name="count">
<para>Returns the total number of members for the specified queue.</para>
</enum>
<enum name="penalty">
<para>Gets or sets queue member penalty.</para>
</enum>
<enum name="paused">
<para>Gets or sets queue member paused status.</para>
</enum>
<enum name="ignorebusy">
<para>Gets or sets queue member ignorebusy.</para>
</enum>
</enumlist>
</parameter>
<parameter name="interface" required="false" />
</syntax>
<description>
<para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
<para>Allows access to queue counts [R] and member information [R/W].</para>
<para>
<replaceable>queuename</replaceable> is required for all operations
<replaceable>interface</replaceable> is required for all member operations.
</para>
</description>
<see-also>
<ref type="application">Queue</ref>
@ -658,6 +672,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</syntax>
<description>
<para>Gets or sets queue members penalty.</para>
<warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
</description>
<see-also>
<ref type="application">Queue</ref>
@ -934,6 +949,9 @@ static struct ast_event_sub *device_state_sub;
/*! \brief queues.conf [general] option */
static int update_cdr = 0;
/*! \brief queues.conf [general] option */
static int negative_penalty_invalid = 0;
enum queue_result {
QUEUE_UNKNOWN = 0,
QUEUE_TIMEOUT = 1,
@ -1043,6 +1061,7 @@ struct member {
unsigned int dead:1; /*!< Used to detect members deleted in realtime */
unsigned int delme:1; /*!< Flag to delete entry on reload */
char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
unsigned int ignorebusy:1; /*!< Flag to ignore member if the status is not available */
};
enum empty_conditions {
@ -1160,6 +1179,7 @@ struct call_queue {
int timeout; /*!< How long to wait for an answer */
int weight; /*!< Respective weight */
int autopause; /*!< Auto pause queue members if they fail to answer */
int autopausedelay; /*!< Delay auto pause for autopausedelay seconds since last call */
int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
/* Queue strategy things */
@ -1190,9 +1210,10 @@ static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
static struct ao2_container *queues;
static void update_realtime_members(struct call_queue *q);
static struct member *interface_exists(struct call_queue *q, const char *interface);
static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
/*! \brief sets the QUEUESTATUS channel variable */
static void set_queue_result(struct ast_channel *chan, enum queue_result res)
{
@ -1698,6 +1719,7 @@ static void init_queue(struct call_queue *q)
q->numperiodicannounce = 0;
q->autopause = QUEUE_AUTOPAUSE_OFF;
q->timeoutpriority = TIMEOUT_PRIORITY_APP;
q->autopausedelay = 0;
if (!q->members) {
if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED)
/* linear strategy depends on order, so we have to place all members in a single bucket */
@ -2003,6 +2025,8 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
q->montype = 1;
} else if (!strcasecmp(param, "autopause")) {
q->autopause = autopause2int(val);
} else if (!strcasecmp(param, "autopausedelay")) {
q->autopausedelay = atoi(val);
} else if (!strcasecmp(param, "maxlen")) {
q->maxlen = atoi(val);
if (q->maxlen < 0)
@ -2081,7 +2105,9 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
int penalty = 0;
int paused = 0;
int found = 0;
int ignorebusy = 0;
const char *config_val;
const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
@ -2095,8 +2121,11 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
if (penalty_str) {
penalty = atoi(penalty_str);
if (penalty < 0)
if ((penalty < 0) && negative_penalty_invalid) {
return;
} else if (penalty < 0) {
penalty = 0;
}
}
if (paused_str) {
@ -2105,31 +2134,39 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
paused = 0;
}
/* Find member by realtime uniqueid and update */
mem_iter = ao2_iterator_init(q->members, 0);
while ((m = ao2_iterator_next(&mem_iter))) {
if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
m->dead = 0; /* Do not delete this one. */
ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
if (paused_str)
m->paused = paused;
if (strcasecmp(state_interface, m->state_interface)) {
ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
}
m->penalty = penalty;
found = 1;
ao2_ref(m, -1);
break;
}
ao2_ref(m, -1);
}
if ((config_val = ast_variable_retrieve(member_config, interface, "ignorebusy"))) {
ignorebusy = ast_true(config_val);
} else {
ignorebusy = 1;
}
/* Find member by realtime uniqueid and update */
mem_iter = ao2_iterator_init(q->members, 0);
while ((m = ao2_iterator_next(&mem_iter))) {
if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
m->dead = 0; /* Do not delete this one. */
ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
if (paused_str)
m->paused = paused;
if (strcasecmp(state_interface, m->state_interface)) {
ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
}
m->penalty = penalty;
m->ignorebusy = ignorebusy;
found = 1;
ao2_ref(m, -1);
break;
}
ao2_ref(m, -1);
}
ao2_iterator_destroy(&mem_iter);
/* Create a new member */
if (!found) {
/* Create a new member */
if (!found) {
if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
m->dead = 0;
m->realtime = 1;
m->ignorebusy = ignorebusy;
ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", "");
ao2_link(q->members, m);
@ -2873,16 +2910,24 @@ static int num_available_members(struct call_queue *q)
mem_iter = ao2_iterator_init(q->members, 0);
while ((mem = ao2_iterator_next(&mem_iter))) {
switch (mem->status) {
case AST_DEVICE_INUSE:
if (!q->ringinuse)
case AST_DEVICE_INVALID:
case AST_DEVICE_UNAVAILABLE:
break;
case AST_DEVICE_INUSE:
case AST_DEVICE_BUSY:
case AST_DEVICE_RINGING:
case AST_DEVICE_RINGINUSE:
case AST_DEVICE_ONHOLD:
if ((!q->ringinuse) || (!mem->ignorebusy)) {
break;
}
/* else fall through */
case AST_DEVICE_NOT_INUSE:
case AST_DEVICE_UNKNOWN:
if (!mem->paused) {
avl++;
}
break;
/* else fall through */
case AST_DEVICE_NOT_INUSE:
case AST_DEVICE_UNKNOWN:
if (!mem->paused) {
avl++;
}
break;
}
ao2_ref(mem, -1);
@ -3010,38 +3055,54 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
char tech[256];
char *location;
const char *macrocontext, *macroexten;
enum ast_device_state newstate;
/* on entry here, we know that tmp->chan == NULL */
if (tmp->member->paused) {
ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
}
tmp->stillgoing = 0;
return 0;
}
if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
(!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
(tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
}
tmp->stillgoing = 0;
(*busies)++;
return 0;
}
if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
if (qe->chan->cdr)
ast_cdr_busy(qe->chan->cdr);
tmp->stillgoing = 0;
return 0;
if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
if ((tmp->member->status == AST_DEVICE_UNKNOWN) || (tmp->member->status == AST_DEVICE_NOT_INUSE)) {
newstate = ast_parse_device_state(tmp->member->interface);
if (newstate != tmp->member->status) {
ast_log(LOG_ERROR, "Found a channel matching iterface %s while status was %i changed to %i\n",
tmp->member->interface, tmp->member->status, newstate);
update_status(qe->parent, tmp->member, newstate);
}
}
if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
}
tmp->stillgoing = 0;
return 0;
}
}
if (tmp->member->paused) {
ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
if (qe->chan->cdr)
ast_cdr_busy(qe->chan->cdr);
tmp->stillgoing = 0;
return 0;
}
if (use_weight && compare_weight(qe->parent,tmp->member)) {
ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
}
tmp->stillgoing = 0;
(*busies)++;
return 0;
@ -3056,8 +3117,9 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
/* Request the peer */
tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
if (!tmp->chan) { /* If we can't, just go on to the next call */
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_cdr_busy(qe->chan->cdr);
}
tmp->stillgoing = 0;
ao2_lock(qe->parent);
@ -3396,6 +3458,18 @@ static void rna(int rnatime, struct queue_ent *qe, char *interface, char *member
}
ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && pause) {
if (qe->parent->autopausedelay > 0) {
struct member *mem;
ao2_lock(qe->parent);
if ((mem = interface_exists(qe->parent, interface))) {
time_t idletime = time(&idletime)-mem->lastcall;
if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
ao2_unlock(qe->parent);
return;
}
}
ao2_unlock(qe->parent);
}
if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
@ -4707,8 +4781,9 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
else
ast_moh_stop(qe->chan);
/* If appropriate, log that we have a destination channel */
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_cdr_setdestchan(qe->chan->cdr, peer->name);
}
/* Make sure channels are compatible */
res = ast_channel_make_compatible(qe->chan, peer);
if (res < 0) {
@ -4788,10 +4863,11 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
if (mixmonapp) {
ast_debug(1, "Starting MixMonitor as requested.\n");
if (!monitorfilename) {
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid));
else
} else {
snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
}
} else {
const char *m = monitorfilename;
for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
@ -4858,12 +4934,13 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce
ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
/* We purposely lock the CDR so that pbx_exec does not update the application data */
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_set_flag(qe->chan->cdr, AST_CDR_FLAG_LOCKED);
}
pbx_exec(qe->chan, mixmonapp, mixmonargs);
if (qe->chan->cdr)
if (qe->chan->cdr) {
ast_clear_flag(qe->chan->cdr, AST_CDR_FLAG_LOCKED);
}
} else {
ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
}
@ -5180,7 +5257,10 @@ static int remove_from_queue(const char *queuename, const char *interface)
ao2_lock(q);
if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
/* XXX future changes should beware of this assumption!! */
if (!mem->dynamic) {
/*Change Penalty on realtime users*/
if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid) && negative_penalty_invalid) {
update_realtime_member_field(mem, q->name, "penalty", "-1");
} else if (!mem->dynamic) {
ao2_ref(mem, -1);
ao2_unlock(q);
queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
@ -5355,35 +5435,34 @@ static int set_member_penalty(const char *queuename, const char *interface, int
int foundinterface = 0, foundqueue = 0;
struct call_queue *q;
struct member *mem;
struct ao2_iterator queue_iter;
char rtpenalty[80];
if (penalty < 0) {
if (penalty < 0 && !negative_penalty_invalid) {
ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
return RESULT_FAILURE;
}
queue_iter = ao2_iterator_init(queues, 0);
while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
if ((q = load_realtime_queue(queuename))) {
foundqueue++;
ao2_lock(q);
if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
foundqueue++;
if ((mem = interface_exists(q, interface))) {
foundinterface++;
if ((mem = interface_exists(q, interface))) {
foundinterface++;
if (!mem->realtime) {
mem->penalty = penalty;
ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
"Queue: %s\r\n"
"Location: %s\r\n"
"Penalty: %d\r\n",
q->name, mem->interface, penalty);
ao2_ref(mem, -1);
} else {
sprintf(rtpenalty,"%i", penalty);
update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
}
ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
"Queue: %s\r\n"
"Location: %s\r\n"
"Penalty: %d\r\n",
q->name, mem->interface, penalty);
ao2_ref(mem, -1);
}
ao2_unlock(q);
queue_t_unref(q, "Done with iterator");
}
ao2_iterator_destroy(&queue_iter);
if (foundinterface) {
return RESULT_SUCCESS;
@ -6157,31 +6236,37 @@ static int queue_function_exists(struct ast_channel *chan, const char *cmd, char
return 0;
}
/*!
/*!
* \brief Get number either busy / free / ready or total members of a specific queue
* \retval number of members (busy / free / ready / total)
* \brief Get or set member properties penalty / paused / ignorebusy
* \retval number of members (busy / free / ready / total) or member info (penalty / paused / ignorebusy)
* \retval -1 on error
*/
static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
int count = 0;
struct member *m;
struct ao2_iterator mem_iter;
struct call_queue *q;
char *option;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(queuename);
AST_APP_ARG(option);
AST_APP_ARG(interface);
);
/* Make sure the returned value on error is zero length string. */
buf[0] = '\0';
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
return -1;
}
if ((option = strchr(data, ',')))
*option++ = '\0';
else
option = "logged";
if ((q = load_realtime_queue(data))) {
AST_STANDARD_APP_ARGS(args, data);
if ((q = load_realtime_queue(args.queuename))) {
ao2_lock(q);
if (!strcasecmp(option, "logged")) {
if (!strcasecmp(args.option, "logged")) {
mem_iter = ao2_iterator_init(q->members, 0);
while ((m = ao2_iterator_next(&mem_iter))) {
/* Count the agents who are logged in and presently answering calls */
@ -6191,7 +6276,7 @@ static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *d
ao2_ref(m, -1);
}
ao2_iterator_destroy(&mem_iter);
} else if (!strcasecmp(option, "free")) {
} else if (!strcasecmp(args.option, "free")) {
mem_iter = ao2_iterator_init(q->members, 0);
while ((m = ao2_iterator_next(&mem_iter))) {
/* Count the agents who are logged in and presently answering calls */
@ -6201,7 +6286,7 @@ static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *d
ao2_ref(m, -1);
}
ao2_iterator_destroy(&mem_iter);
} else if (!strcasecmp(option, "ready")) {
} else if (!strcasecmp(args.option, "ready")) {
time_t now;
time(&now);
mem_iter = ao2_iterator_init(q->members, 0);
@ -6214,22 +6299,104 @@ static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *d
ao2_ref(m, -1);
}
ao2_iterator_destroy(&mem_iter);
} else /* must be "count" */
} else if (!strcasecmp(args.option, "count") || ast_strlen_zero(args.option)) {
count = q->membercount;
} else if (!strcasecmp(args.option, "penalty") && !ast_strlen_zero(args.interface) &&
((m = interface_exists(q, args.interface)))) {
count = m->penalty;
} else if (!strcasecmp(args.option, "paused") && !ast_strlen_zero(args.interface) &&
((m = interface_exists(q, args.interface)))) {
count = m->paused;
} else if (!strcasecmp(args.option, "ignorebusy") && !ast_strlen_zero(args.interface) &&
((m = interface_exists(q, args.interface)))) {
count = m->ignorebusy;
}
ao2_unlock(q);
queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
} else
ast_log(LOG_WARNING, "queue %s was not found\n", data);
} else {
ast_log(LOG_WARNING, "queue %s was not found\n", args.queuename);
}
snprintf(buf, len, "%d", count);
return 0;
}
/*!
/*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ignorebusy. */
static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{
int memvalue;
struct call_queue *q;
struct member *m;
char rtvalue[80];
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(queuename);
AST_APP_ARG(option);
AST_APP_ARG(interface);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER(<queuename>,<option>,<interface>)\n");
return -1;
}
AST_STANDARD_APP_ARGS(args, data);
if (args.argc < 3) {
ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
return -1;
}
if (ast_strlen_zero(args.interface) && ast_strlen_zero(args.option)) {
ast_log (LOG_ERROR, "<interface> and <option> parameter's can't be null\n");
return -1;
}
memvalue = atoi(value);
if (!strcasecmp(args.option, "penalty")) {
/* if queuename = NULL then penalty will be set for interface in all the queues.*/
if (set_member_penalty(args.queuename, args.interface, memvalue)) {
ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
return -1;
}
} else if ((q = load_realtime_queue(args.queuename))) {
ao2_lock(q);
if ((m = interface_exists(q, args.interface))) {
sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
if (!strcasecmp(args.option, "paused")) {
if (m->realtime) {
update_realtime_member_field(m, q->name, args.option, rtvalue);
} else {
m->paused = (memvalue <= 0) ? 0 : 1;
}
} else if (!strcasecmp(args.option, "ignorebusy")) {
if (m->realtime) {
update_realtime_member_field(m, q->name, args.option, rtvalue);
} else {
m->ignorebusy = (memvalue <= 0) ? 0 : 1;
}
} else {
ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ignorebusy are valid\n");
return -1;
}
} else {
ast_log(LOG_ERROR, "Invalid interface or queue\n");
return -1;
}
ao2_unlock(q);
} else {
ast_log(LOG_ERROR, "Invalid queue\n");
return -1;
}
return 0;
}
/*!
* \brief Get the total number of members in a specific queue (Deprecated)
* \retval number of members
* \retval -1 on error
* \retval number of members
* \retval -1 on error
*/
static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
@ -6435,7 +6602,8 @@ static struct ast_custom_function queuevar_function = {
static struct ast_custom_function queuemembercount_function = {
.name = "QUEUE_MEMBER",
.read = queue_function_qac,
.read = queue_function_mem_read,
.write = queue_function_mem_write,
};
static struct ast_custom_function queuemembercount_dep = {
@ -6517,8 +6685,9 @@ static void queue_set_global_params(struct ast_config *cfg)
{
const char *general_val = NULL;
queue_persistent_members = 0;
if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers")))
if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) {
queue_persistent_members = ast_true(general_val);
}
autofill_default = 0;
if ((general_val = ast_variable_retrieve(cfg, "general", "autofill")))
autofill_default = ast_true(general_val);
@ -6533,6 +6702,9 @@ static void queue_set_global_params(struct ast_config *cfg)
shared_lastcall = 0;
if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall")))
shared_lastcall = ast_true(general_val);
negative_penalty_invalid = 0;
if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid")))
negative_penalty_invalid = ast_true(general_val);
}
/*! \brief reload information pertaining to a single member

View File

@ -61,6 +61,10 @@ monitor-type = MixMonitor
;
;shared_lastcall=no
;
; Negative_penalty_invalid will treat members with a negative penalty as logged off
;
;negative_penalty_invalid = no
;
;[markq]
;
; A sample call queue
@ -196,6 +200,10 @@ monitor-type = MixMonitor
; all: Memeber will be paused in all queues he/she is a member
;autopause=yes
;
; Autopausedelay delay autopause for autopausedelay seconds from the
; last call if a member has not taken a call the delay has no effect.
;autopausedelay=60
;
; Maximum number of people waiting in the queue (0 for unlimited)
;
;maxlen = 0
@ -459,6 +467,9 @@ monitor-type = MixMonitor
; uncomment this option. (Note: only the SIP channel driver currently is able
; to report 'in use'.)
;
; A member can have the ignorebusy flag set or unset when ringinuse is set to
; allow a per member control.
;
; ringinuse = no
;
; If you wish to have a delay before the member is connected to the caller (or