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 @@ ...@@ -27,13 +27,18 @@
#define HEART_BEAT_TIMER 10 #define HEART_BEAT_TIMER 10
#define DB_CONNECTION_TIMER 1000 #define DB_CONNECTION_TIMER 10
#define _unused(x) ((void) (x)) #define _unused(x) ((void) (x))
#define U64_FMT "%" PRIu64
#define NNRF_NFM_BASE "/nnrf-nfm/" #define NNRF_NFM_BASE "/nnrf-nfm/"
#define UDR_NF_REGISTER_URL "/nf-instances/" #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_BASE "/nudr-dr/"
#define NUDR_DR_AUTH_STATUS "authentication-status" #define NUDR_DR_AUTH_STATUS "authentication-status"
#define NUDR_DR_AUTH_SUBS "authentication-subscription" #define NUDR_DR_AUTH_SUBS "authentication-subscription"
......
...@@ -51,6 +51,11 @@ bool cassandra_db::initialize() { ...@@ -51,6 +51,11 @@ bool cassandra_db::initialize() {
return false; return false;
} }
//------------------------------------------------------------------------------
bool cassandra_db::connect(uint32_t num_retries) {
return true;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool cassandra_db::close_connection() { bool cassandra_db::close_connection() {
return true; return true;
......
...@@ -40,7 +40,7 @@ class cassandra_db : public database_wrapper<cassandra_db> { ...@@ -40,7 +40,7 @@ class cassandra_db : public database_wrapper<cassandra_db> {
virtual ~cassandra_db(); virtual ~cassandra_db();
bool initialize(); bool initialize();
bool connect(uint32_t num_retries);
bool close_connection(); bool close_connection();
bool insert_authentication_subscription( bool insert_authentication_subscription(
......
...@@ -57,12 +57,28 @@ class database_wrapper : public database_wrapper_abstraction { ...@@ -57,12 +57,28 @@ class database_wrapper : public database_wrapper_abstraction {
return derived->initialize(); 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 { bool close_connection() override {
Logger::udr_app().debug("Initialize from database_wrapper"); Logger::udr_app().debug("Initialize from database_wrapper");
auto derived = static_cast<DerivedT*>(this); auto derived = static_cast<DerivedT*>(this);
return derived->close_connection(); 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( bool insert_authentication_subscription(
const std::string& id, const std::string& id,
const oai::udr::model::AuthenticationSubscription& const oai::udr::model::AuthenticationSubscription&
...@@ -212,16 +228,6 @@ class database_wrapper : public database_wrapper_abstraction { ...@@ -212,16 +228,6 @@ class database_wrapper : public database_wrapper_abstraction {
return derived->query_smf_select_data(ue_id, serving_plmn_id, json_data); 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: protected:
}; };
} // namespace oai::udr::app } // namespace oai::udr::app
......
...@@ -41,25 +41,29 @@ ...@@ -41,25 +41,29 @@
#include "Snssai.h" #include "Snssai.h"
#include "logger.hpp" #include "logger.hpp"
#include "udr.h" #include "udr.h"
#include "udr_event.hpp"
namespace oai::udr::app { namespace oai::udr::app {
class database_wrapper_abstraction { class database_wrapper_abstraction {
public: public:
database_wrapper_abstraction(udr_event& ev) : m_event_sub(ev){}; database_wrapper_abstraction(){};
virtual ~database_wrapper_abstraction(){}; virtual ~database_wrapper_abstraction(){};
// virtual std::unique_ptr<database_wrapper_abstraction> clone() const = 0; // 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 * @param void
* @return true if successful, otherwise return false * @return true if successful, otherwise return false
*/ */
virtual bool initialize() = 0; 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 * Close the connection established to the DB
* @param void * @param void
...@@ -67,6 +71,20 @@ class database_wrapper_abstraction { ...@@ -67,6 +71,20 @@ class database_wrapper_abstraction {
*/ */
virtual bool close_connection() = 0; 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 * Insert a new item to the DB for the Authentication Subscription
* @param [const std::string&] id: UE Identity * @param [const std::string&] id: UE Identity
...@@ -292,20 +310,6 @@ class database_wrapper_abstraction { ...@@ -292,20 +310,6 @@ class database_wrapper_abstraction {
virtual bool query_smf_select_data( virtual bool query_smf_select_data(
const std::string& ue_id, const std::string& serving_plmn_id, const std::string& ue_id, const std::string& serving_plmn_id,
nlohmann::json& json_data) = 0; 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 } // 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 @@ ...@@ -29,6 +29,9 @@
#include "mysql_db.hpp" #include "mysql_db.hpp"
#include <chrono>
#include <thread>
#include "AccessAndMobilitySubscriptionData.h" #include "AccessAndMobilitySubscriptionData.h"
#include "AuthenticationSubscription.h" #include "AuthenticationSubscription.h"
#include "ProblemDetails.h" #include "ProblemDetails.h"
...@@ -42,11 +45,15 @@ using namespace oai::udr::config; ...@@ -42,11 +45,15 @@ using namespace oai::udr::config;
extern udr_config udr_cfg; 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() { mysql_db::~mysql_db() {
if (db_connection.connected()) db_connection.disconnect(); if (db_connection.connected()) db_connection.disconnect();
close_connection();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -57,6 +64,27 @@ bool mysql_db::initialize() { ...@@ -57,6 +64,27 @@ bool mysql_db::initialize() {
throw std::runtime_error("Cannot initialize MySQL"); 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( if (!mysql_real_connect(
&mysql_connector, udr_cfg.mysql.mysql_server.c_str(), &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_user.c_str(), udr_cfg.mysql.mysql_pass.c_str(),
...@@ -66,6 +94,34 @@ bool mysql_db::initialize() { ...@@ -66,6 +94,34 @@ bool mysql_db::initialize() {
mysql_error(&mysql_connector)); mysql_error(&mysql_connector));
throw std::runtime_error("Cannot connect to MySQL DB"); 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; return true;
} }
...@@ -77,7 +133,8 @@ bool mysql_db::close_connection() { ...@@ -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 // get current time
uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>( uint64_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()) std::chrono::system_clock::now().time_since_epoch())
...@@ -89,26 +146,25 @@ void mysql_db::start_event_connection_manager() { ...@@ -89,26 +146,25 @@ void mysql_db::start_event_connection_manager() {
its.it_value.tv_sec * 1000 + its.it_value.tv_sec * 1000 +
its.it_value.tv_nsec / 1000000; // convert sec, nsec to msec its.it_value.tv_nsec / 1000000; // convert sec, nsec to msec
db_connection = m_event_sub.subscribe_task_db_connection_manager( db_connection = m_event_sub.subscribe_task_nf_heartbeat(
boost::bind( boost::bind(&mysql_db::trigger_connection_handling_procedure, this, _1),
&mysql_db::trigger_connection_verification_procedure, this, _1),
interval, ms + interval); interval, ms + interval);
} }
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
void mysql_db::trigger_connection_verification_procedure(uint64_t ms) { void mysql_db::trigger_connection_handling_procedure(uint64_t ms) {
_unused(ms); // _unused(ms);
Logger::udr_mysql().debug("Trigger Connection Handling procedure %ld", ms);
if (!mysql_real_connect(
&mysql_connector, udr_cfg.mysql.mysql_server.c_str(), if (!connect(1)) {
udr_cfg.mysql.mysql_user.c_str(), udr_cfg.mysql.mysql_pass.c_str(), Logger::udr_app().warn("Reset the connection and try again ...");
udr_cfg.mysql.mysql_db.c_str(), 0, 0, 0)) { // If couldn't connect to the DB
Logger::udr_mysql().error( // Reset the connection and try again
"An error occurred while connecting to MySQL DB: %s",
mysql_error(&mysql_connector));
// Reset the connection
close_connection(); close_connection();
initialize(); 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> { ...@@ -44,9 +44,12 @@ class mysql_db : public database_wrapper<mysql_db> {
virtual ~mysql_db(); virtual ~mysql_db();
bool initialize(); bool initialize();
bool connect(uint32_t num_retries);
bool close_connection(); bool close_connection();
void start_event_connection_handling();
void trigger_connection_handling_procedure(uint64_t ms);
bool insert_authentication_subscription( bool insert_authentication_subscription(
const std::string& id, const std::string& id,
const oai::udr::model::AuthenticationSubscription& const oai::udr::model::AuthenticationSubscription&
...@@ -129,6 +132,7 @@ class mysql_db : public database_wrapper<mysql_db> { ...@@ -129,6 +132,7 @@ class mysql_db : public database_wrapper<mysql_db> {
private: private:
MYSQL mysql_connector; MYSQL mysql_connector;
bs2::connection db_connection; bs2::connection db_connection;
udr_event& m_event_sub;
}; };
} // namespace oai::udr::app } // namespace oai::udr::app
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include "mysql_db.hpp" #include "mysql_db.hpp"
#include "udr_config.hpp" #include "udr_config.hpp"
#include "udr_nrf.hpp" #include "udr_nrf.hpp"
#include "db_connection_manager.hpp"
using namespace oai::udr::app; using namespace oai::udr::app;
using namespace oai::udr::model; using namespace oai::udr::model;
...@@ -45,8 +44,7 @@ using namespace oai::udr::config; ...@@ -45,8 +44,7 @@ using namespace oai::udr::config;
extern udr_app* udr_app_inst; extern udr_app* udr_app_inst;
extern udr_config udr_cfg; extern udr_config udr_cfg;
udr_nrf* udr_nrf_inst = nullptr; 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) 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) ...@@ -57,13 +55,18 @@ udr_app::udr_app(const std::string& config_file, udr_event& ev)
if (udr_cfg.db_type == DB_TYPE_CASSANDRA) { if (udr_cfg.db_type == DB_TYPE_CASSANDRA) {
db_connector = std::make_shared<cassandra_db>(); db_connector = std::make_shared<cassandra_db>();
} else { } else {
db_connector = std::make_shared<mysql_db>(); db_connector = std::make_shared<mysql_db>(ev);
} }
if (!db_connector->initialize()) { if (!db_connector->initialize()) {
Logger::udr_app().error("Error when initializing a connection with DB"); Logger::udr_app().error("Error when initializing a connection with DB");
return; return;
} }
if (!db_connector->connect(MAX_FIRST_CONNECTION_RETRY)) {
Logger::udr_app().warn("Could not establish the connection to the DB");
}
// Register to NRF // Register to NRF
if (udr_cfg.register_nrf) { if (udr_cfg.register_nrf) {
try { try {
...@@ -76,14 +79,6 @@ udr_app::udr_app(const std::string& config_file, udr_event& ev) ...@@ -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"); Logger::udr_app().startup("Started");
} }
......
...@@ -42,13 +42,3 @@ bs2::connection udr_event::subscribe_task_nf_heartbeat( ...@@ -42,13 +42,3 @@ bs2::connection udr_event::subscribe_task_nf_heartbeat(
}; };
return task_tick.connect(f); 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 { ...@@ -73,13 +73,13 @@ class udr_event {
* @param [uint64_t] start: * @param [uint64_t] start:
* @return void * @return void
*/ */
bs2::connection subscribe_task_db_connection_reset( // bs2::connection subscribe_task_db_connection_reset(
const db_connection_sig_t::slot_type& sig, uint64_t period, // const db_connection_sig_t::slot_type& sig, uint64_t period,
uint64_t start = 0); // uint64_t start = 0);
private: private:
task_sig_t task_tick; task_sig_t task_tick;
db_connection_sig_t db_connection_sig; // db_connection_sig_t db_connection_sig;
}; };
} // namespace oai::udr::app } // namespace oai::udr::app
#endif #endif
...@@ -43,9 +43,9 @@ typedef bs2::signal_type< ...@@ -43,9 +43,9 @@ typedef bs2::signal_type<
void(uint64_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type void(uint64_t), bs2::keywords::mutex_type<bs2::dummy_mutex>>::type
task_sig_t; task_sig_t;
typedef bs2::signal_type< // typedef bs2::signal_type<
void(uint64_t, std::shared_ptr<database_wrapper_abstraction>&), // void(uint64_t, std::shared_ptr<database_wrapper_abstraction>&),
bs2::keywords::mutex_type<bs2::dummy_mutex>>::type db_connection_sig_t; // bs2::keywords::mutex_type<bs2::dummy_mutex>>::type db_connection_sig_t;
} // namespace oai::udr::app } // namespace oai::udr::app
#endif #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