Commit fc93178e authored by Tien Thinh NGUYEN's avatar Tien Thinh NGUYEN

Add delay after each retry to establish the connection to the DB

parent 6d3d788e
......@@ -27,13 +27,18 @@
#define HEART_BEAT_TIMER 10
#define DB_CONNECTION_TIMER 1000
#define DB_CONNECTION_TIMER 10
#define _unused(x) ((void) (x))
#define U64_FMT "%" PRIu64
#define NNRF_NFM_BASE "/nnrf-nfm/"
#define UDR_NF_REGISTER_URL "/nf-instances/"
#define MAX_FIRST_CONNECTION_RETRY 300
#define MAX_CONNECTION_RETRY 3
#define NUDR_DR_BASE "/nudr-dr/"
#define NUDR_DR_AUTH_STATUS "authentication-status"
#define NUDR_DR_AUTH_SUBS "authentication-subscription"
......
......@@ -51,6 +51,11 @@ bool cassandra_db::initialize() {
return false;
}
//------------------------------------------------------------------------------
bool cassandra_db::connect(uint32_t num_retries) {
return true;
}
//------------------------------------------------------------------------------
bool cassandra_db::close_connection() {
return true;
......
......@@ -40,7 +40,7 @@ class cassandra_db : public database_wrapper<cassandra_db> {
virtual ~cassandra_db();
bool initialize();
bool connect(uint32_t num_retries);
bool close_connection();
bool insert_authentication_subscription(
......
......@@ -57,12 +57,28 @@ class database_wrapper : public database_wrapper_abstraction {
return derived->initialize();
}
bool connect(uint32_t num_retries) {
Logger::udr_app().debug(
"Establish the connection to the DB (from database_wrapper)");
auto derived = static_cast<DerivedT*>(this);
return derived->connect(num_retries);
}
bool close_connection() override {
Logger::udr_app().debug("Initialize from database_wrapper");
auto derived = static_cast<DerivedT*>(this);
return derived->close_connection();
}
void start_event_connection_handling() {
auto derived = static_cast<DerivedT*>(this);
return derived->start_event_connection_handling();
}
void trigger_connection_handling_procedure(uint64_t ms) {
auto derived = static_cast<DerivedT*>(this);
return derived->trigger_connection_handling_procedure(ms);
}
bool insert_authentication_subscription(
const std::string& id,
const oai::udr::model::AuthenticationSubscription&
......@@ -212,16 +228,6 @@ class database_wrapper : public database_wrapper_abstraction {
return derived->query_smf_select_data(ue_id, serving_plmn_id, json_data);
}
void start_event_connection_handling() {
auto derived = static_cast<DerivedT*>(this);
return derived->start_event_connection_handling();
}
void trigger_connection_handling_procedure(uint64_t ms) {
auto derived = static_cast<DerivedT*>(this);
return derived->trigger_connection_handling_procedure(ms);
}
protected:
};
} // namespace oai::udr::app
......
......@@ -41,25 +41,29 @@
#include "Snssai.h"
#include "logger.hpp"
#include "udr.h"
#include "udr_event.hpp"
namespace oai::udr::app {
class database_wrapper_abstraction {
public:
database_wrapper_abstraction(udr_event& ev) : m_event_sub(ev){};
database_wrapper_abstraction(){};
virtual ~database_wrapper_abstraction(){};
// virtual std::unique_ptr<database_wrapper_abstraction> clone() const = 0;
udr_event& m_event_sub;
/*
* Initialize the DB and establish the connection between UDR and the DB
* Initialize the DB
* @param void
* @return true if successful, otherwise return false
*/
virtual bool initialize() = 0;
/*
* Establish the connection between UDR and the DB
* @param [uint32_t] num_retries: Number of retires
* @return true if successful, otherwise return false
*/
virtual bool connect(uint32_t num_retries) = 0;
/*
* Close the connection established to the DB
* @param void
......@@ -67,6 +71,20 @@ class database_wrapper_abstraction {
*/
virtual bool close_connection() = 0;
/*
* Start event connection handling procedure
* @param [void]
* @return void
*/
virtual void start_event_connection_handling() = 0;
/*
* Trigger connection handling procedure (kind of NF Heartbeat)
* @param [uint64_t] ms:
* @return void
*/
virtual void trigger_connection_handling_procedure(uint64_t ms) = 0;
/*
* Insert a new item to the DB for the Authentication Subscription
* @param [const std::string&] id: UE Identity
......@@ -292,20 +310,6 @@ class database_wrapper_abstraction {
virtual bool query_smf_select_data(
const std::string& ue_id, const std::string& serving_plmn_id,
nlohmann::json& json_data) = 0;
/*
* Start event connection handling procedure
* @param [void]
* @return void
*/
virtual void start_event_connection_handling() = 0;
/*
* Trigger connection handling procedure (kind of NF Heartbeat)
* @param [uint64_t] ms:
* @return void
*/
virtual void trigger_connection_handling_procedure(uint64_t ms) = 0;
};
} // namespace oai::udr::app
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file db_connection_manager.cpp
\brief
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2022
\email:
*/
#include "db_connection_manager.hpp"
#include "logger.hpp"
#include "udr.h"
#include "udr_app.hpp"
using namespace oai::udr::config;
using namespace oai::udr::app;
using json = nlohmann::json;
extern udr_config udr_cfg;
//------------------------------------------------------------------------------
db_connection_manager::db_connection_manager(udr_event& ev) : m_event_sub(ev) {}
//---------------------------------------------------------------------------------------------
void db_connection_manager::start_event_connection_initialization(
std::shared_ptr<database_wrapper_abstraction>& db_connector) {
// get current time
uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
struct itimerspec its;
its.it_value.tv_sec = DB_CONNECTION_TIMER; // seconds
its.it_value.tv_nsec = 0; // 100 * 1000 * 1000; //100ms
const uint64_t interval =
its.it_value.tv_sec * 1000 +
its.it_value.tv_nsec / 1000000; // convert sec, nsec to msec
db_connection = m_event_sub.subscribe_task_db_connection_reset(
boost::bind(&udr_nrf::trigger_connection_reset_procedure, this, _1, _2),
db_connector, interval, ms + interval);
}
//---------------------------------------------------------------------------------------------
void db_connection_manager::trigger_connection_reset_procedure(
std::shared_ptr<database_wrapper_abstraction>& db_connector, uint64_t ms) {
_unused(ms);
// Close the current connection
db_connector.close_connection();
// and start a new one
db_connector.initialize();
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file db_connection_manager.hpp
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2022
\email:
*/
#ifndef FILE_DB_CONNECTION_MANAGER_SEEN
#define FILE_DB_CONNECTION_MANAGER_SEEN
#include "database_wrapper_abstraction.hpp"
#include "udr_event.hpp"
namespace oai {
namespace udr {
namespace app {
class db_connection_manager {
private:
public:
db_connection_manager(udr_event& ev);
db_connection_manager(db_connection_manager const&) = delete;
void operator=(db_connection_manager const&) = delete;
/*
* Start event connection initialization procedure
* @param [void]
* @return void
*/
void start_event_connection_initialization(
std::shared_ptr<database_wrapper_abstraction>& db_connector);
/*
* Trigger connection reset procedure (NF Heartbeat)
* @param [void]
* @return void
*/
void trigger_connection_reset_procedure(
uint64_t ms, std::shared_ptr<database_wrapper_abstraction>& db_connector);
private:
udr_event& m_event_sub;
bs2::connection task_connection;
bs2::connection db_connection;
};
} // namespace app
} // namespace udr
} // namespace oai
#endif /* FILE_DB_CONNECTION_MANAGER_SEEN */
......@@ -29,6 +29,9 @@
#include "mysql_db.hpp"
#include <chrono>
#include <thread>
#include "AccessAndMobilitySubscriptionData.h"
#include "AuthenticationSubscription.h"
#include "ProblemDetails.h"
......@@ -42,11 +45,15 @@ using namespace oai::udr::config;
extern udr_config udr_cfg;
//------------------------------------------------------------------------------
mysql_db::mysql_db(udr_event& ev) : database_wrapper<mysql_db>(ev) {}
mysql_db::mysql_db(udr_event& ev)
: database_wrapper<mysql_db>(), m_event_sub(ev) {
start_event_connection_handling();
}
//------------------------------------------------------------------------------
mysql_db::~mysql_db() {
if (db_connection.connected()) db_connection.disconnect();
close_connection();
}
//------------------------------------------------------------------------------
......@@ -57,6 +64,27 @@ bool mysql_db::initialize() {
throw std::runtime_error("Cannot initialize MySQL");
}
/*
int MAX_RETRY=3;
int i=0;
while (i < MAX_RETRY) {
if (!mysql_real_connect(
&mysql_connector, udr_cfg.mysql.mysql_server.c_str(),
udr_cfg.mysql.mysql_user.c_str(),
udr_cfg.mysql.mysql_pass.c_str(), udr_cfg.mysql.mysql_db.c_str(), 0, 0, 0)) {
Logger::udr_mysql().error(
"An error occurred while connecting to MySQL DB: %s, retry
...", mysql_error(&mysql_connector)); i++;
// throw std::runtime_error("Cannot connect to MySQL DB");
} else {
break;
}
}
if (i==MAX_RETRY){
throw std::runtime_error("Cannot connect to MySQL DB");
}
*/
/*
if (!mysql_real_connect(
&mysql_connector, udr_cfg.mysql.mysql_server.c_str(),
udr_cfg.mysql.mysql_user.c_str(), udr_cfg.mysql.mysql_pass.c_str(),
......@@ -66,6 +94,34 @@ bool mysql_db::initialize() {
mysql_error(&mysql_connector));
throw std::runtime_error("Cannot connect to MySQL DB");
}
*/
return true;
}
//------------------------------------------------------------------------------
bool mysql_db::connect(uint32_t num_retries) {
Logger::udr_mysql().debug("Connect to MySQL DB");
int i = 0;
while (i < num_retries) {
if (!mysql_real_connect(
&mysql_connector, udr_cfg.mysql.mysql_server.c_str(),
udr_cfg.mysql.mysql_user.c_str(), udr_cfg.mysql.mysql_pass.c_str(),
udr_cfg.mysql.mysql_db.c_str(), 0, 0, 0)) {
Logger::udr_mysql().error(
"An error occurred while connecting to MySQL DB: %s, retry ...",
mysql_error(&mysql_connector));
i++;
// throw std::runtime_error("Cannot connect to MySQL DB");
} else {
return true;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (i == num_retries) {
return false;
// throw std::runtime_error("Cannot connect to MySQL DB");
}
return true;
}
......@@ -77,7 +133,8 @@ bool mysql_db::close_connection() {
}
//---------------------------------------------------------------------------------------------
void mysql_db::start_event_connection_manager() {
void mysql_db::start_event_connection_handling() {
Logger::udr_mysql().debug("Start Event Connection Handling");
// get current time
uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
......@@ -89,26 +146,25 @@ void mysql_db::start_event_connection_manager() {
its.it_value.tv_sec * 1000 +
its.it_value.tv_nsec / 1000000; // convert sec, nsec to msec
db_connection = m_event_sub.subscribe_task_db_connection_manager(
boost::bind(
&mysql_db::trigger_connection_verification_procedure, this, _1),
db_connection = m_event_sub.subscribe_task_nf_heartbeat(
boost::bind(&mysql_db::trigger_connection_handling_procedure, this, _1),
interval, ms + interval);
}
//---------------------------------------------------------------------------------------------
void mysql_db::trigger_connection_verification_procedure(uint64_t ms) {
_unused(ms);
if (!mysql_real_connect(
&mysql_connector, udr_cfg.mysql.mysql_server.c_str(),
udr_cfg.mysql.mysql_user.c_str(), udr_cfg.mysql.mysql_pass.c_str(),
udr_cfg.mysql.mysql_db.c_str(), 0, 0, 0)) {
Logger::udr_mysql().error(
"An error occurred while connecting to MySQL DB: %s",
mysql_error(&mysql_connector));
// Reset the connection
void mysql_db::trigger_connection_handling_procedure(uint64_t ms) {
// _unused(ms);
Logger::udr_mysql().debug("Trigger Connection Handling procedure %ld", ms);
if (!connect(1)) {
Logger::udr_app().warn("Reset the connection and try again ...");
// If couldn't connect to the DB
// Reset the connection and try again
close_connection();
initialize();
if (!connect(1))
Logger::udr_app().warn("Could not establish the connection to the DB");
} else {
return;
}
}
......
......@@ -44,9 +44,12 @@ class mysql_db : public database_wrapper<mysql_db> {
virtual ~mysql_db();
bool initialize();
bool connect(uint32_t num_retries);
bool close_connection();
void start_event_connection_handling();
void trigger_connection_handling_procedure(uint64_t ms);
bool insert_authentication_subscription(
const std::string& id,
const oai::udr::model::AuthenticationSubscription&
......@@ -129,6 +132,7 @@ class mysql_db : public database_wrapper<mysql_db> {
private:
MYSQL mysql_connector;
bs2::connection db_connection;
udr_event& m_event_sub;
};
} // namespace oai::udr::app
......
......@@ -37,7 +37,6 @@
#include "mysql_db.hpp"
#include "udr_config.hpp"
#include "udr_nrf.hpp"
#include "db_connection_manager.hpp"
using namespace oai::udr::app;
using namespace oai::udr::model;
......@@ -46,7 +45,6 @@ using namespace oai::udr::config;
extern udr_app* udr_app_inst;
extern udr_config udr_cfg;
udr_nrf* udr_nrf_inst = nullptr;
db_connection_manager* db_connection_manager_inst = nullptr;
//------------------------------------------------------------------------------
udr_app::udr_app(const std::string& config_file, udr_event& ev)
......@@ -57,13 +55,18 @@ udr_app::udr_app(const std::string& config_file, udr_event& ev)
if (udr_cfg.db_type == DB_TYPE_CASSANDRA) {
db_connector = std::make_shared<cassandra_db>();
} else {
db_connector = std::make_shared<mysql_db>();
db_connector = std::make_shared<mysql_db>(ev);
}
if (!db_connector->initialize()) {
Logger::udr_app().error("Error when initializing a connection with DB");
return;
}
if (!db_connector->connect(MAX_FIRST_CONNECTION_RETRY)) {
Logger::udr_app().warn("Could not establish the connection to the DB");
}
// Register to NRF
if (udr_cfg.register_nrf) {
try {
......@@ -76,14 +79,6 @@ udr_app::udr_app(const std::string& config_file, udr_event& ev)
}
}
// DB Connection Manager
try {
db_connection_manager_inst = new db_connection_manager(ev);
Logger::udr_app().info("DB Connection Task Created ");
} catch (std::exception& e) {
Logger::udr_app().error("Cannot create DB Connection Task: %s", e.what());
throw;
}
Logger::udr_app().startup("Started");
}
......
......@@ -42,13 +42,3 @@ bs2::connection udr_event::subscribe_task_nf_heartbeat(
};
return task_tick.connect(f);
}
bs2::connection udr_event::subscribe_task_db_connection_reset(
const db_connection_sig_t::slot_type& sig,
std::shared_ptr<database_wrapper_abstraction>& db_connector,
uint64_t period, uint64_t start) {
auto f = [db_connector, period, start, sig](uint64_t t) {
if (t >= start && (t - start) % period == 0) sig(db_connector, t);
};
return db_connection_sig.connect(f);
}
......@@ -73,13 +73,13 @@ class udr_event {
* @param [uint64_t] start:
* @return void
*/
bs2::connection subscribe_task_db_connection_reset(
const db_connection_sig_t::slot_type& sig, uint64_t period,
uint64_t start = 0);
// bs2::connection subscribe_task_db_connection_reset(
// const db_connection_sig_t::slot_type& sig, uint64_t period,
// uint64_t start = 0);
private:
task_sig_t task_tick;
db_connection_sig_t db_connection_sig;
// db_connection_sig_t db_connection_sig;
};
} // namespace oai::udr::app
#endif
......@@ -43,9 +43,9 @@ typedef bs2::signal_type<
void(uint64_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
task_sig_t;
typedef bs2::signal_type<
void(uint64_t, std::shared_ptr<database_wrapper_abstraction>&),
bs2::keywords::mutex_type<bs2::dummy_mutex>>::type db_connection_sig_t;
// typedef bs2::signal_type<
// void(uint64_t, std::shared_ptr<database_wrapper_abstraction>&),
// bs2::keywords::mutex_type<bs2::dummy_mutex>>::type db_connection_sig_t;
} // namespace oai::udr::app
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment