[svn-commits] mjordan: trunk r420625 - in /trunk: ./ apps/ configs/samples/ contrib/ast-db-...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sun Aug 10 19:14:59 CDT 2014


Author: mjordan
Date: Sun Aug 10 19:14:53 2014
New Revision: 420625

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=420625
Log:
app_queue: Add RealTime support for queue rules

This patch gives the optional ability to keep queue rules in RealTime. It is
important to note that with this patch:
 (a) Queue rules in RealTime are only examined on module load/reload
 (b) Queue rules are loaded both from the queuerules.conf file as well as the
     RealTime backend
To inform app_queue to examine RealTime for queue rules, a new setting has been
added to queuerules.conf's general section "realtime_rules". RealTime queue
rules will only be used when this setting is set to "yes".

The schema for the database table supports a rule_name, time, min_penalty, and
max_penalty columns. min_penalty and max_penalty can be relative, if a '-' or
'+' literal is provided. Otherwise, the penalties are treated as constants.

For example:
rule_name, time, min_penalty, max_penalty
'default', '10', '20', '30'
'test2', '20', '30', '55'
'test2', '25', '-11', '+1111'
'test2', '400', '112', '333'
'test3', '0', '4564', '46546'
'test_rule', '40', '15', '50'

which would result in :

Rule: default
 - After 10 seconds, adjust QUEUE_MAX_PENALTY to 30 and adjust
   QUEUE_MIN_PENALTY to 20
Rule: test2
 - After 20 seconds, adjust QUEUE_MAX_PENALTY to 55 and adjust
   QUEUE_MIN_PENALTY to 30
 - After 25 seconds, adjust QUEUE_MAX_PENALTY by 1111 and adjust
   QUEUE_MIN_PENALTY by -11
 - After 400 seconds, adjust QUEUE_MAX_PENALTY to 333 and adjust
   QUEUE_MIN_PENALTY to 112
Rule: test3
 - After 0 seconds, adjust QUEUE_MAX_PENALTY to 46546 and adjust
   QUEUE_MIN_PENALTY to 4564
Rule: test_rule
 - After 40 seconds, adjust QUEUE_MAX_PENALTY to 50 and adjust
   QUEUE_MIN_PENALTY to 15

If you use RealTime, the queue rules will be always reloaded on a module
reload, even if the underlying file did not change. With the option disabled,
the rules will only be reloaded if the file was modified.

Review: https://reviewboard.asterisk.org/r/3607/

ASTERISK-23823 #close
Reported by: Michael K
patches:
  app_queue.c_realtime_trunk.patch uploaded by Michael K (License 6621)
........

Merged revisions 420624 from http://svn.asterisk.org/svn/asterisk/branches/13

Added:
    trunk/contrib/ast-db-manage/config/versions/d39508cb8d8_create_queue_rules.py
      - copied unchanged from r420624, branches/13/contrib/ast-db-manage/config/versions/d39508cb8d8_create_queue_rules.py
Modified:
    trunk/   (props changed)
    trunk/CHANGES
    trunk/UPGRADE-13.txt
    trunk/apps/app_queue.c
    trunk/configs/samples/extconfig.conf.sample
    trunk/configs/samples/queuerules.conf.sample

Propchange: trunk/
------------------------------------------------------------------------------
--- branch-13-merged (original)
+++ branch-13-merged Sun Aug 10 19:14:53 2014
@@ -1,1 +1,1 @@
-/branches/13:1-420494,420514,420534,420536,420538,420562,420577,420592,420609
+/branches/13:1-420494,420514,420534,420536,420538,420562,420577,420592,420609,420624

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=420625&r1=420624&r2=420625
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Sun Aug 10 19:14:53 2014
@@ -93,6 +93,19 @@
    have been added.  The option "p" will play a beep to the channel that starts
    the recording.  The option "P" will play a beep to the channel that stops the
    recording.
+
+Queue
+------------------
+ * Queue rules can now be stored in a database table, queue_rules. Unlike other
+   RealTime tables, the queue_rules table is only examined on module load or
+   module reload. A new general setting has been added to queuerules.conf,
+   'realtime_rules', which, when set to 'yes', will cause app_queue to look in
+   RealTime for additional queue rules to parse. Note that both the file and
+   the database can be used as a provide of queue rules when 'realtime_rules'
+   is set to 'yes'.
+
+   When app_queue is reloaded, all rules are re-parsed and loaded into memory.
+   There is no caching of RealTime queue rules.
 
 ReadFile
 ------------------

Modified: trunk/UPGRADE-13.txt
URL: http://svnview.digium.com/svn/asterisk/trunk/UPGRADE-13.txt?view=diff&rev=420625&r1=420624&r2=420625
==============================================================================
--- trunk/UPGRADE-13.txt (original)
+++ trunk/UPGRADE-13.txt Sun Aug 10 19:14:53 2014
@@ -66,6 +66,9 @@
   new method to achieve this functionality is by using sound_begin to play
   a sound to the conference when waitmarked users are moved into the conference.
 
+Queue:
+ - Queue rules provided in queuerules.conf can no longer be named "general".
+
 SetMusicOnHold:
  - The SetMusicOnHold dialplan application was deprecated and has been removed.
    Users of the application should use the CHANNEL function's musicclass
@@ -342,6 +345,11 @@
  - A new set of Alembic scripts has been added for CDR tables. This will create
    a 'cdr' table with the default schema that Asterisk expects.
 
+ - A new upgrade script has been added that adds a 'queue_rules' table for
+   app_queue. Users of app_queue can store queue rules in a database. It is
+   important to note that app_queue only looks for this table on module load or
+   module reload; for more information, see the CHANGES file.
+
 Resources:
 
 res_odbc:

Modified: trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_queue.c?view=diff&rev=420625&r1=420624&r2=420625
==============================================================================
--- trunk/apps/app_queue.c (original)
+++ trunk/apps/app_queue.c Sun Aug 10 19:14:53 2014
@@ -1362,6 +1362,9 @@
 /*! \brief queues.conf [general] option */
 static int shared_lastcall = 1;
 
+/*! \brief queuesrules.conf [general] option */
+static int realtime_rules = 0;
+
 /*! \brief Subscription to device state change messages */
 static struct stasis_subscription *device_state_sub;
 
@@ -2730,6 +2733,99 @@
 		ast_free(rule);
 		return -1;
 	}
+	return 0;
+}
+
+/*!
+ * \brief Load queue rules from realtime.
+ *
+ * Check rule for errors with time or fomatting, see if rule is relative to rest
+ * of queue, iterate list of rules to find correct insertion point, insert and return.
+ * \retval -1 on failure
+ * \retval 0 on success
+ * \note Call this with the rule_lists locked
+*/
+static int load_realtime_rules(void)
+{
+	struct ast_config *cfg;
+        struct rule_list *rl_iter, *new_rl;
+        struct penalty_rule *pr_iter;
+        char *rulecat = NULL;
+
+	if (!ast_check_realtime("queue_rules")) {
+		ast_log(LOG_WARNING, "Missing \"queue_rules\" in extconfig.conf\n");
+		return 0;
+	}
+	if (!(cfg = ast_load_realtime_multientry("queue_rules", "rule_name LIKE", "%", SENTINEL))) {
+		ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n");
+		return 0;
+	}
+	while ((rulecat = ast_category_browse(cfg, rulecat)) && !ast_strlen_zero(rulecat)) {
+		const char *timestr, *maxstr, *minstr;
+		int penaltychangetime, rule_exists = 0, inserted = 0;
+		int max_penalty = 0, min_penalty = 0, min_relative = 0, max_relative = 0;
+		struct penalty_rule *new_penalty_rule = NULL;
+		AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
+			if (!(strcasecmp(rl_iter->name, rulecat))) {
+				rule_exists = 1;
+				new_rl = rl_iter;
+				break;
+			}
+		}
+		if (!rule_exists) {
+			if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
+				ast_config_destroy(cfg);
+				return -1;
+			}
+			ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name));
+			AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list);
+		}
+		timestr = ast_variable_retrieve(cfg, rulecat, "time");
+		if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) {
+			ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules,	skipping it\n",
+				(ast_strlen_zero(timestr) ? "invalid value" : timestr), rulecat);
+			continue;
+		}
+		if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) {
+			ast_config_destroy(cfg);
+			return -1;
+		}
+		if (!(maxstr = ast_variable_retrieve(cfg, rulecat, "max_penalty")) ||
+			ast_strlen_zero(maxstr) || sscanf(maxstr, "%30d", &max_penalty) != 1) {
+			max_penalty = 0;
+			max_relative = 1;
+		} else {
+			if (*maxstr == '+' || *maxstr == '-') {
+				max_relative = 1;
+			}
+		}
+		if (!(minstr = ast_variable_retrieve(cfg, rulecat, "min_penalty")) ||
+			ast_strlen_zero(minstr) || sscanf(minstr, "%30d", &min_penalty) != 1) {
+			min_penalty = 0;
+			min_relative = 1;
+		} else {
+			if (*minstr == '+' || *minstr == '-') {
+				min_relative = 1;
+			}
+		}
+		new_penalty_rule->time = penaltychangetime;
+		new_penalty_rule->max_relative = max_relative;
+		new_penalty_rule->max_value = max_penalty;
+		new_penalty_rule->min_relative = min_relative;
+		new_penalty_rule->min_value = min_penalty;
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&new_rl->rules, pr_iter, list) {
+			if (new_penalty_rule->time < pr_iter->time) {
+				AST_LIST_INSERT_BEFORE_CURRENT(new_penalty_rule, list);
+				inserted = 1;
+			}
+		}
+		AST_LIST_TRAVERSE_SAFE_END;
+		if (!inserted) {
+			AST_LIST_INSERT_TAIL(&new_rl->rules, new_penalty_rule, list);
+		}
+	}
+
+	ast_config_destroy(cfg);
 	return 0;
 }
 
@@ -8384,6 +8480,16 @@
 	.write = queue_function_memberpenalty_write,
 };
 
+/*! Set the global queue rules parameters as defined in the "general" section of queuerules.conf */
+static void queue_rules_set_global_params(struct ast_config *cfg)
+{
+        const char *general_val = NULL;
+        realtime_rules = 0;
+        if ((general_val = ast_variable_retrieve(cfg, "general", "realtime_rules"))) {
+                realtime_rules = ast_true(general_val);
+        }
+}
+
 /*! \brief Reload the rules defined in queuerules.conf
  *
  * \param reload If 1, then only process queuerules.conf if the file
@@ -8397,7 +8503,7 @@
 	struct penalty_rule *pr_iter;
 	char *rulecat = NULL;
 	struct ast_variable *rulevar = NULL;
-	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+	struct ast_flags config_flags = { (reload && !realtime_rules) ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 
 	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");
@@ -8417,6 +8523,10 @@
 		ast_free(rl_iter);
 	}
 	while ((rulecat = ast_category_browse(cfg, rulecat))) {
+		if (!strcasecmp(rulecat, "general")) {
+			queue_rules_set_global_params(cfg);
+			continue;
+		}
 		if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) {
 			AST_LIST_UNLOCK(&rule_lists);
 			ast_config_destroy(cfg);
@@ -8431,10 +8541,15 @@
 					ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno);
 		}
 	}
+
+	ast_config_destroy(cfg);
+
+	if (realtime_rules && load_realtime_rules()) {
+		AST_LIST_UNLOCK(&rule_lists);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
 	AST_LIST_UNLOCK(&rule_lists);
-
-	ast_config_destroy(cfg);
-
 	return AST_MODULE_LOAD_SUCCESS;
 }
 

Modified: trunk/configs/samples/extconfig.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/samples/extconfig.conf.sample?view=diff&rev=420625&r1=420624&r2=420625
==============================================================================
--- trunk/configs/samples/extconfig.conf.sample (original)
+++ trunk/configs/samples/extconfig.conf.sample Sun Aug 10 19:14:53 2014
@@ -15,7 +15,7 @@
 ; database driver, database and table (or uses the
 ; name of the file as the table if not specified)
 ;
-;uncomment to load queues.conf via the odbc engine.
+; Uncomment to load queues.conf via the odbc engine.
 ;
 ;queues.conf => odbc,asterisk,ast_config
 ;extensions.conf => sqlite,asterisk,ast_config
@@ -89,6 +89,7 @@
 ;meetme => mysql,general
 ;queues => odbc,asterisk
 ;queue_members => odbc,asterisk
+;queue_rules => odbc,asterisk
 ;acls => odbc,asterisk
 ;musiconhold => mysql,general
 ;queue_log => mysql,general

Modified: trunk/configs/samples/queuerules.conf.sample
URL: http://svnview.digium.com/svn/asterisk/trunk/configs/samples/queuerules.conf.sample?view=diff&rev=420625&r1=420624&r2=420625
==============================================================================
--- trunk/configs/samples/queuerules.conf.sample (original)
+++ trunk/configs/samples/queuerules.conf.sample Sun Aug 10 19:14:53 2014
@@ -1,3 +1,14 @@
+
+[general]
+
+; Look for queue rules in the queue_rules database table through RealTime. Note
+; that this option is not strictly "RealTime", in the sense that the queue
+; rules are only loaded and parsed during module load/reload. Queue rules
+; must have a unique rule name and support relative min/max penalties.
+;
+; realtime_rules = yes
+;
+
 ; 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.




More information about the svn-commits mailing list