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(); };
//############################################################################## //############################################################################## 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; }