stats: Replace POSIX semaphore with STL
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user