Auto reformatted the base, ref #470
This commit is contained in:
@@ -17,9 +17,9 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include "core/ILogger.hpp"
|
||||
@@ -59,8 +59,7 @@ namespace lms::core
|
||||
|
||||
static void BM_TraceLogger_Detailed_withArg(benchmark::State& state)
|
||||
{
|
||||
auto someExpensiveArgComputation{ []() -> std::string
|
||||
{
|
||||
auto someExpensiveArgComputation{ []() -> std::string {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds{ 1 });
|
||||
return "foo";
|
||||
} };
|
||||
@@ -77,6 +76,6 @@ namespace lms::core
|
||||
BENCHMARK(BM_TraceLogger_Detailed)->Threads(1)->Threads(std::thread::hardware_concurrency());
|
||||
BENCHMARK(BM_TraceLogger_Detailed_withArg)->Threads(1)->Threads(std::thread::hardware_concurrency());
|
||||
|
||||
}
|
||||
} // namespace lms::core
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <cassert>
|
||||
#include <cstring> // strerror
|
||||
#include <fstream>
|
||||
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
@@ -39,12 +40,14 @@ namespace lms::zip
|
||||
{
|
||||
public:
|
||||
FileException(const std::filesystem::path& p, std::string_view message)
|
||||
: Exception{ "File '" + p.string() + "': " + std::string {message} }
|
||||
{}
|
||||
: Exception{ "File '" + p.string() + "': " + std::string{ message } }
|
||||
{
|
||||
}
|
||||
|
||||
FileException(const std::filesystem::path& p, std::string_view message, int err)
|
||||
: Exception{ "File '" + p.string() + "': " + std::string {message} + ": " + ::strerror(err) }
|
||||
{}
|
||||
: Exception{ "File '" + p.string() + "': " + std::string{ message } + ": " + ::strerror(err) }
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ArchiveException : public Exception
|
||||
@@ -52,7 +55,8 @@ namespace lms::zip
|
||||
public:
|
||||
ArchiveException(struct ::archive* arch)
|
||||
: Exception{ getError(arch) }
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
static std::string_view getError(struct ::archive* arch)
|
||||
{
|
||||
@@ -88,19 +92,16 @@ namespace lms::zip
|
||||
if (!_archive)
|
||||
throw Exception{ "Cannot create archive control struct" };
|
||||
|
||||
auto archiveOpen{ [](struct ::archive*, void*)
|
||||
{
|
||||
auto archiveOpen{ [](struct ::archive*, void*) {
|
||||
return ARCHIVE_OK;
|
||||
} };
|
||||
|
||||
auto archiveWrite{ [](struct ::archive*, void* clientData, const void* buff, ::size_t n) -> la_ssize_t
|
||||
{
|
||||
ArchiveZipper* zipper {static_cast<ArchiveZipper*>(clientData)};
|
||||
auto archiveWrite{ [](struct ::archive*, void* clientData, const void* buff, ::size_t n) -> la_ssize_t {
|
||||
ArchiveZipper* zipper{ static_cast<ArchiveZipper*>(clientData) };
|
||||
return zipper->onWriteCallback(static_cast<const std::byte*>(buff), n);
|
||||
} };
|
||||
|
||||
auto archiveClose{ [](struct ::archive*, void*)
|
||||
{
|
||||
auto archiveClose{ [](struct ::archive*, void*) {
|
||||
return ARCHIVE_OK;
|
||||
} };
|
||||
|
||||
@@ -183,8 +184,7 @@ namespace lms::zip
|
||||
using std::filesystem::perms;
|
||||
::mode_t mode{};
|
||||
|
||||
auto testPerm{ [](perms p, perms permToTest)
|
||||
{
|
||||
auto testPerm{ [](perms p, perms permToTest) {
|
||||
return (p & permToTest) == permToTest;
|
||||
} };
|
||||
|
||||
@@ -295,4 +295,4 @@ namespace lms::zip
|
||||
|
||||
return bufferSize;
|
||||
}
|
||||
}
|
||||
} // namespace lms::zip
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
#include "core/IZipper.hpp"
|
||||
|
||||
extern "C"
|
||||
@@ -77,4 +78,4 @@ namespace lms::zip
|
||||
std::uint64_t _bytesWrittenInCurrentOutputStream{};
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace lms::zip
|
||||
@@ -19,21 +19,21 @@
|
||||
|
||||
#include "ChildProcess.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdexcept>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
@@ -47,13 +47,15 @@ namespace lms::core
|
||||
public:
|
||||
SystemException(int err, const std::string& errMsg)
|
||||
: ChildProcessException{ errMsg + ": " + ::strerror(err) }
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
SystemException(boost::system::error_code ec, const std::string& errMsg)
|
||||
: ChildProcessException{ errMsg + ": " + ec.message() }
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ChildProcess::ChildProcess(boost::asio::io_context& ioContext, const std::filesystem::path& path, const Args& args)
|
||||
: _ioContext{ ioContext }
|
||||
@@ -170,8 +172,7 @@ namespace lms::core
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Async read, bufferSize = " << bufferSize);
|
||||
|
||||
boost::asio::async_read(_childStdout, boost::asio::buffer(data, bufferSize),
|
||||
[this, callback{ std::move(callback) }](const boost::system::error_code& error, std::size_t bytesTransferred)
|
||||
{
|
||||
[this, callback{ std::move(callback) }](const boost::system::error_code& error, std::size_t bytesTransferred) {
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Async read cb - ec = '" << error.message() << "' (" << error.value() << "), bytesTransferred = " << bytesTransferred);
|
||||
|
||||
ReadResult readResult{ ReadResult::Success };
|
||||
@@ -206,4 +207,4 @@ namespace lms::core
|
||||
{
|
||||
return _finished;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -40,20 +40,20 @@ namespace lms::core
|
||||
ChildProcess(boost::asio::io_context& ioContext, const std::filesystem::path& path, const Args& args);
|
||||
|
||||
private:
|
||||
void asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback) override;
|
||||
std::size_t readSome(std::byte* data, std::size_t bufferSize) override;
|
||||
bool finished() const override;
|
||||
void asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback) override;
|
||||
std::size_t readSome(std::byte* data, std::size_t bufferSize) override;
|
||||
bool finished() const override;
|
||||
|
||||
void kill();
|
||||
bool wait(bool block); // return true if waited
|
||||
void kill();
|
||||
bool wait(bool block); // return true if waited
|
||||
|
||||
using FileDescriptor = boost::asio::posix::stream_descriptor;
|
||||
|
||||
boost::asio::io_context& _ioContext;
|
||||
FileDescriptor _childStdout;
|
||||
::pid_t _childPID{};
|
||||
bool _waited{};
|
||||
bool _finished{};
|
||||
std::optional<int> _exitCode;
|
||||
FileDescriptor _childStdout;
|
||||
::pid_t _childPID{};
|
||||
bool _waited{};
|
||||
bool _finished{};
|
||||
std::optional<int> _exitCode;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -39,4 +39,4 @@ namespace lms::core
|
||||
{
|
||||
return std::make_unique<ChildProcess>(_ioContext, path, args);
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -44,4 +44,4 @@ namespace lms::core
|
||||
|
||||
boost::asio::io_context& _ioContext;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -65,7 +65,7 @@ namespace lms::core
|
||||
{
|
||||
try
|
||||
{
|
||||
const libconfig::Setting& values{ _config.lookup(std::string {setting}) };
|
||||
const libconfig::Setting& values{ _config.lookup(std::string{ setting }) };
|
||||
for (int i{}; i < values.getLength(); ++i)
|
||||
_func(static_cast<const char*>(values[i]));
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace lms::core
|
||||
{
|
||||
try
|
||||
{
|
||||
const char* res{ _config.lookup(std::string {setting}) };
|
||||
const char* res{ _config.lookup(std::string{ setting }) };
|
||||
return std::filesystem::path{ std::string(res) };
|
||||
}
|
||||
catch (libconfig::ConfigException&)
|
||||
@@ -127,4 +127,4 @@ namespace lms::core
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -37,15 +37,14 @@ namespace lms::core
|
||||
Config& operator=(Config&&) = delete;
|
||||
|
||||
// Default values are returned in case of setting not found
|
||||
std::string_view getString(std::string_view setting, std::string_view def = "") override;
|
||||
void visitStrings(std::string_view setting, std::function<void(std::string_view)> _func, std::initializer_list<std::string_view> defs) override;
|
||||
std::filesystem::path getPath(std::string_view setting, const std::filesystem::path& def = std::filesystem::path()) override;
|
||||
unsigned long getULong(std::string_view setting, unsigned long def = 0) override;
|
||||
long getLong(std::string_view setting, long def = 0) override;
|
||||
bool getBool(std::string_view setting, bool def = false) override;
|
||||
std::string_view getString(std::string_view setting, std::string_view def = "") override;
|
||||
void visitStrings(std::string_view setting, std::function<void(std::string_view)> _func, std::initializer_list<std::string_view> defs) override;
|
||||
std::filesystem::path getPath(std::string_view setting, const std::filesystem::path& def = std::filesystem::path()) override;
|
||||
unsigned long getULong(std::string_view setting, unsigned long def = 0) override;
|
||||
long getLong(std::string_view setting, long def = 0) override;
|
||||
bool getBool(std::string_view setting, bool def = false) override;
|
||||
|
||||
private:
|
||||
|
||||
libconfig::Config _config;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -80,7 +80,7 @@ namespace lms
|
||||
|
||||
std::ostringstream contentRange;
|
||||
contentRange << "bytes " << startByte << "-"
|
||||
<< _beyondLastByte - 1 << "/" << fileSize;
|
||||
<< _beyondLastByte - 1 << "/" << fileSize;
|
||||
|
||||
response.addHeader("Content-Range", contentRange.str());
|
||||
response.setContentLength(_beyondLastByte - startByte);
|
||||
@@ -134,4 +134,4 @@ namespace lms
|
||||
LMS_LOG(UTILS, DEBUG, "Job complete!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace lms
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/IResourceHandler.hpp"
|
||||
|
||||
namespace lms
|
||||
@@ -33,13 +34,13 @@ namespace lms
|
||||
|
||||
private:
|
||||
Wt::Http::ResponseContinuation* processRequest(const Wt::Http::Request& request, Wt::Http::Response& response) override;
|
||||
void abort() override {};
|
||||
void abort() override{};
|
||||
|
||||
static constexpr std::size_t _chunkSize{ 262'144 };
|
||||
|
||||
std::filesystem::path _path;
|
||||
std::string _mimeType;
|
||||
::uint64_t _beyondLastByte{};
|
||||
::uint64_t _offset{};
|
||||
std::filesystem::path _path;
|
||||
std::string _mimeType;
|
||||
::uint64_t _beyondLastByte{};
|
||||
::uint64_t _offset{};
|
||||
};
|
||||
}
|
||||
} // namespace lms
|
||||
@@ -41,24 +41,23 @@ namespace lms::core
|
||||
threadName += std::to_string(i);
|
||||
}
|
||||
|
||||
_threads.emplace_back([this, threadName]
|
||||
_threads.emplace_back([this, threadName] {
|
||||
if (!threadName.empty())
|
||||
{
|
||||
if (!threadName.empty())
|
||||
{
|
||||
if (auto * traceLogger{ Service<tracing::ITraceLogger>::get() })
|
||||
traceLogger->setThreadName(std::this_thread::get_id(), threadName);
|
||||
}
|
||||
if (auto* traceLogger{ Service<tracing::ITraceLogger>::get() })
|
||||
traceLogger->setThreadName(std::this_thread::get_id(), threadName);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_ioService.run();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LMS_LOG(UTILS, FATAL, "Exception caught in IO context: " << e.what());
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
_ioService.run();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LMS_LOG(UTILS, FATAL, "Exception caught in IO context: " << e.what());
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +81,4 @@ namespace lms::core
|
||||
for (std::thread& t : _threads)
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -25,25 +25,44 @@ namespace lms::core::logging
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
case Module::API_SUBSONIC: return "API_SUBSONIC";
|
||||
case Module::AUTH: return "AUTH";
|
||||
case Module::AV: return "AV";
|
||||
case Module::CHILDPROCESS: return "CHILDPROC";
|
||||
case Module::COVER: return "COVER";
|
||||
case Module::DB: return "DB";
|
||||
case Module::DBUPDATER: return "DB UPDATER";
|
||||
case Module::FEATURE: return "FEATURE";
|
||||
case Module::FEEDBACK: return "FEEDBACK";
|
||||
case Module::HTTP: return "HTTP";
|
||||
case Module::MAIN: return "MAIN";
|
||||
case Module::METADATA: return "METADATA";
|
||||
case Module::REMOTE: return "REMOTE";
|
||||
case Module::SCROBBLING: return "SCROBBLING";
|
||||
case Module::SERVICE: return "SERVICE";
|
||||
case Module::RECOMMENDATION: return "RECOMMENDATION";
|
||||
case Module::TRANSCODING: return "TRANSCODING";
|
||||
case Module::UI: return "UI";
|
||||
case Module::UTILS: return "UTILS";
|
||||
case Module::API_SUBSONIC:
|
||||
return "API_SUBSONIC";
|
||||
case Module::AUTH:
|
||||
return "AUTH";
|
||||
case Module::AV:
|
||||
return "AV";
|
||||
case Module::CHILDPROCESS:
|
||||
return "CHILDPROC";
|
||||
case Module::COVER:
|
||||
return "COVER";
|
||||
case Module::DB:
|
||||
return "DB";
|
||||
case Module::DBUPDATER:
|
||||
return "DB UPDATER";
|
||||
case Module::FEATURE:
|
||||
return "FEATURE";
|
||||
case Module::FEEDBACK:
|
||||
return "FEEDBACK";
|
||||
case Module::HTTP:
|
||||
return "HTTP";
|
||||
case Module::MAIN:
|
||||
return "MAIN";
|
||||
case Module::METADATA:
|
||||
return "METADATA";
|
||||
case Module::REMOTE:
|
||||
return "REMOTE";
|
||||
case Module::SCROBBLING:
|
||||
return "SCROBBLING";
|
||||
case Module::SERVICE:
|
||||
return "SERVICE";
|
||||
case Module::RECOMMENDATION:
|
||||
return "RECOMMENDATION";
|
||||
case Module::TRANSCODING:
|
||||
return "TRANSCODING";
|
||||
case Module::UI:
|
||||
return "UI";
|
||||
case Module::UTILS:
|
||||
return "UTILS";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -52,11 +71,16 @@ namespace lms::core::logging
|
||||
{
|
||||
switch (sev)
|
||||
{
|
||||
case Severity::FATAL: return "fatal";
|
||||
case Severity::ERROR: return "error";
|
||||
case Severity::WARNING: return "warning";
|
||||
case Severity::INFO: return "info";
|
||||
case Severity::DEBUG: return "debug";
|
||||
case Severity::FATAL:
|
||||
return "fatal";
|
||||
case Severity::ERROR:
|
||||
return "error";
|
||||
case Severity::WARNING:
|
||||
return "warning";
|
||||
case Severity::INFO:
|
||||
return "info";
|
||||
case Severity::DEBUG:
|
||||
return "debug";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -66,7 +90,8 @@ namespace lms::core::logging
|
||||
, _module{ module }
|
||||
, _severity{ severity }
|
||||
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
@@ -78,4 +103,4 @@ namespace lms::core::logging
|
||||
{
|
||||
return _oss.str();
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
@@ -23,24 +23,24 @@
|
||||
|
||||
namespace std
|
||||
{
|
||||
std::size_t hash<boost::asio::ip::address>::operator()(const boost::asio::ip::address& ipAddr) const
|
||||
{
|
||||
if (ipAddr.is_v4())
|
||||
return ipAddr.to_v4().to_ulong();
|
||||
std::size_t hash<boost::asio::ip::address>::operator()(const boost::asio::ip::address& ipAddr) const
|
||||
{
|
||||
if (ipAddr.is_v4())
|
||||
return ipAddr.to_v4().to_ulong();
|
||||
|
||||
if (ipAddr.is_v6())
|
||||
{
|
||||
const auto& range {ipAddr.to_v6().to_bytes()};
|
||||
std::size_t res {};
|
||||
if (ipAddr.is_v6())
|
||||
{
|
||||
const auto& range{ ipAddr.to_v6().to_bytes() };
|
||||
std::size_t res{};
|
||||
|
||||
for (auto b : range)
|
||||
res ^= std::hash<char>{}(static_cast<char>(b));
|
||||
for (auto b : range)
|
||||
res ^= std::hash<char>{}(static_cast<char>(b));
|
||||
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
return std::hash<std::string>{}(ipAddr.to_string());
|
||||
}
|
||||
}
|
||||
return std::hash<std::string>{}(ipAddr.to_string());
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
#endif // BOOST_ASIO_HAS_STD_HASH
|
||||
|
||||
@@ -19,12 +19,11 @@
|
||||
|
||||
#include "core/Path.hpp"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
@@ -44,7 +43,7 @@ namespace lms::core::pathUtils
|
||||
{
|
||||
do
|
||||
{
|
||||
std::array<char, 1024> buffer;
|
||||
std::array<char, 1024> buffer;
|
||||
|
||||
ifs.read(buffer.data(), buffer.size());
|
||||
crc32.processBytes(reinterpret_cast<const std::byte*>(buffer.data()), ifs.gcount());
|
||||
@@ -69,7 +68,9 @@ namespace lms::core::pathUtils
|
||||
|
||||
Wt::WDateTime getLastWriteTime(const std::filesystem::path& file)
|
||||
{
|
||||
struct stat sb {};
|
||||
struct stat sb
|
||||
{
|
||||
};
|
||||
|
||||
if (stat(file.string().c_str(), &sb) == -1)
|
||||
throw LmsException("Failed to get stats on file '" + file.string() + "'");
|
||||
@@ -183,4 +184,4 @@ namespace lms::core::pathUtils
|
||||
|
||||
return longestCommonPath;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::pathUtils
|
||||
|
||||
@@ -35,4 +35,4 @@ namespace lms::core::random
|
||||
return RandGenerator{ seed };
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace lms::core::random
|
||||
@@ -131,4 +131,4 @@ namespace lms::core
|
||||
return _sharedCounts[thisThreadId] > 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -35,4 +35,4 @@ namespace lms::core::logging
|
||||
assert(isSeverityActive(log.getSeverity()));
|
||||
_os << std::this_thread::get_id() << " [" << getSeverityName(log.getSeverity()) << "] [" << getModuleName(log.getModule()) << "] " << log.getMessage() << std::endl;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
@@ -23,15 +23,14 @@
|
||||
#include <iomanip>
|
||||
#include <utility>
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/WDate.h>
|
||||
#include <Wt/WDateTime.h>
|
||||
|
||||
namespace lms::core::stringUtils
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
constexpr std::pair<char, std::string_view> jsEscapeChars[]
|
||||
{
|
||||
constexpr std::pair<char, std::string_view> jsEscapeChars[]{
|
||||
{ '\\', "\\\\" },
|
||||
{ '\n', "\\n" },
|
||||
{ '\r', "\\r" },
|
||||
@@ -40,8 +39,7 @@ namespace lms::core::stringUtils
|
||||
{ '\'', "\\\'" },
|
||||
};
|
||||
|
||||
constexpr std::pair<char, std::string_view> jsonEscapeChars[]
|
||||
{
|
||||
constexpr std::pair<char, std::string_view> jsonEscapeChars[]{
|
||||
{ '\\', "\\\\" },
|
||||
{ '\n', "\\n" },
|
||||
{ '\r', "\\r" },
|
||||
@@ -49,8 +47,8 @@ namespace lms::core::stringUtils
|
||||
{ '"', "\\\"" },
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
std::string escape(std::string_view str, const std::pair<char, std::string_view>(&charsToEscape)[N])
|
||||
template<std::size_t N>
|
||||
std::string escape(std::string_view str, const std::pair<char, std::string_view> (&charsToEscape)[N])
|
||||
{
|
||||
std::string escaped;
|
||||
escaped.reserve(str.length());
|
||||
@@ -70,12 +68,12 @@ namespace lms::core::stringUtils
|
||||
return escaped;
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
void writeEscapedString(std::ostream& os, std::string_view str, const std::pair<char, std::string_view>(&charsToEscape)[N])
|
||||
template<std::size_t N>
|
||||
void writeEscapedString(std::ostream& os, std::string_view str, const std::pair<char, std::string_view> (&charsToEscape)[N])
|
||||
{
|
||||
for (const char c : str)
|
||||
{
|
||||
auto itEntry{ std::find_if(std::cbegin(charsToEscape), std::cend(charsToEscape), [=](const auto& entry) { return entry.first == c;}) };
|
||||
auto itEntry{ std::find_if(std::cbegin(charsToEscape), std::cend(charsToEscape), [=](const auto& entry) { return entry.first == c; }) };
|
||||
if (itEntry != std::cend(charsToEscape))
|
||||
os << itEntry->second;
|
||||
else
|
||||
@@ -83,7 +81,7 @@ namespace lms::core::stringUtils
|
||||
}
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
template<typename StringType>
|
||||
std::string joinStrings(std::span<const StringType> strings, std::string_view delimiter)
|
||||
{
|
||||
std::string res;
|
||||
@@ -99,7 +97,7 @@ namespace lms::core::stringUtils
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
template<>
|
||||
std::optional<std::string> readAs(std::string_view str)
|
||||
@@ -198,7 +196,8 @@ namespace lms::core::stringUtils
|
||||
|
||||
for (char c : str)
|
||||
{
|
||||
if (escaped) {
|
||||
if (escaped)
|
||||
{
|
||||
current.push_back(c);
|
||||
escaped = false;
|
||||
}
|
||||
@@ -248,14 +247,14 @@ namespace lms::core::stringUtils
|
||||
std::string res;
|
||||
res.reserve(str.size());
|
||||
|
||||
std::transform(std::cbegin(str), std::cend(str), std::back_inserter(res), [](unsigned char c) { return std::tolower(c);});
|
||||
std::transform(std::cbegin(str), std::cend(str), std::back_inserter(res), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void stringToLower(std::string& str)
|
||||
{
|
||||
std::transform(std::cbegin(str), std::cend(str), std::begin(str), [](unsigned char c) { return std::tolower(c);});
|
||||
std::transform(std::cbegin(str), std::cend(str), std::begin(str), [](unsigned char c) { return std::tolower(c); });
|
||||
}
|
||||
|
||||
std::string stringToUpper(const std::string& str)
|
||||
@@ -263,7 +262,7 @@ namespace lms::core::stringUtils
|
||||
std::string res;
|
||||
res.reserve(str.size());
|
||||
|
||||
std::transform(std::cbegin(str), std::cend(str), std::back_inserter(res), [](char c) { return std::toupper(c);});
|
||||
std::transform(std::cbegin(str), std::cend(str), std::back_inserter(res), [](char c) { return std::toupper(c); });
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -436,4 +435,4 @@ namespace lms::core::stringUtils
|
||||
// assume UTC
|
||||
return date.toString("yyyy-MM-dd").toUTF8();
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::stringUtils
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
|
||||
@@ -32,7 +33,8 @@ namespace lms::core::tracing
|
||||
class CurrentThreadUnregisterer
|
||||
{
|
||||
public:
|
||||
CurrentThreadUnregisterer(TraceLogger* logger) : _logger{ logger } {}
|
||||
CurrentThreadUnregisterer(TraceLogger* logger)
|
||||
: _logger{ logger } {}
|
||||
~CurrentThreadUnregisterer()
|
||||
{
|
||||
if (_logger)
|
||||
@@ -45,7 +47,7 @@ namespace lms::core::tracing
|
||||
|
||||
TraceLogger* _logger;
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
thread_local TraceLogger::Buffer* TraceLogger::_currentBuffer{};
|
||||
|
||||
@@ -71,11 +73,11 @@ namespace lms::core::tracing
|
||||
LMS_LOG(UTILS, INFO, "TraceLogger: using " << _buffers.size() << " buffers. Buffer size = " << std::to_string(BufferSize) << ", entry size = " << sizeof(CompleteEventEntry) << ", entry count per buffer = " << Buffer::CompleteEventCount);
|
||||
|
||||
setMetadata("cpu_count", std::to_string(std::thread::hardware_concurrency()));
|
||||
setMetadata("build_type",
|
||||
setMetadata("build_type",
|
||||
#ifndef NDEBUG
|
||||
"debug"
|
||||
"debug"
|
||||
#else
|
||||
"release"
|
||||
"release"
|
||||
#endif
|
||||
);
|
||||
}
|
||||
@@ -182,7 +184,8 @@ namespace lms::core::tracing
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
os << ", " << std::endl;;
|
||||
os << ", " << std::endl;
|
||||
;
|
||||
|
||||
os << "\t\t{ ";
|
||||
os << "\"name\" : \"" << event.name << "\", ";
|
||||
@@ -297,4 +300,4 @@ namespace lms::core::tracing
|
||||
|
||||
return static_cast<std::uint32_t>(id);
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::tracing
|
||||
@@ -103,4 +103,4 @@ namespace lms::core::tracing
|
||||
|
||||
static thread_local Buffer* _currentBuffer;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::tracing
|
||||
@@ -31,13 +31,13 @@ namespace lms::core
|
||||
{
|
||||
namespace stringUtils
|
||||
{
|
||||
template <>
|
||||
template<>
|
||||
std::optional<UUID>
|
||||
readAs(std::string_view str)
|
||||
readAs(std::string_view str)
|
||||
{
|
||||
return UUID::fromString(str);
|
||||
}
|
||||
}
|
||||
} // namespace stringUtils
|
||||
namespace
|
||||
{
|
||||
bool stringIsUUID(std::string_view str)
|
||||
@@ -46,7 +46,7 @@ namespace lms::core
|
||||
|
||||
return std::regex_match(std::cbegin(str), std::cend(str), re);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
UUID::UUID(std::string_view str)
|
||||
: _value{ stringUtils::stringToLower(str) }
|
||||
@@ -68,9 +68,8 @@ namespace lms::core
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
auto concatRandomBytes{ [](std::ostream& os, std::size_t byteCount)
|
||||
{
|
||||
for (std::size_t i {}; i < byteCount; ++i)
|
||||
auto concatRandomBytes{ [](std::ostream& os, std::size_t byteCount) {
|
||||
for (std::size_t i{}; i < byteCount; ++i)
|
||||
os << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(random::getRandom<std::uint8_t>(0, 255));
|
||||
} };
|
||||
|
||||
@@ -88,4 +87,4 @@ namespace lms::core
|
||||
assert(uuid);
|
||||
return uuid.value();
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -19,10 +19,11 @@
|
||||
|
||||
#include "core/WtLogger.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <sstream>
|
||||
#include <Wt/WServer.h>
|
||||
#include <thread>
|
||||
|
||||
#include <Wt/WLogger.h>
|
||||
#include <Wt/WServer.h>
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
|
||||
@@ -36,7 +37,7 @@ namespace lms::core::logging
|
||||
oss << id;
|
||||
return oss.str();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
WtLogger::WtLogger(Severity minSeverity)
|
||||
: _minSeverity{ minSeverity }
|
||||
@@ -47,11 +48,16 @@ namespace lms::core::logging
|
||||
{
|
||||
switch (minSeverity)
|
||||
{
|
||||
case Severity::DEBUG: return "*";
|
||||
case Severity::INFO: return "* -debug";
|
||||
case Severity::WARNING: return "* -debug -info";
|
||||
case Severity::ERROR: return "* -debug -info -warning";
|
||||
case Severity::FATAL: return "* -debug -info -warning -error";
|
||||
case Severity::DEBUG:
|
||||
return "*";
|
||||
case Severity::INFO:
|
||||
return "* -debug";
|
||||
case Severity::WARNING:
|
||||
return "* -debug -info";
|
||||
case Severity::ERROR:
|
||||
return "* -debug -info -warning";
|
||||
case Severity::FATAL:
|
||||
return "* -debug -info -warning -error";
|
||||
}
|
||||
|
||||
throw LmsException{ "Unhandled severity" };
|
||||
@@ -66,4 +72,4 @@ namespace lms::core::logging
|
||||
{
|
||||
Wt::log(getSeverityName(log.getSeverity())) << Wt::WLogger::sep << to_string(std::this_thread::get_id()) << Wt::WLogger::sep << "[" << getModuleName(log.getModule()) << "]" << Wt::WLogger::sep << log.getMessage();
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
@@ -36,4 +36,4 @@ namespace lms::core::http
|
||||
{
|
||||
_sendQueue.sendRequest(std::make_unique<ClientRequest>(std::move(POSTParams)));
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::http
|
||||
@@ -19,11 +19,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/http/IClient.hpp"
|
||||
|
||||
#include "SendQueue.hpp"
|
||||
|
||||
namespace lms::core::http
|
||||
@@ -33,7 +34,8 @@ namespace lms::core::http
|
||||
public:
|
||||
Client(boost::asio::io_context& ioContext, std::string_view baseUrl)
|
||||
: _sendQueue{ ioContext, baseUrl }
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void sendGETRequest(ClientGETRequestParameters&& request) override;
|
||||
@@ -41,4 +43,4 @@ namespace lms::core::http
|
||||
|
||||
SendQueue _sendQueue;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::http
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
|
||||
#include "core/http/ClientRequestParameters.hpp"
|
||||
|
||||
namespace lms::core::http
|
||||
@@ -28,8 +29,10 @@ namespace lms::core::http
|
||||
class ClientRequest
|
||||
{
|
||||
public:
|
||||
ClientRequest(ClientGETRequestParameters&& GETParams) : _parameters{ std::move(GETParams) } {}
|
||||
ClientRequest(ClientPOSTRequestParameters&& POSTParams) : _parameters{ std::move(POSTParams) } {}
|
||||
ClientRequest(ClientGETRequestParameters&& GETParams)
|
||||
: _parameters{ std::move(GETParams) } {}
|
||||
ClientRequest(ClientPOSTRequestParameters&& POSTParams)
|
||||
: _parameters{ std::move(POSTParams) } {}
|
||||
|
||||
std::size_t retryCount{};
|
||||
|
||||
@@ -37,10 +40,10 @@ namespace lms::core::http
|
||||
{
|
||||
const ClientRequestParameters* res;
|
||||
|
||||
std::visit([&](const auto& parameters)
|
||||
{
|
||||
res = &static_cast<const ClientRequestParameters&>(parameters);
|
||||
}, _parameters);
|
||||
std::visit([&](const auto& parameters) {
|
||||
res = &static_cast<const ClientRequestParameters&>(parameters);
|
||||
},
|
||||
_parameters);
|
||||
|
||||
return *res;
|
||||
}
|
||||
@@ -71,4 +74,4 @@ namespace lms::core::http
|
||||
private:
|
||||
std::variant<ClientGETRequestParameters, ClientPOSTRequestParameters> _parameters;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::http
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
|
||||
#include "SendQueue.hpp"
|
||||
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
#include "core/ILogger.hpp"
|
||||
#include "core/ITraceLogger.hpp"
|
||||
#include "core/String.hpp"
|
||||
|
||||
#define LOG(sev, message) LMS_LOG(SCROBBLING, sev, "[Http SendQueue] - " << message)
|
||||
#define LOG(sev, message) LMS_LOG(SCROBBLING, sev, "[Http SendQueue] - " << message)
|
||||
|
||||
namespace lms::core::stringUtils
|
||||
{
|
||||
@@ -41,35 +41,33 @@ namespace lms::core::stringUtils
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::stringUtils
|
||||
|
||||
namespace lms::core::http
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
std::optional<T> headerReadAs(const Wt::Http::Message& msg, std::string_view headerName)
|
||||
{
|
||||
std::optional<T> res;
|
||||
|
||||
if (const std::string * headerValue{ msg.getHeader(std::string {headerName}) })
|
||||
if (const std::string * headerValue{ msg.getHeader(std::string{ headerName }) })
|
||||
res = stringUtils::readAs<T>(*headerValue);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SendQueue::SendQueue(boost::asio::io_context& ioContext, std::string_view baseUrl)
|
||||
: _ioContext{ ioContext }
|
||||
, _baseUrl{ baseUrl }
|
||||
{
|
||||
_client.done().connect([this](Wt::AsioWrapper::error_code ec, const Wt::Http::Message& msg)
|
||||
{
|
||||
_strand.dispatch([this, ec, msg = std::move(msg)]
|
||||
{
|
||||
onClientDone(ec, msg);
|
||||
});
|
||||
_client.done().connect([this](Wt::AsioWrapper::error_code ec, const Wt::Http::Message& msg) {
|
||||
_strand.dispatch([this, ec, msg = std::move(msg)] {
|
||||
onClientDone(ec, msg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
SendQueue::~SendQueue()
|
||||
@@ -79,13 +77,12 @@ namespace lms::core::http
|
||||
|
||||
void SendQueue::sendRequest(std::unique_ptr<ClientRequest> request)
|
||||
{
|
||||
boost::asio::dispatch(_strand, [this, request = std::move(request)]() mutable
|
||||
{
|
||||
_sendQueue[request->getParameters().priority].emplace_back(std::move(request));
|
||||
boost::asio::dispatch(_strand, [this, request = std::move(request)]() mutable {
|
||||
_sendQueue[request->getParameters().priority].emplace_back(std::move(request));
|
||||
|
||||
if (_state == State::Idle)
|
||||
sendNextQueuedRequest();
|
||||
});
|
||||
if (_state == State::Idle)
|
||||
sendNextQueuedRequest();
|
||||
});
|
||||
}
|
||||
|
||||
void SendQueue::sendNextQueuedRequest()
|
||||
@@ -220,21 +217,20 @@ namespace lms::core::http
|
||||
LOG(DEBUG, "Throttling for " << duration.count() << " seconds");
|
||||
|
||||
_throttleTimer.expires_after(duration);
|
||||
_throttleTimer.async_wait([this](const boost::system::error_code& ec)
|
||||
_throttleTimer.async_wait([this](const boost::system::error_code& ec) {
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
{
|
||||
LOG(DEBUG, "Throttle aborted");
|
||||
return;
|
||||
}
|
||||
else if (ec)
|
||||
{
|
||||
throw LmsException{ "Throttle timer failure: " + std::string {ec.message()} };
|
||||
}
|
||||
LOG(DEBUG, "Throttle aborted");
|
||||
return;
|
||||
}
|
||||
else if (ec)
|
||||
{
|
||||
throw LmsException{ "Throttle timer failure: " + std::string{ ec.message() } };
|
||||
}
|
||||
|
||||
_state = State::Idle;
|
||||
sendNextQueuedRequest();
|
||||
});
|
||||
_state = State::Idle;
|
||||
sendNextQueuedRequest();
|
||||
});
|
||||
_state = State::Throttled;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::http
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/Http/Client.h>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/io_context_strand.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <Wt/Http/Client.h>
|
||||
#include "ClientRequest.hpp"
|
||||
|
||||
namespace lms::core::http
|
||||
@@ -53,15 +53,15 @@ namespace lms::core::http
|
||||
void onClientDoneSuccess(std::unique_ptr<ClientRequest> request, const Wt::Http::Message& msg);
|
||||
void throttle(std::chrono::seconds duration);
|
||||
|
||||
const std::size_t _maxRetryCount{ 2 };
|
||||
const std::chrono::seconds _defaultRetryWaitDuration{ 30 };
|
||||
const std::chrono::seconds _minRetryWaitDuration{ 1 };
|
||||
const std::chrono::seconds _maxRetryWaitDuration{ 300 };
|
||||
const std::size_t _maxRetryCount{ 2 };
|
||||
const std::chrono::seconds _defaultRetryWaitDuration{ 30 };
|
||||
const std::chrono::seconds _minRetryWaitDuration{ 1 };
|
||||
const std::chrono::seconds _maxRetryWaitDuration{ 300 };
|
||||
|
||||
boost::asio::io_context& _ioContext;
|
||||
boost::asio::io_context::strand _strand{ _ioContext };
|
||||
boost::asio::steady_timer _throttleTimer{ _ioContext };
|
||||
std::string _baseUrl;
|
||||
boost::asio::io_context::strand _strand{ _ioContext };
|
||||
boost::asio::steady_timer _throttleTimer{ _ioContext };
|
||||
std::string _baseUrl;
|
||||
|
||||
enum class State
|
||||
{
|
||||
@@ -69,10 +69,10 @@ namespace lms::core::http
|
||||
Throttled,
|
||||
Sending,
|
||||
};
|
||||
State _state{ State::Idle };
|
||||
Wt::Http::Client _client{ _ioContext };
|
||||
State _state{ State::Idle };
|
||||
Wt::Http::Client _client{ _ioContext };
|
||||
std::map<ClientRequestParameters::Priority, std::deque<std::unique_ptr<ClientRequest>>> _sendQueue;
|
||||
std::unique_ptr<ClientRequest> _currentRequest;
|
||||
std::unique_ptr<ClientRequest> _currentRequest;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace lms::core::http
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
@@ -40,4 +40,4 @@ namespace lms::core
|
||||
using Crc32Type = boost::crc_32_type;
|
||||
Crc32Type _result;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
template <typename T, typename underlying_type = std::uint32_t>
|
||||
template<typename T, typename underlying_type = std::uint32_t>
|
||||
class EnumSet
|
||||
{
|
||||
static_assert(std::is_enum<T>::value);
|
||||
@@ -45,13 +45,13 @@ namespace lms::core
|
||||
insert(value);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
template<typename It>
|
||||
constexpr EnumSet(It begin, It end)
|
||||
{
|
||||
assign(begin, end);
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
template<typename It>
|
||||
constexpr void assign(It begin, It end)
|
||||
{
|
||||
clear();
|
||||
@@ -158,7 +158,10 @@ namespace lms::core
|
||||
|
||||
private:
|
||||
static_assert(std::numeric_limits<IndexType>::max() >= sizeof(underlying_type) * 8);
|
||||
enum : IndexType { npos = sizeof(underlying_type) * 8 };
|
||||
enum : IndexType
|
||||
{
|
||||
npos = sizeof(underlying_type) * 8
|
||||
};
|
||||
|
||||
constexpr IndexType getFirstBitSetIndex(IndexType start = {}) const
|
||||
{
|
||||
@@ -190,4 +193,4 @@ namespace lms::core
|
||||
|
||||
underlying_type _bitfield{};
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -29,6 +29,7 @@ namespace lms::core
|
||||
class LmsException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
LmsException(std::string_view error = "") : std::runtime_error{ std::string{ error } } {}
|
||||
LmsException(std::string_view error = "")
|
||||
: std::runtime_error{ std::string{ error } } {}
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -48,9 +48,9 @@ namespace lms::core
|
||||
};
|
||||
|
||||
using ReadCallback = std::function<void(ReadResult, std::size_t)>;
|
||||
virtual void asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback) = 0;
|
||||
virtual void asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback) = 0;
|
||||
|
||||
virtual std::size_t readSome(std::byte* data, std::size_t bufferSize) = 0;
|
||||
virtual bool finished() const = 0;
|
||||
virtual std::size_t readSome(std::byte* data, std::size_t bufferSize) = 0;
|
||||
virtual bool finished() const = 0;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include "IChildProcess.hpp"
|
||||
@@ -35,4 +36,4 @@ namespace lms::core
|
||||
};
|
||||
|
||||
std::unique_ptr<IChildProcessManager> createChildProcessManager(boost::asio::io_service& ioService);
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -31,13 +31,13 @@ namespace lms::core
|
||||
virtual ~IConfig() = default;
|
||||
|
||||
// Default values are returned in case of setting not found
|
||||
virtual std::string_view getString(std::string_view setting, std::string_view def = "") = 0;
|
||||
virtual void visitStrings(std::string_view setting, std::function<void(std::string_view)> _func, std::initializer_list<std::string_view> def = {}) = 0;
|
||||
virtual std::filesystem::path getPath(std::string_view setting, const std::filesystem::path& def = std::filesystem::path()) = 0;
|
||||
virtual unsigned long getULong(std::string_view setting, unsigned long def = 0) = 0;
|
||||
virtual long getLong(std::string_view setting, long def = 0) = 0;
|
||||
virtual bool getBool(std::string_view setting, bool def = false) = 0;
|
||||
virtual std::string_view getString(std::string_view setting, std::string_view def = "") = 0;
|
||||
virtual void visitStrings(std::string_view setting, std::function<void(std::string_view)> _func, std::initializer_list<std::string_view> def = {}) = 0;
|
||||
virtual std::filesystem::path getPath(std::string_view setting, const std::filesystem::path& def = std::filesystem::path()) = 0;
|
||||
virtual unsigned long getULong(std::string_view setting, unsigned long def = 0) = 0;
|
||||
virtual long getLong(std::string_view setting, long def = 0) = 0;
|
||||
virtual bool getBool(std::string_view setting, bool def = false) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IConfig> createConfig(const std::filesystem::path& p);
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "core/Service.hpp"
|
||||
#include "core/String.hpp"
|
||||
#include "Service.hpp"
|
||||
|
||||
namespace lms::core::logging
|
||||
{
|
||||
@@ -93,11 +93,11 @@ namespace lms::core::logging
|
||||
virtual bool isSeverityActive(Severity severity) const = 0;
|
||||
virtual void processLog(const Log& log) = 0;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
|
||||
#define LMS_LOG(module, severity, message) \
|
||||
do \
|
||||
{ \
|
||||
if (auto* logger_ {::lms::core::Service<::lms::core::logging::ILogger>::get()}; logger_ && logger_->isSeverityActive(::lms::core::logging::Severity::severity)) \
|
||||
::lms::core::logging::Log{ *logger_, ::lms::core::logging::Module::module, ::lms::core::logging::Severity::severity }.getOstream() << message; \
|
||||
} while(0)
|
||||
#define LMS_LOG(module, severity, message) \
|
||||
do \
|
||||
{ \
|
||||
if (auto* logger_{ ::lms::core::Service<::lms::core::logging::ILogger>::get() }; logger_ && logger_->isSeverityActive(::lms::core::logging::Severity::severity)) \
|
||||
::lms::core::logging::Log{ *logger_, ::lms::core::logging::Module::module, ::lms::core::logging::Severity::severity }.getOstream() << message; \
|
||||
} while (0)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace lms::core
|
||||
@@ -39,7 +40,7 @@ namespace lms::core
|
||||
IOContextRunner& operator=(const IOContextRunner&) = delete;
|
||||
|
||||
boost::asio::io_service& _ioService;
|
||||
std::optional<boost::asio::io_service::work> _work;
|
||||
std::vector<std::thread> _threads;
|
||||
std::optional<boost::asio::io_service::work> _work;
|
||||
std::vector<std::thread> _threads;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -25,13 +25,13 @@
|
||||
// TODO, move elsewhere
|
||||
namespace lms
|
||||
{
|
||||
// Helper class to serve a resource (must be saved as continuation data if not complete)
|
||||
class IResourceHandler
|
||||
{
|
||||
public:
|
||||
virtual ~IResourceHandler() = default;
|
||||
// Helper class to serve a resource (must be saved as continuation data if not complete)
|
||||
class IResourceHandler
|
||||
{
|
||||
public:
|
||||
virtual ~IResourceHandler() = default;
|
||||
|
||||
[[nodiscard]] virtual Wt::Http::ResponseContinuation* processRequest(const Wt::Http::Request& request, Wt::Http::Response& response) = 0;
|
||||
virtual void abort() = 0;
|
||||
};
|
||||
}
|
||||
[[nodiscard]] virtual Wt::Http::ResponseContinuation* processRequest(const Wt::Http::Request& request, Wt::Http::Response& response) = 0;
|
||||
virtual void abort() = 0;
|
||||
};
|
||||
} // namespace lms
|
||||
@@ -34,20 +34,20 @@
|
||||
#define LMS_CONCAT_IMPL(x, y) x##y
|
||||
#define LMS_CONCAT(x, y) LMS_CONCAT_IMPL(x, y)
|
||||
|
||||
#if LMS_SUPPORT_TRACING
|
||||
#define LMS_SCOPED_TRACE(CATEGORY, LEVEL, NAME, ARGTYPE, ARGVALUE) \
|
||||
std::optional<::lms::core::tracing::ScopedTrace> LMS_CONCAT(ScopedTrace_, __LINE__); \
|
||||
if (::lms::core::tracing::ITraceLogger* traceLogger{ ::lms::core::Service<::lms::core::tracing::ITraceLogger>::get() }; traceLogger && traceLogger->isLevelActive(LEVEL)) \
|
||||
LMS_CONCAT(ScopedTrace_, __LINE__).emplace(CATEGORY, LEVEL, NAME, ARGTYPE, ARGVALUE, traceLogger);
|
||||
#if LMS_SUPPORT_TRACING
|
||||
#define LMS_SCOPED_TRACE(CATEGORY, LEVEL, NAME, ARGTYPE, ARGVALUE) \
|
||||
std::optional<::lms::core::tracing::ScopedTrace> LMS_CONCAT(ScopedTrace_, __LINE__); \
|
||||
if (::lms::core::tracing::ITraceLogger * traceLogger{ ::lms::core::Service<::lms::core::tracing::ITraceLogger>::get() }; traceLogger && traceLogger->isLevelActive(LEVEL)) \
|
||||
LMS_CONCAT(ScopedTrace_, __LINE__).emplace(CATEGORY, LEVEL, NAME, ARGTYPE, ARGVALUE, traceLogger);
|
||||
#else
|
||||
#define LMS_SCOPED_TRACE(CATEGORY, LEVEL, NAME) (void)0
|
||||
#define LMS_SCOPED_TRACE(CATEGORY, LEVEL, NAME) (void)0
|
||||
#endif
|
||||
|
||||
#define LMS_SCOPED_TRACE_OVERVIEW_WITH_ARG(CATEGORY, NAME, ARGTYPE, ARGVALUE) LMS_SCOPED_TRACE(CATEGORY, ::lms::core::tracing::Level::Overview, NAME, ARGTYPE, ARGVALUE)
|
||||
#define LMS_SCOPED_TRACE_DETAILED_WITH_ARG(CATEGORY, NAME, ARGTYPE, ARGVALUE) LMS_SCOPED_TRACE(CATEGORY, ::lms::core::tracing::Level::Detailed, NAME, ARGTYPE, ARGVALUE)
|
||||
#define LMS_SCOPED_TRACE_OVERVIEW_WITH_ARG(CATEGORY, NAME, ARGTYPE, ARGVALUE) LMS_SCOPED_TRACE(CATEGORY, ::lms::core::tracing::Level::Overview, NAME, ARGTYPE, ARGVALUE)
|
||||
#define LMS_SCOPED_TRACE_DETAILED_WITH_ARG(CATEGORY, NAME, ARGTYPE, ARGVALUE) LMS_SCOPED_TRACE(CATEGORY, ::lms::core::tracing::Level::Detailed, NAME, ARGTYPE, ARGVALUE)
|
||||
|
||||
#define LMS_SCOPED_TRACE_OVERVIEW(CATEGORY, NAME) LMS_SCOPED_TRACE_OVERVIEW_WITH_ARG(CATEGORY, NAME, "", "")
|
||||
#define LMS_SCOPED_TRACE_DETAILED(CATEGORY, NAME) LMS_SCOPED_TRACE_DETAILED_WITH_ARG(CATEGORY, NAME, "", "")
|
||||
#define LMS_SCOPED_TRACE_OVERVIEW(CATEGORY, NAME) LMS_SCOPED_TRACE_OVERVIEW_WITH_ARG(CATEGORY, NAME, "", "")
|
||||
#define LMS_SCOPED_TRACE_DETAILED(CATEGORY, NAME) LMS_SCOPED_TRACE_DETAILED_WITH_ARG(CATEGORY, NAME, "", "")
|
||||
|
||||
namespace lms::core::tracing
|
||||
{
|
||||
@@ -124,4 +124,4 @@ namespace lms::core::tracing
|
||||
ITraceLogger* _traceLogger;
|
||||
ITraceLogger::CompleteEvent _event;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::tracing
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "Exception.hpp"
|
||||
|
||||
// TODO, move elsewhere?
|
||||
// TODO, move elsewhere?
|
||||
namespace lms::zip
|
||||
{
|
||||
struct Entry
|
||||
@@ -51,4 +51,4 @@ namespace lms::zip
|
||||
};
|
||||
|
||||
std::unique_ptr<IZipper> createArchiveZipper(const EntryContainer& entries);
|
||||
}
|
||||
} // namespace lms::zip
|
||||
|
||||
@@ -31,7 +31,11 @@ namespace lms::core
|
||||
public:
|
||||
constexpr LiteralString() noexcept = default;
|
||||
template<std::size_t N>
|
||||
constexpr LiteralString(const char(&str)[N]) noexcept : _str{ str, N - 1 } { static_assert(N > 0); }
|
||||
constexpr LiteralString(const char (&str)[N]) noexcept
|
||||
: _str{ str, N - 1 }
|
||||
{
|
||||
static_assert(N > 0);
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept { return _str.empty(); }
|
||||
constexpr const char* c_str() const noexcept { return _str.data(); }
|
||||
@@ -48,7 +52,7 @@ namespace lms::core
|
||||
os << str.str();
|
||||
return os;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
|
||||
namespace std
|
||||
{
|
||||
@@ -60,7 +64,7 @@ namespace std
|
||||
return hash<std::string_view>{}(str.str());
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
@@ -69,15 +73,18 @@ namespace lms::core
|
||||
using hash_type = std::hash<std::string_view>;
|
||||
using is_transparent = void;
|
||||
|
||||
[[nodiscard]] size_t operator()(const LiteralString& str) const {
|
||||
[[nodiscard]] size_t operator()(const LiteralString& str) const
|
||||
{
|
||||
return hash_type{}(str.str());
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t operator()(std::string_view str) const {
|
||||
[[nodiscard]] size_t operator()(std::string_view str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t operator()(const std::string& str) const {
|
||||
[[nodiscard]] size_t operator()(const std::string& str) const
|
||||
{
|
||||
return hash_type{}(str);
|
||||
}
|
||||
};
|
||||
@@ -86,24 +93,29 @@ namespace lms::core
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
[[nodiscard]] bool operator()(const LiteralString& lhs, const LiteralString& rhs) const {
|
||||
[[nodiscard]] bool operator()(const LiteralString& lhs, const LiteralString& rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator()(const LiteralString& lhs, const std::string& rhs) const {
|
||||
[[nodiscard]] bool operator()(const LiteralString& lhs, const std::string& rhs) const
|
||||
{
|
||||
return lhs.str() == rhs;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator()(const LiteralString& lhs, std::string_view rhs) const {
|
||||
[[nodiscard]] bool operator()(const LiteralString& lhs, std::string_view rhs) const
|
||||
{
|
||||
return lhs.str() == rhs;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator()(const std::string_view& lhs, LiteralString rhs) const {
|
||||
[[nodiscard]] bool operator()(const std::string_view& lhs, LiteralString rhs) const
|
||||
{
|
||||
return lhs == rhs.str();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator()(const std::string& lhs, const LiteralString& rhs) const {
|
||||
[[nodiscard]] bool operator()(const std::string& lhs, const LiteralString& rhs) const
|
||||
{
|
||||
return lhs == rhs.str();
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -22,15 +22,16 @@
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
|
||||
#ifndef BOOST_ASIO_HAS_STD_HASH
|
||||
#include <functional>
|
||||
#include <functional>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<> struct hash<boost::asio::ip::address>
|
||||
{
|
||||
std::size_t operator()(const boost::asio::ip::address& ipAddr) const;
|
||||
};
|
||||
template<>
|
||||
struct hash<boost::asio::ip::address>
|
||||
{
|
||||
std::size_t operator()(const boost::asio::ip::address& ipAddr) const;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
#endif // BOOST_ASIO_HAS_STD_HASH
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace lms::core::pathUtils
|
||||
|
||||
std::filesystem::path getLongestCommonPath(const std::filesystem::path& path1, const std::filesystem::path& path2);
|
||||
|
||||
template <typename Iterator>
|
||||
template<typename Iterator>
|
||||
std::filesystem::path getLongestCommonPath(Iterator first, Iterator last)
|
||||
{
|
||||
std::filesystem::path longestCommonPath;
|
||||
@@ -64,4 +64,4 @@ namespace lms::core::pathUtils
|
||||
|
||||
return longestCommonPath;
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::pathUtils
|
||||
|
||||
@@ -29,27 +29,27 @@ namespace lms::core::random
|
||||
|
||||
RandGenerator createSeededGenerator(uint_fast32_t seed);
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
T getRandom(T min, T max)
|
||||
{
|
||||
std::uniform_int_distribution<> dist{ min, max };
|
||||
return dist(getRandGenerator());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
T getRealRandom(T min, T max)
|
||||
{
|
||||
std::uniform_real_distribution<> dist{ min, max };
|
||||
return dist(getRandGenerator());
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
template<typename Container>
|
||||
void shuffleContainer(Container& container)
|
||||
{
|
||||
std::shuffle(std::begin(container), std::end(container), getRandGenerator());
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
template<typename Container>
|
||||
typename Container::const_iterator pickRandom(const Container& container)
|
||||
{
|
||||
if (container.empty())
|
||||
@@ -57,4 +57,4 @@ namespace lms::core::random
|
||||
|
||||
return std::next(std::begin(container), getRandom(0, static_cast<int>(container.size() - 1)));
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::random
|
||||
@@ -48,4 +48,4 @@ namespace lms::core
|
||||
std::mutex _sharedCountMutex;
|
||||
std::unordered_map<std::thread::id, std::size_t> _sharedCounts;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
template <typename Class>
|
||||
template<typename Class>
|
||||
class Service
|
||||
{
|
||||
public:
|
||||
@@ -57,7 +57,7 @@ namespace lms::core
|
||||
static Class* get() { return _service.get(); }
|
||||
static bool exists() { return _service.get(); }
|
||||
|
||||
template <typename SubClass>
|
||||
template<typename SubClass>
|
||||
static Class& assign(std::unique_ptr<SubClass> service)
|
||||
{
|
||||
assert(!_service);
|
||||
@@ -70,4 +70,4 @@ namespace lms::core
|
||||
|
||||
static inline std::unique_ptr<Class> _service;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -39,4 +39,4 @@ namespace lms::core::logging
|
||||
std::ostream& _os;
|
||||
const EnumSet<Severity> _severities;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
@@ -22,9 +22,9 @@
|
||||
#include <initializer_list>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#define QUOTEME(x) QUOTEME_1(x)
|
||||
@@ -34,7 +34,7 @@ namespace Wt
|
||||
{
|
||||
class WDate;
|
||||
class WDateTime;
|
||||
}
|
||||
} // namespace Wt
|
||||
|
||||
namespace lms::core::stringUtils
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace lms::core::stringUtils
|
||||
{
|
||||
T res;
|
||||
|
||||
std::istringstream iss{ std::string {str} };
|
||||
std::istringstream iss{ std::string{ str } };
|
||||
iss >> res;
|
||||
if (iss.fail())
|
||||
return std::nullopt;
|
||||
@@ -100,4 +100,4 @@ namespace lms::core::stringUtils
|
||||
|
||||
[[nodiscard]] std::string toISO8601String(const Wt::WDateTime& dateTime);
|
||||
[[nodiscard]] std::string toISO8601String(const Wt::WDate& date);
|
||||
}
|
||||
} // namespace lms::core::stringUtils
|
||||
@@ -23,27 +23,33 @@
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
template<int... Is>
|
||||
struct Seq { };
|
||||
namespace details
|
||||
{
|
||||
template<int... Is>
|
||||
struct Seq
|
||||
{
|
||||
};
|
||||
|
||||
template<int N, int... Is>
|
||||
struct GenSeq : GenSeq<N - 1, N - 1, Is...> { };
|
||||
template<int N, int... Is>
|
||||
struct GenSeq : GenSeq<N - 1, N - 1, Is...>
|
||||
{
|
||||
};
|
||||
|
||||
template<int... Is>
|
||||
struct GenSeq<0, Is...> : Seq<Is...> { };
|
||||
template<int... Is>
|
||||
struct GenSeq<0, Is...> : Seq<Is...>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T, typename Func, int... Is>
|
||||
void forEachTypeInTuple(T&& t, Func f, Seq<Is...>)
|
||||
{
|
||||
auto l = { (f(std::get<Is>(t)), 0)... };
|
||||
}
|
||||
}
|
||||
template<typename T, typename Func, int... Is>
|
||||
void forEachTypeInTuple(T&& t, Func f, Seq<Is...>)
|
||||
{
|
||||
auto l = { (f(std::get<Is>(t)), 0)... };
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
template<typename... Ts, typename Func>
|
||||
void forEachTypeInTuple(std::tuple<Ts...> const& t, Func f)
|
||||
{
|
||||
details::forEachTypeInTuple(t, f, details::GenSeq<sizeof...(Ts)>());
|
||||
}
|
||||
}
|
||||
template<typename... Ts, typename Func>
|
||||
void forEachTypeInTuple(std::tuple<Ts...> const& t, Func f)
|
||||
{
|
||||
details::forEachTypeInTuple(t, f, details::GenSeq<sizeof...(Ts)>());
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -41,11 +41,11 @@ namespace lms::core
|
||||
UUID(std::string_view value);
|
||||
std::string _value;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core
|
||||
|
||||
namespace lms::core::stringUtils
|
||||
{
|
||||
template <>
|
||||
template<>
|
||||
std::optional<UUID>
|
||||
readAs(std::string_view str);
|
||||
readAs(std::string_view str);
|
||||
}
|
||||
|
||||
@@ -24,18 +24,19 @@
|
||||
|
||||
namespace lms::core::utils
|
||||
{
|
||||
template<class T, class Compare = std::less<>>
|
||||
constexpr T clamp(T v, T lo, T hi, Compare comp = {})
|
||||
{
|
||||
assert(!comp(hi, lo));
|
||||
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
|
||||
}
|
||||
template<class T, class Compare = std::less<>>
|
||||
constexpr T clamp(T v, T lo, T hi, Compare comp = {})
|
||||
{
|
||||
assert(!comp(hi, lo));
|
||||
return comp(v, lo) ? lo : comp(hi, v) ? hi :
|
||||
v;
|
||||
}
|
||||
|
||||
template <typename Container, typename T>
|
||||
void
|
||||
push_back_if_not_present(Container& container, const T& val)
|
||||
{
|
||||
if (std::find(std::cbegin(container), std::cend(container), val) == std::cend(container))
|
||||
container.push_back(val);
|
||||
}
|
||||
}
|
||||
template<typename Container, typename T>
|
||||
void
|
||||
push_back_if_not_present(Container& container, const T& val)
|
||||
{
|
||||
if (std::find(std::cbegin(container), std::cend(container), val) == std::cend(container))
|
||||
container.push_back(val);
|
||||
}
|
||||
} // namespace lms::core::utils
|
||||
@@ -37,4 +37,4 @@ namespace lms::core::logging
|
||||
void processLog(const Log& log) override;
|
||||
const Severity _minSeverity;
|
||||
};
|
||||
}
|
||||
} // namespace lms::core::logging
|
||||
@@ -36,7 +36,7 @@ namespace lms::core::http
|
||||
Low,
|
||||
};
|
||||
|
||||
Priority priority{ Priority::Normal };
|
||||
Priority priority{ Priority::Normal };
|
||||
std::string relativeUrl; // relative to baseUrl used by the client
|
||||
|
||||
using OnSuccessFunc = std::function<void(std::string_view msgBody)>;
|
||||
@@ -56,4 +56,4 @@ namespace lms::core::http
|
||||
Wt::Http::Message message;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace lms::core::http
|
||||
@@ -20,20 +20,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include "core/http/ClientRequestParameters.hpp"
|
||||
|
||||
namespace lms::core::http
|
||||
{
|
||||
class IClient
|
||||
{
|
||||
public:
|
||||
virtual ~IClient() = default;
|
||||
class IClient
|
||||
{
|
||||
public:
|
||||
virtual ~IClient() = default;
|
||||
|
||||
virtual void sendGETRequest(ClientGETRequestParameters&& request) = 0;
|
||||
virtual void sendPOSTRequest(ClientPOSTRequestParameters&& request) = 0;
|
||||
};
|
||||
virtual void sendGETRequest(ClientGETRequestParameters&& request) = 0;
|
||||
virtual void sendPOSTRequest(ClientPOSTRequestParameters&& request) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IClient> createClient(boost::asio::io_context& ioContext, std::string_view baseUrl);
|
||||
}
|
||||
std::unique_ptr<IClient> createClient(boost::asio::io_context& ioContext, std::string_view baseUrl);
|
||||
} // namespace lms::core::http
|
||||
@@ -60,4 +60,4 @@ namespace lms::core
|
||||
EXPECT_EQ(test, test2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "core/LiteralString.hpp"
|
||||
@@ -53,7 +54,7 @@ namespace lms::core
|
||||
TEST(LiteralString, unordered_map)
|
||||
{
|
||||
{
|
||||
std::unordered_map<LiteralString, int> myMap{ {"abc", 42} };
|
||||
std::unordered_map<LiteralString, int> myMap{ { "abc", 42 } };
|
||||
|
||||
EXPECT_TRUE(myMap.contains("abc"));
|
||||
EXPECT_TRUE(myMap.contains(LiteralString{ "abc" }));
|
||||
@@ -61,12 +62,11 @@ namespace lms::core
|
||||
}
|
||||
|
||||
{
|
||||
std::unordered_map<LiteralString, int, LiteralStringHash, LiteralStringEqual> myMap{ {"abc", 42} };
|
||||
std::unordered_map<LiteralString, int, LiteralStringHash, LiteralStringEqual> myMap{ { "abc", 42 } };
|
||||
EXPECT_TRUE(myMap.contains(std::string{ "abc" }));
|
||||
EXPECT_TRUE(myMap.contains(std::string_view{ "abc" }));
|
||||
EXPECT_FALSE(myMap.contains(std::string{ "abcd" }));
|
||||
EXPECT_FALSE(myMap.contains(std::string_view{ "abcd" }));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
+30
-34
@@ -32,14 +32,13 @@ namespace lms::core::pathUtils::tests
|
||||
std::filesystem::path expectedCommonPath;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{"foo.txt", "/foo/foo.txt", ""},
|
||||
{"/", "/file.txt", "/"},
|
||||
{"/foo/bar/file1.txt", "/foo/bar/file2.txt", "/foo/bar"},
|
||||
{"/foo/bar/file.txt", "/foo/bar/file.txt", "/foo/bar/file.txt"},
|
||||
{"/dir1/file.txt", "/dir2/file.txt", "/"},
|
||||
{"/prefix/folder/file.txt", "/prefix/folder/subfolder/file.txt", "/prefix/folder"},
|
||||
TestCase tests[]{
|
||||
{ "foo.txt", "/foo/foo.txt", "" },
|
||||
{ "/", "/file.txt", "/" },
|
||||
{ "/foo/bar/file1.txt", "/foo/bar/file2.txt", "/foo/bar" },
|
||||
{ "/foo/bar/file.txt", "/foo/bar/file.txt", "/foo/bar/file.txt" },
|
||||
{ "/dir1/file.txt", "/dir2/file.txt", "/" },
|
||||
{ "/prefix/folder/file.txt", "/prefix/folder/subfolder/file.txt", "/prefix/folder" },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -48,7 +47,6 @@ namespace lms::core::pathUtils::tests
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Path, getLongestCommonPathIterator)
|
||||
{
|
||||
struct TestCase
|
||||
@@ -57,17 +55,16 @@ namespace lms::core::pathUtils::tests
|
||||
std::filesystem::path expectedCommonPath;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{{}, ""},
|
||||
{{"/"}, "/"},
|
||||
{{"/foo", "/bar"}, "/"},
|
||||
{{"/foo/bar/file1.txt", "/foo/bar/file2.txt"}, "/foo/bar"},
|
||||
{{"/foo", "/foo/"}, "/foo"},
|
||||
{{"/foo", "/foo"}, "/foo"},
|
||||
{{"/foo/", "/foo/"}, "/foo/"},
|
||||
{{"/foo/", "/foo/", "/bar"}, "/"},
|
||||
{{"/foo/", "/foo/", "/foo/bar"}, "/foo"},
|
||||
TestCase tests[]{
|
||||
{ {}, "" },
|
||||
{ { "/" }, "/" },
|
||||
{ { "/foo", "/bar" }, "/" },
|
||||
{ { "/foo/bar/file1.txt", "/foo/bar/file2.txt" }, "/foo/bar" },
|
||||
{ { "/foo", "/foo/" }, "/foo" },
|
||||
{ { "/foo", "/foo" }, "/foo" },
|
||||
{ { "/foo/", "/foo/" }, "/foo/" },
|
||||
{ { "/foo/", "/foo/", "/bar" }, "/" },
|
||||
{ { "/foo/", "/foo/", "/foo/bar" }, "/foo" },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -85,19 +82,18 @@ namespace lms::core::pathUtils::tests
|
||||
bool expectedResult;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{"/file.txt", "/", true},
|
||||
{"/root/folder/file.txt", "/root", true},
|
||||
{"/root/file.txt", "/root", true},
|
||||
{"/root/file.txt", "/root/", true},
|
||||
{"/root", "/root", true},
|
||||
{"/root", "/root/", true},
|
||||
{"/root/", "/root", true},
|
||||
{"/root/", "/root/", true},
|
||||
{"/folder/file.txt", "/root", false},
|
||||
{"/folder/file.txt", "/root/", false},
|
||||
{"", "/root", false},
|
||||
TestCase tests[]{
|
||||
{ "/file.txt", "/", true },
|
||||
{ "/root/folder/file.txt", "/root", true },
|
||||
{ "/root/file.txt", "/root", true },
|
||||
{ "/root/file.txt", "/root/", true },
|
||||
{ "/root", "/root", true },
|
||||
{ "/root", "/root/", true },
|
||||
{ "/root/", "/root", true },
|
||||
{ "/root/", "/root/", true },
|
||||
{ "/folder/file.txt", "/root", false },
|
||||
{ "/folder/file.txt", "/root/", false },
|
||||
{ "", "/root", false },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -105,4 +101,4 @@ namespace lms::core::pathUtils::tests
|
||||
EXPECT_EQ(core::pathUtils::isPathInRootPath(test.path, test.rootPath), test.expectedResult) << "Failed: path = " << test.path << ", rootPath = " << test.rootPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::pathUtils::tests
|
||||
@@ -66,40 +66,39 @@ namespace lms::core
|
||||
std::atomic<std::size_t> nbShared{};
|
||||
for (std::size_t i{}; i < nbThreads; ++i)
|
||||
{
|
||||
threads.emplace_back([&]
|
||||
threads.emplace_back([&] {
|
||||
{
|
||||
{
|
||||
std::unique_lock lock{ mutex };
|
||||
std::unique_lock lock{ mutex };
|
||||
|
||||
std::shared_lock lock2{ mutex };
|
||||
std::shared_lock lock2{ mutex };
|
||||
|
||||
assert(nbUnique == 0);
|
||||
assert(nbShared == 0);
|
||||
nbUnique++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
assert(nbUnique == 1);
|
||||
assert(nbShared == 0);
|
||||
nbUnique--;
|
||||
}
|
||||
assert(nbUnique == 0);
|
||||
assert(nbShared == 0);
|
||||
nbUnique++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
assert(nbUnique == 1);
|
||||
assert(nbShared == 0);
|
||||
nbUnique--;
|
||||
}
|
||||
|
||||
{
|
||||
std::shared_lock lock{ mutex };
|
||||
std::shared_lock lock2{ mutex };
|
||||
{
|
||||
std::shared_lock lock{ mutex };
|
||||
std::shared_lock lock2{ mutex };
|
||||
|
||||
assert(nbUnique == 0);
|
||||
nbShared++;
|
||||
assert(nbUnique == 0);
|
||||
nbShared++;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(15));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(15));
|
||||
|
||||
assert(nbShared > 0);
|
||||
assert(nbShared <= nbThreads);
|
||||
assert(nbUnique == 0);
|
||||
nbShared--;
|
||||
}
|
||||
});
|
||||
assert(nbShared > 0);
|
||||
assert(nbShared <= nbThreads);
|
||||
assert(nbUnique == 0);
|
||||
nbShared--;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (std::thread& t : threads)
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -19,9 +19,10 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/WDate.h>
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/WTime.h>
|
||||
|
||||
#include "core/String.hpp"
|
||||
|
||||
namespace lms::core::stringUtils::tests
|
||||
@@ -35,30 +36,29 @@ namespace lms::core::stringUtils::tests
|
||||
std::vector<std::string_view> expectedOutput;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{"abc", '-', {"abc"}},
|
||||
{"a", '-', {"a"}},
|
||||
{"", '-', {""}},
|
||||
{"a-b-c", '-', {"a", "b", "c"}},
|
||||
{"a|b|c", '|', {"a", "b", "c"}},
|
||||
{"a;b;c", ';', {"a", "b", "c"}},
|
||||
{";b;c", ';', {"", "b", "c"}},
|
||||
{" ;b;c", ';', {" ", "b", "c"}},
|
||||
{" ;;c", ';', {" ", "", "c"}},
|
||||
{" ; ;c", ';', {" ", " ", "c"}},
|
||||
{"a;b; ", ';', {"a", "b", " "}},
|
||||
{"a;b", ';', {"a", "b"}},
|
||||
{";b", ';', {"", "b"}},
|
||||
{";", ';', {"", ""}},
|
||||
{";;", ';', {"", "", ""}},
|
||||
{";;;", ';', {"", "", "", ""}},
|
||||
{";;a;;b;;", ';', {"", "", "a", "", "b", "", ""}},
|
||||
{"a b", ' ', {"a", "b"}},
|
||||
{"", ' ', {""}},
|
||||
{"a-b|c", '-', {"a","b|c"}},
|
||||
{"a|b-c", '-', {"a|b", "c"}},
|
||||
{"test=foo bar", '=', {"test", "foo bar"}},
|
||||
TestCase tests[]{
|
||||
{ "abc", '-', { "abc" } },
|
||||
{ "a", '-', { "a" } },
|
||||
{ "", '-', { "" } },
|
||||
{ "a-b-c", '-', { "a", "b", "c" } },
|
||||
{ "a|b|c", '|', { "a", "b", "c" } },
|
||||
{ "a;b;c", ';', { "a", "b", "c" } },
|
||||
{ ";b;c", ';', { "", "b", "c" } },
|
||||
{ " ;b;c", ';', { " ", "b", "c" } },
|
||||
{ " ;;c", ';', { " ", "", "c" } },
|
||||
{ " ; ;c", ';', { " ", " ", "c" } },
|
||||
{ "a;b; ", ';', { "a", "b", " " } },
|
||||
{ "a;b", ';', { "a", "b" } },
|
||||
{ ";b", ';', { "", "b" } },
|
||||
{ ";", ';', { "", "" } },
|
||||
{ ";;", ';', { "", "", "" } },
|
||||
{ ";;;", ';', { "", "", "", "" } },
|
||||
{ ";;a;;b;;", ';', { "", "", "a", "", "b", "", "" } },
|
||||
{ "a b", ' ', { "a", "b" } },
|
||||
{ "", ' ', { "" } },
|
||||
{ "a-b|c", '-', { "a", "b|c" } },
|
||||
{ "a|b-c", '-', { "a|b", "c" } },
|
||||
{ "test=foo bar", '=', { "test", "foo bar" } },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -77,19 +77,18 @@ namespace lms::core::stringUtils::tests
|
||||
std::vector<std::string_view> expectedOutput;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{"abc", "", {"abc"}},
|
||||
{"abc", "-", {"abc"}},
|
||||
{"abc", "b", {"a", "c"}},
|
||||
{"ab/cd", "/", {"ab", "cd"}},
|
||||
{"ab/cd", "/ ", {"ab/cd"}},
|
||||
{"ab/cd", " /", {"ab/cd"}},
|
||||
{"ab /cd", " /", {"ab", "cd"}},
|
||||
{"ab/ cd", "/ ", {"ab", "cd"}},
|
||||
{"ab / cd", " / ", {"ab", "cd"}},
|
||||
{"ab/cd", " / ", {"ab/cd"}},
|
||||
{"ab/cd / ", " / ", {"ab/cd", ""}},
|
||||
TestCase tests[]{
|
||||
{ "abc", "", { "abc" } },
|
||||
{ "abc", "-", { "abc" } },
|
||||
{ "abc", "b", { "a", "c" } },
|
||||
{ "ab/cd", "/", { "ab", "cd" } },
|
||||
{ "ab/cd", "/ ", { "ab/cd" } },
|
||||
{ "ab/cd", " /", { "ab/cd" } },
|
||||
{ "ab /cd", " /", { "ab", "cd" } },
|
||||
{ "ab/ cd", "/ ", { "ab", "cd" } },
|
||||
{ "ab / cd", " / ", { "ab", "cd" } },
|
||||
{ "ab/cd", " / ", { "ab/cd" } },
|
||||
{ "ab/cd / ", " / ", { "ab/cd", "" } },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -108,15 +107,14 @@ namespace lms::core::stringUtils::tests
|
||||
std::string expectedOutput;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{{"a", "b", "c"}, "-", "a-b-c"},
|
||||
{{"a", "b", "c"}, ",", "a,b,c"},
|
||||
{{"a", "b", "c"}, "***", "a***b***c"},
|
||||
{{"a", "", "c"}, "-", "a--c"},
|
||||
{{"", "b", "c"}, "-", "-b-c"},
|
||||
{{"a"}, "-", "a"},
|
||||
{{"a"}, ",", "a"},
|
||||
TestCase tests[]{
|
||||
{ { "a", "b", "c" }, "-", "a-b-c" },
|
||||
{ { "a", "b", "c" }, ",", "a,b,c" },
|
||||
{ { "a", "b", "c" }, "***", "a***b***c" },
|
||||
{ { "a", "", "c" }, "-", "a--c" },
|
||||
{ { "", "b", "c" }, "-", "-b-c" },
|
||||
{ { "a" }, "-", "a" },
|
||||
{ { "a" }, ",", "a" },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -136,13 +134,12 @@ namespace lms::core::stringUtils::tests
|
||||
std::string expectedOutput;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{{""}, ';', '\\', ""},
|
||||
{{";"}, ';', '\\', "\\;"},
|
||||
{{";;"}, ';', '\\', "\\;\\;"},
|
||||
{{"a;", "b"}, ';', '\\', "a\\;;b"},
|
||||
{{"a;", "b;"}, ';', '\\', "a\\;;b\\;"},
|
||||
TestCase tests[]{
|
||||
{ { "" }, ';', '\\', "" },
|
||||
{ { ";" }, ';', '\\', "\\;" },
|
||||
{ { ";;" }, ';', '\\', "\\;\\;" },
|
||||
{ { "a;", "b" }, ';', '\\', "a\\;;b" },
|
||||
{ { "a;", "b;" }, ';', '\\', "a\\;;b\\;" },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -162,13 +159,12 @@ namespace lms::core::stringUtils::tests
|
||||
std::vector<std::string> expectedOutput;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{"", ';', '\\', {}},
|
||||
{"\\;", ';', '\\', {";"}},
|
||||
{"\\;\\;", ';', '\\', {";;"}},
|
||||
{"a\\;;b", ';', '\\', {"a;", "b"}},
|
||||
{"a\\;;b\\;", ';', '\\', {"a;", "b;"}},
|
||||
TestCase tests[]{
|
||||
{ "", ';', '\\', {} },
|
||||
{ "\\;", ';', '\\', { ";" } },
|
||||
{ "\\;\\;", ';', '\\', { ";;" } },
|
||||
{ "a\\;;b", ';', '\\', { "a;", "b" } },
|
||||
{ "a\\;;b\\;", ';', '\\', { "a;", "b;" } },
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -250,17 +246,16 @@ namespace lms::core::stringUtils::tests
|
||||
std::string expectedOutput;
|
||||
};
|
||||
|
||||
TestCase tests[]
|
||||
{
|
||||
{"", ""},
|
||||
{"C", "C"},
|
||||
{"c", "C"},
|
||||
{" c", " C"},
|
||||
{" cc", " Cc"},
|
||||
{"(c", "(c"},
|
||||
{"1c", "1c"},
|
||||
{"&c", "&c"},
|
||||
{"c c", "C c"}
|
||||
TestCase tests[]{
|
||||
{ "", "" },
|
||||
{ "C", "C" },
|
||||
{ "c", "C" },
|
||||
{ " c", " C" },
|
||||
{ " cc", " Cc" },
|
||||
{ "(c", "(c" },
|
||||
{ "1c", "1c" },
|
||||
{ "&c", "&c" },
|
||||
{ "c c", "C c" }
|
||||
};
|
||||
|
||||
for (const TestCase& test : tests)
|
||||
@@ -279,7 +274,7 @@ namespace lms::core::stringUtils::tests
|
||||
|
||||
TEST(Stringutils, dateTime)
|
||||
{
|
||||
const Wt::WDateTime dateTime{ Wt::WDate {2020, 01, 03 }, Wt::WTime{9, 8, 11, 75} };
|
||||
const Wt::WDateTime dateTime{ Wt::WDate{ 2020, 01, 03 }, Wt::WTime{ 9, 8, 11, 75 } };
|
||||
EXPECT_EQ(toISO8601String(dateTime), "2020-01-03T09:08:11.075");
|
||||
}
|
||||
|
||||
@@ -294,4 +289,4 @@ namespace lms::core::stringUtils::tests
|
||||
EXPECT_FALSE(stringEndsWith("FooBar", "1FooBar"));
|
||||
EXPECT_FALSE(stringEndsWith("FooBar", "R"));
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::stringUtils::tests
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "core/ITraceLogger.hpp"
|
||||
@@ -33,11 +34,10 @@ namespace lms::core::tracing::tests
|
||||
std::vector<std::thread> threads;
|
||||
for (std::size_t i{}; i < 16; ++i)
|
||||
{
|
||||
threads.emplace_back([&]
|
||||
{
|
||||
ScopedTrace loggedEvent{ "MyCategory", Level::Overview, "MyEventLogged", "SomeArgType", "SomeArg", traceLogger.get() };
|
||||
ScopedTrace notLoggedEvent{ "MyNotLoggedCategory", Level::Detailed, "MyEventNotLogged", "SomeNotLoggedArgType", "SomeNotLoggedArg", traceLogger.get() };
|
||||
});
|
||||
threads.emplace_back([&] {
|
||||
ScopedTrace loggedEvent{ "MyCategory", Level::Overview, "MyEventLogged", "SomeArgType", "SomeArg", traceLogger.get() };
|
||||
ScopedTrace notLoggedEvent{ "MyNotLoggedCategory", Level::Detailed, "MyEventNotLogged", "SomeNotLoggedArgType", "SomeNotLoggedArg", traceLogger.get() };
|
||||
});
|
||||
}
|
||||
|
||||
for (std::thread& t : threads)
|
||||
@@ -56,4 +56,4 @@ namespace lms::core::tracing::tests
|
||||
EXPECT_EQ(oss.str().find("SomeNotLoggedArgType"), std::string::npos);
|
||||
EXPECT_EQ(oss.str().find("SomeNotLoggedArg"), std::string::npos);
|
||||
}
|
||||
}
|
||||
} // namespace lms::core::tracing::tests
|
||||
@@ -37,4 +37,4 @@ namespace lms::core
|
||||
EXPECT_TRUE(uuid1 >= uuid2);
|
||||
EXPECT_TRUE(uuid1 <= uuid2);
|
||||
}
|
||||
}
|
||||
} // namespace lms::core
|
||||
@@ -19,9 +19,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user