Example #1
0
File: db3.c Project: crossbuild/rpm
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;
}
Example #2
0
File: db3.c Project: crossbuild/rpm
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;
}
Example #4
0
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;
}