M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +21 -0
@@ 18,6 18,8 @@
#include <application-desktop/Constants.hpp>
#include <service-db/service-db/Settings.hpp>
#include <service-db/QueryMessage.hpp>
+#include <service-evtmgr/EventManager.hpp>
+#include <service-evtmgr/EVMessages.hpp>
#include <purefs/filesystem_paths.hpp>
#include <module-sys/SystemManager/SystemManager.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
@@ 81,6 83,25 @@ auto ServiceDesktop::getSerialNumber() const -> std::string
return settings->getValue(std::string("factory_data/serial"), settings::SettingsScope::Global);
}
+auto ServiceDesktop::requestLogsFlush() -> void
+{
+ int response = 0;
+ auto ret = bus.sendUnicastSync(
+ std::make_shared<sevm::FlushLogsRequest>(), service::name::evt_manager, DefaultLogFlushTimeoutInMs);
+
+ if (ret.first == sys::ReturnCodes::Success) {
+ auto responseMsg = std::dynamic_pointer_cast<sevm::FlushLogsResponse>(ret.second);
+ if ((responseMsg != nullptr) && (responseMsg->retCode == true)) {
+ response = responseMsg->data;
+
+ LOG_DEBUG("Respone data: %d", response);
+ }
+ }
+ if (ret.first == sys::ReturnCodes::Failure || response < 0) {
+ throw std::runtime_error("Logs flush failed");
+ }
+}
+
sys::ReturnCodes ServiceDesktop::InitHandler()
{
M module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp => module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.cpp +19 -0
@@ 38,10 38,29 @@ static bool isWritable(const fs::path &file)
return static_cast<bool>(sf);
}
+auto FilesystemEndpoint::requestLogsFlush() const -> void
+{
+ auto owner = dynamic_cast<ServiceDesktop *>(ownerServicePtr);
+ if (owner) {
+ owner->requestLogsFlush();
+ }
+}
+
auto FilesystemEndpoint::startGetFile(Context &context) const -> sys::ReturnCodes
{
std::filesystem::path filePath = context.getBody()[parserFSM::json::fileName].string_value();
+ try {
+ requestLogsFlush();
+ }
+ catch (const std::runtime_error &e) {
+ LOG_ERROR("Logs flush exception: %s", e.what());
+
+ context.setResponseStatus(parserFSM::http::Code::InternalServerError);
+ context.setResponseBody(json11::Json::object({{json::reason, std::string(e.what())}}));
+ return sys::ReturnCodes::Failure;
+ }
+
if (!std::filesystem::exists(filePath)) {
LOG_ERROR("file not found");
M module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.hpp => module-services/service-desktop/endpoints/filesystem/FilesystemEndpoint.hpp +2 -0
@@ 31,5 31,7 @@ class FilesystemEndpoint : public parserFSM::Endpoint
auto startSendFile(parserFSM::Context &context) const -> sys::ReturnCodes;
auto sendFileChunk(parserFSM::Context &context) const -> sys::ReturnCodes;
+ auto requestLogsFlush() const -> void;
+
FileOperations &fileOps;
};
M module-services/service-desktop/service-desktop/ServiceDesktop.hpp => module-services/service-desktop/service-desktop/ServiceDesktop.hpp +4 -0
@@ 109,12 109,16 @@ class ServiceDesktop : public sys::Service
return usbSecurityModel.get();
}
+ auto requestLogsFlush() -> void;
+
private:
auto getSerialNumber() const -> std::string;
std::unique_ptr<sdesktop::USBSecurityModel> usbSecurityModel;
std::unique_ptr<settings::Settings> settings;
sys::TimerHandle transferTimer;
std::unique_ptr<sdesktop::bluetooth::BluetoothMessagesHandler> btMsgHandler;
+
+ static constexpr unsigned int DefaultLogFlushTimeoutInMs = 1000U;
};
namespace sys
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +16 -9
@@ 45,11 45,12 @@
#include <EventStore.hpp>
#include <SystemManager/messages/PhoneModeRequest.hpp>
#include <vibra/Vibra.hpp>
+#include <ticks.hpp>
namespace
{
- constexpr auto loggerDelayMs = 1000 * 60 * 5;
- constexpr auto loggerTimerName = "Logger";
+ constexpr auto loggerDelayMs = 1000 * 60 * 5;
+ constexpr auto loggerTimerName = "Logger";
constexpr std::array sliderKeyCodes = {
bsp::KeyCodes::SSwitchUp, bsp::KeyCodes::SSwitchMid, bsp::KeyCodes::SSwitchDown};
@@ 281,6 282,13 @@ sys::ReturnCodes EventManager::InitHandler()
processTimezoneRequest(message->getTimezone());
return sys::MessageNone{};
});
+
+ connect(typeid(sevm::FlushLogsRequest), [&]([[maybe_unused]] sys::Message *msg) {
+ if (auto ret = dumpLogsToFile(); ret >= 0) {
+ return std::make_shared<sevm::FlushLogsResponse>(true, ret);
+ }
+ return std::make_shared<sevm::FlushLogsResponse>(false);
+ });
// initialize keyboard worker
EventWorker = std::make_unique<WorkerEvent>(this);
@@ 376,15 384,14 @@ void EventManager::handleKeyMoveEvent(RawKey key)
}
}
-void EventManager::dumpLogsToFile()
+int EventManager::dumpLogsToFile()
{
const auto logPath = purefs::dir::getUserDiskPath() / LOG_FILE_NAME;
- const bool dumpLog = !(std::filesystem::exists(logPath) && std::filesystem::file_size(logPath) > MAX_LOG_FILE_SIZE);
- if (dumpLog) {
- const auto &logs = Log::Logger::get().getLogs();
- std::fstream logFile(logPath, std::fstream::out | std::fstream::app);
- logFile.write(logs.data(), logs.size());
- }
+ const auto ts = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
+
+ LOG_DEBUG("Log flush timestamp: %d", static_cast<unsigned>(ts));
+
+ return Log::Logger::get().dumpToFile(std::move(logPath));
}
void EventManager::handleMinuteUpdate(time_t timestamp)
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +14 -0
@@ 138,4 138,18 @@ namespace sevm
std::chrono::milliseconds repetitionTime;
};
+ class FlushLogsRequest : public sys::DataMessage
+ {};
+
+ class FlushLogsResponse : public sys::ResponseMessage
+ {
+ public:
+ FlushLogsResponse(bool retCode, int retData = 0)
+ : sys::ResponseMessage(sys::ReturnCodes::Success, MessageType::MessageTypeUninitialized), retCode(retCode),
+ data(retData){};
+
+ const bool retCode{};
+ const int data{};
+ };
+
} /* namespace sevm*/
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +4 -1
@@ 79,7 79,10 @@ class EventManager : public sys::Service
sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final;
- void dumpLogsToFile();
+ /// @return: < 0 - An error occurred during log flush
+ /// @return: 0 - Log file reached max size
+ /// @return: 1 - Logs flushed successflully
+ int dumpLogsToFile();
/**
* @brief Sends request to application manager to switch from current application to specific window in application
M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +38 -0
@@ 118,4 118,42 @@ namespace Log
return loggerBufferCurrentPos;
}
+
+ /// @param logPath: file path to store the log
+ /// @return: < 0 - error occured during log flush
+ /// @return: 0 - log flush did not happen
+ /// @return: 1 - log flush successflul
+ auto Logger::dumpToFile(std::filesystem::path logPath) -> int
+ {
+ int status = 0;
+ const bool dumpLog =
+ !(std::filesystem::exists(logPath) && std::filesystem::file_size(logPath) > MAX_LOG_FILE_SIZE);
+ if (!dumpLog) {
+ LOG_DEBUG("Flush skipped");
+ return 0;
+ }
+
+ {
+ status = 1;
+
+ const auto &logs = getLogs();
+
+ LockGuard lock(mutex);
+ std::fstream logFile(logPath, std::fstream::out | std::fstream::app);
+
+ if (!logFile.good()) {
+ status = -EIO;
+ }
+
+ logFile.write(logs.data(), logs.size());
+ if (logFile.bad()) {
+ status = -EIO;
+ }
+ }
+
+ LOG_DEBUG("Flush ended with status: %d", status);
+
+ return status;
+ }
+
}; // namespace Log
M module-utils/log/Logger.hpp => module-utils/log/Logger.hpp +2 -0
@@ 11,6 11,7 @@
#include <map>
#include <mutex.hpp>
#include <string>
+#include <filesystem>
namespace Log
{
@@ 35,6 36,7 @@ namespace Log
auto log(logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args)
-> int;
auto logAssert(const char *fmt, va_list args) -> int;
+ auto dumpToFile(std::filesystem::path logPath) -> int;
static constexpr auto CRIT_STR = "CRIT";
static constexpr auto IRQ_STR = "IRQ";
M test/harness => test/harness +1 -1
@@ 1,1 1,1 @@
-Subproject commit b1ae209e9c257f8f62b3023ca30a361bd4d01e21
+Subproject commit eecee32772ba2f7ad838535bc1fc99e707205d8e