From ceba508593fbb2f897dfa6ba38ec3839e62d85a8 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 13 Oct 2023 15:29:06 +1100 Subject: [PATCH] Add modified time to TrackData --- src/database/database.cpp | 12 +++++++++--- src/database/file_gatherer.cpp | 4 ++-- src/database/include/file_gatherer.hpp | 10 ++++++---- src/database/include/track.hpp | 19 +++++++++++++++---- src/database/records.cpp | 16 ++++++++++++---- src/database/track.cpp | 6 +++--- src/system_fsm/running.cpp | 1 + 7 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/database/database.cpp b/src/database/database.cpp index 60aa69fc..f86b2c9b 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -7,6 +7,7 @@ #include "database.hpp" #include +#include #include #include @@ -200,13 +201,16 @@ auto Database::Update() -> std::future { // Stage 2: search for newly added files. ESP_LOGI(kTag, "scanning for new tracks"); uint64_t num_processed = 0; - file_gatherer_.FindFiles("", [&](const std::pmr::string& path) { + file_gatherer_.FindFiles("", [&](const std::pmr::string& path, + const FILINFO& info) { num_processed++; events::Ui().Dispatch(event::UpdateProgress{ .stage = event::UpdateProgress::Stage::kScanningForNewTracks, .val = num_processed, }); + std::pair modified{info.fdate, info.ftime}; + std::shared_ptr tags = tag_parser_.ReadAndParseTags(path); if (!tags || tags->encoding() == Container::kUnsupported) { // No parseable tags; skip this fiile. @@ -228,7 +232,8 @@ auto Database::Update() -> std::future { TrackId id = dbMintNewTrackId(); ESP_LOGI(kTag, "recording new 0x%lx", id); - auto data = std::make_shared(id, path, hash); + auto data = std::make_shared(id, path, hash, modified); + dbPutTrackData(*data); dbPutHash(hash, id); auto t = std::make_shared(data, tags); @@ -239,7 +244,8 @@ auto Database::Update() -> std::future { std::shared_ptr existing_data = dbGetTrackData(*existing_hash); if (!existing_data) { // We found a hash that matches, but there's no data record? Weird. - auto new_data = std::make_shared(*existing_hash, path, hash); + auto new_data = + std::make_shared(*existing_hash, path, hash, modified); dbPutTrackData(*new_data); auto t = std::make_shared(new_data, tags); dbCreateIndexesForTrack(*t); diff --git a/src/database/file_gatherer.cpp b/src/database/file_gatherer.cpp index b4e87acb..55777139 100644 --- a/src/database/file_gatherer.cpp +++ b/src/database/file_gatherer.cpp @@ -22,7 +22,7 @@ static_assert(sizeof(TCHAR) == sizeof(char), "TCHAR must be CHAR"); auto FileGathererImpl::FindFiles( const std::pmr::string& root, - std::function cb) -> void { + std::function cb) -> void { std::pmr::deque to_explore(&memory::kSpiRamResource); to_explore.push_back(root); @@ -65,7 +65,7 @@ auto FileGathererImpl::FindFiles( } else { // This is a file! Let the callback know about it. // std::invoke(cb, full_path.str(), info); - std::invoke(cb, full_path); + std::invoke(cb, full_path, info); } } } diff --git a/src/database/include/file_gatherer.hpp b/src/database/include/file_gatherer.hpp index 133cf81a..378727f7 100644 --- a/src/database/include/file_gatherer.hpp +++ b/src/database/include/file_gatherer.hpp @@ -19,15 +19,17 @@ class IFileGatherer { public: virtual ~IFileGatherer(){}; - virtual auto FindFiles(const std::pmr::string& root, - std::function cb) + virtual auto FindFiles( + const std::pmr::string& root, + std::function cb) -> void = 0; }; class FileGathererImpl : public IFileGatherer { public: - virtual auto FindFiles(const std::pmr::string& root, - std::function cb) + virtual auto FindFiles( + const std::pmr::string& root, + std::function cb) -> void override; }; diff --git a/src/database/include/track.hpp b/src/database/include/track.hpp index 44bfbc54..1067b25e 100644 --- a/src/database/include/track.hpp +++ b/src/database/include/track.hpp @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include @@ -118,23 +119,30 @@ class TrackData { const std::pmr::string filepath_; const uint64_t tags_hash_; const bool is_tombstoned_; + const std::pair modified_at_; public: /* Constructor used when adding new tracks to the database. */ - TrackData(TrackId id, const std::pmr::string& path, uint64_t hash) + TrackData(TrackId id, + const std::pmr::string& path, + uint64_t hash, + std::pair modified_at) : id_(id), filepath_(path, &memory::kSpiRamResource), tags_hash_(hash), - is_tombstoned_(false) {} + is_tombstoned_(false), + modified_at_(modified_at) {} TrackData(TrackId id, const std::pmr::string& path, uint64_t hash, - bool is_tombstoned) + bool is_tombstoned, + std::pair modified_at) : id_(id), filepath_(path, &memory::kSpiRamResource), tags_hash_(hash), - is_tombstoned_(is_tombstoned) {} + is_tombstoned_(is_tombstoned), + modified_at_(modified_at) {} TrackData(TrackData&& other) = delete; TrackData& operator=(TrackData& other) = delete; @@ -145,6 +153,9 @@ class TrackData { auto filepath() const -> std::pmr::string { return filepath_; } auto tags_hash() const -> uint64_t { return tags_hash_; } auto is_tombstoned() const -> bool { return is_tombstoned_; } + auto modified_at() const -> std::pair { + return modified_at_; + } auto UpdateHash(uint64_t new_hash) const -> TrackData; diff --git a/src/database/records.cpp b/src/database/records.cpp index 37ea429b..9d4dbd78 100644 --- a/src/database/records.cpp +++ b/src/database/records.cpp @@ -67,6 +67,8 @@ auto EncodeDataValue(const TrackData& track) -> std::string { cppbor::Tstr{track.filepath()}, cppbor::Uint{track.tags_hash()}, cppbor::Bool{track.is_tombstoned()}, + cppbor::Uint{track.modified_at().first}, + cppbor::Uint{track.modified_at().second}, }; return val.toString(); } @@ -78,18 +80,24 @@ auto ParseDataValue(const leveldb::Slice& slice) -> std::shared_ptr { return nullptr; } auto vals = item->asArray(); - if (vals->size() != 4 || vals->get(0)->type() != cppbor::UINT || + if (vals->size() != 6 || vals->get(0)->type() != cppbor::UINT || vals->get(1)->type() != cppbor::TSTR || vals->get(2)->type() != cppbor::UINT || - vals->get(3)->type() != cppbor::SIMPLE) { + vals->get(3)->type() != cppbor::SIMPLE || + vals->get(4)->type() != cppbor::UINT || + vals->get(5)->type() != cppbor::UINT) { return {}; } TrackId id = vals->get(0)->asUint()->unsignedValue(); auto path = vals->get(1)->asViewTstr()->view(); uint64_t hash = vals->get(2)->asUint()->unsignedValue(); bool tombstoned = vals->get(3)->asBool()->value(); - return std::make_shared( - id, std::pmr::string{path.data(), path.size()}, hash, tombstoned); + auto modified_at = std::make_pair( + vals->get(4)->asUint()->unsignedValue(), + vals->get(5)->asUint()->unsignedValue()); + return std::make_shared(id, + std::pmr::string{path.data(), path.size()}, + hash, tombstoned, modified_at); } /* 'H/ 0xBEEF' */ diff --git a/src/database/track.cpp b/src/database/track.cpp index ca180124..551379c6 100644 --- a/src/database/track.cpp +++ b/src/database/track.cpp @@ -53,15 +53,15 @@ auto TrackTags::Hash() const -> uint64_t { } auto TrackData::UpdateHash(uint64_t new_hash) const -> TrackData { - return TrackData(id_, filepath_, new_hash, is_tombstoned_); + return TrackData(id_, filepath_, new_hash, is_tombstoned_, modified_at_); } auto TrackData::Entomb() const -> TrackData { - return TrackData(id_, filepath_, tags_hash_, true); + return TrackData(id_, filepath_, tags_hash_, true, modified_at_); } auto TrackData::Exhume(const std::pmr::string& new_path) const -> TrackData { - return TrackData(id_, new_path, tags_hash_, false); + return TrackData(id_, new_path, tags_hash_, false, modified_at_); } auto Track::TitleOrFilename() const -> std::pmr::string { diff --git a/src/system_fsm/running.cpp b/src/system_fsm/running.cpp index 70b4e99c..9d91e7f1 100644 --- a/src/system_fsm/running.cpp +++ b/src/system_fsm/running.cpp @@ -55,6 +55,7 @@ void Running::entry() { ESP_LOGI(kTag, "opening database"); sFileGatherer = new database::FileGathererImpl(); + database::Database::Destroy(); auto database_res = database::Database::Open(*sFileGatherer, sServices->tag_parser()); if (database_res.has_error()) {