示例#1
0
CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn)
    : pdb(NULL)
    , activeTxn(NULL)
{
    int ret;
    fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
    fFlushOnClose = fFlushOnCloseIn;
    if (strFilename.empty())
        return;

    bool fCreate = strchr(pszMode, 'c') != NULL;
    unsigned int nFlags = DB_THREAD;
    if (fCreate)
        nFlags |= DB_CREATE;

    {
        LOCK(bitdb.cs_db);
        if (!bitdb.Open(GetDataDir()))
            throw runtime_error("CDB: Failed to open database environment.");

        strFile = strFilename;
        ++bitdb.mapFileUseCount[strFile];
        pdb = bitdb.mapDb[strFile];
        if (pdb == NULL) {
            pdb = new Db(bitdb.dbenv, 0);

            bool fMockDb = bitdb.IsMock();
            if (fMockDb) {
                DbMpoolFile* mpf = pdb->get_mpf();
                ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
                if (ret != 0)
                    throw runtime_error(strprintf("CDB: Failed to configure for no temp file backing for database %s", strFile));
            }

            ret = pdb->open(NULL, // Txn pointer
                            fMockDb ? NULL : strFile.c_str(), // Filename
                            fMockDb ? strFile.c_str() : "main", // Logical db name
                            DB_BTREE, // Database type
                            nFlags, // Flags
                            0);

            if (ret != 0) {
                delete pdb;
                pdb = NULL;
                --bitdb.mapFileUseCount[strFile];
                strFile = "";
                throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFilename));
            }

            if (fCreate && !Exists(string("version"))) {
                bool fTmp = fReadOnly;
                fReadOnly = false;
                WriteVersion(CLIENT_VERSION);
                fReadOnly = fTmp;
            }

            bitdb.mapDb[strFile] = pdb;
        }
    }
}
示例#2
0
文件: ~BerkeleyQ.cpp 项目: tomerd/q
 bool BerkeleyQ::connect()
 {
     if (NULL != db) return true;
         
     try
     {
         int ret = 0;        
         uint env_flags =    DB_CREATE     |  /* Create the environment if it does not exist */
                             DB_INIT_LOCK  |  /* Initialize the locking subsystem */
                             DB_INIT_MPOOL |  /* Initialize the memory pool (in-memory cache) */
                             DB_PRIVATE    |  /* Region files are not backed by the
                                               * filesystem. Instead, they are backed by
                                               * heap memory.  */
                             DB_THREAD;
         
         DbEnv* env = new DbEnv(0);
         
         ret = env->set_cachesize(0,                  /* 0 gigabytes */
                                  50 * 1024 * 1024,   /* 50 megabytes */
                                  1);                 /* Create 1 cache. All memory will
                                                       * be allocated contiguously. */
         env->open(NULL, env_flags, 0);
         
         db = new Db(env, 0); // Instantiate the Db object
                 
         db->open(NULL,          // Transaction pointer
                  NULL,          // Database file name
                  NULL,          // Optional logical database name
                  DB_BTREE,      // Database access method
                  DB_CREATE | DB_THREAD,     // Open flags
                  0);            // File mode (using defaults)
         
         DbMpoolFile* mp = db->get_mpf();
         ret = mp->set_flags(DB_MPOOL_NOFILE, 1);
         
         db->get_env()->lock_id(&locker_id);
         
         start();
     }
     catch(DbException &e)
     {
         db = NULL;        
         q_error("failed connecting to berkeley. %s", e.what());
     }
     catch(std::exception &e)
     {
         db = NULL;
         q_error("failed connecting to berkeley. %s", e.what());
     }
     catch (...)
     {
         db = NULL;
         q_error("failed connecting to berkeley. unknown error");
     }
     
     return (NULL != db);
 }
示例#3
0
//
// run --
//	Get a set of pages.
//
int
MpoolExample::run(int hits, int pagesize, int npages)
{
	db_pgno_t pageno;
	int cnt, ret;
	void *p;

	// Open the file in the environment.
	DbMpoolFile *mfp;

	if ((ret = memp_fcreate(&mfp, 0)) != 0) {
		cerr << "MpoolExample: memp_fcreate failed: "
		     << strerror(ret) << "\n";
		return (EXIT_FAILURE);
	}
	mfp->open(MPOOL, 0, 0, pagesize);

	cout << "retrieve " << hits << " random pages... ";

	srand((unsigned int)time(NULL));
	for (cnt = 0; cnt < hits; ++cnt) {
		pageno = (rand() % npages) + 1;
		if ((ret = mfp->get(&pageno, NULL, 0, &p)) != 0) {
			cerr << "MpoolExample: unable to retrieve page "
			     << (unsigned long)pageno << ": "
			     << strerror(ret) << "\n";
			return (EXIT_FAILURE);
		}
		if (*(db_pgno_t *)p != pageno) {
			cerr << "MpoolExample: wrong page retrieved ("
			     << (unsigned long)pageno << " != "
			     << *(int *)p << ")\n";
			return (EXIT_FAILURE);
		}
		if ((ret = mfp->put(p, DB_PRIORITY_UNCHANGED, 0)) != 0) {
			cerr << "MpoolExample: unable to return page "
			     << (unsigned long)pageno << ": "
			     << strerror(ret) << "\n";
			return (EXIT_FAILURE);
		}
	}

	cout << "successful.\n";

	// Close the pool.
	if ((ret = close(0)) != 0) {
		cerr << "MpoolExample: " << strerror(ret) << "\n";
		return (EXIT_FAILURE);
	}
	return (EXIT_SUCCESS);
}
示例#4
0
BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bool fFlushOnCloseIn) : pdb(nullptr), activeTxn(nullptr)
{
    fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
    fFlushOnClose = fFlushOnCloseIn;
    env = database.env;
    if (database.IsDummy()) {
        return;
    }
    const std::string &strFilename = database.strFile;

    bool fCreate = strchr(pszMode, 'c') != nullptr;
    unsigned int nFlags = DB_THREAD;
    if (fCreate)
        nFlags |= DB_CREATE;

    {
        LOCK(cs_db);
        if (!env->Open(false /* retry */))
            throw std::runtime_error("BerkeleyBatch: Failed to open database environment.");

        pdb = env->mapDb[strFilename];
        if (pdb == nullptr) {
            int ret;
            std::unique_ptr<Db> pdb_temp = MakeUnique<Db>(env->dbenv.get(), 0);

            bool fMockDb = env->IsMock();
            if (fMockDb) {
                DbMpoolFile* mpf = pdb_temp->get_mpf();
                ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
                if (ret != 0) {
                    throw std::runtime_error(strprintf("BerkeleyBatch: Failed to configure for no temp file backing for database %s", strFilename));
                }
            }

            ret = pdb_temp->open(nullptr,                             // Txn pointer
                            fMockDb ? nullptr : strFilename.c_str(),  // Filename
                            fMockDb ? strFilename.c_str() : "main",   // Logical db name
                            DB_BTREE,                                 // Database type
                            nFlags,                                   // Flags
                            0);

            if (ret != 0) {
                throw std::runtime_error(strprintf("BerkeleyBatch: Error %d, can't open database %s", ret, strFilename));
            }

            // Call CheckUniqueFileid on the containing BDB environment to
            // avoid BDB data consistency bugs that happen when different data
            // files in the same environment have the same fileid.
            //
            // Also call CheckUniqueFileid on all the other g_dbenvs to prevent
            // bitcoin from opening the same data file through another
            // environment when the file is referenced through equivalent but
            // not obviously identical symlinked or hard linked or bind mounted
            // paths. In the future a more relaxed check for equal inode and
            // device ids could be done instead, which would allow opening
            // different backup copies of a wallet at the same time. Maybe even
            // more ideally, an exclusive lock for accessing the database could
            // be implemented, so no equality checks are needed at all. (Newer
            // versions of BDB have an set_lk_exclusive method for this
            // purpose, but the older version we use does not.)
            for (const auto& env : g_dbenvs) {
                CheckUniqueFileid(env.second, strFilename, *pdb_temp, this->env->m_fileids[strFilename]);
            }

            pdb = pdb_temp.release();
            env->mapDb[strFilename] = pdb;

            if (fCreate && !Exists(std::string("version"))) {
                bool fTmp = fReadOnly;
                fReadOnly = false;
                WriteVersion(CLIENT_VERSION);
                fReadOnly = fTmp;
            }
        }
        ++env->mapFileUseCount[strFilename];
        strFile = strFilename;
    }
}