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

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

Generated at Sun Apr 8 18:42:59 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000