--- apps/app_queue.c.orig 2014-06-05 12:25:49.000000000 +0300 +++ apps/app_queue.c 2014-06-05 14:29:03.000000000 +0300 @@ -25,6 +25,9 @@ * \arg Config in \ref Config_qu queues.conf * * \par Development notes + * + * \note 08/05/2014 Added Queue Rules from realtime as option by Michael K. (Voicenter) + * * \note 2004-11-25: Persistent Dynamic Members added by: * NetNation Communications (www.netnation.com) * Kevin Lindsay @@ -928,6 +931,9 @@ static int montype_default = 0; /*! \brief queues.conf [general] option */ static int shared_lastcall = 1; +/*! \brief queues.conf [general] option */ +static int realtime_rules = 0; + /*! \brief Subscription to device state change events */ static struct ast_event_sub *device_state_sub; @@ -1075,11 +1081,6 @@ struct penalty_rule { AST_LIST_ENTRY(penalty_rule) list; /*!< Next penalty_rule */ }; -struct allowed_dtmf { - char digit[AST_MAX_EXTENSION]; /*!< Digit allow to be */ - AST_LIST_ENTRY(allowed_dtmf) list; /*!< */ -}; - #define ANNOUNCEPOSITION_YES 1 /*!< We announce position */ #define ANNOUNCEPOSITION_NO 2 /*!< We don't announce position */ #define ANNOUNCEPOSITION_MORE_THAN 3 /*!< We say "Currently there are more than " */ @@ -6794,6 +6795,38 @@ static struct ast_custom_function queuem .write = queue_function_memberpenalty_write, }; +/*! Set the global queue parameters as defined in the "general" section of queues.conf */ +static void queue_set_global_params(struct ast_config *cfg) +{ + const char *general_val = NULL; + queue_persistent_members = 0; + 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); + montype_default = 0; + if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) { + if (!strcasecmp(general_val, "mixmonitor")) + montype_default = 1; + } + update_cdr = 0; + if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr"))) + update_cdr = ast_true(general_val); + shared_lastcall = 0; + if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall"))) + shared_lastcall = ast_true(general_val); +} + +/*! 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 @@ -6802,13 +6835,15 @@ static struct ast_custom_function queuem */ static int reload_queue_rules(int reload) { + struct ast_config *cfg; struct rule_list *rl_iter, *new_rl; 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"); return AST_MODULE_LOAD_SUCCESS; @@ -6826,51 +6861,116 @@ static int reload_queue_rules(int reload ast_free(pr_iter); ast_free(rl_iter); } - while ((rulecat = ast_category_browse(cfg, rulecat))) { - if (!(new_rl = ast_calloc(1, sizeof(*new_rl)))) { + 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); + return AST_MODULE_LOAD_FAILURE; + } else { + ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name)); + AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list); + for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next) + if(!strcasecmp(rulevar->name, "penaltychange")) + insert_penaltychange(new_rl->name, rulevar->value, rulevar->lineno); + else + 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_NOTICE, "Missing \"queue_rules\" in extconfigs.conf\n"); AST_LIST_UNLOCK(&rule_lists); - ast_config_destroy(cfg); - return AST_MODULE_LOAD_FAILURE; - } else { - ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name)); - AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list); - for (rulevar = ast_variable_browse(cfg, rulecat); rulevar; rulevar = rulevar->next) - if(!strcasecmp(rulevar->name, "penaltychange")) - insert_penaltychange(new_rl->name, rulevar->value, rulevar->lineno); - else - ast_log(LOG_WARNING, "Don't know how to handle rule type '%s' on line %d\n", rulevar->name, rulevar->lineno); + 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, bailing 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) { + ; + }else{ + ast_log(LOG_NOTICE,"Failed to load time for one of the %s rules ­ skipping 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; + 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); - return AST_MODULE_LOAD_SUCCESS; } - -/*! Set the global queue parameters as defined in the "general" section of queues.conf */ -static void queue_set_global_params(struct ast_config *cfg) -{ - const char *general_val = NULL; - queue_persistent_members = 0; - 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); - montype_default = 0; - if ((general_val = ast_variable_retrieve(cfg, "general", "monitor-type"))) { - if (!strcasecmp(general_val, "mixmonitor")) - montype_default = 1; - } - update_cdr = 0; - if ((general_val = ast_variable_retrieve(cfg, "general", "updatecdr"))) - update_cdr = ast_true(general_val); - shared_lastcall = 0; - if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall"))) - shared_lastcall = ast_true(general_val); -} - /*! \brief reload information pertaining to a single member * * This function is called when a member = line is encountered in @@ -8781,6 +8881,7 @@ static int unload_module(void) devicestate_tps = ast_taskprocessor_unreference(devicestate_tps); ao2_ref(queues, -1); ast_unload_realtime("queue_members"); +// ast_unload_realtime("queue_rules"); return res; } @@ -8854,6 +8955,7 @@ static int reload(void) { struct ast_flags mask = {AST_FLAGS_ALL & ~QUEUE_RESET_STATS,}; ast_unload_realtime("queue_members"); +// ast_unload_realtime("queue_rules"); reload_handler(1, &mask, NULL); return 0; }