Remove CachedPrinterModel/VendorProfile/Preset mirror structs from VendorCache

This commit is contained in:
ExPikaPaka
2026-06-18 08:34:50 +02:00
parent 517fa29d6f
commit 493597f132
2 changed files with 56 additions and 183 deletions

View File

@@ -8,7 +8,6 @@
#include <boost/crc.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include "PrintConfig.hpp"
@@ -2227,8 +2226,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
// Then load remaining vendors from per-vendor caches.
auto try_vendor_cache = [&](const std::string& vendor_name) -> bool {
const std::string json_path = (dir / (vendor_name + ".json")).string();
const Semver ver = get_version_from_json(json_path);
const std::string ver_str = ver.valid() ? ver.to_string() : "";
const std::string ver_str = get_vendor_cache_key(json_path);
vendor_json_versions[vendor_name] = ver_str;
VendorCache vc;
@@ -2277,6 +2275,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
const auto json_load_t0 = std::chrono::steady_clock::now();
PresetsConfigSubstitutions substitutions;
std::string errors_cummulative;
std::set<std::string> errored_vendors; // vendors whose JSON parse failed — skip their cache save
// first = true means no vendor has been loaded yet (from cache or JSON).
// false = at least one vendor was applied from the per-vendor cache above.
bool first = validation_mode || cache_miss_vendors.size() == vendor_json_versions.size();
@@ -2320,6 +2319,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
throw err;
errors_cummulative += err.what();
errors_cummulative += "\n";
errored_vendors.insert(orca_lib_vendor);
}
}
@@ -2356,6 +2356,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
throw std::runtime_error(parallel_errors[i]);
errors_cummulative += parallel_errors[i];
errors_cummulative += "\n";
errored_vendors.insert(other_vendors[i]);
continue;
}
if (!parallel_bundles[i])
@@ -2390,10 +2391,14 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
BOOST_LOG_TRIVIAL(info) << "PresetBundle: system presets loaded from JSON in " << json_ms << " ms";
}
// Save per-vendor binary caches for vendors that had to be parsed from JSON.
if (!validation_mode && !cache_miss_vendors.empty() && errors_cummulative.empty()) {
// Save per-vendor binary caches for vendors that parsed successfully.
// Vendors whose JSON produced a parse error are skipped individually so one
// bad vendor does not block caching of all others.
if (!validation_mode && !cache_miss_vendors.empty()) {
const auto save_t0 = std::chrono::steady_clock::now();
for (const auto& vendor_name : cache_miss_vendors) {
if (errored_vendors.count(vendor_name))
continue;
const bool is_orca_lib = (vendor_name == ORCA_FILAMENT_LIBRARY);
const std::string ver_str = vendor_json_versions.count(vendor_name)
? vendor_json_versions.at(vendor_name) : "";
@@ -5697,6 +5702,19 @@ struct CacheFileHeader {
#pragma pack(pop)
static_assert(sizeof(CacheFileHeader) == 20, "CacheFileHeader must be 20 bytes");
// Returns the string used as vendor_json_version in the cache validity check.
// For versioned vendors this is the Semver string from the JSON.
// For version-less vendors we use the file mtime so any edit invalidates the cache.
static std::string get_vendor_cache_key(const std::string& json_path)
{
const Semver ver = get_version_from_json(json_path);
if (ver.valid())
return ver.to_string();
boost::system::error_code ec;
const std::time_t mtime = boost::filesystem::last_write_time(json_path, ec);
return ec ? std::string{} : ("mtime:" + std::to_string(mtime));
}
template<class T>
static void save_blob(const std::string& path, const T& obj)
{
@@ -5790,7 +5808,7 @@ void PresetBundle::VendorCache::capture(const PresetBundle& bundle,
bool capture_filament_maps)
{
cache_version = CACHE_VERSION;
config_options_count = print_config_def.options.size();
config_options_count = static_cast<uint32_t>(print_config_def.options.size());
vendor_json_version = vendor_json_ver;
print_presets.clear();
@@ -5801,66 +5819,17 @@ void PresetBundle::VendorCache::capture(const PresetBundle& bundle,
config_maps.clear();
filament_id_maps.clear();
// Vendor profile
// Vendor profile — copy directly; VendorProfile now carries its own serialize()
auto vp_it = bundle.vendors.find(vendor_id);
if (vp_it != bundle.vendors.end()) {
const VendorProfile& vp = vp_it->second;
profile.id = vp.id;
profile.name = vp.name;
profile.config_version = vp.config_version.valid() ? vp.config_version.to_string() : "";
profile.config_update_url = vp.config_update_url;
profile.changelog_url = vp.changelog_url;
profile.models.clear();
for (const auto& model : vp.models) {
CachedPrinterModel cm;
cm.id = model.id;
cm.name = model.name;
cm.model_id = model.model_id;
cm.family = model.family;
cm.technology = static_cast<int>(model.technology);
for (const auto& v : model.variants)
cm.variants.push_back(v.name);
cm.default_materials = model.default_materials;
cm.not_support_bed_types = model.not_support_bed_types;
cm.bed_model = model.bed_model;
cm.bed_texture = model.bed_texture;
cm.image_bed_type = model.image_bed_type;
cm.bottom_texture_end_name = model.bottom_texture_end_name;
cm.use_double_extruder_default_texture = model.use_double_extruder_default_texture;
cm.bottom_texture_rect = model.bottom_texture_rect;
cm.middle_texture_rect = model.middle_texture_rect;
cm.hotend_model = model.hotend_model;
profile.models.push_back(std::move(cm));
}
profile.default_filaments.clear();
for (const auto& f : vp.default_filaments)
profile.default_filaments.push_back(f);
profile.default_sla_materials.clear();
for (const auto& m : vp.default_sla_materials)
profile.default_sla_materials.push_back(m);
}
if (vp_it != bundle.vendors.end())
profile = vp_it->second;
// Presets — only those belonging to this vendor
auto capture_col = [&](const PresetCollection& coll, std::vector<CachedPreset>& out) {
// Presets — only those belonging to this vendor; Preset now carries its own serialize()
auto capture_col = [&](const PresetCollection& coll, std::vector<Preset>& out) {
for (const Preset& p : coll()) {
if (!p.is_system) continue;
if (p.vendor == nullptr || p.vendor->id != vendor_id) continue;
CachedPreset cp;
cp.type = static_cast<int>(p.type);
cp.name = p.name;
cp.alias = p.alias;
cp.file = p.file;
cp.version = p.version.valid() ? p.version.to_string() : "";
cp.vendor_id = vendor_id;
cp.filament_id = p.filament_id;
cp.setting_id = p.setting_id;
cp.description = p.description;
cp.renamed_from = p.renamed_from;
cp.is_system = p.is_system;
cp.is_visible = p.is_visible;
cp.m_from_orca_filament_lib = p.m_from_orca_filament_lib;
cp.config = p.config;
out.push_back(std::move(cp));
out.push_back(p); // vendor pointer not serialized; apply() reconstructs it
}
};
capture_col(bundle.prints, print_presets);
@@ -5878,55 +5847,23 @@ void PresetBundle::VendorCache::capture(const PresetBundle& bundle,
void PresetBundle::VendorCache::apply(PresetBundle& bundle) const
{
// Restore vendor profile (additive — does not reset the bundle)
bundle.vendors.emplace(profile.id, profile);
// Restore presets; vendor pointer is reconstructed from profile.id since all
// presets in this cache belong to the same vendor.
const VendorProfile* vp = nullptr;
{
VendorProfile vp(profile.id);
vp.name = profile.name;
vp.config_update_url = profile.config_update_url;
vp.changelog_url = profile.changelog_url;
if (!profile.config_version.empty()) {
auto v = Semver::parse(profile.config_version);
if (v) vp.config_version = *v;
}
for (const auto& cm : profile.models) {
VendorProfile::PrinterModel model;
model.id = cm.id;
model.name = cm.name;
model.model_id = cm.model_id;
model.family = cm.family;
model.technology = static_cast<PrinterTechnology>(cm.technology);
for (const auto& v : cm.variants)
model.variants.emplace_back(v);
model.default_materials = cm.default_materials;
model.not_support_bed_types = cm.not_support_bed_types;
model.bed_model = cm.bed_model;
model.bed_texture = cm.bed_texture;
model.image_bed_type = cm.image_bed_type;
model.bottom_texture_end_name = cm.bottom_texture_end_name;
model.use_double_extruder_default_texture = cm.use_double_extruder_default_texture;
model.bottom_texture_rect = cm.bottom_texture_rect;
model.middle_texture_rect = cm.middle_texture_rect;
model.hotend_model = cm.hotend_model;
vp.models.push_back(std::move(model));
}
for (const auto& f : profile.default_filaments)
vp.default_filaments.insert(f);
for (const auto& m : profile.default_sla_materials)
vp.default_sla_materials.insert(m);
bundle.vendors.emplace(profile.id, std::move(vp));
auto it = bundle.vendors.find(profile.id);
if (it != bundle.vendors.end())
vp = &it->second;
}
// Restore presets
auto apply_col = [&](const std::vector<CachedPreset>& cached,
PresetCollection& coll,
bool is_filaments) {
for (const auto& cp : cached) {
Semver version;
if (!cp.version.empty()) {
auto v = Semver::parse(cp.version);
if (v) version = *v;
}
auto apply_col = [&](const std::vector<Preset>& cached,
PresetCollection& coll,
bool is_filaments) {
for (const Preset& cp : cached) {
DynamicPrintConfig config = cp.config;
Preset& p = coll.load_preset(cp.file, cp.name, std::move(config), /*select=*/false, version);
Preset& p = coll.load_preset(cp.file, cp.name, std::move(config), /*select=*/false, cp.version);
p.is_system = true;
p.is_visible = cp.is_visible;
p.alias = cp.alias;
@@ -5935,11 +5872,7 @@ void PresetBundle::VendorCache::apply(PresetBundle& bundle) const
p.setting_id = cp.setting_id;
p.description = cp.description;
p.m_from_orca_filament_lib = cp.m_from_orca_filament_lib;
if (!cp.vendor_id.empty()) {
auto it = bundle.vendors.find(cp.vendor_id);
if (it != bundle.vendors.end())
p.vendor = &it->second;
}
p.vendor = vp;
if (is_filaments)
coll.set_printer_hold_alias(p.alias, p);
}

View File

@@ -13,12 +13,6 @@
#include <boost/filesystem/path.hpp>
#include <unordered_set>
#include <cereal/archives/binary.hpp>
#include <cereal/cereal.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#define DEFAULT_USER_FOLDER_NAME "default"
#define BUNDLE_STRUCTURE_JSON_NAME "bundle_structure.json"
@@ -162,77 +156,23 @@ public:
// One file per vendor:
// Bundled (CI-generated): resources/profiles/<vendor_id>.cache
// User (runtime): data_dir/system/<vendor_id>.cache
struct CachedPrinterModel {
std::string id, name, model_id, family;
int technology = 0;
std::vector<std::string> variants; // nozzle diameter strings
std::vector<std::string> default_materials;
std::vector<std::string> not_support_bed_types;
std::string bed_model, bed_texture, image_bed_type;
std::string bottom_texture_end_name, use_double_extruder_default_texture;
std::string bottom_texture_rect, middle_texture_rect, hotend_model;
template<class Archive>
void serialize(Archive& ar)
{
ar(id, name, model_id, family, technology, variants, default_materials,
not_support_bed_types, bed_model, bed_texture, image_bed_type,
bottom_texture_end_name, use_double_extruder_default_texture,
bottom_texture_rect, middle_texture_rect, hotend_model);
}
};
struct CachedVendorProfile {
std::string id, name, config_version, config_update_url, changelog_url;
std::vector<CachedPrinterModel> models;
std::vector<std::string> default_filaments;
std::vector<std::string> default_sla_materials;
template<class Archive>
void serialize(Archive& ar)
{
ar(id, name, config_version, config_update_url, changelog_url,
models, default_filaments, default_sla_materials);
}
};
struct CachedPreset {
int type = 0;
std::string name, alias, file, version;
std::string vendor_id;
std::string filament_id, setting_id, description;
std::string base_id, user_id, sync_info;
long long updated_time = 0;
std::vector<std::string> renamed_from;
bool is_system = true;
bool is_visible = true;
bool m_from_orca_filament_lib = false;
DynamicPrintConfig config;
template<class Archive>
void serialize(Archive& ar)
{
ar(type, name, alias, file, version, vendor_id, filament_id, setting_id,
description, base_id, user_id, sync_info, updated_time, renamed_from,
is_system, is_visible, m_from_orca_filament_lib, config);
}
};
// VendorProfile, VendorProfile::PrinterModel, and Preset carry their own
// cereal serialize() methods so no mirror structs are needed.
struct VendorCache {
static constexpr uint32_t CACHE_MAGIC = 0x4F52435A; // "ORCZ"
static constexpr uint32_t CACHE_VERSION = 3;
static constexpr uint32_t CACHE_VERSION = 4; // bumped: Preset/VendorProfile serialize directly
uint32_t cache_version = CACHE_VERSION;
size_t config_options_count = 0;
std::string vendor_json_version; // Semver string, or "" for version-less vendors
uint32_t config_options_count = 0; // fixed-width: size_t varies between 32/64-bit builds
std::string vendor_json_version; // Semver string, or mtime:<timestamp> for version-less vendors
CachedVendorProfile profile;
std::vector<CachedPreset> print_presets;
std::vector<CachedPreset> filament_presets;
std::vector<CachedPreset> printer_presets;
std::vector<CachedPreset> sla_print_presets;
std::vector<CachedPreset> sla_material_presets;
VendorProfile profile;
std::vector<Preset> print_presets;
std::vector<Preset> filament_presets;
std::vector<Preset> printer_presets;
std::vector<Preset> sla_print_presets;
std::vector<Preset> sla_material_presets;
// Only populated for the ORCA_FILAMENT_LIBRARY vendor.
std::map<std::string, DynamicPrintConfig> config_maps;
@@ -251,7 +191,7 @@ public:
bool is_valid(const std::string& current_vendor_json_version) const
{
return cache_version == CACHE_VERSION
&& config_options_count == print_config_def.options.size()
&& config_options_count == static_cast<uint32_t>(print_config_def.options.size())
&& vendor_json_version == current_vendor_json_version;
}