[asterisk-commits] jrose: trunk r367080 - in /trunk: ./ apps/ configs/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri May 18 14:40:06 CDT 2012


Author: jrose
Date: Fri May 18 14:39:54 2012
New Revision: 367080

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=367080
Log:
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/

Modified:
    trunk/CHANGES
    trunk/apps/app_queue.c
    trunk/configs/queues.conf.sample

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=367080&r1=367079&r2=367080
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Fri May 18 14:39:54 2012
@@ -125,6 +125,14 @@
 -------------
  * Added queue options autopausebusy and autopauseunavail for automatically
    pausing a queue member when their device reports busy or congestion.
+ * The 'ignorebusy' option for queue members has been deprecated in favor of
+   the option 'ringinuse. Also a 'queue set ringinuse' CLI command has been
+   added as well as an AMI action 'QueueMemberRingInUse' to set this variable on a
+   per interface basis. Individual ringinuse values can now be set in
+   queues.conf via an argument to member definitions. Lastly, the queue
+   'ringinuse' setting now only determines defaults for the per member
+   'ringinuse' setting and does not override per member settings like it does
+   in earlier versions.
 
 Voicemail changes
 -----------------

Modified: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=367080&r1=367079&r2=367080
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Fri May 18 14:39:54 2012
@@ -552,8 +552,8 @@
 					<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 @@
 		<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 @@
 /*! \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 @@
 	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 {
@@ -1153,6 +1171,11 @@
 	QUEUE_EMPTY_INVALID = (1 << 5),
 	QUEUE_EMPTY_UNKNOWN = (1 << 6),
 	QUEUE_EMPTY_WRAPUP = (1 << 7),
+};
+
+enum member_properties {
+	MEMBER_PENALTY = 0,
+	MEMBER_RINGINUSE = 1,
 };
 
 /* values used in multi-bit flags in call_queue */
@@ -1721,12 +1744,12 @@
 }
 
 /*! \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 @@
 	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 @@
 		}
 	}
 
-	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 @@
 				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 @@
 
 	/* 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 @@
 			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 @@
 		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 @@
 
 	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 @@
 	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 @@
 					 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 @@
 		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 @@
 
 /*!
  * \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 @@
 			   ((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 @@
 	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 @@
 	}
 
 	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 @@
 				} 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 @@
 	}
 
 	/* 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 @@
 	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 @@
 
 	/* Add a new member */
 	parse = ast_strdupa(memberdata);
-				
+
 	AST_STANDARD_APP_ARGS(args, parse);
 
 	interface = args.interface;
@@ -7131,10 +7208,26 @@
 		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 @@
 	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 @@
 				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 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 @@
  
 	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 *complete_queue_set_member_penalty(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>;*/
+static char *complete_queue_set_member_value(const char *line, const char *word, int pos, int state)
+{
+	/* 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 @@
 		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 @@
 		"	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 @@
 	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 @@
 	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 @@
 {
 	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 @@
 	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 @@
 
 	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;
 }
 

Modified: trunk/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/queues.conf.sample?view=diff&rev=367080&r1=367079&r2=367080
==============================================================================
--- trunk/configs/queues.conf.sample (original)
+++ trunk/configs/queues.conf.sample Fri May 18 14:39:54 2012
@@ -73,8 +73,8 @@
 ;
 ; app_queue allows calls to members in a "Unknown" state to be treated as available
 ; setting check_state_unknown = yes will cause app_queue to query the channel driver
-; to better determine the state this only applies to queues with ringinuse or ignorebusy
-; set appropriately.
+; to better determine the state this only applies to queues with ringinuse set
+; appropriately.
 ;
 ;check_state_unknown = no
 ;
@@ -504,10 +504,11 @@
 ; If you want the queue to avoid sending calls to members whose devices are
 ; known to be 'in use' (via the channel driver supporting that device state)
 ; uncomment this option. This can be controlled on a per member basis by
-; setting 'ignorebusy' in the QUEUE_MEMBER function. (Note: only the SIP
-; channel driver currently is able to report 'in use'.) (Note: if this option
-; is set to 'no' it will override the per-member 'ignorebusy' setting.
-;
+; setting 'ringinuse' on that member. This can be done in the member definition,
+; in the 'ringinuse' field on a realtime member, via the QUEUE_MEMBER dialplan
+; function, or with CLI/AMI. By default, the per member value will be the same
+; as the queue's ringinuse value if it isn't set on the member deliberately.
+; (Note: only the SIP channel driver currently is able to report 'in use'.)
 ; ringinuse = no
 ;
 ; If you wish to have a delay before the member is connected to the caller (or
@@ -551,12 +552,15 @@
 ; must also preload pbx_config.so and chan_local.so (or pbx_ael.so, pbx_lua.so,
 ; or pbx_realtime.so, depending on how your dialplan is configured).
 ;
+; syntax: member => interface,[,penalty][,membername][,state_interface][,ringinuse]
+;
 ;member => DAHDI/1
 ;member => DAHDI/2,10
 ;member => DAHDI/3,10,Bob Johnson
 ;member => Agent/1001
 ;member => Agent/1002
 ;member => Local/1000 at default,0,John Smith,SIP/1000
+;member => Local/2000 at default,0,Lorem Ipsum,SIP/2000,no
 
 ;
 ; Note that using agent groups is probably not what you want.  Strategies do




More information about the asterisk-commits mailing list