00001
00024 #include <stdio.h>
00025 #include <unistd.h>
00026 #include <stdlib.h>
00027
00028 #include "../../lib/srdb1/db_op.h"
00029 #include "../../lib/kmi/mi.h"
00030 #include "../../sr_module.h"
00031 #include "../../lib/srdb1/db.h"
00032 #include "../../mem/shm_mem.h"
00033 #include "../../mem/mem.h"
00034 #include "../../dprint.h"
00035 #include "../../parser/parse_uri.h"
00036 #include "../../timer.h"
00037 #include "../../ut.h"
00038 #include "../../locking.h"
00039 #include "../../action.h"
00040 #include "../../mod_fix.h"
00041 #include "../../parser/parse_from.h"
00042
00043 #include "mtree.h"
00044
00045 MODULE_VERSION
00046
00047
00048 #define NR_KEYS 3
00049
00050 int mt_fetch_rows = 1000;
00051
00053 static db1_con_t *db_con = NULL;
00054 static db_func_t mt_dbf;
00055
00056 #if 0
00057 INSERT INTO version (table_name, table_version) values ('mtree','1');
00058 CREATE TABLE mtree (
00059 id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
00060 tprefix VARCHAR(32) NOT NULL,
00061 tvalue VARCHAR(128) DEFAULT '' NOT NULL,
00062 CONSTRAINT tprefix_idx UNIQUE (tprefix)
00063 ) ENGINE=MyISAM;
00064 INSERT INTO version (table_name, table_version) values ('mtrees','1');
00065 CREATE TABLE mtrees (
00066 id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
00067 tname VARCHAR(128) NOT NULL,
00068 tprefix VARCHAR(32) NOT NULL,
00069 tvalue VARCHAR(128) DEFAULT '' NOT NULL,
00070 CONSTRAINT tname_tprefix_idx UNIQUE (tname, tprefix)
00071 ) ENGINE=MyISAM;
00072 #endif
00073
00075 static str db_url = str_init(DEFAULT_DB_URL);
00076 static str db_table = str_init("");
00077 static str tname_column = str_init("tname");
00078 static str tprefix_column = str_init("tprefix");
00079 static str tvalue_column = str_init("tvalue");
00080
00081
00082 str mt_char_list = {"0123456789", 10};
00083
00084 static str value_param = {"$avp(s:tvalue)", 0};
00085 static str values_param = {"$avp(s:tvalues)", 0};
00086 static str dstid_param = {"$avp(s:tdstid)", 0};
00087 static str weight_param = {"$avp(s:tweight)", 0};
00088 static str count_param = {"$avp(s:tcount)", 0};
00089 pv_spec_t pv_value;
00090 pv_spec_t pv_values;
00091 pv_spec_t pv_dstid;
00092 pv_spec_t pv_weight;
00093 pv_spec_t pv_count;
00094 int _mt_tree_type = MT_TREE_SVAL;
00095 int _mt_ignore_duplicates = 0;
00096 int _mt_allow_duplicates = 0;
00097
00098
00099 static gen_lock_t *mt_lock = 0;
00100 static volatile int mt_tree_refcnt = 0;
00101 static volatile int mt_reload_flag = 0;
00102
00103 int mt_param(modparam_t type, void *val);
00104 static int fixup_mt_match(void** param, int param_no);
00105 static int w_mt_match(struct sip_msg* msg, char* str1, char* str2,
00106 char* str3);
00107
00108 static int mod_init(void);
00109 static void mod_destroy(void);
00110 static int child_init(int rank);
00111 static int mi_child_init(void);
00112
00113 static int mt_match(struct sip_msg *msg, gparam_t *dm, gparam_t *var,
00114 gparam_t *mode);
00115
00116 static struct mi_root* mt_mi_reload(struct mi_root*, void* param);
00117 static struct mi_root* mt_mi_list(struct mi_root*, void* param);
00118 static struct mi_root* mt_mi_summary(struct mi_root*, void* param);
00119
00120 static int mt_load_db(str *tname);
00121 static int mt_load_db_trees();
00122
00123 static cmd_export_t cmds[]={
00124 {"mt_match", (cmd_function)w_mt_match, 3, fixup_mt_match,
00125 0, REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE},
00126 {0, 0, 0, 0, 0, 0}
00127 };
00128
00129 static param_export_t params[]={
00130 {"mtree", STR_PARAM|USE_FUNC_PARAM, (void*)mt_param},
00131 {"db_url", STR_PARAM, &db_url.s},
00132 {"db_table", STR_PARAM, &db_table.s},
00133 {"tname_column", STR_PARAM, &tname_column.s},
00134 {"tprefix_column", STR_PARAM, &tprefix_column.s},
00135 {"tvalue_column", STR_PARAM, &tvalue_column.s},
00136 {"char_list", STR_PARAM, &mt_char_list.s},
00137 {"fetch_rows", INT_PARAM, &mt_fetch_rows},
00138 {"pv_value", STR_PARAM, &value_param.s},
00139 {"pv_values", STR_PARAM, &values_param.s},
00140 {"pv_dstid", STR_PARAM, &dstid_param.s},
00141 {"pv_weight", STR_PARAM, &weight_param.s},
00142 {"pv_count", STR_PARAM, &count_param.s},
00143 {"mt_tree_type", INT_PARAM, &_mt_tree_type},
00144 {"mt_ignore_duplicates", INT_PARAM, &_mt_ignore_duplicates},
00145 {"mt_allow_duplicates", INT_PARAM, &_mt_allow_duplicates},
00146 {0, 0, 0}
00147 };
00148
00149 static mi_export_t mi_cmds[] = {
00150 { "mt_reload", mt_mi_reload, 0, 0, mi_child_init },
00151 { "mt_list", mt_mi_list, 0, 0, 0 },
00152 { "mt_summary", mt_mi_summary, 0, 0, 0 },
00153 { 0, 0, 0, 0, 0}
00154 };
00155
00156
00157 struct module_exports exports = {
00158 "mtree",
00159 DEFAULT_DLFLAGS,
00160 cmds,
00161 params,
00162 0,
00163 mi_cmds,
00164 0,
00165 0,
00166 mod_init,
00167 0,
00168 mod_destroy,
00169 child_init
00170 };
00171
00172
00173
00177 static int mod_init(void)
00178 {
00179 m_tree_t *pt = NULL;
00180
00181 if(register_mi_mod(exports.name, mi_cmds)!=0)
00182 {
00183 LM_ERR("failed to register MI commands\n");
00184 return -1;
00185 }
00186
00187 db_url.len = strlen(db_url.s);
00188 db_table.len = strlen(db_table.s);
00189 tname_column.len = strlen(tname_column.s);
00190 tprefix_column.len = strlen(tprefix_column.s);
00191 tvalue_column.len = strlen(tvalue_column.s);
00192
00193 value_param.len = strlen(value_param.s);
00194 values_param.len = strlen(values_param.s);
00195 dstid_param.len = strlen(dstid_param.s);
00196 weight_param.len = strlen(weight_param.s);
00197 count_param.len = strlen(count_param.s);
00198
00199 if(pv_parse_spec(&value_param, &pv_value)<00
00200 || !(pv_is_w(&pv_value)))
00201 {
00202 LM_ERR("cannot parse value pv or is read only\n");
00203 return -1;
00204 }
00205
00206 if (pv_parse_spec(&values_param, &pv_values) <0
00207 || pv_values.type != PVT_AVP) {
00208 LM_ERR("cannot parse values avp\n");
00209 return -1;
00210 }
00211
00212 if(pv_parse_spec(&dstid_param, &pv_dstid)<0
00213 || pv_dstid.type!=PVT_AVP)
00214 {
00215 LM_ERR("cannot parse dstid avp\n");
00216 return -1;
00217 }
00218
00219 if(pv_parse_spec(&weight_param, &pv_weight)<0
00220 || pv_weight.type!=PVT_AVP)
00221 {
00222 LM_ERR("cannot parse dstid avp\n");
00223 return -1;
00224 }
00225
00226 if(pv_parse_spec(&count_param, &pv_count)<0
00227 || !(pv_is_w(&pv_weight)))
00228 {
00229 LM_ERR("cannot parse count pv or is read-only\n");
00230 return -1;
00231 }
00232
00233 if(mt_fetch_rows<=0)
00234 mt_fetch_rows = 1000;
00235
00236 mt_char_list.len = strlen(mt_char_list.s);
00237 if(mt_char_list.len<=0)
00238 {
00239 LM_ERR("invalid prefix char list\n");
00240 return -1;
00241 }
00242 LM_DBG("mt_char_list=%s \n", mt_char_list.s);
00243 mt_char_table_init();
00244
00245
00246 if(db_bind_mod(&db_url, &mt_dbf))
00247 {
00248 LM_ERR("database module not found\n");
00249 return -1;
00250 }
00251
00252 if (!DB_CAPABILITY(mt_dbf, DB_CAP_ALL))
00253 {
00254 LM_ERR("database module does not "
00255 "implement all functions needed by the module\n");
00256 return -1;
00257 }
00258
00259
00260 db_con = mt_dbf.init(&db_url);
00261 if(db_con==NULL)
00262 {
00263 LM_ERR("failed to connect to the database\n");
00264 return -1;
00265 }
00266
00267 LM_DBG("database connection opened successfully\n");
00268
00269 if ( (mt_lock=lock_alloc())==0) {
00270 LM_CRIT("failed to alloc lock\n");
00271 goto error1;
00272 }
00273 if (lock_init(mt_lock)==0 ) {
00274 LM_CRIT("failed to init lock\n");
00275 goto error1;
00276 }
00277
00278 if(mt_defined_trees())
00279 {
00280 LM_DBG("static trees defined\n");
00281
00282 pt = mt_get_first_tree();
00283
00284 while(pt!=NULL)
00285 {
00286
00287 if(mt_load_db(&pt->tname)!=0)
00288 {
00289 LM_ERR("cannot load info from database\n");
00290 goto error1;
00291 }
00292 pt = pt->next;
00293 }
00294 } else {
00295 if(db_table.len<=0)
00296 {
00297 LM_ERR("no trees table defined\n");
00298 goto error1;
00299 }
00300 if(mt_init_list_head()<0)
00301 {
00302 LM_ERR("unable to init trees list head\n");
00303 goto error1;
00304 }
00305
00306 if(mt_load_db_trees()!=0)
00307 {
00308 LM_ERR("cannot load trees from database\n");
00309 goto error1;
00310 }
00311 }
00312 mt_dbf.close(db_con);
00313 db_con = 0;
00314
00315 #if 0
00316 mt_print_tree(mt_get_first_tree());
00317 #endif
00318
00319
00320 return 0;
00321
00322 error1:
00323 if (mt_lock)
00324 {
00325 lock_destroy( mt_lock );
00326 lock_dealloc( mt_lock );
00327 mt_lock = 0;
00328 }
00329 mt_destroy_trees();
00330
00331 if(db_con!=NULL)
00332 mt_dbf.close(db_con);
00333 db_con = 0;
00334 return -1;
00335 }
00336
00340 static int mi_child_init(void)
00341 {
00342 db_con = mt_dbf.init(&db_url);
00343 if(db_con==NULL)
00344 {
00345 LM_ERR("failed to connect to database\n");
00346 return -1;
00347 }
00348
00349 return 0;
00350 }
00351
00352
00353
00354 static int child_init(int rank)
00355 {
00356
00357 if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00358 return 0;
00359
00360 if ( mi_child_init()!=0 )
00361 return -1;
00362
00363 LM_DBG("#%d: database connection opened successfully\n", rank);
00364
00365 return 0;
00366 }
00367
00368
00369 static void mod_destroy(void)
00370 {
00371 LM_DBG("cleaning up\n");
00372 mt_destroy_trees();
00373 if (db_con!=NULL && mt_dbf.close!=NULL)
00374 mt_dbf.close(db_con);
00375
00376 if (mt_lock)
00377 {
00378 lock_destroy( mt_lock );
00379 lock_dealloc( mt_lock );
00380 mt_lock = 0;
00381 }
00382
00383 }
00384
00385 static int fixup_mt_match(void** param, int param_no)
00386 {
00387 if(param_no==1 || param_no==2) {
00388 return fixup_spve_null(param, 1);
00389 }
00390 if (param_no != 3) {
00391 LM_ERR("invalid parameter number %d\n", param_no);
00392 return E_UNSPEC;
00393 }
00394 return fixup_igp_null(param, 1);
00395 }
00396
00397
00398
00399 static int mt_match(struct sip_msg *msg, gparam_t *tn, gparam_t *var,
00400 gparam_t *mode)
00401 {
00402 str tname;
00403 str tomatch;
00404 int mval;
00405 m_tree_t *tr = NULL;
00406
00407 if(msg==NULL)
00408 {
00409 LM_ERR("received null msg\n");
00410 return -1;
00411 }
00412
00413 if(fixup_get_svalue(msg, tn, &tname)<0)
00414 {
00415 LM_ERR("cannot get the tree name\n");
00416 return -1;
00417 }
00418 if(fixup_get_svalue(msg, var, &tomatch)<0)
00419 {
00420 LM_ERR("cannot get the match var\n");
00421 return -1;
00422 }
00423 if(fixup_get_ivalue(msg, mode, &mval)<0)
00424 {
00425 LM_ERR("cannot get the mode\n");
00426 return -1;
00427 }
00428
00429 again:
00430 lock_get( mt_lock );
00431 if (mt_reload_flag) {
00432 lock_release( mt_lock );
00433 sleep_us(5);
00434 goto again;
00435 }
00436 mt_tree_refcnt++;
00437 lock_release( mt_lock );
00438
00439 tr = mt_get_tree(&tname);
00440 if(tr==NULL)
00441 {
00442
00443 goto error;
00444 }
00445
00446 if(mt_match_prefix(msg, tr, &tomatch, mval)<0)
00447 {
00448 LM_INFO("no prefix found in [%.*s] for [%.*s]\n",
00449 tname.len, tname.s,
00450 tomatch.len, tomatch.s);
00451 goto error;
00452 }
00453
00454 lock_get( mt_lock );
00455 mt_tree_refcnt--;
00456 lock_release( mt_lock );
00457 return 1;
00458
00459 error:
00460 lock_get( mt_lock );
00461 mt_tree_refcnt--;
00462 lock_release( mt_lock );
00463 return -1;
00464 }
00465
00466 static int w_mt_match(struct sip_msg* msg, char* str1, char* str2,
00467 char* str3)
00468 {
00469 return mt_match(msg, (gparam_t*)str1, (gparam_t*)str2, (gparam_t*)str3);
00470 }
00471
00472 int mt_param(modparam_t type, void *val)
00473 {
00474 if(val==NULL)
00475 goto error;
00476
00477 return mt_table_spec((char*)val);
00478 error:
00479 return -1;
00480
00481 }
00482
00483 static int mt_load_db(str *tname)
00484 {
00485 db_key_t db_cols[3] = {&tprefix_column, &tvalue_column};
00486 str tprefix, tvalue;
00487 db1_res_t* db_res = NULL;
00488 int i, ret;
00489 m_tree_t new_tree;
00490 m_tree_t *old_tree = NULL;
00491 mt_node_t *bk_head = NULL;
00492
00493 if(db_con==NULL)
00494 {
00495 LM_ERR("no db connection\n");
00496 return -1;
00497 }
00498
00499 old_tree = mt_get_tree(tname);
00500 if(old_tree==NULL)
00501 {
00502 LM_ERR("tree definition not found [%.*s]\n", tname->len, tname->s);
00503 return -1;
00504 }
00505 memcpy(&new_tree, old_tree, sizeof(m_tree_t));
00506 new_tree.head = 0;
00507 new_tree.next = 0;
00508
00509 if (mt_dbf.use_table(db_con, &old_tree->dbtable) < 0)
00510 {
00511 LM_ERR("failed to use_table\n");
00512 return -1;
00513 }
00514
00515 if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
00516 if(mt_dbf.query(db_con, 0, 0, 0, db_cols, 0, 2, 0, 0) < 0)
00517 {
00518 LM_ERR("Error while querying db\n");
00519 return -1;
00520 }
00521 if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0)
00522 {
00523 LM_ERR("Error while fetching result\n");
00524 if (db_res)
00525 mt_dbf.free_result(db_con, db_res);
00526 goto error;
00527 } else {
00528 if(RES_ROW_N(db_res)==0)
00529 {
00530 return 0;
00531 }
00532 }
00533 } else {
00534 if((ret=mt_dbf.query(db_con, NULL, NULL, NULL, db_cols,
00535 0, 2, 0, &db_res))!=0
00536 || RES_ROW_N(db_res)<=0 )
00537 {
00538 mt_dbf.free_result(db_con, db_res);
00539 if( ret==0)
00540 {
00541 return 0;
00542 } else {
00543 goto error;
00544 }
00545 }
00546 }
00547
00548 do {
00549 for(i=0; i<RES_ROW_N(db_res); i++)
00550 {
00551
00552 tprefix.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);
00553 tprefix.len = strlen(tprefix.s);
00554
00555 tvalue.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);
00556 tvalue.len = strlen(tvalue.s);
00557
00558 if(tprefix.s==NULL || tvalue.s==NULL
00559 || tprefix.len<=0 || tvalue.len<=0)
00560 {
00561 LM_ERR("Error - bad values in db\n");
00562 continue;
00563 }
00564
00565 if(mt_add_to_tree(&new_tree, &tprefix, &tvalue)<0)
00566 {
00567 LM_ERR("Error adding info to tree\n");
00568 goto error;
00569 }
00570 }
00571 if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
00572 if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0) {
00573 LM_ERR("Error while fetching!\n");
00574 if (db_res)
00575 mt_dbf.free_result(db_con, db_res);
00576 goto error;
00577 }
00578 } else {
00579 break;
00580 }
00581 } while(RES_ROW_N(db_res)>0);
00582 mt_dbf.free_result(db_con, db_res);
00583
00584
00585
00586 lock_get( mt_lock );
00587 mt_reload_flag = 1;
00588 lock_release( mt_lock );
00589
00590 while (mt_tree_refcnt) {
00591 sleep_us(10);
00592 }
00593
00594 bk_head = old_tree->head;
00595 old_tree->head = new_tree.head;
00596
00597 mt_reload_flag = 0;
00598
00599
00600 if (bk_head!=NULL)
00601 mt_free_node(bk_head, new_tree.type);
00602
00603 return 0;
00604
00605 error:
00606 mt_dbf.free_result(db_con, db_res);
00607 if (new_tree.head!=NULL)
00608 mt_free_node(new_tree.head, new_tree.type);
00609 return -1;
00610 }
00611
00612 static int mt_load_db_trees()
00613 {
00614 db_key_t db_cols[3] = {&tname_column, &tprefix_column, &tvalue_column};
00615 str tprefix, tvalue, tname;
00616 db1_res_t* db_res = NULL;
00617 int i, ret;
00618 m_tree_t *new_head = NULL;
00619 m_tree_t *new_tree = NULL;
00620 m_tree_t *old_head = NULL;
00621
00622 if(db_con==NULL)
00623 {
00624 LM_ERR("no db connection\n");
00625 return -1;
00626 }
00627
00628 if (mt_dbf.use_table(db_con, &db_table) < 0)
00629 {
00630 LM_ERR("failed to use_table\n");
00631 return -1;
00632 }
00633
00634 if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH))
00635 {
00636 if(mt_dbf.query(db_con,0,0,0,db_cols,0,3,&tname_column,0) < 0)
00637 {
00638 LM_ERR("Error while querying db\n");
00639 return -1;
00640 }
00641 if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0)
00642 {
00643 LM_ERR("Error while fetching result\n");
00644 if (db_res)
00645 mt_dbf.free_result(db_con, db_res);
00646 goto error;
00647 } else {
00648 if(RES_ROW_N(db_res)==0)
00649 {
00650 return 0;
00651 }
00652 }
00653 } else {
00654 if((ret=mt_dbf.query(db_con, NULL, NULL, NULL, db_cols,
00655 0, 3, &tname_column, &db_res))!=0
00656 || RES_ROW_N(db_res)<=0 )
00657 {
00658 mt_dbf.free_result(db_con, db_res);
00659 if( ret==0)
00660 {
00661 return 0;
00662 } else {
00663 goto error;
00664 }
00665 }
00666 }
00667
00668 do {
00669 for(i=0; i<RES_ROW_N(db_res); i++)
00670 {
00671
00672 tname.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);
00673 tname.len = strlen(tname.s);
00674
00675 tprefix.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);
00676 tprefix.len = strlen(tprefix.s);
00677
00678 tvalue.s = (char*)(RES_ROWS(db_res)[i].values[2].val.string_val);
00679 tvalue.len = strlen(tvalue.s);
00680
00681 if(tprefix.s==NULL || tvalue.s==NULL || tname.s==NULL ||
00682 tprefix.len<=0 || tvalue.len<=0 || tname.len<=0)
00683 {
00684 LM_ERR("Error - bad values in db\n");
00685 continue;
00686 }
00687 new_tree = mt_add_tree(&new_head, &tname, &db_table, _mt_tree_type);
00688 if(new_tree==NULL)
00689 {
00690 LM_ERR("New tree cannot be initialized\n");
00691 goto error;
00692 }
00693 if(mt_add_to_tree(new_tree, &tprefix, &tvalue)<0)
00694 {
00695 LM_ERR("Error adding info to tree\n");
00696 goto error;
00697 }
00698 }
00699 if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
00700 if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0) {
00701 LM_ERR("Error while fetching!\n");
00702 if (db_res)
00703 mt_dbf.free_result(db_con, db_res);
00704 goto error;
00705 }
00706 } else {
00707 break;
00708 }
00709 } while(RES_ROW_N(db_res)>0);
00710 mt_dbf.free_result(db_con, db_res);
00711
00712
00713 lock_get( mt_lock );
00714 mt_reload_flag = 1;
00715 lock_release( mt_lock );
00716
00717 while (mt_tree_refcnt) {
00718 sleep_us(10);
00719 }
00720
00721 old_head = mt_swap_list_head(new_head);
00722
00723 mt_reload_flag = 0;
00724
00725 if (old_head!=NULL)
00726 mt_free_tree(old_head);
00727
00728 return 0;
00729
00730 error:
00731 mt_dbf.free_result(db_con, db_res);
00732 if (new_head!=NULL)
00733 mt_free_tree(new_head);
00734 return -1;
00735 }
00736
00737
00738
00743 static struct mi_root* mt_mi_reload(struct mi_root *cmd_tree, void *param)
00744 {
00745 str tname = {0, 0};
00746 m_tree_t *pt;
00747 struct mi_node* node = NULL;
00748
00749 if(db_table.len>0)
00750 {
00751
00752 if(mt_load_db_trees()!=0)
00753 {
00754 LM_ERR("cannot re-load info from database\n");
00755 goto error;
00756 }
00757 } else {
00758 if(!mt_defined_trees())
00759 {
00760 LM_ERR("empty tree list\n");
00761 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00762 }
00763
00764
00765 node = cmd_tree->node.kids;
00766 if(node != NULL)
00767 {
00768 tname = node->value;
00769 if(tname.s == NULL || tname.len== 0)
00770 return init_mi_tree( 404, "domain not found", 16);
00771
00772 if(*tname.s=='.') {
00773 tname.s = 0;
00774 tname.len = 0;
00775 }
00776 }
00777
00778 pt = mt_get_first_tree();
00779
00780 while(pt!=NULL)
00781 {
00782 if(tname.s==NULL
00783 || (tname.s!=NULL && pt->tname.len>=tname.len
00784 && strncmp(pt->tname.s, tname.s, tname.len)==0))
00785 {
00786
00787 if(mt_load_db(&pt->tname)!=0)
00788 {
00789 LM_ERR("cannot re-load info from database\n");
00790 goto error;
00791 }
00792 }
00793 pt = pt->next;
00794 }
00795 }
00796
00797 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00798
00799 error:
00800 return init_mi_tree( 500, "Failed to reload",16);
00801 }
00802
00803
00804 int mt_print_mi_node(m_tree_t *tree, mt_node_t *pt, struct mi_node* rpl,
00805 char *code, int len)
00806 {
00807 int i;
00808 struct mi_node* node = NULL;
00809 struct mi_attr* attr= NULL;
00810 mt_is_t *tvalues;
00811 str val;
00812
00813 if(pt==NULL || len>=MT_MAX_DEPTH)
00814 return 0;
00815
00816 for(i=0; i<MT_NODE_SIZE; i++)
00817 {
00818 code[len]=mt_char_list.s[i];
00819 tvalues = pt[i].tvalues;
00820 if (tvalues != NULL)
00821 {
00822 node = add_mi_node_child(rpl, 0, "MT", 2, 0, 0);
00823 if(node == NULL)
00824 goto error;
00825 attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
00826 tree->tname.s, tree->tname.len);
00827 if(attr == NULL)
00828 goto error;
00829 attr = add_mi_attr(node, MI_DUP_VALUE, "TPREFIX", 7,
00830 code, len+1);
00831 if(attr == NULL)
00832 goto error;
00833
00834 while (tvalues != NULL) {
00835 if (tree->type == MT_TREE_IVAL) {
00836 val.s = int2str(tvalues->tvalue.n, &val.len);
00837 attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
00838 val.s, val.len);
00839 } else {
00840 attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
00841 tvalues->tvalue.s.s,
00842 tvalues->tvalue.s.len);
00843 }
00844 if(attr == NULL)
00845 goto error;
00846 tvalues = tvalues->next;
00847 }
00848 }
00849 if(mt_print_mi_node(tree, pt[i].child, rpl, code, len+1)<0)
00850 goto error;
00851 }
00852 return 0;
00853 error:
00854 return -1;
00855 }
00856
00864 #define strpos(s,c) (strchr(s,c)-s)
00865 struct mi_root* mt_mi_list(struct mi_root* cmd_tree, void* param)
00866 {
00867 str tname = {0, 0};
00868 m_tree_t *pt;
00869 struct mi_node* node = NULL;
00870 struct mi_root* rpl_tree = NULL;
00871 struct mi_node* rpl = NULL;
00872 static char code_buf[MT_MAX_DEPTH+1];
00873 int len;
00874
00875 if(!mt_defined_trees())
00876 {
00877 LM_ERR("empty tree list\n");
00878 return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
00879 }
00880
00881
00882 node = cmd_tree->node.kids;
00883 if(node != NULL)
00884 {
00885 tname = node->value;
00886 if(tname.s == NULL || tname.len== 0)
00887 return init_mi_tree( 404, "domain not found", 16);
00888
00889 if(*tname.s=='.') {
00890 tname.s = 0;
00891 tname.len = 0;
00892 }
00893 }
00894
00895 rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00896 if(rpl_tree == NULL)
00897 return 0;
00898 rpl = &rpl_tree->node;
00899
00900 pt = mt_get_first_tree();
00901
00902 while(pt!=NULL)
00903 {
00904 if(tname.s==NULL ||
00905 (tname.s!=NULL && pt->tname.len>=tname.len &&
00906 strncmp(pt->tname.s, tname.s, tname.len)==0))
00907 {
00908 len = 0;
00909 if(mt_print_mi_node(pt, pt->head, rpl, code_buf, len)<0)
00910 goto error;
00911 }
00912 pt = pt->next;
00913 }
00914
00915 return rpl_tree;
00916
00917 error:
00918 free_mi_tree(rpl_tree);
00919 return 0;
00920 }
00921
00922 struct mi_root* mt_mi_summary(struct mi_root* cmd_tree, void* param)
00923 {
00924 m_tree_t *pt;
00925 struct mi_root* rpl_tree = NULL;
00926 struct mi_node* node = NULL;
00927 struct mi_attr* attr= NULL;
00928 str val;
00929
00930 if(!mt_defined_trees())
00931 {
00932 LM_ERR("empty tree list\n");
00933 return init_mi_tree( 500, "No trees", 8);
00934 }
00935
00936 rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
00937 if(rpl_tree == NULL)
00938 return 0;
00939
00940 pt = mt_get_first_tree();
00941
00942 while(pt!=NULL)
00943 {
00944 node = add_mi_node_child(&rpl_tree->node, 0, "MT", 2, 0, 0);
00945 if(node == NULL)
00946 goto error;
00947 attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
00948 pt->tname.s, pt->tname.len);
00949 if(attr == NULL)
00950 goto error;
00951 val.s = int2str(pt->type, &val.len);
00952 attr = add_mi_attr(node, MI_DUP_VALUE, "TTYPE", 5,
00953 val.s, val.len);
00954 if(attr == NULL)
00955 goto error;
00956 val.s = int2str(pt->memsize, &val.len);
00957 attr = add_mi_attr(node, MI_DUP_VALUE, "MEMSIZE", 7,
00958 val.s, val.len);
00959 if(attr == NULL)
00960 goto error;
00961 val.s = int2str(pt->nrnodes, &val.len);
00962 attr = add_mi_attr(node, MI_DUP_VALUE, "NRNODES", 7,
00963 val.s, val.len);
00964 if(attr == NULL)
00965 goto error;
00966 val.s = int2str(pt->nritems, &val.len);
00967 attr = add_mi_attr(node, MI_DUP_VALUE, "NRITEMS", 7,
00968 val.s, val.len);
00969 if(attr == NULL)
00970 goto error;
00971
00972 pt = pt->next;
00973 }
00974
00975 return rpl_tree;
00976 error:
00977 free_mi_tree(rpl_tree);
00978 return 0;
00979 }