Simplify the dbenv->open() flags shuffle
authorPanu Matilainen <pmatilai@redhat.com>
Fri, 9 Apr 2010 11:53:31 +0000 (14:53 +0300)
committerPanu Matilainen <pmatilai@redhat.com>
Fri, 9 Apr 2010 11:53:31 +0000 (14:53 +0300)
- We always create an environment. If we dont have permissions to create
  or join a shared environment, we use a private environment. Instead
  of trying to figure out what to do beforehand, retry dbenv->open()
  with different flags to see if it succeeds. This eliminates some
  potential races when others might create/remove the environment
  while we're pondering about appropriate flags.
- Lose the "create" bdb config option, this is something we always
  want to decide internally.
- Remove "force" bdb config option, DB_FORCE is dbenv->remove() option
  and its value clashes with DB_CREATE...

lib/backend/db3.c
lib/backend/dbconfig.c
lib/backend/dbi.h
macros.in

index 7d49708..5db73a4 100644 (file)
@@ -91,19 +91,12 @@ static int isalive(DB_ENV *dbenv, pid_t pid, db_threadid_t tid, uint32_t flags)
 static int db_init(dbiIndex dbi, const char * dbhome, DB_ENV ** dbenvp)
 {
     DB_ENV *dbenv = NULL;
-    int eflags;
     int rc, xx;
+    int retry_open = 2;
 
     if (dbenvp == NULL)
        return 1;
 
-    eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
-
-    {  char *fstr = prDbiOpenFlags(eflags, 1);
-       rpmlog(RPMLOG_DEBUG, "opening  db environment %s %s\n", dbhome, fstr);
-       free(fstr);
-    }
-
     rc = db_env_create(&dbenv, 0);
     rc = cvtdberr(dbi, "db_env_create", rc, _debug);
     if (dbenv == NULL || rc)
@@ -142,7 +135,24 @@ static int db_init(dbiIndex dbi, const char * dbhome, DB_ENV ** dbenvp)
        xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
     }
 
-    rc = (dbenv->open)(dbenv, dbhome, eflags, dbi->dbi_rpmdb->db_perms);
+    /*
+     * Actually open the environment. Fall back to private environment
+     * if we dont have permission to join/create shared environment.
+     */
+    while (retry_open) {
+       char *fstr = prDbiOpenFlags(dbi->dbi_eflags, 1);
+       rpmlog(RPMLOG_DEBUG, "opening  db environment %s %s\n", dbhome, fstr);
+       free(fstr);
+
+       rc = (dbenv->open)(dbenv, dbhome,
+                          dbi->dbi_eflags, dbi->dbi_rpmdb->db_perms);
+       if (rc == EACCES) {
+           dbi->dbi_eflags |= DB_PRIVATE;
+           retry_open--;
+       } else {
+           retry_open = 0;
+       }
+    }
     rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
     if (rc)
        goto errxit;
@@ -453,7 +463,7 @@ int dbiOpen(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
     if ((dbi = dbiNew(rpmdb, rpmtag)) == NULL)
        return 1;
 
-    oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
+    oflags = dbi->dbi_oflags;
 
     /*
      * Map open mode flags onto configured database/environment flags.
@@ -461,46 +471,7 @@ int dbiOpen(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
     if ((rpmdb->db_mode & O_ACCMODE) == O_RDONLY) oflags |= DB_RDONLY;
     if (rpmdb->db_mode & O_CREAT) {
        oflags |= DB_CREATE;
-       dbi->dbi_oeflags |= DB_CREATE;
-    }
-
-    /*
-     * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open.
-     */
-    if (access(dbhome, W_OK) == -1) {
-
-       /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */
-       oflags &= ~DB_CREATE;
-
-       /* ... but DBENV->open might still need DB_CREATE ... */
-       if (dbi->dbi_eflags & DB_PRIVATE) {
-           /* ... nothing ... */
-       } else {
-           dbi->dbi_oeflags &= ~DB_CREATE;
-           /* ... but, unless DB_PRIVATE is used, skip DBENV. */
-           rpmdb->db_use_env = 0;
-       }
-
-       /* ... DB_RDONLY maps dbhome perms across files ...  */
-       oflags |= DB_RDONLY;
-       /* ... and DB_WRITECURSOR won't be needed ...  */
-       dbi->dbi_oflags |= DB_RDONLY;
-
-    } else {   /* dbhome is writable, check for persistent dbenv. */
-       char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
-
-       if (access(dbf, F_OK) == -1) {
-           /* ... non-existent (or unwritable) DBENV, will create ... */
-           dbi->dbi_oeflags |= DB_CREATE;
-       } else {
-           /* ... pre-existent (or bogus) DBENV, will join ... */
-           if (dbi->dbi_eflags & DB_PRIVATE) {
-               /* ... nothing ... */
-           } else {
-               dbi->dbi_oeflags &= ~DB_CREATE;
-           }
-       }
-       dbf = _free(dbf);
+       dbi->dbi_oflags |= DB_CREATE;
     }
 
     /*
index e7bafed..7a6f62b 100644 (file)
@@ -21,11 +21,6 @@ static struct _dbiIndex staticdbi;
 static const struct poptOption rdbOptions[] = {
  /* XXX DB_CXX_NO_EXCEPTIONS */
 
- { "create",   0,POPT_BIT_SET, &staticdbi.dbi_oeflags, DB_CREATE,
-       NULL, NULL },
-
- { "force",    0,POPT_BIT_SET, &staticdbi.dbi_eflags, DB_FORCE,
-       NULL, NULL },
  { "cdb",      0,POPT_BIT_SET, &staticdbi.dbi_eflags, DB_INIT_CDB,
        NULL, NULL },
  { "lock",     0,POPT_BIT_SET, &staticdbi.dbi_eflags, DB_INIT_LOCK,
@@ -239,9 +234,10 @@ dbiIndex dbiNew(rpmdb rpmdb, rpmTag rpmtag)
     dbi->dbi_file = rpmTagGetName(rpmtag);
     dbi->dbi_type = (rpmtag == RPMDBI_PACKAGES) ? DBI_PRIMARY : DBI_SECONDARY;
     dbi->dbi_byteswapped = -1; /* -1 unknown, 0 native order, 1 alien order */
+    dbi->dbi_oflags |= DB_CREATE;
 
     /* XXX FIXME: These all are environment, not per-dbi configuration */
-    dbi->dbi_eflags |= (DB_INIT_MPOOL);
+    dbi->dbi_eflags |= (DB_INIT_MPOOL|DB_CREATE);
     /* Throw in some defaults if configuration didn't set any */
     if (!dbi->dbi_mmapsize) dbi->dbi_mmapsize = 16 * 1024 * 1024;
     if (!dbi->dbi_cachesize) dbi->dbi_cachesize = 1 * 1024 * 1024;
@@ -261,12 +257,10 @@ char * prDbiOpenFlags(int dbflags, int print_dbenv_flags)
        if (opt->argInfo != POPT_BIT_SET)
            continue;
        if (print_dbenv_flags) {
-           if (!(opt->arg == &staticdbi.dbi_oeflags ||
-                 opt->arg == &staticdbi.dbi_eflags))
+           if (!(opt->arg == &staticdbi.dbi_eflags))
                continue;
        } else {
-           if (!(opt->arg == &staticdbi.dbi_oeflags ||
-                 opt->arg == &staticdbi.dbi_oflags))
+           if (!(opt->arg == &staticdbi.dbi_oflags))
                continue;
        }
        if ((dbflags & opt->val) != opt->val)
index 34bbd07..e680ba9 100644 (file)
@@ -44,7 +44,6 @@ typedef enum dbiIndexType_e {
 struct _dbiIndex {
     const char * dbi_file;     /*!< file component of path */
 
-    int        dbi_oeflags;            /*!< common (db,dbenv}->open flags */
     int        dbi_eflags;             /*!< dbenv->open flags */
     int        dbi_oflags;             /*!< db->open flags */
 
index 0cc83b9..927f240 100644 (file)
--- a/macros.in
+++ b/macros.in
@@ -537,8 +537,6 @@ print (t)\
 #---------------------- DBENV->open parameters and tunable values:
 #   mmapsize=16Mb      DBENV->set_mp_mmapsize
 #   cachesize=1Mb      DBENV->set_cachesize, DB->set_cachesize
-#---------------------- DBENV->open and DB->open common bits:
-#   create             DB_CREATE
 #---------------------- DBENV->open bits:
 #   cdb                +++     DB_INIT_CDB
 #   txn                ???     DB_INIT_TXN
@@ -568,12 +566,12 @@ print (t)\
 #
 
 # XXX Use transactions and logs for rpmdb durability (no clue yet):
-#%__dbi_other                  create txn log \
+#%__dbi_other                  txn log \
 #                              mp_mmapsize=8Mb mp_size=512Kb
 
 # Use a CDB database model for concurrent access.
 # XXX Add "private" here for legacy interoperation transiting to glibc+nptl.
-%__dbi_cdb                     create cdb mp_mmapsize=16Mb mp_size=1Mb
+%__dbi_cdb                     cdb mp_mmapsize=16Mb mp_size=1Mb
 
 %__dbi_other                   %{?__dbi_cdb}