mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-02 22:28:45 +00:00
SaveData: log backup error and continue & fix possible concurrent file editing
This commit is contained in:
parent
6c73d80641
commit
a73efdad30
1 changed files with 24 additions and 10 deletions
|
@ -18,6 +18,7 @@
|
||||||
constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save
|
constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save
|
||||||
constexpr std::string_view backup_dir = "sce_backup"; // backup folder
|
constexpr std::string_view backup_dir = "sce_backup"; // backup folder
|
||||||
constexpr std::string_view backup_dir_tmp = "sce_backup_tmp"; // in-progress backup folder
|
constexpr std::string_view backup_dir_tmp = "sce_backup_tmp"; // in-progress backup folder
|
||||||
|
constexpr std::string_view backup_dir_old = "sce_backup_old"; // previous backup folder
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
@ -26,6 +27,8 @@ namespace Libraries::SaveData::Backup {
|
||||||
static std::jthread g_backup_thread;
|
static std::jthread g_backup_thread;
|
||||||
static std::counting_semaphore g_backup_thread_semaphore{0};
|
static std::counting_semaphore g_backup_thread_semaphore{0};
|
||||||
|
|
||||||
|
static std::mutex g_backup_running_mutex;
|
||||||
|
|
||||||
static std::mutex g_backup_queue_mutex;
|
static std::mutex g_backup_queue_mutex;
|
||||||
static std::deque<BackupRequest> g_backup_queue;
|
static std::deque<BackupRequest> g_backup_queue;
|
||||||
static std::deque<BackupRequest> g_result_queue;
|
static std::deque<BackupRequest> g_result_queue;
|
||||||
|
@ -34,38 +37,44 @@ static std::atomic_int g_backup_progress = 0;
|
||||||
static std::atomic g_backup_status = WorkerStatus::NotStarted;
|
static std::atomic g_backup_status = WorkerStatus::NotStarted;
|
||||||
|
|
||||||
static void backup(const std::filesystem::path& dir_name) {
|
static void backup(const std::filesystem::path& dir_name) {
|
||||||
|
std::unique_lock lk{g_backup_running_mutex};
|
||||||
if (!fs::exists(dir_name)) {
|
if (!fs::exists(dir_name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto backup_dir = dir_name / ::backup_dir;
|
||||||
|
const auto backup_dir_tmp = dir_name / ::backup_dir_tmp;
|
||||||
|
const auto backup_dir_old = dir_name / ::backup_dir_old;
|
||||||
|
|
||||||
|
fs::remove_all(backup_dir_tmp);
|
||||||
|
fs::remove_all(backup_dir_old);
|
||||||
|
|
||||||
std::vector<std::filesystem::path> backup_files;
|
std::vector<std::filesystem::path> backup_files;
|
||||||
for (const auto& entry : fs::directory_iterator(dir_name)) {
|
for (const auto& entry : fs::directory_iterator(dir_name)) {
|
||||||
const auto filename = entry.path().filename();
|
const auto filename = entry.path().filename();
|
||||||
if (filename != backup_dir && filename != backup_dir_tmp) {
|
if (filename != backup_dir) {
|
||||||
backup_files.push_back(entry.path());
|
backup_files.push_back(entry.path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto backup_dir = dir_name / ::backup_dir;
|
|
||||||
const auto backup_dir_tmp = dir_name / ::backup_dir_tmp;
|
|
||||||
|
|
||||||
g_backup_progress = 0;
|
g_backup_progress = 0;
|
||||||
|
|
||||||
int total_count = static_cast<int>(backup_files.size());
|
int total_count = static_cast<int>(backup_files.size());
|
||||||
int current_count = 0;
|
int current_count = 0;
|
||||||
|
|
||||||
fs::remove_all(backup_dir_tmp);
|
|
||||||
fs::create_directory(backup_dir_tmp);
|
fs::create_directory(backup_dir_tmp);
|
||||||
for (const auto& file : backup_files) {
|
for (const auto& file : backup_files) {
|
||||||
fs::copy(file, backup_dir_tmp / file.filename(), fs::copy_options::recursive);
|
fs::copy(file, backup_dir_tmp / file.filename(), fs::copy_options::recursive);
|
||||||
current_count++;
|
current_count++;
|
||||||
g_backup_progress = current_count * 100 / total_count;
|
g_backup_progress = current_count * 100 / total_count;
|
||||||
}
|
}
|
||||||
bool has_existing = fs::exists(backup_dir);
|
bool has_existing_backup = fs::exists(backup_dir);
|
||||||
if (has_existing) {
|
if (has_existing_backup) {
|
||||||
fs::rename(backup_dir, dir_name / "sce_backup_old");
|
fs::rename(backup_dir, backup_dir_old);
|
||||||
}
|
}
|
||||||
fs::rename(backup_dir_tmp, backup_dir);
|
fs::rename(backup_dir_tmp, backup_dir);
|
||||||
if (has_existing) {
|
if (has_existing_backup) {
|
||||||
fs::remove_all(dir_name / "sce_backup_old");
|
fs::remove_all(backup_dir_old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +93,11 @@ static void BackupThreadBody() {
|
||||||
}
|
}
|
||||||
g_backup_status = WorkerStatus::Running;
|
g_backup_status = WorkerStatus::Running;
|
||||||
LOG_INFO(Lib_SaveData, "Backing up the following directory: {}", req.save_path.string());
|
LOG_INFO(Lib_SaveData, "Backing up the following directory: {}", req.save_path.string());
|
||||||
backup(req.save_path);
|
try {
|
||||||
|
backup(req.save_path);
|
||||||
|
} catch (const std::filesystem::filesystem_error& err) {
|
||||||
|
LOG_ERROR(Lib_SaveData, "Failed to backup {}: {}", req.save_path.string(), err.what());
|
||||||
|
}
|
||||||
LOG_DEBUG(Lib_SaveData, "Backing up the following directory: {} finished",
|
LOG_DEBUG(Lib_SaveData, "Backing up the following directory: {} finished",
|
||||||
req.save_path.string());
|
req.save_path.string());
|
||||||
{
|
{
|
||||||
|
@ -146,6 +159,7 @@ bool NewRequest(OrbisUserServiceUserId user_id, std::string_view title_id,
|
||||||
|
|
||||||
bool Restore(const std::filesystem::path& save_path) {
|
bool Restore(const std::filesystem::path& save_path) {
|
||||||
LOG_INFO(Lib_SaveData, "Restoring backup for {}", save_path.string());
|
LOG_INFO(Lib_SaveData, "Restoring backup for {}", save_path.string());
|
||||||
|
std::unique_lock lk{g_backup_running_mutex};
|
||||||
if (!fs::exists(save_path) || !fs::exists(save_path / backup_dir)) {
|
if (!fs::exists(save_path) || !fs::exists(save_path / backup_dir)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue