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 <unistd.h>
00032 #include <sys/stat.h>
00033
00034
00035 #include "../../str.h"
00036 #include "../../ut.h"
00037 #include "../../mem/mem.h"
00038
00039 #include "../../sr_module.h"
00040 #include "../../db/db_res.h"
00041 #include "../../db/db.h"
00042 #include "db_berkeley.h"
00043 #include "bdb_lib.h"
00044 #include "bdb_res.h"
00045 #include "bdb_mi.h"
00046
00047 #ifndef CFG_DIR
00048 #define CFG_DIR "/tmp"
00049 #endif
00050
00051 #define BDB_ID "berkeley://"
00052 #define BDB_ID_LEN (sizeof(BDB_ID)-1)
00053 #define BDB_PATH_LEN 256
00054
00055 #define BDB_KEY 1
00056 #define BDB_VALUE 0
00057
00058 MODULE_VERSION
00059
00060 int auto_reload = 0;
00061 int log_enable = 0;
00062 int journal_roll_interval = 0;
00063
00064 static int mod_init(void);
00065 static void destroy(void);
00066
00067 int bdb_bind_api(db_func_t *dbb);
00068
00069
00070
00071
00072 static cmd_export_t cmds[] = {
00073 {"db_bind_api", (cmd_function)bdb_bind_api, 0, 0, 0, 0},
00074 {0, 0, 0, 0, 0, 0}
00075 };
00076
00077
00078
00079
00080
00081 static param_export_t params[] = {
00082 {"auto_reload", INT_PARAM, &auto_reload },
00083 {"log_enable", INT_PARAM, &log_enable },
00084 {"journal_roll_interval", INT_PARAM, &journal_roll_interval },
00085 {0, 0, 0}
00086 };
00087
00088
00089
00090
00091 static mi_export_t mi_cmds[] = {
00092 { MI_BDB_RELOAD, mi_bdb_reload, 0, 0, 0 },
00093 { 0, 0, 0, 0, 0}
00094 };
00095
00096 struct module_exports exports = {
00097 "db_berkeley",
00098 DEFAULT_DLFLAGS,
00099 cmds,
00100 params,
00101 0,
00102 mi_cmds,
00103 0,
00104 0,
00105 mod_init,
00106 0,
00107 destroy,
00108 0
00109 };
00110
00111
00112 static int mod_init(void)
00113 {
00114 db_parms_t p;
00115
00116 p.auto_reload = auto_reload;
00117 p.log_enable = log_enable;
00118 p.cache_size = (4 * 1024 * 1024);
00119 p.journal_roll_interval = journal_roll_interval;
00120
00121 if(bdblib_init(&p))
00122 return -1;
00123
00124 return 0;
00125 }
00126
00127 static void destroy(void)
00128 {
00129 bdblib_destroy();
00130 }
00131
00132 int bdb_bind_api(db_func_t *dbb)
00133 {
00134 if(dbb==NULL)
00135 return -1;
00136
00137 memset(dbb, 0, sizeof(db_func_t));
00138
00139 dbb->use_table = bdb_use_table;
00140 dbb->init = bdb_init;
00141 dbb->close = bdb_close;
00142 dbb->query = (db_query_f)bdb_query;
00143 dbb->free_result = bdb_free_query;
00144 dbb->insert = (db_insert_f)bdb_insert;
00145 dbb->delete = (db_delete_f)bdb_delete;
00146 dbb->update = (db_update_f)bdb_update;
00147
00148 return 0;
00149 }
00150
00151 int bdb_use_table(db_con_t* _h, const str* _t)
00152 {
00153 return db_use_table(_h, _t);
00154 }
00155
00156
00157
00158
00159 db_con_t* bdb_init(const str* _sqlurl)
00160 {
00161 db_con_t* _res;
00162 str _s;
00163 char bdb_path[BDB_PATH_LEN];
00164
00165 if (!_sqlurl || !_sqlurl->s) {
00166 LM_ERR("invalid parameter value\n");
00167 return 0;
00168 }
00169
00170 _s.s = _sqlurl->s;
00171 _s.len = _sqlurl->len;
00172 if(_s.len <= BDB_ID_LEN || strncmp(_s.s, BDB_ID, BDB_ID_LEN)!=0)
00173 {
00174 LM_ERR("invalid database URL - should be:"
00175 " <%s[/]path/to/directory>\n", BDB_ID);
00176 return NULL;
00177 }
00178 _s.s += BDB_ID_LEN;
00179 _s.len -= BDB_ID_LEN;
00180
00181 if(_s.s[0]!='/')
00182 {
00183 if(sizeof(CFG_DIR)+_s.len+2 > BDB_PATH_LEN)
00184 {
00185 LM_ERR("path to database is too long\n");
00186 return NULL;
00187 }
00188 strcpy(bdb_path, CFG_DIR);
00189 bdb_path[sizeof(CFG_DIR)] = '/';
00190 strncpy(&bdb_path[sizeof(CFG_DIR)+1], _s.s, _s.len);
00191 _s.len += sizeof(CFG_DIR);
00192 _s.s = bdb_path;
00193 }
00194
00195 _res = pkg_malloc(sizeof(db_con_t)+sizeof(bdb_con_t));
00196 if (!_res)
00197 {
00198 LM_ERR("No private memory left\n");
00199 return NULL;
00200 }
00201 memset(_res, 0, sizeof(db_con_t) + sizeof(bdb_con_t));
00202 _res->tail = (unsigned long)((char*)_res+sizeof(db_con_t));
00203
00204 LM_INFO("using database at: %.*s", _s.len, _s.s);
00205 BDB_CON_CONNECTION(_res) = bdblib_get_db(&_s);
00206 if (!BDB_CON_CONNECTION(_res))
00207 {
00208 LM_ERR("cannot get the link to database\n");
00209 return NULL;
00210 }
00211
00212 return _res;
00213 }
00214
00215
00216
00217
00218
00219 void bdb_close(db_con_t* _h)
00220 {
00221 if(BDB_CON_RESULT(_h))
00222 db_free_result(BDB_CON_RESULT(_h));
00223 pkg_free(_h);
00224 }
00225
00226
00227
00228
00229 int bdb_reload(char* _n)
00230 {
00231 int rc = 0;
00232 #ifdef BDB_EXTRA_DEBUG
00233 LM_DBG("[bdb_reload] Initiate RELOAD in %s\n", _n);
00234 #endif
00235
00236 if ((rc = bdblib_close(_n)) != 0)
00237 { LM_ERR("[bdb_reload] Error while closing db_berkeley DB.\n");
00238 return rc;
00239 }
00240
00241 if ((rc = bdblib_reopen(_n)) != 0)
00242 { LM_ERR("[bdb_reload] Error while reopening db_berkeley DB.\n");
00243 return rc;
00244 }
00245
00246 #ifdef BDB_EXTRA_DEBUG
00247 LM_DBG("[bdb_reload] RELOAD successful in %s\n", _n);
00248 #endif
00249
00250 return rc;
00251 }
00252
00253
00254
00255
00256 void bdb_check_reload(db_con_t* _con)
00257 {
00258 str s;
00259 char* p;
00260 int rc, len;
00261 struct stat st;
00262 database_p db;
00263 char n[MAX_ROW_SIZE];
00264 char t[MAX_TABLENAME_SIZE];
00265 table_p tp = NULL;
00266 tbl_cache_p tbc = NULL;
00267
00268 p=n;
00269 rc = len = 0;
00270
00271
00272 db = BDB_CON_CONNECTION(_con);
00273 if(!db->dbenv) return;
00274 s.s = db->name.s;
00275 s.len = db->name.len;
00276 len+=s.len;
00277
00278 if(len > MAX_ROW_SIZE)
00279 { LM_ERR("dbenv name too long \n");
00280 return;
00281 }
00282
00283 strncpy(p, s.s, s.len);
00284 p+=s.len;
00285
00286 len++;
00287 if(len > MAX_ROW_SIZE)
00288 { LM_ERR("dbenv name too long \n");
00289 return;
00290 }
00291
00292
00293 *p = '/';
00294 p++;
00295
00296
00297 s.s = CON_TABLE(_con)->s;
00298 s.len = CON_TABLE(_con)->len;
00299 len+=s.len;
00300
00301 if((len>MAX_ROW_SIZE) || (s.len > MAX_TABLENAME_SIZE) )
00302 { LM_ERR("table name too long \n");
00303 return;
00304 }
00305
00306 strncpy(t, s.s, s.len);
00307 t[s.len] = 0;
00308
00309 strncpy(p, s.s, s.len);
00310 p+=s.len;
00311 *p=0;
00312
00313 if( (tbc = bdblib_get_table(db, &s)) == NULL)
00314 return;
00315
00316 if( (tp = tbc->dtp) == NULL)
00317 return;
00318
00319 LM_DBG("stat file [%.*s]\n", len, n);
00320 rc = stat(n, &st);
00321 if(!rc)
00322 { if((tp->ino!=0) && (st.st_ino != tp->ino))
00323 bdb_reload(t);
00324
00325 tp->ino = st.st_ino;
00326 }
00327
00328 }
00329
00330
00331
00332
00333
00334 int bdb_free_query(db_con_t* _h, db_res_t* _r)
00335 {
00336 if(_r)
00337 db_free_result(_r);
00338 if(_h)
00339 BDB_CON_RESULT(_h) = NULL;
00340 return 0;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 int bdb_query(db_con_t* _con, db_key_t* _k, db_op_t* _op, db_val_t* _v,
00356 db_key_t* _c, int _n, int _nc, db_key_t _o, db_res_t** _r)
00357 {
00358 tbl_cache_p _tbc = NULL;
00359 table_p _tp = NULL;
00360 char kbuf[MAX_ROW_SIZE];
00361 char dbuf[MAX_ROW_SIZE];
00362 u_int32_t i, len, ret;
00363 int klen=MAX_ROW_SIZE;
00364 int *lkey=NULL, *lres=NULL;
00365 DBT key, data;
00366 DB *db;
00367 DBC *dbcp;
00368
00369 if ((!_con) || (!_r) || !CON_TABLE(_con))
00370 {
00371 #ifdef BDB_EXTRA_DEBUG
00372 LM_ERR("Invalid parameter value\n");
00373 #endif
00374 return -1;
00375 }
00376 *_r = NULL;
00377
00378
00379 if(auto_reload)
00380 bdb_check_reload(_con);
00381
00382 _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), (str*)CON_TABLE(_con));
00383 if(!_tbc)
00384 { LM_WARN("table does not exist!\n");
00385 return -1;
00386 }
00387
00388 _tp = _tbc->dtp;
00389 if(!_tp)
00390 { LM_WARN("table not loaded!\n");
00391 return -1;
00392 }
00393
00394 #ifdef BDB_EXTRA_DEBUG
00395 LM_DBG("QUERY in %.*s\n", _tp->name.len, _tp->name.s);
00396
00397 if (_o) LM_DBG("DONT-CARE : _o: order by the specified column \n");
00398 if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
00399 #endif
00400
00401 db = _tp->db;
00402 if(!db) return -1;
00403
00404 memset(&key, 0, sizeof(DBT));
00405 memset(kbuf, 0, MAX_ROW_SIZE);
00406 memset(&data, 0, sizeof(DBT));
00407 memset(dbuf, 0, MAX_ROW_SIZE);
00408
00409 data.data = dbuf;
00410 data.ulen = MAX_ROW_SIZE;
00411 data.flags = DB_DBT_USERMEM;
00412
00413
00414
00415
00416 if (_c)
00417 { lres = bdb_get_colmap(_tbc->dtp, _c, _nc);
00418 if(!lres)
00419 { ret = -1;
00420 goto error;
00421 }
00422 }
00423
00424 if(_k)
00425 { lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
00426 if(!lkey)
00427 { ret = -1;
00428 goto error;
00429 }
00430 }
00431 else
00432 {
00433 DB_HASH_STAT st;
00434 memset(&st, 0, sizeof(DB_HASH_STAT));
00435 i =0 ;
00436
00437 #ifdef BDB_EXTRA_DEBUG
00438 LM_DBG("SELECT * FROM %.*s\n", _tp->name.len, _tp->name.s);
00439 #endif
00440
00441
00442 if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
00443 { LM_ERR("Error creating cursor\n");
00444 goto error;
00445 }
00446
00447
00448 while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
00449 { if(!strncasecmp((char*)key.data,"METADATA",8))
00450 continue;
00451 i++;
00452 }
00453
00454 dbcp->c_close(dbcp);
00455 ret=0;
00456
00457 #ifdef BDB_EXTRA_DEBUG
00458 LM_DBG("%i = SELECT COUNT(*) FROM %.*s\n", i, _tp->name.len, _tp->name.s);
00459 #endif
00460
00461 *_r = db_new_result();
00462 if (!*_r)
00463 { LM_ERR("no memory left for result \n");
00464 ret = -2;
00465 goto error;
00466 }
00467
00468 if(i == 0)
00469 {
00470
00471 RES_ROW_N(*_r) = 0;
00472 BDB_CON_RESULT(_con) = *_r;
00473 return 0;
00474 }
00475
00476
00477 RES_ROW_N(*_r) = i;
00478 len = sizeof(db_row_t) * i;
00479 RES_ROWS(*_r) = (db_row_t*)pkg_malloc( len );
00480 memset(RES_ROWS(*_r), 0, len);
00481
00482
00483 if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
00484 { LM_ERR("Error while getting column names\n");
00485 goto error;
00486 }
00487
00488
00489 if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
00490 { LM_ERR("Error creating cursor\n");
00491 goto error;
00492 }
00493
00494
00495 i =0 ;
00496 while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
00497 {
00498 if(!strncasecmp((char*)key.data,"METADATA",8))
00499 continue;
00500
00501 #ifdef BDB_EXTRA_DEBUG
00502 LM_DBG("KEY: [%.*s]\nDATA: [%.*s]\n"
00503 , (int) key.size
00504 , (char *)key.data
00505 , (int) data.size
00506 , (char *)data.data);
00507 #endif
00508
00509
00510 if ((ret=bdb_append_row( *_r, dbuf, lres, i)) < 0)
00511 { LM_ERR("Error while converting row\n");
00512 goto error;
00513 }
00514 i++;
00515 }
00516
00517 dbcp->c_close(dbcp);
00518 BDB_CON_RESULT(_con) = *_r;
00519 return 0;
00520 }
00521
00522 if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
00523 { LM_ERR("error in query key \n");
00524 goto error;
00525 }
00526
00527 key.data = kbuf;
00528 key.ulen = MAX_ROW_SIZE;
00529 key.flags = DB_DBT_USERMEM;
00530 key.size = klen;
00531
00532 data.data = dbuf;
00533 data.ulen = MAX_ROW_SIZE;
00534 data.flags = DB_DBT_USERMEM;
00535
00536
00537 *_r = db_new_result();
00538 if (!*_r)
00539 { LM_ERR("no memory left for result \n");
00540 ret = -2;
00541 goto error;
00542 }
00543 RES_ROW_N(*_r) = 0;
00544 BDB_CON_RESULT(_con) = *_r;
00545
00546 #ifdef BDB_EXTRA_DEBUG
00547 LM_DBG("SELECT KEY: [%.*s]\n"
00548 , (int) key.size
00549 , (char *)key.data );
00550 #endif
00551
00552
00553 if ((ret = db->get(db, NULL, &key, &data, 0)) == 0)
00554 {
00555 #ifdef BDB_EXTRA_DEBUG
00556 LM_DBG("RESULT\nKEY: [%.*s]\nDATA: [%.*s]\n"
00557 , (int) key.size
00558 , (char *)key.data
00559 , (int) data.size
00560 , (char *)data.data);
00561 #endif
00562
00563
00564 if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
00565 { LM_ERR("Error while getting column names\n");
00566 goto error;
00567 }
00568
00569 if ((ret=bdb_convert_row( *_r, dbuf, lres)) < 0)
00570 { LM_ERR("Error while converting row\n");
00571 goto error;
00572 }
00573
00574 }
00575 else
00576 {
00577
00578 switch(ret)
00579 {
00580
00581 case DB_NOTFOUND:
00582
00583 #ifdef BDB_EXTRA_DEBUG
00584 LM_DBG("NO RESULT for QUERY \n");
00585 #endif
00586
00587 ret=0;
00588 break;
00589
00590 case DB_LOCK_DEADLOCK:
00591
00592 case DB_SECONDARY_BAD:
00593
00594 case DB_RUNRECOVERY:
00595 default:
00596 LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
00597 bdblib_recover(_tp,ret);
00598 goto error;
00599 }
00600 }
00601
00602 if(lkey)
00603 pkg_free(lkey);
00604 if(lres)
00605 pkg_free(lres);
00606
00607 return ret;
00608
00609 error:
00610 if(lkey)
00611 pkg_free(lkey);
00612 if(lres)
00613 pkg_free(lres);
00614 if(*_r)
00615 db_free_result(*_r);
00616 *_r = NULL;
00617
00618 return ret;
00619 }
00620
00621
00622
00623
00624
00625
00626 int bdb_raw_query(db_con_t* _h, char* _s, db_res_t** _r)
00627 {
00628 LM_CRIT("DB RAW QUERY not implemented!\n");
00629 return -1;
00630 }
00631
00632
00633
00634
00635 int bdb_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
00636 {
00637 tbl_cache_p _tbc = NULL;
00638 table_p _tp = NULL;
00639 char kbuf[MAX_ROW_SIZE];
00640 char dbuf[MAX_ROW_SIZE];
00641 int i, j, ret, klen, dlen;
00642 int *lkey=NULL;
00643 DBT key, data;
00644 DB *db;
00645
00646 i = j = ret = 0;
00647 klen=MAX_ROW_SIZE;
00648 dlen=MAX_ROW_SIZE;
00649
00650 if ((!_h) || (!_v) || !CON_TABLE(_h))
00651 { return -1;
00652 }
00653
00654 if (!_k)
00655 {
00656 #ifdef BDB_EXTRA_DEBUG
00657 LM_ERR("DB INSERT without KEYs not implemented! \n");
00658 #endif
00659 return -2;
00660 }
00661
00662 _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), (str*)CON_TABLE(_h));
00663 if(!_tbc)
00664 { LM_WARN("table does not exist!\n");
00665 return -3;
00666 }
00667
00668 _tp = _tbc->dtp;
00669 if(!_tp)
00670 { LM_WARN("table not loaded!\n");
00671 return -4;
00672 }
00673
00674 #ifdef BDB_EXTRA_DEBUG
00675 LM_DBG("INSERT in %.*s\n", _tp->name.len, _tp->name.s );
00676 #endif
00677
00678 db = _tp->db;
00679 memset(&key, 0, sizeof(DBT));
00680 memset(kbuf, 0, klen);
00681
00682 if(_tp->ncols<_n)
00683 { LM_WARN("more values than columns!!\n");
00684 return -5;
00685 }
00686
00687 lkey = bdb_get_colmap(_tp, _k, _n);
00688 if(!lkey) return -7;
00689
00690
00691 for(i=0; i<_n; i++)
00692 { j = (lkey)?lkey[i]:i;
00693 if(bdb_is_neq_type(_tp->colp[j]->type, _v[i].type))
00694 {
00695 LM_WARN("incompatible types v[%d] - c[%d]!\n", i, j);
00696 ret = -8;
00697 goto error;
00698 }
00699 }
00700
00701
00702 if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
00703 { LM_ERR("Error in bdblib_valtochar \n");
00704 ret = -9;
00705 goto error;
00706 }
00707
00708 key.data = kbuf;
00709 key.ulen = MAX_ROW_SIZE;
00710 key.flags = DB_DBT_USERMEM;
00711 key.size = klen;
00712
00713
00714 memset(&data, 0, sizeof(DBT));
00715 memset(dbuf, 0, MAX_ROW_SIZE);
00716
00717 if ( (ret = bdblib_valtochar(_tp, lkey, dbuf, &dlen, _v, _n, BDB_VALUE)) != 0 )
00718 { LM_ERR("Error in bdblib_valtochar \n");
00719 ret = -9;
00720 goto error;
00721 }
00722
00723 data.data = dbuf;
00724 data.ulen = MAX_ROW_SIZE;
00725 data.flags = DB_DBT_USERMEM;
00726 data.size = dlen;
00727
00728 if ((ret = db->put(db, NULL, &key, &data, 0)) == 0)
00729 {
00730 bdblib_log(JLOG_INSERT, _tp, dbuf, dlen);
00731
00732 #ifdef BDB_EXTRA_DEBUG
00733 LM_DBG("INSERT\nKEY: [%.*s]\nDATA: [%.*s]\n"
00734 , (int) key.size
00735 , (char *)key.data
00736 , (int) data.size
00737 , (char *)data.data);
00738 #endif
00739 }
00740 else
00741 {
00742 switch(ret)
00743 {
00744
00745 case DB_LOCK_DEADLOCK:
00746
00747
00748 case DB_RUNRECOVERY:
00749 default:
00750 LM_CRIT("DB->put error: %s.\n", db_strerror(ret));
00751 bdblib_recover(_tp, ret);
00752 goto error;
00753 }
00754 }
00755
00756 error:
00757 if(lkey)
00758 pkg_free(lkey);
00759
00760 return ret;
00761
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771 int bdb_delete(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
00772 {
00773 tbl_cache_p _tbc = NULL;
00774 table_p _tp = NULL;
00775 char kbuf[MAX_ROW_SIZE];
00776 int i, j, ret, klen;
00777 int *lkey=NULL;
00778 DBT key;
00779 DB *db;
00780 DBC *dbcp;
00781
00782 i = j = ret = 0;
00783 klen=MAX_ROW_SIZE;
00784
00785 if (_op)
00786 return ( _bdb_delete_cursor(_h, _k, _op, _v, _n) );
00787
00788 if ((!_h) || !CON_TABLE(_h))
00789 return -1;
00790
00791 _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), (str*)CON_TABLE(_h));
00792 if(!_tbc)
00793 { LM_WARN("table does not exist!\n");
00794 return -3;
00795 }
00796
00797 _tp = _tbc->dtp;
00798 if(!_tp)
00799 { LM_WARN("table not loaded!\n");
00800 return -4;
00801 }
00802
00803 #ifdef BDB_EXTRA_DEBUG
00804 LM_DBG("DELETE in %.*s\n", _tp->name.len, _tp->name.s );
00805 #endif
00806
00807 db = _tp->db;
00808 memset(&key, 0, sizeof(DBT));
00809 memset(kbuf, 0, klen);
00810
00811 if(!_k || !_v || _n<=0)
00812 {
00813
00814 if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR) ) != 0)
00815 { LM_ERR("Error creating cursor\n");
00816 goto error;
00817 }
00818
00819 while ((ret = dbcp->c_get(dbcp, &key, NULL, DB_NEXT)) == 0)
00820 {
00821 if(!strncasecmp((char*)key.data,"METADATA",8))
00822 continue;
00823 #ifdef BDB_EXTRA_DEBUG
00824 LM_DBG("KEY: [%.*s]\n"
00825 , (int) key.size
00826 , (char *)key.data);
00827 #endif
00828 ret = dbcp->c_del(dbcp, 0);
00829 }
00830
00831 dbcp->c_close(dbcp);
00832 return 0;
00833 }
00834
00835 lkey = bdb_get_colmap(_tp, _k, _n);
00836 if(!lkey) return -5;
00837
00838
00839 if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
00840 { LM_ERR("Error in bdblib_makekey\n");
00841 ret = -6;
00842 goto error;
00843 }
00844
00845 key.data = kbuf;
00846 key.ulen = MAX_ROW_SIZE;
00847 key.flags = DB_DBT_USERMEM;
00848 key.size = klen;
00849
00850 if ((ret = db->del(db, NULL, &key, 0)) == 0)
00851 {
00852 bdblib_log(JLOG_DELETE, _tp, kbuf, klen);
00853
00854 #ifdef BDB_EXTRA_DEBUG
00855 LM_DBG("DELETED ROW \n KEY: %s \n", (char *)key.data);
00856 #endif
00857 }
00858 else
00859 {
00860 switch(ret){
00861
00862 case DB_NOTFOUND:
00863 ret = 0;
00864 break;
00865
00866
00867 case DB_LOCK_DEADLOCK:
00868
00869 case DB_SECONDARY_BAD:
00870
00871 case DB_RUNRECOVERY:
00872 default:
00873 LM_CRIT("DB->del error: %s.\n"
00874 , db_strerror(ret));
00875 bdblib_recover(_tp, ret);
00876 goto error;
00877 }
00878 }
00879
00880 ret = 0;
00881
00882 error:
00883 if(lkey)
00884 pkg_free(lkey);
00885
00886 return ret;
00887
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897 int _bdb_delete_cursor(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
00898 {
00899 tbl_cache_p _tbc = NULL;
00900 table_p _tp = NULL;
00901 db_res_t* _r = NULL;
00902 char kbuf[MAX_ROW_SIZE];
00903 char dbuf[MAX_ROW_SIZE];
00904 int i, ret, klen=MAX_ROW_SIZE;
00905 DBT key, data;
00906 DB *db;
00907 DBC *dbcp;
00908 int *lkey=NULL;
00909
00910 i = ret = 0;
00911
00912 if ((!_h) || !CON_TABLE(_h))
00913 return -1;
00914
00915 _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), (str*)CON_TABLE(_h));
00916 if(!_tbc)
00917 { LM_WARN("table does not exist!\n");
00918 return -3;
00919 }
00920
00921 _tp = _tbc->dtp;
00922 if(!_tp)
00923 { LM_WARN("table not loaded!\n");
00924 return -4;
00925 }
00926
00927 #ifdef BDB_EXTRA_DEBUG
00928 LM_DBG("DELETE by cursor in %.*s\n", _tp->name.len, _tp->name.s );
00929 #endif
00930
00931 if(_k)
00932 { lkey = bdb_get_colmap(_tp, _k, _n);
00933 if(!lkey)
00934 { ret = -1;
00935 goto error;
00936 }
00937 }
00938
00939
00940 _r = db_new_result();
00941 if (!_r)
00942 { LM_ERR("no memory for result \n");
00943 }
00944
00945 RES_ROW_N(_r) = 0;
00946
00947
00948 if ((ret = bdb_get_columns(_tp, _r, 0, 0)) != 0)
00949 { LM_ERR("Error while getting column names\n");
00950 goto error;
00951 }
00952
00953 db = _tp->db;
00954 memset(&key, 0, sizeof(DBT));
00955 memset(kbuf, 0, klen);
00956 memset(&data, 0, sizeof(DBT));
00957 memset(dbuf, 0, MAX_ROW_SIZE);
00958
00959 data.data = dbuf;
00960 data.ulen = MAX_ROW_SIZE;
00961 data.flags = DB_DBT_USERMEM;
00962
00963
00964 if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR)) != 0)
00965 { LM_ERR("Error creating cursor\n");
00966 }
00967
00968 while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
00969 {
00970 if(!strncasecmp((char*)key.data,"METADATA",8))
00971 continue;
00972
00973
00974 if ((ret=bdb_convert_row( _r, dbuf, 0)) < 0)
00975 { LM_ERR("Error while converting row\n");
00976 goto error;
00977 }
00978
00979 if(bdb_row_match(_k, _op, _v, _n, _r, lkey ))
00980 {
00981
00982 #ifdef BDB_EXTRA_DEBUG
00983 LM_DBG("DELETE ROW by KEY: [%.*s]\n", (int) key.size,
00984 (char *)key.data);
00985 #endif
00986
00987 if((ret = dbcp->c_del(dbcp, 0)) != 0)
00988 {
00989
00990 LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
00991 bdblib_recover(_tp,ret);
00992 }
00993
00994 }
00995
00996 memset(dbuf, 0, MAX_ROW_SIZE);
00997 db_free_rows( _r);
00998 }
00999 ret = 0;
01000
01001 error:
01002 if(dbcp)
01003 dbcp->c_close(dbcp);
01004 if(_r)
01005 db_free_result(_r);
01006 if(lkey)
01007 pkg_free(lkey);
01008
01009 return ret;
01010 }
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 int bdb_update(db_con_t* _con, db_key_t* _k, db_op_t* _op, db_val_t* _v,
01025 db_key_t* _uk, db_val_t* _uv, int _n, int _un)
01026 {
01027 char *c, *t;
01028 int ret, i, qcol, len, sum;
01029 int *lkey=NULL;
01030 tbl_cache_p _tbc = NULL;
01031 table_p _tp = NULL;
01032 char kbuf[MAX_ROW_SIZE];
01033 char qbuf[MAX_ROW_SIZE];
01034 char ubuf[MAX_ROW_SIZE];
01035 DBT key, qdata, udata;
01036 DB *db;
01037
01038 sum = ret = i = qcol = len = 0;
01039
01040 if (!_con || !CON_TABLE(_con) || !_uk || !_uv || _un <= 0)
01041 return -1;
01042
01043 _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), (str*)CON_TABLE(_con));
01044 if(!_tbc)
01045 { LM_ERR("table does not exist\n");
01046 return -1;
01047 }
01048
01049 _tp = _tbc->dtp;
01050 if(!_tp)
01051 { LM_ERR("table not loaded\n");
01052 return -1;
01053 }
01054
01055 db = _tp->db;
01056 if(!db)
01057 { LM_ERR("DB null ptr\n");
01058 return -1;
01059 }
01060
01061 #ifdef BDB_EXTRA_DEBUG
01062 LM_DBG("UPDATE in %.*s\n", _tp->name.len, _tp->name.s);
01063 if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
01064 #endif
01065
01066 memset(&key, 0, sizeof(DBT));
01067 memset(kbuf, 0, MAX_ROW_SIZE);
01068 memset(&qdata, 0, sizeof(DBT));
01069 memset(qbuf, 0, MAX_ROW_SIZE);
01070
01071 qdata.data = qbuf;
01072 qdata.ulen = MAX_ROW_SIZE;
01073 qdata.flags = DB_DBT_USERMEM;
01074
01075 if(_k)
01076 { lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
01077 if(!lkey) return -4;
01078 }
01079 else
01080 {
01081 LM_ERR("Null keys in update _k=0 \n");
01082 return -1;
01083 }
01084
01085 len = MAX_ROW_SIZE;
01086
01087 if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &len, _v, _n, BDB_KEY)) != 0 )
01088 { LM_ERR("Error in query key \n");
01089 goto cleanup;
01090 }
01091
01092 if(lkey) pkg_free(lkey);
01093
01094 key.data = kbuf;
01095 key.ulen = MAX_ROW_SIZE;
01096 key.flags = DB_DBT_USERMEM;
01097 key.size = len;
01098
01099
01100 if ((ret = db->get(db, NULL, &key, &qdata, 0)) == 0)
01101 {
01102
01103 #ifdef BDB_EXTRA_DEBUG
01104 LM_DBG("RESULT\nKEY: [%.*s]\nDATA: [%.*s]\n"
01105 , (int) key.size
01106 , (char *)key.data
01107 , (int) qdata.size
01108 , (char *)qdata.data);
01109 #endif
01110
01111 }
01112 else
01113 { goto db_error;
01114 }
01115
01116
01117
01118
01119 lkey = bdb_get_colmap(_tbc->dtp, _uk, _un);
01120 if(!lkey) return -4;
01121
01122
01123 memset(&udata, 0, sizeof(DBT));
01124 memset(ubuf, 0, MAX_ROW_SIZE);
01125
01126
01127
01128
01129 c = strtok(qbuf, DELIM);
01130 t = ubuf;
01131 while( c!=NULL)
01132 { char* delim = DELIM;
01133 int k;
01134
01135 len = strlen(c);
01136 sum+=len;
01137
01138 if(sum > MAX_ROW_SIZE)
01139 { LM_ERR("value too long for string \n");
01140 ret = -3;
01141 goto cleanup;
01142 }
01143
01144 for(i=0;i<_un;i++)
01145 {
01146 k = lkey[i];
01147 if (qcol == k)
01148 {
01149 int j = MAX_ROW_SIZE - sum;
01150 if( bdb_val2str( &_uv[i], t, &j) )
01151 { LM_ERR("value too long for string \n");
01152 ret = -3;
01153 goto cleanup;
01154 }
01155
01156 goto next;
01157 }
01158
01159 }
01160
01161
01162 strncpy(t, c, len);
01163
01164 next:
01165 t+=len;
01166
01167
01168 sum += DELIM_LEN;
01169 if(sum > MAX_ROW_SIZE)
01170 { LM_ERR("value too long for string \n");
01171 ret = -3;
01172 goto cleanup;
01173 }
01174
01175 strncpy(t, delim, DELIM_LEN);
01176 t += DELIM_LEN;
01177
01178 c = strtok(NULL, DELIM);
01179 qcol++;
01180 }
01181
01182 ubuf[sum] = '0';
01183 udata.data = ubuf;
01184 udata.ulen = MAX_ROW_SIZE;
01185 udata.flags = DB_DBT_USERMEM;
01186 udata.size = sum;
01187
01188 #ifdef BDB_EXTRA_DEBUG
01189 LM_DBG("MODIFIED Data\nKEY: [%.*s]\nDATA: [%.*s]\n"
01190 , (int) key.size
01191 , (char *)key.data
01192 , (int) udata.size
01193 , (char *)udata.data);
01194 #endif
01195
01196 if ((ret = db->del(db, NULL, &key, 0)) == 0)
01197 {
01198 #ifdef BDB_EXTRA_DEBUG
01199 LM_DBG("DELETED ROW\nKEY: %s \n", (char *)key.data);
01200 #endif
01201 }
01202 else
01203 { goto db_error;
01204 }
01205
01206
01207 if ((ret = db->put(db, NULL, &key, &udata, 0)) == 0)
01208 {
01209 bdblib_log(JLOG_UPDATE, _tp, ubuf, sum);
01210 #ifdef BDB_EXTRA_DEBUG
01211 LM_DBG("INSERT \nKEY: [%.*s]\nDATA: [%.*s]\n"
01212 , (int) key.size
01213 , (char *)key.data
01214 , (int) udata.size
01215 , (char *)udata.data);
01216 #endif
01217 }
01218 else
01219 { goto db_error;
01220 }
01221
01222 #ifdef BDB_EXTRA_DEBUG
01223 LM_DBG("UPDATE COMPLETE \n");
01224 #endif
01225
01226
01227 cleanup:
01228 if(lkey)
01229 pkg_free(lkey);
01230
01231 return ret;
01232
01233
01234 db_error:
01235
01236
01237 switch(ret)
01238 {
01239
01240 case DB_NOTFOUND:
01241
01242 #ifdef BDB_EXTRA_DEBUG
01243 LM_DBG("NO RESULT \n");
01244 #endif
01245 return -1;
01246
01247
01248 case DB_LOCK_DEADLOCK:
01249
01250 case DB_SECONDARY_BAD:
01251
01252 case DB_RUNRECOVERY:
01253 default:
01254 LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
01255 bdblib_recover(_tp,ret);
01256 }
01257
01258 if(lkey)
01259 pkg_free(lkey);
01260
01261 return ret;
01262 }