Include title in indexes to avoid a per-record disk read

GOTTA GO FAST
custom
jacqueline 2 years ago
parent 67ab8bf515
commit df22bed072
  1. 2
      src/app_console/app_console.cpp
  2. 26
      src/database/database.cpp
  3. 7
      src/database/include/database.hpp
  4. 9
      src/database/index.cpp
  5. 7
      src/ui/screen_track_browser.cpp
  6. 2
      src/ui/ui_fsm.cpp

@ -259,7 +259,7 @@ int CmdDbIndex(int argc, char** argv) {
for (database::IndexRecord r : res->values()) {
std::cout << r.text().value_or("<unknown>");
if (r.track()) {
std::cout << "\t(id:" << r.track()->data().id() << ")";
std::cout << "\t(id:" << *r.track() << ")";
}
std::cout << std::endl;
}

@ -600,20 +600,12 @@ auto Database::ParseRecord<IndexRecord>(const leveldb::Slice& key,
return {};
}
// If there was a track id included for this key, then this is a leaf record.
// Fetch the actual track data instead of relying on the information in the
// key.
std::optional<Track> track;
if (data->track) {
std::optional<TrackData> track_data = dbGetTrackData(*data->track);
TrackTags track_tags;
if (track_data &&
tag_parser_->ReadAndParseTags(track_data->filepath(), &track_tags)) {
track.emplace(*track_data, track_tags);
}
std::optional<std::string> title;
if (!val.empty()) {
title = val.ToString();
}
return IndexRecord(*data, track);
return IndexRecord(*data, title, data->track);
}
template <>
@ -663,17 +655,17 @@ auto Database::ParseRecord<std::string>(const leveldb::Slice& key,
return stream.str();
}
IndexRecord::IndexRecord(const IndexKey& key, std::optional<Track> track)
: key_(key), track_(track) {}
IndexRecord::IndexRecord(const IndexKey& key, std::optional<shared_string> title, std::optional<TrackId> track)
: key_(key), override_text_(title), track_(track) {}
auto IndexRecord::text() const -> std::optional<shared_string> {
if (track_) {
return track_->TitleOrFilename();
if (override_text_) {
return override_text_;
}
return key_.item;
}
auto IndexRecord::track() const -> std::optional<Track> {
auto IndexRecord::track() const -> std::optional<TrackId> {
return track_;
}

@ -70,16 +70,17 @@ class Result {
class IndexRecord {
public:
explicit IndexRecord(const IndexKey&, std::optional<Track>);
explicit IndexRecord(const IndexKey&, std::optional<shared_string>, std::optional<TrackId>);
auto text() const -> std::optional<shared_string>;
auto track() const -> std::optional<Track>;
auto track() const -> std::optional<TrackId>;
auto Expand(std::size_t) const -> std::optional<Continuation<IndexRecord>>;
private:
IndexKey key_;
std::optional<Track> track_;
std::optional<shared_string> override_text_;
std::optional<TrackId> track_;
};
class Database {

@ -52,15 +52,20 @@ auto Index(const IndexInfo& info, const Track& t, leveldb::WriteBatch* batch)
key.item = {};
}
// If this is the last component, then we should also fill in the track id.
// If this is the last component, then we should also fill in the track id
// and title.
std::optional<std::string> title;
if (i == info.components.size() - 1) {
key.track = t.data().id();
if (info.components.at(i) != Tag::kTitle) {
title = t.TitleOrFilename();
}
} else {
key.track = {};
}
auto encoded = EncodeIndexKey(key);
batch->Put(encoded.slice, leveldb::Slice{});
batch->Put(encoded.slice, title.value_or(""));
// If there are more components after this, then we need to finish by
// narrowing the header with the current title.

@ -110,7 +110,6 @@ auto TrackBrowser::Tick() -> void {
}
if (loading_page_->wait_for(std::chrono::seconds(0)) ==
std::future_status::ready) {
ESP_LOGI(kTag, "load finished. adding to page.");
auto result = loading_page_->get();
AddResults(loading_pos_.value_or(END), result);
@ -125,12 +124,10 @@ auto TrackBrowser::OnItemSelected(lv_event_t* ev) -> void {
return;
}
if (index < kPageBuffer) {
ESP_LOGI(kTag, "fetch page at start");
FetchNewPage(START);
return;
}
if (index > GetNumRecords() - kPageBuffer) {
ESP_LOGI(kTag, "fetch page at end");
FetchNewPage(END);
return;
}
@ -254,7 +251,6 @@ auto TrackBrowser::DropPage(Position pos) -> void {
auto TrackBrowser::FetchNewPage(Position pos) -> void {
if (loading_page_) {
ESP_LOGI(kTag, "already loading; giving up");
return;
}
@ -268,7 +264,6 @@ auto TrackBrowser::FetchNewPage(Position pos) -> void {
break;
}
if (!cont) {
ESP_LOGI(kTag, "out of pages; giving up");
return;
}
@ -282,11 +277,9 @@ auto TrackBrowser::FetchNewPage(Position pos) -> void {
if (current_pages_.size() >= kMaxPages) {
switch (pos) {
case START:
ESP_LOGI(kTag, "dropping end page");
DropPage(END);
break;
case END:
ESP_LOGI(kTag, "dropping start page");
DropPage(START);
break;
}

@ -120,7 +120,7 @@ void Browse::react(const internal::RecordSelected& ev) {
ESP_LOGI(kTag, "selected track '%s'", ev.record.text()->c_str());
// TODO(jacqueline): We should also send some kind of playlist info here.
sQueue->Clear();
sQueue->AddLast(ev.record.track()->data().id());
sQueue->AddLast(*ev.record.track());
transit<Playing>();
} else {
ESP_LOGI(kTag, "selected record '%s'", ev.record.text()->c_str());

Loading…
Cancel
Save