From 27e3ecb60702749837f2dc59d694933b12e3a7bd Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 2 Feb 2016 00:04:57 +0100 Subject: [PATCH] mtree: allow specifying column names per tree - at least two columns must be specified, first is the one corresponding to tprefix - if more than two, then the values of those columns are concatenated with a comma delimiter - columns can be specified with cols attribute in mtree definition and they must be enclosed in quotes in order to be a valid sip parameter value and be separated by comma modparam("mtree", "mtree", "name=mt;dbtable=mtree;cols='tprefix,tvalue1,tvalue2'") --- modules/mtree/mtree.c | 70 +++++++++++++++++++++++++++++--- modules/mtree/mtree.h | 9 ++++- modules/mtree/mtree_mod.c | 84 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 149 insertions(+), 14 deletions(-) diff --git a/modules/mtree/mtree.c b/modules/mtree/mtree.c index 6b6283ded05..91f3e63896b 100644 --- a/modules/mtree/mtree.c +++ b/modules/mtree/mtree.c @@ -99,9 +99,12 @@ int mt_init_list_head(void) /** * */ -m_tree_t* mt_init_tree(str* tname, str *dbtable, int type, int multi) +m_tree_t* mt_init_tree(str* tname, str *dbtable, str *scols, int type, + int multi) { m_tree_t *pt = NULL; + int i; + int c; pt = (m_tree_t*)shm_malloc(sizeof(m_tree_t)); if(pt==NULL) @@ -137,6 +140,53 @@ m_tree_t* mt_init_tree(str* tname, str *dbtable, int type, int multi) memcpy(pt->dbtable.s, dbtable->s, dbtable->len); pt->dbtable.len = dbtable->len; + if(scols!=NULL && scols->s!=NULL && scols->len>0) { + pt->scols[0].s = (char*)shm_malloc((1+scols->len)*sizeof(char)); + if(pt->scols[0].s==NULL) { + shm_free(pt->tname.s); + shm_free(pt->dbtable.s); + shm_free(pt); + LM_ERR("no more shm memory\n"); + return NULL; + } + memset(pt->scols[0].s, 0, (1+scols->len)*sizeof(char)); + memcpy(pt->scols[0].s, scols->s, scols->len); + pt->scols[0].len = scols->len; + c = 0; + for(i=0; ilen; i++) { + if(pt->scols[0].s[i]==',') { + pt->scols[c].len = (pt->scols[0].s + i - pt->scols[c].s); + LM_DBG("db table column[%d]='%.*s'\n", c, + pt->scols[c].len, pt->scols[c].s); + c++; + if(c>=MT_MAX_COLS) { + LM_ERR("too many columns %d\n", c); + shm_free(pt->scols[0].s); + shm_free(pt->tname.s); + shm_free(pt->dbtable.s); + shm_free(pt); + return NULL; + } + pt->scols[c].s = pt->scols[0].s + i + 1; + pt->scols[c].len = pt->scols[0].s + scols->len - pt->scols[c].s; + } + } + LM_DBG("db table column[%d]='%.*s'\n", c, + pt->scols[c].len, pt->scols[c].s); + if(c==0) { + LM_ERR("there must be at least two columns (prefix, value)\n"); + shm_free(pt->scols[0].s); + shm_free(pt->tname.s); + shm_free(pt->dbtable.s); + shm_free(pt); + return NULL; + } + pt->ncols = c + 1; + pt->pack[0] = 'l'; + pt->pack[1] = ','; + pt->pack[2] = '*'; + } + return pt; } @@ -723,11 +773,14 @@ int mt_table_spec(char* val) s.len = strlen(s.s); if(s.s[s.len-1]==';') s.len--; + LM_DBG("parsing [%.*s]\n", s.len, s.s); if (parse_params(&s, CLASS_ANY, &phooks, ¶ms_list)<0) return -1; memset(&tmp, 0, sizeof(m_tree_t)); for (pit = params_list; pit; pit=pit->next) { + LM_DBG("parm: %.*s=%.*s\n", pit->name.len, pit->name.s, + pit->body.len, pit->body.s); if (pit->name.len==4 && strncasecmp(pit->name.s, "name", 4)==0) { tmp.tname = pit->body; @@ -740,6 +793,10 @@ int mt_table_spec(char* val) } else if(pit->name.len==7 && strncasecmp(pit->name.s, "dbtable", 7)==0) { tmp.dbtable = pit->body; + } else if(pit->name.len==4 + && strncasecmp(pit->name.s, "cols", 4)==0) { + tmp.ncols = 1; + tmp.scols[0] = pit->body; } } if(tmp.tname.s==NULL) @@ -794,11 +851,12 @@ int mt_table_spec(char* val) { LM_DBG("adding new tname [%s]\n", tmp.tname.s); - ndl = mt_init_tree(&tmp.tname, &tmp.dbtable, tmp.type, + ndl = mt_init_tree(&tmp.tname, &tmp.dbtable, &tmp.scols[0], tmp.type, tmp.multi); if(ndl==NULL) { - LM_ERR("no more shm memory\n"); + LM_ERR("cannot init the tree [%.*s]\n", + tmp.tname.len, tmp.tname.s); goto error; } @@ -819,8 +877,8 @@ int mt_table_spec(char* val) return -1; } -m_tree_t *mt_add_tree(m_tree_t **dpt, str *tname, str *dbtable, int type, - int multi) +m_tree_t *mt_add_tree(m_tree_t **dpt, str *tname, str *dbtable, str *cols, + int type, int multi) { m_tree_t *it = NULL; m_tree_t *prev = NULL; @@ -847,7 +905,7 @@ m_tree_t *mt_add_tree(m_tree_t **dpt, str *tname, str *dbtable, int type, { LM_DBG("adding new tname [%s]\n", tname->s); - ndl = mt_init_tree(tname, dbtable, type, multi); + ndl = mt_init_tree(tname, dbtable, cols, type, multi); if(ndl==NULL) { LM_ERR("no more shm memory\n"); diff --git a/modules/mtree/mtree.h b/modules/mtree/mtree.h index 923c801ca8a..583e3658db6 100644 --- a/modules/mtree/mtree.h +++ b/modules/mtree/mtree.h @@ -63,12 +63,16 @@ typedef struct _mt_node #define MT_NODE_SIZE mt_char_list.len +#define MT_MAX_COLS 8 typedef struct _m_tree { str tname; str dbtable; int type; int multi; + int ncols; + str scols[MT_MAX_COLS]; + char pack[4]; unsigned int nrnodes; unsigned int nritems; unsigned int memsize; @@ -89,7 +93,8 @@ is_t* mt_get_tvalue(m_tree_t *pt, str *tomatch, int *len); int mt_match_prefix(struct sip_msg *msg, m_tree_t *pt, str *tomatch, int mode); -m_tree_t* mt_init_tree(str* tname, str* dbtable, int type, int multi); +m_tree_t* mt_init_tree(str* tname, str* dbtable, str *scols, int type, + int multi); void mt_free_tree(m_tree_t *pt); int mt_print_tree(m_tree_t *pt); void mt_free_node(mt_node_t *pn, int type); @@ -105,7 +110,7 @@ int mt_defined_trees(void); m_tree_t *mt_swap_list_head(m_tree_t *ntree); int mt_init_list_head(void); m_tree_t *mt_add_tree(m_tree_t **dpt, str *tname, str *dbtable, - int type, int multi); + str *cols, int type, int multi); int mt_mi_match_prefix(struct mi_node *rpl, m_tree_t *pt, str *tomatch, int mode); diff --git a/modules/mtree/mtree_mod.c b/modules/mtree/mtree_mod.c index 44fa62cf41a..b8106ea49ba 100644 --- a/modules/mtree/mtree_mod.c +++ b/modules/mtree/mtree_mod.c @@ -481,19 +481,84 @@ int mt_param(modparam_t type, void *val) } +static int mt_pack_values(m_tree_t *pt, db1_res_t* db_res, + int row, int cols, str *tvalue) +{ + static char vbuf[4096]; + int c; + int len; + char *p; + str iv; + + len = 0; + for(c=1; c=4096) { + LM_ERR("too large values (need %d)\n", len+c); + return -1; + } + p = vbuf; + for(c=1; cpack[2]; + p++; + } else if(RES_ROWS(db_res)[row].values[c].type == DB1_STRING) { + strcpy(p, RES_ROWS(db_res)[row].values[c].val.string_val); + p += strlen(RES_ROWS(db_res)[row].values[c].val.string_val); + } else if(RES_ROWS(db_res)[row].values[c].type == DB1_STR) { + strncpy(p, RES_ROWS(db_res)[row].values[c].val.str_val.s, + RES_ROWS(db_res)[row].values[c].val.str_val.len); + p += RES_ROWS(db_res)[row].values[c].val.str_val.len; + } else if(RES_ROWS(db_res)[row].values[c].type == DB1_INT) { + iv.s = sint2str(RES_ROWS(db_res)[row].values[c].val.int_val, &iv.len); + strncpy(p, iv.s, iv.len); + p += iv.len; + } + if(c+1pack[1]; + p++; + } + } + tvalue->s = vbuf; + tvalue->len = p - vbuf; + LM_DBG("packed: [%.*s]\n", tvalue->len, tvalue->s); + return 0; +} + static int mt_load_db(m_tree_t *pt) { - db_key_t db_cols[3] = {&tprefix_column, &tvalue_column}; + db_key_t db_cols[MT_MAX_COLS] = {&tprefix_column, &tvalue_column}; db_key_t key_cols[1]; db_op_t op[1] = {OP_EQ}; db_val_t vals[1]; str tprefix, tvalue; db1_res_t* db_res = NULL; - int i, ret; + int i, ret, c; m_tree_t new_tree; m_tree_t *old_tree = NULL; mt_node_t *bk_head = NULL; + if(pt->ncols>0) { + for(c=0; cncols; c++) { + db_cols[c] = &pt->scols[c]; + } + } else { + db_cols[0] = &tprefix_column; + db_cols[1] = &tvalue_column; + c = 2; + } key_cols[0] = &tname_column; VAL_TYPE(vals) = DB1_STRING; VAL_NULL(vals) = 0; @@ -530,7 +595,7 @@ static int mt_load_db(m_tree_t *pt) if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) { if(mt_dbf.query(db_con, key_cols, op, vals, db_cols, pt->multi, - 2, 0, 0) < 0) + c, 0, 0) < 0) { LM_ERR("Error while querying db\n"); return -1; @@ -578,8 +643,15 @@ static int mt_load_db(m_tree_t *pt) tprefix.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val); tprefix.len = strlen(ZSW(tprefix.s)); - tvalue.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val); - tvalue.len = strlen(ZSW(tvalue.s)); + if(c>2) { + if(mt_pack_values(&new_tree, db_res, i, c, &tvalue)<0) { + LM_ERR("Error packing values\n"); + goto error; + } + } else { + tvalue.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val); + tvalue.len = strlen(ZSW(tvalue.s)); + } if(tprefix.s==NULL || tvalue.s==NULL || tprefix.len<=0 || tvalue.len<=0) @@ -719,7 +791,7 @@ static int mt_load_db_trees() LM_ERR("Error - bad values in db\n"); continue; } - new_tree = mt_add_tree(&new_head, &tname, &db_table, + new_tree = mt_add_tree(&new_head, &tname, &db_table, NULL, _mt_tree_type, 0); if(new_tree==NULL) {