[asterisk-commits] mmichelson: branch mmichelson/queue-penalty r93739 - /team/mmichelson/queue-p...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Dec 18 14:30:07 CST 2007


Author: mmichelson
Date: Tue Dec 18 14:30:06 2007
New Revision: 93739

URL: http://svn.digium.com/view/asterisk?view=rev&rev=93739
Log:
Several changes

1. I changed the "rules" list to have a lock, and use this list lock instead of the queue's lock since it is much more logical
2. Laureano on IRC pointed out a potential memory leak which is fixed here. Thanks Laureano! :)
3. I realized that I was completely mishandling relative penalty changes in the insert_penaltychange function. It's fixed now.
4. I now initialize the list of rules in the init_queue function.
5. I added the logic to change values of the QUEUE_MAX_PENALTY in wait_our_turn and queue_exec.

At this point, you could call what's written a really rough draft. It SHOULD work as long as you
don't make any changes to the penalty rules while someone is in the queue (In other words no reloads or realtime updates)

My next step is to test what's written to see if things are actually going as planned. After that I will work on 
refining the code which has been written and try to integrate other enhancements.


Modified:
    team/mmichelson/queue-penalty/apps/app_queue.c

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=93739&r1=93738&r2=93739
==============================================================================
--- team/mmichelson/queue-penalty/apps/app_queue.c (original)
+++ team/mmichelson/queue-penalty/apps/app_queue.c Tue Dec 18 14:30:06 2007
@@ -335,6 +335,7 @@
 	time_t start;                       /*!< When we started holding */
 	time_t expire;                      /*!< When this entry should expire (time out of queue) */
 	struct ast_channel *chan;           /*!< Our channel */
+	struct penalty_rule *pr;			/*!< The penalty rule we will implement next */
 	struct queue_ent *next;             /*!< The next queue entry */
 };
 
@@ -463,7 +464,7 @@
 	int membercount;
 	struct queue_ent *head;             /*!< Head of the list of callers */
 	AST_LIST_ENTRY(call_queue) list;    /*!< Next call queue */
-	AST_LIST_HEAD_NOLOCK(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
+	AST_LIST_HEAD(, penalty_rule) rules; /*!< The list of penalty rules to invoke */
 };
 
 
@@ -889,6 +890,8 @@
 		if (q->sound_periodicannounce[i])
 			ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
 	}
+
+	AST_LIST_HEAD_INIT(&q->rules);
 }
 
 static void clear_queue(struct call_queue *q)
@@ -986,10 +989,10 @@
 static int insert_penaltychange (struct call_queue *q, const char *content, const int linenum)
 {
 	char *timestr, *changestr, *contentdup;
-	struct penalty_rule *pr = NULL, *iter;
-	int time, change, inserted = 0;
-
-	if (!(pr = ast_calloc(1, sizeof(*pr)))) {
+	struct penalty_rule *rule = NULL, *iter;
+	int time, inserted = 0;
+
+	if (!(rule = ast_calloc(1, sizeof(*rule)))) {
 		ast_log(LOG_ERROR, "Cannot allocate memory for penaltychange rule at line %d!\n", linenum);
 		return -1;
 	}
@@ -998,6 +1001,7 @@
 	
 	if (!(changestr = strchr(contentdup, ','))) {
 		ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
+		ast_free(rule);
 		return -1;
 	}
 	
@@ -1007,31 +1011,24 @@
 	/*Let's get the number of seconds first...*/
 	if ((time = atoi(timestr)) < 0) {
 		ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
-		ast_free(pr);
+		ast_free(rule);
 		return -1;
 	}
 
-	pr->time = time;
+	rule->time = time;
 
 	/*Now on to the change*/
 	if (*changestr == '+' || *changestr == '-') {
-		pr->relative = 1;
-		changestr++;
-	}
-
-	if ((change = atoi(changestr)) < 0) {
-		ast_log(LOG_WARNING, "Improper change parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
-		ast_free(pr);
-		return -1;
-	}
-
-	pr->value = change;
+		rule->relative = 1;
+	}
+
+	rule->value = atoi(changestr); 
 
 	/*We have the rule made, now we need to insert it where it belongs*/
-	ao2_lock(q);
+	AST_LIST_LOCK(&q->rules);
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&q->rules, iter, list) {
-		if (pr->time < iter->time) {
-			AST_LIST_INSERT_BEFORE_CURRENT(pr, list);
+		if (rule->time < iter->time) {
+			AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
 			inserted = 1;
 			break;
 		}
@@ -1039,9 +1036,9 @@
 	AST_LIST_TRAVERSE_SAFE_END;
 
 	if (!inserted) {
-		AST_LIST_INSERT_TAIL(&q->rules, pr, list);
-	}
-	ao2_unlock(q);
+		AST_LIST_INSERT_TAIL(&q->rules, rule, list);
+	}
+	AST_LIST_UNLOCK(&q->rules);
 
 	return 0;
 }
@@ -2625,6 +2622,18 @@
 		if (qe->parent->periodicannouncefrequency &&
 			(res = say_periodic_announcement(qe,ringing)))
 			break;
+		
+		/* see if we need to move to the next penalty level for this queue */
+		if (qe->pr && (time(NULL) > (qe->pr->time - qe->start))) {
+			int max_penalty = qe->pr->relative ? qe->max_penalty + qe->pr->value : qe->pr->value;
+			char max_penalty_str[12]; /*XXX Will change this idiom and probably optimize things once everything is running */
+			snprintf(max_penalty_str, sizeof(max_penalty_str) - 1, "%d", max_penalty);
+			AST_LIST_LOCK(&qe->parent->rules);
+			pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
+			qe->max_penalty = max_penalty;
+			qe->pr = AST_LIST_NEXT(qe->pr, list);
+			AST_LIST_UNLOCK(&qe->parent->rules);
+		}
 
 		/* Wait a second before checking again */
 		if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
@@ -4112,6 +4121,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, ""));
+		qe.pr = AST_LIST_FIRST(&qe.parent->rules);
 check_turns:
 		if (ringing) {
 			ast_indicate(chan, AST_CONTROL_RINGING);
@@ -4207,6 +4217,18 @@
 				res = 0;
 				ast_queue_log(qe.parent->name, qe.chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld", qe.pos, qe.opos, (long) time(NULL) - qe.start);
 				break;
+			}
+
+			/* see if we need to move to the next penalty level for this queue */
+			if (qe.pr && (time(NULL) > (qe.pr->time - qe.start))) {
+				char max_penalty_str[12]; /*XXX Will change this idiom and probably optimize things once everything is running */
+				max_penalty = qe.pr->relative ? qe.max_penalty + qe.pr->value : qe.pr->value;
+				snprintf(max_penalty_str, sizeof(max_penalty_str) - 1, "%d", max_penalty);
+				AST_LIST_LOCK(&qe.parent->rules);
+				pbx_builtin_setvar_helper(qe.chan, "QUEUE_MAX_PENALTY", max_penalty_str);
+				qe.max_penalty = max_penalty;
+				qe.pr = AST_LIST_NEXT(qe.pr, list);
+				AST_LIST_UNLOCK(&qe.parent->rules);
 			}
 
 			/* If using dynamic realtime members, we should regenerate the member list for this queue */




More information about the asterisk-commits mailing list