Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

lib/db3.c

Go to the documentation of this file.
00001 
00005 static int _debug = 1;  /* XXX if < 0 debugging, > 0 unusual error returns */
00006 
00007 #ifdef  __LCLINT__
00008 typedef unsigned int u_int32_t;
00009 typedef unsigned short u_int16_t;
00010 typedef unsigned char u_int8_t;
00011 typedef int int32_t;
00012 #endif
00013 
00014 #include "system.h"
00015 
00016 #include <db3/db.h>
00017 
00018 #include <rpmlib.h>
00019 #include <rpmmacro.h>
00020 #include <rpmurl.h>     /* XXX urlPath proto */
00021 
00022 #include "rpmdb.h"
00023 #include "debug.h"
00024 
00025 /*@access rpmdb@*/
00026 /*@access dbiIndex@*/
00027 /*@access dbiIndexSet@*/
00028 
00029 #if DB_VERSION_MAJOR == 3
00030 #define __USE_DB3       1
00031 
00032 #if defined(__USE_DB2) || defined(__USE_DB3)
00033 #if defined(__USE_DB2)
00034 static /*@observer@*/ const char * db_strerror(int error)
00035 {
00036     if (error == 0)
00037         return ("Successful return: 0");
00038     if (error > 0)
00039         return (strerror(error));
00040 
00041     switch (error) {
00042     case DB_INCOMPLETE:
00043         return ("DB_INCOMPLETE: Cache flush was unable to complete");
00044     case DB_KEYEMPTY:
00045         return ("DB_KEYEMPTY: Non-existent key/data pair");
00046     case DB_KEYEXIST:
00047         return ("DB_KEYEXIST: Key/data pair already exists");
00048     case DB_LOCK_DEADLOCK:
00049         return ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
00050     case DB_LOCK_NOTGRANTED:
00051         return ("DB_LOCK_NOTGRANTED: Lock not granted");
00052     case DB_NOTFOUND:
00053         return ("DB_NOTFOUND: No matching key/data pair found");
00054 #if defined(__USE_DB3)
00055     case DB_OLD_VERSION:
00056         return ("DB_OLDVERSION: Database requires a version upgrade");
00057     case DB_RUNRECOVERY:
00058         return ("DB_RUNRECOVERY: Fatal error, run database recovery");
00059 #else   /* __USE_DB3 */
00060     case DB_LOCK_NOTHELD:
00061         return ("DB_LOCK_NOTHELD:");
00062     case DB_REGISTERED:
00063         return ("DB_REGISTERED:");
00064 #endif  /* __USE_DB3 */
00065     default:
00066       {
00067         /*
00068          * !!!
00069          * Room for a 64-bit number + slop.  This buffer is only used
00070          * if we're given an unknown error, which should never happen.
00071          * Note, however, we're no longer thread-safe if it does.
00072          */
00073         static char ebuf[40];
00074 
00075         (void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
00076         return(ebuf);
00077       }
00078     }
00079     /*@notreached@*/
00080 }
00081 
00082 static int db_env_create(DB_ENV **dbenvp, int foo)
00083 {
00084     DB_ENV *dbenv;
00085 
00086     if (dbenvp == NULL)
00087         return 1;
00088     dbenv = xcalloc(1, sizeof(*dbenv));
00089 
00090     *dbenvp = dbenv;
00091     return 0;
00092 }
00093 #endif  /* __USE_DB2 */
00094 
00095 static int cvtdberr(dbiIndex dbi, const char * msg, int error, int printit) {
00096     int rc = 0;
00097 
00098     rc = error;
00099 
00100     if (printit && rc) {
00101         if (msg)
00102             rpmError(RPMERR_DBERR, _("db%d error(%d) from %s: %s\n"),
00103                 dbi->dbi_api, rc, msg, db_strerror(error));
00104         else
00105             rpmError(RPMERR_DBERR, _("db%d error(%d): %s\n"),
00106                 dbi->dbi_api, rc, db_strerror(error));
00107     }
00108 
00109     return rc;
00110 }
00111 
00112 static int db_fini(dbiIndex dbi, const char * dbhome, const char * dbfile,
00113                 /*@unused@*/ const char * dbsubfile)
00114 {
00115     rpmdb rpmdb = dbi->dbi_rpmdb;
00116     DB_ENV * dbenv = dbi->dbi_dbenv;
00117 
00118 #if defined(__USE_DB3)
00119     int rc;
00120 
00121     if (dbenv == NULL) {
00122         dbi->dbi_dbenv = NULL;
00123         return 0;
00124     }
00125 
00126     rc = dbenv->close(dbenv, 0);
00127     rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
00128 
00129     if (dbfile)
00130         rpmMessage(RPMMESS_DEBUG, _("closed  db environment %s/%s\n"),
00131                         dbhome, dbfile);
00132 
00133     if (rpmdb->db_remove_env || dbi->dbi_tear_down) {
00134         int xx;
00135 
00136         xx = db_env_create(&dbenv, 0);
00137         xx = cvtdberr(dbi, "db_env_create", rc, _debug);
00138 #if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
00139         xx = dbenv->remove(dbenv, dbhome, 0);
00140 #else
00141         xx = dbenv->remove(dbenv, dbhome, NULL, 0);
00142 #endif
00143         xx = cvtdberr(dbi, "dbenv->remove", rc, _debug);
00144 
00145         if (dbfile)
00146             rpmMessage(RPMMESS_DEBUG, _("removed db environment %s/%s\n"),
00147                         dbhome, dbfile);
00148 
00149     }
00150         
00151 #else   /* __USE_DB3 */
00152     rc = db_appexit(dbenv);
00153     rc = cvtdberr(dbi, "db_appexit", rc, _debug);
00154     free(dbenv);
00155 #endif  /* __USE_DB3 */
00156     dbi->dbi_dbenv = NULL;
00157     return rc;
00158 }
00159 
00160 static int db3_fsync_disable(/*@unused@*/ int fd) {
00161     return 0;
00162 }
00163 
00164 static int db_init(dbiIndex dbi, const char *dbhome, const char *dbfile,
00165                 /*@unused@*/ const char * dbsubfile, /*@out@*/ DB_ENV **dbenvp)
00166 {
00167     rpmdb rpmdb = dbi->dbi_rpmdb;
00168     DB_ENV *dbenv = NULL;
00169     int eflags;
00170     int rc;
00171 
00172     if (dbenvp == NULL)
00173         return 1;
00174 
00175     /* XXX HACK */
00176     if (rpmdb->db_errfile == NULL)
00177         rpmdb->db_errfile = stderr;
00178 
00179     eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
00180     if ( dbi->dbi_mode & O_CREAT) eflags |= DB_CREATE;
00181 
00182     if (dbfile)
00183         rpmMessage(RPMMESS_DEBUG, _("opening db environment %s/%s %s\n"),
00184                 dbhome, dbfile, prDbiOpenFlags(eflags, 1));
00185 
00186     rc = db_env_create(&dbenv, dbi->dbi_cflags);
00187     rc = cvtdberr(dbi, "db_env_create", rc, _debug);
00188     if (rc)
00189         goto errxit;
00190 
00191 #if defined(__USE_DB3)
00192   { int xx;
00193     dbenv->set_errcall(dbenv, rpmdb->db_errcall);
00194     dbenv->set_errfile(dbenv, rpmdb->db_errfile);
00195     dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
00196  /* dbenv->set_paniccall(???) */
00197     dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT,
00198                 (dbi->dbi_verbose & DB_VERB_CHKPOINT));
00199     dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK,
00200                 (dbi->dbi_verbose & DB_VERB_DEADLOCK));
00201     dbenv->set_verbose(dbenv, DB_VERB_RECOVERY,
00202                 (dbi->dbi_verbose & DB_VERB_RECOVERY));
00203     dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR,
00204                 (dbi->dbi_verbose & DB_VERB_WAITSFOR));
00205  /* dbenv->set_lg_max(???) */
00206  /* dbenv->set_lk_conflicts(???) */
00207  /* dbenv->set_lk_detect(???) */
00208  /* dbenv->set_lk_max(???) */
00209     xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mp_mmapsize);
00210     xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
00211     xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_mp_size, 0);
00212     xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
00213  /* dbenv->set_tx_max(???) */
00214  /* dbenv->set_tx_recover(???) */
00215     if (dbi->dbi_no_fsync) {
00216 #if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
00217         xx = db_env_set_func_fsync(db3_fsync_disable);
00218 #else
00219         xx = dbenv->set_func_fsync(dbenv, db3_fsync_disable);
00220 #endif
00221         xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
00222     }
00223   }
00224 #else   /* __USE_DB3 */
00225     dbenv->db_errcall = rpmdb->db_errcall;
00226     dbenv->db_errfile = rpmdb->db_errfile;
00227     dbenv->db_errpfx = rpmdb->db_errpfx;
00228     dbenv->db_verbose = dbi->dbi_verbose;
00229     dbenv->mp_mmapsize = dbi->dbi_mp_mmapsize;  /* XXX default is 10 Mb */
00230     dbenv->mp_size = dbi->dbi_mp_size;          /* XXX default is 128 Kb */
00231 #endif  /* __USE_DB3 */
00232 
00233 #if defined(__USE_DB3)
00234 #if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
00235     rc = dbenv->open(dbenv, dbhome, eflags, dbi->dbi_perms);
00236 #else
00237     rc = dbenv->open(dbenv, dbhome, NULL, eflags, dbi->dbi_perms);
00238 #endif
00239     rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
00240     if (rc)
00241         goto errxit;
00242 #else   /* __USE_DB3 */
00243     rc = db_appinit(dbhome, NULL, dbenv, eflags);
00244     rc = cvtdberr(dbi, "db_appinit", rc, _debug);
00245     if (rc)
00246         goto errxit;
00247 #endif  /* __USE_DB3 */
00248 
00249     *dbenvp = dbenv;
00250 
00251     return 0;
00252 
00253 errxit:
00254 
00255 #if defined(__USE_DB3)
00256     if (dbenv) {
00257         int xx;
00258         xx = dbenv->close(dbenv, 0);
00259         xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
00260     }
00261 #else   /* __USE_DB3 */
00262     if (dbenv)  free(dbenv);
00263 #endif  /* __USE_DB3 */
00264     return rc;
00265 }
00266 
00267 #endif  /* __USE_DB2 || __USE_DB3 */
00268 
00269 static int db3sync(dbiIndex dbi, unsigned int flags)
00270 {
00271     DB * db = dbi->dbi_db;
00272     int rc;
00273 
00274 #if defined(__USE_DB2) || defined(__USE_DB3)
00275     int _printit;
00276 
00277     rc = db->sync(db, flags);
00278     /* XXX DB_INCOMPLETE is returned occaisionally with multiple access. */
00279     _printit = (rc == DB_INCOMPLETE ? 0 : _debug);
00280     rc = cvtdberr(dbi, "db->sync", rc, _printit);
00281 #else   /* __USE_DB2 || __USE_DB3 */
00282     rc = db->sync(db, flags);
00283 #endif  /* __USE_DB2 || __USE_DB3 */
00284 
00285     return rc;
00286 }
00287 
00288 static int db3c_del(dbiIndex dbi, DBC * dbcursor, u_int32_t flags)
00289 {
00290     int rc;
00291 
00292     rc = dbcursor->c_del(dbcursor, flags);
00293     rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
00294     return rc;
00295 }
00296 
00297 /*@unused@*/ static int db3c_dup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
00298                 u_int32_t flags)
00299 {
00300     int rc;
00301 
00302     rc = dbcursor->c_dup(dbcursor, dbcp, flags);
00303     rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
00304     return rc;
00305 }
00306 
00307 static int db3c_get(dbiIndex dbi, DBC * dbcursor,
00308         DBT * key, DBT * data, u_int32_t flags)
00309 {
00310     int _printit;
00311     int rc;
00312     int rmw;
00313 
00314 #ifdef  NOTYET
00315     if ((dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00316         rmw = DB_RMW;
00317     else
00318 #endif
00319         rmw = 0;
00320 
00321     rc = dbcursor->c_get(dbcursor, key, data, rmw | flags);
00322 
00323     /* XXX DB_NOTFOUND can be returned */
00324     _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00325     rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
00326     return rc;
00327 }
00328 
00329 static int db3c_put(dbiIndex dbi, DBC * dbcursor,
00330         DBT * key, DBT * data, u_int32_t flags)
00331 {
00332     int rc;
00333 
00334     rc = dbcursor->c_put(dbcursor, key, data, flags);
00335 
00336     rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
00337     return rc;
00338 }
00339 
00340 static inline int db3c_close(dbiIndex dbi, /*@only@*/ DBC * dbcursor)
00341 {
00342     int rc;
00343 
00344     rc = dbcursor->c_close(dbcursor);
00345     rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
00346     return rc;
00347 }
00348 
00349 static inline int db3c_open(dbiIndex dbi, /*@out@*/ DBC ** dbcp)
00350 {
00351     DB * db = dbi->dbi_db;
00352     DB_TXN * txnid = NULL;
00353     int flags;
00354     int rc;
00355 
00356 #if defined(__USE_DB3)
00357     if ((dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
00358         flags = DB_WRITECURSOR;
00359     else
00360         flags = 0;
00361     rc = db->cursor(db, txnid, dbcp, flags);
00362 #else   /* __USE_DB3 */
00363     rc = db->cursor(db, txnid, dbcp);
00364 #endif  /* __USE_DB3 */
00365     rc = cvtdberr(dbi, "db3c_open", rc, _debug);
00366 
00367     return rc;
00368 }
00369 
00370 static int db3cclose(dbiIndex dbi, /*@only@*/ DBC * dbcursor,
00371                 unsigned int flags)
00372 {
00373     int rc = 0;
00374 
00375     /* XXX per-iterator cursors */
00376     if (flags == 1)
00377         return db3c_close(dbi, dbcursor);
00378 
00379     if (!dbi->dbi_use_cursors)
00380         return 0;
00381 
00382     if (dbcursor == NULL)
00383         dbcursor = dbi->dbi_rmw;
00384     if (dbcursor) {
00385         if (dbcursor == dbi->dbi_rmw)
00386             dbi->dbi_rmw = NULL;
00387         rc = db3c_close(dbi, dbcursor);
00388     }
00389     return rc;
00390 }
00391 
00392 static int db3copen(dbiIndex dbi, /*@out@*/ DBC ** dbcp, unsigned int flags)
00393 {
00394     DBC * dbcursor;
00395     int rc = 0;
00396 
00397     /* XXX per-iterator cursors */
00398     if (flags == 1)
00399         return db3c_open(dbi, dbcp);
00400 
00401     if (!dbi->dbi_use_cursors) {
00402         if (dbcp) *dbcp = NULL;
00403         return 0;
00404     }
00405 
00406     if ((dbcursor = dbi->dbi_rmw) == NULL) {
00407         if ((rc = db3c_open(dbi, &dbcursor)) == 0)
00408             dbi->dbi_rmw = dbcursor;
00409     }
00410 
00411     if (dbcp)
00412         *dbcp = dbi->dbi_rmw;
00413 
00414     return rc;
00415 }
00416 
00417 static int db3cput(dbiIndex dbi, DBC * dbcursor,
00418                 const void * keyp, size_t keylen,
00419                 const void * datap, size_t datalen,
00420                 /*@unused@*/ unsigned int flags)
00421 {
00422     DB * db = dbi->dbi_db;
00423     DB_TXN * txnid = NULL;
00424     DBT key, data;
00425     int rc;
00426 
00427     memset(&key, 0, sizeof(key));
00428     memset(&data, 0, sizeof(data));
00429     key.data = (void *)keyp;
00430     key.size = keylen;
00431     data.data = (void *)datap;
00432     data.size = datalen;
00433 
00434     if (dbcursor == NULL) {
00435         rc = db->put(db, txnid, &key, &data, 0);
00436         rc = cvtdberr(dbi, "db->put", rc, _debug);
00437     } else {
00438 
00439         rc = db3c_put(dbi, dbcursor, &key, &data, DB_KEYLAST);
00440 
00441     }
00442 
00443     return rc;
00444 }
00445 
00446 static int db3cdel(dbiIndex dbi, DBC * dbcursor,
00447                 const void * keyp, size_t keylen,
00448                 /*@unused@*/ unsigned int flags)
00449 {
00450     DB * db = dbi->dbi_db;
00451     DB_TXN * txnid = NULL;
00452     DBT key, data;
00453     int rc;
00454 
00455     memset(&key, 0, sizeof(key));
00456     memset(&data, 0, sizeof(data));
00457 
00458     key.data = (void *)keyp;
00459     key.size = keylen;
00460 
00461     if (dbcursor == NULL) {
00462         rc = db->del(db, txnid, &key, 0);
00463         rc = cvtdberr(dbi, "db->del", rc, _debug);
00464     } else {
00465 
00466         rc = db3c_get(dbi, dbcursor, &key, &data, DB_SET);
00467 
00468         if (rc == 0) {
00469             /* XXX TODO: loop over duplicates */
00470             rc = db3c_del(dbi, dbcursor, 0);
00471         }
00472 
00473     }
00474 
00475     return rc;
00476 }
00477 
00478 static int db3cget(dbiIndex dbi, DBC * dbcursor,
00479                 void ** keyp, size_t * keylen,
00480                 void ** datap, size_t * datalen,
00481                 /*@unused@*/ unsigned int flags)
00482 {
00483     DB * db = dbi->dbi_db;
00484     DB_TXN * txnid = NULL;
00485     DBT key, data;
00486     int rc;
00487 
00488     memset(&key, 0, sizeof(key));
00489     memset(&data, 0, sizeof(data));
00490     if (keyp)           key.data = *keyp;
00491     if (keylen)         key.size = *keylen;
00492     if (datap)          data.data = *datap;
00493     if (datalen)        data.size = *datalen;
00494 
00495     if (dbcursor == NULL) {
00496         int _printit;
00497         rc = db->get(db, txnid, &key, &data, 0);
00498         /* XXX DB_NOTFOUND can be returned */
00499         _printit = (rc == DB_NOTFOUND ? 0 : _debug);
00500         rc = cvtdberr(dbi, "db->get", rc, _printit);
00501     } else {
00502 
00503         /* XXX db3 does DB_FIRST on uninitialized cursor */
00504         rc = db3c_get(dbi, dbcursor, &key, &data,
00505                 key.data == NULL ? DB_NEXT : DB_SET);
00506 
00507     }
00508 
00509     if (rc == 0) {
00510         if (keyp)       *keyp = key.data;
00511         if (keylen)     *keylen = key.size;
00512         if (datap)      *datap = data.data;
00513         if (datalen)    *datalen = data.size;
00514     }
00515 
00516     return rc;
00517 }
00518 
00519 static int db3byteswapped(dbiIndex dbi)
00520 {
00521     DB * db = dbi->dbi_db;
00522     int rc = 0;
00523 
00524 #if defined(__USE_DB3)
00525     rc = db->get_byteswapped(db);
00526 #endif  /* __USE_DB3 */
00527 
00528     return rc;
00529 }
00530 
00531 static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags)
00532 {
00533     rpmdb rpmdb = dbi->dbi_rpmdb;
00534     const char * urlfn = NULL;
00535     const char * dbhome;
00536     const char * dbfile;
00537     const char * dbsubfile;
00538     DB * db = dbi->dbi_db;
00539     int rc = 0, xx;
00540 
00541     urlfn = rpmGenPath(
00542         (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root),
00543         (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home),
00544         NULL);
00545     (void) urlPath(urlfn, &dbhome);
00546     if (dbi->dbi_temporary) {
00547         dbfile = NULL;
00548         dbsubfile = NULL;
00549     } else {
00550 #ifdef  HACK
00551         dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00552         dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00553 #else
00554         dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00555         dbsubfile = NULL;
00556 #endif
00557     }
00558 
00559 #if defined(__USE_DB2) || defined(__USE_DB3)
00560 
00561     if (dbi->dbi_rmw)
00562         db3cclose(dbi, NULL, 0);
00563 
00564     if (db) {
00565         rc = db->close(db, 0);
00566         rc = cvtdberr(dbi, "db->close", rc, _debug);
00567         db = dbi->dbi_db = NULL;
00568 
00569         rpmMessage(RPMMESS_DEBUG, _("closed  db index       %s/%s\n"),
00570                 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)));
00571 
00572     }
00573 
00574     if (dbi->dbi_dbinfo) {
00575         free(dbi->dbi_dbinfo);
00576         dbi->dbi_dbinfo = NULL;
00577     }
00578 
00579     if (dbi->dbi_use_dbenv)
00580         xx = db_fini(dbi, dbhome, dbfile, dbsubfile);
00581 
00582 #else   /* __USE_DB2 || __USE_DB3 */
00583 
00584     rc = db->close(db);
00585 
00586 #endif  /* __USE_DB2 || __USE_DB3 */
00587     dbi->dbi_db = NULL;
00588 
00589     if (urlfn)
00590         free((void *)urlfn);
00591 
00592     db3Free(dbi);
00593 
00594     return rc;
00595 }
00596 
00597 static int db3open(/*@keep@*/ rpmdb rpmdb, int rpmtag, dbiIndex * dbip)
00598 {
00599     const char * urlfn = NULL;
00600     const char * dbhome;
00601     const char * dbfile;
00602     const char * dbsubfile;
00603     extern struct _dbiVec db3vec;
00604     dbiIndex dbi = NULL;
00605     int rc = 0;
00606     int xx;
00607 
00608 #if defined(__USE_DB2) || defined(__USE_DB3)
00609     DB * db = NULL;
00610     DB_ENV * dbenv = NULL;
00611     DB_TXN * txnid = NULL;
00612     u_int32_t oflags;
00613     int _printit;
00614 
00615     if (dbip)
00616         *dbip = NULL;
00617     if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00618         return 1;
00619     dbi->dbi_api = DB_VERSION_MAJOR;
00620 
00621     urlfn = rpmGenPath(
00622         (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root),
00623         (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home),
00624         NULL);
00625     (void) urlPath(urlfn, &dbhome);
00626     if (dbi->dbi_temporary) {
00627         dbfile = NULL;
00628         dbsubfile = NULL;
00629     } else {
00630 #ifdef  HACK
00631         dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
00632         dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : tagName(dbi->dbi_rpmtag));
00633 #else
00634         dbfile = (dbi->dbi_file ? dbi->dbi_file : tagName(dbi->dbi_rpmtag));
00635         dbsubfile = NULL;
00636 #endif
00637     }
00638 
00639     oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
00640     oflags &= ~DB_TRUNCATE;     /* XXX this is dangerous */
00641 
00642 #if 0   /* XXX rpmdb: illegal flag combination specified to DB->open */
00643     if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
00644 #endif
00645     if (dbi->dbi_temporary) {
00646         oflags &= ~DB_RDONLY;
00647         oflags |= DB_CREATE;
00648     } else {
00649         if(!(dbi->dbi_mode & O_RDWR)) oflags |= DB_RDONLY;
00650         if ( dbi->dbi_mode & O_CREAT) oflags |= DB_CREATE;
00651         if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE;
00652     }
00653 
00654     dbi->dbi_dbinfo = NULL;
00655 
00656     if (dbi->dbi_use_dbenv)
00657         rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
00658 
00659     rpmMessage(RPMMESS_DEBUG, _("opening db index       %s/%s %s mode=0x%x\n"),
00660                 dbhome, (dbfile ? dbfile : tagName(dbi->dbi_rpmtag)),
00661                 prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
00662 
00663     if (rc == 0) {
00664 #if defined(__USE_DB3)
00665         rc = db_create(&db, dbenv, dbi->dbi_cflags);
00666         rc = cvtdberr(dbi, "db_create", rc, _debug);
00667         if (rc == 0) {
00668             if (dbi->dbi_lorder) {
00669                 rc = db->set_lorder(db, dbi->dbi_lorder);
00670                 rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
00671             }
00672             if (dbi->dbi_cachesize) {
00673                 rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0);
00674                 rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug);
00675             }
00676             if (dbi->dbi_pagesize) {
00677                 rc = db->set_pagesize(db, dbi->dbi_pagesize);
00678                 rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
00679             }
00680             if (rpmdb->db_malloc) {
00681                 rc = db->set_malloc(db, rpmdb->db_malloc);
00682                 rc = cvtdberr(dbi, "db->set_malloc", rc, _debug);
00683             }
00684             if (oflags & DB_CREATE) {
00685                 switch(dbi->dbi_type) {
00686                 default:
00687                 case DB_HASH:
00688                     if (dbi->dbi_h_ffactor) {
00689                         rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
00690                         rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
00691                     }
00692                     if (dbi->dbi_h_hash_fcn) {
00693                         rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
00694                         rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
00695                     }
00696                     if (dbi->dbi_h_nelem) {
00697                         rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
00698                         rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
00699                     }
00700                     if (dbi->dbi_h_flags) {
00701                         rc = db->set_flags(db, dbi->dbi_h_flags);
00702                         rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
00703                     }
00704                     if (dbi->dbi_h_dup_compare_fcn) {
00705                         rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn);
00706                         rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
00707                     }
00708                     break;
00709                 case DB_BTREE:
00710                 case DB_RECNO:
00711                 case DB_QUEUE:
00712                     break;
00713                 }
00714             }
00715             dbi->dbi_dbinfo = NULL;
00716 
00717             {   const char * dbfullpath;
00718                 const char * dbpath;
00719                 char * t;
00720                 int nb;
00721 
00722                 nb = strlen(dbhome);
00723                 if (dbfile)     nb += 1 + strlen(dbfile);
00724                 dbfullpath = t = alloca(nb + 1);
00725 
00726                 t = stpcpy(t, dbhome);
00727                 if (dbfile)
00728                     t = stpcpy( stpcpy( t, "/"), dbfile);
00729                 dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
00730                         ? dbfullpath : dbfile;
00731 
00732                 rc = db->open(db, dbpath, dbsubfile,
00733                     dbi->dbi_type, oflags, dbi->dbi_perms);
00734             }
00735 
00736             /* XXX return rc == errno without printing */
00737             _printit = (rc > 0 ? 0 : _debug);
00738             xx = cvtdberr(dbi, "db->open", rc, _printit);
00739 
00740             if (rc == 0 && dbi->dbi_get_rmw_cursor) {
00741                 DBC * dbcursor = NULL;
00742                 xx = db->cursor(db, txnid, &dbcursor,
00743                         ((oflags & DB_RDONLY) ? 0 : DB_WRITECURSOR));
00744                 xx = cvtdberr(dbi, "db->cursor", xx, _debug);
00745                 dbi->dbi_rmw = dbcursor;
00746             } else
00747                 dbi->dbi_rmw = NULL;
00748 
00749             if (rc == 0 && dbi->dbi_lockdbfd) {
00750                 int fdno = -1;
00751 
00752                 if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
00753                     rc = 1;
00754                 } else {
00755                     struct flock l;
00756                     l.l_whence = 0;
00757                     l.l_start = 0;
00758                     l.l_len = 0;
00759                     l.l_type = (dbi->dbi_mode & O_RDWR) ? F_WRLCK : F_RDLCK;
00760                     l.l_pid = 0;
00761 
00762                     if (fcntl(fdno, F_SETLK, (void *) &l)) {
00763                         rpmError(RPMERR_FLOCK,
00764                                 _("cannot get %s lock on %s/%s\n"),
00765                                 ((dbi->dbi_mode & O_RDWR)
00766                                         ? _("exclusive") : _("shared")),
00767                                 dbhome, dbfile);
00768                         rc = 1;
00769                     } else if (dbfile) {
00770                         rpmMessage(RPMMESS_DEBUG,
00771                                 _("locked  db index       %s/%s\n"),
00772                                 dbhome, dbfile);
00773                     }
00774                 }
00775             }
00776         }
00777 #else   /* __USE_DB3 */
00778       { DB_INFO * dbinfo = xcalloc(1, sizeof(*dbinfo));
00779         dbinfo->db_cachesize = dbi->dbi_cachesize;
00780         dbinfo->db_lorder = dbi->dbi_lorder;
00781         dbinfo->db_pagesize = dbi->dbi_pagesize;
00782         dbinfo->db_malloc = rpmdb->db_malloc;
00783         if (oflags & DB_CREATE) {
00784             switch(dbi->dbi_type) {
00785             default:
00786             case DB_HASH:
00787                 dbinfo->h_ffactor = dbi->dbi_h_ffactor;
00788                 dbinfo->h_hash = dbi->dbi_h_hash_fcn;
00789                 dbinfo->h_nelem = dbi->dbi_h_nelem;
00790                 dbinfo->flags = dbi->dbi_h_flags;
00791                 break;
00792             }
00793         }
00794         dbi->dbi_dbinfo = dbinfo;
00795         rc = db_open(dbfile, dbi->dbi_type, oflags,
00796                         dbi->dbi_perms, dbenv, dbinfo, &db);
00797         /* XXX return rc == errno without printing */
00798         _printit = (rc > 0 ? 0 : _debug);
00799         xx = cvtdberr(dbi, "db->open", rc, _printit);
00800       }
00801 #endif  /* __USE_DB3 */
00802     }
00803 
00804     dbi->dbi_db = db;
00805     dbi->dbi_dbenv = dbenv;
00806 
00807 #else   /* __USE_DB2 || __USE_DB3 */
00808     void * dbopeninfo = NULL;
00809 
00810     if (dbip)
00811         *dbip = NULL;
00812     if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
00813         return 1;
00814 
00815     dbi->dbi_db = dbopen(dbfile, dbi->dbi_mode, dbi->dbi_perms,
00816                 dbi->dbi_type, dbopeninfo);
00817     /* XXX return rc == errno without printing */
00818     if (dbi->dbi_db == NULL) rc = errno;
00819 #endif  /* __USE_DB2 || __USE_DB3 */
00820 
00821     if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
00822         dbi->dbi_vec = &db3vec;
00823         *dbip = dbi;
00824     } else
00825         db3close(dbi, 0);
00826 
00827     if (urlfn)
00828         free((void *)urlfn);
00829 
00830     return rc;
00831 }
00832 
00835 struct _dbiVec db3vec = {
00836     DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
00837     db3open, db3close, db3sync, db3copen, db3cclose, db3cdel, db3cget, db3cput,
00838     db3byteswapped
00839 };
00840 
00841 #endif  /* DB_VERSION_MAJOR == 3 */

Generated at Mon May 21 08:53:39 2001 for rpm by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001