00001
00006
00007 static int _debug = 1;
00008
00009 #include "system.h"
00010
00011 #if defined(HAVE_FTOK) && defined(HAVE_SYS_IPC_H)
00012 #include <sys/ipc.h>
00013 #endif
00014
00015 #if defined(__LCLINT__)
00016
00017 typedef unsigned int u_int32_t;
00018 typedef unsigned short u_int16_t;
00019 typedef unsigned char u_int8_t;
00020
00021 typedef int int32_t;
00022
00023
00024 #endif
00025
00026 #include <db3/db.h>
00027
00028 #include <rpmlib.h>
00029 #include <rpmmacro.h>
00030 #include <rpmurl.h>
00031
00032 #include "rpmdb.h"
00033
00034 #include "debug.h"
00035
00036
00037
00038
00039
00043
00044 struct dbiHStats_s {
00045 unsigned int hash_magic;
00046 unsigned int hash_version;
00047 unsigned int hash_nkeys;
00048 unsigned int hash_ndata;
00049 unsigned int hash_pagesize;
00050 unsigned int hash_nelem;
00051 unsigned int hash_ffactor;
00052 unsigned int hash_buckets;
00053 unsigned int hash_free;
00054 unsigned int hash_bfree;
00055 unsigned int hash_bigpages;
00056 unsigned int hash_big_bfree;
00057 unsigned int hash_overflows;
00058 unsigned int hash_ovfl_free;
00059 unsigned int hash_dup;
00060 unsigned int hash_dup_free;
00061 };
00062
00066 struct dbiBStats_s {
00067 unsigned int bt_magic;
00068 unsigned int bt_version;
00069 unsigned int bt_nkeys;
00070 unsigned int bt_ndata;
00071 unsigned int bt_pagesize;
00072 unsigned int bt_minkey;
00073 unsigned int bt_re_len;
00074 unsigned int bt_re_pad;
00075 unsigned int bt_levels;
00076 unsigned int bt_int_pg;
00077 unsigned int bt_leaf_pg;
00078 unsigned int bt_dup_pg;
00079 unsigned int bt_over_pg;
00080 unsigned int bt_free;
00081 unsigned int bt_int_pgfree;
00082 unsigned int bt_leaf_pgfree;
00083 unsigned int bt_dup_pgfree;
00084 unsigned int bt_over_pgfree;
00085 };
00086
00087
00088
00089 static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit)
00090
00091
00092 {
00093 int rc = 0;
00094
00095 rc = error;
00096
00097 if (printit && rc) {
00098
00099 if (msg)
00100 rpmError(RPMERR_DBERR, _("db%d error(%d) from %s: %s\n"),
00101 dbi->dbi_api, rc, msg, db_strerror(error));
00102 else
00103 rpmError(RPMERR_DBERR, _("db%d error(%d): %s\n"),
00104 dbi->dbi_api, rc, db_strerror(error));
00105
00106 }
00107
00108 return rc;
00109 }
00110
00111
00112 static int db_fini(dbiIndex dbi, const char * dbhome,
00113 const char * dbfile,
00114 const char * dbsubfile)
00115
00116
00117 {
00118 rpmdb rpmdb = dbi->dbi_rpmdb;
00119 DB_ENV * dbenv = rpmdb->db_dbenv;
00120 int rc;
00121
00122 if (dbenv == NULL)
00123 return 0;
00124
00125 rc = dbenv->close(dbenv, 0);
00126 rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
00127
00128 if (dbfile)
00129 rpmMessage(RPMMESS_DEBUG, _("closed db environment %s/%s\n"),
00130 dbhome, dbfile);
00131
00132 if (rpmdb->db_remove_env || dbi->dbi_tear_down) {
00133 int xx;
00134
00135
00136 xx = db_env_create(&dbenv, 0);
00137
00138 xx = cvtdberr(dbi, "db_env_create", rc, _debug);
00139 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00140 xx = dbenv->remove(dbenv, dbhome, 0);
00141 #else
00142 xx = dbenv->remove(dbenv, dbhome, NULL, 0);
00143 #endif
00144 xx = cvtdberr(dbi, "dbenv->remove", rc, _debug);
00145
00146 if (dbfile)
00147 rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s\n"),
00148 dbhome, dbfile);
00149
00150 }
00151 return rc;
00152 }
00153
00154 static int db3_fsync_disable( int fd)
00155
00156 {
00157 return 0;
00158 }
00159
00160
00161 static int db_init(dbiIndex dbi, const char * dbhome,
00162 const char * dbfile,
00163 const char * dbsubfile,
00164 DB_ENV ** dbenvp)
00165
00166
00167
00168 {
00169 rpmdb rpmdb = dbi->dbi_rpmdb;
00170 DB_ENV *dbenv = NULL;
00171 int eflags;
00172 int rc;
00173
00174 if (dbenvp == NULL)
00175 return 1;
00176
00177
00178
00179 if (rpmdb->db_errfile == NULL)
00180 rpmdb->db_errfile = stderr;
00181
00182
00183 eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
00184 if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
00185
00186 if (dbfile)
00187 rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"),
00188 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
00189
00190
00191 if (dbi->dbi_host == NULL)
00192 dbi->dbi_ecflags &= ~DB_CLIENT;
00193
00194
00195 if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
00196 #if defined(HAVE_FTOK)
00197 dbi->dbi_shmkey = ftok(dbhome, 0);
00198 #else
00199 dbi->dbi_shmkey = 0x44631380;
00200 #endif
00201 }
00202
00203 rc = db_env_create(&dbenv, dbi->dbi_ecflags);
00204 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00205 if (rc)
00206 goto errxit;
00207
00208 if (dbenv == NULL)
00209 return 1;
00210
00211 { int xx;
00212
00213 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00214 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00215 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00216
00217
00218 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00219 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00220 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00221 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00222 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00223 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00224 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00225 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00226
00227
00228
00229
00230 xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mp_mmapsize);
00231 xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
00232 xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_mp_size, 0);
00233 xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
00234
00235
00236 if (dbi->dbi_no_fsync) {
00237 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00238 xx = db_env_set_func_fsync(db3_fsync_disable);
00239 #else
00240 xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
00241 #endif
00242 xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
00243 }
00244
00245
00246 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00247 if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00248 xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
00249 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00250 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00251 }
00252 #else
00253 if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) {
00254 xx = dbenv->set_server(dbenv, dbi->dbi_host,
00255 dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
00256 xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
00257 }
00258 #endif
00259 if (dbi->dbi_shmkey) {
00260 xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
00261 xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
00262 }
00263 if (dbi->dbi_tmpdir) {
00264 const char * root;
00265 const char * tmpdir;
00266
00267 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00268 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00269 root = NULL;
00270
00271 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00272
00273 xx = dbenv->set_tmp_dir(dbenv, tmpdir);
00274 xx = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00275 tmpdir = _free(tmpdir);
00276 }
00277 }
00278
00279 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR != 0) || (DB_VERSION_MAJOR == 4)
00280 rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
00281 #else
00282 rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
00283 #endif
00284 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00285 if (rc)
00286 goto errxit;
00287
00288 *dbenvp = dbenv;
00289
00290 return 0;
00291
00292 errxit:
00293 if (dbenv) {
00294 int xx;
00295 xx = dbenv->close(dbenv, 0);
00296 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00297 }
00298 return rc;
00299 }
00300
00301
00302 static int db3sync(dbiIndex dbi, unsigned int flags)
00303
00304
00305 {
00306 DB * db = dbi->dbi_db;
00307 int rc = 0;
00308 int _printit;
00309
00310 if (db != NULL)
00311 rc = db->sync(db, flags);
00312
00313 _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
00314 rc = cvtdberr(dbi, "db->sync", rc, _printit);
00315 return rc;
00316 }
00317
00318 static int db3c_del(dbiIndex dbi, DBC * dbcursor, u_int32_t flags)
00319
00320
00321 {
00322 int rc;
00323
00324 rc = dbcursor->c_del(dbcursor, flags);
00325 rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
00326 return rc;
00327 }
00328
00329 static int db3c_dup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
00330 u_int32_t flags)
00331
00332
00333 {
00334 int rc;
00335
00336 if (dbcp) *dbcp = NULL;
00337 rc = dbcursor->c_dup(dbcursor, dbcp, flags);
00338 rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
00339
00340 return rc;
00341
00342 }
00343
00344 static int db3c_get(dbiIndex dbi, DBC * dbcursor,
00345 DBT * key, DBT * data, u_int32_t flags)
00346
00347
00348 {
00349 int _printit;
00350 int rc;
00351 int rmw;
00352
00353 #ifdef NOTYET
00354 if ((dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00355 rmw = DB_RMW;
00356 else
00357 #endif
00358 rmw = 0;
00359
00360 rc = dbcursor->c_get(dbcursor, key, data, rmw | flags);
00361
00362
00363 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00364 rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00365 return rc;
00366 }
00367
00368 static int db3c_put(dbiIndex dbi, DBC * dbcursor,
00369 DBT * key, DBT * data, u_int32_t flags)
00370
00371
00372 {
00373 int rc;
00374
00375 rc = dbcursor->c_put(dbcursor, key, data, flags);
00376
00377 rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
00378 return rc;
00379 }
00380
00381 static inline int db3c_close(dbiIndex dbi, DBC * dbcursor)
00382
00383
00384 {
00385 int rc;
00386
00387 if (dbcursor == NULL) return -2;
00388
00389 rc = dbcursor->c_close(dbcursor);
00390 rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
00391 return rc;
00392 }
00393
00394 static inline int db3c_open(dbiIndex dbi, DBC ** dbcp,
00395 int dbiflags)
00396
00397
00398 {
00399 DB * db = dbi->dbi_db;
00400 DB_TXN * txnid = NULL;
00401 int flags;
00402 int rc;
00403
00404 if (db == NULL) return -2;
00405 if ((dbiflags & DBI_WRITECURSOR) &&
00406 (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00407 {
00408 flags = DB_WRITECURSOR;
00409 } else
00410 flags = 0;
00411 if (dbcp) *dbcp = NULL;
00412 rc = db->cursor(db, txnid, dbcp, flags);
00413 rc = cvtdberr(dbi, "db3c_open", rc, _debug);
00414
00415 return rc;
00416 }
00417
00418 static int db3cclose(dbiIndex dbi, DBC * dbcursor,
00419 unsigned int flags)
00420
00421
00422 {
00423 int rc = 0;
00424
00425
00426 if (flags & DBI_ITERATOR)
00427 return db3c_close(dbi, dbcursor);
00428
00429 if (!dbi->dbi_use_cursors)
00430 return 0;
00431
00432
00433 if (dbcursor == NULL)
00434 dbcursor = dbi->dbi_rmw;
00435
00436 if (dbcursor) {
00437
00438 if (dbcursor == dbi->dbi_rmw)
00439 dbi->dbi_rmw = NULL;
00440
00441 rc = db3c_close(dbi, dbcursor);
00442 }
00443 return rc;
00444 }
00445
00446 static int db3copen(dbiIndex dbi,
00447 DBC ** dbcp, unsigned int flags)
00448
00449
00450 {
00451 DBC * dbcursor;
00452 int rc = 0;
00453
00454
00455 if (flags & DBI_ITERATOR)
00456 return db3c_open(dbi, dbcp, flags);
00457
00458 if (!dbi->dbi_use_cursors) {
00459 if (dbcp) *dbcp = NULL;
00460 return 0;
00461 }
00462
00463 if ((dbcursor = dbi->dbi_rmw) == NULL) {
00464 if ((rc = db3c_open(dbi, &dbcursor, flags)) == 0)
00465 dbi->dbi_rmw = dbcursor;
00466 }
00467
00468 if (dbcp)
00469 *dbcp = dbi->dbi_rmw;
00470
00471 return rc;
00472 }
00473
00474 static int db3cput(dbiIndex dbi, DBC * dbcursor,
00475 const void * keyp, size_t keylen,
00476 const void * datap, size_t datalen,
00477 unsigned int flags)
00478
00479
00480 {
00481 DB * db = dbi->dbi_db;
00482 DB_TXN * txnid = NULL;
00483 DBT key, data;
00484 int rc;
00485
00486 memset(&key, 0, sizeof(key));
00487 memset(&data, 0, sizeof(data));
00488 key.data = (void *)keyp;
00489 key.size = keylen;
00490 data.data = (void *)datap;
00491 data.size = datalen;
00492
00493 if (dbcursor == NULL) {
00494 if (db == NULL) return -2;
00495 rc = db->put(db, txnid, &key, &data, 0);
00496 rc = cvtdberr(dbi, "db->put", rc, _debug);
00497 } else {
00498
00499 rc = db3c_put(dbi, dbcursor, &key, &data, DB_KEYLAST);
00500
00501 }
00502
00503 return rc;
00504 }
00505
00506 static int db3cdel(dbiIndex dbi, DBC * dbcursor,
00507 const void * keyp, size_t keylen,
00508 unsigned int flags)
00509
00510
00511 {
00512 DB * db = dbi->dbi_db;
00513 DB_TXN * txnid = NULL;
00514 DBT key, data;
00515 int rc;
00516
00517 memset(&key, 0, sizeof(key));
00518 memset(&data, 0, sizeof(data));
00519
00520 key.data = (void *)keyp;
00521 key.size = keylen;
00522
00523 if (dbcursor == NULL) {
00524 if (db == NULL) return -2;
00525 rc = db->del(db, txnid, &key, 0);
00526 rc = cvtdberr(dbi, "db->del", rc, _debug);
00527 } else {
00528
00529 rc = db3c_get(dbi, dbcursor, &key, &data, DB_SET);
00530
00531 if (rc == 0) {
00532
00533 rc = db3c_del(dbi, dbcursor, 0);
00534 }
00535
00536 }
00537
00538 return rc;
00539 }
00540
00541 static int db3cget(dbiIndex dbi, DBC * dbcursor,
00542 void ** keyp, size_t * keylen,
00543 void ** datap, size_t * datalen,
00544 unsigned int flags)
00545
00546
00547 {
00548 DB * db = dbi->dbi_db;
00549 DB_TXN * txnid = NULL;
00550 DBT key, data;
00551 int rc;
00552
00553 memset(&key, 0, sizeof(key));
00554 memset(&data, 0, sizeof(data));
00555
00556 if (keyp) key.data = *keyp;
00557 if (keylen) key.size = *keylen;
00558 if (datap) data.data = *datap;
00559 if (datalen) data.size = *datalen;
00560
00561
00562 if (dbcursor == NULL) {
00563 int _printit;
00564
00565 if (db == NULL) return -2;
00566
00567 rc = db->get(db, txnid, &key, &data, 0);
00568
00569 _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00570 rc = cvtdberr(dbi, "db->get", rc, _printit);
00571 } else {
00572
00573
00574 rc = db3c_get(dbi, dbcursor, &key, &data,
00575 key.data == NULL ? DB_NEXT : DB_SET);
00576
00577 }
00578
00579 if (rc == 0) {
00580
00581 if (keyp) *keyp = key.data;
00582 if (keylen) *keylen = key.size;
00583 if (datap) *datap = data.data;
00584 if (datalen) *datalen = data.size;
00585
00586 }
00587
00588
00589 return rc;
00590
00591 }
00592
00593 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
00594 unsigned int * countp,
00595 unsigned int flags)
00596
00597
00598 {
00599 db_recno_t count = 0;
00600 int rc = 0;
00601
00602 flags = 0;
00603 rc = dbcursor->c_count(dbcursor, &count, flags);
00604 rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
00605 if (rc) return rc;
00606 if (countp) *countp = count;
00607
00608 return rc;
00609 }
00610
00611 static int db3byteswapped(dbiIndex dbi)
00612 {
00613 DB * db = dbi->dbi_db;
00614 int rc = 0;
00615
00616 if (db != NULL) {
00617 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
00618 || (DB_VERSION_MAJOR == 4)
00619 int isswapped = 0;
00620 rc = db->get_byteswapped(db, &isswapped);
00621 if (rc == 0)
00622 rc = isswapped;
00623 #else
00624 rc = db->get_byteswapped(db);
00625 #endif
00626 }
00627
00628 return rc;
00629 }
00630
00631 static int db3stat(dbiIndex dbi, unsigned int flags)
00632
00633
00634 {
00635 DB * db = dbi->dbi_db;
00636 int rc = 0;
00637
00638 if (db == NULL) return -2;
00639 #if defined(DB_FAST_STAT)
00640 if (flags)
00641 flags = DB_FAST_STAT;
00642 else
00643 #endif
00644 flags = 0;
00645 dbi->dbi_stats = _free(dbi->dbi_stats);
00646
00647 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
00648 rc = db->stat(db, &dbi->dbi_stats, flags);
00649 #else
00650 rc = db->stat(db, &dbi->dbi_stats, NULL, flags);
00651 #endif
00652 rc = cvtdberr(dbi, "db->stat", rc, _debug);
00653 return rc;
00654 }
00655
00656
00657 static int db3close( dbiIndex dbi, unsigned int flags)
00658
00659
00660
00661 {
00662 rpmdb rpmdb = dbi->dbi_rpmdb;
00663 const char * urlfn = NULL;
00664 const char * root;
00665 const char * home;
00666 const char * dbhome;
00667 const char * dbfile;
00668 const char * dbsubfile;
00669 DB * db = dbi->dbi_db;
00670 int rc = 0, xx;
00671
00672 flags = 0;
00673
00674
00675
00676
00677 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00678 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00679 root = NULL;
00680 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00681
00682
00683
00684
00685
00686
00687 urlfn = rpmGenPath(root, home, NULL);
00688
00689 (void) urlPath(urlfn, &dbhome);
00690 if (dbi->dbi_temporary) {
00691 dbfile = NULL;
00692 dbsubfile = NULL;
00693 } else {
00694 #ifdef HACK
00695 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00696 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00697 #else
00698 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00699 dbsubfile = NULL;
00700 #endif
00701 }
00702
00703 if (dbi->dbi_rmw)
00704 rc = db3cclose(dbi, NULL, 0);
00705
00706 if (db) {
00707 rc = db->close(db, 0);
00708 rc = cvtdberr(dbi, "db->close", rc, _debug);
00709 db = dbi->dbi_db = NULL;
00710
00711 rpmMessage(RPMMESS_DEBUG, _("closed db index %s/%s\n"),
00712 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00713
00714 }
00715
00716 if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) {
00717 if (rpmdb->db_opens == 1) {
00718
00719 xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
00720
00721 rpmdb->db_dbenv = NULL;
00722 }
00723 rpmdb->db_opens--;
00724 }
00725
00726 if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) {
00727 DB_ENV * dbenv = NULL;
00728
00729
00730 rc = db_env_create(&dbenv, 0);
00731
00732 rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00733 if (rc || dbenv == NULL) goto exit;
00734
00735
00736 dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00737 dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00738 dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00739
00740
00741 xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00742 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00743 xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00744 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00745 xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00746 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00747 xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00748 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00749
00750 if (dbi->dbi_tmpdir) {
00751
00752 const char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
00753
00754 rc = dbenv->set_tmp_dir(dbenv, tmpdir);
00755 rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug);
00756 tmpdir = _free(tmpdir);
00757 if (rc) goto exit;
00758 }
00759
00760 rc = dbenv->open(dbenv, dbhome,
00761 DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0);
00762 rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00763 if (rc) goto exit;
00764
00765
00766 rc = db_create(&db, dbenv, 0);
00767
00768 rc = cvtdberr(dbi, "db_create", rc, _debug);
00769
00770 if (db != NULL) {
00771
00772 const char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL);
00773
00774
00775 rc = db->verify(db, dbf, NULL, NULL, flags);
00776 rc = cvtdberr(dbi, "db->verify", rc, _debug);
00777
00778 rpmMessage(RPMMESS_DEBUG, _("verified db index %s/%s\n"),
00779 (dbhome ? dbhome : ""),
00780 (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00781
00782 xx = db->close(db, 0);
00783 xx = cvtdberr(dbi, "db->close", xx, _debug);
00784 db = NULL;
00785 if (rc == 0 && xx) rc = xx;
00786
00787 dbf = _free(dbf);
00788 }
00789 xx = dbenv->close(dbenv, 0);
00790 xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00791 if (rc == 0 && xx) rc = xx;
00792 }
00793
00794 exit:
00795 dbi->dbi_db = NULL;
00796
00797 urlfn = _free(urlfn);
00798
00799 dbi = db3Free(dbi);
00800
00801 return rc;
00802 }
00803
00804
00805 static int db3open( rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
00806
00807
00808
00809 {
00810
00811 extern struct _dbiVec db3vec;
00812
00813 const char * urlfn = NULL;
00814 const char * root;
00815 const char * home;
00816 const char * dbhome;
00817 const char * dbfile;
00818 const char * dbsubfile;
00819 dbiIndex dbi = NULL;
00820 int rc = 0;
00821 int xx;
00822
00823 DB * db = NULL;
00824 DB_ENV * dbenv = NULL;
00825 DB_TXN * txnid = NULL;
00826 u_int32_t oflags;
00827 int _printit;
00828
00829 if (dbip)
00830 *dbip = NULL;
00831
00832
00833
00834
00835
00836 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00837
00838 return 1;
00839
00840
00841 dbi->dbi_api = DB_VERSION_MAJOR;
00842
00843
00844
00845
00846 root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
00847 if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
00848 root = NULL;
00849 home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
00850
00851
00852
00853
00854
00855
00856 urlfn = rpmGenPath(root, home, NULL);
00857
00858 (void) urlPath(urlfn, &dbhome);
00859 if (dbi->dbi_temporary) {
00860 dbfile = NULL;
00861 dbsubfile = NULL;
00862 } else {
00863 #ifdef HACK
00864 dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00865 dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00866 #else
00867 dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00868 dbsubfile = NULL;
00869 #endif
00870 }
00871
00872 oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
00873 oflags &= ~DB_TRUNCATE;
00874
00875 #if 0
00876 if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
00877 #endif
00878
00879
00880
00881
00882 if (dbi->dbi_temporary) {
00883 oflags |= DB_CREATE;
00884 dbi->dbi_oeflags |= DB_CREATE;
00885 oflags &= ~DB_RDONLY;
00886 dbi->dbi_oflags &= ~DB_RDONLY;
00887 } else {
00888 if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
00889 if (dbi->dbi_mode & O_CREAT) {
00890 oflags |= DB_CREATE;
00891 dbi->dbi_oeflags |= DB_CREATE;
00892 }
00893 #ifdef DANGEROUS
00894 if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
00895 #endif
00896 }
00897
00898
00899
00900
00901 if (dbi->dbi_use_dbenv) {
00902 if (access(dbhome, W_OK) == -1) {
00903
00904
00905 oflags &= ~DB_CREATE;
00906
00907
00908 if (dbi->dbi_eflags & DB_PRIVATE) {
00909 dbi->dbi_eflags &= ~DB_JOINENV;
00910 } else {
00911 dbi->dbi_eflags |= DB_JOINENV;
00912 dbi->dbi_oeflags &= ~DB_CREATE;
00913 dbi->dbi_oeflags &= ~DB_THREAD;
00914
00915 dbi->dbi_use_dbenv = 0;
00916 }
00917
00918
00919 if (dbi->dbi_temporary) {
00920 oflags |= DB_CREATE;
00921 dbi->dbi_oeflags |= DB_CREATE;
00922 oflags &= ~DB_RDONLY;
00923 dbi->dbi_oflags &= ~DB_RDONLY;
00924 } else {
00925 oflags |= DB_RDONLY;
00926
00927 dbi->dbi_oflags |= DB_RDONLY;
00928 }
00929
00930 } else {
00931
00932 const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
00933
00934
00935 if (access(dbf, F_OK) == -1) {
00936
00937 dbi->dbi_oeflags |= DB_CREATE;
00938 dbi->dbi_eflags &= ~DB_JOINENV;
00939 } else {
00940
00941 if (dbi->dbi_eflags & DB_PRIVATE) {
00942 dbi->dbi_eflags &= ~DB_JOINENV;
00943 } else {
00944 dbi->dbi_eflags |= DB_JOINENV;
00945 dbi->dbi_oeflags &= ~DB_CREATE;
00946 dbi->dbi_oeflags &= ~DB_THREAD;
00947 }
00948 }
00949 dbf = _free(dbf);
00950 }
00951 }
00952
00953
00954
00955
00956 if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
00957
00958 const char * dbfn = (dbfile ? dbfile : tagName(dbi->dbi_rpmtag));
00959
00960 const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
00961
00962
00963 if (access(dbf, F_OK) == -1) {
00964
00965 oflags &= ~DB_RDONLY;
00966 } else {
00967
00968 oflags &= ~DB_CREATE;
00969 }
00970
00971
00972 if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
00973 dbi->dbi_oflags &= ~DB_RDONLY;
00974 } else {
00975 dbi->dbi_oflags |= DB_RDONLY;
00976 }
00977 dbf = _free(dbf);
00978 }
00979
00980
00981
00982
00983 if (oflags & DB_RDONLY)
00984 dbi->dbi_verify_on_close = 0;
00985
00986 if (dbi->dbi_use_dbenv) {
00987
00988 if (rpmdb->db_dbenv == NULL) {
00989 rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
00990 if (rc == 0) {
00991 rpmdb->db_dbenv = dbenv;
00992 rpmdb->db_opens = 1;
00993 }
00994 } else {
00995 dbenv = rpmdb->db_dbenv;
00996 rpmdb->db_opens++;
00997 }
00998
00999 }
01000
01001 rpmMessage(RPMMESS_DEBUG, _("opening db index %s/%s %s mode=0x%x\n"),
01002 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)),
01003 prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
01004
01005 if (rc == 0) {
01006 static int _lockdbfd = 0;
01007
01008
01009 rc = db_create(&db, dbenv, dbi->dbi_cflags);
01010
01011 rc = cvtdberr(dbi, "db_create", rc, _debug);
01012 if (rc == 0 && db != NULL) {
01013 if (rc == 0 && dbi->dbi_lorder) {
01014 rc = db->set_lorder(db, dbi->dbi_lorder);
01015 rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
01016 }
01017 if (rc == 0 && dbi->dbi_cachesize) {
01018 rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0);
01019 rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug);
01020 }
01021 if (rc == 0 && dbi->dbi_pagesize) {
01022 rc = db->set_pagesize(db, dbi->dbi_pagesize);
01023 rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
01024 }
01025
01026 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3) || (DB_VERSION_MAJOR == 4)
01027 if (rc == 0 &&
01028 rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free)
01029 {
01030 rc = db->set_alloc(db,
01031 rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free);
01032 rc = cvtdberr(dbi, "db->set_alloc", rc, _debug);
01033 }
01034 #else
01035 if (rc == 0 && rpmdb->db_malloc) {
01036 rc = db->set_malloc(db, rpmdb->db_malloc);
01037 rc = cvtdberr(dbi, "db->set_malloc", rc, _debug);
01038 }
01039 #endif
01040 if (rc == 0 && oflags & DB_CREATE) {
01041 switch(dbi->dbi_type) {
01042 default:
01043 case DB_HASH:
01044 if (dbi->dbi_h_ffactor) {
01045 rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
01046 rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
01047 if (rc) break;
01048 }
01049 if (dbi->dbi_h_nelem) {
01050 rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
01051 rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
01052 if (rc) break;
01053 }
01054 if (dbi->dbi_h_flags) {
01055 rc = db->set_flags(db, dbi->dbi_h_flags);
01056 rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
01057 if (rc) break;
01058 }
01059
01060 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01061 if (dbi->dbi_h_hash_fcn) {
01062 rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
01063 rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
01064 if (rc) break;
01065 }
01066 if (dbi->dbi_h_dup_compare_fcn) {
01067 rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn);
01068 rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01069 if (rc) break;
01070 }
01071 #endif
01072 break;
01073 case DB_BTREE:
01074 if (dbi->dbi_bt_flags) {
01075 rc = db->set_flags(db, dbi->dbi_bt_flags);
01076 rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug);
01077 if (rc) break;
01078 }
01079 if (dbi->dbi_bt_minkey) {
01080 rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey);
01081 rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug);
01082 if (rc) break;
01083 }
01084
01085 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2) || (DB_VERSION_MAJOR == 4)
01086 if (dbi->dbi_bt_compare_fcn) {
01087 rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn);
01088 rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug);
01089 if (rc) break;
01090 }
01091 if (dbi->dbi_bt_dup_compare_fcn) {
01092 rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn);
01093 rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
01094 if (rc) break;
01095 }
01096 if (dbi->dbi_bt_prefix_fcn) {
01097 rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn);
01098 rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug);
01099 if (rc) break;
01100 }
01101 #endif
01102 break;
01103 case DB_RECNO:
01104 if (dbi->dbi_re_delim) {
01105 rc = db->set_re_delim(db, dbi->dbi_re_delim);
01106 rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug);
01107 if (rc) break;
01108 }
01109 if (dbi->dbi_re_len) {
01110 rc = db->set_re_len(db, dbi->dbi_re_len);
01111 rc = cvtdberr(dbi, "db->set_re_len", rc, _debug);
01112 if (rc) break;
01113 }
01114 if (dbi->dbi_re_pad) {
01115 rc = db->set_re_pad(db, dbi->dbi_re_pad);
01116 rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug);
01117 if (rc) break;
01118 }
01119 if (dbi->dbi_re_source) {
01120 rc = db->set_re_source(db, dbi->dbi_re_source);
01121 rc = cvtdberr(dbi, "db->set_re_source", rc, _debug);
01122 if (rc) break;
01123 }
01124 break;
01125 case DB_QUEUE:
01126 if (dbi->dbi_q_extentsize) {
01127 rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize);
01128 rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug);
01129 if (rc) break;
01130 }
01131 break;
01132 }
01133 }
01134
01135 if (rc == 0) {
01136 const char * dbfullpath;
01137 const char * dbpath;
01138 char * t;
01139 int nb;
01140
01141 nb = strlen(dbhome);
01142 if (dbfile) nb += 1 + strlen(dbfile);
01143 dbfullpath = t = alloca(nb + 1);
01144
01145 t = stpcpy(t, dbhome);
01146 if (dbfile)
01147 t = stpcpy( stpcpy( t, "/"), dbfile);
01148 #ifdef HACK
01149 dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
01150 ? dbfullpath : dbfile;
01151 #else
01152 dbpath = (!dbi->dbi_temporary)
01153 ? dbfullpath : dbfile;
01154 #endif
01155
01156 rc = db->open(db, dbpath, dbsubfile,
01157 dbi->dbi_type, oflags, dbi->dbi_perms);
01158
01159 if (rc == 0 && dbi->dbi_type == DB_UNKNOWN) {
01160 #if (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 3 && DB_VERSION_PATCH == 11) \
01161 || (DB_VERSION_MAJOR == 4)
01162 DBTYPE dbi_type = DB_UNKNOWN;
01163 xx = db->get_type(db, &dbi_type);
01164 if (xx == 0)
01165 dbi->dbi_type = dbi_type;
01166 #else
01167 dbi->dbi_type = db->get_type(db);
01168 #endif
01169 }
01170 }
01171
01172
01173 _printit = (rc > 0 ? 0 : _debug);
01174 xx = cvtdberr(dbi, "db->open", rc, _printit);
01175
01176 if (rc == 0 && dbi->dbi_use_dbenv
01177 && (dbi->dbi_eflags & DB_INIT_CDB) && dbi->dbi_get_rmw_cursor)
01178 {
01179 DBC * dbcursor = NULL;
01180 xx = db->cursor(db, txnid, &dbcursor,
01181 ((oflags & DB_RDONLY) ? 0 : DB_WRITECURSOR));
01182 xx = cvtdberr(dbi, "db->cursor", xx, _debug);
01183 dbi->dbi_rmw = dbcursor;
01184 } else
01185 dbi->dbi_rmw = NULL;
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202 if (rc == 0 && dbi->dbi_lockdbfd &&
01203 (!dbi->dbi_use_dbenv || _lockdbfd++ == 0))
01204 {
01205 int fdno = -1;
01206
01207 if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
01208 rc = 1;
01209 } else {
01210 struct flock l;
01211 memset(&l, 0, sizeof(l));
01212 l.l_whence = 0;
01213 l.l_start = 0;
01214 l.l_len = 0;
01215 l.l_type = (dbi->dbi_mode & (O_RDWR|O_WRONLY))
01216 ? F_WRLCK : F_RDLCK;
01217 l.l_pid = 0;
01218
01219 rc = fcntl(fdno, F_SETLK, (void *) &l);
01220 if (rc) {
01221
01222 rc = ((dbi->dbi_use_dbenv &&
01223 (dbi->dbi_eflags & DB_INIT_CDB))
01224 ? 0 : 1);
01225 rpmError( (rc ? RPMERR_FLOCK : RPMWARN_FLOCK),
01226 _("cannot get %s lock on %s/%s\n"),
01227 ((dbi->dbi_mode & (O_RDWR|O_WRONLY))
01228 ? _("exclusive") : _("shared")),
01229 dbhome, (dbfile ? dbfile : ""));
01230 } else if (dbfile) {
01231 rpmMessage(RPMMESS_DEBUG,
01232 _("locked db index %s/%s\n"),
01233 dbhome, dbfile);
01234 }
01235 }
01236 }
01237 }
01238 }
01239
01240 dbi->dbi_db = db;
01241
01242 if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
01243 dbi->dbi_vec = &db3vec;
01244 *dbip = dbi;
01245 } else {
01246 dbi->dbi_verify_on_close = 0;
01247 (void) db3close(dbi, 0);
01248 }
01249
01250 urlfn = _free(urlfn);
01251
01252
01253 return rc;
01254
01255 }
01256
01259
01260
01261 struct _dbiVec db3vec = {
01262 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
01263 db3open, db3close, db3sync, db3copen, db3cclose, db3cdel, db3cget, db3cput,
01264 db3ccount, db3byteswapped, db3stat
01265 };
01266
01267