summaryrefslogtreecommitdiff
path: root/apps/app_queue.c
diff options
context:
space:
mode:
authorJonathan Rose <jrose@digium.com>2012-05-18 19:39:54 +0000
committerJonathan Rose <jrose@digium.com>2012-05-18 19:39:54 +0000
commitec3b8a1f2799acf4a04b95e12b10923181ae8207 (patch)
tree14478d8172aa13faa593f24f562a8951c7dce0cc /apps/app_queue.c
parent11348736af2097be6ca9d99f160ead3e85e44ec2 (diff)
app_queue: Per Member ringinuse option and deprecation of ignorebusy
Adds a number of methods for controlling the setting of 'ringinuse' which is basically the same concept as the old ignorebusy setting, only now the per member setting always controls whether or not the member is actually ringed while in use. A CLI command and a manager action have been added to change a given queue member's ringinuse option while Asterisk is running and the an argument has been added for adding members with deliberately set ringinuse in queues.conf Some effort has been made to ensure compatability with dialplans and databases still referring to 'ignorebusy'. (issue ASTERISK-19536) reported by: Philippe Lindheimer Review: https://reviewboard.asterisk.org/r/1919/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@367080 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_queue.c')
-rw-r--r--apps/app_queue.c313
1 files changed, 267 insertions, 46 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c
index a566c9aed..ae82bd936 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -552,8 +552,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<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 name="ringinuse">
+ <para>Gets or sets queue member ringinuse.</para>
</enum>
</enumlist>
</parameter>
@@ -817,6 +817,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<description>
</description>
</manager>
+
+ <manager name="QueueMemberRingInUse" language="en_US">
+ <synopsis>
+ Set the ringinuse value for a queue member.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Interface" required="true" />
+ <parameter name="RingInUse" required="true" />
+ <parameter name="Queue" />
+ </syntax>
+ <description>
+ </description>
+ </manager>
+
<manager name="QueueRule" language="en_US">
<synopsis>
Queue Rules.
@@ -1032,6 +1047,9 @@ static int log_membername_as_agent = 0;
/*! \brief queues.conf [general] option */
static int check_state_unknown = 0;
+/*! \brief name of the ringinuse field in the realtime database */
+static char *realtime_ringinuse_field;
+
enum queue_result {
QUEUE_UNKNOWN = 0,
QUEUE_TIMEOUT = 1,
@@ -1141,7 +1159,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 */
+ unsigned int ringinuse:1; /*!< Flag to ring queue members even if their status is 'inuse' */
};
enum empty_conditions {
@@ -1155,6 +1173,11 @@ enum empty_conditions {
QUEUE_EMPTY_WRAPUP = (1 << 7),
};
+enum member_properties {
+ MEMBER_PENALTY = 0,
+ MEMBER_RINGINUSE = 1,
+};
+
/* values used in multi-bit flags in call_queue */
#define ANNOUNCEHOLDTIME_ALWAYS 1
#define ANNOUNCEHOLDTIME_ONCE 2
@@ -1721,12 +1744,12 @@ static int get_queue_member_status(struct member *cur)
}
/*! \brief allocate space for new queue member and set fields based on parameters passed */
-static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface)
+static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
{
struct member *cur;
if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
- cur->ignorebusy = 1;
+ cur->ringinuse = ringinuse;
cur->penalty = penalty;
cur->paused = paused;
ast_copy_string(cur->interface, interface, sizeof(cur->interface));
@@ -2252,7 +2275,7 @@ 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;
+ int ringinuse = q->ringinuse;
const char *config_val;
const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
@@ -2282,10 +2305,14 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
}
}
- if ((config_val = ast_variable_retrieve(member_config, interface, "ignorebusy"))) {
- ignorebusy = ast_true(config_val);
- } else {
- ignorebusy = 1;
+ if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) {
+ if (ast_true(config_val)) {
+ ringinuse = 1;
+ } else if (ast_false(config_val)) {
+ ringinuse = 0;
+ } else {
+ ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
+ }
}
/* Find member by realtime uniqueid and update */
@@ -2301,7 +2328,7 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
}
m->penalty = penalty;
- m->ignorebusy = ignorebusy;
+ m->ringinuse = ringinuse;
found = 1;
ao2_ref(m, -1);
break;
@@ -2312,10 +2339,9 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc
/* Create a new member */
if (!found) {
- if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
+ if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
m->dead = 0;
m->realtime = 1;
- m->ignorebusy = ignorebusy;
ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
if (!log_membername_as_agent) {
ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
@@ -3104,7 +3130,7 @@ static int num_available_members(struct call_queue *q)
case AST_DEVICE_RINGING:
case AST_DEVICE_RINGINUSE:
case AST_DEVICE_ONHOLD:
- if ((!q->ringinuse) || (!mem->ignorebusy)) {
+ if (!mem->ringinuse) {
break;
}
/* else fall through */
@@ -3265,7 +3291,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
return 0;
}
- if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
+ if (tmp->member->ringinuse) {
if (check_state_unknown && (tmp->member->status == AST_DEVICE_UNKNOWN)) {
newstate = ast_device_state(tmp->member->interface);
if (newstate != tmp->member->status) {
@@ -5560,7 +5586,8 @@ static int add_to_queue(const char *queuename, const char *interface, const char
ao2_lock(q);
if ((old_member = interface_exists(q, interface)) == NULL) {
- if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface))) {
+ if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse))) {
+ new_member->ringinuse = q->ringinuse;
new_member->dynamic = 1;
ao2_link(q->members, new_member);
manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
@@ -5714,23 +5741,71 @@ static int set_member_penalty_help_members(struct call_queue *q, const char *int
return foundinterface;
}
+static int set_member_ringinuse_help_members(struct call_queue *q, const char *interface, int ringinuse)
+{
+ struct member *mem;
+ int foundinterface = 0;
+ char rtringinuse[80];
+
+ ao2_lock(q);
+ if ((mem = interface_exists(q, interface))) {
+ foundinterface++;
+ if (!mem->realtime) {
+ mem->ringinuse = ringinuse;
+ } else {
+ sprintf(rtringinuse, "%i", ringinuse);
+ update_realtime_member_field(mem, q->name, realtime_ringinuse_field, rtringinuse);
+ }
+ ast_queue_log(q->name, "NONE", interface, "RINGINUSE", "%d", ringinuse);
+ manager_event(EVENT_FLAG_AGENT, "QueueMemberRinginuse",
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "Ringinuse: %d\r\n",
+ q->name, mem->interface, ringinuse);
+ ao2_ref(mem, -1);
+ }
+ ao2_unlock(q);
+
+ return foundinterface;
+}
+
+static int set_member_value_help_members(struct call_queue *q, const char *interface, int property, int value)
+{
+ switch(property) {
+ case MEMBER_PENALTY:
+ return set_member_penalty_help_members(q, interface, value);
+
+ case MEMBER_RINGINUSE:
+ return set_member_ringinuse_help_members(q, interface, value);
+
+ default:
+ ast_log(LOG_ERROR, "Attempted to set invalid property\n");
+ return 0;
+ }
+}
+
/*!
* \internal
* \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
- * \param[in] queuename If specified, only act on a member if it belongs to this queue
+ * \param[in] queuename If specified, only act on a mem`ber if it belongs to this queue
* \param[in] interface Interface of queue member(s) having priority set.
+ * \param[in] property Which queue property is being set
* \param[in] penalty Value penalty is being changed to for each member
*/
-static int set_member_penalty(const char *queuename, const char *interface, int penalty)
+static int set_member_value(const char *queuename, const char *interface, int property, int value)
{
int foundinterface = 0, foundqueue = 0;
struct call_queue *q;
struct ast_config *queue_config = NULL;
struct ao2_iterator queue_iter;
- if (penalty < 0 && !negative_penalty_invalid) {
- ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
- return RESULT_FAILURE;
+ /* property dependent restrictions on values should be checked in this switch */
+ switch (property) {
+ case MEMBER_PENALTY:
+ if (value < 0 && !negative_penalty_invalid) {
+ ast_log(LOG_ERROR, "Invalid penalty (%d)\n", value);
+ return RESULT_FAILURE;
+ }
}
if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */
@@ -5743,7 +5818,7 @@ static int set_member_penalty(const char *queuename, const char *interface, int
name = ast_category_browse(queue_config, name)) {
if ((q = find_load_queue_rt_friendly(name))) {
foundqueue++;
- foundinterface += set_member_penalty_help_members(q, interface, penalty);
+ foundinterface += set_member_value_help_members(q, interface, property, value);
}
}
}
@@ -5753,13 +5828,13 @@ static int set_member_penalty(const char *queuename, const char *interface, int
queue_iter = ao2_iterator_init(queues, 0);
while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
foundqueue++;
- foundinterface += set_member_penalty_help_members(q, interface, penalty);
+ foundinterface += set_member_value_help_members(q, interface, property, value);
}
ao2_iterator_destroy(&queue_iter);
} else { /* We actually have a queuename, so we can just act on the single queue. */
if ((q = find_load_queue_rt_friendly(queuename))) {
foundqueue++;
- foundinterface += set_member_penalty_help_members(q, interface, penalty);
+ foundinterface += set_member_value_help_members(q, interface, property, value);
}
}
@@ -6569,8 +6644,8 @@ static int queue_function_exists(struct ast_channel *chan, const char *cmd, char
/*!
* \brief Get number either busy / free / ready or total members of a specific queue
- * \brief Get or set member properties penalty / paused / ignorebusy
- * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ignorebusy)
+ * \brief Get or set member properties penalty / paused / ringinuse
+ * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ringinuse)
* \retval -1 on error
*/
static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
@@ -6645,13 +6720,14 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
((m = interface_exists(q, args.interface)))) {
count = m->paused;
ao2_ref(m, -1);
- } else if (!strcasecmp(args.option, "ignorebusy") && !ast_strlen_zero(args.interface) &&
+ } else if ( (!strcasecmp(args.option, "ignorebusy") || !strcasecmp(args.option, "ringinuse")) &&
+ !ast_strlen_zero(args.interface) &&
((m = interface_exists(q, args.interface)))) {
- count = m->ignorebusy;
+ count = m->ringinuse;
ao2_ref(m, -1);
} else {
ast_log(LOG_ERROR, "Unknown option %s provided to %s, valid values are: "
- "logged, free, ready, count, penalty, paused, ignorebusy\n", args.option, cmd);
+ "logged, free, ready, count, penalty, paused, ringinuse\n", args.option, cmd);
}
ao2_unlock(q);
queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
@@ -6664,7 +6740,7 @@ static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, ch
return 0;
}
-/*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ignorebusy. */
+/*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ringinuse. */
static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{
int memvalue;
@@ -6696,10 +6772,9 @@ static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, c
}
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)) {
+ if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, memvalue)) {
ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
return -1;
}
@@ -6713,14 +6788,14 @@ static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, c
} else {
m->paused = (memvalue <= 0) ? 0 : 1;
}
- } else if (!strcasecmp(args.option, "ignorebusy")) {
+ } else if ((!strcasecmp(args.option, "ignorebusy")) || (!strcasecmp(args.option, "ringinuse"))) {
if (m->realtime) {
update_realtime_member_field(m, q->name, args.option, rtvalue);
} else {
- m->ignorebusy = (memvalue <= 0) ? 0 : 1;
+ m->ringinuse = (memvalue <= 0) ? 0 : 1;
}
} else {
- ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ignorebusy are valid\n");
+ ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ringinuse/ignorebusy are valid\n");
ao2_ref(m, -1);
ao2_unlock(q);
ao2_ref(q, -1);
@@ -6935,7 +7010,7 @@ static int queue_function_memberpenalty_write(struct ast_channel *chan, const ch
}
/* if queuename = NULL then penalty will be set for interface in all the queues. */
- if (set_member_penalty(args.queuename, args.interface, penalty)) {
+ if (set_member_value(args.queuename, args.interface, MEMBER_PENALTY, penalty)) {
ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
return -1;
}
@@ -7088,11 +7163,13 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
struct member *cur, *newm;
struct member tmpmem;
int penalty;
+ int ringinuse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(interface);
AST_APP_ARG(penalty);
AST_APP_ARG(membername);
AST_APP_ARG(state_interface);
+ AST_APP_ARG(ringinuse);
);
if (ast_strlen_zero(memberdata)) {
@@ -7102,7 +7179,7 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
/* Add a new member */
parse = ast_strdupa(memberdata);
-
+
AST_STANDARD_APP_ARGS(args, parse);
interface = args.interface;
@@ -7131,10 +7208,26 @@ static void reload_single_member(const char *memberdata, struct call_queue *q)
state_interface = interface;
}
+ if (!ast_strlen_zero(args.ringinuse)) {
+ tmp = args.ringinuse;
+ ast_strip(tmp);
+ if (ast_true(tmp)) {
+ ringinuse = 1;
+ } else if (ast_false(tmp)) {
+ ringinuse = 0;
+ } else {
+ ast_log(LOG_ERROR, "Member %s has an invalid ringinuse value. Using %s ringinuse value.\n",
+ membername, q->name);
+ ringinuse = q->ringinuse;
+ }
+ } else {
+ ringinuse = q->ringinuse;
+ }
+
/* Find the old position in the list */
ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
cur = ao2_find(q->members, &tmpmem, OBJ_POINTER | OBJ_UNLINK);
- if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface))) {
+ if ((newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0, state_interface, ringinuse))) {
ao2_link(q->members, newm);
ao2_ref(newm, -1);
}
@@ -7242,13 +7335,21 @@ static void reload_single_queue(struct ast_config *cfg, struct ast_flags *mask,
if (member_reload) {
ao2_callback(q->members, OBJ_NODATA, mark_member_dead, NULL);
}
+
+ /* On the first pass we just read the parameters of the queue */
+ for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
+ if (queue_reload && strcasecmp(var->name, "member")) {
+ queue_set_param(q, var->name, var->value, var->lineno, 1);
+ }
+ }
+
+ /* On the second pass, we read members */
for (var = ast_variable_browse(cfg, queuename); var; var = var->next) {
if (member_reload && !strcasecmp(var->name, "member")) {
reload_single_member(var->value, q);
- } else if (queue_reload) {
- queue_set_param(q, var->name, var->value, var->lineno, 1);
}
}
+
/* At this point, we've determined if the queue has a weight, so update use_weight
* as appropriate
*/
@@ -7521,6 +7622,9 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
if (mem->penalty) {
ast_str_append(&out, 0, " with penalty %d", mem->penalty);
}
+
+ ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
+
ast_str_append(&out, 0, "%s%s%s (%s)",
mem->dynamic ? " (dynamic)" : "",
mem->realtime ? " (realtime)" : "",
@@ -8070,6 +8174,40 @@ static char *complete_queue_add_member(const char *line, const char *word, int p
}
}
+static int manager_queue_member_ringinuse(struct mansession *s, const struct message *m)
+{
+ const char *queuename, *interface, *ringinuse_s;
+ int ringinuse;
+
+ interface = astman_get_header(m, "Interface");
+ ringinuse_s = astman_get_header(m, "RingInUse");
+
+ /* Optional - if not supplied, set the ringinuse value for the given Interface in all queues */
+ queuename = astman_get_header(m, "Queue");
+
+ if (ast_strlen_zero(interface) || ast_strlen_zero(ringinuse_s)) {
+ astman_send_error(s, m, "Need 'Interface' and 'RingInUse' parameters.");
+ return 0;
+ }
+
+ if (ast_true(ringinuse_s)) {
+ ringinuse = 1;
+ } else if (ast_false(ringinuse_s)) {
+ ringinuse = 0;
+ } else {
+ astman_send_error(s, m, "'RingInUse' parameter must be a truth value (yes/no, on/off, 0/1, etc)");
+ return 0;
+ }
+
+ if (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
+ astman_send_error(s, m, "Invalid interface, queuename, or ringinuse value\n");
+ } else {
+ astman_send_ack(s, m, "Interface ringinuse set successfully");
+ }
+
+ return 0;
+}
+
static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
{
const char *queuename, *interface, *penalty_s;
@@ -8087,7 +8225,7 @@ static int manager_queue_member_penalty(struct mansession *s, const struct messa
penalty = atoi(penalty_s);
- if (set_member_penalty((char *)queuename, (char *)interface, penalty)) {
+ if (set_member_value((char *)queuename, (char *)interface, MEMBER_PENALTY, penalty)) {
astman_send_error(s, m, "Invalid interface, queuename or penalty");
} else {
astman_send_ack(s, m, "Interface penalty set successfully");
@@ -8353,9 +8491,9 @@ static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct
}
}
-static char *complete_queue_set_member_penalty(const char *line, const char *word, int pos, int state)
+static char *complete_queue_set_member_value(const char *line, const char *word, int pos, int state)
{
- /* 0 - queue; 1 - set; 2 - penalty; 3 - <penalty>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
+ /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
switch (pos) {
case 4:
if (state == 0) {
@@ -8375,7 +8513,64 @@ static char *complete_queue_set_member_penalty(const char *line, const char *wor
return NULL;
}
}
-
+
+static char *handle_queue_set_member_ringinuse(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ const char *queuename = NULL, *interface;
+ int ringinuse;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "queue set ringinuse";
+ e->usage =
+ "Usage: queue set ringinuse <yes/no> on <interface> [in <queue>]\n"
+ " Set a member's ringinuse in the queue specified. If no queue is specified\n"
+ " then that interface's penalty is set in all queues to which that interface is a member.\n";
+ break;
+ return NULL;
+ case CLI_GENERATE:
+ return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
+ }
+
+ /* Sensible argument counts */
+ if (a->argc != 6 && a->argc != 8) {
+ return CLI_SHOWUSAGE;
+ }
+
+ /* Uses proper indicational words */
+ if (strcmp(a->argv[4], "on") || (a->argc > 6 && strcmp(a->argv[6], "in"))) {
+ return CLI_SHOWUSAGE;
+ }
+
+ /* Set the queue name if applicale */
+ if (a->argc == 8) {
+ queuename = a->argv[7];
+ }
+
+ /* Interface being set */
+ interface = a->argv[5];
+
+ /* Check and set the ringinuse value */
+ if (ast_true(a->argv[3])) {
+ ringinuse = 1;
+ } else if (ast_false(a->argv[3])) {
+ ringinuse = 0;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ switch (set_member_value(queuename, interface, MEMBER_RINGINUSE, ringinuse)) {
+ case RESULT_SUCCESS:
+ ast_cli(a->fd, "Set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
+ return CLI_SUCCESS;
+ case RESULT_FAILURE:
+ ast_cli(a->fd, "Failed to set ringinuse on interface '%s' from queue '%s'\n", interface, queuename);
+ return CLI_FAILURE;
+ default:
+ return CLI_FAILURE;
+ }
+}
+
static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
const char *queuename = NULL, *interface;
@@ -8390,7 +8585,7 @@ static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, s
" then that interface's penalty is set in all queues to which that interface is a member\n";
return NULL;
case CLI_GENERATE:
- return complete_queue_set_member_penalty(a->line, a->word, a->pos, a->n);
+ return complete_queue_set_member_value(a->line, a->word, a->pos, a->n);
}
if (a->argc != 6 && a->argc != 8) {
@@ -8405,7 +8600,7 @@ static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, s
interface = a->argv[5];
penalty = atoi(a->argv[3]);
- switch (set_member_penalty(queuename, interface, penalty)) {
+ switch (set_member_value(queuename, interface, MEMBER_PENALTY, penalty)) {
case RESULT_SUCCESS:
ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
return CLI_SUCCESS;
@@ -8586,6 +8781,7 @@ static struct ast_cli_entry cli_queue[] = {
AST_CLI_DEFINE(handle_queue_remove_member, "Removes a channel from a specified queue"),
AST_CLI_DEFINE(handle_queue_pause_member, "Pause or unpause a queue member"),
AST_CLI_DEFINE(handle_queue_set_member_penalty, "Set penalty for a channel of a specified queue"),
+ AST_CLI_DEFINE(handle_queue_set_member_ringinuse, "Set ringinuse for a channel of a specified queue"),
AST_CLI_DEFINE(handle_queue_rule_show, "Show the rules defined in queuerules.conf"),
AST_CLI_DEFINE(handle_queue_reload, "Reload queues, members, queue rules, or parameters"),
AST_CLI_DEFINE(handle_queue_reset, "Reset statistics for a queue"),
@@ -8914,6 +9110,7 @@ static int load_module(void)
{
int res;
struct ast_flags mask = {AST_FLAGS_ALL, };
+ struct ast_config *member_config;
queues = ao2_container_alloc(MAX_QUEUE_BUCKETS, queue_hash_cb, queue_cmp_cb);
@@ -8942,6 +9139,7 @@ static int load_module(void)
res |= ast_manager_register_xml("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member);
res |= ast_manager_register_xml("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom);
res |= ast_manager_register_xml("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty);
+ res |= ast_manager_register_xml("QueueMemberRingInUse", EVENT_FLAG_AGENT, manager_queue_member_ringinuse);
res |= ast_manager_register_xml("QueueRule", 0, manager_queue_rule_show);
res |= ast_manager_register_xml("QueueReload", 0, manager_queue_reload);
res |= ast_manager_register_xml("QueueReset", 0, manager_queue_reset);
@@ -8966,6 +9164,29 @@ static int load_module(void)
ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
+ /*
+ * This section is used to determine which name for 'ringinuse' to use in realtime members
+ * Necessary for supporting older setups.
+ */
+ member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name LIKE", "%", SENTINEL);
+ if (!member_config) {
+ realtime_ringinuse_field = "ringinuse";
+ } else {
+ const char *config_val;
+ if ((config_val = ast_variable_retrieve(member_config, NULL, "ringinuse"))) {
+ ast_log(LOG_NOTICE, "ringinuse field entries found in queue_members table. Using 'ringinuse'\n");
+ realtime_ringinuse_field = "ringinuse";
+ } else if ((config_val = ast_variable_retrieve(member_config, NULL, "ignorebusy"))) {
+ ast_log(LOG_NOTICE, "ignorebusy field found in queue_members table with no ringinuse field. Using 'ignorebusy'\n");
+ realtime_ringinuse_field = "ignorebusy";
+ } else {
+ ast_log(LOG_NOTICE, "No entries were found for ringinuse/ignorebusy in queue_members table. Using 'ringinuse'\n");
+ realtime_ringinuse_field = "ringinuse";
+ }
+ }
+
+ ast_config_destroy(member_config);
+
return res ? AST_MODULE_LOAD_DECLINE : 0;
}