From 9d9dfc71a583022bdd290a2d99cd28b06eba603f Mon Sep 17 00:00:00 2001 From: Eduardo Almeida Date: Wed, 15 Dec 2021 21:33:25 +0000 Subject: [PATCH] stats: Replace POSIX semaphore with STL --- build-support/macros-and-definitions.cmake | 1 - src/stats/CMakeLists.txt | 14 +-- src/stats/model/sqlite-data-output.cc | 2 +- src/stats/model/sqlite-output.cc | 116 +++++++-------------- src/stats/model/sqlite-output.h | 36 ++++--- 5 files changed, 59 insertions(+), 110 deletions(-) diff --git a/build-support/macros-and-definitions.cmake b/build-support/macros-and-definitions.cmake index a53760fae..645cb2c0b 100644 --- a/build-support/macros-and-definitions.cmake +++ b/build-support/macros-and-definitions.cmake @@ -1138,7 +1138,6 @@ macro(process_options) check_include_file_cxx("stdlib.h" "HAVE_STDLIB_H") check_include_file_cxx("signal.h" "HAVE_SIGNAL_H") check_include_file_cxx("netpacket/packet.h" "HAVE_PACKETH") - check_include_file_cxx("semaphore.h" "HAVE_SEMAPHORE_H") check_function_exists("getenv" "HAVE_GETENV") configure_file( diff --git a/src/stats/CMakeLists.txt b/src/stats/CMakeLists.txt index a14d77271..e937b2415 100644 --- a/src/stats/CMakeLists.txt +++ b/src/stats/CMakeLists.txt @@ -4,26 +4,16 @@ set(sqlite_libraries) if(${ENABLE_SQLITE}) set(sqlite_sources model/sqlite-data-output.cc + model/sqlite-output.cc ) set(sqlite_headers model/sqlite-data-output.h + model/sqlite-output.h ) include_directories(${SQLite3_INCLUDE_DIRS}) set(sqlite_libraries ${SQLite3_LIBRARIES} ) - if(HAVE_SEMAPHORE_H) - list( - APPEND - sqlite_sources - model/sqlite-output.cc - ) - list( - APPEND - sqlite_headers - model/sqlite-output.h - ) - endif() endif() set(source_files diff --git a/src/stats/model/sqlite-data-output.cc b/src/stats/model/sqlite-data-output.cc index b0f544eb8..0d510558e 100644 --- a/src/stats/model/sqlite-data-output.cc +++ b/src/stats/model/sqlite-data-output.cc @@ -64,7 +64,7 @@ SqliteDataOutput::Output (DataCollector &dc) std::string run = dc.GetRunLabel (); bool res; - m_sqliteOut = new SQLiteOutput (m_dbFile, "ns-3-sqlite-data-output-sem"); + m_sqliteOut = new SQLiteOutput (m_dbFile); res = m_sqliteOut->SpinExec ("CREATE TABLE IF NOT EXISTS Experiments (run, experiment, strategy, input, description text)"); NS_ASSERT (res); diff --git a/src/stats/model/sqlite-output.cc b/src/stats/model/sqlite-output.cc index 6cb6a15ab..5844de5a0 100644 --- a/src/stats/model/sqlite-output.cc +++ b/src/stats/model/sqlite-output.cc @@ -27,8 +27,7 @@ namespace ns3 { NS_LOG_COMPONENT_DEFINE ("SQLiteOutput"); -SQLiteOutput::SQLiteOutput (const std::string &name, const std::string &semName) - : m_semName (semName) +SQLiteOutput::SQLiteOutput (const std::string &name) { int rc = sqlite3_open (name.c_str (), &m_db); NS_ABORT_MSG_UNLESS (rc == SQLITE_OK, "Failed to open DB"); @@ -59,14 +58,14 @@ bool SQLiteOutput::SpinExec (sqlite3_stmt *stmt) const { int rc = SpinExec (m_db, stmt); - return !CheckError (m_db, rc, "", nullptr, false); + return !CheckError (m_db, rc, "", false); } bool SQLiteOutput::WaitExec (const std::string &cmd) const { int rc = WaitExec (m_db, cmd); - return !CheckError (m_db, rc, cmd, nullptr, false); + return !CheckError (m_db, rc, cmd, false); } bool @@ -239,32 +238,18 @@ SQLiteOutput::WaitPrepare (sqlite3 *db, sqlite3_stmt **stmt, const std::string & { int rc; bool ret; - sem_t *sem = sem_open (m_semName.c_str (), O_CREAT, S_IRUSR | S_IWUSR, 1); - NS_ABORT_MSG_IF (sem == SEM_FAILED, - "FAILED to open system semaphore, errno: " << errno); + std::unique_lock lock {m_mutex}; - if (sem_wait (sem) == 0) + rc = sqlite3_prepare_v2 (db, cmd.c_str (), + static_cast (cmd.size ()), + stmt, nullptr); + + ret = CheckError (db, rc, cmd, false); + if (ret) { - rc = sqlite3_prepare_v2 (db, cmd.c_str (), - static_cast (cmd.size ()), - stmt, nullptr); - - ret = CheckError (db, rc, cmd, sem, false); - if (ret) - { - return rc; - } - - sem_post (sem); + return rc; } - else - { - NS_FATAL_ERROR ("Can't lock semaphore"); - } - - sem_close (sem); - sem = nullptr; return rc; } @@ -331,15 +316,10 @@ SQLiteOutput::Error (sqlite3 *db, const std::string &cmd) bool SQLiteOutput::CheckError (sqlite3 *db, int rc, const std::string &cmd, - sem_t *sem, bool hardExit) + bool hardExit) { if (rc != SQLITE_OK && rc != SQLITE_DONE) { - if (sem != nullptr) - { - sem_post (sem); - sem_close (sem); - } if (hardExit) { Error (db, cmd); @@ -360,21 +340,21 @@ SQLiteOutput::SpinExec (sqlite3 *db, const std::string &cmd) bool ret; int rc = SpinPrepare (db, &stmt, cmd); - ret = CheckError (db, rc, cmd, nullptr, false); + ret = CheckError (db, rc, cmd, false); if (ret) { return rc; } rc = SpinStep (stmt); - ret = CheckError (db, rc, cmd, nullptr, false); + ret = CheckError (db, rc, cmd, false); if (ret) { return rc; } rc = SpinFinalize (stmt); - CheckError (db, rc, cmd, nullptr, false); + CheckError (db, rc, cmd, false); return rc; } @@ -384,7 +364,7 @@ SQLiteOutput::SpinExec (sqlite3 *db, sqlite3_stmt *stmt) { bool ret; int rc = SpinStep (stmt); - ret = CheckError (db, rc, "", nullptr, false); + ret = CheckError (db, rc, "", false); if (ret) { return rc; @@ -400,31 +380,17 @@ SQLiteOutput::WaitExec (sqlite3 *db, sqlite3_stmt *stmt) const bool ret; int rc = SQLITE_ERROR; - sem_t *sem = sem_open (m_semName.c_str (), O_CREAT, S_IRUSR | S_IWUSR, 1); + std::unique_lock lock {m_mutex}; - NS_ABORT_MSG_IF (sem == SEM_FAILED, - "FAILED to open system semaphore, errno: " << errno); + rc = SpinStep (stmt); - if (sem_wait (sem) == 0) + ret = CheckError (db, rc, "", false); + if (ret) { - rc = SpinStep (stmt); - - ret = CheckError (db, rc, "", sem, false); - if (ret) - { - return rc; - } - - rc = SpinFinalize (stmt); - - sem_post (sem); - } - else - { - NS_FATAL_ERROR ("Can't lock system semaphore"); + return rc; } - sem_close (sem); + rc = SpinFinalize (stmt); return rc; } @@ -436,34 +402,24 @@ SQLiteOutput::WaitExec (sqlite3 *db, const std::string &cmd) const bool ret; int rc = SQLITE_ERROR; - sem_t *sem = sem_open (m_semName.c_str (), O_CREAT, S_IRUSR | S_IWUSR, 1); + std::unique_lock lock {m_mutex}; - NS_ABORT_MSG_IF (sem == SEM_FAILED, - "FAILED to open system semaphore, errno: " << errno); - - if (sem_wait (sem) == 0) + rc = SpinPrepare (db, &stmt, cmd); + ret = CheckError (db, rc, cmd, false); + if (ret) { - rc = SpinPrepare (db, &stmt, cmd); - ret = CheckError (db, rc, cmd, sem, false); - if (ret) - { - return rc; - } - - rc = SpinStep (stmt); - - ret = CheckError (db, rc, cmd, sem, false); - if (ret) - { - return rc; - } - - rc = SpinFinalize (stmt); - - sem_post (sem); + return rc; } - sem_close (sem); + rc = SpinStep (stmt); + + ret = CheckError (db, rc, cmd, false); + if (ret) + { + return rc; + } + + rc = SpinFinalize (stmt); return rc; } diff --git a/src/stats/model/sqlite-output.h b/src/stats/model/sqlite-output.h index 69cd11f96..a459ad880 100644 --- a/src/stats/model/sqlite-output.h +++ b/src/stats/model/sqlite-output.h @@ -22,7 +22,7 @@ #include "ns3/simple-ref-count.h" #include #include -#include +#include namespace ns3 { @@ -34,7 +34,7 @@ namespace ns3 { * The class is able to execute commands, and retrieve results, from an SQLITE * database. The methods with the "Spin" prefix, in case of concurrent access * to the database, will spin until the operation is applied. The methods with - * the "Wait" prefix will wait on a system semaphore. + * the "Wait" prefix will wait on a mutex. * * If you run multiple simulations that write on the same database, it is * recommended to use the "Wait" prefixed methods. Otherwise, if the access to @@ -48,9 +48,9 @@ public: /** * \brief SQLiteOutput constructor * \param name database name - * \param semName system semaphore name */ - SQLiteOutput (const std::string &name, const std::string &semName); + SQLiteOutput (const std::string &name); + /** * Destructor */ @@ -78,22 +78,23 @@ public: * \return true in case of success */ bool SpinExec (sqlite3_stmt *stmt) const; + /** - * \brief Execute a command, waiting on a system semaphore + * \brief Execute a command, waiting on a mutex * \param cmd Command to be executed * \return true in case of success */ bool WaitExec (const std::string &cmd) const; /** - * \brief Execute a command, waiting on a system semaphore + * \brief Execute a command, waiting on a mutex * \param stmt Sqlite3 statement to be executed * \return true in case of success */ bool WaitExec (sqlite3_stmt *stmt) const; /** - * \brief Prepare a statement, waiting on a system semaphore + * \brief Prepare a statement, waiting on a mutex * \param stmt Sqlite statement * \param cmd Command to prepare inside the statement * \return true in case of success @@ -135,6 +136,7 @@ public: * \param stmt Statement * \return Sqlite error core */ + static int SpinStep (sqlite3_stmt *stmt); /** * \brief Finalize a statement until the result is ok or an error @@ -157,21 +159,23 @@ public: protected: /** - * \brief Execute a command, waiting on a system semaphore + * \brief Execute a command, waiting on a mutex * \param db Database * \param cmd Command * \return Sqlite error code */ int WaitExec (sqlite3 *db, const std::string &cmd) const; + /** - * \brief Execute a statement, waiting on a system semaphore + * \brief Execute a statement, waiting on a mutex * \param db Database * \param stmt Statement * \return Sqlite error code */ int WaitExec (sqlite3 *db, sqlite3_stmt *stmt) const; + /** - * \brief Prepare a statement, waiting on a system semaphore + * \brief Prepare a statement, waiting on a mutex * \param db Database * \param stmt Statement * \param cmd Command to prepare @@ -194,7 +198,7 @@ protected: * \return Sqlite error code */ static int SpinExec (sqlite3 *db, sqlite3_stmt *stmt); - + /** * \brief Preparing a command ignoring concurrency problems, retrying instead * \param db Database @@ -210,24 +214,24 @@ protected: * \param cmd Command */ [[ noreturn ]] static void Error (sqlite3 *db, const std::string &cmd); + /** * \brief Check any error in the db * \param db Database * \param rc Sqlite return code * \param cmd Command - * \param sem System semaphore * \param hardExit if true, will exit the program * \return true in case of error, false otherwise */ static bool CheckError (sqlite3 *db, int rc, const std::string &cmd, - sem_t *sem, bool hardExit); + bool hardExit); private: - std::string m_dBname; //!< Database name - std::string m_semName; //!< System semaphore name + std::string m_dBname; //!< Database name + mutable std::mutex m_mutex; //!< Mutex sqlite3 *m_db { nullptr - }; //!< Database pointer + }; //!< Database pointer }; } // namespace ns3