km_bdb_lib.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  1. /*
  2. * $Id$
  3. *
  4. * db_berkeley module, portions of this code were templated using
  5. * the dbtext and postgres modules.
  6. * Copyright (C) 2007 Cisco Systems
  7. *
  8. * This file is part of SIP-router, a free SIP server.
  9. *
  10. * SIP-router is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * SIP-router is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * History:
  25. * --------
  26. * 2007-09-19 genesis (wiquan)
  27. */
  28. /*! \file
  29. * Berkeley DB :
  30. *
  31. * \ingroup database
  32. */
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <time.h>
  36. #include <sys/types.h>
  37. #include <dirent.h>
  38. #include "../../ut.h"
  39. #include "../../mem/mem.h"
  40. #include "../../dprint.h"
  41. #include "km_bdb_util.h"
  42. #include "km_bdb_lib.h"
  43. #include "km_bdb_val.h"
  44. static database_p *_cachedb = NULL;
  45. static db_parms_p _db_parms = NULL;
  46. /**
  47. *
  48. */
  49. int km_bdblib_init(db_parms_p _p)
  50. {
  51. if (!_cachedb)
  52. {
  53. _cachedb = pkg_malloc( sizeof(database_p) );
  54. if (!_cachedb)
  55. { LM_CRIT("not enough private memory\n");
  56. return -1;
  57. }
  58. *_cachedb = NULL;
  59. /*create default parms*/
  60. db_parms_p dp = (db_parms_p) pkg_malloc( sizeof(db_parms_t) );
  61. if (!dp)
  62. { LM_CRIT("not enough private memory\n");
  63. return -1;
  64. }
  65. if(_p)
  66. {
  67. dp->cache_size = _p->cache_size;
  68. dp->auto_reload = _p->auto_reload;
  69. dp->log_enable = _p->log_enable;
  70. dp->journal_roll_interval = _p->journal_roll_interval;
  71. }
  72. else
  73. {
  74. dp->cache_size = (4 * 1024 * 1024); //4Mb
  75. dp->auto_reload = 0;
  76. dp->log_enable = 0;
  77. dp->journal_roll_interval = 3600;
  78. }
  79. _db_parms = dp;
  80. }
  81. return 0;
  82. }
  83. /**
  84. * close all DBs and then the DBENV; free all memory
  85. */
  86. int km_bdblib_destroy(void)
  87. {
  88. if (_cachedb) db_free(*_cachedb);
  89. if(_db_parms) pkg_free(_db_parms);
  90. return 0;
  91. }
  92. /** closes the underlying Berkeley DB.
  93. assumes the lib data-structures are already initialzed;
  94. used to sync and reload the db file.
  95. */
  96. int km_bdblib_close(char* _n)
  97. {
  98. str s;
  99. int rc;
  100. tbl_cache_p _tbc;
  101. DB* _db = NULL;
  102. DB_ENV* _env = NULL;
  103. database_p _db_p = *_cachedb;
  104. if (!_cachedb || !_n)
  105. return -1;
  106. rc = 0;
  107. s.s = (char*)_n;
  108. s.len = strlen(_n);
  109. if (_db_p)
  110. {
  111. _env = _db_p->dbenv;
  112. _tbc = _db_p->tables;
  113. LM_DBG("ENV %.*s \n"
  114. , _db_p->name.len
  115. , _db_p->name.s);
  116. if(s.len == _db_p->name.len &&
  117. !strncasecmp(s.s, _db_p->name.s, _db_p->name.len))
  118. {
  119. //close the whole dbenv
  120. LM_DBG("ENV %.*s \n", s.len, s.s);
  121. while(_tbc)
  122. {
  123. if(_tbc->dtp)
  124. {
  125. lock_get(&_tbc->dtp->sem);
  126. _db = _tbc->dtp->db;
  127. if(_db)
  128. rc = _db->close(_db, 0);
  129. if(rc != 0)
  130. LM_CRIT("error closing %s\n", _tbc->dtp->name.s);
  131. _tbc->dtp->db = NULL;
  132. lock_release(&_tbc->dtp->sem);
  133. }
  134. _tbc = _tbc->next;
  135. }
  136. _env->close(_env, 0);
  137. _db_p->dbenv = NULL;
  138. return 0;
  139. }
  140. //close a particular db
  141. while(_tbc)
  142. {
  143. if(_tbc->dtp)
  144. {
  145. LM_DBG("checking DB %.*s \n"
  146. , _tbc->dtp->name.len
  147. , _tbc->dtp->name.s);
  148. if(_tbc->dtp->name.len == s.len &&
  149. !strncasecmp(_tbc->dtp->name.s, s.s, s.len ))
  150. {
  151. LM_DBG("DB %.*s \n", s.len, s.s);
  152. lock_get(&_tbc->dtp->sem);
  153. _db = _tbc->dtp->db;
  154. if(_db)
  155. rc = _db->close(_db, 0);
  156. if(rc != 0)
  157. LM_CRIT("error closing %s\n", _tbc->dtp->name.s);
  158. _tbc->dtp->db = NULL;
  159. lock_release(&_tbc->dtp->sem);
  160. return 0;
  161. }
  162. }
  163. _tbc = _tbc->next;
  164. }
  165. }
  166. LM_DBG("DB not found %.*s \n", s.len, s.s);
  167. return 1; /*table not found*/
  168. }
  169. /** opens the underlying Berkeley DB.
  170. assumes the lib data-structures are already initialzed;
  171. used to sync and reload the db file.
  172. */
  173. int km_bdblib_reopen(char* _n)
  174. {
  175. str s;
  176. int rc, flags;
  177. tbl_cache_p _tbc;
  178. DB* _db = NULL;
  179. DB_ENV* _env = NULL;
  180. database_p _db_p = *_cachedb;
  181. rc = flags = 0;
  182. _tbc = NULL;
  183. if (!_cachedb || !_n)
  184. return -1;
  185. s.s = (char*)_n;
  186. s.len = strlen(_n);
  187. if (_db_p)
  188. {
  189. _env = _db_p->dbenv;
  190. _tbc = _db_p->tables;
  191. if(s.len ==_db_p->name.len &&
  192. !strncasecmp(s.s, _db_p->name.s,_db_p->name.len))
  193. {
  194. //open the whole dbenv
  195. LM_DBG("-- km_bdblib_reopen ENV %.*s \n", s.len, s.s);
  196. if(!_db_p->dbenv)
  197. { rc = km_bdblib_create_dbenv(&_env, _n);
  198. _db_p->dbenv = _env;
  199. }
  200. if(rc!=0) return rc;
  201. _env = _db_p->dbenv;
  202. _tbc = _db_p->tables;
  203. while(_tbc)
  204. {
  205. if(_tbc->dtp)
  206. {
  207. lock_get(&_tbc->dtp->sem);
  208. if(!_tbc->dtp->db)
  209. {
  210. if ((rc = db_create(&_db, _env, 0)) != 0)
  211. { _env->err(_env, rc, "db_create");
  212. LM_CRIT("error in db_create, db error: %s.\n",db_strerror(rc));
  213. km_bdblib_recover(_tbc->dtp, rc);
  214. }
  215. }
  216. if ((rc = _db->open(_db, NULL, _n, NULL, DB_HASH, DB_CREATE, 0664)) != 0)
  217. { _db->dbenv->err(_env, rc, "DB->open: %s", _n);
  218. LM_CRIT("error in db_open: %s.\n",db_strerror(rc));
  219. km_bdblib_recover(_tbc->dtp, rc);
  220. }
  221. _tbc->dtp->db = _db;
  222. lock_release(&_tbc->dtp->sem);
  223. }
  224. _tbc = _tbc->next;
  225. }
  226. _env->close(_env, 0);
  227. return rc;
  228. }
  229. //open a particular db
  230. while(_tbc)
  231. {
  232. if(_tbc->dtp)
  233. {
  234. LM_DBG("checking DB %.*s \n"
  235. , _tbc->dtp->name.len
  236. , _tbc->dtp->name.s);
  237. if(_tbc->dtp->name.len == s.len &&
  238. !strncasecmp(_tbc->dtp->name.s, s.s, s.len ))
  239. {
  240. LM_DBG("DB %.*s \n", s.len, s.s);
  241. lock_get(&_tbc->dtp->sem);
  242. if(!_tbc->dtp->db)
  243. {
  244. if ((rc = db_create(&_db, _env, 0)) != 0)
  245. { _env->err(_env, rc, "db_create");
  246. LM_CRIT("error in db_create, db error: %s.\n",db_strerror(rc));
  247. km_bdblib_recover(_tbc->dtp, rc);
  248. }
  249. }
  250. if ((rc = _db->open(_db, NULL, _n, NULL, DB_HASH, DB_CREATE, 0664)) != 0)
  251. { _db->dbenv->err(_env, rc, "DB->open: %s", _n);
  252. LM_CRIT("bdb open: %s.\n",db_strerror(rc));
  253. km_bdblib_recover(_tbc->dtp, rc);
  254. }
  255. _tbc->dtp->db = _db;
  256. lock_release(&_tbc->dtp->sem);
  257. return rc;
  258. }
  259. }
  260. _tbc = _tbc->next;
  261. }
  262. }
  263. LM_DBG("DB not found %.*s \n", s.len, s.s);
  264. return 1; /*table not found*/
  265. }
  266. /**
  267. *
  268. */
  269. int km_bdblib_create_dbenv(DB_ENV **_dbenv, char* _home)
  270. {
  271. DB_ENV *env;
  272. char *progname;
  273. int rc, flags;
  274. progname = "kamailio";
  275. /* Create an environment and initialize it for additional error * reporting. */
  276. if ((rc = db_env_create(&env, 0)) != 0)
  277. {
  278. LM_ERR("db_env_create failed! bdb error: %s.\n", db_strerror(rc));
  279. return (rc);
  280. }
  281. env->set_errpfx(env, progname);
  282. /* Specify the shared memory buffer pool cachesize */
  283. if ((rc = env->set_cachesize(env, 0, _db_parms->cache_size, 0)) != 0)
  284. {
  285. LM_ERR("dbenv set_cachsize failed! bdb error: %s.\n", db_strerror(rc));
  286. env->err(env, rc, "set_cachesize");
  287. goto err;
  288. }
  289. /* Concurrent Data Store flags */
  290. flags = DB_CREATE |
  291. DB_INIT_CDB |
  292. DB_INIT_MPOOL |
  293. DB_THREAD;
  294. /* Transaction Data Store flags ; not supported yet */
  295. /*
  296. flags = DB_CREATE |
  297. DB_RECOVER |
  298. DB_INIT_LOG |
  299. DB_INIT_LOCK |
  300. DB_INIT_MPOOL |
  301. DB_THREAD |
  302. DB_INIT_TXN;
  303. */
  304. /* Open the environment */
  305. if ((rc = env->open(env, _home, flags, 0)) != 0)
  306. {
  307. LM_ERR("dbenv is not initialized! bdb error: %s.\n",db_strerror(rc));
  308. env->err(env, rc, "environment open: %s", _home);
  309. goto err;
  310. }
  311. *_dbenv = env;
  312. return (0);
  313. err: (void)env->close(env, 0);
  314. return (rc);
  315. }
  316. /**
  317. */
  318. database_p km_bdblib_get_db(str *_s)
  319. {
  320. int rc;
  321. database_p _db_p=NULL;
  322. char name[512];
  323. if(!_s || !_s->s || _s->len<=0 || _s->len > 512)
  324. return NULL;
  325. if( !_cachedb)
  326. {
  327. LM_ERR("db_berkeley cache is not initialized! Check if you loaded db_berkeley "
  328. "before any other module that uses it.\n");
  329. return NULL;
  330. }
  331. _db_p = *_cachedb;
  332. if(_db_p)
  333. {
  334. LM_DBG("db already cached!\n");
  335. return _db_p;
  336. }
  337. if(!km_bdb_is_database(_s))
  338. {
  339. LM_ERR("database [%.*s] does not exists!\n" ,_s->len , _s->s);
  340. return NULL;
  341. }
  342. _db_p = (database_p)pkg_malloc(sizeof(database_t));
  343. if(!_db_p)
  344. {
  345. LM_ERR("no private memory for dbenv_t.\n");
  346. pkg_free(_db_p);
  347. return NULL;
  348. }
  349. _db_p->name.s = (char*)pkg_malloc(_s->len*sizeof(char));
  350. memcpy(_db_p->name.s, _s->s, _s->len);
  351. _db_p->name.len = _s->len;
  352. strncpy(name, _s->s, _s->len);
  353. name[_s->len] = 0;
  354. if ((rc = km_bdblib_create_dbenv(&(_db_p->dbenv), name)) != 0)
  355. {
  356. LM_ERR("km_bdblib_create_dbenv failed");
  357. pkg_free(_db_p->name.s);
  358. pkg_free(_db_p);
  359. return NULL;
  360. }
  361. _db_p->tables=NULL;
  362. *_cachedb = _db_p;
  363. return _db_p;
  364. }
  365. /**
  366. * look thru a linked list for the table. if dne, create a new one
  367. * and add to the list
  368. */
  369. tbl_cache_p km_bdblib_get_table(database_p _db, str *_s)
  370. {
  371. tbl_cache_p _tbc = NULL;
  372. table_p _tp = NULL;
  373. if(!_db || !_s || !_s->s || _s->len<=0)
  374. return NULL;
  375. if(!_db->dbenv)
  376. {
  377. return NULL;
  378. }
  379. _tbc = _db->tables;
  380. while(_tbc)
  381. {
  382. if(_tbc->dtp)
  383. {
  384. if(_tbc->dtp->name.len == _s->len
  385. && !strncasecmp(_tbc->dtp->name.s, _s->s, _s->len ))
  386. {
  387. return _tbc;
  388. }
  389. }
  390. _tbc = _tbc->next;
  391. }
  392. _tbc = (tbl_cache_p)pkg_malloc(sizeof(tbl_cache_t));
  393. if(!_tbc)
  394. return NULL;
  395. if(!lock_init(&_tbc->sem))
  396. {
  397. pkg_free(_tbc);
  398. return NULL;
  399. }
  400. _tp = km_bdblib_create_table(_db, _s);
  401. #ifdef BDB_EXTRA_DEBUG
  402. LM_DBG("table: %.*s\n", _s->len, _s->s);
  403. #endif
  404. if(!_tp)
  405. {
  406. LM_ERR("failed to create table.\n");
  407. pkg_free(_tbc);
  408. return NULL;
  409. }
  410. lock_get(&_tbc->sem);
  411. _tbc->dtp = _tp;
  412. if(_db->tables)
  413. (_db->tables)->prev = _tbc;
  414. _tbc->next = _db->tables;
  415. _db->tables = _tbc;
  416. lock_release(&_tbc->sem);
  417. return _tbc;
  418. }
  419. void km_bdblib_log(int op, table_p _tp, char* _msg, int len)
  420. {
  421. if(!_tp || !len) return;
  422. if(! _db_parms->log_enable) return;
  423. if (_tp->logflags == JLOG_NONE) return;
  424. if ((_tp->logflags & op) == op)
  425. { int op_len=7;
  426. char buf[MAX_ROW_SIZE + op_len];
  427. char *c;
  428. time_t now = time(NULL);
  429. if( _db_parms->journal_roll_interval)
  430. {
  431. if((_tp->t) && (now - _tp->t) > _db_parms->journal_roll_interval)
  432. { /*try to roll logfile*/
  433. if(km_bdblib_create_journal(_tp))
  434. {
  435. LM_ERR("Journaling has FAILED !\n");
  436. return;
  437. }
  438. }
  439. }
  440. c = buf;
  441. switch (op)
  442. {
  443. case JLOG_INSERT:
  444. strncpy(c, "INSERT|", op_len);
  445. break;
  446. case JLOG_UPDATE:
  447. strncpy(c, "UPDATE|", op_len);
  448. break;
  449. case JLOG_DELETE:
  450. strncpy(c, "DELETE|", op_len);
  451. break;
  452. }
  453. c += op_len;
  454. strncpy(c, _msg, len);
  455. c +=len;
  456. *c = '\n';
  457. c++;
  458. *c = '\0';
  459. if ((_tp->logflags & JLOG_STDOUT) == JLOG_STDOUT)
  460. puts(buf);
  461. if ((_tp->logflags & JLOG_SYSLOG) == JLOG_SYSLOG)
  462. syslog(LOG_LOCAL6, "%s", buf);
  463. if(_tp->fp)
  464. {
  465. if(!fputs(buf, _tp->fp) )
  466. fflush(_tp->fp);
  467. }
  468. }
  469. }
  470. /**
  471. * The function is called to create a handle to a db table.
  472. *
  473. * On startup, we do not create any of the db handles.
  474. * Instead it is done on first-use (lazy-initialized) to only create handles to
  475. * files (db) that we require.
  476. *
  477. * There is one db file per kamailio table (eg. acc), and they should exist
  478. * in your DB_PATH (refer to kamctlrc) directory.
  479. *
  480. * This function does _not_ create the underlying binary db tables.
  481. * Creating the tables MUST be manually performed before
  482. * kamailio startup by 'kamdbctl create'
  483. *
  484. * Function returns NULL on error, which will cause kamailio to exit.
  485. *
  486. */
  487. table_p km_bdblib_create_table(database_p _db, str *_s)
  488. {
  489. int rc,i,flags;
  490. DB *bdb = NULL;
  491. table_p tp = NULL;
  492. char tblname[MAX_TABLENAME_SIZE];
  493. if(!_db || !_db->dbenv)
  494. {
  495. LM_ERR("no database_p or dbenv.\n");
  496. return NULL;
  497. }
  498. tp = (table_p)pkg_malloc(sizeof(table_t));
  499. if(!tp)
  500. {
  501. LM_ERR("no private memory for table_t.\n");
  502. return NULL;
  503. }
  504. if ((rc = db_create(&bdb, _db->dbenv, 0)) != 0)
  505. {
  506. _db->dbenv->err(_db->dbenv, rc, "database create");
  507. LM_ERR("error in db_create, bdb error: %s.\n",db_strerror(rc));
  508. pkg_free(tp);
  509. return NULL;
  510. }
  511. memset(tblname, 0, MAX_TABLENAME_SIZE);
  512. strncpy(tblname, _s->s, _s->len);
  513. #ifdef BDB_EXTRA_DEBUG
  514. LM_DBG("CREATE TABLE = %s\n", tblname);
  515. #endif
  516. flags = DB_THREAD;
  517. if ((rc = bdb->open(bdb, NULL, tblname, NULL, DB_HASH, flags, 0664)) != 0)
  518. {
  519. _db->dbenv->err(_db->dbenv, rc, "DB->open: %s", tblname);
  520. LM_ERR("bdb open failed: %s.\n",db_strerror(rc));
  521. pkg_free(tp);
  522. return NULL;
  523. }
  524. if(!lock_init(&tp->sem))
  525. {
  526. goto error;
  527. }
  528. tp->name.s = (char*)pkg_malloc(_s->len*sizeof(char));
  529. memcpy(tp->name.s, _s->s, _s->len);
  530. tp->name.len = _s->len;
  531. tp->db=bdb;
  532. tp->ncols=0;
  533. tp->nkeys=0;
  534. tp->ro=0; /*0=ReadWrite ; 1=ReadOnly*/
  535. tp->ino=0; /*inode*/
  536. tp->logflags=0; /*bitmap; 4=Delete, 2=Update, 1=Insert, 0=None*/
  537. tp->fp=0;
  538. tp->t=0;
  539. for(i=0;i<MAX_NUM_COLS;i++)
  540. tp->colp[i] = NULL;
  541. /*load metadata; seeded\db_loaded when database are created*/
  542. /*initialize columns with metadata*/
  543. rc = km_load_metadata_columns(tp);
  544. if(rc!=0)
  545. {
  546. LM_ERR("FAILED to load METADATA COLS in table: %s.\n", tblname);
  547. goto error;
  548. }
  549. /*initialize columns default values from metadata*/
  550. rc = km_load_metadata_defaults(tp);
  551. if(rc!=0)
  552. {
  553. LM_ERR("FAILED to load METADATA DEFAULTS in table: %s.\n", tblname);
  554. goto error;
  555. }
  556. rc = km_load_metadata_keys(tp);
  557. if(rc!=0)
  558. {
  559. LM_ERR("FAILED to load METADATA KEYS in table: %s.\n", tblname);
  560. /*will have problems later figuring column types*/
  561. goto error;
  562. }
  563. /*opened RW by default; Query to set the RO flag */
  564. rc = km_load_metadata_readonly(tp);
  565. if(rc!=0)
  566. {
  567. LM_INFO("No METADATA_READONLY in table: %s.\n", tblname);
  568. /*non-critical; table will default to READWRITE*/
  569. }
  570. if(tp->ro)
  571. {
  572. /*schema defines this table RO readonly*/
  573. #ifdef BDB_EXTRA_DEBUG
  574. LM_DBG("TABLE %.*s is changing to READONLY mode\n"
  575. , tp->name.len, tp->name.s);
  576. #endif
  577. if ((rc = bdb->close(bdb,0)) != 0)
  578. {
  579. _db->dbenv->err(_db->dbenv, rc, "DB->close: %s", tblname);
  580. LM_ERR("bdb close: %s.\n",db_strerror(rc));
  581. goto error;
  582. }
  583. bdb = NULL;
  584. if ((rc = db_create(&bdb, _db->dbenv, 0)) != 0)
  585. {
  586. _db->dbenv->err(_db->dbenv, rc, "database create");
  587. LM_ERR("error in db_create.\n");
  588. goto error;
  589. }
  590. flags = DB_THREAD | DB_RDONLY;
  591. if ((rc = bdb->open(bdb, NULL, tblname, NULL, DB_HASH, flags, 0664)) != 0)
  592. {
  593. _db->dbenv->err(_db->dbenv, rc, "DB->open: %s", tblname);
  594. LM_ERR("bdb open: %s.\n",db_strerror(rc));
  595. goto error;
  596. }
  597. tp->db=bdb;
  598. }
  599. /* set the journaling flags; flags indicate which operations
  600. need to be journalled. (e.g possible to only journal INSERT.)
  601. */
  602. rc = km_load_metadata_logflags(tp);
  603. if(rc!=0)
  604. LM_INFO("No METADATA_LOGFLAGS in table: %s.\n", tblname);
  605. if ((tp->logflags & JLOG_FILE) == JLOG_FILE)
  606. km_bdblib_create_journal(tp);
  607. return tp;
  608. error:
  609. if(tp)
  610. {
  611. pkg_free(tp->name.s);
  612. pkg_free(tp);
  613. }
  614. return NULL;
  615. }
  616. int km_bdblib_create_journal(table_p _tp)
  617. {
  618. char *s;
  619. char fn[1024];
  620. char d[64];
  621. FILE *fp = NULL;
  622. struct tm *t;
  623. int bl;
  624. database_p _db_p = *_cachedb;
  625. time_t tim = time(NULL);
  626. if(! _db_p || ! _tp) return -1;
  627. if(! _db_parms->log_enable) return 0;
  628. /* journal filename ; e.g. '/var/kamailio/db/location-YYYYMMDDhhmmss.jnl' */
  629. s=fn;
  630. strncpy(s, _db_p->name.s, _db_p->name.len);
  631. s+=_db_p->name.len;
  632. *s = '/';
  633. s++;
  634. strncpy(s, _tp->name.s, _tp->name.len);
  635. s+=_tp->name.len;
  636. t = localtime( &tim );
  637. bl=strftime(d,128,"-%Y%m%d%H%M%S.jnl",t);
  638. strncpy(s, d, bl);
  639. s+= bl;
  640. *s = 0;
  641. if(_tp->fp)
  642. { /* must be rolling. */
  643. if( fclose(_tp->fp) )
  644. { LM_ERR("Failed to Close Log in table: %.*s .\n", _tp->name.len,
  645. _tp->name.s);
  646. return -1;
  647. }
  648. }
  649. if( (fp = fopen(fn, "w")) != NULL )
  650. {
  651. _tp->fp = fp;
  652. }
  653. else
  654. {
  655. LM_ERR("Failed to Open Log in table: %.*s .\n",_tp->name.len, _tp->name.s);
  656. return -1;
  657. }
  658. _tp->t = tim;
  659. return 0;
  660. }
  661. int km_load_metadata_columns(table_p _tp)
  662. {
  663. int ret,n,len;
  664. char dbuf[MAX_ROW_SIZE];
  665. char *s = NULL;
  666. char cn[64], ct[16];
  667. DB *db = NULL;
  668. DBT key, data;
  669. column_p col;
  670. ret = n = len = 0;
  671. if(!_tp || !_tp->db)
  672. return -1;
  673. if(_tp->ncols!=0)
  674. return 0;
  675. db = _tp->db;
  676. memset(&key, 0, sizeof(DBT));
  677. memset(&data, 0, sizeof(DBT));
  678. memset(dbuf, 0, MAX_ROW_SIZE);
  679. key.data = METADATA_COLUMNS;
  680. key.size = strlen(METADATA_COLUMNS);
  681. /*memory for the result*/
  682. data.data = dbuf;
  683. data.ulen = MAX_ROW_SIZE;
  684. data.flags = DB_DBT_USERMEM;
  685. if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
  686. {
  687. db->err(db, ret, "km_load_metadata_columns DB->get failed");
  688. LM_ERR("FAILED to find METADATA_COLUMNS in DB \n");
  689. return -1;
  690. }
  691. /* eg: dbuf = "table_name(str) table_version(int)" */
  692. s = strtok(dbuf, " ");
  693. while(s!=NULL && n<MAX_NUM_COLS)
  694. {
  695. /* eg: meta[0]=table_name meta[1]=str */
  696. sscanf(s,"%20[^(](%10[^)])[^\n]", cn, ct);
  697. /* create column*/
  698. col = (column_p) pkg_malloc(sizeof(column_t));
  699. if(!col)
  700. { LM_ERR("out of private memory \n");
  701. return -1;
  702. }
  703. /* set name*/
  704. len = strlen( cn );
  705. col->name.s = (char*)pkg_malloc(len * sizeof(char));
  706. memcpy(col->name.s, cn, len );
  707. col->name.len = len;
  708. /*set column type*/
  709. if(strncmp(ct, "str", 3)==0)
  710. { col->type = DB1_STRING;
  711. }
  712. else if(strncmp(ct, "int", 3)==0)
  713. { col->type = DB1_INT;
  714. }
  715. else if(strncmp(ct, "double", 6)==0)
  716. { col->type = DB1_DOUBLE;
  717. }
  718. else if(strncmp(ct, "datetime", 8)==0)
  719. { col->type = DB1_DATETIME;
  720. }
  721. else
  722. { col->type = DB1_STRING;
  723. }
  724. col->flag = 0;
  725. _tp->colp[n] = col;
  726. n++;
  727. _tp->ncols++;
  728. s=strtok(NULL, " ");
  729. }
  730. return 0;
  731. }
  732. int km_load_metadata_keys(table_p _tp)
  733. {
  734. int ret,n,ci;
  735. char dbuf[MAX_ROW_SIZE];
  736. char *s = NULL;
  737. DB *db = NULL;
  738. DBT key, data;
  739. ret = n = ci = 0;
  740. if(!_tp || !_tp->db)
  741. return -1;
  742. db = _tp->db;
  743. memset(&key, 0, sizeof(DBT));
  744. memset(&data, 0, sizeof(DBT));
  745. memset(dbuf, 0, MAX_ROW_SIZE);
  746. key.data = METADATA_KEY;
  747. key.size = strlen(METADATA_KEY);
  748. data.data = dbuf;
  749. data.ulen = MAX_ROW_SIZE;
  750. data.flags = DB_DBT_USERMEM;
  751. if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
  752. {
  753. db->err(db, ret, "km_load_metadata_keys DB->get failed");
  754. LM_ERR("FAILED to find METADATA in table \n");
  755. return ret;
  756. }
  757. s = strtok(dbuf, " ");
  758. while(s!=NULL && n< _tp->ncols)
  759. { ret = sscanf(s,"%i", &ci);
  760. if(ret != 1) return -1;
  761. if( _tp->colp[ci] )
  762. { _tp->colp[ci]->flag = 1;
  763. _tp->nkeys++;
  764. }
  765. n++;
  766. s=strtok(NULL, " ");
  767. }
  768. return 0;
  769. }
  770. int km_load_metadata_readonly(table_p _tp)
  771. {
  772. int i, ret;
  773. char dbuf[MAX_ROW_SIZE];
  774. DB *db = NULL;
  775. DBT key, data;
  776. i = 0;
  777. if(!_tp || !_tp->db)
  778. return -1;
  779. db = _tp->db;
  780. memset(&key, 0, sizeof(DBT));
  781. memset(&data, 0, sizeof(DBT));
  782. memset(dbuf, 0, MAX_ROW_SIZE);
  783. key.data = METADATA_READONLY;
  784. key.size = strlen(METADATA_READONLY);
  785. data.data = dbuf;
  786. data.ulen = MAX_ROW_SIZE;
  787. data.flags = DB_DBT_USERMEM;
  788. if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
  789. { return ret;
  790. }
  791. if( 1 == sscanf(dbuf,"%i", &i) )
  792. _tp->ro=(i>0)?1:0;
  793. return 0;
  794. }
  795. int km_load_metadata_logflags(table_p _tp)
  796. {
  797. int i, ret;
  798. char dbuf[MAX_ROW_SIZE];
  799. DB *db = NULL;
  800. DBT key, data;
  801. i = 0;
  802. if(!_tp || !_tp->db)
  803. return -1;
  804. db = _tp->db;
  805. memset(&key, 0, sizeof(DBT));
  806. memset(&data, 0, sizeof(DBT));
  807. memset(dbuf, 0, MAX_ROW_SIZE);
  808. key.data = METADATA_LOGFLAGS;
  809. key.size = strlen(METADATA_LOGFLAGS);
  810. data.data = dbuf;
  811. data.ulen = MAX_ROW_SIZE;
  812. data.flags = DB_DBT_USERMEM;
  813. if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
  814. { return ret;
  815. }
  816. if( 1 == sscanf(dbuf,"%i", &i) )
  817. _tp->logflags=i;
  818. return 0;
  819. }
  820. int km_load_metadata_defaults(table_p _tp)
  821. {
  822. int ret,n,len;
  823. char dbuf[MAX_ROW_SIZE];
  824. char *s = NULL;
  825. char cv[64];
  826. DB *db = NULL;
  827. DBT key, data;
  828. column_p col;
  829. ret = n = len = 0;
  830. if(!_tp || !_tp->db)
  831. return -1;
  832. db = _tp->db;
  833. memset(&key, 0, sizeof(DBT));
  834. memset(&data, 0, sizeof(DBT));
  835. memset(dbuf, 0, MAX_ROW_SIZE);
  836. key.data = METADATA_DEFAULTS;
  837. key.size = strlen(METADATA_DEFAULTS);
  838. /*memory for the result*/
  839. data.data = dbuf;
  840. data.ulen = MAX_ROW_SIZE;
  841. data.flags = DB_DBT_USERMEM;
  842. if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
  843. {
  844. #ifdef BDB_EXTRA_DEBUG
  845. LM_DBG("NO DEFAULTS ; SETTING ALL columns to NULL! \n" );
  846. #endif
  847. /*no defaults in DB; make some up.*/
  848. for(n=0; n<_tp->ncols; n++)
  849. {
  850. col = _tp->colp[n];
  851. if( col )
  852. { /*set all columns default value to 'NULL' */
  853. len = strlen("NULL");
  854. col->dv.s = (char*)pkg_malloc(len * sizeof(char));
  855. memcpy(col->dv.s, "NULL", len);
  856. col->dv.len = len;
  857. }
  858. }
  859. return 0;
  860. }
  861. /* use the defaults provided*/
  862. s = strtok(dbuf, DELIM);
  863. while(s!=NULL && n< _tp->ncols)
  864. { ret = sscanf(s,"%s", cv);
  865. if(ret != 1) return -1;
  866. col = _tp->colp[n];
  867. if( col )
  868. { /*set column default*/
  869. len = strlen(s);
  870. col->dv.s = (char*)pkg_malloc(len * sizeof(char));
  871. memcpy(col->dv.s, cv, len);
  872. col->dv.len = len;
  873. #ifdef BDB_EXTRA_DEBUG
  874. LM_DBG("COLUMN DEFAULT is %.*s for column[%.*s] \n"
  875. , col->dv.len , ZSW(col->dv.s)
  876. , col->name.len , ZSW(col->name.s)
  877. );
  878. #endif
  879. }
  880. n++;
  881. s=strtok(NULL, DELIM);
  882. }
  883. return 0;
  884. }
  885. /*creates a composite key _k of length _klen from n values of _v;
  886. provide your own initialized memory for target _k and _klen;
  887. resulting value: _k = "KEY1 | KEY2"
  888. ko = key only
  889. */
  890. int km_bdblib_valtochar(table_p _tp, int* _lres, char* _k, int* _klen, db_val_t* _v, int _n, int _ko)
  891. {
  892. char *p;
  893. char sk[MAX_ROW_SIZE]; // subkey(sk) val
  894. char* delim = DELIM;
  895. char* cNULL = "NULL";
  896. int len, total, sum;
  897. int i, j, k;
  898. p = _k;
  899. len = sum = total = 0;
  900. i = j = k = 0;
  901. if(!_tp) return -1;
  902. if(!_v || (_n<1) ) return -1;
  903. if(!_k || !_klen ) return -1;
  904. if( *_klen < 1) return -1;
  905. memset(sk, 0, MAX_ROW_SIZE);
  906. total = *_klen;
  907. *_klen = 0; //sum
  908. if(! _lres)
  909. {
  910. #ifdef BDB_EXTRA_DEBUG
  911. LM_DBG("schema has NOT specified any keys! \n");
  912. #endif
  913. /* schema has not specified keys
  914. just use the provided data in order provided
  915. */
  916. for(i=0;i<_n;i++)
  917. { len = total - sum;
  918. if ( km_bdb_val2str(&_v[i], sk, &len) != 0 )
  919. { LM_ERR("error building composite key \n");
  920. return -2;
  921. }
  922. sum += len;
  923. if(sum > total)
  924. { LM_ERR("Destination buffer too short for subval %s\n",sk);
  925. return -2;
  926. }
  927. /* write sk */
  928. strncpy(p, sk, len);
  929. p += len;
  930. *_klen = sum;
  931. sum += DELIM_LEN;
  932. if(sum > total)
  933. { LM_ERR("Destination buffer too short for delim \n");
  934. return -3;
  935. }
  936. /* write delim */
  937. strncpy(p, delim, DELIM_LEN);
  938. p += DELIM_LEN;
  939. *_klen = sum;;
  940. }
  941. return 0;
  942. }
  943. /*
  944. schema has specified keys
  945. verify all schema keys are provided
  946. use 'NULL' for those that are missing.
  947. */
  948. for(i=0; i<_tp->ncols; i++)
  949. { /* i indexes columns in schema order */
  950. if( _ko)
  951. { /* keymode; skip over non-key columns */
  952. if( ! _tp->colp[i]->flag)
  953. continue;
  954. }
  955. for(j=0; j<_n; j++)
  956. {
  957. /*
  958. j indexes the columns provided in _k
  959. which may be less than the total required by
  960. the schema. the app does not know the order
  961. of the columns in our schema!
  962. */
  963. k = (_lres) ? _lres[j] : j;
  964. /*
  965. * k index will remap back to our schema order; like i
  966. */
  967. if(i == k)
  968. {
  969. /*
  970. KEY was provided; append to buffer;
  971. _k[j] contains a key, but its a key that
  972. corresponds to column k of our schema.
  973. now we know its a match, and we dont need
  974. index k for anything else
  975. */
  976. #ifdef BDB_EXTRA_DEBUG
  977. LM_DBG("KEY PROVIDED[%i]: %.*s.%.*s \n", i
  978. , _tp->name.len , ZSW(_tp->name.s)
  979. , _tp->colp[i]->name.len, ZSW(_tp->colp[i]->name.s)
  980. );
  981. #endif
  982. len = total - sum;
  983. if ( km_bdb_val2str(&_v[j], sk, &len) != 0)
  984. { LM_ERR("Destination buffer too short for subval %s\n",sk);
  985. return -4;
  986. }
  987. sum += len;
  988. if(sum > total)
  989. { LM_ERR("Destination buffer too short for subval %s\n",sk);
  990. return -5;
  991. }
  992. strncpy(p, sk, len);
  993. p += len;
  994. *_klen = sum;
  995. sum += DELIM_LEN;
  996. if(sum > total)
  997. { LM_ERR("Destination buffer too short for delim \n");
  998. return -5;
  999. }
  1000. /* append delim */
  1001. strncpy(p, delim, DELIM_LEN);
  1002. p += DELIM_LEN;
  1003. *_klen = sum;
  1004. /* take us out of inner for loop
  1005. and at the end of the outer loop
  1006. to look for our next schema key
  1007. */
  1008. goto next;
  1009. }
  1010. }
  1011. /*
  1012. NO KEY provided; use the column default value (dv)
  1013. i.e _tp->colp[i]->dv
  1014. */
  1015. #ifdef BDB_EXTRA_DEBUG
  1016. LM_DBG("Missing KEY[%i]: %.*s.%.*s using default [%.*s] \n", i
  1017. , _tp->name.len , ZSW(_tp->name.s)
  1018. , _tp->colp[i]->name.len, ZSW(_tp->colp[i]->name.s)
  1019. , _tp->colp[i]->dv.len , ZSW(_tp->colp[i]->dv.s)
  1020. );
  1021. #endif
  1022. len = _tp->colp[i]->dv.len;
  1023. sum += len;
  1024. if(sum > total)
  1025. { LM_ERR("Destination buffer too short for subval %s\n",cNULL);
  1026. return -5;
  1027. }
  1028. strncpy(p, _tp->colp[i]->dv.s, len);
  1029. p += len;
  1030. *_klen = sum;
  1031. sum += DELIM_LEN;
  1032. if(sum > total)
  1033. { LM_ERR("Destination buffer too short for delim \n");
  1034. return -5;
  1035. }
  1036. strncpy(p, delim, DELIM_LEN);
  1037. p += DELIM_LEN;
  1038. *_klen = sum;
  1039. next:
  1040. continue;
  1041. }
  1042. return 0;
  1043. }
  1044. /**
  1045. *
  1046. */
  1047. int db_free(database_p _dbp)
  1048. {
  1049. tbl_cache_p _tbc = NULL, _tbc0=NULL;
  1050. if(!_dbp)
  1051. return -1;
  1052. _tbc = _dbp->tables;
  1053. while(_tbc)
  1054. {
  1055. _tbc0 = _tbc->next;
  1056. tbl_cache_free(_tbc);
  1057. _tbc = _tbc0;
  1058. }
  1059. if(_dbp->dbenv)
  1060. _dbp->dbenv->close(_dbp->dbenv, 0);
  1061. if(_dbp->name.s)
  1062. pkg_free(_dbp->name.s);
  1063. pkg_free(_dbp);
  1064. return 0;
  1065. }
  1066. /**
  1067. *
  1068. */
  1069. int tbl_cache_free(tbl_cache_p _tbc)
  1070. {
  1071. if(!_tbc)
  1072. return -1;
  1073. lock_get(&_tbc->sem);
  1074. if(_tbc->dtp)
  1075. tbl_free(_tbc->dtp);
  1076. lock_destroy(&_tbc->sem);
  1077. pkg_free(_tbc);
  1078. return 0;
  1079. }
  1080. /**
  1081. * close DB (sync data to disk) and free mem
  1082. */
  1083. int tbl_free(table_p _tp)
  1084. { int i;
  1085. if(!_tp)
  1086. return -1;
  1087. if(_tp->db)
  1088. _tp->db->close(_tp->db, 0);
  1089. if(_tp->fp)
  1090. fclose(_tp->fp);
  1091. if(_tp->name.s)
  1092. pkg_free(_tp->name.s);
  1093. for(i=0;i<_tp->ncols;i++)
  1094. { if(_tp->colp[i])
  1095. { pkg_free(_tp->colp[i]->name.s);
  1096. pkg_free(_tp->colp[i]->dv.s);
  1097. pkg_free(_tp->colp[i]);
  1098. }
  1099. }
  1100. pkg_free(_tp);
  1101. return 0;
  1102. }
  1103. int km_bdblib_recover(table_p _tp, int _rc)
  1104. {
  1105. switch(_rc)
  1106. {
  1107. case DB_LOCK_DEADLOCK:
  1108. LM_ERR("DB_LOCK_DEADLOCK detected !!\n");
  1109. case DB_RUNRECOVERY:
  1110. LM_ERR("DB_RUNRECOVERY detected !! \n");
  1111. km_bdblib_destroy();
  1112. exit(1);
  1113. break;
  1114. }
  1115. return 0;
  1116. }