From 888053b3b5975c1d24bd075248af056a23f39a9d Mon Sep 17 00:00:00 2001 From: tallicamike Date: Mon, 6 Oct 2014 16:03:05 +0300 Subject: [PATCH] [qrouting] added grp score, drouting sorting callback based, free shm memory for dialog_prop and trans_prop --- modules/drouting/dr_cb.c | 146 ++++++++++++++++++++++++++++++--- modules/drouting/dr_cb.h | 14 ++-- modules/drouting/drouting.c | 99 +++++++++++++++++++--- modules/drouting/prefix_tree.h | 1 + modules/qrouting/qr_acc.c | 13 ++- modules/qrouting/qr_sort.c | 98 ++++++++++++++++++---- modules/qrouting/qr_stats.c | 37 ++++++--- modules/qrouting/qr_stats.h | 4 +- 8 files changed, 349 insertions(+), 63 deletions(-) diff --git a/modules/drouting/dr_cb.c b/modules/drouting/dr_cb.c index 163906aaa6..6782885086 100644 --- a/modules/drouting/dr_cb.c +++ b/modules/drouting/dr_cb.c @@ -61,8 +61,42 @@ static void destroy_dr_callbacks_list(struct dr_callback *cb) } } +void destroy_dr_cbs(int types) { + int i; + struct dr_callback *dr_sort_cb_it; + + if(types & DRCB_REG_ADD_RULE || types & DRCB_REG_CR + || types & DRCB_REG_GW || types & DRCB_REG_INIT_RULE) { + if(dr_reg_cbs && dr_reg_cbs != POINTER_CLOSED_MARKER) { + destroy_dr_callbacks_list(dr_reg_cbs->first); + shm_free(dr_reg_cbs); + } + dr_reg_cbs = POINTER_CLOSED_MARKER; + } + else if(types & DRCB_ACC_CALL) { + if(dr_acc_cbs && dr_acc_cbs != POINTER_CLOSED_MARKER) { + destroy_dr_callbacks_list(dr_acc_cbs->first); + shm_free(dr_acc_cbs); + } + dr_acc_cbs = POINTER_CLOSED_MARKER; + } + else if(types & DRCB_SORT_DST) { + for(i=0; i callback_param_free && dr_sort_cb_it->param) { + dr_sort_cb_it->callback_param_free(dr_sort_cb_it->param); + dr_sort_cb_it->param = NULL; + } + } + } + +} -void destroy_dr_cbs(void) +/* + * adds a given callback to a given callback list + */ +int insert_drcb(struct dr_head_cbl **dr_cb_list, struct dr_callback *cb, + int types) { int i; struct dr_callback *dr_sort_cb_it; @@ -80,8 +114,16 @@ void destroy_dr_cbs(void) dr_sort_cb_it->param = NULL; } } + cb->next = (*dr_cb_list)->first; + (*dr_cb_list)->first = cb; + (*dr_cb_list)->types |= types; + return 0; } +/* TODO: param will be the index in the array */ +int register_dr_cb(int types, drouting_cb f, void *param, + param_free_cb ff) { + long int cb_sort_index = 0; /* TODO: param will be the index in the array */ int register_dr_cb(enum drcb_types type, dr_cb f, void *param, @@ -90,11 +132,49 @@ int register_dr_cb(enum drcb_types type, dr_cb f, void *param, long int cb_sort_index = 0; struct dr_callback *cb; - cb = (struct dr_callback*)shm_malloc(sizeof(struct dr_callback)); - if (cb == 0) { - LM_ERR("no more shm memory\n"); - return -1; - } + if((types != 0) && (types & (types-1)) == 0) { /* check that the type is a + power of two - only one + type of cb selected */ + cb = (struct dr_callback*)shm_malloc(sizeof(struct dr_callback)); + if(cb == 0) { + LM_ERR("no more shm memory\n"); + return -1; + } + + cb->types = types; + cb->callback = f; + if(!(types & DRCB_SORT_DST)) { + cb->param = param; /* because now param holds the type of the + sorting function */ + } else { + cb->param = NULL; + } + cb->callback_param_free = ff; + cb->next = NULL; + + if(types & DRCB_SORT_DST) { + if(param == NULL) { + LM_ERR("no index supplied for sort callback registered at dr\n"); + return -1; + } + cb_sort_index = (long int)param; + if(cb_sort_index > N_MAX_SORT_CBS) { + LM_ERR("Sort cbs array not large enough to accomodate cb at dr\n"); + return -1; + } + if(dr_sort_cbs[cb_sort_index] != NULL) { + LM_WARN("[dr] sort callback at index '%ld' will be overwritten\n", + cb_sort_index); + } + dr_sort_cbs[cb_sort_index] = cb; + } else if(types & DRCB_ACC_CALL) { + if(insert_drcb(&dr_acc_cbs, cb, types) == -1) + goto error; + } else if(types & (DRCB_REG_INIT_RULE | DRCB_REG_GW | + DRCB_REG_CR | DRCB_REG_ADD_RULE)) { + if(insert_drcb(&dr_reg_cbs, cb, types) == -1) + goto error; + } cb->callback = f; cb->callback_param_free = ff; @@ -147,15 +227,55 @@ int run_dr_sort_cbs(sort_cb_type type, void *param) return 0; } +/* runs a callback from an array - sort_cb_type will represent + * the index within the array */ +int run_indexed_callback(struct dr_callback **dr_sort_cbs_lst, sort_cb_type type, + void *params, int max_type) { + struct dr_cb_params *param = NULL; -int run_dr_cbs(enum drcb_types type, void *param) -{ - struct dr_callback *it; + if(type > max_type) { + LM_WARN("No such '%d' callback exists\n", type); + return -1; + } - it = dr_cbs[type]; - while(it) { - it->callback(param); - it = it->next; + if(dr_sort_cbs_lst[type] == NULL) { + LM_WARN("callback type '%d' not registered\n", type); + return -1; + } + if(params != NULL) { + param = (struct dr_cb_params *) shm_malloc(sizeof(struct dr_cb_params)); + if(param == NULL) { + LM_ERR("no more shm memory\n"); + return -1; + } + } + param->param = ¶ms; + dr_sort_cbs_lst[type]->callback(0, param); + return 0; +} + +int run_dr_cbs(struct dr_head_cbl *dr_cb_lst, int type, void *params) { + struct dr_callback * dr_cb_it; + struct dr_cb_params *param = NULL; + if(params != NULL) { + param = (struct dr_cb_params *) shm_malloc(sizeof(struct dr_cb_params)); + if(param == NULL) { + LM_ERR("no more shm memory\n"); + return -1; + } + } + if(dr_cb_lst != NULL && (dr_cb_lst->types & type)) { + dr_cb_it = dr_cb_lst->first; + while(dr_cb_it) { + if(dr_cb_it->types & type) { + param->param = ¶ms; + dr_cb_it->callback(dr_cb_it->types, param); + } + dr_cb_it = dr_cb_it->next; + } + } else { + LM_WARN("No callback list to match the given type\n"); + return -1; } return 0; } diff --git a/modules/drouting/dr_cb.h b/modules/drouting/dr_cb.h index 511d2727ec..ee2a3a67bf 100644 --- a/modules/drouting/dr_cb.h +++ b/modules/drouting/dr_cb.h @@ -19,14 +19,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * History - * ------- - * 2014-09-24 initial version (Mihai Tiganus) - * 2016-02-18 ported to 2.2 (bogdan) */ - #ifndef _DR_CB_H_ #define _DR_CB_H_ @@ -61,6 +55,13 @@ struct dr_acc_call_params { struct sip_msg *msg; }; +struct dr_sort_params { + pgw_list_t *pgwl; /* gws/cr to be sorted */ + int size; /* the size of pgwl */ + unsigned short *sorted_dst; /* returns an array with the indexes of the sorted dest */ + int rc; /* return code for the funciton */ +}; + /* callback function prototype */ @@ -80,6 +81,7 @@ struct dr_callback { dr_param_free_cb* callback_param_free; struct dr_callback * next; }; +/* TODO: should i have a different structure for sort_callbacks */ /* sorting related data */ diff --git a/modules/drouting/drouting.c b/modules/drouting/drouting.c index e8c958aae9..ee499e88e3 100644 --- a/modules/drouting/drouting.c +++ b/modules/drouting/drouting.c @@ -37,6 +37,7 @@ #include "dr_clustering.h" #include "dr_api.h" #include "dr_api_internal.h" +#include "dr_cb.h" #include "../../mem/rpm_mem.h" @@ -44,6 +45,7 @@ #define DR_PARAM_RULE_FALLBACK (1<<1) #define DR_PARAM_STRICT_LEN (1<<2) #define DR_PARAM_ONLY_CHECK (1<<3) +#define DR_PARAM_USE_QR (1<<4) #define DR_PARAM_INTERNAL_TRIGGERED (1<<30) #define DRD_TABLE_VER 6 @@ -305,6 +307,13 @@ mi_response_t *mi_dr_enable_probing_1(const mi_params_t *params, /*0-> disabled, 1 ->enabled*/ unsigned int *dr_enable_probing_state=0; +/* sorting functions used by dr */ +static void no_sort(int type, struct dr_cb_params *param); +static void weight_based_sort(int type, struct dr_cb_params *params); +static int sort_rt_dst(pgw_list_t *pgwl, int size, int type, + unsigned short *idx); + + /* event */ static str dr_event = str_init("E_DROUTING_STATUS"); static event_id_t dr_evi_id; @@ -1386,6 +1395,25 @@ static int dr_init(void) LM_INFO("starting drouting with cache head=%p\n", dr_cache); } + /* register dr callbacks for sorting */ + if(register_drcb(DRCB_SORT_DST, &no_sort, (void*)NO_SORT, NULL) < 0) { + LM_ERR("[DR] failed to register DRCB_SORT_DST callback [no_sort] to dr\n"); + return -1; + } + if(register_drcb(DRCB_SORT_DST, &weight_based_sort, + (void*)WEIGHT_BASED_SORT, NULL) < 0) { + LM_ERR("[DR] failed to register DRCB_SORT_DST callback" \ + " [weight_based_sort] to dr\n"); + return -1; + + } + + name_w_part.s = shm_malloc( MAX_LEN_NAME_W_PART /* length of + fixed string */); + if( name_w_part.s == 0 ) { + LM_ERR(" No more shm memory [drouting:name_w_part.s]\n"); + goto error; + if( use_partitions == 1 ) { /* loading configurations from db */ if (get_config_from_db() == -1) { LM_ERR("Failed to get configuration from db_config\n"); @@ -2397,20 +2425,66 @@ static int use_next_gw(struct sip_msg* msg, } \ }while(0) \ -static int sort_rt_dst(pgw_list_t *pgwl, unsigned short size, - int weight, unsigned short *idx) +/* don't sort anything let the list as it is */ +static void no_sort(int type, struct dr_cb_params *param) { + int i; + unsigned short *sorted_dst; + int size; + + size = ((struct dr_sort_params*)*param->param)->size; + sorted_dst = ((struct dr_sort_params*)*param->param)->sorted_dst; + + for(i = 0; i < size; i++) { + sorted_dst[i] = i; /* leave the gw list as itis */ + } + ((struct dr_sort_params*)*param->param)->sorted_dst = sorted_dst; + ((struct dr_sort_params*)*param->param)->rc = 0; /* everything ok */ +} +#define DR_MAX_GWLIST 64 + +static int sort_rt_dst(pgw_list_t *pgwl, int size, int type, unsigned short *idx) { + struct dr_sort_params * sort_params; + + sort_params = (struct dr_sort_params *)pkg_malloc( + sizeof(struct dr_sort_params)); + if(sort_params == NULL) { + LM_ERR("no more pkg memory\n"); + return -1; + } + sort_params->pgwl = pgwl; + sort_params->size = size; + sort_params->sorted_dst = idx; + if(!pgwl->is_carrier && (type & DR_PARAM_USE_WEIGTH)) { + run_indexed_callback(dr_sort_cbs, WEIGHT_BASED_SORT, (void*)sort_params + ,N_MAX_SORT_CBS); + } else if(pgwl->is_carrier && (type & DR_CR_FLAG_WEIGHT)) { + run_indexed_callback(dr_sort_cbs, WEIGHT_BASED_SORT, (void*)sort_params + ,N_MAX_SORT_CBS); + } else { + run_indexed_callback(dr_sort_cbs, NO_SORT, (void*)sort_params + ,N_MAX_SORT_CBS); + } + return 0; +} +/* sort based on the weight of the gws */ +static void weight_based_sort(int type, struct dr_cb_params *params) { static unsigned short *running_sum = NULL; static unsigned short sum_buf_size = 0; unsigned int i, first, weight_sum, rand_no; + pgw_list_t *pgwl; + int size; + unsigned short *idx; + + pgwl = ((struct dr_sort_params*)*params->param)->pgwl; + size = ((struct dr_sort_params*)*params->param)->size; + idx = ((struct dr_sort_params*)*params->param)->sorted_dst; + /* populate the index array */ for( i=0 ; i1) { resize_dr_sort_buffer( running_sum, sum_buf_size, size, err); /* calculate the running sum */ @@ -2429,6 +2503,7 @@ static int sort_rt_dst(pgw_list_t *pgwl, unsigned short size, if (running_sum[i]>rand_no) break; if (i==size) { LM_CRIT("bug in weight sort\n"); + ((struct dr_sort_params*)*params->param)->rc = -1; goto err; } } else { @@ -2446,14 +2521,12 @@ static int sort_rt_dst(pgw_list_t *pgwl, unsigned short size, first ++; } - return 0; -err: - return -1; + ((struct dr_sort_params*)*params->param)->rc = 0; } inline static int push_gw_for_usage(struct sip_msg *msg, struct head_db *current_partition, - struct sip_uri *uri, rt_info_t *rt, pgw_list_t * dst, int cr_id, int gw_id/* pgw_t *gw , str *c_id, str *c_attrs */, int idx) + struct sip_uri *uri, rt_info_t *rt, pgw_list_t * dst, int cr_id, int gw_id, int idx) { char buf[PTR_STRING_SIZE]; /* a hexa string */ str *ruri; @@ -2475,7 +2548,7 @@ inline static int push_gw_for_usage(struct sip_msg *msg, struct head_db *current gw = rt->pgwl[cr_id].dst.carrier->pgwl[gw_id].dst.gw; } } else if(dst != NULL) { /* routing was not done rule-based => don't use - qrouting : called from route_2gw or route_2cr */ +qrouting : called from route_2gw or route_2cr */ if(dst->is_carrier) { gw = dst->dst.carrier->pgwl[gw_id].dst.gw; c_id = &dst->dst.carrier->id; @@ -2523,7 +2596,7 @@ inline static int push_gw_for_usage(struct sip_msg *msg, struct head_db *current LM_INFO("RUN CALL\n"); run_callbacks(dr_acc_cbs, DRCB_ACC_CALL, acc_call_params); /* qr - accouting */ + accouting */ } } else { @@ -2879,7 +2952,7 @@ static int do_routing(struct sip_msg* msg, struct head_db *part, int grp, /* sort the destination elements in the rule */ resize_dr_sort_buffer( dsts_idx, dsts_idx_size, rt_info->pgwa_len, error2); i = sort_rt_dst(rt_info->pgwl, rt_info->pgwa_len, - flags&DR_PARAM_USE_WEIGTH, dsts_idx); + flags, dsts_idx); if (i!=0) { LM_ERR("failed to sort destinations in rule\n"); goto error2; @@ -2920,7 +2993,7 @@ static int do_routing(struct sip_msg* msg, struct head_db *part, int grp, resize_dr_sort_buffer( carrier_idx, carrier_idx_size, dst->dst.carrier->pgwa_len, skip); j = sort_rt_dst(dst->dst.carrier->pgwl, dst->dst.carrier->pgwa_len, - dst->dst.carrier->flags&DR_CR_FLAG_WEIGHT, carrier_idx); + dst->dst.carrier->flags, carrier_idx); if (j!=0) { LM_ERR("failed to sort gws for carrier <%.*s>, skipping\n", dst->dst.carrier->id.len, dst->dst.carrier->id.s); diff --git a/modules/drouting/prefix_tree.h b/modules/drouting/prefix_tree.h index e3f41d8c5b..c9ee8bade6 100644 --- a/modules/drouting/prefix_tree.h +++ b/modules/drouting/prefix_tree.h @@ -104,6 +104,7 @@ typedef struct pgw_list_ { #define DR_CR_FLAG_FIRST (1<<1) #define DR_CR_FLAG_IS_OFF (1<<2) #define DR_CR_FLAG_DIRTY (1<<3) +#define DR_CR_FLAG_QR (1<<4) /* list of carriers */ struct pcr_ { diff --git a/modules/qrouting/qr_acc.c b/modules/qrouting/qr_acc.c index 9fb8f2a52b..3a94390371 100644 --- a/modules/qrouting/qr_acc.c +++ b/modules/qrouting/qr_acc.c @@ -219,6 +219,9 @@ static void call_ended(struct dlg_cell* dlg, int type, ++(dialog_prop->gw->current_interval.n.cd); dialog_prop->gw->current_interval.stats.cd += cd; lock_release(dialog_prop->gw->acc_lock); + if(dialog_prop != NULL) { + release_dialog_prop(dialog_prop); + } } /* @@ -288,7 +291,6 @@ void qr_check_reply_tmcb(struct cell *cell, int type, struct tmcb_params *ps) { LM_ERR("failed to register callback for call termination\n"); goto error; } - LM_INFO("callback for call duration registered\n"); } else if (ps->code != 408 || (ps->code == 408 && (cell->flags & T_UAC_HAS_RECV_REPLY) )){ /* if it's 408 it must have one provisional response */ @@ -301,6 +303,12 @@ void qr_check_reply_tmcb(struct cell *cell, int type, struct tmcb_params *ps) { ++(trans_prop->gw->current_interval.n.ok); lock_release(trans_prop->gw->acc_lock); } + + /* transaction properties are no longer needed */ + if(trans_prop != NULL) { + release_trans_prop(trans_prop); + } + return ; error: if(dialog_prop != NULL) { @@ -387,8 +395,11 @@ void update_gw_stats(qr_gw_t *gw) { /* update the statistics for a group of gateways */ void update_grp_stats(qr_grp_t grp) { int i; + for(i = 0; i < grp.n; i++) { update_gw_stats(grp.gw[i]); } + grp.state |= QR_STATUS_DIRTY; } + diff --git a/modules/qrouting/qr_sort.c b/modules/qrouting/qr_sort.c index 4bb57decd1..84baa2c7f3 100644 --- a/modules/qrouting/qr_sort.c +++ b/modules/qrouting/qr_sort.c @@ -28,6 +28,9 @@ */ #include "qr_sort.h" +#define QR_PENALTY_THRESHOLD_1 1 +#define QR_PENALTY_THRESHOLD_2 1 + int qr_add_gw_to_list(qr_sorted_list_t **sorted_list, qr_gw_t *gw) { qr_sorted_elem_t *new_elem = (qr_sorted_elem_t*)shm_malloc( @@ -41,9 +44,12 @@ int qr_add_gw_to_list(qr_sorted_list_t **sorted_list, qr_gw_t *gw) { memset(new_elem, 0, sizeof(qr_sorted_elem_t)); new_elem->dr_gw = gw->dr_gw; + lock_start_read(gw->ref_lock); if(sorted_list[gw->score]->start == NULL) { /* list was empty */ + lock_stop_read(gw->ref_lock); sorted_list[gw->score]->start = new_elem; } else { /* list was not empty */ + lock_stop_read(gw->ref_lock); sorted_list[gw->score]->end->next = new_elem; } @@ -117,32 +123,92 @@ inline double acd(qr_gw_t *gw) { lock_stop_read(gw->ref_lock); return acd; } + +static inline void qr_mark_gw_dsbl(qr_gw_t *gw) { + lock_start_write(gw->ref_lock); + gw->state |= QR_STATUS_DSBL; /* mark the gateway as disabled */ + lock_stop_write(gw->ref_lock); +} /* * computes the score of the gateway using the warning * thresholds */ -void qr_score(qr_gw_t *gw, qr_thresholds_t * thresholds) { - int score = 0; +int qr_score_gw(qr_gw_t *gw, qr_thresholds_t * thresholds) { + int score = 0, asr_v, ccr_v, pdd_v, ast_v, acd_v; /* FIXME: might be better under a single lock * because of possible changes between lock ( a * new sampling interval might bring new statistics) */ - if(asr(gw)asr1) - ++score; - if(ccr(gw)ccr1) - ++score; - if(pdd(gw)>thresholds->pdd1) - ++score; - if(ast(gw)>thresholds->ast1) - ++score; - if(acd(gw)>thresholds->acd1) - ++score; + asr_v = asr(gw); + if(asr_v < thresholds->asr1) { + score += QR_PENALTY_THRESHOLD_2; + if(asr_v < thresholds->asr2) { + score += QR_PENALTY_THRESHOLD_2; + qr_mark_gw_dsbl(gw); + } + } + ccr_v = ccr(gw); + if(ccr_v < thresholds->ccr1) { + score += QR_PENALTY_THRESHOLD_1; + if(ccr_v < thresholds->ccr2) { + score += QR_PENALTY_THRESHOLD_2; + qr_mark_gw_dsbl(gw); + } + } + pdd_v = pdd(gw); + if(pdd_v > thresholds->pdd1) { + score += QR_PENALTY_THRESHOLD_1; + if(pdd_v > thresholds->pdd2) { + score += QR_PENALTY_THRESHOLD_2; + qr_mark_gw_dsbl(gw); + } + } + ast_v = ast(gw); + if(ast_v > thresholds->ast1) { + score += QR_PENALTY_THRESHOLD_1; + if(ast_v > thresholds->ast2) { + score +=QR_PENALTY_THRESHOLD_2; + qr_mark_gw_dsbl(gw); + } + } + acd_v = acd(gw); + if(acd_v > thresholds->acd1) { + score += QR_PENALTY_THRESHOLD_1; + if(ast_v > thresholds->acd2) { + score += QR_PENALTY_THRESHOLD_2; + qr_mark_gw_dsbl(gw); + } + } /* update gw score and status */ lock_start_write(gw->ref_lock); gw->score = score; gw->state &= ~QR_STATUS_DIRTY; lock_stop_write(gw->ref_lock); + + return 0; +} + +void qr_score_grp(qr_grp_t *grp, qr_thresholds_t * thresholds) { + int i; + int mean = 0; + + for(i = 0; i < grp->n; i++) { + lock_start_read(grp->gw[i]->ref_lock); + if(grp->gw[i]->state & QR_STATUS_DIRTY) { + lock_stop_read(grp->gw[i]->ref_lock); + mean += qr_score_gw(grp->gw[i], thresholds); + + } else { + lock_stop_read(grp->gw[i]->ref_lock); + } + } + mean /= grp->n; + lock_start_write(grp->ref_lock); + grp->score = mean; + grp->state &= ~QR_STATUS_DIRTY; + lock_stop_write(grp->ref_lock); + } /* * inserts destination in sorted list @@ -151,14 +217,14 @@ inline int qr_insert_dst(qr_sorted_list_t **sorted, qr_rule_t *rule, int dst_id) { if(rule->dest[dst_id].type & QR_DST_GRP) { return -1; /* TODO group support - should accept multiple - sorting methods*/ + should accept multiple + sorting methods*/ } lock_start_read(rule->dest[dst_id].dst.gw->ref_lock); if(rule->dest[dst_id].dst.gw->state & QR_STATUS_DIRTY) { lock_stop_read(rule->dest[dst_id].dst.gw->ref_lock); - qr_score(rule->dest[dst_id].dst.gw, &rule->thresholds); /* compute the - score */ + qr_score_gw(rule->dest[dst_id].dst.gw, &rule->thresholds); /* compute the + score */ rule->dest[dst_id].dst.gw->state &= ~QR_STATUS_DIRTY; } else { lock_stop_read(rule->dest[dst_id].dst.gw->ref_lock); diff --git a/modules/qrouting/qr_stats.c b/modules/qrouting/qr_stats.c index 942709934f..12a7b3ab53 100644 --- a/modules/qrouting/qr_stats.c +++ b/modules/qrouting/qr_stats.c @@ -191,26 +191,37 @@ void qr_dst_is_grp(int type, struct dr_cb_params *params) { if(rule != NULL) { rule->dest[n_dst].type = QR_DST_GRP; + memset(&rule->dest[n_dst].dst.grp, 0, sizeof(qr_grp_t)); + rule->dest[n_dst].dst.grp.state |= QR_STATUS_DIRTY; rule->dest[n_dst].dst.grp.gw = (qr_gw_t**)shm_malloc(n_gws * sizeof(qr_gw_t*)); - if(rule->dest[n_dst].dst.grp.gw != NULL) { - rule->dest[n_dst].dst.grp.n = n_gws; - rule->dest[n_dst].dst.grp.id = cr_name; - for(i = 0; i < n_gws; i++) { - dr_gw = (void*)drb.get_gw_from_cr(grp, i); /* get the gateway - as pgw_t from dr */ - rule->dest[n_dst].dst.grp.gw[i] = qr_create_gw(dr_gw); - gw_name = drb.get_gw_name(rule->dest[n_dst].dst.grp.gw[i]->dr_gw); - LM_DBG("Gw '%.*s' added to carrier '%.*s' from rule %d\n", - gw_name->len, gw_name->s, cr_name->len, cr_name->s, - rule->r_id); - } - } else { + if(rule->dest[n_dst].dst.grp.gw == NULL) { LM_ERR("no more shm memory\n"); + goto error; + } + if ((rule->dest[n_dst].dst.grp.ref_lock = lock_init_rw()) == NULL) { + LM_ERR("failed to init RW lock\n"); + goto error; + } + + rule->dest[n_dst].dst.grp.n = n_gws; + rule->dest[n_dst].dst.grp.id = cr_name; + for(i = 0; i < n_gws; i++) { + dr_gw = (void*)drb.get_gw_from_cr(grp, i); /* get the gateway + as pgw_t from dr */ + rule->dest[n_dst].dst.grp.gw[i] = qr_create_gw(dr_gw); + gw_name = drb.get_gw_name(rule->dest[n_dst].dst.grp.gw[i]->dr_gw); + LM_DBG("Gw '%.*s' added to carrier '%.*s' from rule %d\n", + gw_name->len, gw_name->s, cr_name->len, cr_name->s, + rule->r_id); } } else { LM_ERR("bad rule\n"); } + return ; +error: + if(rule->dest[n_dst].dst.grp.gw != NULL) + shm_free(rule->dest[n_dst].dst.grp.gw); } /* add rule to internal rule list */ diff --git a/modules/qrouting/qr_stats.h b/modules/qrouting/qr_stats.h index 2fef438aa3..521b8b203c 100644 --- a/modules/qrouting/qr_stats.h +++ b/modules/qrouting/qr_stats.h @@ -99,9 +99,11 @@ typedef struct qr_grp { qr_gw_t **gw; char sort_method; /* sorting for the group */ str *id; + int score; + char state; + rw_lock_t *ref_lock; int n; } qr_grp_t; -/* TODO: add weights */ /* two types of destination */