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 bool Android_GetFileInfo(const std::string &fileUri, File::FileInfo *info) { 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_GetFreeSpaceByFilePath(const std::string &filePath) { return -1; }
|
||||
inline bool Android_IsExternalStoragePreservedLegacy() { return false; }
|
||||
|
|
|
@ -324,6 +324,34 @@ std::string ResolvePath(const std::string &path) {
|
|||
#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.
|
||||
bool ExistsInDir(const Path &path, const std::string &filename) {
|
||||
return Exists(path / filename);
|
||||
|
|
|
@ -79,6 +79,9 @@ uint64_t GetFileSize(const Path &filename);
|
|||
// Overloaded GetSize, accepts FILE*
|
||||
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.
|
||||
bool CreateDir(const Path &filename);
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
bool RemoveFile(const std::string &filename) override;
|
||||
u64 FreeSpace(const std::string &path) override;
|
||||
|
||||
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||
|
||||
private:
|
||||
// File positions.
|
||||
std::map<u32, s64> entries_;
|
||||
|
|
|
@ -115,6 +115,9 @@ public:
|
|||
FileSystemFlags Flags() override { return flags; }
|
||||
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:
|
||||
struct OpenFileEntry {
|
||||
DirectoryFileHandle hFile;
|
||||
|
@ -159,6 +162,8 @@ public:
|
|||
FileSystemFlags Flags() override { return FileSystemFlags::FLASH; }
|
||||
u64 FreeSpace(const std::string &path) override { return 0; }
|
||||
|
||||
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||
|
||||
private:
|
||||
struct OpenFileEntry {
|
||||
u8 *fileData;
|
||||
|
|
|
@ -136,11 +136,11 @@ public:
|
|||
virtual PSPDevType DevType(u32 handle) = 0;
|
||||
virtual FileSystemFlags Flags() = 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:
|
||||
virtual void DoState(PointerWrap &p) override {}
|
||||
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 FileSystemFlags Flags() override { return FileSystemFlags::NONE; }
|
||||
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; }
|
||||
bool RemoveFile(const std::string &filename) override { return false; }
|
||||
|
||||
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||
|
||||
private:
|
||||
struct TreeEntry {
|
||||
~TreeEntry();
|
||||
|
@ -150,6 +152,8 @@ public:
|
|||
int RenameFile(const std::string &from, const std::string &to) override { return -1; }
|
||||
bool RemoveFile(const std::string &filename) override { return false; }
|
||||
|
||||
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<IFileSystem> isoFileSystem_;
|
||||
};
|
||||
|
|
|
@ -500,12 +500,9 @@ bool MetaFileSystem::RemoveFile(const std::string &filename)
|
|||
std::string of;
|
||||
IFileSystem *system;
|
||||
int error = MapFilePath(filename, of, &system);
|
||||
if (error == 0)
|
||||
{
|
||||
if (error == 0) {
|
||||
return system->RemoveFile(of);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
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;
|
||||
auto allFiles = GetDirListing(dirPath);
|
||||
for (auto file : allFiles) {
|
||||
if (file.name == "." || file.name == "..")
|
||||
continue;
|
||||
if (file.type == FILETYPE_DIRECTORY) {
|
||||
result += getDirSize(dirPath + file.name);
|
||||
result += RecursiveSize(dirPath + file.name);
|
||||
} else {
|
||||
result += file.size;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
bool RemoveFile(const std::string &filename) override;
|
||||
|
||||
bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; }
|
||||
|
||||
private:
|
||||
void LoadFileListIndex();
|
||||
// Warning: modifies input string.
|
||||
|
|
|
@ -96,7 +96,7 @@ static void MemoryStick_CalcInitialFree() {
|
|||
std::unique_lock<std::mutex> guard(freeCalcMutex);
|
||||
freeCalcStatus = FreeCalcStatus::RUNNING;
|
||||
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);
|
||||
freeCalcStatus = FreeCalcStatus::DONE;
|
||||
|
@ -127,7 +127,7 @@ u64 MemoryStick_FreeSpace() {
|
|||
|
||||
// Assume the memory stick is only used to store savedata.
|
||||
if (!memstickCurrentUseValid) {
|
||||
memstickCurrentUse = pspFileSystem.getDirSize("ms0:/PSP/SAVEDATA/");
|
||||
memstickCurrentUse = pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/");
|
||||
memstickCurrentUseValid = true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue