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)
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;
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.
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;
}
/*
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,
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;
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)
#---------------------- 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
#
# 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}