From 8a5be211408078764963ad5ebff4af879189a73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 11 Oct 2024 11:55:27 +0200 Subject: [PATCH] MemStick screen: Call free_disk_space from async tasks See #19522 --- Common/File/DiskFree.h | 1 + Core/FileSystems/BlobFileSystem.cpp | 2 +- Core/FileSystems/BlobFileSystem.h | 2 +- Core/FileSystems/DirectoryFileSystem.cpp | 2 +- Core/FileSystems/DirectoryFileSystem.h | 4 +- Core/FileSystems/FileSystem.h | 4 +- Core/FileSystems/ISOFileSystem.h | 4 +- Core/FileSystems/MetaFileSystem.cpp | 11 ++--- Core/FileSystems/MetaFileSystem.h | 2 +- Core/FileSystems/VirtualDiscFileSystem.h | 2 +- Core/HW/MemoryStick.cpp | 6 ++- UI/MemStickScreen.cpp | 51 +++++++++++++++++++----- UI/MemStickScreen.h | 8 ++++ 13 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Common/File/DiskFree.h b/Common/File/DiskFree.h index a08f44bdd1..a5a5fb3c68 100644 --- a/Common/File/DiskFree.h +++ b/Common/File/DiskFree.h @@ -5,4 +5,5 @@ #include "Common/File/Path.h" // If this fails, false is returned and space is negative. +// Try to avoid calling this from the main thread, if possible. Can be SLOW. bool free_disk_space(const Path &path, int64_t &space); diff --git a/Core/FileSystems/BlobFileSystem.cpp b/Core/FileSystems/BlobFileSystem.cpp index fb47eefa9d..ddcb20cc41 100644 --- a/Core/FileSystems/BlobFileSystem.cpp +++ b/Core/FileSystems/BlobFileSystem.cpp @@ -130,6 +130,6 @@ bool BlobFileSystem::RemoveFile(const std::string &filename) { return false; } -u64 BlobFileSystem::FreeSpace(const std::string &path) { +u64 BlobFileSystem::FreeDiskSpace(const std::string &path) { return 0; } diff --git a/Core/FileSystems/BlobFileSystem.h b/Core/FileSystems/BlobFileSystem.h index 6def55870d..adb4440c90 100644 --- a/Core/FileSystems/BlobFileSystem.h +++ b/Core/FileSystems/BlobFileSystem.h @@ -52,7 +52,7 @@ public: bool RmDir(const std::string &dirname) override; int RenameFile(const std::string &from, const std::string &to) override; bool RemoveFile(const std::string &filename) override; - u64 FreeSpace(const std::string &path) override; + u64 FreeDiskSpace(const std::string &path) override; bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; } diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index f3948bf347..eb2d6c68d4 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -871,7 +871,7 @@ std::vector DirectoryFileSystem::GetDirListing(const std::string &p return ReplayApplyDiskListing(myVector, CoreTiming::GetGlobalTimeUs()); } -u64 DirectoryFileSystem::FreeSpace(const std::string &path) { +u64 DirectoryFileSystem::FreeDiskSpace(const std::string &path) { int64_t result = 0; if (free_disk_space(GetLocalPath(path), result)) { return ReplayApplyDisk64(ReplayAction::FREESPACE, (uint64_t)result, CoreTiming::GetGlobalTimeUs()); diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index 965a90f8fc..d0a9f9d6f5 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -83,7 +83,7 @@ public: int RenameFile(const std::string &from, const std::string &to) override; bool RemoveFile(const std::string &filename) override; FileSystemFlags Flags() override { return flags; } - u64 FreeSpace(const std::string &path) override; + u64 FreeDiskSpace(const std::string &path) override; bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override; @@ -129,7 +129,7 @@ public: int RenameFile(const std::string &from, const std::string &to) override; bool RemoveFile(const std::string &filename) override; FileSystemFlags Flags() override { return FileSystemFlags::FLASH; } - u64 FreeSpace(const std::string &path) override { return 0; } + u64 FreeDiskSpace(const std::string &path) override { return 0; } bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; } diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index 693c1a55d9..27953fe76c 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -145,7 +145,7 @@ public: virtual int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) = 0; virtual PSPDevType DevType(u32 handle) = 0; virtual FileSystemFlags Flags() = 0; - virtual u64 FreeSpace(const std::string &path) = 0; + virtual u64 FreeDiskSpace(const std::string &path) = 0; virtual bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) = 0; }; @@ -175,7 +175,7 @@ public: int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override { return SCE_KERNEL_ERROR_ERRNO_FUNCTION_NOT_SUPPORTED; } PSPDevType DevType(u32 handle) override { return PSPDevType::INVALID; } FileSystemFlags Flags() override { return FileSystemFlags::NONE; } - u64 FreeSpace(const std::string &path) override { return 0; } + u64 FreeDiskSpace(const std::string &path) override { return 0; } bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; } }; diff --git a/Core/FileSystems/ISOFileSystem.h b/Core/FileSystems/ISOFileSystem.h index 668c4d7174..492fcf9b2b 100644 --- a/Core/FileSystems/ISOFileSystem.h +++ b/Core/FileSystems/ISOFileSystem.h @@ -44,7 +44,7 @@ public: int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; PSPDevType DevType(u32 handle) override; FileSystemFlags Flags() override; - u64 FreeSpace(const std::string &path) override { return 0; } + u64 FreeDiskSpace(const std::string &path) override { return 0; } size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override; size_t WriteFile(u32 handle, const u8 *pointer, s64 size, int &usec) override; @@ -146,7 +146,7 @@ public: return isoFileSystem_->DevType(handle); } FileSystemFlags Flags() override { return isoFileSystem_->Flags(); } - u64 FreeSpace(const std::string &path) override { return isoFileSystem_->FreeSpace(path); } + u64 FreeDiskSpace(const std::string &path) override { return isoFileSystem_->FreeDiskSpace(path); } size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override { return isoFileSystem_->WriteFile(handle, pointer, size); diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index adc86c0ebb..1ab0e2cb94 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -606,20 +606,18 @@ int MetaFileSystem::ReadEntireFile(const std::string &filename, std::vector return 0; } -u64 MetaFileSystem::FreeSpace(const std::string &path) -{ +u64 MetaFileSystem::FreeDiskSpace(const std::string &path) { std::lock_guard guard(lock); std::string of; IFileSystem *system; int error = MapFilePath(path, of, &system); if (error == 0) - return system->FreeSpace(of); + return system->FreeDiskSpace(of); else return 0; } -void MetaFileSystem::DoState(PointerWrap &p) -{ +void MetaFileSystem::DoState(PointerWrap &p) { std::lock_guard guard(lock); auto s = p.Section("MetaFileSystem", 1); @@ -634,8 +632,7 @@ void MetaFileSystem::DoState(PointerWrap &p) u32 n = (u32) fileSystems.size(); Do(p, n); bool skipPfat0 = false; - if (n != (u32) fileSystems.size()) - { + if (n != (u32) fileSystems.size()) { if (n == (u32) fileSystems.size() - 1) { skipPfat0 = true; } else { diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index 0a2255566f..54cc5c9d8f 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -127,7 +127,7 @@ public: int Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 outlen, int &usec) override; PSPDevType DevType(u32 handle) override; FileSystemFlags Flags() override { return FileSystemFlags::NONE; } - u64 FreeSpace(const std::string &path) override; + u64 FreeDiskSpace(const std::string &path) override; // Convenience helper - returns < 0 on failure. int ReadEntireFile(const std::string &filename, std::vector &data, bool quiet = false); diff --git a/Core/FileSystems/VirtualDiscFileSystem.h b/Core/FileSystems/VirtualDiscFileSystem.h index d2839ad21b..e8110e0b2d 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.h +++ b/Core/FileSystems/VirtualDiscFileSystem.h @@ -44,7 +44,7 @@ public: PSPDevType DevType(u32 handle) override; std::vector GetDirListing(const std::string &path, bool *exists = nullptr) override; FileSystemFlags Flags() override { return FileSystemFlags::UMD; } - u64 FreeSpace(const std::string &path) override { return 0; } + u64 FreeDiskSpace(const std::string &path) override { return 0; } // unsupported operations size_t WriteFile(u32 handle, const u8 *pointer, s64 size) override; diff --git a/Core/HW/MemoryStick.cpp b/Core/HW/MemoryStick.cpp index 8511a9d76c..8d503f8694 100644 --- a/Core/HW/MemoryStick.cpp +++ b/Core/HW/MemoryStick.cpp @@ -103,7 +103,7 @@ static void MemoryStick_CalcInitialFree() { AndroidJNIThreadContext jniContext; - memstickInitialFree = pspFileSystem.FreeSpace("ms0:/") + pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/"); + memstickInitialFree = pspFileSystem.FreeDiskSpace("ms0:/") + pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/"); std::unique_lock guard(freeCalcMutex); freeCalcStatus = FreeCalcStatus::DONE; @@ -122,10 +122,12 @@ static void MemoryStick_WaitInitialFree() { } u64 MemoryStick_FreeSpace() { + NOTICE_LOG(Log::IO, "Calculated free disk space"); + MemoryStick_WaitInitialFree(); const CompatFlags &flags = PSP_CoreParameter().compat.flags(); - u64 realFreeSpace = pspFileSystem.FreeSpace("ms0:/"); + u64 realFreeSpace = pspFileSystem.FreeDiskSpace("ms0:/"); // Cap the memory stick size to avoid math errors when old games get sizes that were // not planned for back then (even though 2GB cards were available.) diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index d7f28bbf57..fffb2f8321 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -470,6 +470,14 @@ ConfirmMemstickMoveScreen::~ConfirmMemstickMoveScreen() { moveDataTask_->BlockUntilReady(); delete moveDataTask_; } + if (oldSpaceTask_) { + oldSpaceTask_->BlockUntilReady(); + delete oldSpaceTask_; + } + if (newSpaceTask_) { + newSpaceTask_->BlockUntilReady(); + delete newSpaceTask_; + } } void ConfirmMemstickMoveScreen::CreateViews() { @@ -479,7 +487,7 @@ void ConfirmMemstickMoveScreen::CreateViews() { root_ = new LinearLayout(ORIENT_HORIZONTAL); - Path oldMemstickFolder = g_Config.memStickDirectory; + Path &oldMemstickFolder = g_Config.memStickDirectory; Spacer *spacerColumn = new Spacer(new LinearLayoutParams(20.0, FILL_PARENT, 0.0f)); ViewGroup *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0)); @@ -488,18 +496,20 @@ void ConfirmMemstickMoveScreen::CreateViews() { root_->Add(leftColumn); root_->Add(rightColumn); - int64_t freeSpaceNew; - int64_t freeSpaceOld; - free_disk_space(newMemstickFolder_, freeSpaceNew); - free_disk_space(oldMemstickFolder, freeSpaceOld); - leftColumn->Add(new TextView(ms->T("Selected PSP Data Folder"), ALIGN_LEFT, false)); if (!initialSetup_) { leftColumn->Add(new NoticeView(NoticeLevel::WARN, ms->T("PPSSPP will restart after the change"), "")); } leftColumn->Add(new TextView(newMemstickFolder_.ToVisualString(), ALIGN_LEFT, false)); - std::string newFreeSpaceText = std::string(ms->T("Free space")) + ": " + FormatSpaceString(freeSpaceNew); - leftColumn->Add(new TextView(newFreeSpaceText, ALIGN_LEFT, false)); + + newFreeSpaceView_ = leftColumn->Add(new TextView(ms->T("Free space"), ALIGN_LEFT, false)); + + newSpaceTask_ = Promise::Spawn(&g_threadManager, [&]() -> SpaceResult * { + int64_t freeSpaceNew; + free_disk_space(newMemstickFolder_, freeSpaceNew); + return new SpaceResult{ freeSpaceNew }; + }, TaskType::IO_BLOCKING, TaskPriority::HIGH); + if (existingFilesInNewFolder_) { leftColumn->Add(new NoticeView(NoticeLevel::SUCCESS, ms->T("Already contains PSP data"), "")); if (!moveData_) { @@ -511,11 +521,15 @@ void ConfirmMemstickMoveScreen::CreateViews() { } if (!oldMemstickFolder.empty()) { - std::string oldFreeSpaceText = std::string(ms->T("Free space")) + ": " + FormatSpaceString(freeSpaceOld); + oldSpaceTask_ = Promise::Spawn(&g_threadManager, [&]() -> SpaceResult * { + int64_t freeSpaceOld; + free_disk_space(oldMemstickFolder, freeSpaceOld); + return new SpaceResult{ freeSpaceOld }; + }, TaskType::IO_BLOCKING, TaskPriority::HIGH); rightColumn->Add(new TextView(std::string(ms->T("Current")) + ":", ALIGN_LEFT, false)); rightColumn->Add(new TextView(oldMemstickFolder.ToVisualString(), ALIGN_LEFT, false)); - rightColumn->Add(new TextView(oldFreeSpaceText, ALIGN_LEFT, false)); + oldFreeSpaceView_ = rightColumn->Add(new TextView(ms->T("Free space"), ALIGN_LEFT, false)); } if (moveDataTask_) { @@ -567,6 +581,23 @@ void ConfirmMemstickMoveScreen::update() { moveDataTask_ = nullptr; } } + + if (newSpaceTask_ && newFreeSpaceView_) { + SpaceResult *result = newSpaceTask_->Poll(); + if (result) { + newFreeSpaceView_->SetText(std::string(ms->T("Free space")) + ": " + FormatSpaceString(result->bytesFree)); + delete newSpaceTask_; + newSpaceTask_ = nullptr; + } + } + if (oldSpaceTask_ && oldFreeSpaceView_) { + SpaceResult *result = oldSpaceTask_->Poll(); + if (result) { + oldFreeSpaceView_->SetText(std::string(ms->T("Free space")) + ": " + FormatSpaceString(result->bytesFree)); + delete oldSpaceTask_; + oldSpaceTask_ = nullptr; + } + } } UI::EventReturn ConfirmMemstickMoveScreen::OnConfirm(UI::EventParams ¶ms) { diff --git a/UI/MemStickScreen.h b/UI/MemStickScreen.h index cb10cffe72..e65b458335 100644 --- a/UI/MemStickScreen.h +++ b/UI/MemStickScreen.h @@ -93,6 +93,10 @@ private: #endif }; +struct SpaceResult { + int64_t bytesFree; +}; + class ConfirmMemstickMoveScreen : public UIDialogScreenWithBackground { public: ConfirmMemstickMoveScreen(const Path &newMemstickFolder, bool initialSetup); @@ -121,8 +125,12 @@ private: MoveProgressReporter progressReporter_; UI::TextView *progressView_ = nullptr; + UI::TextView *newFreeSpaceView_ = nullptr; + UI::TextView *oldFreeSpaceView_ = nullptr; Promise *moveDataTask_ = nullptr; + Promise *oldSpaceTask_ = nullptr; + Promise *newSpaceTask_ = nullptr; std::string error_; };