static uint32_t db_envflags(DB * db) { DB_ENV * env = db->get_env(db); uint32_t eflags = 0; (void) env->get_open_flags(env, &eflags); return eflags; }
static int db_fini(rpmdb rdb, const char * dbhome) { DB_ENV * dbenv = rdb->db_dbenv; int rc; int lockfd = -1; uint32_t eflags = 0; if (dbenv == NULL) return 0; if (rdb->db_opens > 1) { rdb->db_opens--; return 0; } (void) dbenv->get_open_flags(dbenv, &eflags); if (!(eflags & DB_PRIVATE)) lockfd = serialize_env(dbhome); rc = dbenv->close(dbenv, 0); rc = dbapi_err(rdb, "dbenv->close", rc, _debug); rpmlog(RPMLOG_DEBUG, "closed db environment %s\n", dbhome); if (!(eflags & DB_PRIVATE) && rdb->db_remove_env) { int xx; xx = db_env_create(&dbenv, 0); xx = dbapi_err(rdb, "db_env_create", xx, _debug); xx = dbenv->remove(dbenv, dbhome, 0); /* filter out EBUSY as it just means somebody else gets to clean it */ xx = dbapi_err(rdb, "dbenv->remove", xx, (xx == EBUSY ? 0 : _debug)); rpmlog(RPMLOG_DEBUG, "removed db environment %s\n", dbhome); } if (lockfd >= 0) close(lockfd); return rc; }
/** probe if the directory contains an environment, and if so, * if it has transactions */ e_txn probe_txn(bfpath *bfp) { DB_ENV *dbe; int r; #if DB_AT_LEAST(4,2) u_int32_t flags; #endif r = db_env_create(&dbe, 0); if (r) { print_error(__FILE__, __LINE__, "cannot create environment handle: %s", db_strerror(r)); return T_ERROR; } /* we might call dbe->set_flags here to set DB_NOPANIC, but this is * only supported from 4.1 onwards and probably not worth the * effort, we'll just check for DB_RUNRECOVERY */ #if DB_AT_LEAST(3,2) r = dbe->open(dbe, bfp->dirname, DB_JOINENV, DS_MODE); #else r = ENOENT; #endif if (r == DB_RUNRECOVERY) { dbe->close(dbe, 0); return T_ENABLED; } if (r == ENOENT) { struct stat st; int w; char *t = bfp->filepath; struct dirent *de; e_txn rc = T_DONT_KNOW; DIR *d; /* no environment found by JOINENV, but clean up handle */ dbe->close(dbe, 0); /* retry, looking for log\.[0-9]{10} files - needed for instance * after bogoutil --db-remove DIR or when DB_JOINENV is * unsupported */ d = opendir(bfp->dirname); if (d == NULL) { print_error(__FILE__, __LINE__, "cannot open directory %s: %s", t, strerror(r)); rc = T_ERROR; } else { while ((errno = 0, de = readdir(d))) { if (strlen(de->d_name) == 14 && strncmp(de->d_name, "log.", 4) == 0 && strspn(de->d_name + 4, "0123456789") == 10) { rc = T_ENABLED; break; } } if (errno) rc = T_ERROR; closedir(d); if (rc != T_ERROR && rc != T_ENABLED) { w = stat(t, &st); if (w == 0) { rc = T_DISABLED; } else if (errno != ENOENT) { rc = T_ERROR; print_error(__FILE__, __LINE__, "cannot stat %s: %s", t, db_strerror(r)); } } } return rc; } /* if (r == ENOENT) for environment join */ if (r != 0) { print_error(__FILE__, __LINE__, "cannot join environment: %s", db_strerror(r)); return T_ERROR; } /* environment found, validate if it has transactions */ #if DB_AT_LEAST(4,2) r = dbe->get_open_flags(dbe, &flags); if (r) { print_error(__FILE__, __LINE__, "cannot query flags: %s", db_strerror(r)); return T_ERROR; } dbe->close(dbe, 0); if ((flags & DB_INIT_TXN) == 0) { print_error(__FILE__, __LINE__, "environment found but does not support transactions."); return T_ERROR; } #else dbe->close(dbe, 0); #endif return T_ENABLED; }
int main(int argc, char **argv) { // Deal with command line arguments const char *path2DbEnv = 0; u_int32_t envFlags = (DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL); u_int32_t txnEnvFlags = (DB_INIT_TXN|DB_INIT_LOCK|DB_INIT_LOG); u_int32_t dbxmlFlags = DBXML_ALLOW_EXTERNAL_ACCESS; vector<string> scripts; int verbose = 0; bool transactionMode = false; bool dbPrivate = false; bool envCreate = false; const char *progName = argv[0]; const char *password = 0; int cacheSize = 64; int ch; int ret = 0; while ((ch = getopt(argc, argv, "?h:hs:tvxVP:cz:")) != -1) { switch (ch) { case 'h': { path2DbEnv = optarg; break; } case 'z': { cacheSize = atoi(optarg); break; } case 'c': { envFlags &= ~DB_PRIVATE; envCreate = true; break; } case 'x': { dbxmlFlags &= ~DBXML_ALLOW_EXTERNAL_ACCESS; break; } case 't': { transactionMode = true; envFlags |= txnEnvFlags; break; } case 's': { scripts.push_back(optarg); break; } case 'v': { ++verbose; break; } case 'V': { printf("%s\n", DbXml::dbxml_version(NULL, NULL, NULL)); printf("%s\n", db_version(NULL, NULL, NULL)); exit(0); } case 'P': { password = optarg; break; } case '?': default: { usage(progName, 0); break; } } } // Turn on logging if extra verbose is specified if(verbose > 1) { setLogLevel(LEVEL_ALL, true); setLogCategory(CATEGORY_ALL, true); setLogCategory(CATEGORY_NODESTORE, verbose > 2); verboseErrors = true; } SigBlock sb; // block signals, resend at end of scope try { // Create a DB environment, and XmlManager DB_ENV *dbenv; int dberr = 0; dberr = db_env_create(&dbenv, 0); if (dberr) { cout << "Error creating environment: " << dberr << endl; exit(-1); } if (password) dbenv->set_encrypt(dbenv, password, DB_ENCRYPT_AES); dbenv->set_errcall(dbenv, errcall); dbenv->set_cachesize(dbenv, 0, cacheSize * 1024 * 1024, 1); dbenv->set_lk_max_lockers(dbenv, 10000); dbenv->set_lk_max_locks(dbenv, 10000); dbenv->set_lk_max_objects(dbenv, 10000); if (!dbPrivate) { dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT); if (verbose && !envCreate) { cout << "Attempting to join environment: " << (path2DbEnv ? path2DbEnv : ".") << endl; } dberr = dbenv->open(dbenv, path2DbEnv, DB_USE_ENVIRON, 0); if (dberr != 0) { if (dberr == DB_VERSION_MISMATCH) { cerr << "Error opening environment " << (path2DbEnv ? path2DbEnv : ".") << ": " << "environment version mismatch" << endl; exit(-1); } if (verbose) { if(envCreate) { cerr << "Creating environment: " << (path2DbEnv ? path2DbEnv : ".") << endl; } else { cerr << "Unable to join environment " << (path2DbEnv ? path2DbEnv : ".") << ", creating a DB_PRIVATE environment" << endl; } } dberr = dbenv->open(dbenv, path2DbEnv, envFlags, 0); } else { cout << "Joined existing environment" << endl; u_int32_t eflags = 0; dbenv->get_open_flags(dbenv, &eflags); if (eflags & DB_INIT_TXN) transactionMode = true; else { if (verbose && (transactionMode == true)) cout << "Joined a non-transactional environment, turning off transaction mode" << endl; transactionMode = false; } } } else { dberr = dbenv->open(dbenv, path2DbEnv, envFlags, 0); } if (dberr != 0) { cerr << "Error opening environment " << (path2DbEnv ? path2DbEnv : ".") << ", error is " << dberr << endl; exit(-1); } XmlManager db(dbenv, dbxmlFlags|DBXML_ADOPT_DBENV); // Create the environment Environment env(db, sb); env.transactions() = transactionMode; // Create the Shell object DefaultShell shell; // Run scripts, if specified if(!scripts.empty()) { env.interactive() = false; env.verbose() = (verbose != 0); for(vector<string>::iterator i = scripts.begin(); i != scripts.end() && !env.quit(); ++i) { ifstream scriptFile(i->c_str(), ios::in); if(!scriptFile) { cerr << progName << ": cannot open script file: " << *i << endl; } else { env.streamName() = *i; env.lineNo() = 0; shell.mainLoop(scriptFile, env); scriptFile.close(); } } } // Perform the queries if(!env.quit()) { env.interactive() = true; env.verbose() = true; env.streamName() = "stdin"; env.lineNo() = 0; do { shell.mainLoop(cin, env); if(env.sigBlock().isInterrupted()) env.sigBlock().reset(); } while(!env.quit() && !cin.eof()); } } catch(exception &e) { cerr << progName << ": error at lowest level: " << e.what() << endl; ret = 1; } catch(...) { cerr << progName << ": error at lowest level: " << endl; ret = 1; } return ret; }