void berkeleydb_store<Object>::get_range(const timestamp& from,
                                         const timestamp& to,
                                         const long lp_id,
                                         std::vector<obj_ptr>& ret_obj) {
  boost::lock_guard<boost::mutex> guard(get_mutex_);
  if (from > to) return;

  /* generate key */
  std::vector<char> from_char;
  key_lpid_to_char(from, lp_id, from_char);
  Dbt db_key = Dbt(&from_char[0], from_char.size());

  /* prepare data */
  char* binary;
  Dbt data;
  data.set_data(binary);
  data.set_flags(DB_DBT_MALLOC);

  /* seek to from */
  Dbc* cursorp;
  db->cursor(NULL, &cursorp, 0);
  int ret = cursorp->get(&db_key, &data, DB_SET_RANGE);
  if (ret) {
    if (cursorp != NULL) cursorp->close();
    return;
  }
  std::string get_data_binary
      = std::string((char*) data.get_data(), data.get_size());
  std::stringstream from_ss;
  from_ss << get_data_binary;
  boost::archive::binary_iarchive iar(from_ss);
  Object obj;
  iar >> obj;
  ret_obj.push_back(boost::make_shared<Object>(obj));

  /* get until end */
  while ((ret = cursorp->get(&db_key, &data, DB_NEXT)) == 0) {
    timestamp tmstmp;
    long id;
    char_to_key_lpid((char*) db_key.get_data(), tmstmp, id);
    if (tmstmp > to || id != lp_id) break;

    get_data_binary = std::string((char*) data.get_data(), data.get_size());
    std::stringstream ss;
    ss << get_data_binary;
    boost::archive::binary_iarchive iar(ss);
    Object deserialized_obj;
    iar >> deserialized_obj;
    ret_obj.push_back(boost::make_shared<Object>(deserialized_obj));
  }

  if (cursorp != NULL) cursorp->close();
};
void berkeleydb_store<Object>::get_prev(const timestamp& time,
                                        const long lp_id,
                                        obj_ptr& ret_obj,
                                        timestamp& time_of_ret) {
  boost::lock_guard<boost::mutex> guard(get_mutex_);
  /* generate key */
  std::vector<char> key;
  key_lpid_to_char(time, lp_id, key);
  Dbt db_key = Dbt(&key[0], key.size());

  /* prepare data */
  char* binary;
  Dbt data;
  data.set_data(binary);
  data.set_flags(DB_DBT_MALLOC);

  /* seek to key */
  Dbc* cursorp;
  db->cursor(NULL, &cursorp, 0);
  int ret = cursorp->get(&db_key, &data, DB_SET_RANGE);

  /* seek back */
  ret = cursorp->get(&db_key, &data, DB_PREV);

  /* get value */
  std::string obj_binary
      = std::string((char*) data.get_data(), data.get_size());
  std::stringstream ss;
  ss << obj_binary;
  boost::archive::binary_iarchive iar(ss);
  Object obj;
  iar >> obj;
  ret_obj = boost::make_shared<Object>(obj);

  /* get key */
  long lp_id_;
  char_to_key_lpid((char*) db_key.get_data(), time_of_ret, lp_id_);
  if (cursorp != NULL) cursorp->close();
};
Example #3
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;
}