Initial commit of source code
This commit is contained in:
45
src/core/coreManager.cpp
Normal file
45
src/core/coreManager.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "coreManager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace core;
|
||||
//--------------------------------------------------------------
|
||||
/* Default constructor */
|
||||
CoreManager::CoreManager()
|
||||
{
|
||||
init();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default destructor */
|
||||
CoreManager::~CoreManager()
|
||||
{
|
||||
release();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get a reference to the application bus */
|
||||
dBus::Bus &CoreManager::getBus() const
|
||||
{
|
||||
return *m_bus;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Initialize the core manager (e.g., set up the bus, etc.) */
|
||||
void CoreManager::init()
|
||||
{
|
||||
// Initialize the application bus
|
||||
m_bus = make_unique<dBus::Bus>();
|
||||
|
||||
// Initialize other subsystems (e.g., logger, etc.)
|
||||
m_logger = make_unique<logger::Logger>(*m_bus);
|
||||
m_requirementManager = make_unique<requirementManager::RequirementManager>(*m_bus);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Release resources used by the core manager (e.g., clean up the bus, etc.) */
|
||||
void CoreManager::release()
|
||||
{
|
||||
// Clean up other subsystems (e.g., logger, etc.)
|
||||
m_requirementManager.reset();
|
||||
m_logger.reset();
|
||||
|
||||
// Clean up the application bus
|
||||
m_bus.reset();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
35
src/core/coreManager.h
Normal file
35
src/core/coreManager.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "logger/logger.h"
|
||||
#include "requirementManager/requirementManager.h"
|
||||
|
||||
#include <dBus/dBus.h>
|
||||
#include <memory>
|
||||
|
||||
namespace core
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class CoreManager
|
||||
{
|
||||
public:
|
||||
CoreManager(); // Default constructor
|
||||
virtual ~CoreManager(); // Default destructor
|
||||
CoreManager(const CoreManager &obj) = delete; // Copy constructor
|
||||
CoreManager(CoreManager &&obj) noexcept = delete; // Move constructor
|
||||
CoreManager &operator=(const CoreManager &obj) = delete; // Copy assignment operator
|
||||
CoreManager &operator=(CoreManager &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
[[nodiscard]] dBus::Bus &getBus() const; // Get a reference to the application bus
|
||||
|
||||
protected:
|
||||
std::unique_ptr<dBus::Bus> m_bus; // Application data bus
|
||||
|
||||
std::unique_ptr<logger::Logger> m_logger; // Application logger system
|
||||
std::unique_ptr<requirementManager::RequirementManager> m_requirementManager; // Requirement manager system
|
||||
|
||||
private:
|
||||
void init(); // Initialize the core manager (e.g., set up the bus, etc.)
|
||||
void release(); // Release resources used by the core manager (e.g., clean up the bus, etc.)
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace core
|
||||
172
src/core/logger/logger.cpp
Normal file
172
src/core/logger/logger.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "logger.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <syncstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace core::logger;
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
Logger::Logger(dBus::Bus &bus)
|
||||
: Node(bus)
|
||||
{
|
||||
// Initialize the log printing loop
|
||||
runPrintingLoop();
|
||||
|
||||
// Initialize the bus listener thread
|
||||
runBusListener();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default destructor */
|
||||
Logger::~Logger()
|
||||
{
|
||||
// Stop the bus listener thread if it's running
|
||||
stopBusListener();
|
||||
|
||||
// Stop the log printing loop if it's running
|
||||
stopPrintingLoop();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Run the loop that periodically prints log entries to the console */
|
||||
void Logger::runPrintingLoop()
|
||||
{
|
||||
/* Start the printing thread to periodically print log entries to the console.
|
||||
* The thread will continuously wait for messages and process them until a stop is requested */
|
||||
// clang-format off
|
||||
m_printingThread = std::jthread([this](const std::stop_token &stopToken)
|
||||
{
|
||||
while (!stopToken.stop_requested())
|
||||
{
|
||||
// Sleep for a short duration to avoid busy waiting and reduce CPU usage
|
||||
this_thread::sleep_for(100ms);
|
||||
|
||||
// Print the log entries after processing the message
|
||||
if (m_logEntries.timer.isElapsed(LOG_PRINT_INTERVAL, true))
|
||||
printLogEntries();
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Stop the log printing loop */
|
||||
void Logger::stopPrintingLoop()
|
||||
{
|
||||
// Stop printing thread loop
|
||||
m_printingThread.request_stop();
|
||||
|
||||
// Despite a jthread will automatically join in its destructor, we
|
||||
// can explicitly join here to ensure that the thread has finished
|
||||
// executing before the Logger object is destroyed.
|
||||
// This is especially important if the thread is still running and
|
||||
// may access resources that are being cleaned up in the destructor.
|
||||
// By joining the thread, we can ensure a clean shutdown of the Logger
|
||||
// and avoid potential issues with dangling threads or accessing invalid resources.
|
||||
if (m_printingThread.joinable())
|
||||
m_printingThread.join();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Print the log entries to the console */
|
||||
void Logger::printLogEntries()
|
||||
{
|
||||
// Move the log entries to a local variable and clear the
|
||||
// original vector to minimize the time the mutex is locked
|
||||
std::vector<std::string> logEntries;
|
||||
{
|
||||
scoped_lock lock(m_logEntries.mtx);
|
||||
logEntries = std::move(m_logEntries.entries);
|
||||
m_logEntries.entries.clear();
|
||||
}
|
||||
|
||||
for (const auto &entry : logEntries)
|
||||
{
|
||||
// Use osyncstream to ensure thread-safe output to the console
|
||||
std::osyncstream syncOut(std::cout);
|
||||
syncOut << entry << std::endl;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Process a log message received from the bus */
|
||||
void Logger::processUserMessage(const LogMessage_ptr &logMessage)
|
||||
{
|
||||
// Sanity check
|
||||
if (!logMessage)
|
||||
return;
|
||||
|
||||
// Add the log entry to the vector of log entries
|
||||
std::scoped_lock lock(m_logEntries.mtx);
|
||||
m_logEntries.entries.push_back(logMessage->toString());
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Process a system log message received from the bus */
|
||||
void Logger::processSystemMessage(const std::string &logMessage)
|
||||
{
|
||||
// Sanity check
|
||||
if (logMessage.empty())
|
||||
return;
|
||||
|
||||
// Add the log entry to the vector of log entries
|
||||
std::scoped_lock lock(m_logEntries.mtx);
|
||||
m_logEntries.entries.push_back(logMessage);
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Run the bus listener thread */
|
||||
void Logger::runBusListener()
|
||||
{
|
||||
// Subscribe to the bus in broadcast mode to receive all messages posted to the bus
|
||||
m_bus.subscribeToBroadcast(this);
|
||||
|
||||
/* Start the bus listener thread to process incoming messages related to requirements.
|
||||
* The thread will continuously wait for messages and process them until a stop is requested */
|
||||
// clang-format off
|
||||
m_busListenerThread = std::jthread([this](const std::stop_token &stopToken)
|
||||
{
|
||||
while (!stopToken.stop_requested())
|
||||
{
|
||||
// Wait for a message to be received
|
||||
syncWaitForMessage();
|
||||
|
||||
// Process all received messages
|
||||
while (getMessageCount() > 0)
|
||||
{
|
||||
auto message = popNextMessage();
|
||||
if (message)
|
||||
processMessageBus(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Stop the bus listener thread */
|
||||
void Logger::stopBusListener()
|
||||
{
|
||||
// Stop event thread loop
|
||||
m_busListenerThread.request_stop();
|
||||
|
||||
// Wake up event thread if waiting
|
||||
notifyMessageQueue();
|
||||
|
||||
// Join the bus listener thread to ensure it has finished
|
||||
// executing before the Logger object is destroyed
|
||||
if (m_busListenerThread.joinable())
|
||||
m_busListenerThread.join();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Process a message received from the bus */
|
||||
void Logger::processMessageBus(const Message_ptr &message)
|
||||
{
|
||||
// Check the message type and process accordingly
|
||||
const auto messageType = message->getMessageTypeID();
|
||||
|
||||
if (messageType == dBus::makeID("log.message"))
|
||||
{
|
||||
// Process log message
|
||||
processUserMessage(message->as<dBus::EventMessage<api::log::LogMessage>>());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Process system log message (for any other message type, we will log it as a system message)
|
||||
processSystemMessage(message->toString());
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
53
src/core/logger/logger.h
Normal file
53
src/core/logger/logger.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include <dBus/api/log.h>
|
||||
#include <dBus/dBus.h>
|
||||
#include <mutex>
|
||||
#include <sdi_toolBox/dateTime/timer.h>
|
||||
#include <thread>
|
||||
|
||||
namespace core::logger
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class Logger : public dBus::Node
|
||||
{
|
||||
static constexpr auto LOG_PRINT_INTERVAL = std::chrono::seconds{ 1 };
|
||||
|
||||
public:
|
||||
Logger() = delete; // Default constructor
|
||||
virtual ~Logger(); // Default destructor
|
||||
Logger(const Logger &obj) = delete; // Copy constructor
|
||||
Logger(Logger &&obj) noexcept = delete; // Move constructor
|
||||
Logger &operator=(const Logger &obj) = delete; // Copy assignment operator
|
||||
Logger &operator=(Logger &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
explicit Logger(dBus::Bus &bus); // Constructor
|
||||
|
||||
protected:
|
||||
struct
|
||||
{
|
||||
std::mutex mtx; // Mutex to protect access to the log entries vector
|
||||
sdi_toolBox::dateTime::Timer timer; // Timer to control the frequency of log printing
|
||||
std::vector<std::string> entries; // Vector to store log entries received from the bus
|
||||
} m_logEntries;
|
||||
|
||||
private:
|
||||
void runPrintingLoop(); // Run the loop that periodically prints log entries to the console
|
||||
void stopPrintingLoop(); // Stop the log printing loop
|
||||
void printLogEntries(); // Print the log entries to the console
|
||||
std::jthread m_printingThread; // Thread for printing log entries to the console
|
||||
|
||||
// Logger management
|
||||
using LogMessage_ptr = std::shared_ptr<dBus::EventMessage<api::log::LogMessage>>;
|
||||
void processUserMessage(const LogMessage_ptr &logMessage); // Process a log message received from the bus
|
||||
void processSystemMessage(const std::string &logMessage); // Process a system log message received from the bus
|
||||
|
||||
// dBus management
|
||||
using Message_ptr = std::shared_ptr<dBus::Message>;
|
||||
void runBusListener(); // Run the bus listener thread
|
||||
void stopBusListener(); // Stop the bus listener thread
|
||||
void processMessageBus(const Message_ptr &message); // Process a message received from the bus
|
||||
std::jthread m_busListenerThread; // Thread for listening to bus messages related to requirements
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace core::logger
|
||||
89
src/core/requirementManager/requirementManager.cpp
Normal file
89
src/core/requirementManager/requirementManager.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "requirementManager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace core::requirementManager;
|
||||
//--------------------------------------------------------------
|
||||
/* Constructor */
|
||||
RequirementManager::RequirementManager(dBus::Bus &bus)
|
||||
: Node(bus)
|
||||
{
|
||||
// Initialize the bus listener thread
|
||||
runBusListener();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Default destructor */
|
||||
RequirementManager::~RequirementManager()
|
||||
{
|
||||
// Stop the bus listener thread if it's running
|
||||
stopBusListener();
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Get the root requirement */
|
||||
api::requirement::Requirement &RequirementManager::getRootRequirement()
|
||||
{
|
||||
return m_rootRequirement;
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Run the bus listener thread */
|
||||
void RequirementManager::runBusListener()
|
||||
{
|
||||
// Subscribe to the bus for messages related to log entries
|
||||
subscribe(dBus::makeID("requirement.file.operation"));
|
||||
|
||||
/* Start the bus listener thread to process incoming messages related to requirements.
|
||||
* The thread will continuously wait for messages and process them until a stop is requested. */
|
||||
// clang-format off
|
||||
m_busListenerThread = std::jthread([this](const std::stop_token &stopToken)
|
||||
{
|
||||
while (!stopToken.stop_requested())
|
||||
{
|
||||
// Wait for a message to be received
|
||||
syncWaitForMessage();
|
||||
|
||||
// Process all received messages
|
||||
while (getMessageCount() > 0)
|
||||
{
|
||||
auto message = popNextMessage();
|
||||
if (message)
|
||||
processMessageBus(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Stop the bus listener thread */
|
||||
void RequirementManager::stopBusListener()
|
||||
{
|
||||
// Stop event thread loop
|
||||
m_busListenerThread.request_stop();
|
||||
|
||||
// Wake up event thread if waiting
|
||||
notifyMessageQueue();
|
||||
|
||||
/* No need to join the thread explicitly as std::jthread will
|
||||
* automatically join in its destructor.
|
||||
* Subscribe to the bus will be automatically cleaned up in the
|
||||
* Node destructor. */
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
/* Process a message received from the bus */
|
||||
void RequirementManager::processMessageBus(const Message_ptr &message)
|
||||
{
|
||||
const auto messageType = message->getMessageTypeID();
|
||||
switch (messageType)
|
||||
{
|
||||
case dBus::makeID("requirement.file.operation"):
|
||||
{
|
||||
// Process file operation request
|
||||
const auto requestMessage = message->as<dBus::RequestMessage<api::requirement::FileOperationEvent, void>>();
|
||||
if (!requestMessage)
|
||||
break;
|
||||
|
||||
requestMessage->responsePromise.set_exception(std::make_exception_ptr(std::runtime_error("Failed to process file operation request")));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------
|
||||
38
src/core/requirementManager/requirementManager.h
Normal file
38
src/core/requirementManager/requirementManager.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <api/requirement.h>
|
||||
#include <dBus/dBus.h>
|
||||
#include <thread>
|
||||
|
||||
namespace core::requirementManager
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
class RequirementManager : public dBus::Node
|
||||
{
|
||||
public:
|
||||
RequirementManager() = delete; // Default constructor
|
||||
virtual ~RequirementManager(); // Default destructor
|
||||
RequirementManager(const RequirementManager &obj) = delete; // Copy constructor
|
||||
RequirementManager(RequirementManager &&obj) noexcept = delete; // Move constructor
|
||||
RequirementManager &operator=(const RequirementManager &obj) = delete; // Copy assignment operator
|
||||
RequirementManager &operator=(RequirementManager &&obj) noexcept = delete; // Move assignment operator
|
||||
|
||||
explicit RequirementManager(dBus::Bus &bus); // Constructor
|
||||
|
||||
protected:
|
||||
// dBus::Bus &m_bus; // Reference to the application bus
|
||||
|
||||
api::requirement::Requirement m_rootRequirement;
|
||||
|
||||
private:
|
||||
api::requirement::Requirement &getRootRequirement(); // Get the root requirement
|
||||
|
||||
// dBus management
|
||||
using Message_ptr = std::shared_ptr<dBus::Message>;
|
||||
void runBusListener(); // Run the bus listener thread
|
||||
void stopBusListener(); // Stop the bus listener thread
|
||||
void processMessageBus(const Message_ptr &message); // Process a message received from the bus
|
||||
std::jthread m_busListenerThread; // Thread for listening to bus messages related to requirements
|
||||
};
|
||||
//--------------------------------------------------------------
|
||||
} // namespace core::requirementManager
|
||||
Reference in New Issue
Block a user