CMakeLists.txt: requires C++23 standard
CMakeLists.txt: add compiler version checks adc_netserver.h: add AdcTrivialLogger class (use of 'deduced this' feature of C++23 standard); AdcGenericNetServer class now has basic based on std::basic_ostream logging capability
This commit is contained in:
@@ -246,9 +246,11 @@ public:
|
||||
_netService.asyncReceive(
|
||||
[self, this](netservice_t::async_callback_err_t ec, message_t msg) {
|
||||
if (ec) {
|
||||
std::string str("asyncReceive operation completed with error: ");
|
||||
netservice_t::formatError(ec, str);
|
||||
_serverPtr->errorMessage(str);
|
||||
// std::string str("asyncReceive operation completed with error: ");
|
||||
// netservice_t::formatError(ec, str);
|
||||
// _serverPtr->errorMessage(str);
|
||||
_serverPtr->logError("asyncReceive operation completed with error: {}",
|
||||
netservice_t::formattableError(ec));
|
||||
stop();
|
||||
} else {
|
||||
auto msg_sptr = std::make_shared<message_t>(std::move(msg));
|
||||
@@ -261,9 +263,11 @@ public:
|
||||
*msg_sptr,
|
||||
[self, msg_sptr, this](netservice_t::async_callback_err_t ec) {
|
||||
if (ec) {
|
||||
std::string str("asyncSend operation completed with error: ");
|
||||
netservice_t::formatError(ec, str);
|
||||
_serverPtr->errorMessage(str);
|
||||
// std::string str("asyncSend operation completed with error: ");
|
||||
// netservice_t::formatError(ec, str);
|
||||
// _serverPtr->errorMessage(str);
|
||||
_serverPtr->logError("asyncSend operation completed with error: {}",
|
||||
netservice_t::formattableError(ec));
|
||||
stop();
|
||||
} else {
|
||||
start();
|
||||
|
||||
@@ -160,8 +160,11 @@ concept adc_netservice_c = requires(SRVT srv, const SRVT srv_const) {
|
||||
|
||||
srv.close();
|
||||
|
||||
// static method
|
||||
SRVT::formatError(std::declval<typename SRVT::async_callback_err_t>(), std::declval<std::string&>());
|
||||
// // static method
|
||||
// SRVT::formatError(std::declval<typename SRVT::async_callback_err_t>(), std::declval<std::string&>());
|
||||
|
||||
// convert given error to formattable (valid input to std::format) representation
|
||||
{ SRVT::formattableError(std::declval<typename SRVT::async_callback_err_t>()) } -> traits::formattable;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ ABSTRACT DEVICE COMPONENTS LIBRARY
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
@@ -28,7 +29,87 @@ namespace adc
|
||||
|
||||
/* SOME USEFULL PRIVITIVES */
|
||||
|
||||
// Ageneric implementation pf POSIX OS daemon
|
||||
|
||||
// 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)...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// A generic implementation of POSIX OS daemon
|
||||
class AdcPosixGenericDaemon
|
||||
{
|
||||
public:
|
||||
@@ -224,12 +305,15 @@ protected:
|
||||
/* very generic network server */
|
||||
|
||||
template <typename IdentT = std::string>
|
||||
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager
|
||||
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager, public AdcTrivialLogger
|
||||
{
|
||||
public:
|
||||
typedef IdentT server_ident_t;
|
||||
|
||||
AdcGenericNetServer(const server_ident_t& id) : _serverIdent(id) {}
|
||||
AdcGenericNetServer(const server_ident_t& id, std::basic_ostream<char>& log_stream = std::cout)
|
||||
: AdcTrivialLogger(log_stream), _serverIdent(id)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AdcGenericNetServer(const AdcGenericNetServer&) = delete;
|
||||
@@ -353,16 +437,18 @@ protected:
|
||||
_isListening<SessionT>[this][id] = true;
|
||||
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||
} else {
|
||||
std::string str{"Cannot start accepting connection: "};
|
||||
SessionT::netservice_t::formatError(ec, str);
|
||||
errorMessage(str);
|
||||
// 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));
|
||||
|
||||
_isListening<SessionT>[this][id] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
virtual void errorMessage(const std::string&) {};
|
||||
// virtual void errorMessage(const std::string&) {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -758,10 +758,19 @@ public:
|
||||
}
|
||||
|
||||
|
||||
static void formatError(std::error_code err, std::string& result_str)
|
||||
// static void formatError(std::error_code err, std::string& result_str)
|
||||
// {
|
||||
// std::format_to(std::back_inserter(result_str), "{} (Err category: {}) (Err msg: {})", err.value(),
|
||||
// err.category().name(), err.message());
|
||||
// }
|
||||
|
||||
static std::string formattableError(std::error_code ec)
|
||||
{
|
||||
std::format_to(std::back_inserter(result_str), "{} (Err category: {}) (Err msg: {})", err.value(),
|
||||
err.category().name(), err.message());
|
||||
std::string s;
|
||||
std::format_to(std::back_inserter(s), "{} (Err category: {}) (Err msg: {})", ec.value(), ec.category().name(),
|
||||
ec.message());
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user