Back to C++20 standard!
Logging is worked (AdcOstreamLogger and AdcSPDLOGLogger classes)
This commit is contained in:
parent
05e0055193
commit
78a9e53d18
@ -4,7 +4,7 @@ project(ADC LANGUAGES CXX)
|
|||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
# set(CMAKE_BUILD_TYPE Release)
|
# set(CMAKE_BUILD_TYPE Release)
|
||||||
|
|
||||||
@ -12,21 +12,21 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
# check compiler version to ensure supporting of
|
# check compiler version to ensure supporting of
|
||||||
# 'deducing this' C++23 feature
|
# 'deducing this' C++23 feature
|
||||||
#
|
#
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
# if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0)
|
# if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0)
|
||||||
message(FATAL_ERROR "GCC version must be at least 14.0!")
|
# message(FATAL_ERROR "GCC version must be at least 14.0!")
|
||||||
endif()
|
# endif()
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
# elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
|
# if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
|
||||||
message(FATAL_ERROR "Clang version must be at least 18.0!")
|
# message(FATAL_ERROR "Clang version must be at least 18.0!")
|
||||||
endif()
|
# endif()
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
# elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.32")
|
# if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.32")
|
||||||
message(FATAL_ERROR "MSVC version must be at least 19.32")
|
# message(FATAL_ERROR "MSVC version must be at least 19.32")
|
||||||
endif()
|
# endif()
|
||||||
else()
|
# else()
|
||||||
message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang and GCC.")
|
# message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang and GCC.")
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -85,6 +85,7 @@ option(SPDLOG_LIBRARY "Use of SPDLOG library for logging" ON)
|
|||||||
|
|
||||||
if (SPDLOG_LIBRARY)
|
if (SPDLOG_LIBRARY)
|
||||||
find_package(spdlog REQUIRED)
|
find_package(spdlog REQUIRED)
|
||||||
|
find_package(fmt REQUIRED)
|
||||||
|
|
||||||
set(ADC_COMMON_HEADERS ${ADC_COMMON_HEADERS}
|
set(ADC_COMMON_HEADERS ${ADC_COMMON_HEADERS}
|
||||||
common/adc_spdlog.h
|
common/adc_spdlog.h
|
||||||
@ -199,6 +200,7 @@ if (BUILD_TESTS)
|
|||||||
add_test(VALUE_HOLDER ${DEVATTR_TEST_APP})
|
add_test(VALUE_HOLDER ${DEVATTR_TEST_APP})
|
||||||
add_test(NETMSG_TEST ${NETMSG_TEST_APP})
|
add_test(NETMSG_TEST ${NETMSG_TEST_APP})
|
||||||
add_test(ASIO_NETSRV_TEST ${ASIO_NETSERVER_TEST_APP})
|
add_test(ASIO_NETSRV_TEST ${ASIO_NETSERVER_TEST_APP})
|
||||||
|
target_link_libraries(${ASIO_NETSERVER_TEST_APP} PRIVATE fmt::fmt)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
endif(BUILD_TESTS)
|
endif(BUILD_TESTS)
|
||||||
|
|
||||||
|
|||||||
@ -24,10 +24,11 @@ public:
|
|||||||
|
|
||||||
typedef spdlog::level::level_enum loglevel_t;
|
typedef spdlog::level::level_enum loglevel_t;
|
||||||
|
|
||||||
AdcSPDLOGLogger(std::shared_ptr<spdlog::logger> logger,
|
template <traits::adc_input_char_range R = decltype(LOGGER_DEFAULT_FORMAT)>
|
||||||
const traits::adc_input_char_range auto& pattern = LOGGER_DEFAULT_FORMAT)
|
AdcSPDLOGLogger(std::shared_ptr<spdlog::logger> logger, const R& pattern = LOGGER_DEFAULT_FORMAT)
|
||||||
: _loggerSPtr(logger), _currentLogPattern(pattern)
|
: _loggerSPtr(logger), _currentLogPattern()
|
||||||
{
|
{
|
||||||
|
std::ranges::copy(pattern, std::back_inserter(_currentLogPattern));
|
||||||
_loggerSPtr->set_pattern(_currentLogPattern);
|
_loggerSPtr->set_pattern(_currentLogPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,45 +46,81 @@ public:
|
|||||||
return _loggerSPtr->level();
|
return _loggerSPtr->level();
|
||||||
}
|
}
|
||||||
|
|
||||||
void logMessage(loglevel_t level, std::string_view fmt, traits::formattable auto&&... args)
|
void logMessage(loglevel_t level, const std::string& msg)
|
||||||
{
|
{
|
||||||
_loggerSPtr->log(level, fmt, std::forward<decltype(args)>(args)...);
|
_loggerSPtr->log(level, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// specialized for given level methods
|
// specialized for given level methods
|
||||||
|
|
||||||
void logCritical(std::string_view fmt, traits::formattable auto&&... args)
|
void logCritical(const std::string& msg)
|
||||||
{
|
{
|
||||||
logMessage(spdlog::level::critical, fmt, std::forward<decltype(args)>(args)...);
|
logMessage(spdlog::level::critical, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logError(std::string_view fmt, traits::formattable auto&&... args)
|
void logError(const std::string& msg)
|
||||||
{
|
{
|
||||||
logMessage(spdlog::level::err, fmt, std::forward<decltype(args)>(args)...);
|
logMessage(spdlog::level::err, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logWarn(std::string_view fmt, traits::formattable auto&&... args)
|
void logWarn(const std::string& msg)
|
||||||
{
|
{
|
||||||
logMessage(spdlog::level::warn, fmt, std::forward<decltype(args)>(args)...);
|
logMessage(spdlog::level::warn, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logInfo(std::string_view fmt, traits::formattable auto&&... args)
|
void logInfo(const std::string& msg)
|
||||||
{
|
{
|
||||||
logMessage(spdlog::level::info, fmt, std::forward<decltype(args)>(args)...);
|
logMessage(spdlog::level::info, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logDebug(std::string_view fmt, traits::formattable auto&&... args)
|
void logDebug(const std::string& msg)
|
||||||
{
|
{
|
||||||
logMessage(spdlog::level::debug, fmt, std::forward<decltype(args)>(args)...);
|
logMessage(spdlog::level::debug, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logTrace(std::string_view fmt, traits::formattable auto&&... args)
|
void logTrace(const std::string& msg)
|
||||||
{
|
{
|
||||||
logMessage(spdlog::level::trace, fmt, std::forward<decltype(args)>(args)...);
|
logMessage(spdlog::level::trace, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... ArgTs>
|
||||||
|
void logCritical(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
_loggerSPtr->log(spdlog::level::critical, fmt, std::forward<ArgTs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... ArgTs>
|
||||||
|
void logError(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
_loggerSPtr->log(spdlog::level::err, fmt, std::forward<ArgTs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... ArgTs>
|
||||||
|
void logWarn(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
_loggerSPtr->log(spdlog::level::warn, fmt, std::forward<ArgTs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... ArgTs>
|
||||||
|
void logInfo(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
_loggerSPtr->log(spdlog::level::info, fmt, std::forward<ArgTs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... ArgTs>
|
||||||
|
void logDebug(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
_loggerSPtr->log(spdlog::level::debug, fmt, std::forward<ArgTs>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... ArgTs>
|
||||||
|
void logTrace(std::format_string<ArgTs...> fmt, ArgTs&&... args)
|
||||||
|
{
|
||||||
|
_loggerSPtr->log(spdlog::level::trace, fmt, std::forward<ArgTs>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static constexpr size_t LOGGER_DEFAULT_FORMAT_MARK_POS = 21;
|
static constexpr size_t LOGGER_DEFAULT_FORMAT_MARK_POS = 20;
|
||||||
|
|
||||||
std::string _currentLogPattern;
|
std::string _currentLogPattern;
|
||||||
std::shared_ptr<spdlog::logger> _loggerSPtr;
|
std::shared_ptr<spdlog::logger> _loggerSPtr;
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <thread>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "../common/adc_traits.h"
|
#include "../common/adc_traits.h"
|
||||||
@ -453,6 +454,7 @@ namespace constants
|
|||||||
{
|
{
|
||||||
|
|
||||||
static constexpr char DEFAULT_CONVERTER_DELIMITER[] = " ";
|
static constexpr char DEFAULT_CONVERTER_DELIMITER[] = " ";
|
||||||
|
static constexpr char DEFAULT_CONVERTER_DELIMITER_COMA[] = ", ";
|
||||||
|
|
||||||
} // namespace constants
|
} // namespace constants
|
||||||
|
|
||||||
@ -676,6 +678,17 @@ static constexpr size_t AdcFNV1aHash(const R& r)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* current thread ID std::string representation */
|
||||||
|
|
||||||
|
static std::string AdcThisThreadId()
|
||||||
|
{
|
||||||
|
std::stringstream st;
|
||||||
|
st << std::this_thread::get_id();
|
||||||
|
|
||||||
|
return st.str();
|
||||||
|
}
|
||||||
|
|
||||||
/* std::basic_ostream based multithread-safe simple logger */
|
/* std::basic_ostream based multithread-safe simple logger */
|
||||||
|
|
||||||
template <typename CharT = char, typename CharTraitsT = std::char_traits<CharT>>
|
template <typename CharT = char, typename CharTraitsT = std::char_traits<CharT>>
|
||||||
@ -709,43 +722,37 @@ public:
|
|||||||
return _currentLogLevel;
|
return _currentLogLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <traits::formattable... Ts>
|
void logMessage(loglevel_t level, const std::string& msg)
|
||||||
void logMessage(loglevel_t level, std::string_view fmt, Ts&&... args)
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_logMutex);
|
std::lock_guard<std::mutex> lock(_logMutex);
|
||||||
|
|
||||||
if (_currentLogLevel < level)
|
if (_currentLogLevel < level)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string s;
|
|
||||||
std::format_to(std::back_inserter(s), fmt, std::forward<Ts>(args)...);
|
|
||||||
|
|
||||||
const std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
const std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||||
|
|
||||||
// format log-message in form:
|
// format log-message in form:
|
||||||
// [YYYY-MM-DD HH:MM:SS][level] log-message
|
// [YYYY-MM-DD HH:MM:SS][level] log-message
|
||||||
//
|
//
|
||||||
_logStream << std::put_time(std::localtime(&now), "[%F %T]") << "[" << LOGLEVEL_MARK[_currentLogLevel] << "] "
|
_logStream << std::put_time(std::localtime(&now), "[%F %T]") << "[" << LOGLEVEL_MARK[level] << "] " << msg
|
||||||
<< s;
|
<< "\n"
|
||||||
|
<< std::flush;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::formattable... Ts>
|
void logError(const std::string& msg)
|
||||||
void logError(std::string_view fmt, Ts&&... args)
|
|
||||||
{
|
{
|
||||||
logMessage(ERROR_LEVEL, fmt, std::forward<Ts>(args)...);
|
logMessage(ERROR_LEVEL, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <traits::formattable... Ts>
|
void logInfo(const std::string& msg)
|
||||||
void logInfo(std::string_view fmt, Ts&&... args)
|
|
||||||
{
|
{
|
||||||
logMessage(INFO_LEVEL, fmt, std::forward<Ts>(args)...);
|
logMessage(INFO_LEVEL, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <traits::formattable... Ts>
|
void logDebug(const std::string& msg)
|
||||||
void logDebug(std::string_view fmt, Ts&&... args)
|
|
||||||
{
|
{
|
||||||
logMessage(DEBUG_LEVEL, fmt, std::forward<Ts>(args)...);
|
logMessage(DEBUG_LEVEL, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include "adc_device_netmsg.h"
|
#include "adc_device_netmsg.h"
|
||||||
#include "adc_netserver.h"
|
#include "adc_netserver.h"
|
||||||
@ -105,11 +106,12 @@ namespace adc
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
template <typename IdentT = std::string>
|
template <typename IdentT = std::string, interfaces::adc_logger_c LoggerT = utils::AdcOstreamLogger<char>>
|
||||||
class AdcDeviceNetServer : public AdcGenericNetServer<IdentT>
|
class AdcDeviceNetServer : public AdcGenericNetServer<IdentT, LoggerT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using typename AdcGenericNetServer<IdentT>::server_ident_t;
|
using typename AdcGenericNetServer<IdentT, LoggerT>::server_ident_t;
|
||||||
|
using typename AdcGenericNetServer<IdentT, LoggerT>::logger_t;
|
||||||
|
|
||||||
// type for serialized data (attr/command ID, attr values etc...)
|
// type for serialized data (attr/command ID, attr values etc...)
|
||||||
typedef std::vector<char> serialized_t;
|
typedef std::vector<char> serialized_t;
|
||||||
@ -232,13 +234,15 @@ public:
|
|||||||
_recvTimeout(ctx.recvTimeout),
|
_recvTimeout(ctx.recvTimeout),
|
||||||
_sendTimeout(ctx.sendTimeout)
|
_sendTimeout(ctx.sendTimeout)
|
||||||
{
|
{
|
||||||
_serverPtr->logInfo("Create client session with ID = {} (addr = {})", _ident, (void*)this);
|
_serverPtr->logInfo("Create client session with ID = {} (addr = {}, thread = {})", _ident, (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual ~Session()
|
virtual ~Session()
|
||||||
{
|
{
|
||||||
_serverPtr->logInfo("Delete client session with ID = {} (addr = {})", _ident, (void*)this);
|
_serverPtr->logInfo("Delete client session with ID = {} (addr = {}, thread = {})", _ident, (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
}
|
}
|
||||||
|
|
||||||
netsession_ident_t ident() const
|
netsession_ident_t ident() const
|
||||||
@ -248,18 +252,22 @@ public:
|
|||||||
|
|
||||||
void start()
|
void start()
|
||||||
{
|
{
|
||||||
_serverPtr->logInfo("Start client session with ID = {} (addr = {})", _ident, (void*)this);
|
static bool first_time = true;
|
||||||
|
if (first_time) {
|
||||||
|
_serverPtr->logInfo("Start client session with ID = {} (addr = {}, thread = {})", _ident, (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
first_time = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
auto self(this->shared_from_this());
|
auto self(this->shared_from_this());
|
||||||
|
|
||||||
_netService.asyncReceive(
|
_netService.asyncReceive(
|
||||||
[self, this](netservice_t::async_callback_err_t ec, message_t msg) {
|
[self, this](netservice_t::async_callback_err_t ec, message_t msg) {
|
||||||
if (ec) {
|
if (ec) {
|
||||||
// std::string str("asyncReceive operation completed with error: ");
|
_serverPtr->logError(
|
||||||
// netservice_t::formatError(ec, str);
|
"asyncReceive operation completed with error: {} (session addr = {}, thread = {})",
|
||||||
// _serverPtr->errorMessage(str);
|
netservice_t::formattableError(ec), (void*)this, utils::AdcThisThreadId());
|
||||||
_serverPtr->logError("asyncReceive operation completed with error: {}",
|
|
||||||
netservice_t::formattableError(ec));
|
|
||||||
stop();
|
stop();
|
||||||
} else {
|
} else {
|
||||||
auto msg_sptr = std::make_shared<message_t>(std::move(msg));
|
auto msg_sptr = std::make_shared<message_t>(std::move(msg));
|
||||||
@ -272,11 +280,9 @@ public:
|
|||||||
*msg_sptr,
|
*msg_sptr,
|
||||||
[self, msg_sptr, this](netservice_t::async_callback_err_t ec) {
|
[self, msg_sptr, this](netservice_t::async_callback_err_t ec) {
|
||||||
if (ec) {
|
if (ec) {
|
||||||
// std::string str("asyncSend operation completed with error: ");
|
_serverPtr->logError(
|
||||||
// netservice_t::formatError(ec, str);
|
"asyncSend operation completed with error: {} (session addr = {}, thread = {})",
|
||||||
// _serverPtr->errorMessage(str);
|
netservice_t::formattableError(ec), (void*)this, utils::AdcThisThreadId());
|
||||||
_serverPtr->logError("asyncSend operation completed with error: {}",
|
|
||||||
netservice_t::formattableError(ec));
|
|
||||||
stop();
|
stop();
|
||||||
} else {
|
} else {
|
||||||
start();
|
start();
|
||||||
@ -290,7 +296,8 @@ public:
|
|||||||
|
|
||||||
void stop()
|
void stop()
|
||||||
{
|
{
|
||||||
_serverPtr->logInfo("Stop client session with ID = {} (addr = {})", _ident, (void*)this);
|
_serverPtr->logInfo("Stop client session with ID = {} (addr = {}, thread = {})", _ident, (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
|
||||||
_netService.close();
|
_netService.close();
|
||||||
}
|
}
|
||||||
@ -391,8 +398,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// using AdcGenericNetServer::AdcGenericNetServer;
|
using AdcGenericNetServer<IdentT, LoggerT>::AdcGenericNetServer;
|
||||||
AdcDeviceNetServer(const server_ident_t& id) : AdcGenericNetServer<IdentT>(id), _devices() {}
|
// AdcDeviceNetServer(const server_ident_t& id) : AdcGenericNetServer<IdentT>(id), _devices() {}
|
||||||
|
|
||||||
virtual ~AdcDeviceNetServer() = default;
|
virtual ~AdcDeviceNetServer() = default;
|
||||||
|
|
||||||
@ -406,6 +413,18 @@ public:
|
|||||||
CmdIdDeserialT&& cmd_id_deser_func = {}) // deserializer of command ID
|
CmdIdDeserialT&& cmd_id_deser_func = {}) // deserializer of command ID
|
||||||
{
|
{
|
||||||
auto id = std::forward<IdSerialT>(id_ser_func)(dev_ptr->ident());
|
auto id = std::forward<IdSerialT>(id_ser_func)(dev_ptr->ident());
|
||||||
|
|
||||||
|
if constexpr (traits::formattable<serialized_t>) {
|
||||||
|
this->logInfo("Add ADC device with ID: {} (addr = {}, thread = {})", id, (void*)dev_ptr,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
} else {
|
||||||
|
std::string s;
|
||||||
|
std::ranges::copy(id, std::back_inserter(s));
|
||||||
|
|
||||||
|
this->logInfo("Add ADC device with ID: {} (addr = {}, thread = {})", s, (void*)dev_ptr,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
}
|
||||||
|
|
||||||
_devices.try_emplace(dev_ptr, dev_ptr, id, std::forward<AttrIdDeserialT>(attr_id_deser_func),
|
_devices.try_emplace(dev_ptr, dev_ptr, id, std::forward<AttrIdDeserialT>(attr_id_deser_func),
|
||||||
std::forward<CmdIdDeserialT>(cmd_id_deser_func));
|
std::forward<CmdIdDeserialT>(cmd_id_deser_func));
|
||||||
|
|
||||||
@ -415,7 +434,25 @@ public:
|
|||||||
template <interfaces::adc_device_c DeviceT>
|
template <interfaces::adc_device_c DeviceT>
|
||||||
AdcDeviceNetServer& delDevice(DeviceT* dev_ptr)
|
AdcDeviceNetServer& delDevice(DeviceT* dev_ptr)
|
||||||
{
|
{
|
||||||
_devices.erase(dev_ptr);
|
auto it = _devices.find(dev_ptr);
|
||||||
|
if (it == _devices.end()) {
|
||||||
|
this->logError("Invalid ADC device pointer ({})! It seems the device was not added!", (void*)dev_ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (traits::formattable<serialized_t>) {
|
||||||
|
this->logInfo("Delete ADC device with ID: {} (addr = {}, thread = {})", it->ident(), (void*)dev_ptr,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
} else {
|
||||||
|
std::string s;
|
||||||
|
std::ranges::copy(it->ident(), std::back_inserter(s));
|
||||||
|
|
||||||
|
this->logInfo("Delete ADC device with ID: {} (addr = {}, thread = {})", s, (void*)dev_ptr,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
}
|
||||||
|
|
||||||
|
_devices.erase(it);
|
||||||
|
// _devices.erase(dev_ptr);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -118,12 +118,14 @@ concept adc_netservice_c = requires(SRVT srv, const SRVT srv_const) {
|
|||||||
// acceptor type
|
// acceptor type
|
||||||
requires std::is_class_v<typename SRVT::acceptor_t>;
|
requires std::is_class_v<typename SRVT::acceptor_t>;
|
||||||
requires adc_async_callback_t<typename SRVT::acceptor_t::async_accept_callback_t>;
|
requires adc_async_callback_t<typename SRVT::acceptor_t::async_accept_callback_t>;
|
||||||
requires requires(typename SRVT::acceptor_t acc) {
|
requires requires(typename SRVT::acceptor_t acc, const typename SRVT::acceptor_t acc_const) {
|
||||||
acc.asyncAccept(std::declval<typename SRVT::acceptor_t::async_accept_callback_t>(),
|
acc.asyncAccept(std::declval<typename SRVT::acceptor_t::async_accept_callback_t>(),
|
||||||
std::declval<const typename SRVT::timeout_t&>());
|
std::declval<const typename SRVT::timeout_t&>());
|
||||||
|
|
||||||
// { acc.accept(std::declval<const typename SRVT::timeout_t&>()) } -> std::same_as<SRVT>;
|
// { acc.accept(std::declval<const typename SRVT::timeout_t&>()) } -> std::same_as<SRVT>;
|
||||||
acc.accept(std::declval<const typename SRVT::timeout_t&>());
|
acc.accept(std::declval<const typename SRVT::timeout_t&>());
|
||||||
|
|
||||||
|
{ acc_const.localEndpoint() } -> traits::formattable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -160,6 +162,8 @@ concept adc_netservice_c = requires(SRVT srv, const SRVT srv_const) {
|
|||||||
|
|
||||||
srv.close();
|
srv.close();
|
||||||
|
|
||||||
|
{ srv_const.remoteEndpoint() } -> traits::formattable;
|
||||||
|
|
||||||
// // static method
|
// // static method
|
||||||
// SRVT::formatError(std::declval<typename SRVT::async_callback_err_t>(), std::declval<std::string&>());
|
// SRVT::formatError(std::declval<typename SRVT::async_callback_err_t>(), std::declval<std::string&>());
|
||||||
|
|
||||||
@ -224,7 +228,10 @@ concept adc_netsession_proto_c =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* LOGGER */
|
/* LOGGER:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
template <typename LOGGERT>
|
template <typename LOGGERT>
|
||||||
concept adc_logger_c = requires(LOGGERT log, const LOGGERT log_const) {
|
concept adc_logger_c = requires(LOGGERT log, const LOGGERT log_const) {
|
||||||
@ -234,22 +241,15 @@ concept adc_logger_c = requires(LOGGERT log, const LOGGERT log_const) {
|
|||||||
{ log_const.getLogLevel() } -> std::same_as<typename LOGGERT::loglevel_t>;
|
{ log_const.getLogLevel() } -> std::same_as<typename LOGGERT::loglevel_t>;
|
||||||
|
|
||||||
// logging method signature:
|
// logging method signature:
|
||||||
// void method(std::string_view fmt, traits::formattable auto&& args...)
|
// void method(loglevel_t level, traits::formattable auto&& args...)
|
||||||
|
|
||||||
log.logMessage(std::declval<typename LOGGERT::loglevel_t>(), std::declval<std::string_view>());
|
log.logMessage(std::declval<typename LOGGERT::loglevel_t>(), std::declval<std::string>());
|
||||||
log.logMessage(std::declval<typename LOGGERT::loglevel_t>(), std::declval<std::string_view>(),
|
|
||||||
std::declval<std::string>());
|
|
||||||
|
|
||||||
// logging method must accept at least the single argument - formatting string
|
// specialized logging methods signature:
|
||||||
log.logInfo(std::declval<std::string_view>());
|
|
||||||
// method must be defined at least for std::string as its argument
|
|
||||||
log.logInfo(std::declval<std::string_view>(), std::declval<std::string>());
|
|
||||||
|
|
||||||
log.logWarn(std::declval<std::string_view>());
|
log.logInfo(std::declval<std::string>());
|
||||||
log.logWarn(std::declval<std::string_view>(), std::declval<std::string>());
|
log.logDebug(std::declval<std::string>());
|
||||||
|
log.logError(std::declval<std::string>());
|
||||||
log.logError(std::declval<std::string_view>());
|
|
||||||
log.logError(std::declval<std::string_view>(), std::declval<std::string>());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,9 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#if __has_include(<unistd.h>) // POSIX
|
#if __has_include(<unistd.h>) // POSIX
|
||||||
@ -21,8 +21,10 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "../common/adc_utils.h"
|
||||||
#include "adc_net_concepts.h"
|
#include "adc_net_concepts.h"
|
||||||
|
|
||||||
|
|
||||||
namespace adc
|
namespace adc
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -30,87 +32,6 @@ namespace adc
|
|||||||
/* SOME USEFULL PRIVITIVES */
|
/* SOME USEFULL PRIVITIVES */
|
||||||
|
|
||||||
|
|
||||||
// A simple std::ostream logger
|
|
||||||
class AdcTrivialLogger
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~AdcTrivialLogger() = default;
|
|
||||||
|
|
||||||
// protected:
|
|
||||||
static constexpr std::string_view errorLevelMark{"error"};
|
|
||||||
static constexpr std::string_view warnLevelMark{"warning"};
|
|
||||||
static constexpr std::string_view infoLevelMark{"info"};
|
|
||||||
|
|
||||||
std::basic_ostream<char>& _stream;
|
|
||||||
|
|
||||||
AdcTrivialLogger(std::basic_ostream<char>& stream = std::cout) : _stream(stream) {}
|
|
||||||
|
|
||||||
template <traits::formattable... ArgTs>
|
|
||||||
std::string logMsgFormat(std::string_view level_mark, std::string_view fmt, ArgTs&&... args)
|
|
||||||
{
|
|
||||||
std::string s;
|
|
||||||
std::format_to(std::back_inserter(s), fmt, std::forward<ArgTs>(args)...);
|
|
||||||
|
|
||||||
std::stringstream st;
|
|
||||||
|
|
||||||
const std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
|
||||||
|
|
||||||
// format log-message in form:
|
|
||||||
// [YYYY-MM-DD HH:MM:SS][level] log-message
|
|
||||||
//
|
|
||||||
st << std::put_time(std::localtime(&now), "[%F %T]") << "[" << level_mark << "] " << s;
|
|
||||||
|
|
||||||
return st.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// define default logging function of ERROR, WARNING and INFO levels
|
|
||||||
template <traits::formattable... ArgTs>
|
|
||||||
void logError(this auto&& self, std::string_view fmt, ArgTs&&... args)
|
|
||||||
{
|
|
||||||
using obj_t = decltype(self);
|
|
||||||
|
|
||||||
if constexpr (std::same_as<std::remove_cvref_t<obj_t>, AdcTrivialLogger>) {
|
|
||||||
std::forward<obj_t>(self)._stream
|
|
||||||
<< std::forward<obj_t>(self).logMsgFormat(errorLevelMark, fmt, std::forward<ArgTs>(args)...) << "\n"
|
|
||||||
<< std::flush;
|
|
||||||
} else {
|
|
||||||
std::forward<obj_t>(self).logError(fmt, std::forward<ArgTs>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::formattable... ArgTs>
|
|
||||||
void logWarn(this auto&& self, std::string_view fmt, ArgTs&&... args)
|
|
||||||
{
|
|
||||||
using obj_t = decltype(self);
|
|
||||||
|
|
||||||
if constexpr (std::same_as<obj_t, AdcTrivialLogger>) {
|
|
||||||
std::forward<obj_t>(self)._stream
|
|
||||||
<< std::forward<obj_t>(self).logMsgFormat(warnLevelMark, fmt, std::forward<ArgTs>(args)...) << "\n"
|
|
||||||
<< std::flush;
|
|
||||||
} else {
|
|
||||||
std::forward<obj_t>(self).logWarn(fmt, std::forward<ArgTs>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <traits::formattable... ArgTs>
|
|
||||||
void logInfo(this auto&& self, std::string_view fmt, ArgTs&&... args)
|
|
||||||
{
|
|
||||||
using obj_t = decltype(self);
|
|
||||||
|
|
||||||
if constexpr (std::same_as<obj_t, AdcTrivialLogger>) {
|
|
||||||
std::forward<obj_t>(self)._stream
|
|
||||||
<< std::forward<obj_t>(self).logMsgFormat(infoLevelMark, fmt, std::forward<ArgTs>(args)...) << "\n"
|
|
||||||
<< std::flush;
|
|
||||||
} else {
|
|
||||||
std::forward<obj_t>(self).logInfo(fmt, std::forward<ArgTs>(args)...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static_assert(interfaces::adc_logger_c<AdcTrivialLogger>, "!!!!!!!!!!!");
|
|
||||||
|
|
||||||
// A generic implementation of POSIX OS daemon
|
// A generic implementation of POSIX OS daemon
|
||||||
class AdcPosixGenericDaemon
|
class AdcPosixGenericDaemon
|
||||||
{
|
{
|
||||||
@ -303,25 +224,39 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static_assert(interfaces::adc_logger_c<utils::AdcOstreamLogger<>>, "!!!!!");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* very generic network server */
|
/* very generic network server */
|
||||||
|
|
||||||
template <typename IdentT = std::string>
|
template <typename IdentT = std::string, interfaces::adc_logger_c LoggerT = utils::AdcOstreamLogger<char>>
|
||||||
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager, public AdcTrivialLogger
|
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager, public LoggerT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef IdentT server_ident_t;
|
typedef IdentT server_ident_t;
|
||||||
|
typedef LoggerT logger_t;
|
||||||
|
|
||||||
AdcGenericNetServer(const server_ident_t& id, std::basic_ostream<char>& log_stream = std::cout)
|
template <typename... LoggerCtorArgTs>
|
||||||
: AdcTrivialLogger(log_stream), _serverIdent(id)
|
AdcGenericNetServer(const server_ident_t& id, LoggerCtorArgTs&&... ctor_args)
|
||||||
|
: _serverIdent(id), LoggerT(std::forward<LoggerCtorArgTs>(ctor_args)...)
|
||||||
{
|
{
|
||||||
|
if constexpr (traits::formattable<IdentT>) {
|
||||||
|
logInfo("Create ADC generic network server with ID: {} (addr = {}, thread = {})", id, (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
} else {
|
||||||
|
logInfo("Create ADC generic network server (addr = {}, thread = {})", (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AdcGenericNetServer(const AdcGenericNetServer&) = delete;
|
AdcGenericNetServer(const AdcGenericNetServer&) = delete;
|
||||||
AdcGenericNetServer(AdcGenericNetServer&& other)
|
AdcGenericNetServer(AdcGenericNetServer&& other)
|
||||||
: AdcPosixGenericDaemon(std::move(other)), AdcNetSessionManager(std::move(other))
|
: AdcPosixGenericDaemon(std::move(other)), AdcNetSessionManager(std::move(other)), LoggerT(std::move(other))
|
||||||
{
|
{
|
||||||
|
logDebug("Move ADC server class: this = {}, target = {}", (void*)this, (void*)&other);
|
||||||
|
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -336,11 +271,22 @@ public:
|
|||||||
_moveCtorFunc = std::move(other._moveCtorFunc);
|
_moveCtorFunc = std::move(other._moveCtorFunc);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~AdcGenericNetServer() = default;
|
virtual ~AdcGenericNetServer()
|
||||||
|
{
|
||||||
|
if constexpr (traits::formattable<IdentT>) {
|
||||||
|
logInfo("Delete ADC generic network server with ID: {} (addr = {}, thread = {})", _serverIdent, (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
} else {
|
||||||
|
logInfo("Delete ADC generic network server (addr = {}, thread = {})", (void*)this,
|
||||||
|
utils::AdcThisThreadId());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
AdcGenericNetServer& operator=(const AdcGenericNetServer&) = delete;
|
AdcGenericNetServer& operator=(const AdcGenericNetServer&) = delete;
|
||||||
AdcGenericNetServer& operator=(AdcGenericNetServer&& other)
|
AdcGenericNetServer& operator=(AdcGenericNetServer&& other)
|
||||||
{
|
{
|
||||||
|
logDebug("Assign-move ADC server class: this = {}, target = {}", (void*)this, (void*)&other);
|
||||||
|
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
AdcPosixGenericDaemon::operator=(std::move(other));
|
AdcPosixGenericDaemon::operator=(std::move(other));
|
||||||
AdcNetSessionManager::operator=(std::move(other));
|
AdcNetSessionManager::operator=(std::move(other));
|
||||||
@ -369,6 +315,8 @@ public:
|
|||||||
void start(SessionT::netsession_ident_t id, SessionT::netsession_ctx_t sess_ctx, AcceptorCtorArgTs&&... ctor_args)
|
void start(SessionT::netsession_ident_t id, SessionT::netsession_ctx_t sess_ctx, AcceptorCtorArgTs&&... ctor_args)
|
||||||
requires traits::adc_hashable_c<typename SessionT::netsession_ident_t>
|
requires traits::adc_hashable_c<typename SessionT::netsession_ident_t>
|
||||||
{
|
{
|
||||||
|
logDebug("Call {}", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
if (!_isListening<SessionT>[this][id]) {
|
if (!_isListening<SessionT>[this][id]) {
|
||||||
auto acceptor = std::make_shared<typename SessionT::netservice_t::acceptor_t>(
|
auto acceptor = std::make_shared<typename SessionT::netservice_t::acceptor_t>(
|
||||||
std::forward<AcceptorCtorArgTs>(ctor_args)...);
|
std::forward<AcceptorCtorArgTs>(ctor_args)...);
|
||||||
@ -380,6 +328,16 @@ public:
|
|||||||
_isListening<SessionT>[inst][id] = false;
|
_isListening<SessionT>[inst][id] = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if constexpr (traits::formattable<typename SessionT::netsession_ident_t>) {
|
||||||
|
logInfo(
|
||||||
|
"Start listening for client connections at <{}> endpoint (session ID: {}, server addr = {}, thread "
|
||||||
|
"= {})",
|
||||||
|
acceptor->localEndpoint(), id, (void*)this, utils::AdcThisThreadId());
|
||||||
|
} else {
|
||||||
|
logInfo("Start listening for client connections at <{}> endpoint (server addr = {}, thread = {})",
|
||||||
|
acceptor->localEndpoint(), (void*)this, utils::AdcThisThreadId());
|
||||||
|
}
|
||||||
|
|
||||||
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,6 +371,30 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// helper methods for logging
|
||||||
|
template <traits::formattable... Ts>
|
||||||
|
void logMessage(LoggerT::loglevel_t level, std::format_string<Ts...> fmt, Ts&&... args)
|
||||||
|
{
|
||||||
|
LoggerT::logMessage(level, std::format(fmt, std::forward<Ts>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... Ts>
|
||||||
|
void logInfo(std::format_string<Ts...> fmt, Ts&&... args)
|
||||||
|
{
|
||||||
|
LoggerT::logInfo(std::format(fmt, std::forward<Ts>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... Ts>
|
||||||
|
void logDebug(std::format_string<Ts...> fmt, Ts&&... args)
|
||||||
|
{
|
||||||
|
LoggerT::logDebug(std::format(fmt, std::forward<Ts>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::formattable... Ts>
|
||||||
|
void logError(std::format_string<Ts...> fmt, Ts&&... args)
|
||||||
|
{
|
||||||
|
LoggerT::logError(std::format(fmt, std::forward<Ts>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// template <interfaces::adc_netsession_c SessionT>
|
// template <interfaces::adc_netsession_c SessionT>
|
||||||
@ -433,24 +415,22 @@ protected:
|
|||||||
acceptor->asyncAccept([acceptor, id = std::move(id), sess_ctx = std::move(sess_ctx), this](
|
acceptor->asyncAccept([acceptor, id = std::move(id), sess_ctx = std::move(sess_ctx), this](
|
||||||
auto ec, typename SessionT::netservice_t srv) mutable {
|
auto ec, typename SessionT::netservice_t srv) mutable {
|
||||||
if (!ec) {
|
if (!ec) {
|
||||||
|
logInfo(
|
||||||
|
"Client connection is succesfully accepted! Client endpoint: {} (server addr = {}, thread = {})",
|
||||||
|
srv.remoteEndpoint(), (void*)this, utils::AdcThisThreadId());
|
||||||
|
|
||||||
auto sess = std::make_shared<SessionT>(id, std::move(srv), sess_ctx);
|
auto sess = std::make_shared<SessionT>(id, std::move(srv), sess_ctx);
|
||||||
startSession(sess);
|
startSession(sess);
|
||||||
|
|
||||||
_isListening<SessionT>[this][id] = true;
|
_isListening<SessionT>[this][id] = true;
|
||||||
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||||
} else {
|
} else {
|
||||||
// std::string str{"Cannot start accepting connection: "};
|
|
||||||
// SessionT::netservice_t::formatError(ec, str);
|
|
||||||
// errorMessage(str);
|
|
||||||
|
|
||||||
this->logError("Cannot start accepting connection: {}", SessionT::netservice_t::formattableError(ec));
|
this->logError("Cannot start accepting connection: {}", SessionT::netservice_t::formattableError(ec));
|
||||||
|
|
||||||
_isListening<SessionT>[this][id] = false;
|
_isListening<SessionT>[this][id] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual void errorMessage(const std::string&) {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -14,20 +14,26 @@
|
|||||||
namespace adc::impl
|
namespace adc::impl
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename IdentT = std::string>
|
template <typename IdentT = std::string, interfaces::adc_logger_c LoggerT = utils::AdcOstreamLogger<char>>
|
||||||
class AdcDeviceNetServerASIO : public AdcDeviceNetServer<IdentT>
|
class AdcDeviceNetServerASIO : public AdcDeviceNetServer<IdentT, LoggerT>
|
||||||
{
|
{
|
||||||
typedef AdcDeviceNetServer<IdentT> base_t;
|
typedef AdcDeviceNetServer<IdentT, LoggerT> base_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using typename base_t::logger_t;
|
||||||
using typename base_t::server_ident_t;
|
using typename base_t::server_ident_t;
|
||||||
|
|
||||||
typedef std::string session_ident_t;
|
typedef std::string session_ident_t;
|
||||||
|
|
||||||
template <typename ServiceT>
|
template <typename ServiceT>
|
||||||
using Session = typename base_t::template Session<ServiceT, session_ident_t>;
|
using Session = typename base_t::template Session<ServiceT, session_ident_t>;
|
||||||
|
|
||||||
AdcDeviceNetServerASIO(const server_ident_t& id, asio::io_context& io_context)
|
template <typename... LoggerCtorArgTs>
|
||||||
: base_t(id), _ioContext(io_context), _stopSignal(io_context), _restartSignal(io_context)
|
AdcDeviceNetServerASIO(const server_ident_t& id, asio::io_context& io_context, LoggerCtorArgTs&&... ctor_args)
|
||||||
|
: base_t(id, std::forward<LoggerCtorArgTs>(ctor_args)...),
|
||||||
|
_ioContext(io_context),
|
||||||
|
_stopSignal(io_context),
|
||||||
|
_restartSignal(io_context)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +99,26 @@ public:
|
|||||||
requires(std::convertible_to<std::ranges::range_value_t<RST>, int> &&
|
requires(std::convertible_to<std::ranges::range_value_t<RST>, int> &&
|
||||||
std::convertible_to<std::ranges::range_value_t<RRT>, int>)
|
std::convertible_to<std::ranges::range_value_t<RRT>, int>)
|
||||||
{
|
{
|
||||||
|
auto sig_list = [](const auto& sig_range) {
|
||||||
|
std::string sgs;
|
||||||
|
#ifdef _GNU_SOURCE
|
||||||
|
std::vector<std::string> vsg;
|
||||||
|
|
||||||
|
std::ranges::transform(sig_range, std::back_inserter(vsg),
|
||||||
|
[](auto s) { return std::format("'{}'", sigdescr_np(s)); });
|
||||||
|
|
||||||
|
utils::AdcJoinRange(vsg, std::string_view(", "), sgs);
|
||||||
|
#else
|
||||||
|
sgs = utils::AdcDefaultValueConverter<utils::constants::DEFAULT_CONVERTER_DELIMITER_COMA>::serialize<
|
||||||
|
std::string>(sig_range);
|
||||||
|
#endif
|
||||||
|
return sgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
this->logDebug("Setup 'stop-server' signal to: {}", sig_list(stop_sig_num));
|
||||||
|
this->logDebug("Setup 'restart-server' signal to: {}", sig_list(restart_sig_num));
|
||||||
|
|
||||||
|
|
||||||
for (const int sig : stop_sig_num) {
|
for (const int sig : stop_sig_num) {
|
||||||
_stopSignal.add(sig);
|
_stopSignal.add(sig);
|
||||||
}
|
}
|
||||||
@ -119,6 +145,9 @@ public:
|
|||||||
{
|
{
|
||||||
_sessionRecvTimeout = recv_timeout;
|
_sessionRecvTimeout = recv_timeout;
|
||||||
_sessionSendTimeout = send_timeout;
|
_sessionSendTimeout = send_timeout;
|
||||||
|
|
||||||
|
this->logDebug("Set session timeouts: recv = {} msec, send = {} msec", _sessionRecvTimeout.count(),
|
||||||
|
_sessionSendTimeout.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -129,25 +158,41 @@ protected:
|
|||||||
std::chrono::milliseconds _sessionRecvTimeout = std::chrono::hours(12);
|
std::chrono::milliseconds _sessionRecvTimeout = std::chrono::hours(12);
|
||||||
std::chrono::milliseconds _sessionSendTimeout = std::chrono::seconds(5);
|
std::chrono::milliseconds _sessionSendTimeout = std::chrono::seconds(5);
|
||||||
|
|
||||||
|
void daemonize()
|
||||||
|
{
|
||||||
|
this->logInfo("Daemonize server process (server addr: {})", (void*)this);
|
||||||
|
|
||||||
|
base_t::daemonize();
|
||||||
|
}
|
||||||
|
|
||||||
// demonizing ASIO-related methods
|
// demonizing ASIO-related methods
|
||||||
virtual void daemonizePrepare()
|
virtual void daemonizePrepare()
|
||||||
{
|
{
|
||||||
|
this->logDebug("ASIO-related call of daemonizePrepare()");
|
||||||
|
|
||||||
_ioContext.notify_fork(asio::execution_context::fork_prepare);
|
_ioContext.notify_fork(asio::execution_context::fork_prepare);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void daemonizeFinalize()
|
virtual void daemonizeFinalize()
|
||||||
{
|
{
|
||||||
|
this->logDebug("ASIO-related call of daemonizeFinalize()");
|
||||||
|
|
||||||
_ioContext.notify_fork(asio::io_context::fork_child);
|
_ioContext.notify_fork(asio::io_context::fork_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void signalReceived(std::error_code, int signo)
|
virtual void signalReceived(std::error_code ec, int signo)
|
||||||
{
|
{
|
||||||
std::cout << "SIGNAL: " << signo << "\n";
|
#ifdef _GNU_SOURCE
|
||||||
|
this->logInfo("The server received the signal: '{}' (ec = {})", sigdescr_np(signo), ec.message());
|
||||||
|
#else
|
||||||
|
this->logInfo("The server received the signal: {} (ec = {})", signo, ec.message());
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void restart()
|
virtual void restart()
|
||||||
{
|
{
|
||||||
|
this->logInfo("Restart server (server addr: {})", (void*)this);
|
||||||
|
|
||||||
this->stopAllSessions();
|
this->stopAllSessions();
|
||||||
|
|
||||||
_restartSignal.async_wait([this](std::error_code ec, int signo) {
|
_restartSignal.async_wait([this](std::error_code ec, int signo) {
|
||||||
|
|||||||
@ -296,6 +296,15 @@ public:
|
|||||||
_acceptor.close(ec);
|
_acceptor.close(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string localEndpoint() const
|
||||||
|
{
|
||||||
|
std::stringstream st;
|
||||||
|
st << _acceptor.local_endpoint();
|
||||||
|
|
||||||
|
return st.str();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
asio::io_context& _ioContext;
|
asio::io_context& _ioContext;
|
||||||
srv_acceptor_t _acceptor;
|
srv_acceptor_t _acceptor;
|
||||||
@ -758,11 +767,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static void formatError(std::error_code err, std::string& result_str)
|
std::string remoteEndpoint() const
|
||||||
// {
|
{
|
||||||
// std::format_to(std::back_inserter(result_str), "{} (Err category: {}) (Err msg: {})", err.value(),
|
std::stringstream st;
|
||||||
// err.category().name(), err.message());
|
st << _socket.remote_endpoint();
|
||||||
// }
|
|
||||||
|
if (st.str().empty()) {
|
||||||
|
return "<local>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return st.str();
|
||||||
|
}
|
||||||
|
|
||||||
static std::string formattableError(std::error_code ec)
|
static std::string formattableError(std::error_code ec)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,6 +8,11 @@
|
|||||||
#include "../net/adc_netproto.h"
|
#include "../net/adc_netproto.h"
|
||||||
#include "../net/asio/adc_device_netserver_asio.h"
|
#include "../net/asio/adc_device_netserver_asio.h"
|
||||||
|
|
||||||
|
#ifdef USE_SPDLOG_LIBRARY
|
||||||
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||||
|
#include "../common/adc_spdlog.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef adc::impl::AdcDeviceNetServerASIO<std::string_view> server_t;
|
typedef adc::impl::AdcDeviceNetServerASIO<std::string_view> server_t;
|
||||||
typedef adc::AdcDeviceAttribute<std::string, server_t::serialized_t> attr_t;
|
typedef adc::AdcDeviceAttribute<std::string, server_t::serialized_t> attr_t;
|
||||||
|
|
||||||
@ -132,7 +137,17 @@ int main(int argc, char* argv[])
|
|||||||
asio::signal_set signals(io_ctx, SIGINT, SIGTERM);
|
asio::signal_set signals(io_ctx, SIGINT, SIGTERM);
|
||||||
signals.async_wait([&](std::error_code, int) { io_ctx.stop(); });
|
signals.async_wait([&](std::error_code, int) { io_ctx.stop(); });
|
||||||
|
|
||||||
adc::impl::AdcDeviceNetServerASIO server("TEST SRV", io_ctx);
|
using server_t = adc::impl::AdcDeviceNetServerASIO<std::string, adc::AdcSPDLOGLogger>;
|
||||||
|
std::shared_ptr<spdlog::logger> logger = spdlog::stdout_color_mt("console");
|
||||||
|
logger->set_level(spdlog::level::debug);
|
||||||
|
// server_t server("TEST SRV", io_ctx, logger, "[%Y-%m-%d %T.%e][%l]: %v");
|
||||||
|
server_t server("TEST SRV", io_ctx, logger);
|
||||||
|
|
||||||
|
// using server_t = adc::impl::AdcDeviceNetServerASIO<>;
|
||||||
|
// server_t server("TEST SRV", io_ctx);
|
||||||
|
// server.setLogLevel(server_t::logger_t::DEBUG_LEVEL);
|
||||||
|
|
||||||
|
|
||||||
server.setupSignals();
|
server.setupSignals();
|
||||||
|
|
||||||
server.addDevice(&dev1);
|
server.addDevice(&dev1);
|
||||||
@ -154,11 +169,11 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "try to start listenning at '" << ep << "' ...";
|
// std::cout << "try to start listenning at '" << ep << "' ...";
|
||||||
|
|
||||||
server.start<adc::AdcStopSeqSessionProto<>>(epn);
|
server.start<adc::AdcStopSeqSessionProto<>>(epn);
|
||||||
|
|
||||||
std::cout << "\tOK\n";
|
// std::cout << "\tOK\n";
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Unrecognized endpoint: '" << ep << "'! Ignore!\n";
|
std::cerr << "Unrecognized endpoint: '" << ep << "'! Ignore!\n";
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user