From f09ba5ffd53bf7d28e0dc516c00a8f69ca7efae9 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Thu, 28 Sep 2023 08:29:55 +1000 Subject: Use bindey for databinding instead of hand rolling ui updates --- src/database/database.cpp | 104 ++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 49 deletions(-) (limited to 'src/database/database.cpp') diff --git a/src/database/database.cpp b/src/database/database.cpp index fd0e50c1..1ecd72e0 100644 --- a/src/database/database.cpp +++ b/src/database/database.cpp @@ -144,7 +144,7 @@ auto Database::Update() -> std::future { OwningSlice prefix = EncodeDataPrefix(); it->Seek(prefix.slice); while (it->Valid() && it->key().starts_with(prefix.slice)) { - std::optional track = ParseDataValue(it->value()); + std::shared_ptr track = ParseDataValue(it->value()); if (!track) { // The value was malformed. Drop this record. ESP_LOGW(kTag, "dropping malformed metadata"); @@ -159,9 +159,9 @@ auto Database::Update() -> std::future { continue; } - TrackTags tags{}; - if (!tag_parser_.ReadAndParseTags(track->filepath(), &tags) || - tags.encoding() == Container::kUnsupported) { + std::shared_ptr tags = + tag_parser_.ReadAndParseTags(track->filepath()); + if (!tags || tags->encoding() == Container::kUnsupported) { // We couldn't read the tags for this track. Either they were // malformed, or perhaps the file is missing. Either way, tombstone // this record. @@ -174,7 +174,7 @@ auto Database::Update() -> std::future { // At this point, we know that the track still exists in its original // location. All that's left to do is update any metadata about it. - uint64_t new_hash = tags.Hash(); + uint64_t new_hash = tags->Hash(); if (new_hash != track->tags_hash()) { // This track's tags have changed. Since the filepath is exactly the // same, we assume this is a legitimate correction. Update the @@ -185,7 +185,9 @@ auto Database::Update() -> std::future { dbPutHash(new_hash, track->id()); } - dbCreateIndexesForTrack({*track, tags}); + Track t{track, tags}; + + dbCreateIndexesForTrack(t); it->Next(); } @@ -197,15 +199,14 @@ auto Database::Update() -> std::future { .stage = event::UpdateProgress::Stage::kScanningForNewTracks, }); file_gatherer_.FindFiles("", [&](const std::pmr::string& path) { - TrackTags tags; - if (!tag_parser_.ReadAndParseTags(path, &tags) || - tags.encoding() == Container::kUnsupported) { + std::shared_ptr tags = tag_parser_.ReadAndParseTags(path); + if (!tags || tags->encoding() == Container::kUnsupported) { // No parseable tags; skip this fiile. return; } // Check for any existing record with the same hash. - uint64_t hash = tags.Hash(); + uint64_t hash = tags->Hash(); OwningSlice key = EncodeHashKey(hash); std::optional existing_hash; std::string raw_entry; @@ -219,33 +220,36 @@ auto Database::Update() -> std::future { TrackId id = dbMintNewTrackId(); ESP_LOGI(kTag, "recording new 0x%lx", id); - TrackData data(id, path, hash); - dbPutTrackData(data); + auto data = std::make_shared(id, path, hash); + dbPutTrackData(*data); dbPutHash(hash, id); - dbCreateIndexesForTrack({data, tags}); + auto t = std::make_shared(data, tags); + dbCreateIndexesForTrack(*t); return; } - std::optional existing_data = dbGetTrackData(*existing_hash); + std::shared_ptr existing_data = dbGetTrackData(*existing_hash); if (!existing_data) { // We found a hash that matches, but there's no data record? Weird. - TrackData new_data(*existing_hash, path, hash); - dbPutTrackData(new_data); - dbCreateIndexesForTrack({*existing_data, tags}); + auto new_data = std::make_shared(*existing_hash, path, hash); + dbPutTrackData(*new_data); + auto t = std::make_shared(new_data, tags); + dbCreateIndexesForTrack(*t); return; } if (existing_data->is_tombstoned()) { ESP_LOGI(kTag, "exhuming track %lu", existing_data->id()); dbPutTrackData(existing_data->Exhume(path)); - dbCreateIndexesForTrack({*existing_data, tags}); + auto t = std::make_shared(existing_data, tags); + dbCreateIndexesForTrack(*t); } else if (existing_data->filepath() != path) { ESP_LOGW(kTag, "tag hash collision for %s and %s", existing_data->filepath().c_str(), path.c_str()); ESP_LOGI(kTag, "hash components: %s, %s, %s", - tags.at(Tag::kTitle).value_or("no title").c_str(), - tags.at(Tag::kArtist).value_or("no artist").c_str(), - tags.at(Tag::kAlbum).value_or("no album").c_str()); + tags->at(Tag::kTitle).value_or("no title").c_str(), + tags->at(Tag::kArtist).value_or("no artist").c_str(), + tags->at(Tag::kAlbum).value_or("no album").c_str()); } }); events::Ui().Dispatch(event::UpdateFinished{}); @@ -264,26 +268,27 @@ auto Database::GetTrackPath(TrackId id) }); } -auto Database::GetTrack(TrackId id) -> std::future> { - return worker_task_->Dispatch>( - [=, this]() -> std::optional { - std::optional data = dbGetTrackData(id); +auto Database::GetTrack(TrackId id) -> std::future> { + return worker_task_->Dispatch>( + [=, this]() -> std::shared_ptr { + std::shared_ptr data = dbGetTrackData(id); if (!data || data->is_tombstoned()) { return {}; } - TrackTags tags; - if (!tag_parser_.ReadAndParseTags(data->filepath(), &tags)) { + std::shared_ptr tags = + tag_parser_.ReadAndParseTags(data->filepath()); + if (!tags) { return {}; } - return Track(*data, tags); + return std::make_shared(data, tags); }); } auto Database::GetBulkTracks(std::vector ids) - -> std::future>> { - return worker_task_->Dispatch>>( - [=, this]() -> std::vector> { - std::map id_to_track{}; + -> std::future>> { + return worker_task_->Dispatch>>( + [=, this]() -> std::vector> { + std::map> id_to_track{}; // Sort the list of ids so that we can retrieve them all in a single // iteration through the database, without re-seeking. @@ -299,16 +304,16 @@ auto Database::GetBulkTracks(std::vector ids) // This id wasn't found at all. Skip it. continue; } - std::optional track = + std::shared_ptr track = ParseRecord(it->key(), it->value()); if (track) { - id_to_track.insert({id, *track}); + id_to_track.insert({id, track}); } } // We've fetched all of the ids in the request, so now just put them // back into the order they were asked for in. - std::vector> results; + std::vector> results; for (const TrackId& id : ids) { if (id_to_track.contains(id)) { results.push_back(id_to_track.at(id)); @@ -426,7 +431,7 @@ auto Database::dbPutTrackData(const TrackData& s) -> void { } } -auto Database::dbGetTrackData(TrackId id) -> std::optional { +auto Database::dbGetTrackData(TrackId id) -> std::shared_ptr { OwningSlice key = EncodeDataKey(id); std::string raw_val; if (!db_->Get(leveldb::ReadOptions(), key.slice, &raw_val).ok()) { @@ -454,7 +459,7 @@ auto Database::dbGetHash(const uint64_t& hash) -> std::optional { return ParseHashValue(raw_val); } -auto Database::dbCreateIndexesForTrack(Track track) -> void { +auto Database::dbCreateIndexesForTrack(const Track& track) -> void { for (const IndexInfo& index : GetIndexes()) { leveldb::WriteBatch writes; if (Index(index, track, &writes)) { @@ -481,7 +486,7 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { // Grab results. std::optional first_key; - std::vector records; + std::vector> records; while (records.size() < c.page_size && it->Valid()) { if (!it->key().starts_with({c.prefix.data(), c.prefix.size()})) { break; @@ -489,9 +494,9 @@ auto Database::dbGetPage(const Continuation& c) -> Result* { if (!first_key) { first_key = it->key().ToString(); } - std::optional parsed = ParseRecord(it->key(), it->value()); + std::shared_ptr parsed = ParseRecord(it->key(), it->value()); if (parsed) { - records.push_back(*parsed); + records.push_back(parsed); } if (c.forward) { it->Next(); @@ -577,7 +582,7 @@ template auto Database::dbGetPage( template <> auto Database::ParseRecord(const leveldb::Slice& key, const leveldb::Slice& val) - -> std::optional { + -> std::shared_ptr { std::optional data = ParseIndexKey(key); if (!data) { return {}; @@ -588,28 +593,29 @@ auto Database::ParseRecord(const leveldb::Slice& key, title = val.ToString(); } - return IndexRecord(*data, title, data->track); + return std::make_shared(*data, title, data->track); } template <> auto Database::ParseRecord(const leveldb::Slice& key, const leveldb::Slice& val) - -> std::optional { - std::optional data = ParseDataValue(val); + -> std::shared_ptr { + std::shared_ptr data = ParseDataValue(val); if (!data || data->is_tombstoned()) { return {}; } - TrackTags tags; - if (!tag_parser_.ReadAndParseTags(data->filepath(), &tags)) { + std::shared_ptr tags = + tag_parser_.ReadAndParseTags(data->filepath()); + if (!tags) { return {}; } - return Track(*data, tags); + return std::make_shared(data, tags); } template <> auto Database::ParseRecord(const leveldb::Slice& key, const leveldb::Slice& val) - -> std::optional { + -> std::shared_ptr { std::ostringstream stream; stream << "key: "; if (key.size() < 3 || key.data()[1] != '\0') { @@ -634,7 +640,7 @@ auto Database::ParseRecord(const leveldb::Slice& key, } } std::pmr::string res{stream.str(), &memory::kSpiRamResource}; - return res; + return std::make_shared(res); } IndexRecord::IndexRecord(const IndexKey& key, -- cgit v1.2.3