Skip to content

Commit dd885cf

Browse files
committed
GameList: Cache invalid entries
Saves repeatedly scanning them every time the application starts.
1 parent 8a0400a commit dd885cf

2 files changed

Lines changed: 57 additions & 25 deletions

File tree

src/core/game_list.cpp

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static bool ShouldLoadAchievementsProgress();
9292
static bool GetExeListEntry(const std::string& path, Entry* entry);
9393
static bool GetPsfListEntry(const std::string& path, Entry* entry);
9494
static bool GetDiscListEntry(const std::string& path, Entry* entry);
95+
static void MakeInvalidEntry(Entry* entry);
9596

9697
static void ApplyCustomAttributes(const std::string& path, Entry* entry,
9798
const INISettingsInterface& custom_attributes_ini);
@@ -109,7 +110,7 @@ static void ScanDirectory(const char* path, bool recursive, bool only_cache,
109110
static bool AddFileFromCache(const std::string& path, std::time_t timestamp, const PlayedTimeMap& played_time_map,
110111
const INISettingsInterface& custom_attributes_ini,
111112
const Achievements::ProgressDatabase& achievements_progress);
112-
static bool ScanFile(std::string path, std::time_t timestamp, std::unique_lock<std::recursive_mutex>& lock,
113+
static void ScanFile(std::string path, std::time_t timestamp, std::unique_lock<std::recursive_mutex>& lock,
113114
const PlayedTimeMap& played_time_map, const INISettingsInterface& custom_attributes_ini,
114115
const Achievements::ProgressDatabase& achievements_progress, BinaryFileWriter& cache_writer);
115116

@@ -369,6 +370,32 @@ bool GameList::GetDiscListEntry(const std::string& path, Entry* entry)
369370
return true;
370371
}
371372

373+
void GameList::MakeInvalidEntry(Entry* entry)
374+
{
375+
entry->type = EntryType::Count;
376+
entry->region = DiscRegion::Other;
377+
entry->disc_set_index = -1;
378+
entry->disc_set_member = false;
379+
entry->has_custom_title = false;
380+
entry->has_custom_region = false;
381+
entry->custom_language = GameDatabase::Language::MaxCount;
382+
entry->path = {};
383+
entry->serial = {};
384+
entry->title = {};
385+
entry->disc_set_name = {};
386+
entry->dbentry = nullptr;
387+
entry->hash = 0;
388+
entry->file_size = 0;
389+
entry->uncompressed_size = 0;
390+
entry->last_modified_time = 0;
391+
entry->last_played_time = 0;
392+
entry->achievements_hash = {};
393+
entry->achievements_game_id = 0;
394+
entry->num_achievements = 0;
395+
entry->unlocked_achievements = 0;
396+
entry->unlocked_achievements_hc = 0;
397+
}
398+
372399
bool GameList::PopulateEntryFromPath(const std::string& path, Entry* entry)
373400
{
374401
if (System::IsExePath(path))
@@ -420,7 +447,7 @@ bool GameList::LoadEntriesFromCache(BinaryFileReader& reader)
420447
!reader.ReadS64(&ge.file_size) || !reader.ReadU64(&ge.uncompressed_size) ||
421448
!reader.ReadU64(reinterpret_cast<u64*>(&ge.last_modified_time)) || !reader.ReadS8(&ge.disc_set_index) ||
422449
!reader.Read(ge.achievements_hash.data(), ge.achievements_hash.size()) ||
423-
region >= static_cast<u8>(DiscRegion::Count) || type >= static_cast<u8>(EntryType::Count))
450+
region >= static_cast<u8>(DiscRegion::Count) || type > static_cast<u8>(EntryType::Count))
424451
{
425452
WARNING_LOG("Game list cache entry is corrupted");
426453
return false;
@@ -522,11 +549,8 @@ void GameList::ScanDirectory(const char* path, bool recursive, bool only_cache,
522549
{
523550
files_scanned++;
524551

525-
if (progress->IsCancelled() || !GameList::IsScannableFilename(ffd.FileName) ||
526-
IsPathExcluded(excluded_paths, ffd.FileName))
527-
{
552+
if (progress->IsCancelled() || !IsScannableFilename(ffd.FileName) || IsPathExcluded(excluded_paths, ffd.FileName))
528553
continue;
529-
}
530554

531555
std::unique_lock lock(s_mutex);
532556
if (GetEntryForPath(ffd.FileName) ||
@@ -559,6 +583,10 @@ bool GameList::AddFileFromCache(const std::string& path, std::time_t timestamp,
559583
return false;
560584
}
561585

586+
// don't add invalid entries to the list, but don't scan them either
587+
if (!entry.IsValid())
588+
return true;
589+
562590
auto iter = played_time_map.find(entry.serial);
563591
if (iter != played_time_map.end())
564592
{
@@ -570,7 +598,7 @@ bool GameList::AddFileFromCache(const std::string& path, std::time_t timestamp,
570598
return true;
571599
}
572600

573-
bool GameList::ScanFile(std::string path, std::time_t timestamp, std::unique_lock<std::recursive_mutex>& lock,
601+
void GameList::ScanFile(std::string path, std::time_t timestamp, std::unique_lock<std::recursive_mutex>& lock,
574602
const PlayedTimeMap& played_time_map, const INISettingsInterface& custom_attributes_ini,
575603
const Achievements::ProgressDatabase& achievements_progress, BinaryFileWriter& cache_writer)
576604
{
@@ -580,10 +608,23 @@ bool GameList::ScanFile(std::string path, std::time_t timestamp, std::unique_loc
580608
VERBOSE_LOG("Scanning '{}'...", path);
581609

582610
Entry entry;
583-
if (!PopulateEntryFromPath(path, &entry))
611+
if (PopulateEntryFromPath(path, &entry))
584612
{
585-
lock.lock();
586-
return false;
613+
const auto iter = played_time_map.find(entry.serial);
614+
if (iter != played_time_map.end())
615+
{
616+
entry.last_played_time = iter->second.last_played_time;
617+
entry.total_played_time = iter->second.total_played_time;
618+
}
619+
620+
ApplyCustomAttributes(entry.path, &entry, custom_attributes_ini);
621+
622+
if (entry.IsDisc())
623+
PopulateEntryAchievements(&entry, achievements_progress);
624+
}
625+
else
626+
{
627+
MakeInvalidEntry(&entry);
587628
}
588629

589630
entry.path = std::move(path);
@@ -592,29 +633,19 @@ bool GameList::ScanFile(std::string path, std::time_t timestamp, std::unique_loc
592633
if (cache_writer.IsOpen() && !WriteEntryToCache(&entry, cache_writer)) [[unlikely]]
593634
WARNING_LOG("Failed to write entry '{}' to cache", entry.path);
594635

595-
const auto iter = played_time_map.find(entry.serial);
596-
if (iter != played_time_map.end())
597-
{
598-
entry.last_played_time = iter->second.last_played_time;
599-
entry.total_played_time = iter->second.total_played_time;
600-
}
601-
602-
ApplyCustomAttributes(entry.path, &entry, custom_attributes_ini);
603-
604-
if (entry.IsDisc())
605-
PopulateEntryAchievements(&entry, achievements_progress);
606-
607636
lock.lock();
608637

638+
// don't add invalid entries to the list
639+
if (!entry.IsValid())
640+
return;
641+
609642
// replace if present
610643
auto it = std::find_if(s_entries.begin(), s_entries.end(),
611644
[&entry](const Entry& existing_entry) { return (existing_entry.path == entry.path); });
612645
if (it != s_entries.end())
613646
*it = std::move(entry);
614647
else
615648
s_entries.push_back(std::move(entry));
616-
617-
return true;
618649
}
619650

620651
bool GameList::RescanCustomAttributesForPath(const std::string& path, const INISettingsInterface& custom_attributes_ini)

src/core/game_list.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ enum class EntryType : u8
3333

3434
struct Entry
3535
{
36-
EntryType type = EntryType::Disc;
36+
EntryType type = EntryType::Count;
3737
DiscRegion region = DiscRegion::Other;
3838

3939
s8 disc_set_index = -1;
@@ -69,6 +69,7 @@ struct Entry
6969

7070
TinyString GetReleaseDateString() const;
7171

72+
ALWAYS_INLINE bool IsValid() const { return (type < EntryType::Count); }
7273
ALWAYS_INLINE bool IsDisc() const { return (type == EntryType::Disc); }
7374
ALWAYS_INLINE bool IsDiscSet() const { return (type == EntryType::DiscSet); }
7475
ALWAYS_INLINE bool HasCustomLanguage() const { return (custom_language != GameDatabase::Language::MaxCount); }

0 commit comments

Comments
 (0)