2
0

mtree_mod.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  1. /**
  2. * $Id$
  3. *
  4. * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. #include <stdio.h>
  24. #include <unistd.h>
  25. #include <stdlib.h>
  26. #include <time.h>
  27. #include "../../lib/srdb1/db_op.h"
  28. #include "../../lib/kmi/mi.h"
  29. #include "../../sr_module.h"
  30. #include "../../lib/srdb1/db.h"
  31. #include "../../mem/shm_mem.h"
  32. #include "../../mem/mem.h"
  33. #include "../../dprint.h"
  34. #include "../../parser/parse_uri.h"
  35. #include "../../timer.h"
  36. #include "../../ut.h"
  37. #include "../../locking.h"
  38. #include "../../action.h"
  39. #include "../../mod_fix.h"
  40. #include "../../parser/parse_from.h"
  41. #include "../../rpc.h"
  42. #include "../../rpc_lookup.h"
  43. #include "mtree.h"
  44. MODULE_VERSION
  45. #define NR_KEYS 3
  46. int mt_fetch_rows = 1000;
  47. /** database connection */
  48. static db1_con_t *db_con = NULL;
  49. static db_func_t mt_dbf;
  50. #if 0
  51. INSERT INTO version (table_name, table_version) values ('mtree','1');
  52. CREATE TABLE mtree (
  53. id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
  54. tprefix VARCHAR(32) NOT NULL,
  55. tvalue VARCHAR(128) DEFAULT '' NOT NULL,
  56. CONSTRAINT tprefix_idx UNIQUE (tprefix)
  57. ) ENGINE=MyISAM;
  58. INSERT INTO version (table_name, table_version) values ('mtrees','1');
  59. CREATE TABLE mtrees (
  60. id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
  61. tname VARCHAR(128) NOT NULL,
  62. tprefix VARCHAR(32) NOT NULL,
  63. tvalue VARCHAR(128) DEFAULT '' NOT NULL,
  64. CONSTRAINT tname_tprefix_idx UNIQUE (tname, tprefix)
  65. ) ENGINE=MyISAM;
  66. #endif
  67. /** parameters */
  68. static str db_url = str_init(DEFAULT_DB_URL);
  69. static str db_table = str_init("");
  70. static str tname_column = str_init("tname");
  71. static str tprefix_column = str_init("tprefix");
  72. static str tvalue_column = str_init("tvalue");
  73. /* List of allowed chars for a prefix*/
  74. str mt_char_list = str_init("0123456789");
  75. static str value_param = str_init("$avp(s:tvalue)");
  76. static str values_param = str_init("$avp(s:tvalues)");
  77. static str dstid_param = str_init("$avp(s:tdstid)");
  78. static str weight_param = str_init("$avp(s:tweight)");
  79. static str count_param = str_init("$avp(s:tcount)");
  80. pv_spec_t pv_value;
  81. pv_spec_t pv_values;
  82. pv_spec_t pv_dstid;
  83. pv_spec_t pv_weight;
  84. pv_spec_t pv_count;
  85. int _mt_tree_type = MT_TREE_SVAL;
  86. int _mt_ignore_duplicates = 0;
  87. int _mt_allow_duplicates = 0;
  88. /* lock, ref counter and flag used for reloading the date */
  89. static gen_lock_t *mt_lock = 0;
  90. static volatile int mt_tree_refcnt = 0;
  91. static volatile int mt_reload_flag = 0;
  92. int mt_param(modparam_t type, void *val);
  93. static int fixup_mt_match(void** param, int param_no);
  94. static int w_mt_match(struct sip_msg* msg, char* str1, char* str2,
  95. char* str3);
  96. static int mod_init(void);
  97. static void mod_destroy(void);
  98. static int child_init(int rank);
  99. static int mi_child_init(void);
  100. static int mtree_init_rpc(void);
  101. static int mt_match(struct sip_msg *msg, gparam_t *dm, gparam_t *var,
  102. gparam_t *mode);
  103. static struct mi_root* mt_mi_reload(struct mi_root*, void* param);
  104. static struct mi_root* mt_mi_list(struct mi_root*, void* param);
  105. static struct mi_root* mt_mi_summary(struct mi_root*, void* param);
  106. static struct mi_root* mt_mi_match(struct mi_root*, void* param);
  107. static int mt_load_db(m_tree_t *pt);
  108. static int mt_load_db_trees();
  109. static cmd_export_t cmds[]={
  110. {"mt_match", (cmd_function)w_mt_match, 3, fixup_mt_match,
  111. 0, REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE},
  112. {0, 0, 0, 0, 0, 0}
  113. };
  114. static param_export_t params[]={
  115. {"mtree", PARAM_STRING|USE_FUNC_PARAM, (void*)mt_param},
  116. {"db_url", PARAM_STR, &db_url},
  117. {"db_table", PARAM_STR, &db_table},
  118. {"tname_column", PARAM_STR, &tname_column},
  119. {"tprefix_column", PARAM_STR, &tprefix_column},
  120. {"tvalue_column", PARAM_STR, &tvalue_column},
  121. {"char_list", PARAM_STR, &mt_char_list},
  122. {"fetch_rows", INT_PARAM, &mt_fetch_rows},
  123. {"pv_value", PARAM_STR, &value_param},
  124. {"pv_values", PARAM_STR, &values_param},
  125. {"pv_dstid", PARAM_STR, &dstid_param},
  126. {"pv_weight", PARAM_STR, &weight_param},
  127. {"pv_count", PARAM_STR, &count_param},
  128. {"mt_tree_type", INT_PARAM, &_mt_tree_type},
  129. {"mt_ignore_duplicates", INT_PARAM, &_mt_ignore_duplicates},
  130. {"mt_allow_duplicates", INT_PARAM, &_mt_allow_duplicates},
  131. {0, 0, 0}
  132. };
  133. static mi_export_t mi_cmds[] = {
  134. { "mt_reload", mt_mi_reload, 0, 0, mi_child_init },
  135. { "mt_list", mt_mi_list, 0, 0, 0 },
  136. { "mt_summary", mt_mi_summary, 0, 0, 0 },
  137. { "mt_match", mt_mi_match, 0, 0, 0 },
  138. { 0, 0, 0, 0, 0}
  139. };
  140. struct module_exports exports = {
  141. "mtree",
  142. DEFAULT_DLFLAGS, /* dlopen flags */
  143. cmds,
  144. params,
  145. 0,
  146. mi_cmds, /* exported MI functions */
  147. 0, /* exported pseudo-variables */
  148. 0, /* extra processes */
  149. mod_init, /* module initialization function */
  150. 0, /* response function */
  151. mod_destroy, /* destroy function */
  152. child_init /* per child init function */
  153. };
  154. /**
  155. * init module function
  156. */
  157. static int mod_init(void)
  158. {
  159. m_tree_t *pt = NULL;
  160. if(register_mi_mod(exports.name, mi_cmds)!=0)
  161. {
  162. LM_ERR("failed to register MI commands\n");
  163. return -1;
  164. }
  165. if(mtree_init_rpc()!=0)
  166. {
  167. LM_ERR("failed to register RPC commands\n");
  168. return -1;
  169. }
  170. if(pv_parse_spec(&value_param, &pv_value)<00
  171. || !(pv_is_w(&pv_value)))
  172. {
  173. LM_ERR("cannot parse value pv or is read only\n");
  174. return -1;
  175. }
  176. if (pv_parse_spec(&values_param, &pv_values) <0
  177. || pv_values.type != PVT_AVP) {
  178. LM_ERR("cannot parse values avp\n");
  179. return -1;
  180. }
  181. if(pv_parse_spec(&dstid_param, &pv_dstid)<0
  182. || pv_dstid.type!=PVT_AVP)
  183. {
  184. LM_ERR("cannot parse dstid avp\n");
  185. return -1;
  186. }
  187. if(pv_parse_spec(&weight_param, &pv_weight)<0
  188. || pv_weight.type!=PVT_AVP)
  189. {
  190. LM_ERR("cannot parse dstid avp\n");
  191. return -1;
  192. }
  193. if(pv_parse_spec(&count_param, &pv_count)<0
  194. || !(pv_is_w(&pv_weight)))
  195. {
  196. LM_ERR("cannot parse count pv or is read-only\n");
  197. return -1;
  198. }
  199. if(mt_fetch_rows<=0)
  200. mt_fetch_rows = 1000;
  201. if(mt_char_list.len<=0)
  202. {
  203. LM_ERR("invalid prefix char list\n");
  204. return -1;
  205. }
  206. LM_DBG("mt_char_list=%s \n", mt_char_list.s);
  207. mt_char_table_init();
  208. /* binding to mysql module */
  209. if(db_bind_mod(&db_url, &mt_dbf))
  210. {
  211. LM_ERR("database module not found\n");
  212. return -1;
  213. }
  214. if (!DB_CAPABILITY(mt_dbf, DB_CAP_ALL))
  215. {
  216. LM_ERR("database module does not "
  217. "implement all functions needed by the module\n");
  218. return -1;
  219. }
  220. /* open a connection with the database */
  221. db_con = mt_dbf.init(&db_url);
  222. if(db_con==NULL)
  223. {
  224. LM_ERR("failed to connect to the database\n");
  225. return -1;
  226. }
  227. LM_DBG("database connection opened successfully\n");
  228. if ( (mt_lock=lock_alloc())==0) {
  229. LM_CRIT("failed to alloc lock\n");
  230. goto error1;
  231. }
  232. if (lock_init(mt_lock)==0 ) {
  233. LM_CRIT("failed to init lock\n");
  234. goto error1;
  235. }
  236. if(mt_defined_trees())
  237. {
  238. LM_DBG("static trees defined\n");
  239. pt = mt_get_first_tree();
  240. while(pt!=NULL)
  241. {
  242. LM_DBG("loading from tree <%.*s>\n",
  243. pt->tname.len, pt->tname.s);
  244. /* loading all information from database */
  245. if(mt_load_db(pt)!=0)
  246. {
  247. LM_ERR("cannot load info from database\n");
  248. goto error1;
  249. }
  250. pt = pt->next;
  251. }
  252. } else {
  253. if(db_table.len<=0)
  254. {
  255. LM_ERR("no trees table defined\n");
  256. goto error1;
  257. }
  258. if(mt_init_list_head()<0)
  259. {
  260. LM_ERR("unable to init trees list head\n");
  261. goto error1;
  262. }
  263. /* loading all information from database */
  264. if(mt_load_db_trees()!=0)
  265. {
  266. LM_ERR("cannot load trees from database\n");
  267. goto error1;
  268. }
  269. }
  270. mt_dbf.close(db_con);
  271. db_con = 0;
  272. #if 0
  273. mt_print_tree(mt_get_first_tree());
  274. #endif
  275. /* success code */
  276. return 0;
  277. error1:
  278. if (mt_lock)
  279. {
  280. lock_destroy( mt_lock );
  281. lock_dealloc( mt_lock );
  282. mt_lock = 0;
  283. }
  284. mt_destroy_trees();
  285. if(db_con!=NULL)
  286. mt_dbf.close(db_con);
  287. db_con = 0;
  288. return -1;
  289. }
  290. /**
  291. * mi and worker process initialization
  292. */
  293. static int mi_child_init(void)
  294. {
  295. db_con = mt_dbf.init(&db_url);
  296. if(db_con==NULL)
  297. {
  298. LM_ERR("failed to connect to database\n");
  299. return -1;
  300. }
  301. return 0;
  302. }
  303. /* each child get a new connection to the database */
  304. static int child_init(int rank)
  305. {
  306. /* skip child init for non-worker process ranks */
  307. if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
  308. return 0;
  309. if ( mi_child_init()!=0 )
  310. return -1;
  311. LM_DBG("#%d: database connection opened successfully\n", rank);
  312. return 0;
  313. }
  314. static void mod_destroy(void)
  315. {
  316. LM_DBG("cleaning up\n");
  317. mt_destroy_trees();
  318. if (db_con!=NULL && mt_dbf.close!=NULL)
  319. mt_dbf.close(db_con);
  320. /* destroy lock */
  321. if (mt_lock)
  322. {
  323. lock_destroy( mt_lock );
  324. lock_dealloc( mt_lock );
  325. mt_lock = 0;
  326. }
  327. }
  328. static int fixup_mt_match(void** param, int param_no)
  329. {
  330. if(param_no==1 || param_no==2) {
  331. return fixup_spve_null(param, 1);
  332. }
  333. if (param_no != 3) {
  334. LM_ERR("invalid parameter number %d\n", param_no);
  335. return E_UNSPEC;
  336. }
  337. return fixup_igp_null(param, 1);
  338. }
  339. /* use tree tn, match var, by mode, output in avp params */
  340. static int mt_match(struct sip_msg *msg, gparam_t *tn, gparam_t *var,
  341. gparam_t *mode)
  342. {
  343. str tname;
  344. str tomatch;
  345. int mval;
  346. m_tree_t *tr = NULL;
  347. if(msg==NULL)
  348. {
  349. LM_ERR("received null msg\n");
  350. return -1;
  351. }
  352. if(fixup_get_svalue(msg, tn, &tname)<0)
  353. {
  354. LM_ERR("cannot get the tree name\n");
  355. return -1;
  356. }
  357. if(fixup_get_svalue(msg, var, &tomatch)<0)
  358. {
  359. LM_ERR("cannot get the match var\n");
  360. return -1;
  361. }
  362. if(fixup_get_ivalue(msg, mode, &mval)<0)
  363. {
  364. LM_ERR("cannot get the mode\n");
  365. return -1;
  366. }
  367. again:
  368. lock_get( mt_lock );
  369. if (mt_reload_flag) {
  370. lock_release( mt_lock );
  371. sleep_us(5);
  372. goto again;
  373. }
  374. mt_tree_refcnt++;
  375. lock_release( mt_lock );
  376. tr = mt_get_tree(&tname);
  377. if(tr==NULL)
  378. {
  379. /* no tree with such name*/
  380. goto error;
  381. }
  382. if(mt_match_prefix(msg, tr, &tomatch, mval)<0)
  383. {
  384. LM_DBG("no prefix found in [%.*s] for [%.*s]\n",
  385. tname.len, tname.s,
  386. tomatch.len, tomatch.s);
  387. goto error;
  388. }
  389. lock_get( mt_lock );
  390. mt_tree_refcnt--;
  391. lock_release( mt_lock );
  392. return 1;
  393. error:
  394. lock_get( mt_lock );
  395. mt_tree_refcnt--;
  396. lock_release( mt_lock );
  397. return -1;
  398. }
  399. static int w_mt_match(struct sip_msg* msg, char* str1, char* str2,
  400. char* str3)
  401. {
  402. return mt_match(msg, (gparam_t*)str1, (gparam_t*)str2, (gparam_t*)str3);
  403. }
  404. int mt_param(modparam_t type, void *val)
  405. {
  406. if(val==NULL)
  407. goto error;
  408. return mt_table_spec((char*)val);
  409. error:
  410. return -1;
  411. }
  412. static int mt_load_db(m_tree_t *pt)
  413. {
  414. db_key_t db_cols[3] = {&tprefix_column, &tvalue_column};
  415. db_key_t key_cols[1];
  416. db_op_t op[1] = {OP_EQ};
  417. db_val_t vals[1];
  418. str tprefix, tvalue;
  419. db1_res_t* db_res = NULL;
  420. int i, ret;
  421. m_tree_t new_tree;
  422. m_tree_t *old_tree = NULL;
  423. mt_node_t *bk_head = NULL;
  424. key_cols[0] = &tname_column;
  425. VAL_TYPE(vals) = DB1_STRING;
  426. VAL_NULL(vals) = 0;
  427. VAL_STRING(vals) = pt->tname.s;
  428. if(db_con==NULL)
  429. {
  430. LM_ERR("no db connection\n");
  431. return -1;
  432. }
  433. old_tree = mt_get_tree(&(pt->tname));
  434. if(old_tree==NULL)
  435. {
  436. LM_ERR("tree definition not found [%.*s]\n", pt->tname.len,
  437. pt->tname.s);
  438. return -1;
  439. }
  440. memcpy(&new_tree, old_tree, sizeof(m_tree_t));
  441. new_tree.head = 0;
  442. new_tree.next = 0;
  443. new_tree.nrnodes = 0;
  444. new_tree.nritems = 0;
  445. new_tree.memsize = 0;
  446. new_tree.reload_count++;
  447. new_tree.reload_time = (unsigned int)time(NULL);
  448. if (mt_dbf.use_table(db_con, &old_tree->dbtable) < 0)
  449. {
  450. LM_ERR("failed to use_table\n");
  451. return -1;
  452. }
  453. if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
  454. if(mt_dbf.query(db_con, key_cols, op, vals, db_cols, pt->multi,
  455. 2, 0, 0) < 0)
  456. {
  457. LM_ERR("Error while querying db\n");
  458. return -1;
  459. }
  460. if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0)
  461. {
  462. LM_ERR("Error while fetching result\n");
  463. goto error;
  464. } else {
  465. if(RES_ROW_N(db_res)==0)
  466. {
  467. goto dbreloaded;
  468. }
  469. }
  470. } else {
  471. if((ret=mt_dbf.query(db_con, key_cols, op, vals, db_cols,
  472. pt->multi, 2, 0, &db_res))!=0
  473. || RES_ROW_N(db_res)<=0 )
  474. {
  475. if(ret==0)
  476. {
  477. goto dbreloaded;
  478. } else {
  479. goto error;
  480. }
  481. }
  482. }
  483. if(RES_ROW_N(db_res)>0)
  484. {
  485. if(RES_ROWS(db_res)[0].values[0].type != DB1_STRING
  486. || RES_ROWS(db_res)[0].values[1].type != DB1_STRING)
  487. {
  488. LM_ERR("wrond column types in db table (%d / %d)\n",
  489. RES_ROWS(db_res)[0].values[0].type,
  490. RES_ROWS(db_res)[0].values[1].type);
  491. goto error;
  492. }
  493. }
  494. do {
  495. for(i=0; i<RES_ROW_N(db_res); i++)
  496. {
  497. /* check for NULL values ?!?! */
  498. tprefix.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);
  499. tprefix.len = strlen(ZSW(tprefix.s));
  500. tvalue.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);
  501. tvalue.len = strlen(ZSW(tvalue.s));
  502. if(tprefix.s==NULL || tvalue.s==NULL
  503. || tprefix.len<=0 || tvalue.len<=0)
  504. {
  505. LM_ERR("Error - bad record in db"
  506. " (prefix: %p/%d - value: %p/%d)\n",
  507. tprefix.s, tprefix.len, tvalue.s, tvalue.len);
  508. continue;
  509. }
  510. if(mt_add_to_tree(&new_tree, &tprefix, &tvalue)<0)
  511. {
  512. LM_ERR("Error adding info to tree\n");
  513. goto error;
  514. }
  515. }
  516. if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
  517. if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0) {
  518. LM_ERR("Error while fetching!\n");
  519. if (db_res)
  520. mt_dbf.free_result(db_con, db_res);
  521. goto error;
  522. }
  523. } else {
  524. break;
  525. }
  526. } while(RES_ROW_N(db_res)>0);
  527. dbreloaded:
  528. mt_dbf.free_result(db_con, db_res);
  529. /* block all readers */
  530. lock_get( mt_lock );
  531. mt_reload_flag = 1;
  532. lock_release( mt_lock );
  533. while (mt_tree_refcnt) {
  534. sleep_us(10);
  535. }
  536. bk_head = old_tree->head;
  537. old_tree->head = new_tree.head;
  538. old_tree->nrnodes = new_tree.nrnodes;
  539. old_tree->nritems = new_tree.nritems;
  540. old_tree->memsize = new_tree.memsize;
  541. old_tree->reload_count = new_tree.reload_count;
  542. old_tree->reload_time = new_tree.reload_time;
  543. mt_reload_flag = 0;
  544. /* free old data */
  545. if (bk_head!=NULL)
  546. mt_free_node(bk_head, new_tree.type);
  547. return 0;
  548. error:
  549. mt_dbf.free_result(db_con, db_res);
  550. if (new_tree.head!=NULL)
  551. mt_free_node(new_tree.head, new_tree.type);
  552. return -1;
  553. }
  554. static int mt_load_db_trees()
  555. {
  556. db_key_t db_cols[3] = {&tname_column, &tprefix_column, &tvalue_column};
  557. str tprefix, tvalue, tname;
  558. db1_res_t* db_res = NULL;
  559. int i, ret;
  560. m_tree_t *new_head = NULL;
  561. m_tree_t *new_tree = NULL;
  562. m_tree_t *old_head = NULL;
  563. if(db_con==NULL)
  564. {
  565. LM_ERR("no db connection\n");
  566. return -1;
  567. }
  568. if (mt_dbf.use_table(db_con, &db_table) < 0)
  569. {
  570. LM_ERR("failed to use_table\n");
  571. return -1;
  572. }
  573. if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH))
  574. {
  575. if(mt_dbf.query(db_con,0,0,0,db_cols,0,3,&tname_column,0) < 0)
  576. {
  577. LM_ERR("Error while querying db\n");
  578. return -1;
  579. }
  580. if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0)
  581. {
  582. LM_ERR("Error while fetching result\n");
  583. if (db_res)
  584. mt_dbf.free_result(db_con, db_res);
  585. goto error;
  586. } else {
  587. if(RES_ROW_N(db_res)==0)
  588. {
  589. return 0;
  590. }
  591. }
  592. } else {
  593. if((ret=mt_dbf.query(db_con, NULL, NULL, NULL, db_cols,
  594. 0, 3, &tname_column, &db_res))!=0
  595. || RES_ROW_N(db_res)<=0 )
  596. {
  597. mt_dbf.free_result(db_con, db_res);
  598. if( ret==0)
  599. {
  600. return 0;
  601. } else {
  602. goto error;
  603. }
  604. }
  605. }
  606. do {
  607. for(i=0; i<RES_ROW_N(db_res); i++)
  608. {
  609. /* check for NULL values ?!?! */
  610. tname.s = (char*)(RES_ROWS(db_res)[i].values[0].val.string_val);
  611. tname.len = strlen(tname.s);
  612. tprefix.s = (char*)(RES_ROWS(db_res)[i].values[1].val.string_val);
  613. tprefix.len = strlen(tprefix.s);
  614. tvalue.s = (char*)(RES_ROWS(db_res)[i].values[2].val.string_val);
  615. tvalue.len = strlen(tvalue.s);
  616. if(tprefix.s==NULL || tvalue.s==NULL || tname.s==NULL ||
  617. tprefix.len<=0 || tvalue.len<=0 || tname.len<=0)
  618. {
  619. LM_ERR("Error - bad values in db\n");
  620. continue;
  621. }
  622. new_tree = mt_add_tree(&new_head, &tname, &db_table,
  623. _mt_tree_type, 0);
  624. if(new_tree==NULL)
  625. {
  626. LM_ERR("New tree cannot be initialized\n");
  627. goto error;
  628. }
  629. if(mt_add_to_tree(new_tree, &tprefix, &tvalue)<0)
  630. {
  631. LM_ERR("Error adding info to tree\n");
  632. goto error;
  633. }
  634. }
  635. if (DB_CAPABILITY(mt_dbf, DB_CAP_FETCH)) {
  636. if(mt_dbf.fetch_result(db_con, &db_res, mt_fetch_rows)<0) {
  637. LM_ERR("Error while fetching!\n");
  638. if (db_res)
  639. mt_dbf.free_result(db_con, db_res);
  640. goto error;
  641. }
  642. } else {
  643. break;
  644. }
  645. } while(RES_ROW_N(db_res)>0);
  646. mt_dbf.free_result(db_con, db_res);
  647. /* block all readers */
  648. lock_get( mt_lock );
  649. mt_reload_flag = 1;
  650. lock_release( mt_lock );
  651. while (mt_tree_refcnt) {
  652. sleep_us(10);
  653. }
  654. old_head = mt_swap_list_head(new_head);
  655. mt_reload_flag = 0;
  656. /* free old data */
  657. if (old_head!=NULL)
  658. mt_free_tree(old_head);
  659. return 0;
  660. error:
  661. mt_dbf.free_result(db_con, db_res);
  662. if (new_head!=NULL)
  663. mt_free_tree(new_head);
  664. return -1;
  665. }
  666. /**************************** MI ***************************/
  667. /**
  668. * "mt_reload" syntax :
  669. * \n
  670. */
  671. static struct mi_root* mt_mi_reload(struct mi_root *cmd_tree, void *param)
  672. {
  673. str tname = {0, 0};
  674. m_tree_t *pt;
  675. struct mi_node* node = NULL;
  676. if(db_table.len>0)
  677. {
  678. /* re-loading all information from database */
  679. if(mt_load_db_trees()!=0)
  680. {
  681. LM_ERR("cannot re-load info from database\n");
  682. goto error;
  683. }
  684. } else {
  685. if(!mt_defined_trees())
  686. {
  687. LM_ERR("empty tree list\n");
  688. return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
  689. }
  690. /* read tree name */
  691. node = cmd_tree->node.kids;
  692. if(node != NULL)
  693. {
  694. tname = node->value;
  695. if(tname.s == NULL || tname.len== 0)
  696. return init_mi_tree( 404, "domain not found", 16);
  697. if(*tname.s=='.') {
  698. tname.s = 0;
  699. tname.len = 0;
  700. }
  701. }
  702. pt = mt_get_first_tree();
  703. while(pt!=NULL)
  704. {
  705. if(tname.s==NULL
  706. || (tname.s!=NULL && pt->tname.len>=tname.len
  707. && strncmp(pt->tname.s, tname.s, tname.len)==0))
  708. {
  709. /* re-loading table from database */
  710. if(mt_load_db(pt)!=0)
  711. {
  712. LM_ERR("cannot re-load info from database\n");
  713. goto error;
  714. }
  715. }
  716. pt = pt->next;
  717. }
  718. }
  719. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  720. error:
  721. return init_mi_tree( 500, "Failed to reload",16);
  722. }
  723. int mt_print_mi_node(m_tree_t *tree, mt_node_t *pt, struct mi_node* rpl,
  724. char *code, int len)
  725. {
  726. int i;
  727. struct mi_node* node = NULL;
  728. struct mi_attr* attr= NULL;
  729. mt_is_t *tvalues;
  730. str val;
  731. if(pt==NULL || len>=MT_MAX_DEPTH)
  732. return 0;
  733. for(i=0; i<MT_NODE_SIZE; i++)
  734. {
  735. code[len]=mt_char_list.s[i];
  736. tvalues = pt[i].tvalues;
  737. if (tvalues != NULL)
  738. {
  739. node = add_mi_node_child(rpl, 0, "MT", 2, 0, 0);
  740. if(node == NULL)
  741. goto error;
  742. attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
  743. tree->tname.s, tree->tname.len);
  744. if(attr == NULL)
  745. goto error;
  746. attr = add_mi_attr(node, MI_DUP_VALUE, "TPREFIX", 7,
  747. code, len+1);
  748. if(attr == NULL)
  749. goto error;
  750. while (tvalues != NULL) {
  751. if (tree->type == MT_TREE_IVAL) {
  752. val.s = int2str(tvalues->tvalue.n, &val.len);
  753. attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
  754. val.s, val.len);
  755. } else {
  756. attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
  757. tvalues->tvalue.s.s,
  758. tvalues->tvalue.s.len);
  759. }
  760. if(attr == NULL)
  761. goto error;
  762. tvalues = tvalues->next;
  763. }
  764. }
  765. if(mt_print_mi_node(tree, pt[i].child, rpl, code, len+1)<0)
  766. goto error;
  767. }
  768. return 0;
  769. error:
  770. return -1;
  771. }
  772. /**
  773. * "mt_list" syntax :
  774. * tname
  775. *
  776. * - '.' (dot) means NULL value and will match anything
  777. */
  778. #define strpos(s,c) (strchr(s,c)-s)
  779. struct mi_root* mt_mi_list(struct mi_root* cmd_tree, void* param)
  780. {
  781. str tname = {0, 0};
  782. m_tree_t *pt;
  783. struct mi_node* node = NULL;
  784. struct mi_root* rpl_tree = NULL;
  785. struct mi_node* rpl = NULL;
  786. static char code_buf[MT_MAX_DEPTH+1];
  787. int len;
  788. if(!mt_defined_trees())
  789. {
  790. LM_ERR("empty tree list\n");
  791. return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
  792. }
  793. /* read tree name */
  794. node = cmd_tree->node.kids;
  795. if(node != NULL)
  796. {
  797. tname = node->value;
  798. if(tname.s == NULL || tname.len== 0)
  799. return init_mi_tree( 404, "domain not found", 16);
  800. if(*tname.s=='.') {
  801. tname.s = 0;
  802. tname.len = 0;
  803. }
  804. }
  805. rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  806. if(rpl_tree == NULL)
  807. return 0;
  808. rpl = &rpl_tree->node;
  809. pt = mt_get_first_tree();
  810. while(pt!=NULL)
  811. {
  812. if(tname.s==NULL ||
  813. (tname.s!=NULL && pt->tname.len>=tname.len &&
  814. strncmp(pt->tname.s, tname.s, tname.len)==0))
  815. {
  816. len = 0;
  817. if(mt_print_mi_node(pt, pt->head, rpl, code_buf, len)<0)
  818. goto error;
  819. }
  820. pt = pt->next;
  821. }
  822. return rpl_tree;
  823. error:
  824. free_mi_tree(rpl_tree);
  825. return 0;
  826. }
  827. struct mi_root* mt_mi_summary(struct mi_root* cmd_tree, void* param)
  828. {
  829. m_tree_t *pt;
  830. struct mi_root* rpl_tree = NULL;
  831. struct mi_node* node = NULL;
  832. struct mi_attr* attr= NULL;
  833. str val;
  834. if(!mt_defined_trees())
  835. {
  836. LM_ERR("empty tree list\n");
  837. return init_mi_tree( 500, "No trees", 8);
  838. }
  839. rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  840. if(rpl_tree == NULL)
  841. return 0;
  842. pt = mt_get_first_tree();
  843. while(pt!=NULL)
  844. {
  845. node = add_mi_node_child(&rpl_tree->node, 0, "MT", 2, 0, 0);
  846. if(node == NULL)
  847. goto error;
  848. attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
  849. pt->tname.s, pt->tname.len);
  850. if(attr == NULL)
  851. goto error;
  852. val.s = int2str(pt->type, &val.len);
  853. attr = add_mi_attr(node, MI_DUP_VALUE, "TTYPE", 5,
  854. val.s, val.len);
  855. if(attr == NULL)
  856. goto error;
  857. val.s = int2str(pt->memsize, &val.len);
  858. attr = add_mi_attr(node, MI_DUP_VALUE, "MEMSIZE", 7,
  859. val.s, val.len);
  860. if(attr == NULL)
  861. goto error;
  862. val.s = int2str(pt->nrnodes, &val.len);
  863. attr = add_mi_attr(node, MI_DUP_VALUE, "NRNODES", 7,
  864. val.s, val.len);
  865. if(attr == NULL)
  866. goto error;
  867. val.s = int2str(pt->nritems, &val.len);
  868. attr = add_mi_attr(node, MI_DUP_VALUE, "NRITEMS", 7,
  869. val.s, val.len);
  870. if(attr == NULL)
  871. goto error;
  872. val.s = int2str((int)pt->reload_count, &val.len);
  873. attr = add_mi_attr(node, MI_DUP_VALUE, "RELOADCOUNT", 11,
  874. val.s, val.len);
  875. if(attr == NULL)
  876. goto error;
  877. val.s = int2str((int)pt->reload_time, &val.len);
  878. attr = add_mi_attr(node, MI_DUP_VALUE, "RELOADTIME", 10,
  879. val.s, val.len);
  880. if(attr == NULL)
  881. goto error;
  882. pt = pt->next;
  883. }
  884. return rpl_tree;
  885. error:
  886. free_mi_tree(rpl_tree);
  887. return 0;
  888. }
  889. void rpc_mtree_summary(rpc_t* rpc, void* c)
  890. {
  891. str tname = {0, 0};
  892. m_tree_t *pt;
  893. void* th;
  894. void* ih;
  895. int found;
  896. if(!mt_defined_trees())
  897. {
  898. rpc->fault(c, 500, "Empty tree list");
  899. return;
  900. }
  901. /* read optional tree name */
  902. if(rpc->scan(c, "*S", &tname)==0)
  903. {
  904. tname.s = NULL;
  905. tname.len = 0;
  906. }
  907. pt = mt_get_first_tree();
  908. if(pt==NULL)
  909. {
  910. rpc->fault(c, 404, "No tree");
  911. return;
  912. }
  913. found = 0;
  914. while(pt!=NULL)
  915. {
  916. if(tname.s==NULL
  917. || (tname.s!=NULL && pt->tname.len>=tname.len
  918. && strncmp(pt->tname.s, tname.s, tname.len)==0))
  919. {
  920. found = 1;
  921. if (rpc->add(c, "{", &th) < 0)
  922. {
  923. rpc->fault(c, 500, "Internal error creating rpc");
  924. return;
  925. }
  926. if(rpc->struct_add(th, "s{",
  927. "table", pt->tname.s,
  928. "item", &ih) < 0)
  929. {
  930. rpc->fault(c, 500, "Internal error creating rpc ih");
  931. return;
  932. }
  933. if(rpc->struct_add(ih, "d", "ttype", pt->type) < 0 ) {
  934. rpc->fault(c, 500, "Internal error adding type");
  935. return;
  936. }
  937. if(rpc->struct_add(ih, "d", "memsize", pt->memsize) < 0 ) {
  938. rpc->fault(c, 500, "Internal error adding memsize");
  939. return;
  940. }
  941. if(rpc->struct_add(ih, "d", "nrnodes", pt->nrnodes) < 0 ) {
  942. rpc->fault(c, 500, "Internal error adding nodes");
  943. return;
  944. }
  945. if(rpc->struct_add(ih, "d", "nritems", pt->nritems) < 0 ) {
  946. rpc->fault(c, 500, "Internal error adding items");
  947. return;
  948. }
  949. if(rpc->struct_add(ih, "d", "reload_count",
  950. (int)pt->reload_count) < 0 ) {
  951. rpc->fault(c, 500, "Internal error adding items");
  952. return;
  953. }
  954. if(rpc->struct_add(ih, "d", "reload_time",
  955. (int)pt->reload_time) < 0 ) {
  956. rpc->fault(c, 500, "Internal error adding items");
  957. return;
  958. }
  959. }
  960. pt = pt->next;
  961. }
  962. if(found==0)
  963. {
  964. rpc->fault(c, 404, "Tree not found");
  965. return;
  966. }
  967. return;
  968. }
  969. static const char* rpc_mtree_summary_doc[2] = {
  970. "Print summary of loaded mtree tables",
  971. 0
  972. };
  973. void rpc_mtree_reload(rpc_t* rpc, void* c)
  974. {
  975. str tname = {0, 0};
  976. m_tree_t *pt;
  977. if(db_table.len>0)
  978. {
  979. /* re-loading all information from database */
  980. if(mt_load_db_trees()!=0)
  981. {
  982. LM_ERR("cannot re-load mtrees from database\n");
  983. goto error;
  984. }
  985. } else {
  986. if(!mt_defined_trees())
  987. {
  988. LM_ERR("empty mtree list\n");
  989. goto error;
  990. }
  991. /* read tree name */
  992. if (rpc->scan(c, "S", &tname) != 1) {
  993. rpc->fault(c, 500, "Failed to get table name parameter");
  994. return;
  995. }
  996. pt = mt_get_first_tree();
  997. while(pt!=NULL)
  998. {
  999. if(tname.s==NULL
  1000. || (tname.s!=NULL && pt->tname.len>=tname.len
  1001. && strncmp(pt->tname.s, tname.s, tname.len)==0))
  1002. {
  1003. /* re-loading table from database */
  1004. if(mt_load_db(pt)!=0)
  1005. {
  1006. LM_ERR("cannot re-load mtree from database\n");
  1007. goto error;
  1008. }
  1009. }
  1010. pt = pt->next;
  1011. }
  1012. }
  1013. return;
  1014. error:
  1015. rpc->fault(c, 500, "Mtree Reload Failed");
  1016. }
  1017. static const char* rpc_mtree_reload_doc[2] = {
  1018. "Reload mtrees from database to memory",
  1019. 0
  1020. };
  1021. void rpc_mtree_match(rpc_t* rpc, void* ctx)
  1022. {
  1023. str tname = STR_NULL;
  1024. str tomatch = STR_NULL;
  1025. int mode = -1;
  1026. m_tree_t *tr;
  1027. if(!mt_defined_trees())
  1028. {
  1029. rpc->fault(ctx, 500, "Empty tree list.");
  1030. return;
  1031. }
  1032. if (rpc->scan(ctx, ".SSd", &tname, &tomatch, &mode) < 3) {
  1033. rpc->fault(ctx, 500, "Invalid Parameters");
  1034. return;
  1035. }
  1036. if (mode !=0 && mode != 2) {
  1037. rpc->fault(ctx, 500, "Invalid parameter 'mode'");
  1038. return;
  1039. }
  1040. again:
  1041. lock_get( mt_lock );
  1042. if (mt_reload_flag) {
  1043. lock_release( mt_lock );
  1044. sleep_us(5);
  1045. goto again;
  1046. }
  1047. mt_tree_refcnt++;
  1048. lock_release( mt_lock );
  1049. tr = mt_get_tree(&tname);
  1050. if(tr==NULL)
  1051. {
  1052. /* no tree with such name*/
  1053. rpc->fault(ctx, 404, "Not found tree");
  1054. goto error;
  1055. }
  1056. if(mt_rpc_match_prefix(rpc, ctx, tr, &tomatch, mode)<0)
  1057. {
  1058. LM_DBG("no prefix found in [%.*s] for [%.*s]\n",
  1059. tname.len, tname.s,
  1060. tomatch.len, tomatch.s);
  1061. rpc->fault(ctx, 404, "Not found");
  1062. }
  1063. error:
  1064. lock_get( mt_lock );
  1065. mt_tree_refcnt--;
  1066. lock_release( mt_lock );
  1067. }
  1068. static const char* rpc_mtree_match_doc[6] = {
  1069. "Match prefix value against mtree",
  1070. "uses three required parameters",
  1071. "tname - tree name",
  1072. "prefix - prefix for matching",
  1073. "mode - mode for matching (0 or 2)",
  1074. 0
  1075. };
  1076. rpc_export_t mtree_rpc[] = {
  1077. {"mtree.summary", rpc_mtree_summary, rpc_mtree_summary_doc, RET_ARRAY},
  1078. {"mtree.reload", rpc_mtree_reload, rpc_mtree_reload_doc, 0},
  1079. {"mtree.match", rpc_mtree_match, rpc_mtree_match_doc, 0},
  1080. {0, 0, 0, 0}
  1081. };
  1082. static int mtree_init_rpc(void)
  1083. {
  1084. if (rpc_register_array(mtree_rpc) != 0)
  1085. {
  1086. LM_ERR("failed to register RPC commands\n");
  1087. return -1;
  1088. }
  1089. return 0;
  1090. }
  1091. struct mi_root* mt_mi_match(struct mi_root* cmd_tree, void* param)
  1092. {
  1093. m_tree_t *tr;
  1094. struct mi_root* rpl_tree = NULL;
  1095. struct mi_node* node = NULL;
  1096. str tname, prefix, mode_param;
  1097. str bad_tname_param = STR_STATIC_INIT("Bad tname parameter");
  1098. str bad_prefix_param = STR_STATIC_INIT("Bad prefix parameter");
  1099. str bad_mode_param = STR_STATIC_INIT("Bad mode parameter");
  1100. int mode;
  1101. if(!mt_defined_trees())
  1102. {
  1103. LM_ERR("empty tree list\n");
  1104. return init_mi_tree( 500, "No trees", 8);
  1105. }
  1106. /* read tree name */
  1107. node = cmd_tree->node.kids;
  1108. if(node != NULL)
  1109. {
  1110. tname = node->value;
  1111. if(tname.s == NULL || tname.len== 0)
  1112. return init_mi_tree( 400, bad_tname_param.s, bad_tname_param.len);
  1113. }
  1114. else
  1115. {
  1116. return init_mi_tree( 400, bad_tname_param.s, bad_tname_param.len);
  1117. }
  1118. /* read given prefix */
  1119. node = node->next;
  1120. if(node != NULL)
  1121. {
  1122. prefix = node->value;
  1123. if(prefix.s == NULL || prefix.len== 0)
  1124. return init_mi_tree( 400, bad_prefix_param.s, bad_prefix_param.len);
  1125. }
  1126. else
  1127. {
  1128. return init_mi_tree( 400, bad_prefix_param.s, bad_prefix_param.len);
  1129. }
  1130. /* read mode parameter (required) */
  1131. node = node->next;
  1132. if (node != NULL)
  1133. {
  1134. mode_param = node->value;
  1135. if (mode_param.s == NULL || mode_param.len == 0 ||
  1136. str2int(&mode_param, (unsigned int*)&mode))
  1137. mode = -1;
  1138. if (mode != 0 && mode != 2)
  1139. return init_mi_tree( 400, bad_mode_param.s, bad_mode_param.len);
  1140. }
  1141. else
  1142. {
  1143. return init_mi_tree( 400, bad_mode_param.s, bad_mode_param.len);
  1144. }
  1145. again:
  1146. lock_get( mt_lock );
  1147. if (mt_reload_flag) {
  1148. lock_release( mt_lock );
  1149. sleep_us(5);
  1150. goto again;
  1151. }
  1152. mt_tree_refcnt++;
  1153. lock_release( mt_lock );
  1154. tr = mt_get_tree(&tname);
  1155. if(tr==NULL)
  1156. {
  1157. /* no tree with such name*/
  1158. rpl_tree = init_mi_tree( 404, "Not found tree", 14);
  1159. goto error;
  1160. }
  1161. rpl_tree = init_mi_tree( 200, "OK", 2);
  1162. if (rpl_tree == NULL)
  1163. goto error;
  1164. if(mt_mi_match_prefix(&rpl_tree->node, tr, &prefix, mode)<0)
  1165. {
  1166. LM_DBG("no prefix found in [%.*s] for [%.*s]\n",
  1167. tname.len, tname.s,
  1168. prefix.len, prefix.s);
  1169. free_mi_tree(rpl_tree);
  1170. rpl_tree = init_mi_tree( 404, "Not found tvalue", 16);
  1171. }
  1172. error:
  1173. lock_get( mt_lock );
  1174. mt_tree_refcnt--;
  1175. lock_release( mt_lock );
  1176. return rpl_tree;
  1177. }