[asterisk-commits] mmichelson: branch mmichelson/queue-penalty r94076 - in /team/mmichelson/queu...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Dec 19 16:16:37 CST 2007


Author: mmichelson
Date: Wed Dec 19 16:16:37 2007
New Revision: 94076

URL: http://svn.digium.com/view/asterisk?view=rev&rev=94076
Log:
Best to just enumerate the changes here:

1. penaltychange rules are now defined in a separate conf file (queuerules.conf). By doing this you can use the same
rules in multiple queues easily.
2. queues themselves now have a "defaultrule" option that says which rules to use.
3. "defaultrule" may be overridden by using an argument to Queue() stating which one to use instead.

I have tested this, but not too thoroughly. In fact, I consider this commit to mainly be a "progress" commit in the
sense that I don't really consider what I've written here to be final and there's still more to come.


Added:
    team/mmichelson/queue-penalty/configs/queuerules.conf.sample   (with props)
Modified:
    team/mmichelson/queue-penalty/apps/app_queue.c
    team/mmichelson/queue-penalty/configs/queues.conf.sample

Modified: team/mmichelson/queue-penalty/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/mmichelson/queue-penalty/apps/app_queue.c?view=diff&rev=94076&r1=94075&r2=94076
==============================================================================
--- team/mmichelson/queue-penalty/apps/app_queue.c (original)
+++ team/mmichelson/queue-penalty/apps/app_queue.c Wed Dec 19 16:16:37 2007
@@ -135,7 +135,7 @@
 static char *synopsis = "Queue a call for a call queue";
 
 static char *descrip =
-"  Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub]):\n"
+"  Queue(queuename[,options[,URL][,announceoverride][,timeout][,AGI][,macro][,gosub][,rule]):\n"
 "Queues an incoming call in a particular call queue as defined in queues.conf.\n"
 "This application will return to the dialplan if the queue does not exist, or\n"
 "any of the join options cause the caller to not enter the queue.\n"
@@ -170,6 +170,8 @@
 "calling party's channel once they are connected to a queue member.\n"
 "  The optional gosub parameter will run a gosub on the \n"
 "calling party's channel once they are connected to a queue member.\n"
+"  The optional rule parameter will cause the queue's defaultrule to be.\n"
+"overridden by the rule specified
 "  The timeout will cause the queue to fail out after a specified number of\n"
 "seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"
 "  This application sets the following channel variable upon completion:\n"
@@ -394,6 +396,8 @@
 		AST_STRING_FIELD(membermacro);
 		/*! Gosub to run upon member connection */
 		AST_STRING_FIELD(membergosub);
+		/*! Default rule to use if none specified in call to Queue() */
+		AST_STRING_FIELD(defaultrule);
 		/*! Sound file: "Your call is now first in line" (def. queue-youarenext) */
 		AST_STRING_FIELD(sound_next);
 		/*! Sound file: "There are currently" (def. queue-thereare) */
@@ -471,6 +475,13 @@
 	AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
 };
 
+struct rule_list {
+	char name[80];
+	AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
+	AST_LIST_ENTRY(rule_list) list;
+};
+
+AST_LIST_HEAD_STATIC(rule_lists, rule_list);
 
 static struct ao2_container *queues;
 
@@ -992,10 +1003,12 @@
 	AST_LIST_UNLOCK(&interfaces);
 }
 
-static int insert_penaltychange (struct call_queue *q, const char *content, const int linenum)
+/*Note: call this with the rule_lists locked */
+static int insert_penaltychange (const char *list_name, const char *content, const int linenum)
 {
 	char *timestr, *maxstr, *minstr, *contentdup;
-	struct penalty_rule *rule = NULL, *iter;
+	struct penalty_rule *rule = NULL, *rule_iter;
+	struct rule_list *rl_iter;
 	int time, inserted = 0;
 
 	if (!(rule = ast_calloc(1, sizeof(*rule)))) {
@@ -1042,20 +1055,23 @@
 		rule->min_relative = 1;
 
 	/*We have the rule made, now we need to insert it where it belongs*/
-	ao2_lock(q);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&q->rules, iter, list) {
-		if (rule->time < iter->time) {
-			AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
-			inserted = 1;
-			break;
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
-
-	if (!inserted) {
-		AST_LIST_INSERT_TAIL(&q->rules, rule, list);
-	}
-	ao2_unlock(q);
+	AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
+		if(strcasecmp(rl_iter->name, list_name))
+			continue;
+
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
+			if (rule->time < rule_iter->time) {
+				AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
+				inserted = 1;
+				break;
+			}
+		}
+		AST_LIST_TRAVERSE_SAFE_END;
+	
+		if (!inserted) {
+			AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
+		}
+	}
 
 	return 0;
 }
@@ -1221,8 +1237,8 @@
 		   we will not see any effect on use_weight until next reload. */
 	} else if (!strcasecmp(param, "timeoutrestart")) {
 		q->timeoutrestart = ast_true(val);
-	} else if (!strcasecmp(param, "penaltychange" )) {
-		insert_penaltychange(q, val, linenum);
+	} else if (!strcasecmp(param, "defaultrule")) {
+		ast_string_field_set(q, defaultrule, val);
 	} else if (failunknown) {
 		if (linenum >= 0) {
 			ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
@@ -1294,7 +1310,6 @@
 static void destroy_queue(void *obj)
 {
 	struct call_queue *q = obj;
-	struct penalty_rule *pr_iter;
 	int i;
 
 	ast_debug(0, "Queue destructor called for queue '%s'!\n", q->name);
@@ -1305,8 +1320,6 @@
 		if (q->sound_periodicannounce[i])
 			free(q->sound_periodicannounce[i]);
 	}
-	while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules, list)))
-		ast_free(pr_iter);
 	ao2_ref(q->members, -1);
 }
 
@@ -4057,20 +4070,28 @@
 	return 0;
 }
 
-static void copy_rules(struct queue_ent *qe)
+static void copy_rules(struct queue_ent *qe, const char *rulename)
 {
 	struct penalty_rule *pr_iter;
-	ao2_lock(qe->parent);
-	AST_LIST_TRAVERSE(&qe->parent->rules, pr_iter, list) {
-		struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
-		new_pr->time = pr_iter->time;
-		new_pr->max_value = pr_iter->max_value;
-		new_pr->min_value = pr_iter->min_value;
-		new_pr->max_relative = pr_iter->max_relative;
-		new_pr->min_relative = pr_iter->min_relative;
-		AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
-	}
-	ao2_unlock(qe->parent);
+	struct rule_list *rl_iter;
+	const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
+	AST_LIST_LOCK(&rule_lists);
+	AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
+		if(!strcasecmp(rl_iter->name, tmp))
+			break;
+	}
+	if (rl_iter) {
+		AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
+			struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
+			new_pr->time = pr_iter->time;
+			new_pr->max_value = pr_iter->max_value;
+			new_pr->min_value = pr_iter->min_value;
+			new_pr->max_relative = pr_iter->max_relative;
+			new_pr->min_relative = pr_iter->min_relative;
+			AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
+		}
+	}
+	AST_LIST_UNLOCK(&rule_lists);
 }
 
 static int queue_exec(struct ast_channel *chan, void *data)
@@ -4098,6 +4119,7 @@
 		AST_APP_ARG(agi);
 		AST_APP_ARG(macro);
 		AST_APP_ARG(gosub);
+		AST_APP_ARG(rule);
 	);
 	/* Our queue entry */
 	struct queue_ent qe;
@@ -4182,7 +4204,7 @@
 	if (!join_queue(args.queuename, &qe, &reason)) {
 		ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", S_OR(args.url, ""),
 			S_OR(chan->cid.cid_num, ""));
-		copy_rules(&qe);
+		copy_rules(&qe, args.rule);
 		qe.pr = AST_LIST_FIRST(&qe.qe_rules);
 check_turns:
 		if (ringing) {
@@ -4714,6 +4736,8 @@
 	struct ast_variable *var;
 	struct member *cur, *newm;
 	struct ao2_iterator mem_iter;
+	struct penalty_rule *pr_iter;
+	struct rule_list *rl_iter;
 	int new;
 	const char *general_val = NULL;
 	char parse[80];
@@ -4727,6 +4751,32 @@
 		AST_APP_ARG(penalty);
 		AST_APP_ARG(membername);
 	);
+
+	/*First things first. Let's load queuerules.conf*/
+	AST_LIST_LOCK(&rule_lists);
+	while((rl_iter = AST_LIST_REMOVE_HEAD(&rule_lists, list))) {
+		while ((pr_iter = AST_LIST_REMOVE_HEAD(&rl_iter->rules, list)))
+			ast_free(pr_iter);
+		ast_free(rl_iter);
+	}
+	if (!(cfg = ast_config_load("queuerules.conf", config_flags))) {
+		ast_log(LOG_NOTICE, "No queuerules.conf file found, queues will not follow penalty rules\n");
+	} else {
+		char *rulecat = NULL;
+		struct ast_variable *rulevar = NULL;
+		while((rulecat = ast_category_browse(cfg, rulecat))) {
+			struct rule_list *rl = ast_calloc(1, sizeof(*rl));
+			if (!rl){
+				/*Handle allocation failure*/
+			} else {
+				ast_copy_string(rl->name, rulecat, sizeof(rl->name));
+				AST_LIST_INSERT_TAIL(&rule_lists, rl, list);
+				for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next)
+					insert_penaltychange(rl->name, rulevar->value, rulevar->lineno);
+			}
+		}
+	}
+	AST_LIST_UNLOCK(&rule_lists);
 	
 	if (!(cfg = ast_config_load("queues.conf", config_flags))) {
 		ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");

Added: team/mmichelson/queue-penalty/configs/queuerules.conf.sample
URL: http://svn.digium.com/view/asterisk/team/mmichelson/queue-penalty/configs/queuerules.conf.sample?view=auto&rev=94076
==============================================================================
--- team/mmichelson/queue-penalty/configs/queuerules.conf.sample (added)
+++ team/mmichelson/queue-penalty/configs/queuerules.conf.sample Wed Dec 19 16:16:37 2007
@@ -1,0 +1,19 @@
+; It is possible to change the value of the QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY 
+; channel variables in mid-call by defining rules in the queue for when to do so. This can allow for
+; a call to be opened to more members or potentially a different set of members. 
+; The advantage to changing members this way as opposed to inserting the caller into a 
+; different queue with more members or reinserting the caller into the same queue with a different 
+; QUEUE_MAX_PENALTY or QUEUE_MIN_PENALTY set is that the caller does not lose his place in the queue. 
+; Note: There is a limitation to these rules; a caller will follow the penaltychange rules for 
+; the queue that were defined at the time the caller entered the queue. If an update to the rules is 
+; made during the the caller's stay in the queue, these will not be reflected for that caller.
+;
+; The syntax for these rules is
+; penaltychange => <number of seconds into the call>,<absolute or relative change to QUEUE_MAX_PENALTY>[,absolute or relative change to QUEUE_MIN_PENALTY]
+;
+; Example:
+; [myrule]
+; penaltychange => 30,+3   ; 30 seconds into the call increase the QUEUE_MAX_PENALTY by 3, no change to QUEUE_MIN_PENALTY
+; penaltychange => 60,10,5 ; 60 seconds into the call increase the QUEUE_MAX_PENALTY to 10 and increase the QUEUE_MIN_PENALTY to 5
+; penaltychange => 75,,7   ; 75 seconds into the call keep the QUEUE_MAX_PENALTY the same and increase the QUEUE_MIN_PENALTY to 7
+

Propchange: team/mmichelson/queue-penalty/configs/queuerules.conf.sample
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mmichelson/queue-penalty/configs/queuerules.conf.sample
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mmichelson/queue-penalty/configs/queuerules.conf.sample
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/mmichelson/queue-penalty/configs/queues.conf.sample
URL: http://svn.digium.com/view/asterisk/team/mmichelson/queue-penalty/configs/queues.conf.sample?view=diff&rev=94076&r1=94075&r2=94076
==============================================================================
--- team/mmichelson/queue-penalty/configs/queues.conf.sample (original)
+++ team/mmichelson/queue-penalty/configs/queues.conf.sample Wed Dec 19 16:16:37 2007
@@ -362,22 +362,12 @@
 ;
 ; timeoutrestart = no
 ;
-; It is possible to change the value of the QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY 
-; channel variables in mid-call by defining rules in the queue for when to do so. This can allow for
-; a call to be opened to more members or potentially a different set of members. 
-; The advantage to changing members this way as opposed to inserting the caller into a 
-; different queue with more members or reinserting the caller into the same queue with a different 
-; QUEUE_MAX_PENALTY or QUEUE_MIN_PENALTY set is that the caller does not lose his place in the queue. 
-; Note: There is a limitation to these rules; a caller will follow the penaltychange rules for 
-; the queue that were defined at the time the caller entered the queue. If an update to the rules is 
-; made during the the caller's stay in the queue, these will not be reflected for that caller.
-;
-; The syntax for these rules is
-; penaltychange => <number of seconds into the call>,<absolute or relative change to QUEUE_MAX_PENALTY>[,absolute or relative change to QUEUE_MIN_PENALTY]
-;
-; penaltychange => 30,+3   ; 30 seconds into the call increase the QUEUE_MAX_PENALTY by 3, no change to QUEUE_MIN_PENALTY
-; penaltychange => 60,10,5 ; 60 seconds into the call increase the QUEUE_MAX_PENALTY to 10 and increase the QUEUE_MIN_PENALTY to 5
-; penaltychange => 75,,7   ; 75 seconds into the call keep the QUEUE_MAX_PENALTY the same and increase the QUEUE_MIN_PENALTY to 7
+; If you wish to implement a rule defined in queuerules.conf (see 
+; configs/queuerules.conf.sample from the asterisk source directory for
+; more information about penalty rules) by default, you may specify this
+; by setting defaultrule to the rule's name
+;
+; defaultrule = myrule
 ;
 ; Each member of this call queue is listed on a separate line in
 ; the form technology/dialstring.  "member" means a normal member of a




More information about the asterisk-commits mailing list