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