diff --git a/Core/Config.cpp b/Core/Config.cpp index 313b7ecdc7..ef19b9ca70 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1141,7 +1141,7 @@ void Config::CleanRecent() { std::vector cleanedRecent; for (size_t i = 0; i < recentIsos.size(); i++) { FileLoader *loader = ConstructFileLoader(recentIsos[i]); - if (loader->Exists()) { + if (loader->ExistsFast()) { // Make sure we don't have any redundant items. auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]); if (duplicate == cleanedRecent.end()) { diff --git a/Core/FileLoaders/CachingFileLoader.cpp b/Core/FileLoaders/CachingFileLoader.cpp index 0b34e2c7bb..1c46c99dbb 100644 --- a/Core/FileLoaders/CachingFileLoader.cpp +++ b/Core/FileLoaders/CachingFileLoader.cpp @@ -23,8 +23,16 @@ // Takes ownership of backend. CachingFileLoader::CachingFileLoader(FileLoader *backend) - : filesize_(0), filepos_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) { - filesize_ = backend->FileSize(); + : filesize_(0), filepos_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false), prepared_(false) { +} + +void CachingFileLoader::Prepare() { + if (prepared_) { + return; + } + prepared_ = true; + + filesize_ = backend_->FileSize(); if (filesize_ > 0) { InitCache(); } @@ -46,6 +54,14 @@ bool CachingFileLoader::Exists() { return exists_ == 1; } +bool CachingFileLoader::ExistsFast() { + if (exists_ == -1) { + lock_guard guard(backendMutex_); + return backend_->ExistsFast(); + } + return exists_ == 1; +} + bool CachingFileLoader::IsDirectory() { if (isDirectory_ == -1) { lock_guard guard(backendMutex_); @@ -55,6 +71,7 @@ bool CachingFileLoader::IsDirectory() { } s64 CachingFileLoader::FileSize() { + Prepare(); return filesize_; } @@ -68,6 +85,7 @@ void CachingFileLoader::Seek(s64 absolutePos) { } size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) { + Prepare(); if (absolutePos >= filesize_) { bytes = 0; } else if (absolutePos + (s64)bytes >= filesize_) { diff --git a/Core/FileLoaders/CachingFileLoader.h b/Core/FileLoaders/CachingFileLoader.h index 903fb8f885..e3c2cc9b4a 100644 --- a/Core/FileLoaders/CachingFileLoader.h +++ b/Core/FileLoaders/CachingFileLoader.h @@ -28,6 +28,7 @@ public: virtual ~CachingFileLoader() override; virtual bool Exists() override; + virtual bool ExistsFast() override; virtual bool IsDirectory() override; virtual s64 FileSize() override; virtual std::string Path() const override; @@ -45,6 +46,7 @@ public: virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data) override; private: + void Prepare(); void InitCache(); void ShutdownCache(); size_t ReadFromCache(s64 pos, size_t bytes, void *data); @@ -84,4 +86,5 @@ private: recursive_mutex blocksMutex_; mutable recursive_mutex backendMutex_; bool aheadThread_; + bool prepared_; }; diff --git a/Core/FileLoaders/DiskCachingFileLoader.cpp b/Core/FileLoaders/DiskCachingFileLoader.cpp index e51c84541b..2efaff810c 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.cpp +++ b/Core/FileLoaders/DiskCachingFileLoader.cpp @@ -38,8 +38,16 @@ recursive_mutex DiskCachingFileLoader::cachesMutex_; // Takes ownership of backend. DiskCachingFileLoader::DiskCachingFileLoader(FileLoader *backend) - : filesize_(0), filepos_(0), backend_(backend), cache_(nullptr) { - filesize_ = backend->FileSize(); + : prepared_(false), filesize_(0), filepos_(0), backend_(backend), cache_(nullptr) { +} + +void DiskCachingFileLoader::Prepare() { + if (prepared_) { + return; + } + prepared_ = true; + + filesize_ = backend_->FileSize(); if (filesize_ > 0) { InitCache(); } @@ -54,19 +62,22 @@ DiskCachingFileLoader::~DiskCachingFileLoader() { } bool DiskCachingFileLoader::Exists() { - if (cache_ && cache_->HasData()) { - // It may require a slow operation to check - if we have data, let's say yes. - // This helps initial load, since we check each recent file for existence. - return true; - } + Prepare(); return backend_->Exists(); } +bool DiskCachingFileLoader::ExistsFast() { + // It may require a slow operation to check - if we have data, let's say yes. + // This helps initial load, since we check each recent file for existence. + return true; +} + bool DiskCachingFileLoader::IsDirectory() { - return backend_->IsDirectory() ? 1 : 0; + return backend_->IsDirectory(); } s64 DiskCachingFileLoader::FileSize() { + Prepare(); return filesize_; } @@ -79,6 +90,7 @@ void DiskCachingFileLoader::Seek(s64 absolutePos) { } size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) { + Prepare(); size_t readSize; if (absolutePos >= filesize_) { diff --git a/Core/FileLoaders/DiskCachingFileLoader.h b/Core/FileLoaders/DiskCachingFileLoader.h index 511507d240..e0ca3e9adc 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.h +++ b/Core/FileLoaders/DiskCachingFileLoader.h @@ -31,6 +31,7 @@ public: virtual ~DiskCachingFileLoader() override; virtual bool Exists() override; + virtual bool ExistsFast() override; virtual bool IsDirectory() override; virtual s64 FileSize() override; virtual std::string Path() const override; @@ -50,9 +51,11 @@ public: static std::vector GetCachedPathsInUse(); private: + void Prepare(); void InitCache(); void ShutdownCache(); + bool prepared_; s64 filesize_; s64 filepos_; FileLoader *backend_; diff --git a/Core/FileLoaders/HTTPFileLoader.cpp b/Core/FileLoaders/HTTPFileLoader.cpp index 8cc8b9e104..725f6b0cad 100644 --- a/Core/FileLoaders/HTTPFileLoader.cpp +++ b/Core/FileLoaders/HTTPFileLoader.cpp @@ -21,7 +21,15 @@ #include "Core/FileLoaders/HTTPFileLoader.h" HTTPFileLoader::HTTPFileLoader(const std::string &filename) - : filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false) { + : filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false), prepared_(false) { +} + +void HTTPFileLoader::Prepare() { + if (prepared_) { + return; + } + prepared_ = true; + if (!client_.Resolve(url_.Host().c_str(), url_.Port())) { // TODO: Should probably set some flag? return; @@ -39,7 +47,7 @@ HTTPFileLoader::HTTPFileLoader(const std::string &filename) int code = client_.ReadResponseHeaders(&readbuf, responseHeaders); if (code != 200) { // Leave size at 0, invalid. - ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename.c_str()); + ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str()); Disconnect(); return; } @@ -78,7 +86,7 @@ HTTPFileLoader::HTTPFileLoader(const std::string &filename) WARN_LOG(LOADER, "HTTP server did not advertise support for range requests."); } if (filesize_ == 0) { - ERROR_LOG(LOADER, "Could not determine file size for %s", filename.c_str()); + ERROR_LOG(LOADER, "Could not determine file size for %s", filename_.c_str()); } // If we didn't end up with a filesize_ (e.g. chunked response), give up. File invalid. @@ -89,15 +97,21 @@ HTTPFileLoader::~HTTPFileLoader() { } bool HTTPFileLoader::Exists() { + Prepare(); return url_.Valid() && filesize_ > 0; } +bool HTTPFileLoader::ExistsFast() { + return url_.Valid(); +} + bool HTTPFileLoader::IsDirectory() { // Only files. return false; } s64 HTTPFileLoader::FileSize() { + Prepare(); return filesize_; } @@ -110,6 +124,7 @@ void HTTPFileLoader::Seek(s64 absolutePos) { } size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data) { + Prepare(); s64 absoluteEnd = std::min(absolutePos + (s64)bytes, filesize_); if (absolutePos >= filesize_ || bytes == 0) { // Read outside of the file or no read at all, just fail immediately. diff --git a/Core/FileLoaders/HTTPFileLoader.h b/Core/FileLoaders/HTTPFileLoader.h index de4cd53adb..69c0ce5e50 100644 --- a/Core/FileLoaders/HTTPFileLoader.h +++ b/Core/FileLoaders/HTTPFileLoader.h @@ -29,6 +29,7 @@ public: virtual ~HTTPFileLoader() override; virtual bool Exists() override; + virtual bool ExistsFast() override; virtual bool IsDirectory() override; virtual s64 FileSize() override; virtual std::string Path() const override; @@ -46,6 +47,8 @@ public: virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data) override; private: + void Prepare(); + void Connect() { if (!connected_) { connected_ = client_.Connect(); @@ -66,4 +69,5 @@ private: http::Client client_; std::string filename_; bool connected_; + bool prepared_; }; diff --git a/Core/FileLoaders/RamCachingFileLoader.cpp b/Core/FileLoaders/RamCachingFileLoader.cpp index 20598d631c..b9e75e1c2f 100644 --- a/Core/FileLoaders/RamCachingFileLoader.cpp +++ b/Core/FileLoaders/RamCachingFileLoader.cpp @@ -48,6 +48,14 @@ bool RamCachingFileLoader::Exists() { return exists_ == 1; } +bool RamCachingFileLoader::ExistsFast() { + if (exists_ == -1) { + lock_guard guard(backendMutex_); + return backend_->ExistsFast(); + } + return exists_ == 1; +} + bool RamCachingFileLoader::IsDirectory() { if (isDirectory_ == -1) { lock_guard guard(backendMutex_); diff --git a/Core/FileLoaders/RamCachingFileLoader.h b/Core/FileLoaders/RamCachingFileLoader.h index e1678ccd4c..38d05826f7 100644 --- a/Core/FileLoaders/RamCachingFileLoader.h +++ b/Core/FileLoaders/RamCachingFileLoader.h @@ -28,6 +28,7 @@ public: ~RamCachingFileLoader() override; bool Exists() override; + bool ExistsFast() override; bool IsDirectory() override; s64 FileSize() override; std::string Path() const override; diff --git a/Core/FileLoaders/RetryingFileLoader.cpp b/Core/FileLoaders/RetryingFileLoader.cpp index 4a998f1777..28fa17a955 100644 --- a/Core/FileLoaders/RetryingFileLoader.cpp +++ b/Core/FileLoaders/RetryingFileLoader.cpp @@ -35,6 +35,14 @@ bool RetryingFileLoader::Exists() { return true; } +bool RetryingFileLoader::ExistsFast() { + if (!backend_->ExistsFast()) { + // Retry once, immediately. + return backend_->ExistsFast(); + } + return true; +} + bool RetryingFileLoader::IsDirectory() { // Can't tell if it's an error either way. return backend_->IsDirectory(); diff --git a/Core/FileLoaders/RetryingFileLoader.h b/Core/FileLoaders/RetryingFileLoader.h index 962e7fc5cd..24cd0c284a 100644 --- a/Core/FileLoaders/RetryingFileLoader.h +++ b/Core/FileLoaders/RetryingFileLoader.h @@ -26,6 +26,7 @@ public: virtual ~RetryingFileLoader() override; virtual bool Exists() override; + virtual bool ExistsFast() override; virtual bool IsDirectory() override; virtual s64 FileSize() override; virtual std::string Path() const override; diff --git a/Core/Loaders.h b/Core/Loaders.h index 4fbe126a5a..2fe2e8cc46 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -54,6 +54,9 @@ public: virtual ~FileLoader() {} virtual bool Exists() = 0; + virtual bool ExistsFast() { + return Exists(); + } virtual bool IsDirectory() = 0; virtual s64 FileSize() = 0; virtual std::string Path() const = 0;