Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 415442) +++ apps/app_queue.c (working copy) @@ -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; @@ -8389,6 +8392,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 @@ -8402,7 +8415,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"); @@ -8422,6 +8435,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); @@ -8436,6 +8453,86 @@ ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno); } } + if (realtime_rules) { + if(!ast_check_realtime("queue_rules")) { + ast_log(LOG_WARNING, "Missing \"queue_rules\" in extconfigs.conf\n"); + AST_LIST_UNLOCK(&rule_lists); + return AST_MODULE_LOAD_SUCCESS; + } + if (!(cfg = ast_load_realtime_multientry("queue_rules", "rule_name LIKE", "%", SENTINEL))) { + ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n"); + AST_LIST_UNLOCK(&rule_lists); + return AST_MODULE_LOAD_SUCCESS; + } + rulecat = NULL; + while ((rulecat = ast_category_browse(cfg, rulecat)) && !ast_strlen_zero(rulecat)) { + const char *timestr, *maxstr, *minstr; + int penaltychangetime, rule_exists = 0, max_penalty = 0, min_penalty = 0, min_relative = 0, max_relative = 0, inserted = 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_LIST_UNLOCK(&rule_lists); + ast_config_destroy(cfg); + ast_log(LOG_ERROR, "Failed to allocate memory for new queue rule, baililng out\n"); + return AST_MODULE_LOAD_FAILURE; + } + 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) || (penaltychangetime = atoi(timestr)) < 0) { + ast_log(LOG_NOTICE, "Failed to parse time for one of the %s rules, so gonna skip it\n", rulecat); + continue; + } + if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) { + ast_log(LOG_ERROR, "Failed to allocate memory for new queue rule, bailing out\n"); + AST_LIST_UNLOCK(&rule_lists); + ast_config_destroy(cfg); + return AST_MODULE_LOAD_FAILURE; + } + if (!(maxstr = ast_variable_retrieve(cfg, rulecat, "max_penalty")) || ast_strlen_zero(maxstr)) { + max_penalty = 0; + max_relative = 1; + } else { + max_penalty = atoi(maxstr); + } + if (*maxstr == '+' || *maxstr == '-') { + max_relative = 1; + } + if (!(minstr = ast_variable_retrieve(cfg, rulecat, "min_penalty")) || ast_strlen_zero(minstr)) { + min_penalty = 0; + min_relative = 1; + } else { + min_penalty = atoi(minstr); + } + 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); + inserted = 1; + } + } + } AST_LIST_UNLOCK(&rule_lists); ast_config_destroy(cfg);