mtree_mod.c

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 /* List of allowed chars for a prefix*/
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 /* lock, ref counter and flag used for reloading the date */
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, /* dlopen flags */
00160         cmds,
00161         params,
00162         0,
00163         mi_cmds,        /* exported MI functions */
00164         0,              /* exported pseudo-variables */
00165         0,              /* extra processes */
00166         mod_init,       /* module initialization function */
00167         0,              /* response function */
00168         mod_destroy,    /* destroy function */
00169         child_init      /* per child init function */
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         /* binding to mysql module */
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         /* open a connection with the database */
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                         /* loading all information from database */
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                 /* loading all information from database */
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         /* success code */
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 /* each child get a new connection to the database */
00354 static int child_init(int rank)
00355 {
00356         /* skip child init for non-worker process ranks */
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                 /* destroy lock */
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 /* use tree tn, match var, by mode, output in avp params */
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                 /* no tree with such name*/
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                         /* check for NULL values ?!?! */
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         /* block all readers */
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         /* free old data */
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                         /* check for NULL values ?!?! */
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         /* block all readers */
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         /* free old data */
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 /**************************** MI ***************************/
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                 /* re-loading all information from database */
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                 /* read tree name */
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                                 /* re-loading table from database */
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         /* read tree name */
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 }