//##############################################################################
//##############################################################################
boost::shared_ptr<BerkeleyDB>
BerkeleyDB::get(const boost::shared_ptr<db::ConfigIface> db_config)
{
    std::lock_guard<std::mutex> guard { inst_lock_ };
    if(terminated_) {
        THROW_STACK(range::db::Exception("Cannot acquire instance of BerkeleyDB after terminal shutdown"));
    }
    if(!inst_) {
        inst_ = boost::shared_ptr<BerkeleyDB>(new BerkeleyDB(db_config));
    }
    return inst_;
}
Example #2
0
//##############################################################################
//##############################################################################
BerkeleyDBCXXDb::BerkeleyDBCXXDb(const std::string &name,
        boost::shared_ptr<BerkeleyDB> backend,
        const boost::shared_ptr<db::ConfigIface> db_config, boost::shared_ptr<BerkeleyDBCXXEnv> env)
    : name_(name), backend_(backend), env_(env), db_config_(db_config), log(BerkeleyDBCXXDbLogModule)
{
    RANGE_LOG_FUNCTION();
    inst_ = boost::make_shared<Db>(env_->getEnv(), 0);

    int rval = 0;
    DbTxn * txn;
    try { 
        rval = env_->getEnv()->txn_begin(NULL, &txn, DB_TXN_SYNC | DB_TXN_WAIT | DB_TXN_SNAPSHOT);
    }
    catch(DbException &e) {
        THROW_STACK(UnknownTransactionException(e.what()));
    }
    try { 
        inst_->open(txn, name.c_str(), name.c_str(), DB_HASH,
                DB_CREATE | DB_MULTIVERSION | DB_THREAD, 0);
    }
    catch(DbException &e) {
        txn->abort();
        THROW_STACK(DatabaseEnvironmentException(e.what()));
    }
    catch(std::exception &e) {
        txn->abort();
        THROW_STACK(DatabaseEnvironmentException(e.what()));
    }
    switch(rval) {
        case 0:
            break;
        case ENOMEM:
            THROW_STACK(DatabaseEnvironmentException("The maximum number of concurrent transactions has been reached."));
    }
    txn->commit(0);
}
Example #3
0
//##############################################################################
//##############################################################################
ChangeList
BerkeleyDBCXXDb::read_changelist() const
{
    RANGE_LOG_FUNCTION();
    std::string buf = this->get_record(record_type::GRAPH_META, "changelist");
    ChangeList changes;
    if(!buf.empty()) {
        changes.ParseFromString(buf);
        if(!changes.IsInitialized()) {
            THROW_STACK(DatabaseVersioningError("Changelist cannot be initialized"));
        }
        return changes;
    }
    changes.set_current_version(0);
    changes.mutable_change();
    changes.mutable_unknown_fields();
    return changes;
    //THROW_STACK(DatabaseVersioningError("Changelist cannot be read"));
}
Example #4
0
bool STACK_check(int need)
{
  static VALUE *old = NULL;

	fprintf(stderr, "STACK_check: SP = %d need = %d limit = %d\n", (int)(((char *)SP - STACK_base) / sizeof(VALUE)), need, (int)((STACK_limit - STACK_base) / sizeof(VALUE)));
	
  if (SP > old)
  {
    fprintf(stderr, "**** STACK_check: -> %ld bytes\n", ((char *)SP - STACK_base));
    old = SP;
  }
	
  if (((char *)(SP + need) + sizeof(STACK_CONTEXT)) >= STACK_limit)
	{
    THROW_STACK();
		return TRUE;
	}
	else
		return FALSE;
}
Example #5
0
//##############################################################################
//##############################################################################
bool
BerkeleyDBCXXDb::commit_record(change_t change)
{
    RANGE_LOG_TIMED_FUNCTION();
    std::string key, data;
    record_type type;
    uint64_t object_version;

    std::tie(type, key, object_version, data) = change;
    std::string fullkey = key_name(type, key);

    auto lck = boost::dynamic_pointer_cast<BerkeleyDBCXXLock>(this->write_lock(type, key));
    DbTxn * dbtxn = BerkeleyDBCXXLockTxnGetter(lck).txn();
    Dbt dbkey { (void*) fullkey.c_str(), (uint32_t) fullkey.size() };
    Dbt dbdata { (void*) data.c_str(), (uint32_t) data.size() };

    int dbrval = 0;
    try {
        dbrval = inst_->put(dbtxn, &dbkey, &dbdata, 0);
    }
    catch (DbException &e) {
        THROW_STACK(DatabaseEnvironmentException(std::string("Unable to read record") + e.what()));
    }
    catch (std::exception &e) {
        THROW_STACK(DatabaseEnvironmentException(std::string("Unable to read record") + e.what()));
    }
    switch(dbrval) {
        case 0:
            return true;
            break;
        case DB_LOCK_DEADLOCK:
            THROW_STACK(DatabaseEnvironmentException("A transactional database environment operation was selected to resolve a deadlock."));
            break;
        case DB_LOCK_NOTGRANTED:
            THROW_STACK(DatabaseEnvironmentException("unable to grant a lock in the allowed time."));
            break;
        case DB_REP_HANDLE_DEAD:
            THROW_STACK(DatabaseEnvironmentException("Dead handle"));
            break;
        case EACCES:
            THROW_STACK(DatabaseEnvironmentException("Database read-only"));
            break;
        default:
            LOG(error, "unknown_rval_from_Db_put") << dbrval;
            return false;
    }
}
Example #6
0
//##############################################################################
//##############################################################################
std::string 
BerkeleyDBCXXDb::get_record(record_type type, const std::string& key) const
{
    RANGE_LOG_TIMED_FUNCTION();
    std::string fullkey = key_name(type, key);
    auto txn = current_txn_.lock();
    if(txn) {
        std::string data;
        if(txn->get_record(type, key, data)) {
            return data;
        }
    }
    auto lck = boost::dynamic_pointer_cast<BerkeleyDBCXXLock>(this->read_lock(type, key));
    DbTxn * dbtxn = BerkeleyDBCXXLockTxnGetter(lck).txn();
    Dbt dbkey { (void*) fullkey.c_str(), (uint32_t) fullkey.size() };

    size_t bufsize = 131072;
    std::unique_ptr<char[]> buf { nullptr };
    Dbt dbdata;
    int dbrval = 0;
  
    do {
        if(buf) { LOG(debug0, "resizing_record_buffer") << bufsize; }
        buf = std::unique_ptr<char[]>(new char[bufsize]);

        if(!buf) {
            std::stringstream s;
            s << "Unable to allocate buffer of size: " << bufsize;
            THROW_STACK(DatabaseEnvironmentException(s.str()));
        }

        dbdata = Dbt(buf.get(), bufsize);
        dbdata.set_ulen(bufsize);
        dbdata.set_flags(DB_DBT_USERMEM);
        bufsize *= 2;

        int flags = lck->readonly() ? 0 : DB_RMW;
        try {
            dbrval = inst_->get(dbtxn, &dbkey, &dbdata, flags);
        }
        catch (DbException &e) {
            if(e.get_errno() == DB_BUFFER_SMALL) { continue; }
            THROW_STACK(DatabaseEnvironmentException(std::string("Unable to read record") + e.what()));
        }
        catch (std::exception &e) {
            THROW_STACK(DatabaseEnvironmentException(std::string("Unable to read record") + e.what()));
        }
    } while(dbrval == DB_BUFFER_SMALL);

    switch(dbrval) {
        case 0:
            break;
        case DB_NOTFOUND:
            return std::string();
        case DB_BUFFER_SMALL:
            THROW_STACK(DatabaseEnvironmentException("The requested item could not be returned due to undersized buffer."));
            break;
        case DB_LOCK_DEADLOCK:
            THROW_STACK(DatabaseEnvironmentException("A transactional database environment operation was selected to resolve a deadlock."));
            break;
        case DB_LOCK_NOTGRANTED:
            THROW_STACK(DatabaseEnvironmentException("unable to grant a lock in the allowed time."));
            break;
        case DB_REP_HANDLE_DEAD:
            THROW_STACK(DatabaseEnvironmentException("Dead handle"));
            break;
        default:
            LOG(error, "unknown dbrval") << dbrval;
    }

    std::string rval { (char *) dbdata.get_data(), dbdata.get_size() };
    return rval;
}