Skip to content

Commit

Permalink
mtree: allow specifying column names per tree
Browse files Browse the repository at this point in the history
- 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'")
  • Loading branch information
miconda committed Feb 1, 2016
1 parent 5bd26e2 commit 27e3ecb
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 14 deletions.
70 changes: 64 additions & 6 deletions modules/mtree/mtree.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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; i<scols->len; 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;
}

Expand Down Expand Up @@ -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, &params_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;
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand All @@ -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");
Expand Down
9 changes: 7 additions & 2 deletions modules/mtree/mtree.h
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand Down
84 changes: 78 additions & 6 deletions modules/mtree/mtree_mod.c
Expand Up @@ -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<cols; c++) {
if(VAL_NULL(&RES_ROWS(db_res)[row].values[c])) {
len += 1;
} else if(RES_ROWS(db_res)[row].values[c].type == DB1_STRING) {
len += strlen(RES_ROWS(db_res)[row].values[c].val.string_val);
} else if(RES_ROWS(db_res)[row].values[c].type == DB1_STR) {
len += RES_ROWS(db_res)[row].values[c].val.str_val.len;
} else if(RES_ROWS(db_res)[row].values[c].type == DB1_INT) {
len += 12;
} else {
LM_ERR("unsupported data type for column %d\n", c);
return -1;
}
}
if(len + c>=4096) {
LM_ERR("too large values (need %d)\n", len+c);
return -1;
}
p = vbuf;
for(c=1; c<cols; c++) {
if(VAL_NULL(&RES_ROWS(db_res)[row].values[c])) {
*p = pt->pack[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+1<cols) {
*p = pt->pack[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; c<pt->ncols; 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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down

0 comments on commit 27e3ecb

Please sign in to comment.