Add metafilesystem hook to add optimized implementations of compute recursive directory size
This commit is contained in:
parent
e842d395fa
commit
48310d15a9
11 changed files with 88 additions and 13 deletions
|
@ -73,7 +73,7 @@ inline StorageError Android_RemoveFile(const std::string &fileUri) { return Stor
|
||||||
inline StorageError Android_RenameFileTo(const std::string &fileUri, const std::string &newName) { return StorageError::UNKNOWN; }
|
inline StorageError Android_RenameFileTo(const std::string &fileUri, const std::string &newName) { return StorageError::UNKNOWN; }
|
||||||
inline bool Android_GetFileInfo(const std::string &fileUri, File::FileInfo *info) { return false; }
|
inline bool Android_GetFileInfo(const std::string &fileUri, File::FileInfo *info) { return false; }
|
||||||
inline bool Android_FileExists(const std::string &fileUri) { return false; }
|
inline bool Android_FileExists(const std::string &fileUri) { return false; }
|
||||||
inline int64_t Android_GetRecursiveDirectorySize(const std::string &fileUri) { return -1; }
|
inline int64_t Android_ComputeRecursiveDirectorySize(const std::string &fileUri) { return -1; }
|
||||||
inline int64_t Android_GetFreeSpaceByContentUri(const std::string &uri) { return -1; }
|
inline int64_t Android_GetFreeSpaceByContentUri(const std::string &uri) { return -1; }
|
||||||
inline int64_t Android_GetFreeSpaceByFilePath(const std::string &filePath) { return -1; }
|
inline int64_t Android_GetFreeSpaceByFilePath(const std::string &filePath) { return -1; }
|
||||||
inline bool Android_IsExternalStoragePreservedLegacy() { return false; }
|
inline bool Android_IsExternalStoragePreservedLegacy() { return false; }
|
||||||
|
|
|
@ -324,6 +324,34 @@ std::string ResolvePath(const std::string &path) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t RecursiveSize(const Path &path) {
|
||||||
|
// TODO: Some file systems can optimize this.
|
||||||
|
std::vector<FileInfo> fileInfo;
|
||||||
|
if (!GetFilesInDir(path, &fileInfo)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int64_t result = 0;
|
||||||
|
for (const auto &file : fileInfo) {
|
||||||
|
if (file.name == "." || file.name == "..")
|
||||||
|
continue;
|
||||||
|
if (file.isDirectory) {
|
||||||
|
result += RecursiveSize(file.fullName);
|
||||||
|
} else {
|
||||||
|
result += file.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ComputeRecursiveDirectorySize(const Path &path) {
|
||||||
|
if (path.Type() == PathType::CONTENT_URI) {
|
||||||
|
return Android_ComputeRecursiveDirectorySize(path.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic solution.
|
||||||
|
return RecursiveSize(path);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if file filename exists. Will return true on directories.
|
// Returns true if file filename exists. Will return true on directories.
|
||||||
bool ExistsInDir(const Path &path, const std::string &filename) {
|
bool ExistsInDir(const Path &path, const std::string &filename) {
|
||||||
return Exists(path / filename);
|
return Exists(path / filename);
|
||||||
|
|
|
@ -79,6 +79,9 @@ uint64_t GetFileSize(const Path &filename);
|
||||||
// Overloaded GetSize, accepts FILE*
|
// Overloaded GetSize, accepts FILE*
|
||||||
uint64_t GetFileSize(FILE *f);
|
uint64_t GetFileSize(FILE *f);
|
||||||
|
|
||||||
|
// Computes the recursive size of a directory. Warning: Might be slow!
|
||||||
|
uint64_t ComputeRecursiveDirectorySize(const Path &path);
|
||||||
|
|
||||||
// Returns true if successful, or path already exists.
|
// Returns true if successful, or path already exists.
|
||||||
bool CreateDir(const Path &filename);
|
bool CreateDir(const Path &filename);
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ public:
|
||||||
bool RemoveFile(const std::string &filename) override;
|
bool RemoveFile(const std::string &filename) override;
|
||||||
u64 FreeSpace(const std::string &path) override;
|
u64 FreeSpace(const std::string &path) override;
|
||||||
|
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// File positions.
|
// File positions.
|
||||||
std::map<u32, s64> entries_;
|
std::map<u32, s64> entries_;
|
||||||
|
|
|
@ -115,6 +115,9 @@ public:
|
||||||
FileSystemFlags Flags() override { return flags; }
|
FileSystemFlags Flags() override { return flags; }
|
||||||
u64 FreeSpace(const std::string &path) override;
|
u64 FreeSpace(const std::string &path) override;
|
||||||
|
|
||||||
|
// TODO: Replace with optimized implementation.
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct OpenFileEntry {
|
struct OpenFileEntry {
|
||||||
DirectoryFileHandle hFile;
|
DirectoryFileHandle hFile;
|
||||||
|
@ -159,6 +162,8 @@ public:
|
||||||
FileSystemFlags Flags() override { return FileSystemFlags::FLASH; }
|
FileSystemFlags Flags() override { return FileSystemFlags::FLASH; }
|
||||||
u64 FreeSpace(const std::string &path) override { return 0; }
|
u64 FreeSpace(const std::string &path) override { return 0; }
|
||||||
|
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct OpenFileEntry {
|
struct OpenFileEntry {
|
||||||
u8 *fileData;
|
u8 *fileData;
|
||||||
|
|
|
@ -136,11 +136,11 @@ public:
|
||||||
virtual PSPDevType DevType(u32 handle) = 0;
|
virtual PSPDevType DevType(u32 handle) = 0;
|
||||||
virtual FileSystemFlags Flags() = 0;
|
virtual FileSystemFlags Flags() = 0;
|
||||||
virtual u64 FreeSpace(const std::string &path) = 0;
|
virtual u64 FreeSpace(const std::string &path) = 0;
|
||||||
|
virtual bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class EmptyFileSystem : public IFileSystem
|
class EmptyFileSystem : public IFileSystem {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual void DoState(PointerWrap &p) override {}
|
virtual void DoState(PointerWrap &p) override {}
|
||||||
std::vector<PSPFileInfo> GetDirListing(std::string path) override {std::vector<PSPFileInfo> vec; return vec;}
|
std::vector<PSPFileInfo> GetDirListing(std::string path) override {std::vector<PSPFileInfo> vec; return vec;}
|
||||||
|
@ -161,6 +161,7 @@ public:
|
||||||
virtual PSPDevType DevType(u32 handle) override { return PSPDevType::INVALID; }
|
virtual PSPDevType DevType(u32 handle) override { return PSPDevType::INVALID; }
|
||||||
virtual FileSystemFlags Flags() override { return FileSystemFlags::NONE; }
|
virtual FileSystemFlags Flags() override { return FileSystemFlags::NONE; }
|
||||||
virtual u64 FreeSpace(const std::string &path) override { return 0; }
|
virtual u64 FreeSpace(const std::string &path) override { return 0; }
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,8 @@ public:
|
||||||
int RenameFile(const std::string &from, const std::string &to) override { return -1; }
|
int RenameFile(const std::string &from, const std::string &to) override { return -1; }
|
||||||
bool RemoveFile(const std::string &filename) override { return false; }
|
bool RemoveFile(const std::string &filename) override { return false; }
|
||||||
|
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct TreeEntry {
|
struct TreeEntry {
|
||||||
~TreeEntry();
|
~TreeEntry();
|
||||||
|
@ -150,6 +152,8 @@ public:
|
||||||
int RenameFile(const std::string &from, const std::string &to) override { return -1; }
|
int RenameFile(const std::string &from, const std::string &to) override { return -1; }
|
||||||
bool RemoveFile(const std::string &filename) override { return false; }
|
bool RemoveFile(const std::string &filename) override { return false; }
|
||||||
|
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<IFileSystem> isoFileSystem_;
|
std::shared_ptr<IFileSystem> isoFileSystem_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -500,12 +500,9 @@ bool MetaFileSystem::RemoveFile(const std::string &filename)
|
||||||
std::string of;
|
std::string of;
|
||||||
IFileSystem *system;
|
IFileSystem *system;
|
||||||
int error = MapFilePath(filename, of, &system);
|
int error = MapFilePath(filename, of, &system);
|
||||||
if (error == 0)
|
if (error == 0) {
|
||||||
{
|
|
||||||
return system->RemoveFile(of);
|
return system->RemoveFile(of);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -648,17 +645,36 @@ void MetaFileSystem::DoState(PointerWrap &p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 MetaFileSystem::getDirSize(const std::string &dirPath) {
|
int64_t MetaFileSystem::RecursiveSize(const std::string &dirPath) {
|
||||||
u64 result = 0;
|
u64 result = 0;
|
||||||
auto allFiles = GetDirListing(dirPath);
|
auto allFiles = GetDirListing(dirPath);
|
||||||
for (auto file : allFiles) {
|
for (auto file : allFiles) {
|
||||||
if (file.name == "." || file.name == "..")
|
if (file.name == "." || file.name == "..")
|
||||||
continue;
|
continue;
|
||||||
if (file.type == FILETYPE_DIRECTORY) {
|
if (file.type == FILETYPE_DIRECTORY) {
|
||||||
result += getDirSize(dirPath + file.name);
|
result += RecursiveSize(dirPath + file.name);
|
||||||
} else {
|
} else {
|
||||||
result += file.size;
|
result += file.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t MetaFileSystem::ComputeRecursiveDirectorySize(const std::string &filename) {
|
||||||
|
std::lock_guard<std::recursive_mutex> guard(lock);
|
||||||
|
std::string of;
|
||||||
|
IFileSystem *system;
|
||||||
|
int error = MapFilePath(filename, of, &system);
|
||||||
|
if (error == 0) {
|
||||||
|
int64_t size;
|
||||||
|
if (system->ComputeRecursiveDirSizeIfFast(of, &size)) {
|
||||||
|
// Some file systems can optimize this.
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
// Those that can't, we just run a generic implementation.
|
||||||
|
return RecursiveSize(filename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -136,5 +136,19 @@ public:
|
||||||
startingDirectory = dir;
|
startingDirectory = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 getDirSize(const std::string &dirPath);
|
int64_t ComputeRecursiveDirectorySize(const std::string &dirPath);
|
||||||
|
|
||||||
|
// Shouldn't ever be called, but meh.
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override {
|
||||||
|
int64_t sizeTemp = ComputeRecursiveDirectorySize(path);
|
||||||
|
if (sizeTemp >= 0) {
|
||||||
|
*size = sizeTemp;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t RecursiveSize(const std::string &dirPath);
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,6 +52,8 @@ public:
|
||||||
int RenameFile(const std::string &from, const std::string &to) override;
|
int RenameFile(const std::string &from, const std::string &to) override;
|
||||||
bool RemoveFile(const std::string &filename) override;
|
bool RemoveFile(const std::string &filename) override;
|
||||||
|
|
||||||
|
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadFileListIndex();
|
void LoadFileListIndex();
|
||||||
// Warning: modifies input string.
|
// Warning: modifies input string.
|
||||||
|
|
|
@ -96,7 +96,7 @@ static void MemoryStick_CalcInitialFree() {
|
||||||
std::unique_lock<std::mutex> guard(freeCalcMutex);
|
std::unique_lock<std::mutex> guard(freeCalcMutex);
|
||||||
freeCalcStatus = FreeCalcStatus::RUNNING;
|
freeCalcStatus = FreeCalcStatus::RUNNING;
|
||||||
freeCalcThread = std::thread([] {
|
freeCalcThread = std::thread([] {
|
||||||
memstickInitialFree = pspFileSystem.FreeSpace("ms0:/") + pspFileSystem.getDirSize("ms0:/PSP/SAVEDATA/");
|
memstickInitialFree = pspFileSystem.FreeSpace("ms0:/") + pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/");
|
||||||
|
|
||||||
std::unique_lock<std::mutex> guard(freeCalcMutex);
|
std::unique_lock<std::mutex> guard(freeCalcMutex);
|
||||||
freeCalcStatus = FreeCalcStatus::DONE;
|
freeCalcStatus = FreeCalcStatus::DONE;
|
||||||
|
@ -127,7 +127,7 @@ u64 MemoryStick_FreeSpace() {
|
||||||
|
|
||||||
// Assume the memory stick is only used to store savedata.
|
// Assume the memory stick is only used to store savedata.
|
||||||
if (!memstickCurrentUseValid) {
|
if (!memstickCurrentUseValid) {
|
||||||
memstickCurrentUse = pspFileSystem.getDirSize("ms0:/PSP/SAVEDATA/");
|
memstickCurrentUse = pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/");
|
||||||
memstickCurrentUseValid = true;
|
memstickCurrentUseValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue