stats: Replace POSIX semaphore with STL

This commit is contained in:
Eduardo Almeida
2021-12-15 21:33:25 +00:00
parent f4d296baaa
commit 9d9dfc71a5
5 changed files with 59 additions and 110 deletions

View File

@@ -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(

View File

@@ -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

View File

@@ -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);

View File

@@ -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<int> (cmd.size ()),
stmt, nullptr);
ret = CheckError (db, rc, cmd, false);
if (ret)
{
rc = sqlite3_prepare_v2 (db, cmd.c_str (),
static_cast<int> (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;
}

View File

@@ -22,7 +22,7 @@
#include "ns3/simple-ref-count.h"
#include <sqlite3.h>
#include <string>
#include <semaphore.h>
#include <mutex>
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