[svn-commits] irroot: branch irroot/app_queue_skill r325535 - in /team/irroot/app_queue_ski...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jun 29 09:37:36 CDT 2011


Author: irroot
Date: Wed Jun 29 09:37:32 2011
New Revision: 325535

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=325535
Log:
Resolved Conflicts Introduced with r324364

Modified:
    team/irroot/app_queue_skill/   (props changed)
    team/irroot/app_queue_skill/CHANGES
    team/irroot/app_queue_skill/UPGRADE.txt
    team/irroot/app_queue_skill/apps/app_queue.c
    team/irroot/app_queue_skill/configs/queues.conf.sample

Propchange: team/irroot/app_queue_skill/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/irroot/app_queue_skill/
------------------------------------------------------------------------------
    svn:mergeinfo = /trunk:322065-325534

Modified: team/irroot/app_queue_skill/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/irroot/app_queue_skill/CHANGES?view=diff&rev=325535&r1=325534&r2=325535
==============================================================================
--- team/irroot/app_queue_skill/CHANGES (original)
+++ team/irroot/app_queue_skill/CHANGES Wed Jun 29 09:37:32 2011
@@ -439,6 +439,15 @@
    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
 ----------------------------------------

Modified: team/irroot/app_queue_skill/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/irroot/app_queue_skill/UPGRADE.txt?view=diff&rev=325535&r1=325534&r2=325535
==============================================================================
--- team/irroot/app_queue_skill/UPGRADE.txt (original)
+++ team/irroot/app_queue_skill/UPGRADE.txt Wed Jun 29 09:37:32 2011
@@ -50,5 +50,9 @@
  - 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.
+
 ===========================================================
 ===========================================================

Modified: team/irroot/app_queue_skill/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/app_queue_skill/apps/app_queue.c?view=diff&rev=325535&r1=325534&r2=325535
==============================================================================
--- team/irroot/app_queue_skill/apps/app_queue.c (original)
+++ team/irroot/app_queue_skill/apps/app_queue.c Wed Jun 29 09:37:32 2011
@@ -521,11 +521,25 @@
 					<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 @@
 		</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>
@@ -936,6 +951,9 @@
 /*! \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,
@@ -1137,6 +1155,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 */
 };
 
 enum empty_conditions {
@@ -1254,6 +1273,7 @@
 	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 */
@@ -1285,6 +1305,7 @@
 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);
@@ -1808,6 +1829,7 @@
 	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 */
@@ -2113,6 +2135,8 @@
 			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)
@@ -2191,7 +2215,9 @@
 	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);
@@ -2206,14 +2232,23 @@
 
 	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) {
 		paused = atoi(paused_str);
 		if (paused < 0)
 			paused = 0;
+	}
+
+	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 */
@@ -2226,8 +2261,9 @@
 				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;
 			if (!ast_strlen_zero(skills)) {
 				ast_copy_string(m->skills, skills, sizeof(m->skills));
 			} else {
@@ -2247,7 +2283,8 @@
 		if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, skills))) {
 			m->dead = 0;
 			m->realtime = 1;
-+			update_queue_ent_skills_next_check(q);
+			m->ignorebusy = ignorebusy;
+			update_queue_ent_skills_next_check(q);
 			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);
@@ -3926,17 +3963,25 @@
 	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;
-			/* else fall through */
-		case AST_DEVICE_NOT_INUSE:
-		case AST_DEVICE_UNKNOWN:
-			if (!mem->paused &&
-+			    (!qe || member_is_selected(qe, mem))) {
-				avl++;
-			}
-			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) &&
+				    (!qe || member_is_selected(qe, mem))) {
+					avl++;
+				}
+				break;
 		}
 		ao2_ref(mem, -1);
 
@@ -4064,34 +4109,49 @@
 	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 (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 (!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 (!member_is_selected(qe, tmp->member)) {
 		if (option_debug)
@@ -4104,8 +4164,9 @@
 
 	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;
@@ -4120,8 +4181,9 @@
 	/* 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);
@@ -4460,6 +4522,18 @@
 	}
 	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",
@@ -5778,8 +5852,9 @@
 		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) {
@@ -5859,10 +5934,11 @@
 				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++) {
@@ -5929,12 +6005,13 @@
 					
 					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");
 				}
@@ -6253,7 +6330,10 @@
 		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");
@@ -6440,35 +6520,34 @@
 	int foundinterface = 0, foundqueue = 0;
 	struct call_queue *q;
 	struct member *mem;
-	struct ao2_iterator queue_iter;
-
-	if (penalty < 0) {
+	char rtpenalty[80];
+
+	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;
@@ -7271,31 +7350,37 @@
 	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 */
@@ -7305,7 +7390,7 @@
 				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 */
@@ -7315,7 +7400,7 @@
 				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);
@@ -7328,22 +7413,104 @@
 				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)
 {
@@ -7549,7 +7716,8 @@
 
 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 = {
@@ -7747,8 +7915,9 @@
 {
 	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);
@@ -7763,6 +7932,9 @@
 	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

Modified: team/irroot/app_queue_skill/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/irroot/app_queue_skill/configs/queues.conf.sample?view=diff&rev=325535&r1=325534&r2=325535
==============================================================================
--- team/irroot/app_queue_skill/configs/queues.conf.sample (original)
+++ team/irroot/app_queue_skill/configs/queues.conf.sample Wed Jun 29 09:37:32 2011
@@ -60,6 +60,10 @@
 ; The default value is yes.
 ;
 ;shared_lastcall=no
+;
+; Negative_penalty_invalid will treat members with a negative penalty as logged off
+;
+;negative_penalty_invalid = no
 ;
 ;[markq]
 ;
@@ -195,6 +199,10 @@
 ; yes: Member will be paused only in the queue where the timeout took place
 ; 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)
 ;
@@ -459,6 +467,9 @@
 ; 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




More information about the svn-commits mailing list