Skip to content

Commit

Permalink
Qt: more package install fixes
Browse files Browse the repository at this point in the history
- Clean directories if fill_path fails
- Fix check_target_app_version when installing multiple packages (compromise: no more optimized singular file installs)
  • Loading branch information
Megamouse committed Jan 11, 2023
1 parent e9ba620 commit 8d7dca1
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 22 deletions.
60 changes: 53 additions & 7 deletions rpcs3/Crypto/unpkg.cpp
Expand Up @@ -988,29 +988,70 @@ void package_reader::extract_worker(thread_key thread_data_key)
}
}

bool package_reader::extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths)
package_error package_reader::extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths)
{
std::map<std::string, install_entry*> all_install_entries;
package_error error = package_error::no_error;

// Use a seperate map for each reader. We need to check if the target app version exists for each package in sequence.
std::vector<std::map<std::string, install_entry*>> all_install_entries;

for (package_reader& reader : readers)
{
if (!reader.fill_data(all_install_entries))
reader.m_result = result::not_started;
error = reader.check_target_app_version();

if (error == package_error::no_error)
{
return false;
reader.m_result = result::started;
all_install_entries.push_back({});

if (!reader.fill_data(all_install_entries.back()))
{
error = package_error::other;
}
}

if (error != package_error::no_error)
{
reader.m_result = result::error;
break;
}
}

if (error != package_error::no_error)
{
// Clean dirty dirs
for (package_reader& other : readers)
{
if (other.m_was_null && fs::is_dir(other.m_install_path))
{
pkg_log.notice("Removing partial installation ('%s')", other.m_install_path);

if (fs::remove_all(other.m_install_path, true))
{
other.m_result = other.m_result == result::error ? result::error_cleaned : result::aborted_cleaned;
}
else
{
pkg_log.notice("Failed to remove partial installation ('%s') (error=%s)", other.m_install_path, fs::g_tls_error);
other.m_result = other.m_result == result::error ? result::error : result::aborted;
}
}
}

return error;
}

usz num_failures = 0;

for (package_reader& reader : readers)
{
reader.m_bufs.resize(std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size()));
reader.m_num_failures = 0;
reader.m_result = result::not_started;

atomic_t<usz> thread_indexer = 0;

named_thread_group workers("PKG Installer "sv, std::max<usz>(reader.m_bufs.size(), 1) - 1, [&]()
named_thread_group workers("PKG Installer "sv, std::max<u32>(::narrow<u32>(reader.m_bufs.size()), 1) - 1, [&]()
{
reader.extract_worker(thread_key{thread_indexer++});
});
Expand Down Expand Up @@ -1067,7 +1108,12 @@ bool package_reader::extract_data(std::deque<package_reader>& readers, std::dequ
bootable_paths.emplace_back(std::move(reader.m_bootable_file_path));
}

return num_failures == 0;
if (num_failures > 0)
{
error = package_error::other;
}

return error;
}

void package_reader::archive_seek(const s64 new_offset, const fs::seek_mode damode)
Expand Down
3 changes: 2 additions & 1 deletion rpcs3/Crypto/unpkg.h
Expand Up @@ -335,6 +335,7 @@ class package_reader
enum result
{
not_started,
started,
success,
aborted,
aborted_cleaned,
Expand All @@ -344,7 +345,7 @@ class package_reader

bool is_valid() const { return m_is_valid; }
package_error check_target_app_version() const;
static bool extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths);
static package_error extract_data(std::deque<package_reader>& readers, std::deque<std::string>& bootable_paths);
psf::registry get_psf() const { return m_psf; }
result get_result() const { return m_result; };

Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/system_utils.cpp
Expand Up @@ -92,8 +92,8 @@ namespace rpcs3::utils
named_thread worker("PKG Installer", [&]
{
std::deque<std::string> bootables;

return package_reader::extract_data(reader, bootables);
const package_error error = package_reader::extract_data(reader, bootables);
return error == package_error::no_error;
});

// Wait for the completion
Expand Down
18 changes: 6 additions & 12 deletions rpcs3/rpcs3qt/main_window.cpp
Expand Up @@ -944,26 +944,18 @@ void main_window::HandlePackageInstallation(QStringList file_paths)

std::deque<package_reader> readers;

for (usz i = 0; error == package_error::no_error && i < packages.size(); i++)
for (const compat::package_info& info : packages)
{
readers.emplace_back(sstr(packages[i].path));
error = readers.back().check_target_app_version();
readers.emplace_back(sstr(info.path));
}

std::deque<std::string> bootable_paths;

// Run PKG unpacking asynchronously
named_thread worker("PKG Installer", [&readers, &error, &bootable_paths]
{
if (error == package_error::no_error)
{
if (package_reader::extract_data(readers, bootable_paths))
{
return true;
}
}

return false;
error = package_reader::extract_data(readers, bootable_paths);
return error == package_error::no_error;
});

pdlg.show();
Expand Down Expand Up @@ -1021,6 +1013,7 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
break;
}
case package_reader::result::not_started:
case package_reader::result::started:
case package_reader::result::aborted_cleaned:
{
gui_log.notice("Aborted installation of %s (title_id=%s, title=%s, version=%s).", sstr(package.path), sstr(package.title_id), sstr(package.title), sstr(package.version));
Expand Down Expand Up @@ -1146,6 +1139,7 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
{
case package_reader::result::success:
case package_reader::result::not_started:
case package_reader::result::started:
case package_reader::result::aborted:
case package_reader::result::aborted_cleaned:
break;
Expand Down

0 comments on commit 8d7dca1

Please sign in to comment.