int TestSetThreadCount(CuTest *ct) { /* SKIP */ /* Run this test only when hash is supported. */ #ifdef HAVE_HASH DB_ENV *dbenv; DB *db; CuAssert(ct, "db_env_create", db_env_create(&dbenv, 0) == 0); dbenv->set_errpfx(dbenv, "TestSetThreadCount"); CuAssert(ct, "set_thread_count", dbenv->set_thread_count(dbenv, 2) == 0); CuAssert(ct, "env->open", dbenv->open(dbenv, ".", DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE | DB_THREAD, 0) == 0); CuAssert(ct, "db_create", db_create(&db, dbenv, 0) == 0); CuAssert(ct, "DB->open", db->open( db, NULL, NULL, "TestSetThreadCount", DB_HASH, DB_CREATE, 0) == 0); db->close(db, 0); dbenv->close(dbenv, 0); #else printf("TestSetThreadCount is not supported by the build.\n"); #endif /* HAVE_HASH */ return (0); }
/* * Creates a database environment handle * * ARGUMENTS: * path Pathname of the database directory. Shall not be NULL. * The client can free it upon return. * dbEnv Pointer to a pointer to the database environment. Shall * not be NULL. "*dbEnv" is set upon successful return. * RETURNS: * 0 Success. "*dbEnv" is set. * ENOMEM System error. "log_start()" called. * EIO Backend database error. "log_start()" called. */ static RegStatus createEnvHandle( const char* const path, DB_ENV** const dbEnv) { RegStatus status; DB_ENV* env; assert(NULL != path); log_clear(); if (status = db_env_create(&env, 0)) { log_serror("Couldn't create environment handle for database: %s", db_strerror(status)); status = ENOMEM; } else { env->set_errcall(env, logDbError); if (status = env->set_isalive(env, is_alive)) { log_add("Couldn't register \"is_alive()\" function for " "database \"%s\"", path); status = EIO; } else { static const unsigned threadCount = 256; if (status = env->set_thread_count(env, threadCount)) { log_add("Couldn't set thread count to %u for database \"%s\"", threadCount, path); status = EIO; } else { *dbEnv = env; } } if (status) (void)env->close(env, 0); } /* "env" allocated */ return status; }
static int db_init(rpmdb rdb, const char * dbhome) { DB_ENV *dbenv = NULL; int rc, xx; int retry_open = 2; int lockfd = -1; struct dbConfig_s * cfg = &rdb->cfg; /* This is our setup, thou shall not have other setups before us */ uint32_t eflags = (DB_CREATE|DB_INIT_MPOOL|DB_INIT_CDB); if (rdb->db_dbenv != NULL) { rdb->db_opens++; return 0; } else { /* On first call, set backend description to something... */ free(rdb->db_descr); rasprintf(&rdb->db_descr, "db%u", DB_VERSION_MAJOR); } /* * Both verify and rebuild are rather special, if for different reasons: * On rebuild we dont want to be affected by eg paniced environment, and * CDB only slows things down there. Verify is a quirky beast unlike * anything else in BDB, and does not like shared env or CDB. */ if (rdb->db_flags & (RPMDB_FLAG_VERIFYONLY|RPMDB_FLAG_REBUILD)) { eflags |= DB_PRIVATE; eflags &= ~DB_INIT_CDB; } rc = db_env_create(&dbenv, 0); rc = dbapi_err(rdb, "db_env_create", rc, _debug); if (dbenv == NULL || rc) goto errxit; dbenv->set_alloc(dbenv, rmalloc, rrealloc, NULL); dbenv->set_errcall(dbenv, NULL); dbenv->set_errpfx(dbenv, _errpfx); dbenv->set_msgcall(dbenv, warnlog); /* * 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, isalive); dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, (cfg->db_verbose & DB_VERB_DEADLOCK)); dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, (cfg->db_verbose & DB_VERB_RECOVERY)); dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, (cfg->db_verbose & DB_VERB_WAITSFOR)); if (cfg->db_mmapsize) { xx = dbenv->set_mp_mmapsize(dbenv, cfg->db_mmapsize); xx = dbapi_err(rdb, "dbenv->set_mp_mmapsize", xx, _debug); } if (cfg->db_cachesize) { xx = dbenv->set_cachesize(dbenv, 0, cfg->db_cachesize, 0); xx = dbapi_err(rdb, "dbenv->set_cachesize", xx, _debug); } /* * Serialize shared environment open (and clock) via fcntl() lock. * Otherwise we can end up calling dbenv->failchk() while another * process is joining the environment, leading to transient * DB_RUNRECOVER errors. Also prevents races wrt removing the * environment (eg chrooted operation). Silently fall back to * private environment on failure to allow non-privileged queries * to "work", broken as it might be. */ if (!(eflags & DB_PRIVATE)) { lockfd = serialize_env(dbhome); if (lockfd < 0) { eflags |= DB_PRIVATE; retry_open--; rpmlog(RPMLOG_DEBUG, "serialize failed, using private dbenv\n"); } } /* * Actually open the environment. Fall back to private environment * if we dont have permission to join/create shared environment or * system doesn't support it.. */ while (retry_open) { char *fstr = prDbiOpenFlags(eflags, 1); rpmlog(RPMLOG_DEBUG, "opening db environment %s %s\n", dbhome, fstr); free(fstr); rc = (dbenv->open)(dbenv, dbhome, eflags, rdb->db_perms); if ((rc == EACCES || rc == EROFS) || (rc == EINVAL && errno == rc)) { eflags |= DB_PRIVATE; retry_open--; } else { retry_open = 0; } } rc = dbapi_err(rdb, "dbenv->open", rc, _debug); if (rc) goto errxit; dbenv->set_errcall(dbenv, errlog); /* stale lock removal */ rc = dbenv->failchk(dbenv, 0); rc = dbapi_err(rdb, "dbenv->failchk", rc, _debug); if (rc) goto errxit; rdb->db_dbenv = dbenv; rdb->db_opens = 1; if (lockfd >= 0) close(lockfd); return 0; errxit: if (dbenv) { int xx; xx = dbenv->close(dbenv, 0); xx = dbapi_err(rdb, "dbenv->close", xx, _debug); } if (lockfd >= 0) close(lockfd); return rc; }
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; }