M board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +0 -1
@@ 60,7 60,6 @@ void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elem
CrashCatcherReturnCodes CrashCatcher_DumpEnd(void)
{
cwrite.saveDump();
- cwrite.deleteOldDump();
_exit_backtrace(-1, false);
return CRASH_CATCHER_EXIT;
}
M board/rt1051/crashdump/crashdumpwriter_vfs.cpp => board/rt1051/crashdump/crashdumpwriter_vfs.cpp +11 -20
@@ 18,19 18,23 @@
namespace
{
- constexpr inline auto suffix = "_crashdump.hex";
+ constexpr inline auto suffix = "_crashdump.hex";
+ constexpr inline auto file_index = ".1";
// Crashdump filename pattern:
- // [serial-number]_[timestamp-in-seconds]_crashdump.hex
+ // [serial-number]_[timestamp-in-seconds]_crashdump.hex.[index]
+ // [index] was added to ensure resistance to the device date retraction
inline std::string generate_crashdump_filename()
{
const auto crash_time =
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch())
.count();
- auto filename = std::string("/") + crashdump::getSerialNumber() + "_" + std::to_string(crash_time) + suffix;
+ auto filename =
+ std::string("/") + crashdump::getSerialNumber() + "_" + std::to_string(crash_time) + suffix + file_index;
return filename;
}
+
} // namespace
namespace crashdump
@@ 41,6 45,10 @@ namespace crashdump
const auto crashDumpFilePath = purefs::dir::getCrashDumpsPath().string() + generate_crashdump_filename();
LOG_INFO("Crash dump %s preparing ...", crashDumpFilePath.c_str());
+ if (!rotator.rotateFiles(purefs::dir::getCrashDumpsPath())) {
+ LOG_FATAL("Failed to rotate crash dumps errno: %i", errno);
+ _exit_backtrace(-1, false);
+ }
file = std::fopen(crashDumpFilePath.c_str(), "w");
if (!file) {
LOG_FATAL("Failed to open crash dump file errno %i", errno);
@@ 56,23 64,6 @@ namespace crashdump
std::fclose(file);
}
- void CrashDumpWriterVFS::deleteOldDump()
- {
- std::set<std::filesystem::path> crashdumps{};
- for (const auto &entry : std::filesystem::directory_iterator(purefs::dir::getCrashDumpsPath())) {
- std::cout << entry.path() << std::endl;
- crashdumps.insert(entry.path());
- }
-
- if (crashdumps.size() > maxFilesCount) {
- auto crashdump_to_delete = crashdumps.begin();
- LOG_INFO("Deleting %s ...", crashdump_to_delete->c_str());
- if (not std::filesystem::remove(crashdump_to_delete->c_str())) {
- LOG_WARN("File: %s was not deleted.", crashdump_to_delete->c_str());
- }
- }
- }
-
void CrashDumpWriterVFS::writeBytes(const uint8_t *buff, std::size_t size)
{
if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
M board/rt1051/crashdump/crashdumpwriter_vfs.hpp => board/rt1051/crashdump/crashdumpwriter_vfs.hpp +4 -3
@@ 3,6 3,7 @@
#pragma once
+#include <rotator/Rotator.hpp>
#include <array>
#include <ctime>
#include <memory>
@@ 15,21 16,21 @@ namespace purefs::fs
namespace crashdump
{
- constexpr inline auto maxFilesCount = 5;
+ constexpr inline auto maxRotationFilesCount = 5;
class CrashDumpWriterVFS
{
public:
- CrashDumpWriterVFS()
+ CrashDumpWriterVFS() : rotator{".hex"}
{}
void openDump();
void saveDump();
- void deleteOldDump();
void writeBytes(const std::uint8_t *buff, std::size_t size);
void writeHalfWords(const std::uint16_t *buff, std::size_t size);
void writeWords(const std::uint32_t *buff, std::size_t size);
private:
+ utils::Rotator<maxRotationFilesCount> rotator;
std::FILE *file{};
};
M module-utils/rotator/include/rotator/Rotator.hpp => module-utils/rotator/include/rotator/Rotator.hpp +56 -1
@@ 1,10 1,13 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+#include <Utils.hpp>
+
#include <filesystem>
#include <string>
+#include <set>
namespace utils
{
@@ 41,6 44,32 @@ namespace utils
return path;
}
+ uint getFileNumber(const std::string &filename) const
+ {
+ const auto position = filename.rfind(".");
+ if (position == std::string::npos) {
+ return 0;
+ }
+ const auto indexStartPosition = position + 1;
+ auto numberLength = filename.length() - indexStartPosition;
+ return utils::toNumeric(filename.substr(indexStartPosition, numberLength));
+ }
+
+ std::filesystem::path incrementFileNumber(const std::filesystem::path &crashdumpPath) const
+ {
+ auto newCrashdumpName = crashdumpPath.string();
+ auto position = newCrashdumpName.rfind(".");
+ if (position == std::string::npos) {
+ return crashdumpPath;
+ }
+ const auto indexStartPosition = position + 1;
+ const auto numberLength = newCrashdumpName.length() - indexStartPosition;
+ auto fileNumber = utils::toNumeric(newCrashdumpName.substr(indexStartPosition, numberLength));
+ auto incrementedFileNumber = fileNumber ? std::to_string(++fileNumber) : "hex.0";
+ newCrashdumpName.replace(indexStartPosition, numberLength, incrementedFileNumber);
+ return std::filesystem::path(newCrashdumpName);
+ }
+
public:
explicit Rotator(std::string extension) : extension{extension}
{}
@@ 79,5 108,31 @@ namespace utils
std::filesystem::rename(path, rotatedLogPath, ec);
return (ec) ? false : true;
}
+
+ bool rotateFiles(const std::filesystem::path &path) const
+ {
+ std::error_code ec;
+ std::set<std::filesystem::path> crashdumps{};
+
+ for (const auto &entry : std::filesystem::directory_iterator(path)) {
+ crashdumps.insert(entry.path());
+ }
+
+ for (const auto &crashdump : crashdumps) {
+ if (getFileNumber(crashdump.string()) >= maxRotationFilesCount) {
+ std::filesystem::remove(crashdump, ec);
+ if (ec) {
+ return false;
+ }
+ continue;
+ }
+ std::filesystem::rename(crashdump, incrementFileNumber(crashdump), ec);
+ if (ec) {
+ return false;
+ }
+ }
+
+ return (ec) ? false : true;
+ }
};
} // namespace utils
M module-utils/rotator/tests/test_Rotator.cpp => module-utils/rotator/tests/test_Rotator.cpp +85 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <catch2/catch.hpp>
@@ 23,6 23,11 @@ namespace
{
return this->getRotatedFilePath(source, rotationCount);
}
+
+ std::filesystem::path incrementFileIndex(const std::filesystem::path &source)
+ {
+ return this->incrementFileNumber(source);
+ }
};
} // namespace
@@ 92,3 97,82 @@ TEST_CASE("Rotation of hex dump files")
}
}
}
+
+TEST_CASE("Rotate files with serial_number and timestamp")
+{
+ HexRotator rotator;
+ std::string path("./rotator_tests");
+
+ SECTION("Increment filename index")
+ {
+ std::string filename = "123_12345_crashdump.hex.1";
+ std::string expected_filename = "123_12345_crashdump.hex.2";
+ auto result = rotator.incrementFileIndex(std::filesystem::path(filename));
+ REQUIRE(result == expected_filename);
+ }
+
+ SECTION("Rotate files")
+ {
+
+ std::vector<std::string> test_filenames = {
+ "/123_12345_crashdump.hex.1", "/123_12346_crashdump.hex.2", "/123_12347_crashdump.hex.3"};
+ std::vector<std::string> expected_test_filenames = {
+ "/123_12345_crashdump.hex.2", "/123_12346_crashdump.hex.3", "/123_12347_crashdump.hex.4"};
+
+ std::filesystem::create_directory(path);
+
+ for (const auto &tf : test_filenames) {
+ std::ofstream(std::string(path + tf).c_str());
+ }
+ REQUIRE(rotator.rotateFiles(std::filesystem::path(path)));
+ for (const auto &etf : expected_test_filenames) {
+ REQUIRE(std::filesystem::exists(std::string(path + etf)));
+ }
+
+ std::filesystem::remove_all(path);
+ }
+
+ SECTION("Rotate files - max number reach")
+ {
+
+ std::vector<std::string> test_filenames = {"/123_12345_crashdump.hex.1",
+ "/123_12346_crashdump.hex.2",
+ "/123_12347_crashdump.hex.3",
+ "/123_12349_crashdump.hex.4",
+ "/123_12351_crashdump.hex.5"};
+
+ std::vector<std::string> expected_test_filenames = {"/123_12345_crashdump.hex.2",
+ "/123_12346_crashdump.hex.3",
+ "/123_12347_crashdump.hex.4",
+ "/123_12349_crashdump.hex.5"};
+
+ std::string file_expected_to_not_exist = "/123_12351_crashdump.hex.6";
+
+ std::filesystem::create_directory(path);
+
+ for (const auto &tf : test_filenames) {
+ std::ofstream(std::string(path + tf).c_str());
+ }
+ REQUIRE(rotator.rotateFiles(std::filesystem::path(path)));
+ for (const auto &tf : test_filenames) {
+ REQUIRE_FALSE(std::filesystem::exists(std::string(path + tf)));
+ }
+ for (const auto &etf : expected_test_filenames) {
+ REQUIRE(std::filesystem::exists(std::string(path + etf)));
+ }
+ REQUIRE_FALSE(std::filesystem::exists(std::string(path + file_expected_to_not_exist)));
+
+ std::filesystem::remove_all(path);
+ }
+
+ SECTION("Increment filename - no number at the end")
+ {
+ std::string filename = "123_12345_crashdump.hex";
+ std::string expected_filename = "123_12345_crashdump.hex.0";
+ auto result = rotator.incrementFileIndex(std::filesystem::path(filename));
+ REQUIRE(result == expected_filename);
+ }
+
+ // in case of fail in earlier tests
+ std::filesystem::remove_all(path);
+}