Simplified logger configuration, it no longer depends on Wt
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
namespace Zip
|
||||
{
|
||||
@@ -73,7 +73,7 @@ namespace Zip
|
||||
{
|
||||
const int res {::archive_write_free(arch)};
|
||||
if (res != ARCHIVE_OK)
|
||||
LMS_LOG(UTILS, ERROR) << "Failure while freeing archive control struct: " << std::string {::strerror(res)};
|
||||
LMS_LOG(UTILS, ERROR, "Failure while freeing archive control struct: " << std::string {::strerror(res)});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -176,7 +176,7 @@ namespace Zip
|
||||
void
|
||||
ArchiveZipper::abort()
|
||||
{
|
||||
LMS_LOG(UTILS, DEBUG) << "Aborting zip creation";
|
||||
LMS_LOG(UTILS, DEBUG, "Aborting zip creation");
|
||||
if (_archive)
|
||||
{
|
||||
::archive_write_fail(_archive.get());
|
||||
|
||||
@@ -36,177 +36,172 @@
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class SystemException : public ChildProcessException
|
||||
{
|
||||
public:
|
||||
SystemException(int err, const std::string& errMsg)
|
||||
: ChildProcessException {errMsg + ": " + ::strerror(err)}
|
||||
{}
|
||||
class SystemException : public ChildProcessException
|
||||
{
|
||||
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()}
|
||||
{}
|
||||
};
|
||||
SystemException(boost::system::error_code ec, const std::string& errMsg)
|
||||
: ChildProcessException{ errMsg + ": " + ec.message() }
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
ChildProcess::ChildProcess(boost::asio::io_context& ioContext, const std::filesystem::path& path, const Args& args)
|
||||
: _ioContext {ioContext}
|
||||
, _childStdout {_ioContext}
|
||||
: _ioContext{ ioContext }
|
||||
, _childStdout{ _ioContext }
|
||||
|
||||
{
|
||||
// make sure only one thread is executing this part of code
|
||||
static std::mutex mutex;
|
||||
std::unique_lock<std::mutex> lock {mutex};
|
||||
// make sure only one thread is executing this part of code
|
||||
static std::mutex mutex;
|
||||
std::unique_lock<std::mutex> lock{ mutex };
|
||||
|
||||
int pipe[2];
|
||||
int pipe[2];
|
||||
|
||||
int res {pipe2(pipe, O_NONBLOCK | O_CLOEXEC)};
|
||||
if (res < 0)
|
||||
throw SystemException {errno, "pipe2 failed!"};
|
||||
int res{ pipe2(pipe, O_NONBLOCK | O_CLOEXEC) };
|
||||
if (res < 0)
|
||||
throw SystemException{ errno, "pipe2 failed!" };
|
||||
|
||||
{
|
||||
{
|
||||
#if defined(__linux__) && defined(F_SETPIPE_SZ)
|
||||
// Just a hint here to prevent the writer from writing too many bytes ahead of the reader
|
||||
constexpr std::size_t pipeSize {65536*4};
|
||||
// Just a hint here to prevent the writer from writing too many bytes ahead of the reader
|
||||
constexpr std::size_t pipeSize{ 65536 * 4 };
|
||||
|
||||
if (fcntl(pipe[0], F_SETPIPE_SZ, pipeSize) == -1)
|
||||
throw SystemException {errno, "fcntl failed!"};
|
||||
if (fcntl(pipe[1], F_SETPIPE_SZ, pipeSize) == -1)
|
||||
throw SystemException {errno, "fcntl failed!"};
|
||||
if (fcntl(pipe[0], F_SETPIPE_SZ, pipeSize) == -1)
|
||||
throw SystemException{ errno, "fcntl failed!" };
|
||||
if (fcntl(pipe[1], F_SETPIPE_SZ, pipeSize) == -1)
|
||||
throw SystemException{ errno, "fcntl failed!" };
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1)
|
||||
throw SystemException {errno, "fork failed!"};
|
||||
res = fork();
|
||||
if (res == -1)
|
||||
throw SystemException{ errno, "fork failed!" };
|
||||
|
||||
if (res == 0) // CHILD
|
||||
{
|
||||
close(pipe[0]);
|
||||
close(STDIN_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
if (res == 0) // CHILD
|
||||
{
|
||||
close(pipe[0]);
|
||||
close(STDIN_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
|
||||
// Replace stdout with pipe write
|
||||
if (dup2(pipe[1], STDOUT_FILENO) == -1)
|
||||
exit(-1);
|
||||
// Replace stdout with pipe write
|
||||
if (dup2(pipe[1], STDOUT_FILENO) == -1)
|
||||
exit(-1);
|
||||
|
||||
std::vector<const char*> execArgs;
|
||||
std::transform(std::cbegin(args), std::cend(args), std::back_inserter(execArgs), [](const std::string& arg) { return arg.c_str(); });
|
||||
execArgs.push_back(nullptr);
|
||||
std::vector<const char*> execArgs;
|
||||
std::transform(std::cbegin(args), std::cend(args), std::back_inserter(execArgs), [](const std::string& arg) { return arg.c_str(); });
|
||||
execArgs.push_back(nullptr);
|
||||
|
||||
res = execv(path.string().c_str(), (char *const*)&execArgs[0]);
|
||||
if (res == -1)
|
||||
exit(-1);
|
||||
}
|
||||
else // PARENT
|
||||
{
|
||||
close(pipe[1]);
|
||||
{
|
||||
boost::system::error_code assignError;
|
||||
_childStdout.assign(pipe[0], assignError);
|
||||
if (assignError)
|
||||
throw SystemException {assignError, "fork failed!"};
|
||||
}
|
||||
_childPID = res;
|
||||
}
|
||||
res = execv(path.string().c_str(), (char* const*)&execArgs[0]);
|
||||
if (res == -1)
|
||||
exit(-1);
|
||||
}
|
||||
else // PARENT
|
||||
{
|
||||
close(pipe[1]);
|
||||
{
|
||||
boost::system::error_code assignError;
|
||||
_childStdout.assign(pipe[0], assignError);
|
||||
if (assignError)
|
||||
throw SystemException{ assignError, "fork failed!" };
|
||||
}
|
||||
_childPID = res;
|
||||
}
|
||||
}
|
||||
|
||||
ChildProcess::~ChildProcess()
|
||||
{
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "Closing child process...";
|
||||
{
|
||||
boost::system::error_code closeError;
|
||||
_childStdout.close(closeError);
|
||||
if (closeError)
|
||||
LMS_LOG(CHILDPROCESS, ERROR) << "Closed failed: " << closeError.message();
|
||||
}
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Closing child process...");
|
||||
{
|
||||
boost::system::error_code closeError;
|
||||
_childStdout.close(closeError);
|
||||
if (closeError)
|
||||
LMS_LOG(CHILDPROCESS, ERROR, "Closed failed: " << closeError.message());
|
||||
}
|
||||
|
||||
if (!_finished)
|
||||
kill();
|
||||
if (!_finished)
|
||||
kill();
|
||||
|
||||
wait(true);
|
||||
wait(true);
|
||||
}
|
||||
|
||||
void
|
||||
ChildProcess::kill()
|
||||
void ChildProcess::kill()
|
||||
{
|
||||
// process may already have finished
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "Killing child process...";
|
||||
if (::kill(_childPID, SIGKILL) == -1)
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "Kill failed: " << ::strerror(errno);
|
||||
// process may already have finished
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Killing child process...");
|
||||
if (::kill(_childPID, SIGKILL) == -1)
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Kill failed: " << ::strerror(errno));
|
||||
}
|
||||
|
||||
bool
|
||||
ChildProcess::wait(bool block)
|
||||
bool ChildProcess::wait(bool block)
|
||||
{
|
||||
assert(!_waited);
|
||||
assert(!_waited);
|
||||
|
||||
int wstatus {};
|
||||
const pid_t pid {waitpid(_childPID, &wstatus, block ? 0 : WNOHANG)};
|
||||
int wstatus{};
|
||||
const pid_t pid{ waitpid(_childPID, &wstatus, block ? 0 : WNOHANG) };
|
||||
|
||||
if (pid == -1)
|
||||
throw SystemException {errno, "waitpid failed!"};
|
||||
else if (pid == 0)
|
||||
return false;
|
||||
if (pid == -1)
|
||||
throw SystemException{ errno, "waitpid failed!" };
|
||||
else if (pid == 0)
|
||||
return false;
|
||||
|
||||
if (WIFEXITED(wstatus))
|
||||
{
|
||||
_exitCode = WEXITSTATUS(wstatus);
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "Exit code = " << *_exitCode;
|
||||
}
|
||||
if (WIFEXITED(wstatus))
|
||||
{
|
||||
_exitCode = WEXITSTATUS(wstatus);
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Exit code = " << *_exitCode);
|
||||
}
|
||||
|
||||
_waited = true;
|
||||
return true;
|
||||
_waited = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ChildProcess::asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback)
|
||||
void ChildProcess::asyncRead(std::byte* data, std::size_t bufferSize, ReadCallback callback)
|
||||
{
|
||||
assert(!finished());
|
||||
assert(!finished());
|
||||
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "Async read, bufferSize = " << bufferSize;
|
||||
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)
|
||||
{
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "Async read cb - ec = '" << error.message() << "' (" << error.value() << "), bytesTransferred = " << bytesTransferred;
|
||||
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)
|
||||
{
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "Async read cb - ec = '" << error.message() << "' (" << error.value() << "), bytesTransferred = " << bytesTransferred);
|
||||
|
||||
ReadResult readResult {ReadResult::Success};
|
||||
if (error)
|
||||
{
|
||||
if (error != boost::asio::error::eof)
|
||||
{
|
||||
// forbidden to read any captured param here as the ChildProcess instance may already have been killed
|
||||
return;
|
||||
}
|
||||
ReadResult readResult{ ReadResult::Success };
|
||||
if (error)
|
||||
{
|
||||
if (error != boost::asio::error::eof)
|
||||
{
|
||||
// forbidden to read any captured param here as the ChildProcess instance may already have been killed
|
||||
return;
|
||||
}
|
||||
|
||||
readResult = ReadResult::EndOfFile;
|
||||
_finished = true;
|
||||
}
|
||||
readResult = ReadResult::EndOfFile;
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
callback(readResult, bytesTransferred);
|
||||
});
|
||||
callback(readResult, bytesTransferred);
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t
|
||||
ChildProcess::readSome(std::byte* data, std::size_t bufferSize)
|
||||
std::size_t ChildProcess::readSome(std::byte* data, std::size_t bufferSize)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
const std::size_t res {_childStdout.read_some(boost::asio::buffer(data, bufferSize), ec)};
|
||||
LMS_LOG(CHILDPROCESS, DEBUG) << "read some " << res << " bytes, ec = " << ec.message();
|
||||
if (ec)
|
||||
_childStdout.close(ec);
|
||||
boost::system::error_code ec;
|
||||
const std::size_t res{ _childStdout.read_some(boost::asio::buffer(data, bufferSize), ec) };
|
||||
LMS_LOG(CHILDPROCESS, DEBUG, "read some " << res << " bytes, ec = " << ec.message());
|
||||
if (ec)
|
||||
_childStdout.close(ec);
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
ChildProcess::finished() const
|
||||
bool ChildProcess::finished() const
|
||||
{
|
||||
return _finished;
|
||||
return _finished;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "ChildProcessManager.hpp"
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
#include "ChildProcess.hpp"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "Config.hpp"
|
||||
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
std::unique_ptr<IConfig> createConfig(const std::filesystem::path& p)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
std::unique_ptr<IResourceHandler>
|
||||
createFileResourceHandler(const std::filesystem::path& path, std::string_view mimeType)
|
||||
@@ -45,7 +45,7 @@ FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::
|
||||
{
|
||||
if (!ifs)
|
||||
{
|
||||
LMS_LOG(UTILS, ERROR) << "Cannot open file stream for '" << _path.string() << "'";
|
||||
LMS_LOG(UTILS, ERROR, "Cannot open file stream for '" << _path.string() << "'");
|
||||
response.setStatus(404);
|
||||
return {};
|
||||
}
|
||||
@@ -54,7 +54,7 @@ FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::
|
||||
const ::uint64_t fileSize{ static_cast<::uint64_t>(ifs.tellg()) };
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
|
||||
LMS_LOG(UTILS, DEBUG) << "File '" << _path.string() << "', fileSize = " << fileSize;
|
||||
LMS_LOG(UTILS, DEBUG, "File '" << _path.string() << "', fileSize = " << fileSize);
|
||||
|
||||
response.addHeader("Accept-Ranges", "bytes");
|
||||
|
||||
@@ -66,13 +66,13 @@ FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::
|
||||
response.setStatus(416); // Requested range not satisfiable
|
||||
response.addHeader("Content-Range", contentRange.str());
|
||||
|
||||
LMS_LOG(UTILS, DEBUG) << "Range not satisfiable";
|
||||
LMS_LOG(UTILS, DEBUG, "Range not satisfiable");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (ranges.size() == 1)
|
||||
{
|
||||
LMS_LOG(UTILS, DEBUG) << "Range requested = " << ranges[0].firstByte() << "/" << ranges[0].lastByte();
|
||||
LMS_LOG(UTILS, DEBUG, "Range requested = " << ranges[0].firstByte() << "-" << ranges[0].lastByte());
|
||||
|
||||
response.setStatus(206);
|
||||
startByte = ranges[0].firstByte();
|
||||
@@ -87,19 +87,19 @@ FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(UTILS, DEBUG) << "No range requested";
|
||||
LMS_LOG(UTILS, DEBUG, "No range requested");
|
||||
|
||||
response.setStatus(200);
|
||||
_beyondLastByte = fileSize;
|
||||
response.setContentLength(_beyondLastByte);
|
||||
}
|
||||
|
||||
LMS_LOG(UTILS, DEBUG) << "Mimetype set to '" << _mimeType << "'";
|
||||
LMS_LOG(UTILS, DEBUG, "Mimetype set to '" << _mimeType << "'");
|
||||
response.setMimeType(_mimeType);
|
||||
}
|
||||
else if (!ifs)
|
||||
{
|
||||
LMS_LOG(UTILS, ERROR) << "Cannot reopen file stream for '" << _path.string() << "'";
|
||||
LMS_LOG(UTILS, ERROR, "Cannot reopen file stream for '" << _path.string() << "'");
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -113,19 +113,24 @@ FileResourceHandler::processRequest(const Wt::Http::Request& request, Wt::Http::
|
||||
|
||||
ifs.read(&buf[0], pieceSize);
|
||||
const ::uint64_t actualPieceSize{ static_cast<::uint64_t>(ifs.gcount()) };
|
||||
response.out().write(&buf[0], actualPieceSize);
|
||||
if (actualPieceSize > 0)
|
||||
{
|
||||
response.out().write(&buf[0], actualPieceSize);
|
||||
LMS_LOG(UTILS, DEBUG, "Written " << actualPieceSize << " bytes, range = " << startByte << "-" << startByte + actualPieceSize - 1 << "");
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(UTILS, DEBUG, "Written 0 byte");
|
||||
}
|
||||
|
||||
LMS_LOG(UTILS, DEBUG) << "Written " << actualPieceSize << " bytes";
|
||||
|
||||
LMS_LOG(UTILS, DEBUG) << "Progress: " << actualPieceSize << "/" << restSize;
|
||||
if (ifs.good() && actualPieceSize < restSize)
|
||||
{
|
||||
_offset = startByte + actualPieceSize;
|
||||
LMS_LOG(UTILS, DEBUG) << "Job not complete! Next chunk offset = " << _offset;
|
||||
LMS_LOG(UTILS, DEBUG, "Job not complete! Remaining range: " << _offset << "-" << _beyondLastByte - 1);
|
||||
|
||||
return response.createContinuation();
|
||||
}
|
||||
|
||||
LMS_LOG(UTILS, DEBUG) << "Job complete!";
|
||||
LMS_LOG(UTILS, DEBUG, "Job complete!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
IOContextRunner::IOContextRunner(boost::asio::io_service& ioService, std::size_t threadCount)
|
||||
: _ioService {ioService}
|
||||
, _work {ioService}
|
||||
{
|
||||
LMS_LOG(UTILS, INFO) << "Starting IO context with " << threadCount << " threads...";
|
||||
LMS_LOG(UTILS, INFO, "Starting IO context with " << threadCount << " threads...");
|
||||
for (std::size_t i {}; i < threadCount; ++i)
|
||||
{
|
||||
_threads.emplace_back([&]
|
||||
@@ -38,7 +38,7 @@ IOContextRunner::IOContextRunner(boost::asio::io_service& ioService, std::size_t
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LMS_LOG(UTILS, FATAL) << "Exception caught in IO context: " << e.what();
|
||||
LMS_LOG(UTILS, FATAL, "Exception caught in IO context: " << e.what());
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
@@ -48,10 +48,10 @@ IOContextRunner::IOContextRunner(boost::asio::io_service& ioService, std::size_t
|
||||
void
|
||||
IOContextRunner::stop()
|
||||
{
|
||||
LMS_LOG(UTILS, DEBUG) << "Stopping IO context...";
|
||||
LMS_LOG(UTILS, DEBUG, "Stopping IO context...");
|
||||
_work.reset();
|
||||
_ioService.stop();
|
||||
LMS_LOG(UTILS, DEBUG) << "IO context stopped!";
|
||||
LMS_LOG(UTILS, DEBUG, "IO context stopped!");
|
||||
}
|
||||
|
||||
IOContextRunner::~IOContextRunner()
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
|
||||
const char* getModuleName(Module mod)
|
||||
{
|
||||
@@ -59,20 +59,19 @@ const char* getSeverityName(Severity sev)
|
||||
return "";
|
||||
}
|
||||
|
||||
Log::Log(Logger* logger, Module module, Severity severity)
|
||||
: _module{ module },
|
||||
_severity{ severity },
|
||||
_logger{ logger }
|
||||
Log::Log(ILogger& logger, Module module, Severity severity)
|
||||
: _logger{ logger }
|
||||
, _module{ module }
|
||||
, _severity{ severity }
|
||||
|
||||
{}
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
if (_logger)
|
||||
_logger->processLog(*this);
|
||||
_logger.processLog(*this);
|
||||
}
|
||||
|
||||
std::string
|
||||
Log::getMessage() const
|
||||
std::string Log::getMessage() const
|
||||
{
|
||||
return _oss.str();
|
||||
}
|
||||
|
||||
+104
-114
@@ -30,146 +30,136 @@
|
||||
|
||||
#include "utils/Crc32Calculator.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "utils/String.hpp"
|
||||
|
||||
namespace PathUtils
|
||||
{
|
||||
std::uint32_t computeCrc32(const std::filesystem::path& p)
|
||||
{
|
||||
Utils::Crc32Calculator crc32;
|
||||
|
||||
std::uint32_t
|
||||
computeCrc32(const std::filesystem::path& p)
|
||||
{
|
||||
Utils::Crc32Calculator crc32;
|
||||
std::ifstream ifs{ p.string().c_str(), std::ios_base::binary };
|
||||
if (ifs)
|
||||
{
|
||||
do
|
||||
{
|
||||
std::array<char, 1024> buffer;
|
||||
|
||||
std::ifstream ifs {p.string().c_str(), std::ios_base::binary};
|
||||
if (ifs)
|
||||
{
|
||||
do
|
||||
{
|
||||
std::array<char,1024> buffer;
|
||||
ifs.read(buffer.data(), buffer.size());
|
||||
crc32.processBytes(reinterpret_cast<const std::byte*>(buffer.data()), ifs.gcount());
|
||||
} while (ifs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR, "Failed to open file '" << p.string() << "'");
|
||||
throw LmsException("Failed to open file '" + p.string() + "'");
|
||||
}
|
||||
|
||||
ifs.read( buffer.data(), buffer.size() );
|
||||
crc32.processBytes( reinterpret_cast<const std::byte*>(buffer.data()), ifs.gcount() );
|
||||
}
|
||||
while (ifs);
|
||||
}
|
||||
else
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR) << "Failed to open file '" << p.string() << "'";
|
||||
throw LmsException("Failed to open file '" + p.string() + "'" );
|
||||
}
|
||||
return crc32.getResult();
|
||||
}
|
||||
|
||||
return crc32.getResult();
|
||||
}
|
||||
bool ensureDirectory(const std::filesystem::path& dir)
|
||||
{
|
||||
if (std::filesystem::exists(dir))
|
||||
return std::filesystem::is_directory(dir);
|
||||
else
|
||||
return std::filesystem::create_directory(dir);
|
||||
}
|
||||
|
||||
bool
|
||||
ensureDirectory(const std::filesystem::path& dir)
|
||||
{
|
||||
if (std::filesystem::exists(dir))
|
||||
return std::filesystem::is_directory(dir);
|
||||
else
|
||||
return std::filesystem::create_directory(dir);
|
||||
}
|
||||
Wt::WDateTime getLastWriteTime(const std::filesystem::path& file)
|
||||
{
|
||||
struct stat sb {};
|
||||
|
||||
Wt::WDateTime
|
||||
getLastWriteTime(const std::filesystem::path& file)
|
||||
{
|
||||
struct stat sb {};
|
||||
if (stat(file.string().c_str(), &sb) == -1)
|
||||
throw LmsException("Failed to get stats on file '" + file.string() + "'");
|
||||
|
||||
if (stat(file.string().c_str(), &sb) == -1)
|
||||
throw LmsException("Failed to get stats on file '" + file.string() + "'" );
|
||||
return Wt::WDateTime::fromTime_t(sb.st_mtime);
|
||||
}
|
||||
|
||||
return Wt::WDateTime::fromTime_t(sb.st_mtime);
|
||||
}
|
||||
bool exploreFilesRecursive(const std::filesystem::path& directory, std::function<bool(std::error_code, const std::filesystem::path&)> cb, const std::filesystem::path* excludeDirFileName)
|
||||
{
|
||||
std::error_code ec;
|
||||
std::filesystem::directory_iterator itPath{ directory, std::filesystem::directory_options::follow_directory_symlink, ec };
|
||||
|
||||
bool
|
||||
exploreFilesRecursive(const std::filesystem::path& directory, std::function<bool(std::error_code, const std::filesystem::path&)> cb, const std::filesystem::path* excludeDirFileName)
|
||||
{
|
||||
std::error_code ec;
|
||||
std::filesystem::directory_iterator itPath {directory, std::filesystem::directory_options::follow_directory_symlink, ec};
|
||||
if (ec)
|
||||
{
|
||||
cb(ec, directory);
|
||||
return true; // try to continue exploring anyway
|
||||
}
|
||||
|
||||
if (ec)
|
||||
{
|
||||
cb(ec, directory);
|
||||
return true; // try to continue exploring anyway
|
||||
}
|
||||
if (excludeDirFileName && !excludeDirFileName->empty())
|
||||
{
|
||||
const std::filesystem::path excludePath{ directory / *excludeDirFileName };
|
||||
|
||||
if (excludeDirFileName && !excludeDirFileName->empty())
|
||||
{
|
||||
const std::filesystem::path excludePath {directory / *excludeDirFileName};
|
||||
if (std::filesystem::exists(excludePath, ec))
|
||||
{
|
||||
LMS_LOG(DBUPDATER, DEBUG, "Found '" << excludePath.string() << "': skipping directory");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(excludePath, ec))
|
||||
{
|
||||
LMS_LOG(DBUPDATER, DEBUG) << "Found '" << excludePath.string() << "': skipping directory";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
std::filesystem::directory_iterator itEnd;
|
||||
while (itPath != itEnd)
|
||||
{
|
||||
bool continueExploring{ true };
|
||||
|
||||
std::filesystem::directory_iterator itEnd;
|
||||
while (itPath != itEnd)
|
||||
{
|
||||
bool continueExploring {true};
|
||||
if (ec)
|
||||
{
|
||||
continueExploring = cb(ec, *itPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::filesystem::is_regular_file(*itPath, ec))
|
||||
{
|
||||
continueExploring = cb(ec, *itPath);
|
||||
}
|
||||
else if (std::filesystem::is_directory(*itPath, ec))
|
||||
{
|
||||
if (!ec)
|
||||
continueExploring = exploreFilesRecursive(*itPath, cb, excludeDirFileName);
|
||||
else
|
||||
continueExploring = cb(ec, *itPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (ec)
|
||||
{
|
||||
continueExploring = cb(ec, *itPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::filesystem::is_regular_file(*itPath, ec))
|
||||
{
|
||||
continueExploring = cb(ec, *itPath);
|
||||
}
|
||||
else if (std::filesystem::is_directory(*itPath, ec))
|
||||
{
|
||||
if (!ec)
|
||||
continueExploring = exploreFilesRecursive(*itPath, cb, excludeDirFileName);
|
||||
else
|
||||
continueExploring = cb(ec, *itPath);
|
||||
}
|
||||
}
|
||||
if (!continueExploring)
|
||||
return false;
|
||||
|
||||
if (!continueExploring)
|
||||
return false;
|
||||
itPath.increment(ec);
|
||||
}
|
||||
|
||||
itPath.increment(ec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool hasFileAnyExtension(const std::filesystem::path& file, const std::vector<std::filesystem::path>& supportedExtensions)
|
||||
{
|
||||
const std::filesystem::path extension{ StringUtils::stringToLower(file.extension().string()) };
|
||||
|
||||
bool
|
||||
hasFileAnyExtension(const std::filesystem::path& file, const std::vector<std::filesystem::path>& supportedExtensions)
|
||||
{
|
||||
const std::filesystem::path extension {StringUtils::stringToLower(file.extension().string())};
|
||||
return (std::find(std::cbegin(supportedExtensions), std::cend(supportedExtensions), extension) != std::cend(supportedExtensions));
|
||||
}
|
||||
|
||||
return (std::find(std::cbegin(supportedExtensions), std::cend(supportedExtensions), extension) != std::cend(supportedExtensions));
|
||||
}
|
||||
bool isPathInRootPath(const std::filesystem::path& path, const std::filesystem::path& rootPath, const std::filesystem::path* excludeDirFileName)
|
||||
{
|
||||
std::filesystem::path curPath = path;
|
||||
|
||||
bool
|
||||
isPathInRootPath(const std::filesystem::path& path, const std::filesystem::path& rootPath, const std::filesystem::path* excludeDirFileName)
|
||||
{
|
||||
std::filesystem::path curPath = path;
|
||||
while (curPath.parent_path() != curPath)
|
||||
{
|
||||
curPath = curPath.parent_path();
|
||||
|
||||
while (curPath.parent_path() != curPath)
|
||||
{
|
||||
curPath = curPath.parent_path();
|
||||
if (excludeDirFileName && !excludeDirFileName->empty())
|
||||
{
|
||||
assert(!excludeDirFileName->has_parent_path());
|
||||
|
||||
if (excludeDirFileName && !excludeDirFileName->empty())
|
||||
{
|
||||
assert(!excludeDirFileName->has_parent_path());
|
||||
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(curPath / *excludeDirFileName, ec))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (curPath == rootPath)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
std::error_code ec;
|
||||
if (std::filesystem::exists(curPath / *excludeDirFileName, ec))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (curPath == rootPath)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // ns PathUtils
|
||||
|
||||
@@ -170,6 +170,22 @@ namespace StringUtils
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string joinStrings(const std::vector<std::string_view>& strings, std::string_view delimiter)
|
||||
{
|
||||
std::string res;
|
||||
bool first{ true };
|
||||
|
||||
for (std::string_view str : strings)
|
||||
{
|
||||
if (!first)
|
||||
res += delimiter;
|
||||
res += str;
|
||||
first = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string joinStrings(const std::vector<std::string>& strings, const std::string& delimiter)
|
||||
{
|
||||
return boost::algorithm::join(strings, delimiter);
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
|
||||
#include <thread>
|
||||
#include <sstream>
|
||||
#include <Wt/WApplication.h>
|
||||
#include <Wt/WServer.h>
|
||||
#include <Wt/WLogger.h>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/Exception.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -36,6 +36,30 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
WtLogger::WtLogger(Severity minSeverity)
|
||||
: _minSeverity{ minSeverity }
|
||||
{
|
||||
}
|
||||
|
||||
std::string WtLogger::computeLogConfig(Severity minSeverity)
|
||||
{
|
||||
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";
|
||||
}
|
||||
|
||||
throw LmsException{ "Unhandled severity" };
|
||||
}
|
||||
|
||||
bool WtLogger::isSeverityActive(Severity severity) const
|
||||
{
|
||||
return static_cast<int>(severity) <= static_cast<int>(_minSeverity);
|
||||
}
|
||||
|
||||
void WtLogger::processLog(const Log& log)
|
||||
{
|
||||
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();
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
#include "utils/ILogger.hpp"
|
||||
#include "utils/String.hpp"
|
||||
|
||||
#define LOG(sev) LMS_LOG(SCROBBLING, sev) << "[Http SendQueue] - "
|
||||
#define LOG(sev, message) LMS_LOG(SCROBBLING, sev, "[Http SendQueue] - " << message)
|
||||
|
||||
namespace StringUtils
|
||||
{
|
||||
@@ -98,7 +98,7 @@ namespace Http
|
||||
|
||||
for (auto& [prio, requests] : _sendQueue)
|
||||
{
|
||||
LOG(DEBUG) << "Processing prio " << static_cast<int>(prio) << ", request count = " << requests.size();
|
||||
LOG(DEBUG, "Processing prio " << static_cast<int>(prio) << ", request count = " << requests.size());
|
||||
while (!requests.empty())
|
||||
{
|
||||
std::unique_ptr<ClientRequest> request {std::move(requests.front())};
|
||||
@@ -118,7 +118,7 @@ namespace Http
|
||||
SendQueue::sendRequest(const ClientRequest& request)
|
||||
{
|
||||
std::string url {_baseUrl + request.getParameters().relativeUrl};
|
||||
LOG(DEBUG) << "Sending request to url '" << url << "'";
|
||||
LOG(DEBUG, "Sending request to url '" << url << "'");
|
||||
|
||||
bool res {};
|
||||
switch (request.getType())
|
||||
@@ -133,7 +133,7 @@ namespace Http
|
||||
}
|
||||
|
||||
if (!res)
|
||||
LOG(ERROR) << "Send failed, bad url or unsupported scheme?";
|
||||
LOG(ERROR, "Send failed, bad url or unsupported scheme?");
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -143,14 +143,14 @@ namespace Http
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
{
|
||||
LOG(DEBUG) << "Client aborted";
|
||||
LOG(DEBUG, "Client aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(_currentRequest);
|
||||
_state = State::Idle;
|
||||
|
||||
LOG(DEBUG) << "Client done. status = " << msg.status();
|
||||
LOG(DEBUG, "Client done. status = " << msg.status());
|
||||
if (ec)
|
||||
onClientDoneError(std::move(_currentRequest), ec);
|
||||
else
|
||||
@@ -160,7 +160,7 @@ namespace Http
|
||||
void
|
||||
SendQueue::onClientDoneError(std::unique_ptr<ClientRequest> request, Wt::AsioWrapper::error_code ec)
|
||||
{
|
||||
LOG(ERROR) << "Retry " << request->retryCount << ", client error: '" << ec.message() << "'";
|
||||
LOG(ERROR, "Retry " << request->retryCount << ", client error: '" << ec.message() << "'");
|
||||
|
||||
// may be a network error, try again later
|
||||
throttle(_defaultRetryWaitDuration);
|
||||
@@ -171,7 +171,7 @@ namespace Http
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR) << "Too many retries, giving up operation and throttle";
|
||||
LOG(ERROR, "Too many retries, giving up operation and throttle");
|
||||
if (request->getParameters().onFailureFunc)
|
||||
request->getParameters().onFailureFunc();
|
||||
}
|
||||
@@ -189,7 +189,7 @@ namespace Http
|
||||
}
|
||||
|
||||
const auto remainingCount {headerReadAs<std::size_t>(msg, "X-RateLimit-Remaining")};
|
||||
LOG(DEBUG) << "Remaining messages = " << (remainingCount ? *remainingCount : 0);
|
||||
LOG(DEBUG, "Remaining messages = " << (remainingCount ? *remainingCount : 0));
|
||||
if (mustThrottle || (remainingCount && *remainingCount == 0))
|
||||
{
|
||||
const auto waitDuration {headerReadAs<std::chrono::seconds>(msg, "X-RateLimit-Reset-In")};
|
||||
@@ -205,7 +205,7 @@ namespace Http
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR) << "Send error: '" << msg.body() << "'";
|
||||
LOG(ERROR, "Send error: '" << msg.body() << "'");
|
||||
if (requestParameters.onFailureFunc)
|
||||
requestParameters.onFailureFunc();
|
||||
}
|
||||
@@ -221,14 +221,14 @@ namespace Http
|
||||
assert(_state == State::Idle);
|
||||
|
||||
const std::chrono::seconds duration {clamp(requestedDuration, _minRetryWaitDuration, _maxRetryWaitDuration)};
|
||||
LOG(DEBUG) << "Throttling for " << duration.count() << " seconds";
|
||||
LOG(DEBUG, "Throttling for " << duration.count() << " seconds");
|
||||
|
||||
_throttleTimer.expires_after(duration);
|
||||
_throttleTimer.async_wait([this](const boost::system::error_code& ec)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
{
|
||||
LOG(DEBUG) << "Throttle aborted";
|
||||
LOG(DEBUG, "Throttle aborted");
|
||||
return;
|
||||
}
|
||||
else if (ec)
|
||||
|
||||
Reference in New Issue
Block a user