00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <time.h>
00033 #include <sys/types.h>
00034 #include <dirent.h>
00035 #include "../../ut.h"
00036 #include "../../mem/mem.h"
00037 #include "../../dprint.h"
00038
00039 #include "bdb_util.h"
00040 #include "bdb_lib.h"
00041 #include "bdb_val.h"
00042
00043 static database_p *_cachedb = NULL;
00044 static db_parms_p _db_parms = NULL;
00045
00046
00047
00048
00049 int bdblib_init(db_parms_p _p)
00050 {
00051 if (!_cachedb)
00052 {
00053 _cachedb = pkg_malloc( sizeof(database_p) );
00054 if (!_cachedb)
00055 { LM_CRIT("not enough private memory\n");
00056 return -1;
00057 }
00058
00059 *_cachedb = NULL;
00060
00061
00062 db_parms_p dp = (db_parms_p) pkg_malloc( sizeof(db_parms_t) );
00063 if (!dp)
00064 { LM_CRIT("not enough private memory\n");
00065 return -1;
00066 }
00067
00068 if(_p)
00069 {
00070 dp->cache_size = _p->cache_size;
00071 dp->auto_reload = _p->auto_reload;
00072 dp->log_enable = _p->log_enable;
00073 dp->journal_roll_interval = _p->journal_roll_interval;
00074 }
00075 else
00076 {
00077 dp->cache_size = (4 * 1024 * 1024);
00078 dp->auto_reload = 0;
00079 dp->log_enable = 0;
00080 dp->journal_roll_interval = 3600;
00081 }
00082
00083 _db_parms = dp;
00084 }
00085 return 0;
00086 }
00087
00088
00089
00090
00091
00092 int bdblib_destroy(void)
00093 {
00094 if (_cachedb) db_free(*_cachedb);
00095 if(_db_parms) pkg_free(_db_parms);
00096 return 0;
00097 }
00098
00099
00100
00101
00102
00103
00104 int bdblib_close(char* _n)
00105 {
00106 str s;
00107 int rc;
00108 tbl_cache_p _tbc;
00109 DB* _db = NULL;
00110 DB_ENV* _env = NULL;
00111 database_p _db_p = *_cachedb;
00112
00113 if (!_cachedb || !_n)
00114 return -1;
00115
00116 rc = 0;
00117 s.s = (char*)_n;
00118 s.len = strlen(_n);
00119
00120 if (_db_p)
00121 {
00122 _env = _db_p->dbenv;
00123 _tbc = _db_p->tables;
00124 LM_DBG("ENV %.*s \n"
00125 , _db_p->name.len
00126 , _db_p->name.s);
00127 if(s.len == _db_p->name.len &&
00128 !strncasecmp(s.s, _db_p->name.s, _db_p->name.len))
00129 {
00130
00131 LM_DBG("ENV %.*s \n", s.len, s.s);
00132 while(_tbc)
00133 {
00134 if(_tbc->dtp)
00135 {
00136 lock_get(&_tbc->dtp->sem);
00137 _db = _tbc->dtp->db;
00138 if(_db)
00139 rc = _db->close(_db, 0);
00140 if(rc != 0)
00141 LM_CRIT("error closing %s\n", _tbc->dtp->name.s);
00142 _tbc->dtp->db = NULL;
00143
00144 lock_release(&_tbc->dtp->sem);
00145 }
00146 _tbc = _tbc->next;
00147 }
00148 _env->close(_env, 0);
00149 _db_p->dbenv = NULL;
00150 return 0;
00151 }
00152
00153
00154 while(_tbc)
00155 {
00156 if(_tbc->dtp)
00157 {
00158 LM_DBG("checking DB %.*s \n"
00159 , _tbc->dtp->name.len
00160 , _tbc->dtp->name.s);
00161
00162 if(_tbc->dtp->name.len == s.len &&
00163 !strncasecmp(_tbc->dtp->name.s, s.s, s.len ))
00164 {
00165 LM_DBG("DB %.*s \n", s.len, s.s);
00166 lock_get(&_tbc->dtp->sem);
00167 _db = _tbc->dtp->db;
00168 if(_db)
00169 rc = _db->close(_db, 0);
00170 if(rc != 0)
00171 LM_CRIT("error closing %s\n", _tbc->dtp->name.s);
00172 _tbc->dtp->db = NULL;
00173 lock_release(&_tbc->dtp->sem);
00174 return 0;
00175 }
00176 }
00177 _tbc = _tbc->next;
00178 }
00179 }
00180 LM_DBG("DB not found %.*s \n", s.len, s.s);
00181 return 1;
00182 }
00183
00184
00185
00186
00187
00188 int bdblib_reopen(char* _n)
00189 {
00190 str s;
00191 int rc, flags;
00192 tbl_cache_p _tbc;
00193 DB* _db = NULL;
00194 DB_ENV* _env = NULL;
00195 database_p _db_p = *_cachedb;
00196 rc = flags = 0;
00197 _tbc = NULL;
00198
00199 if (!_cachedb || !_n)
00200 return -1;
00201
00202 s.s = (char*)_n;
00203 s.len = strlen(_n);
00204
00205 if (_db_p)
00206 {
00207 _env = _db_p->dbenv;
00208 _tbc = _db_p->tables;
00209
00210 if(s.len ==_db_p->name.len &&
00211 !strncasecmp(s.s, _db_p->name.s,_db_p->name.len))
00212 {
00213
00214 LM_DBG("-- bdblib_reopen ENV %.*s \n", s.len, s.s);
00215 if(!_db_p->dbenv)
00216 { rc = bdblib_create_dbenv(&_env, _n);
00217 _db_p->dbenv = _env;
00218 }
00219
00220 if(rc!=0) return rc;
00221 _env = _db_p->dbenv;
00222 _tbc = _db_p->tables;
00223
00224 while(_tbc)
00225 {
00226 if(_tbc->dtp)
00227 {
00228 lock_get(&_tbc->dtp->sem);
00229 if(!_tbc->dtp->db)
00230 {
00231 if ((rc = db_create(&_db, _env, 0)) != 0)
00232 { _env->err(_env, rc, "db_create");
00233 LM_CRIT("error in db_create, db error: %s.\n",db_strerror(rc));
00234 bdblib_recover(_tbc->dtp, rc);
00235 }
00236 }
00237
00238 if ((rc = _db->open(_db, NULL, _n, NULL, DB_HASH, DB_CREATE, 0664)) != 0)
00239 { _db->dbenv->err(_env, rc, "DB->open: %s", _n);
00240 LM_CRIT("error in db_open: %s.\n",db_strerror(rc));
00241 bdblib_recover(_tbc->dtp, rc);
00242 }
00243
00244 _tbc->dtp->db = _db;
00245 lock_release(&_tbc->dtp->sem);
00246 }
00247 _tbc = _tbc->next;
00248 }
00249 _env->close(_env, 0);
00250 return rc;
00251 }
00252
00253
00254 while(_tbc)
00255 {
00256 if(_tbc->dtp)
00257 {
00258 LM_DBG("checking DB %.*s \n"
00259 , _tbc->dtp->name.len
00260 , _tbc->dtp->name.s);
00261
00262 if(_tbc->dtp->name.len == s.len &&
00263 !strncasecmp(_tbc->dtp->name.s, s.s, s.len ))
00264 {
00265 LM_DBG("DB %.*s \n", s.len, s.s);
00266 lock_get(&_tbc->dtp->sem);
00267 if(!_tbc->dtp->db)
00268 {
00269 if ((rc = db_create(&_db, _env, 0)) != 0)
00270 { _env->err(_env, rc, "db_create");
00271 LM_CRIT("error in db_create, db error: %s.\n",db_strerror(rc));
00272 bdblib_recover(_tbc->dtp, rc);
00273 }
00274 }
00275
00276 if ((rc = _db->open(_db, NULL, _n, NULL, DB_HASH, DB_CREATE, 0664)) != 0)
00277 { _db->dbenv->err(_env, rc, "DB->open: %s", _n);
00278 LM_CRIT("bdb open: %s.\n",db_strerror(rc));
00279 bdblib_recover(_tbc->dtp, rc);
00280 }
00281 _tbc->dtp->db = _db;
00282 lock_release(&_tbc->dtp->sem);
00283 return rc;
00284 }
00285 }
00286 _tbc = _tbc->next;
00287 }
00288
00289 }
00290 LM_DBG("DB not found %.*s \n", s.len, s.s);
00291 return 1;
00292 }
00293
00294
00295
00296
00297
00298 int bdblib_create_dbenv(DB_ENV **_dbenv, char* _home)
00299 {
00300 DB_ENV *env;
00301 char *progname;
00302 int rc, flags;
00303
00304 progname = "openser";
00305
00306
00307 if ((rc = db_env_create(&env, 0)) != 0)
00308 {
00309 LM_ERR("db_env_create failed! bdb error: %s.\n", db_strerror(rc));
00310 return (rc);
00311 }
00312
00313 env->set_errpfx(env, progname);
00314
00315
00316 if ((rc = env->set_cachesize(env, 0, _db_parms->cache_size, 0)) != 0)
00317 {
00318 LM_ERR("dbenv set_cachsize failed! bdb error: %s.\n", db_strerror(rc));
00319 env->err(env, rc, "set_cachesize");
00320 goto err;
00321 }
00322
00323
00324 flags = DB_CREATE |
00325 DB_INIT_CDB |
00326 DB_INIT_MPOOL |
00327 DB_THREAD;
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 if ((rc = env->open(env, _home, flags, 0)) != 0)
00342 {
00343 LM_ERR("dbenv is not initialized! bdb error: %s.\n",db_strerror(rc));
00344 env->err(env, rc, "environment open: %s", _home);
00345 goto err;
00346 }
00347
00348 *_dbenv = env;
00349 return (0);
00350
00351 err: (void)env->close(env, 0);
00352 return (rc);
00353 }
00354
00355
00356
00357
00358 database_p bdblib_get_db(str *_s)
00359 {
00360 int rc;
00361 database_p _db_p=NULL;
00362 char name[512];
00363
00364 if(!_s || !_s->s || _s->len<=0 || _s->len > 512)
00365 return NULL;
00366
00367 if( !_cachedb)
00368 {
00369 LM_ERR("db_berkeley cache is not initialized! Check if you loaded db_berkeley "
00370 "before any other module that uses it.\n");
00371 return NULL;
00372 }
00373
00374 _db_p = *_cachedb;
00375 if(_db_p)
00376 {
00377 LM_DBG("db already cached!\n");
00378 return _db_p;
00379 }
00380
00381 if(!bdb_is_database(_s))
00382 {
00383 LM_ERR("database [%.*s] does not exists!\n" ,_s->len , _s->s);
00384 return NULL;
00385 }
00386
00387 _db_p = (database_p)pkg_malloc(sizeof(database_t));
00388 if(!_db_p)
00389 {
00390 LM_ERR("no private memory for dbenv_t.\n");
00391 pkg_free(_db_p);
00392 return NULL;
00393 }
00394
00395 _db_p->name.s = (char*)pkg_malloc(_s->len*sizeof(char));
00396 memcpy(_db_p->name.s, _s->s, _s->len);
00397 _db_p->name.len = _s->len;
00398
00399 strncpy(name, _s->s, _s->len);
00400 name[_s->len] = 0;
00401
00402 if ((rc = bdblib_create_dbenv(&(_db_p->dbenv), name)) != 0)
00403 {
00404 LM_ERR("bdblib_create_dbenv failed");
00405 pkg_free(_db_p->name.s);
00406 pkg_free(_db_p);
00407 return NULL;
00408 }
00409
00410 _db_p->tables=NULL;
00411 *_cachedb = _db_p;
00412
00413 return _db_p;
00414 }
00415
00416
00417
00418
00419
00420
00421 tbl_cache_p bdblib_get_table(database_p _db, str *_s)
00422 {
00423 tbl_cache_p _tbc = NULL;
00424 table_p _tp = NULL;
00425
00426 if(!_db || !_s || !_s->s || _s->len<=0)
00427 return NULL;
00428
00429 if(!_db->dbenv)
00430 {
00431 return NULL;
00432 }
00433
00434 _tbc = _db->tables;
00435 while(_tbc)
00436 {
00437 if(_tbc->dtp)
00438 {
00439
00440 if(_tbc->dtp->name.len == _s->len
00441 && !strncasecmp(_tbc->dtp->name.s, _s->s, _s->len ))
00442 {
00443 return _tbc;
00444 }
00445 }
00446 _tbc = _tbc->next;
00447 }
00448
00449 _tbc = (tbl_cache_p)pkg_malloc(sizeof(tbl_cache_t));
00450 if(!_tbc)
00451 return NULL;
00452
00453 if(!lock_init(&_tbc->sem))
00454 {
00455 pkg_free(_tbc);
00456 return NULL;
00457 }
00458
00459 _tp = bdblib_create_table(_db, _s);
00460
00461 #ifdef BDB_EXTRA_DEBUG
00462 LM_DBG("table: %.*s\n", _s->len, _s->s);
00463 #endif
00464
00465 if(!_tp)
00466 {
00467 LM_ERR("failed to create table.\n");
00468 pkg_free(_tbc);
00469 return NULL;
00470 }
00471
00472 lock_get(&_tbc->sem);
00473 _tbc->dtp = _tp;
00474
00475 if(_db->tables)
00476 (_db->tables)->prev = _tbc;
00477
00478 _tbc->next = _db->tables;
00479 _db->tables = _tbc;
00480 lock_release(&_tbc->sem);
00481
00482 return _tbc;
00483 }
00484
00485
00486 void bdblib_log(int op, table_p _tp, char* _msg, int len)
00487 {
00488 if(!_tp || !len) return;
00489 if(! _db_parms->log_enable) return;
00490 if (_tp->logflags == JLOG_NONE) return;
00491
00492 if ((_tp->logflags & op) == op)
00493 { int op_len=7;
00494 char buf[MAX_ROW_SIZE + op_len];
00495 char *c;
00496 time_t now = time(NULL);
00497
00498 if( _db_parms->journal_roll_interval)
00499 {
00500 if((_tp->t) && (now - _tp->t) > _db_parms->journal_roll_interval)
00501 {
00502 if(bdblib_create_journal(_tp))
00503 {
00504 LM_ERR("Journaling has FAILED !\n");
00505 return;
00506 }
00507 }
00508 }
00509
00510 c = buf;
00511 switch (op)
00512 {
00513 case JLOG_INSERT:
00514 strncpy(c, "INSERT|", op_len);
00515 break;
00516 case JLOG_UPDATE:
00517 strncpy(c, "UPDATE|", op_len);
00518 break;
00519 case JLOG_DELETE:
00520 strncpy(c, "DELETE|", op_len);
00521 break;
00522 }
00523
00524 c += op_len;
00525 strncpy(c, _msg, len);
00526 c +=len;
00527 *c = '\n';
00528 c++;
00529 *c = '\0';
00530
00531 if ((_tp->logflags & JLOG_STDOUT) == JLOG_STDOUT)
00532 puts(buf);
00533
00534 if ((_tp->logflags & JLOG_SYSLOG) == JLOG_SYSLOG)
00535 syslog(LOG_LOCAL6, buf);
00536
00537 if(_tp->fp)
00538 {
00539 if(!fputs(buf, _tp->fp) )
00540 fflush(_tp->fp);
00541 }
00542 }
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 table_p bdblib_create_table(database_p _db, str *_s)
00563 {
00564
00565 int rc,i,flags;
00566 DB *bdb = NULL;
00567 table_p tp = NULL;
00568 char tblname[MAX_TABLENAME_SIZE];
00569
00570 if(!_db || !_db->dbenv)
00571 {
00572 LM_ERR("no database_p or dbenv.\n");
00573 return NULL;
00574 }
00575
00576 tp = (table_p)pkg_malloc(sizeof(table_t));
00577 if(!tp)
00578 {
00579 LM_ERR("no private memory for table_t.\n");
00580 return NULL;
00581 }
00582
00583 if ((rc = db_create(&bdb, _db->dbenv, 0)) != 0)
00584 {
00585 _db->dbenv->err(_db->dbenv, rc, "database create");
00586 LM_ERR("error in db_create, bdb error: %s.\n",db_strerror(rc));
00587 pkg_free(tp);
00588 return NULL;
00589 }
00590
00591 memset(tblname, 0, MAX_TABLENAME_SIZE);
00592 strncpy(tblname, _s->s, _s->len);
00593
00594 #ifdef BDB_EXTRA_DEBUG
00595 LM_DBG("CREATE TABLE = %s\n", tblname);
00596 #endif
00597
00598 flags = DB_THREAD;
00599
00600 if ((rc = bdb->open(bdb, NULL, tblname, NULL, DB_HASH, flags, 0664)) != 0)
00601 {
00602 _db->dbenv->err(_db->dbenv, rc, "DB->open: %s", tblname);
00603 LM_ERR("bdb open failed: %s.\n",db_strerror(rc));
00604 pkg_free(tp);
00605 return NULL;
00606 }
00607
00608 if(!lock_init(&tp->sem))
00609 {
00610 goto error;
00611 }
00612
00613 tp->name.s = (char*)pkg_malloc(_s->len*sizeof(char));
00614 memcpy(tp->name.s, _s->s, _s->len);
00615 tp->name.len = _s->len;
00616 tp->db=bdb;
00617 tp->ncols=0;
00618 tp->nkeys=0;
00619 tp->ro=0;
00620 tp->ino=0;
00621 tp->logflags=0;
00622 tp->fp=0;
00623 tp->t=0;
00624
00625 for(i=0;i<MAX_NUM_COLS;i++)
00626 tp->colp[i] = NULL;
00627
00628
00629
00630
00631 rc = load_metadata_columns(tp);
00632 if(rc!=0)
00633 {
00634 LM_ERR("FAILED to load METADATA COLS in table: %s.\n", tblname);
00635 goto error;
00636 }
00637
00638
00639 rc = load_metadata_defaults(tp);
00640 if(rc!=0)
00641 {
00642 LM_ERR("FAILED to load METADATA DEFAULTS in table: %s.\n", tblname);
00643 goto error;
00644 }
00645
00646 rc = load_metadata_keys(tp);
00647 if(rc!=0)
00648 {
00649 LM_ERR("FAILED to load METADATA KEYS in table: %s.\n", tblname);
00650
00651 goto error;
00652 }
00653
00654
00655 rc = load_metadata_readonly(tp);
00656 if(rc!=0)
00657 {
00658 LM_INFO("No METADATA_READONLY in table: %s.\n", tblname);
00659
00660 }
00661
00662 if(tp->ro)
00663 {
00664
00665 #ifdef BDB_EXTRA_DEBUG
00666 LM_DBG("TABLE %.*s is changing to READONLY mode\n"
00667 , tp->name.len, tp->name.s);
00668 #endif
00669
00670 if ((rc = bdb->close(bdb,0)) != 0)
00671 {
00672 _db->dbenv->err(_db->dbenv, rc, "DB->close: %s", tblname);
00673 LM_ERR("bdb close: %s.\n",db_strerror(rc));
00674 goto error;
00675 }
00676
00677 bdb = NULL;
00678 if ((rc = db_create(&bdb, _db->dbenv, 0)) != 0)
00679 {
00680 _db->dbenv->err(_db->dbenv, rc, "database create");
00681 LM_ERR("error in db_create.\n");
00682 goto error;
00683 }
00684
00685 flags = DB_THREAD | DB_RDONLY;
00686 if ((rc = bdb->open(bdb, NULL, tblname, NULL, DB_HASH, flags, 0664)) != 0)
00687 {
00688 _db->dbenv->err(_db->dbenv, rc, "DB->open: %s", tblname);
00689 LM_ERR("bdb open: %s.\n",db_strerror(rc));
00690 goto error;
00691 }
00692 tp->db=bdb;
00693 }
00694
00695
00696
00697
00698 rc = load_metadata_logflags(tp);
00699 if(rc!=0)
00700 LM_INFO("No METADATA_LOGFLAGS in table: %s.\n", tblname);
00701
00702 if ((tp->logflags & JLOG_FILE) == JLOG_FILE)
00703 bdblib_create_journal(tp);
00704
00705 return tp;
00706
00707 error:
00708 if(tp)
00709 {
00710 pkg_free(tp->name.s);
00711 pkg_free(tp);
00712 }
00713 return NULL;
00714 }
00715
00716 int bdblib_create_journal(table_p _tp)
00717 {
00718 char *s;
00719 char fn[1024];
00720 char d[64];
00721 FILE *fp = NULL;
00722 struct tm *t;
00723 int bl;
00724 database_p _db_p = *_cachedb;
00725 time_t tim = time(NULL);
00726
00727 if(! _db_p || ! _tp) return -1;
00728 if(! _db_parms->log_enable) return 0;
00729
00730 s=fn;
00731 strncpy(s, _db_p->name.s, _db_p->name.len);
00732 s+=_db_p->name.len;
00733
00734 *s = '/';
00735 s++;
00736
00737 strncpy(s, _tp->name.s, _tp->name.len);
00738 s+=_tp->name.len;
00739
00740 t = localtime( &tim );
00741 bl=strftime(d,128,"-%Y%m%d%H%M%S.jnl",t);
00742 strncpy(s, d, bl);
00743 s+= bl;
00744 *s = 0;
00745
00746 if(_tp->fp)
00747 {
00748 if( fclose(_tp->fp) )
00749 { LM_ERR("Failed to Close Log in table: %.*s .\n", _tp->name.len,
00750 _tp->name.s);
00751 return -1;
00752 }
00753 }
00754
00755 if( (fp = fopen(fn, "w")) != NULL )
00756 {
00757 _tp->fp = fp;
00758 }
00759 else
00760 {
00761 LM_ERR("Failed to Open Log in table: %.*s .\n",_tp->name.len, _tp->name.s);
00762 return -1;
00763 }
00764
00765 _tp->t = tim;
00766 return 0;
00767
00768 }
00769
00770 int load_metadata_columns(table_p _tp)
00771 {
00772 int ret,n,len;
00773 char dbuf[MAX_ROW_SIZE];
00774 char *s = NULL;
00775 char cn[64], ct[16];
00776 DB *db = NULL;
00777 DBT key, data;
00778 column_p col;
00779 ret = n = len = 0;
00780
00781 if(!_tp || !_tp->db)
00782 return -1;
00783
00784 if(_tp->ncols!=0)
00785 return 0;
00786
00787 db = _tp->db;
00788 memset(&key, 0, sizeof(DBT));
00789 memset(&data, 0, sizeof(DBT));
00790 memset(dbuf, 0, MAX_ROW_SIZE);
00791
00792 key.data = METADATA_COLUMNS;
00793 key.size = strlen(METADATA_COLUMNS);
00794
00795
00796 data.data = dbuf;
00797 data.ulen = MAX_ROW_SIZE;
00798 data.flags = DB_DBT_USERMEM;
00799
00800 if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
00801 {
00802 db->err(db, ret, "load_metadata_columns DB->get failed");
00803 LM_ERR("FAILED to find METADATA_COLUMNS in DB \n");
00804 return -1;
00805 }
00806
00807
00808 s = strtok(dbuf, " ");
00809 while(s!=NULL && n<MAX_NUM_COLS)
00810 {
00811
00812 if (sscanf(s,"%20[^(](%10[^)])[^\n]", cn, ct) < 0) {
00813 LM_ERR("could not parse meta data\n");
00814 return -1;
00815 }
00816
00817
00818 col = (column_p) pkg_malloc(sizeof(column_t));
00819 if(!col)
00820 { LM_ERR("out of private memory \n");
00821 return -1;
00822 }
00823
00824
00825 len = strlen( cn );
00826 col->name.s = (char*)pkg_malloc(len * sizeof(char));
00827 memcpy(col->name.s, cn, len );
00828 col->name.len = len;
00829
00830
00831 if(strncmp(ct, "str", 3)==0)
00832 { col->type = DB_STRING;
00833 }
00834 else if(strncmp(ct, "int", 3)==0)
00835 { col->type = DB_INT;
00836 }
00837 else if(strncmp(ct, "double", 6)==0)
00838 { col->type = DB_DOUBLE;
00839 }
00840 else if(strncmp(ct, "datetime", 8)==0)
00841 { col->type = DB_DATETIME;
00842 }
00843 else
00844 { col->type = DB_STRING;
00845 }
00846
00847 col->flag = 0;
00848 _tp->colp[n] = col;
00849 n++;
00850 _tp->ncols++;
00851 s=strtok(NULL, " ");
00852 }
00853
00854 return 0;
00855 }
00856
00857 int load_metadata_keys(table_p _tp)
00858 {
00859 int ret,n,ci;
00860 char dbuf[MAX_ROW_SIZE];
00861 char *s = NULL;
00862 DB *db = NULL;
00863 DBT key, data;
00864 ret = n = ci = 0;
00865
00866 if(!_tp || !_tp->db)
00867 return -1;
00868
00869 db = _tp->db;
00870 memset(&key, 0, sizeof(DBT));
00871 memset(&data, 0, sizeof(DBT));
00872 memset(dbuf, 0, MAX_ROW_SIZE);
00873 key.data = METADATA_KEY;
00874 key.size = strlen(METADATA_KEY);
00875 data.data = dbuf;
00876 data.ulen = MAX_ROW_SIZE;
00877 data.flags = DB_DBT_USERMEM;
00878
00879 if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
00880 {
00881 db->err(db, ret, "load_metadata_keys DB->get failed");
00882 LM_ERR("FAILED to find METADATA in table \n");
00883 return ret;
00884 }
00885
00886 s = strtok(dbuf, " ");
00887 while(s!=NULL && n< _tp->ncols)
00888 { ret = sscanf(s,"%i", &ci);
00889 if(ret != 1) return -1;
00890 if( _tp->colp[ci] )
00891 { _tp->colp[ci]->flag = 1;
00892 _tp->nkeys++;
00893 }
00894 n++;
00895 s=strtok(NULL, " ");
00896 }
00897
00898 return 0;
00899 }
00900
00901
00902 int load_metadata_readonly(table_p _tp)
00903 {
00904 int i, ret;
00905 char dbuf[MAX_ROW_SIZE];
00906
00907 DB *db = NULL;
00908 DBT key, data;
00909 i = 0;
00910
00911 if(!_tp || !_tp->db)
00912 return -1;
00913
00914 db = _tp->db;
00915 memset(&key, 0, sizeof(DBT));
00916 memset(&data, 0, sizeof(DBT));
00917 memset(dbuf, 0, MAX_ROW_SIZE);
00918 key.data = METADATA_READONLY;
00919 key.size = strlen(METADATA_READONLY);
00920 data.data = dbuf;
00921 data.ulen = MAX_ROW_SIZE;
00922 data.flags = DB_DBT_USERMEM;
00923
00924 if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
00925 { return ret;
00926 }
00927
00928 if( 1 == sscanf(dbuf,"%i", &i) )
00929 _tp->ro=(i>0)?1:0;
00930
00931 return 0;
00932 }
00933
00934 int load_metadata_logflags(table_p _tp)
00935 {
00936 int i, ret;
00937 char dbuf[MAX_ROW_SIZE];
00938
00939 DB *db = NULL;
00940 DBT key, data;
00941 i = 0;
00942
00943 if(!_tp || !_tp->db)
00944 return -1;
00945
00946 db = _tp->db;
00947 memset(&key, 0, sizeof(DBT));
00948 memset(&data, 0, sizeof(DBT));
00949 memset(dbuf, 0, MAX_ROW_SIZE);
00950 key.data = METADATA_LOGFLAGS;
00951 key.size = strlen(METADATA_LOGFLAGS);
00952 data.data = dbuf;
00953 data.ulen = MAX_ROW_SIZE;
00954 data.flags = DB_DBT_USERMEM;
00955
00956 if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
00957 { return ret;
00958 }
00959
00960 if( 1 == sscanf(dbuf,"%i", &i) )
00961 _tp->logflags=i;
00962
00963 return 0;
00964 }
00965
00966 int load_metadata_defaults(table_p _tp)
00967 {
00968 int ret,n,len;
00969 char dbuf[MAX_ROW_SIZE];
00970 char *s = NULL;
00971 char cv[64];
00972 DB *db = NULL;
00973 DBT key, data;
00974 column_p col;
00975 ret = n = len = 0;
00976
00977 if(!_tp || !_tp->db)
00978 return -1;
00979
00980 db = _tp->db;
00981 memset(&key, 0, sizeof(DBT));
00982 memset(&data, 0, sizeof(DBT));
00983 memset(dbuf, 0, MAX_ROW_SIZE);
00984
00985 key.data = METADATA_DEFAULTS;
00986 key.size = strlen(METADATA_DEFAULTS);
00987
00988
00989 data.data = dbuf;
00990 data.ulen = MAX_ROW_SIZE;
00991 data.flags = DB_DBT_USERMEM;
00992
00993 if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
00994 {
00995 #ifdef BDB_EXTRA_DEBUG
00996 LM_DBG("NO DEFAULTS ; SETTING ALL columns to NULL! \n" );
00997 #endif
00998
00999
01000 for(n=0; n<_tp->ncols; n++)
01001 {
01002 col = _tp->colp[n];
01003 if( col )
01004 {
01005 len = strlen("NULL");
01006 col->dv.s = (char*)pkg_malloc(len * sizeof(char));
01007 memcpy(col->dv.s, "NULL", len);
01008 col->dv.len = len;
01009 }
01010 }
01011 return 0;
01012 }
01013
01014
01015 s = strtok(dbuf, DELIM);
01016 while(s!=NULL && n< _tp->ncols)
01017 { ret = sscanf(s,"%s", cv);
01018 if(ret != 1) return -1;
01019 col = _tp->colp[n];
01020 if( col )
01021 {
01022 len = strlen(s);
01023 col->dv.s = (char*)pkg_malloc(len * sizeof(char));
01024 memcpy(col->dv.s, cv, len);
01025 col->dv.len = len;
01026 #ifdef BDB_EXTRA_DEBUG
01027 LM_DBG("COLUMN DEFAULT is %.*s for column[%.*s] \n"
01028 , col->dv.len , ZSW(col->dv.s)
01029 , col->name.len , ZSW(col->name.s)
01030 );
01031 #endif
01032
01033 }
01034 n++;
01035 s=strtok(NULL, DELIM);
01036 }
01037
01038 return 0;
01039 }
01040
01041
01042
01043
01044
01045
01046
01047 int bdblib_valtochar(table_p _tp, int* _lres, char* _k, int* _klen, db_val_t* _v, int _n, int _ko)
01048 {
01049 char *p;
01050 char sk[MAX_ROW_SIZE];
01051 char* delim = DELIM;
01052 char* cNULL = "NULL";
01053 int len, total, sum;
01054 int i, j, k;
01055 p = _k;
01056 len = sum = total = 0;
01057 i = j = k = 0;
01058
01059 if(!_tp) return -1;
01060 if(!_v || (_n<1) ) return -1;
01061 if(!_k || !_klen ) return -1;
01062 if( *_klen < 1) return -1;
01063
01064 memset(sk, 0, MAX_ROW_SIZE);
01065 total = *_klen;
01066 *_klen = 0;
01067
01068 if(! _lres)
01069 {
01070 #ifdef BDB_EXTRA_DEBUG
01071 LM_DBG("schema has NOT specified any keys! \n");
01072 #endif
01073
01074
01075
01076
01077 for(i=0;i<_n;i++)
01078 { len = total - sum;
01079 if ( bdb_val2str(&_v[i], sk, &len) != 0 )
01080 { LM_ERR("error building composite key \n");
01081 return -2;
01082 }
01083
01084 sum += len;
01085 if(sum > total)
01086 { LM_ERR("Destination buffer too short for subval %s\n",sk);
01087 return -2;
01088 }
01089
01090
01091 strncpy(p, sk, len);
01092 p += len;
01093 *_klen = sum;
01094
01095 sum += DELIM_LEN;
01096 if(sum > total)
01097 { LM_ERR("Destination buffer too short for delim \n");
01098 return -3;
01099 }
01100
01101
01102 strncpy(p, delim, DELIM_LEN);
01103 p += DELIM_LEN;
01104 *_klen = sum;;
01105 }
01106 return 0;
01107 }
01108
01109
01110
01111
01112
01113
01114
01115 for(i=0; i<_tp->ncols; i++)
01116 {
01117 if( _ko)
01118 {
01119 if( ! _tp->colp[i]->flag)
01120 continue;
01121 }
01122
01123 for(j=0; j<_n; j++)
01124 {
01125
01126
01127
01128
01129
01130
01131 k = (_lres) ? _lres[j] : j;
01132
01133
01134
01135
01136 if(i == k)
01137 {
01138
01139
01140
01141
01142
01143
01144
01145 #ifdef BDB_EXTRA_DEBUG
01146 LM_DBG("KEY PROVIDED[%i]: %.*s.%.*s \n", i
01147 , _tp->name.len , ZSW(_tp->name.s)
01148 , _tp->colp[i]->name.len, ZSW(_tp->colp[i]->name.s)
01149 );
01150 #endif
01151
01152 len = total - sum;
01153 if ( bdb_val2str(&_v[j], sk, &len) != 0)
01154 { LM_ERR("Destination buffer too short for subval %s\n",sk);
01155 return -4;
01156 }
01157
01158 sum += len;
01159 if(sum > total)
01160 { LM_ERR("Destination buffer too short for subval %s\n",sk);
01161 return -5;
01162 }
01163
01164 strncpy(p, sk, len);
01165 p += len;
01166 *_klen = sum;
01167
01168 sum += DELIM_LEN;
01169 if(sum > total)
01170 { LM_ERR("Destination buffer too short for delim \n");
01171 return -5;
01172 }
01173
01174
01175 strncpy(p, delim, DELIM_LEN);
01176 p += DELIM_LEN;
01177 *_klen = sum;
01178
01179
01180
01181
01182
01183
01184 goto next;
01185 }
01186
01187 }
01188
01189
01190
01191
01192
01193 #ifdef BDB_EXTRA_DEBUG
01194 LM_DBG("Missing KEY[%i]: %.*s.%.*s using default [%.*s] \n", i
01195 , _tp->name.len , ZSW(_tp->name.s)
01196 , _tp->colp[i]->name.len, ZSW(_tp->colp[i]->name.s)
01197 , _tp->colp[i]->dv.len , ZSW(_tp->colp[i]->dv.s)
01198 );
01199 #endif
01200 len = _tp->colp[i]->dv.len;
01201 sum += len;
01202 if(sum > total)
01203 { LM_ERR("Destination buffer too short for subval %s\n",cNULL);
01204 return -5;
01205 }
01206
01207 strncpy(p, _tp->colp[i]->dv.s, len);
01208 p += len;
01209 *_klen = sum;
01210
01211 sum += DELIM_LEN;
01212 if(sum > total)
01213 { LM_ERR("Destination buffer too short for delim \n");
01214 return -5;
01215 }
01216
01217 strncpy(p, delim, DELIM_LEN);
01218 p += DELIM_LEN;
01219 *_klen = sum;
01220 next:
01221 continue;
01222 }
01223
01224
01225
01226 return 0;
01227 }
01228
01229
01230
01231
01232
01233 int db_free(database_p _dbp)
01234 {
01235 tbl_cache_p _tbc = NULL, _tbc0=NULL;
01236 if(!_dbp)
01237 return -1;
01238
01239 _tbc = _dbp->tables;
01240
01241 while(_tbc)
01242 {
01243 _tbc0 = _tbc->next;
01244 tbl_cache_free(_tbc);
01245 _tbc = _tbc0;
01246 }
01247
01248 if(_dbp->dbenv)
01249 _dbp->dbenv->close(_dbp->dbenv, 0);
01250
01251 if(_dbp->name.s)
01252 pkg_free(_dbp->name.s);
01253
01254 pkg_free(_dbp);
01255
01256 return 0;
01257 }
01258
01259
01260
01261
01262
01263 int tbl_cache_free(tbl_cache_p _tbc)
01264 {
01265 if(!_tbc)
01266 return -1;
01267
01268 lock_get(&_tbc->sem);
01269
01270 if(_tbc->dtp)
01271 tbl_free(_tbc->dtp);
01272
01273 lock_destroy(&_tbc->sem);
01274 pkg_free(_tbc);
01275
01276 return 0;
01277 }
01278
01279
01280
01281
01282
01283 int tbl_free(table_p _tp)
01284 { int i;
01285 if(!_tp)
01286 return -1;
01287
01288 if(_tp->db)
01289 _tp->db->close(_tp->db, 0);
01290
01291 if(_tp->fp)
01292 fclose(_tp->fp);
01293
01294 if(_tp->name.s)
01295 pkg_free(_tp->name.s);
01296
01297 for(i=0;i<_tp->ncols;i++)
01298 { if(_tp->colp[i])
01299 { pkg_free(_tp->colp[i]->name.s);
01300 pkg_free(_tp->colp[i]->dv.s);
01301 pkg_free(_tp->colp[i]);
01302 }
01303 }
01304
01305 pkg_free(_tp);
01306 return 0;
01307 }
01308
01309 int bdblib_recover(table_p _tp, int _rc)
01310 {
01311 switch(_rc)
01312 {
01313 case DB_LOCK_DEADLOCK:
01314 LM_ERR("DB_LOCK_DEADLOCK detected !!\n");
01315
01316 case DB_RUNRECOVERY:
01317 LM_ERR("DB_RUNRECOVERY detected !! \n");
01318 bdblib_destroy();
01319 exit(1);
01320 break;
01321 }
01322
01323 return 0;
01324 }