static int db_init(dbiIndex dbi, const char * dbhome, const char * dbfile, const char * dbsubfile, DB_ENV ** dbenvp) { rpmdb rpmdb = dbi->dbi_rpmdb; DB_ENV *dbenv = NULL; int eflags; int rc; if (dbenvp == NULL) return 1; /* XXX HACK */ if (rpmdb->db_errfile == NULL) rpmdb->db_errfile = stderr; eflags = (dbi->dbi_oeflags | dbi->dbi_eflags); if (eflags & DB_JOINENV) eflags &= DB_JOINENV; if (dbfile) { char *dbiflags = prDbiOpenFlags(eflags, 1); rpmlog(RPMLOG_DEBUG, "opening db environment %s/%s %s\n", dbhome, dbfile, dbiflags); free(dbiflags); } /* XXX Can't do RPC w/o host. */ if (dbi->dbi_host == NULL) dbi->dbi_ecflags &= ~DB_CLIENT; /* XXX Set a default shm_key. */ if ((dbi->dbi_eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) { #if defined(HAVE_FTOK) dbi->dbi_shmkey = ftok(dbhome, 0); #else dbi->dbi_shmkey = 0x44631380; #endif } rc = db_env_create(&dbenv, dbi->dbi_ecflags); rc = cvtdberr(dbi, "db_env_create", rc, _debug); if (dbenv == NULL || rc) goto errxit; { int xx; /* 4.1: dbenv->set_app_dispatch(???) */ /* 4.1: dbenv->set_alloc(???) */ /* 4.1: dbenv->set_data_dir(???) */ /* 4.1: dbenv->set_encrypt(???) */ dbenv->set_errcall(dbenv, (void *) rpmdb->db_errcall); dbenv->set_errfile(dbenv, rpmdb->db_errfile); dbenv->set_errpfx(dbenv, rpmdb->db_errpfx); /* 4.1: dbenv->set_feedback(???) */ /* 4.1: dbenv->set_flags(???) */ /* dbenv->set_paniccall(???) */ #if (DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 5) /* * These enable automatic stale lock removal. * thread_count 8 is some kind of "magic minimum" value... */ dbenv->set_thread_count(dbenv, 8); dbenv->set_isalive(dbenv, db3isalive); #endif if ((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) { const char * home; int retry = 0; if ((home = strrchr(dbhome, '/')) != NULL) dbhome = ++home; while (retry++ < 5) { xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host, dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0); xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug); if (!xx) break; (void) sleep(15); } } else { #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, (dbi->dbi_verbose & DB_VERB_CHKPOINT)); #endif xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, (dbi->dbi_verbose & DB_VERB_DEADLOCK)); xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, (dbi->dbi_verbose & DB_VERB_RECOVERY)); xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, (dbi->dbi_verbose & DB_VERB_WAITSFOR)); if (dbi->dbi_mmapsize) { xx = dbenv->set_mp_mmapsize(dbenv, dbi->dbi_mmapsize); xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug); } if (dbi->dbi_tmpdir) { const char * root; char * tmpdir; root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL); xx = dbenv->set_tmp_dir(dbenv, tmpdir); xx = cvtdberr(dbi, "dbenv->set_tmp_dir", xx, _debug); tmpdir = _free(tmpdir); } } /* dbenv->set_lk_conflicts(???) */ /* dbenv->set_lk_detect(???) */ /* 4.1: dbenv->set_lk_max_lockers(???) */ /* 4.1: dbenv->set_lk_max_locks(???) */ /* 4.1: dbenv->set_lk_max_objects(???) */ /* 4.1: dbenv->set_lg_bsize(???) */ /* 4.1: dbenv->set_lg_dir(???) */ /* 4.1: dbenv->set_lg_max(???) */ /* 4.1: dbenv->set_lg_regionmax(???) */ if (dbi->dbi_cachesize) { xx = dbenv->set_cachesize(dbenv, 0, dbi->dbi_cachesize, 0); xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug); } /* 4.1 dbenv->set_timeout(???) */ /* dbenv->set_tx_max(???) */ /* 4.1: dbenv->set_tx_timestamp(???) */ /* dbenv->set_tx_recover(???) */ /* dbenv->set_rep_transport(???) */ /* dbenv->set_rep_limit(???) */ if (dbi->dbi_no_fsync) { xx = db_env_set_func_fsync(db3_fsync_disable); xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug); } if (dbi->dbi_shmkey) { xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey); xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug); } } rc = (dbenv->open)(dbenv, dbhome, eflags, dbi->dbi_perms); rc = cvtdberr(dbi, "dbenv->open", rc, _debug); if (rc) goto errxit; #if (DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 5) /* stale lock removal */ rc = dbenv->failchk(dbenv, 0); rc = cvtdberr(dbi, "dbenv->failchk", rc, _debug); if (rc) goto errxit; #endif *dbenvp = dbenv; return 0; errxit: if (dbenv) { int xx; xx = dbenv->close(dbenv, 0); xx = cvtdberr(dbi, "dbenv->close", xx, _debug); } return rc; }
static int db3close(dbiIndex dbi, unsigned int flags) { rpmdb rpmdb = dbi->dbi_rpmdb; const char * root; const char * home; char * dbhome; const char * dbfile; const char * dbsubfile; DB * db = dbi->dbi_db; int _printit; int rc = 0, xx; flags = 0; /* XXX unused */ /* * Get the prefix/root component and directory path. */ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home); dbhome = rpmGenPath(root, home, NULL); if (dbi->dbi_temporary) { dbfile = NULL; dbsubfile = NULL; } else { #ifdef HACK /* XXX necessary to support dbsubfile */ dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename); dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : rpmTagGetName(dbi->dbi_rpmtag)); #else dbfile = (dbi->dbi_file ? dbi->dbi_file : rpmTagGetName(dbi->dbi_rpmtag)); dbsubfile = NULL; #endif } if (db) { rc = db->close(db, 0); /* XXX ignore not found error messages. */ _printit = (rc == ENOENT ? 0 : _debug); rc = cvtdberr(dbi, "db->close", rc, _printit); db = dbi->dbi_db = NULL; rpmlog(RPMLOG_DEBUG, "closed db index %s/%s\n", dbhome, (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag))); } if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) { if (rpmdb->db_opens == 1) { xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile); rpmdb->db_dbenv = NULL; } rpmdb->db_opens--; } if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) { DB_ENV * dbenv = NULL; rc = db_env_create(&dbenv, 0); rc = cvtdberr(dbi, "db_env_create", rc, _debug); if (rc || dbenv == NULL) goto exit; dbenv->set_errcall(dbenv, (void *) rpmdb->db_errcall); dbenv->set_errfile(dbenv, rpmdb->db_errfile); dbenv->set_errpfx(dbenv, rpmdb->db_errpfx); /* dbenv->set_paniccall(???) */ #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, (dbi->dbi_verbose & DB_VERB_CHKPOINT)); #endif xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, (dbi->dbi_verbose & DB_VERB_DEADLOCK)); xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, (dbi->dbi_verbose & DB_VERB_RECOVERY)); xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, (dbi->dbi_verbose & DB_VERB_WAITSFOR)); if (dbi->dbi_tmpdir) { char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL); rc = dbenv->set_tmp_dir(dbenv, tmpdir); rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug); tmpdir = _free(tmpdir); if (rc) goto exit; } rc = (dbenv->open)(dbenv, dbhome, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0); rc = cvtdberr(dbi, "dbenv->open", rc, _debug); if (rc) goto exit; rc = db_create(&db, dbenv, 0); rc = cvtdberr(dbi, "db_create", rc, _debug); if (db != NULL) { char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL); rc = db->verify(db, dbf, NULL, NULL, flags); rc = cvtdberr(dbi, "db->verify", rc, _debug); rpmlog(RPMLOG_DEBUG, "verified db index %s/%s\n", (dbhome ? dbhome : ""), (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag))); /* * The DB handle may not be accessed again after * DB->verify is called, regardless of its return. */ db = NULL; dbf = _free(dbf); } xx = dbenv->close(dbenv, 0); xx = cvtdberr(dbi, "dbenv->close", xx, _debug); if (rc == 0 && xx) rc = xx; } exit: dbi->dbi_db = NULL; free(dbhome); dbi = db3Free(dbi); return rc; }
/* * This should be done before the program is open for business. * As such, it does not need to be reentrant. */ int open_db_env(char *topdir) { DB_ENV *tmpenv = NULL; int st; struct stat64 sbuf; char logdir[MAXPATHLEN+1]; char tmpdir[MAXPATHLEN+1]; char *dirarr[3]; int i; if (topdir == NULL) { return (-1); } snprintf(logdir, sizeof (tmpdir), "%s/.logs", topdir); snprintf(tmpdir, sizeof (tmpdir), "%s/.tmp", topdir); dirarr[0] = topdir; dirarr[1] = logdir; dirarr[2] = tmpdir; /* first, set up the environment */ st = db_env_create(&tmpenv, 0); if (st != 0) { return (st); } /* make sure the directories exist */ for (i = 0; i < 3; i++) { st = stat64(dirarr[i], &sbuf); if ((st != 0) && (errno == ENOENT)) { st = mkdirp(dirarr[i], 0744); if (st == 0) { st = stat64(dirarr[i], &sbuf); } } if ((st == 0) && (!S_ISDIR(sbuf.st_mode))) { st = -1; break; } } if (st != 0) { return (st); } st = tmpenv->set_data_dir(tmpenv, topdir); if (st != 0) { return (st); } st = tmpenv->set_lg_dir(tmpenv, logdir); if (st != 0) { return (st); } st = tmpenv->set_tmp_dir(tmpenv, tmpdir); if (st != 0) { return (st); } st = tmpenv->set_flags(tmpenv, env_fl, 1); if (st != 0) { return (st); } /* overall database cache size */ st = tmpenv->set_cachesize(tmpenv, 0, (60 * MEGA), 1); st = tmpenv->set_shm_key(tmpenv, FSM_SHM_MASTER_KEY); if (st != 0) { return (st); } /* log buffer in memory */ st = tmpenv->set_lg_bsize(tmpenv, (30 * MEGA)); if (st != 0) { return (st); } /* set up additional error logging */ tmpenv->set_errcall(tmpenv, fsmdb_log_err); /* Increase the number of locks available */ tmpenv->set_lk_max_locks(tmpenv, 10000); tmpenv->set_lk_max_lockers(tmpenv, 10000); tmpenv->set_lk_max_objects(tmpenv, 10000); /* Increase the number of concurrent transactions available */ /* Note: Default in 4.4-20 is '20'. In later versions it's 100 */ tmpenv->set_tx_max(tmpenv, 100); st = tmpenv->open(tmpenv, topdir, env_ofl, 0644); if (st != 0) { /* check for a major failure */ if (st == DB_RUNRECOVERY) { st = tmpenv->open(tmpenv, topdir, env_ffl, 0644); } /* log catastrophic failure and remove all db files. */ if (st == DB_RUNRECOVERY) { fsmdb_log_err(dbEnv, NULL, "Database files corrupt, cannot recover. " "Files will be removed. Please re-index any " "recovery points to regenerate the database."); fsmdb_remove_all(topdir); } } if (st != 0) { return (st); } /* clear out unneeded log files */ tmpenv->log_archive(tmpenv, NULL, DB_ARCH_REMOVE); /* all set, ready to use */ dbEnv = tmpenv; return (st); }