From 4423d836f4ee628cad83866d373d499261cf99b5 Mon Sep 17 00:00:00 2001 From: An Tao Date: Mon, 18 May 2020 08:31:18 +0800 Subject: [PATCH] Add methods to get DbClient connection status (#436) --- lib/inc/drogon/HttpAppFramework.h | 5 +++++ lib/src/DbClientManager.h | 1 + lib/src/DbClientManagerSkipped.cc | 7 +++++++ lib/src/HttpAppFrameworkImpl.cc | 7 ++++++- lib/src/HttpAppFrameworkImpl.h | 2 ++ orm_lib/inc/drogon/orm/DbClient.h | 7 +++++++ orm_lib/src/DbClientImpl.cc | 6 ++++++ orm_lib/src/DbClientImpl.h | 3 ++- orm_lib/src/DbClientLockFree.cc | 5 +++++ orm_lib/src/DbClientLockFree.h | 1 + orm_lib/src/DbClientManager.cc | 19 +++++++++++++++++++ orm_lib/src/TransactionImpl.h | 4 ++++ orm_lib/tests/db_test.cc | 12 ++++++++++++ 13 files changed, 77 insertions(+), 2 deletions(-) diff --git a/lib/inc/drogon/HttpAppFramework.h b/lib/inc/drogon/HttpAppFramework.h index 12c28306..4a5541b8 100644 --- a/lib/inc/drogon/HttpAppFramework.h +++ b/lib/inc/drogon/HttpAppFramework.h @@ -1013,6 +1013,11 @@ class HttpAppFramework : public trantor::NonCopyable */ virtual orm::DbClientPtr getFastDbClient( const std::string &name = "default") = 0; + /** + * @brief Check if all database clients in the framework are available + * (connect to the database successfully). + */ + virtual bool areAllDbClientsAvailable() const noexcept = 0; /// Create a database client /** diff --git a/lib/src/DbClientManager.h b/lib/src/DbClientManager.h index 39586c8e..dc564775 100644 --- a/lib/src/DbClientManager.h +++ b/lib/src/DbClientManager.h @@ -52,6 +52,7 @@ class DbClientManager : public trantor::NonCopyable const std::string &filename, const std::string &name, const bool isFast); + bool areAllDbClientsAvailable() const noexcept; private: std::map dbClientsMap_; diff --git a/lib/src/DbClientManagerSkipped.cc b/lib/src/DbClientManagerSkipped.cc index e59b6836..033e9663 100644 --- a/lib/src/DbClientManagerSkipped.cc +++ b/lib/src/DbClientManagerSkipped.cc @@ -37,6 +37,13 @@ void DbClientManager::createDbClient(const std::string &dbType, const std::string &filename, const std::string &name, const bool isFast) +{ + LOG_FATAL << "No database is supported by drogon, please install the " + "database development library first."; + abort(); +} + +bool DbClientManager::areAllDbClientsAvailable() const noexcept { LOG_FATAL << "No database is supported by drogon, please install the " "database development library first."; diff --git a/lib/src/HttpAppFrameworkImpl.cc b/lib/src/HttpAppFrameworkImpl.cc index fb8ffd4d..c26d46e4 100644 --- a/lib/src/HttpAppFrameworkImpl.cc +++ b/lib/src/HttpAppFrameworkImpl.cc @@ -328,7 +328,7 @@ HttpAppFramework &HttpAppFrameworkImpl::setLogPath( if (access(logPath.c_str(), 0) != 0) #endif { - std::cerr << "Log path dose not exist!\n"; + std::cerr << "Log path does not exist!\n"; exit(1); } #ifdef _WIN32 @@ -943,3 +943,8 @@ HttpAppFramework &HttpAppFrameworkImpl::addALocation( filters); return *this; } + +bool HttpAppFrameworkImpl::areAllDbClientsAvailable() const noexcept +{ + return dbClientManagerPtr_->areAllDbClientsAvailable(); +} \ No newline at end of file diff --git a/lib/src/HttpAppFrameworkImpl.h b/lib/src/HttpAppFrameworkImpl.h index 9c26c6db..7e750c91 100644 --- a/lib/src/HttpAppFrameworkImpl.h +++ b/lib/src/HttpAppFrameworkImpl.h @@ -432,6 +432,8 @@ class HttpAppFrameworkImpl : public HttpAppFramework #endif } + virtual bool areAllDbClientsAvailable() const noexcept override; + private: virtual void registerHttpController( const std::string &pathPattern, diff --git a/orm_lib/inc/drogon/orm/DbClient.h b/orm_lib/inc/drogon/orm/DbClient.h index 9bfaffaa..c6ccd226 100644 --- a/orm_lib/inc/drogon/orm/DbClient.h +++ b/orm_lib/inc/drogon/orm/DbClient.h @@ -181,6 +181,13 @@ class DbClient : public trantor::NonCopyable virtual void newTransactionAsync( const std::function &)> &callback) = 0; + /** + * @brief Check if there is a connection successfully established. + * + * @return true + * @return false + */ + virtual bool hasAvailableConnections() const noexcept = 0; ClientType type() const { diff --git a/orm_lib/src/DbClientImpl.cc b/orm_lib/src/DbClientImpl.cc index 4444f87b..66b5348e 100644 --- a/orm_lib/src/DbClientImpl.cc +++ b/orm_lib/src/DbClientImpl.cc @@ -440,3 +440,9 @@ DbConnectionPtr DbClientImpl::newConnection(trantor::EventLoop *loop) // std::cout<<"newConn end"< lock(connectionsMutex_); + return (!readyConnections_.empty()) || (!busyConnections_.empty()); +} \ No newline at end of file diff --git a/orm_lib/src/DbClientImpl.h b/orm_lib/src/DbClientImpl.h index 67f9c595..60503c22 100644 --- a/orm_lib/src/DbClientImpl.h +++ b/orm_lib/src/DbClientImpl.h @@ -50,6 +50,7 @@ class DbClientImpl : public DbClient, virtual void newTransactionAsync( const std::function &)> &callback) override; + virtual bool hasAvailableConnections() const noexcept override; private: size_t connectionsNumber_; @@ -72,7 +73,7 @@ class DbClientImpl : public DbClient, const DbConnectionPtr &conn, std::function &)> &&callback); - std::mutex connectionsMutex_; + mutable std::mutex connectionsMutex_; std::unordered_set connections_; std::unordered_set readyConnections_; std::unordered_set busyConnections_; diff --git a/orm_lib/src/DbClientLockFree.cc b/orm_lib/src/DbClientLockFree.cc index 0ff11004..fe2cf047 100644 --- a/orm_lib/src/DbClientLockFree.cc +++ b/orm_lib/src/DbClientLockFree.cc @@ -434,3 +434,8 @@ DbConnectionPtr DbClientLockFree::newConnection() // std::cout<<"newConn end"< &)> &callback) override; + virtual bool hasAvailableConnections() const noexcept override; private: std::string connectionInfo_; diff --git a/orm_lib/src/DbClientManager.cc b/orm_lib/src/DbClientManager.cc index dca48c8c..10f79a2b 100644 --- a/orm_lib/src/DbClientManager.cc +++ b/orm_lib/src/DbClientManager.cc @@ -155,3 +155,22 @@ void DbClientManager::createDbClient(const std::string &dbType, #endif } } + +bool DbClientManager::areAllDbClientsAvailable() const noexcept +{ + for (auto const &pair : dbClientsMap_) + { + if (!(pair.second)->hasAvailableConnections()) + return false; + } + auto loop = trantor::EventLoop::getEventLoopOfCurrentThread(); + if (loop && loop->index() < app().getThreadNum()) + { + for (auto const &pair : dbFastClientsMap_) + { + if (!(*(pair.second))->hasAvailableConnections()) + return false; + } + } + return true; +} diff --git a/orm_lib/src/TransactionImpl.h b/orm_lib/src/TransactionImpl.h index 7925ad2e..da692913 100644 --- a/orm_lib/src/TransactionImpl.h +++ b/orm_lib/src/TransactionImpl.h @@ -38,6 +38,10 @@ class TransactionImpl : public Transaction, { commitCallback_ = commitCallback; } + virtual bool hasAvailableConnections() const noexcept override + { + return connectionPtr_->status() == ConnectStatus::Ok; + } private: DbConnectionPtr connectionPtr_; diff --git a/orm_lib/tests/db_test.cc b/orm_lib/tests/db_test.cc index 29c86172..3c3e412a 100644 --- a/orm_lib/tests/db_test.cc +++ b/orm_lib/tests/db_test.cc @@ -1937,13 +1937,25 @@ int main(int argc, char *argv[]) #if USE_POSTGRESQL auto postgre_client = DbClient::newPgClient( "host=127.0.0.1 port=5432 dbname=postgres user=postgres", 1); + while (!postgre_client->hasAvailableConnections()) + { + std::this_thread::sleep_for(1s); + } #endif #if USE_MYSQL auto mysql_client = DbClient::newMysqlClient("host=localhost port=3306 user=root", 1); + while (!mysql_client->hasAvailableConnections()) + { + std::this_thread::sleep_for(1s); + } #endif #if USE_SQLITE3 auto sqlite_client = DbClient::newSqlite3Client("filename=:memory:", 1); + while (!sqlite_client->hasAvailableConnections()) + { + std::this_thread::sleep_for(1s); + } #endif LOG_DEBUG << "start!"; std::this_thread::sleep_for(1s);