Compare commits

..

1 Commits

Author SHA1 Message Date
peachismomo
013a9452af fix: prevent Windows OTA vendor profile update race 2026-07-28 19:48:10 +08:00
3 changed files with 47 additions and 89 deletions

View File

@@ -32,13 +32,15 @@ static void append_and_translate(ExPolygons &dst, const ExPolygons &src, const P
for (; dst_idx < dst.size(); ++dst_idx) for (; dst_idx < dst.size(); ++dst_idx)
dst[dst_idx].translate(instance_shift); dst[dst_idx].translate(instance_shift);
} }
// Orca: Translate the brim area into print coordinates and store it per instance. // BBS: generate brim area by objs
static void append_and_translate(const ExPolygons& src, const PrintInstance& instance, static void append_and_translate(ExPolygons& dst, const ExPolygons& src,
size_t instance_idx, std::map<ObjectInstanceID, ExPolygons>& brimAreaMap) { const PrintInstance& instance, size_t instance_idx, std::map<ObjectInstanceID, ExPolygons>& brimAreaMap) {
ExPolygons srcShifted = src; ExPolygons srcShifted = src;
Point instance_shift = instance.shift_without_plate_offset(); Point instance_shift = instance.shift_without_plate_offset();
for (ExPolygon& expoly : srcShifted) for (size_t src_idx = 0; src_idx < srcShifted.size(); ++src_idx)
expoly.translate(instance_shift); srcShifted[src_idx].translate(instance_shift);
srcShifted = diff_ex(srcShifted, dst);
//expolygons_append(dst, temp2);
expolygons_append(brimAreaMap[{ instance.print_object->id(), instance_idx }], std::move(srcShifted)); expolygons_append(brimAreaMap[{ instance.print_object->id(), instance_idx }], std::move(srcShifted));
} }
@@ -570,7 +572,7 @@ static ExPolygons outer_inner_brim_area(const Print& print,
for (size_t instance_idx = 0; instance_idx < object->instances().size(); ++instance_idx) { for (size_t instance_idx = 0; instance_idx < object->instances().size(); ++instance_idx) {
const PrintInstance& instance = object->instances()[instance_idx]; const PrintInstance& instance = object->instances()[instance_idx];
if (!brim_area_object.empty()) if (!brim_area_object.empty())
append_and_translate(brim_area_object, instance, instance_idx, brimAreaMap); append_and_translate(brim_area, brim_area_object, instance, instance_idx, brimAreaMap);
append_and_translate(no_brim_area, no_brim_area_object, instance); append_and_translate(no_brim_area, no_brim_area_object, instance);
append_and_translate(holes, holes_object, instance); append_and_translate(holes, holes_object, instance);
append_and_translate(objectIslands, objectIsland, instance); append_and_translate(objectIslands, objectIsland, instance);
@@ -873,14 +875,6 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
ExPolygons islands_area_ex = outer_inner_brim_area(print, ExPolygons islands_area_ex = outer_inner_brim_area(print,
float(flow.scaled_spacing()), brimAreaMap, objPrintVec, printExtruders); float(flow.scaled_spacing()), brimAreaMap, objPrintVec, printExtruders);
if (!print.config().combine_brims) {
ExPolygons claimed_area;
for (auto& [_, areas] : brimAreaMap) {
areas = diff_ex(areas, claimed_area);
expolygons_append(claimed_area, areas);
}
}
// BBS: Find boundingbox of the first layer // BBS: Find boundingbox of the first layer
for (const ObjectID printObjID : print.print_object_ids()) { for (const ObjectID printObjID : print.print_object_ids()) {
BoundingBox bbx; BoundingBox bbx;

View File

@@ -1,12 +1,14 @@
#include "PresetUpdater.hpp" #include "PresetUpdater.hpp"
#include <algorithm> #include <algorithm>
#include <boost/filesystem/directory.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/nowide/fstream.hpp> #include <boost/nowide/fstream.hpp>
#include <functional> #include <functional>
#include <atomic> #include <atomic>
#include <mutex>
#include <set> #include <set>
#include <string>
#include <thread> #include <thread>
#include <unordered_map> #include <unordered_map>
#include <ostream> #include <ostream>
@@ -19,6 +21,7 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <vector>
#include <wx/app.h> #include <wx/app.h>
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
@@ -204,7 +207,6 @@ struct PresetUpdater::priv
// Per-vendor update checking // Per-vendor update checking
std::set<std::string> checked_vendors; std::set<std::string> checked_vendors;
std::mutex vendor_check_mutex;
std::vector<std::thread> vendor_check_threads; std::vector<std::thread> vendor_check_threads;
std::atomic<bool> vendor_check_cancel{false}; std::atomic<bool> vendor_check_cancel{false};
@@ -221,10 +223,10 @@ struct PresetUpdater::priv
priv(); priv();
void set_download_prefs(AppConfig *app_config); void set_download_prefs(AppConfig *app_config);
bool get_file(const std::string &url, const fs::path &target_path) const; bool get_file(const std::string &url, const fs::path &target_path) const;
//BBS: refine preset update logic //BBS: refine preset update logic
bool extract_file(const fs::path &source_path, const fs::path &dest_path = {}); bool extract_file(const fs::path &source_path, const fs::path &dest_path = {});
void prune_tmps() const; void prune_tmp(const std::string& vendor_id) const;
void sync_version() const; void sync_version() const;
void parse_version_string(const std::string& body) const; void parse_version_string(const std::string& body) const;
void sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch = false, std::string current_version="", std::string changelog_file=""); void sync_resources(std::string http_url, std::map<std::string, Resource> &resources, bool check_patch = false, std::string current_version="", std::string changelog_file="");
@@ -371,14 +373,14 @@ bool PresetUpdater::priv::extract_file(const fs::path &source_path, const fs::pa
return true; return true;
} }
// Remove leftover paritally downloaded files, if any. // Remove a leftover partial archive for the vendor about to be synchronized.
void PresetUpdater::priv::prune_tmps() const void PresetUpdater::priv::prune_tmp(const std::string& vendor_id) const
{ {
for (auto &dir_entry : boost::filesystem::directory_iterator(cache_path)) boost::system::error_code ec;
if (is_plain_file(dir_entry) && dir_entry.path().extension() == TMP_EXTENSION) { const fs::path tmp_path = cache_path / (vendor_id + TMP_EXTENSION);
BOOST_LOG_TRIVIAL(debug) << "[Orca Updater]remove old cached files: " << dir_entry.path().string(); fs::remove(tmp_path, ec);
fs::remove(dir_entry.path()); if (ec)
} BOOST_LOG_TRIVIAL(warning) << "[Orca Updater]failed to remove " << tmp_path.string() << ": " << ec.message();
} }
//BBS: refine the Preset Updater logic //BBS: refine the Preset Updater logic
@@ -1060,10 +1062,9 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
Semver resource_ver = get_version_from_json(file_path); Semver resource_ver = get_version_from_json(file_path);
Semver vendor_ver = get_version_from_json(path_in_vendor.string()); Semver vendor_ver = get_version_from_json(path_in_vendor.string());
bool version_match = ((resource_ver.maj() == vendor_ver.maj()) && (resource_ver.min() == vendor_ver.min())); if (vendor_ver < resource_ver) {
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:found vendor " << vendor_name << " newer version "
if (!version_match || (vendor_ver < resource_ver)) { << resource_ver.to_string() << " from resource, old version " << vendor_ver.to_string();
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:found vendor "<<vendor_name<<" newer version "<<resource_ver.to_string() <<" from resource, old version "<<vendor_ver.to_string();
bundles.insert(vendor_name); bundles.insert(vendor_name);
} }
} }
@@ -1305,49 +1306,29 @@ PresetUpdater::~PresetUpdater()
//BBS: change directories by design //BBS: change directories by design
//BBS: refine the preset updater logic //BBS: refine the preset updater logic
void PresetUpdater::sync(std::string http_url, std::string language, std::string plugin_version, PresetBundle *preset_bundle) void PresetUpdater::sync(std::string http_url, std::string language, std::string plugin_version, PresetBundle * /*preset_bundle*/)
{ {
//p->set_download_prefs(GUI::wxGetApp().app_config); //p->set_download_prefs(GUI::wxGetApp().app_config);
if (!p->enabled_version_check && !p->enabled_config_update) { return; } if (!p->enabled_version_check && !p->enabled_config_update) { return; }
// Copy the whole vendors data for use in the background thread p->thread = std::thread([this, http_url, language, plugin_version]() {
// Unfortunatelly as of C++11, it needs to be copied again try {
// into the closure (but perhaps the compiler can elide this). this->p->sync_version();
VendorMap vendors = preset_bundle ? preset_bundle->vendors : VendorMap{}; if (p->cancel)
return;
// Determine active vendor before entering the thread // Vendor profile updates are triggered by check_vendor_update()
std::string active_vendor; // after the startup printer preset has been restored.
if (preset_bundle) { this->p->sync_plugins(http_url, plugin_version);
const Preset& printer = preset_bundle->printers.get_edited_preset(); this->p->sync_printer_config(http_url);
if (printer.vendor) //if (p->cancel)
active_vendor = printer.vendor->id; // return;
} //remove the tooltip currently
//this->p->sync_tooltip(http_url, language);
p->thread = std::thread([this, vendors, active_vendor, http_url, language, plugin_version]() { } catch (const std::exception &e) {
this->p->prune_tmps(); BOOST_LOG_TRIVIAL(error) << "[Orca Updater] background sync failed: " << e.what();
if (p->cancel) } catch (...) {
return; BOOST_LOG_TRIVIAL(error) << "[Orca Updater] background sync failed with an unknown exception";
this->p->sync_version(); }
if (p->cancel)
return;
// Per-vendor config check for the active vendor at startup
if (!active_vendor.empty() && !vendors.empty()) {
this->p->sync_vendor_config(active_vendor);
if (p->cancel)
return;
{
std::lock_guard<std::mutex> lock(this->p->vendor_check_mutex);
this->p->checked_vendors.insert(active_vendor);
}
}
if (p->cancel)
return;
this->p->sync_plugins(http_url, plugin_version);
this->p->sync_printer_config(http_url);
//if (p->cancel)
// return;
//remove the tooltip currently
//this->p->sync_tooltip(http_url, language);
}); });
} }
@@ -1356,16 +1337,17 @@ void PresetUpdater::check_vendor_update(const std::string& vendor_id)
if (!p->enabled_config_update) return; if (!p->enabled_config_update) return;
if (vendor_id.empty()) return; if (vendor_id.empty()) return;
std::lock_guard<std::mutex> lock(p->vendor_check_mutex);
if (!p->checked_vendors.insert(vendor_id).second) if (!p->checked_vendors.insert(vendor_id).second)
return; return;
p->vendor_check_threads.emplace_back([this, vendor_id]() { p->vendor_check_threads.emplace_back([this, vendor_id]() {
try { try {
this->p->prune_tmp(vendor_id);
this->p->sync_vendor_config(vendor_id); this->p->sync_vendor_config(vendor_id);
} catch (const std::exception& e) { } catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "[Orca Updater] vendor update failed for " << vendor_id << ": " << e.what(); BOOST_LOG_TRIVIAL(error) << "[Orca Updater] vendor update failed for " << vendor_id << ": " << e.what();
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "[Orca Updater] vendor update failed for " << vendor_id << " with an unknown exception";
} }
}); });
} }

View File

@@ -153,24 +153,6 @@ TEST_CASE("Object brims are generated per instance", "[SkirtBrim]")
} }
} }
TEST_CASE("Uncombined neighboring brims precede their respective objects", "[SkirtBrim]")
{
Print print;
Model model;
place_two_cubes_apart(0, {
{ "skirt_loops", 0 },
{ "brim_type", "outer_only" },
{ "brim_width", 5 },
{ "combine_brims", 0 },
}, print, model);
print.process();
REQUIRE(print.skirt_brim_groups().size() == 1);
REQUIRE(print.skirt_brim_groups().front().brims.size() == 2);
CHECK(role_sequence(gcode(print), { "brim", "perimeter" }) ==
std::vector<std::string>{ "brim", "perimeter", "brim", "perimeter" });
}
TEST_CASE("Combine brims merges neighboring object instances", "[SkirtBrim]") TEST_CASE("Combine brims merges neighboring object instances", "[SkirtBrim]")
{ {
Print print; Print print;