Improve error handling.

Do not cancel the entire process when an error occurs. Instead, return a list of failed contents.
This commit is contained in:
zhupengfei
2020-05-16 15:13:52 +08:00
parent 4391845185
commit 1c28fff725
4 changed files with 38 additions and 12 deletions
+12
View File
@@ -22,6 +22,10 @@ bool InnerFAT::IsGood() const {
} }
bool InnerFAT::ExtractDirectory(const std::string& path, std::size_t index) const { bool InnerFAT::ExtractDirectory(const std::string& path, std::size_t index) const {
if (index >= directory_entry_table.size()) {
LOG_ERROR(Core, "Index out of bound {}", index);
return false;
}
auto entry = directory_entry_table[index]; auto entry = directory_entry_table[index];
std::array<char, 17> name_data = {}; // Append a null terminator std::array<char, 17> name_data = {}; // Append a null terminator
@@ -152,6 +156,10 @@ bool SDSavegame::ExtractFile(const std::string& path, std::size_t index) const {
return false; return false;
} }
if (index >= file_entry_table.size()) {
LOG_ERROR(Core, "Index out of bound {}", index);
return false;
}
auto entry = file_entry_table[index]; auto entry = file_entry_table[index];
std::array<char, 17> name_data = {}; // Append a null terminator std::array<char, 17> name_data = {}; // Append a null terminator
@@ -305,6 +313,10 @@ bool SDExtdata::ExtractFile(const std::string& path, std::size_t index) const {
/// Maximum amount of device files a device directory can hold. /// Maximum amount of device files a device directory can hold.
constexpr u32 DeviceDirCapacity = 126; constexpr u32 DeviceDirCapacity = 126;
if (index >= file_entry_table.size()) {
LOG_ERROR(Core, "Index out of bound {}", index);
return false;
}
auto entry = file_entry_table[index]; auto entry = file_entry_table[index];
std::array<char, 17> name_data = {}; // Append a null terminator std::array<char, 17> name_data = {}; // Append a null terminator
+5 -2
View File
@@ -21,8 +21,7 @@ void ImportJob::run() {
if (!importer.ImportContent(content, callback)) { if (!importer.ImportContent(content, callback)) {
importer.DeleteContent(content); importer.DeleteContent(content);
if (!cancelled) { if (!cancelled) {
emit ErrorOccured(content); failed_contents.emplace_back(content);
return;
} }
} }
count++; count++;
@@ -39,3 +38,7 @@ void ImportJob::Cancel() {
cancelled.store(true); cancelled.store(true);
importer.AbortImporting(); importer.AbortImporting();
} }
std::vector<Core::ContentSpecifier> ImportJob::GetFailedContents() const {
return failed_contents;
}
+3 -1
View File
@@ -19,6 +19,8 @@ public:
void run() override; void run() override;
void Cancel(); void Cancel();
std::vector<Core::ContentSpecifier> GetFailedContents() const;
signals: signals:
/** /**
* Called when progress is updated on the current content. * Called when progress is updated on the current content.
@@ -32,12 +34,12 @@ signals:
void NextContent(u64 size_imported, u64 count, Core::ContentSpecifier next_content); void NextContent(u64 size_imported, u64 count, Core::ContentSpecifier next_content);
void Completed(); void Completed();
void ErrorOccured(Core::ContentSpecifier current_content);
private: private:
std::atomic_bool cancelled{false}; std::atomic_bool cancelled{false};
Core::SDMCImporter& importer; Core::SDMCImporter& importer;
std::vector<Core::ContentSpecifier> contents; std::vector<Core::ContentSpecifier> contents;
std::vector<Core::ContentSpecifier> failed_contents;
}; };
Q_DECLARE_METATYPE(Core::ContentSpecifier) Q_DECLARE_METATYPE(Core::ContentSpecifier)
+18 -9
View File
@@ -495,16 +495,25 @@ void ImportDialog::StartImporting() {
.arg(ReadableByteSize(current_size_imported)) .arg(ReadableByteSize(current_size_imported))
.arg(ReadableByteSize(current_content.maximum_size))); .arg(ReadableByteSize(current_content.maximum_size)));
}); });
connect(job, &ImportJob::ErrorOccured, this, connect(job, &ImportJob::Completed, this, [this, dialog, job] {
[this, dialog](Core::ContentSpecifier current_content) {
QMessageBox::critical(this, tr("Error"),
tr("Failed to import content %1 (%2)!")
.arg(GetContentName(current_content))
.arg(GetContentTypeName(current_content.type)));
dialog->hide();
});
connect(job, &ImportJob::Completed, this, [this, dialog] {
dialog->setValue(dialog->maximum()); dialog->setValue(dialog->maximum());
const auto failed_contents = job->GetFailedContents();
if (failed_contents.empty()) {
QMessageBox::information(this, tr("Import Completed"),
tr("Successfully imported the selected contents."));
} else {
QString list_content;
for (const auto& content : failed_contents) {
list_content.append(QStringLiteral("<li>%1 (%2)</li>")
.arg(GetContentName(content))
.arg(GetContentTypeName(content.type)));
}
QMessageBox::critical(
this, tr("Import Failed"),
tr("The following contents couldn't be imported:<ul>%1</ul>").arg(list_content));
}
RelistContent(); RelistContent();
}); });
connect(dialog, &QProgressDialog::canceled, this, [this, dialog, job] { connect(dialog, &QProgressDialog::canceled, this, [this, dialog, job] {