Include title in indexes to avoid a per-record disk read
GOTTA GO FAST
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user