PresetUpdater: Add/fix logging, comments

This commit is contained in:
Vojtech Kral 2018-04-23 11:16:47 +02:00
parent e0421a3ba6
commit 33c0d1dca3
2 changed files with 102 additions and 22 deletions

View File

@ -1,9 +1,9 @@
#include "PresetUpdater.hpp"
#include <iostream> // XXX
#include <algorithm>
#include <thread>
#include <stack>
#include <ostream>
#include <stdexcept>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
@ -48,6 +48,7 @@ static const char *INDEX_FILENAME = "index.idx";
static const char *TMP_EXTENSION = ".download";
// A confirmation dialog listing configuration updates
struct UpdateNotification : wxDialog
{
// If this dialog gets any more complex, it should probably be factored out...
@ -123,6 +124,11 @@ struct Update
{}
std::string name() { return source.stem().string(); }
friend std::ostream& operator<<(std::ostream& os , const Update &update) {
os << "Update(" << update.source.string() << " -> " << update.target.string() << ')';
return os;
}
};
typedef std::vector<Update> Updates;
@ -171,6 +177,7 @@ PresetUpdater::priv::priv(int version_online_event) :
index_db = std::move(Index::load_db());
}
// Pull relevant preferences from AppConfig
void PresetUpdater::priv::set_download_prefs(AppConfig *app_config)
{
enabled_version_check = app_config->get("version_check") == "1";
@ -178,19 +185,29 @@ void PresetUpdater::priv::set_download_prefs(AppConfig *app_config)
enabled_config_update = app_config->get("preset_update") == "1";
}
// Downloads a file (http get operation). Cancels if the Updater is being destroyed.
bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &target_path) const
{
bool res = false;
fs::path tmp_path = target_path;
tmp_path += (boost::format(".%1%%2%") % get_current_pid() % TMP_EXTENSION).str();
std::cerr << "get_file(): " << url << " -> " << target_path << std::endl
<< "\ttmp_path: " << tmp_path << std::endl;
BOOST_LOG_TRIVIAL(info) << boost::format("Get: `%1%`\n\t-> `%2%`\n\tvia tmp path `%3%`")
% url
% target_path.string()
% tmp_path.string();
Http::get(url)
.on_progress([this](Http::Progress, bool &cancel) {
if (cancel) { cancel = true; }
})
.on_error([&](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%")
% url
% http_status
% body;
})
.on_complete([&](std::string body, unsigned http_status) {
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
file.write(body.c_str(), body.size());
@ -203,26 +220,39 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
return res;
}
// Remove leftover paritally downloaded files, if any.
void PresetUpdater::priv::prune_tmps() const
{
for (fs::directory_iterator it(cache_path); it != fs::directory_iterator(); ++it) {
if (it->path().extension() == TMP_EXTENSION) {
BOOST_LOG_TRIVIAL(debug) << "Cache prune: " << it->path().string();
fs::remove(it->path());
}
}
}
// Get Slic3rPE version available online, save in AppConfig.
void PresetUpdater::priv::sync_version() const
{
if (! enabled_version_check) { return; }
BOOST_LOG_TRIVIAL(info) << boost::format("Downloading Slic3rPE online version from: `%1%`") % version_check_url;
Http::get(version_check_url)
.size_limit(SLIC3R_VERSION_BODY_MAX)
.on_progress([this](Http::Progress, bool &cancel) {
cancel = this->cancel;
})
.on_error([&](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%")
% version_check_url
% http_status
% body;
})
.on_complete([&](std::string body, unsigned http_status) {
boost::trim(body);
BOOST_LOG_TRIVIAL(info) << boost::format("Got Slic3rPE online version: `%1%`. Sending to GUI thread...") % body;
wxCommandEvent* evt = new wxCommandEvent(version_online_event);
evt->SetString(body);
GUI::get_app()->QueueEvent(evt);
@ -230,9 +260,11 @@ void PresetUpdater::priv::sync_version() const
.perform_sync();
}
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
// Both are saved in cache.
void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors) const
{
std::cerr << "sync_config()" << std::endl;
BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache";
if (!enabled_config_update) { return; }
@ -240,54 +272,65 @@ void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors) con
for (const auto &index : index_db) {
if (cancel) { return; }
std::cerr << "Index: " << index.vendor() << std::endl;
const auto vendor_it = vendors.find(VendorProfile(index.vendor()));
if (vendor_it == vendors.end()) { continue; }
if (vendor_it == vendors.end()) {
BOOST_LOG_TRIVIAL(warning) << "No such vendor: " << index.vendor();
continue;
}
const VendorProfile &vendor = *vendor_it;
if (vendor.config_update_url.empty()) { continue; }
if (vendor.config_update_url.empty()) {
BOOST_LOG_TRIVIAL(info) << "Vendor has no config_update_url: " << vendor.name;
continue;
}
// Download a fresh index
BOOST_LOG_TRIVIAL(info) << "Downloading index for vendor: " << vendor.name;
const auto idx_url = vendor.config_update_url + "/" + INDEX_FILENAME;
const auto idx_path = cache_path / (vendor.id + ".idx");
if (! get_file(idx_url, idx_path)) { continue; }
if (cancel) { return; }
std::cerr << "Got a new index: " << idx_path << std::endl;
// Load the fresh index up
Index new_index;
new_index.load(idx_path);
// See if a there's a new version to download
const auto recommended_it = new_index.recommended();
if (recommended_it == new_index.end()) { continue; }
if (recommended_it == new_index.end()) {
BOOST_LOG_TRIVIAL(error) << "No recommended version for vendor: " << vendor.name << ", invalid index?";
continue;
}
const auto recommended = recommended_it->config_version;
std::cerr << "Current vendor version: " << vendor.config_version.to_string() << std::endl;
std::cerr << "Recommended version:\t" << recommended.to_string() << std::endl;
BOOST_LOG_TRIVIAL(debug) << boost::format("New index for vendor: %1%: current version: %2%, recommended version: %3%")
% vendor.name
% vendor.config_version.to_string()
% recommended.to_string();
if (vendor.config_version >= recommended) { continue; }
// Download a fresh bundle
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
const auto bundle_url = (boost::format("%1%/%2%.ini") % vendor.config_update_url % recommended.to_string()).str();
const auto bundle_path = cache_path / (vendor.id + ".ini");
if (! get_file(bundle_url, bundle_path)) { continue; }
if (cancel) { return; }
std::cerr << "Got a new bundle: " << bundle_path << std::endl;
}
}
// Install indicies from resources. Only installs those that are either missing or older than in resources.
void PresetUpdater::priv::check_install_indices() const
{
BOOST_LOG_TRIVIAL(info) << "Checking if indices need to be installed from resources...";
for (fs::directory_iterator it(rsrc_path); it != fs::directory_iterator(); ++it) {
const auto &path = it->path();
if (path.extension() == ".idx") {
const auto path_in_cache = cache_path / path.filename();
if (! fs::exists(path_in_cache)) {
BOOST_LOG_TRIVIAL(info) << "Install index from resources: " << path.filename();
fs::copy_file(path, path_in_cache, fs::copy_option::overwrite_if_exists);
} else {
Index idx_rsrc, idx_cache;
@ -295,6 +338,7 @@ void PresetUpdater::priv::check_install_indices() const
idx_cache.load(path_in_cache);
if (idx_cache.version() < idx_rsrc.version()) {
BOOST_LOG_TRIVIAL(info) << "Update index from resources: " << path.filename();
fs::copy_file(path, path_in_cache, fs::copy_option::overwrite_if_exists);
}
}
@ -302,14 +346,18 @@ void PresetUpdater::priv::check_install_indices() const
}
}
// Generates a list of bundle updates that are to be performed
Updates PresetUpdater::priv::config_update() const
{
Updates updates;
BOOST_LOG_TRIVIAL(info) << "Checking for cached configuration updates...";
for (const auto idx : index_db) {
const auto bundle_path = vendor_path / (idx.vendor() + ".ini");
if (! fs::exists(bundle_path)) {
BOOST_LOG_TRIVIAL(info) << "Bundle not present for index, skipping: " << idx.vendor();
continue;
}
@ -318,7 +366,7 @@ Updates PresetUpdater::priv::config_update() const
const auto ver_current = idx.find(vp.config_version);
if (ver_current == idx.end()) {
BOOST_LOG_TRIVIAL(warning) << boost::format("Preset bundle (`%1%`) version not found in index: %2%") % idx.vendor() % vp.config_version.to_string();
BOOST_LOG_TRIVIAL(error) << boost::format("Preset bundle (`%1%`) version not found in index: %2%") % idx.vendor() % vp.config_version.to_string();
continue;
}
@ -327,7 +375,13 @@ Updates PresetUpdater::priv::config_update() const
throw std::runtime_error((boost::format("Invalid index: `%1%`") % idx.vendor()).str());
}
BOOST_LOG_TRIVIAL(debug) << boost::format("Vendor: %1%, version installed: %2%, version cached: %3%")
% vp.name
% recommended->config_version.to_string()
% ver_current->config_version.to_string();
if (! ver_current->is_current_slic3r_supported()) {
BOOST_LOG_TRIVIAL(warning) << "Current Slic3r incompatible with installed bundle: " << bundle_path.string();
// TODO: Downgrade situation
@ -336,6 +390,7 @@ Updates PresetUpdater::priv::config_update() const
auto path_in_cache = cache_path / (idx.vendor() + ".ini");
if (! fs::exists(path_in_cache)) {
BOOST_LOG_TRIVIAL(warning) << "Index indicates update, but new bundle not found in cache: " << path_in_cache.string();
continue;
}
@ -351,11 +406,16 @@ Updates PresetUpdater::priv::config_update() const
void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) const
{
BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.size();
if (snapshot) {
BOOST_LOG_TRIVIAL(info) << "Taking a snapshot...";
SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE);
}
for (const auto &update : updates) {
BOOST_LOG_TRIVIAL(info) << '\t' << update;
fs::copy_file(update.source, update.target, fs::copy_option::overwrite_if_exists);
PresetBundle bundle;
@ -382,6 +442,8 @@ PresetUpdater::PresetUpdater(int version_online_event) :
PresetUpdater::~PresetUpdater()
{
if (p && p->thread.joinable()) {
// This will stop transfers being done by the thread, if any.
// Cancelling takes some time, but should complete soon enough.
p->cancel = true;
p->thread.join();
}
@ -406,8 +468,12 @@ void PresetUpdater::sync(PresetBundle *preset_bundle)
void PresetUpdater::slic3r_update_notify()
{
if (! p->enabled_version_check || p->had_config_update) { return; }
// ^ We don't want to bother the user with updates multiple times, put off till next time.
if (! p->enabled_version_check) { return; }
if (p->had_config_update) {
BOOST_LOG_TRIVIAL(info) << "New Slic3r version available, but there was a configuration update, notification won't be displayed";
return;
}
auto* app_config = GUI::get_app_config();
const auto ver_slic3r = Semver::parse(SLIC3R_VERSION);
@ -438,6 +504,8 @@ void PresetUpdater::config_update() const
auto updates = p->config_update();
if (updates.size() > 0) {
BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. Asking for confirmation ...") % updates.size();
const auto msg = _(L("Configuration update is available. Would you like to install it?"));
auto ext_msg = _(L(
@ -457,20 +525,25 @@ void PresetUpdater::config_update() const
wxMessageDialog dlg(NULL, msg, _(L("Configuration update")), wxYES_NO|wxCENTRE);
dlg.SetExtendedMessage(ext_msg);
const auto res = dlg.ShowModal();
std::cerr << "After modal" << std::endl;
if (res == wxID_YES) {
// User gave clearance, updates are go
BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update";
p->perform_updates(std::move(updates));
} else {
BOOST_LOG_TRIVIAL(info) << "User refused the update";
}
p->had_config_update = true;
} else {
BOOST_LOG_TRIVIAL(info) << "No configuration updates available.";
}
}
void PresetUpdater::install_bundles_rsrc(std::vector<std::string> &&bundles, bool snapshot)
void PresetUpdater::install_bundles_rsrc(std::vector<std::string> bundles, bool snapshot)
{
Updates updates;
BOOST_LOG_TRIVIAL(info) << boost::format("Installing %1% bundles from resources ...") % bundles.size();
for (const auto &bundle : bundles) {
auto path_in_rsrc = p->rsrc_path / bundle;
auto path_in_vendors = p->vendor_path / bundle;

View File

@ -20,10 +20,17 @@ public:
PresetUpdater &operator=(const PresetUpdater &) = delete;
~PresetUpdater();
// If either version check or config updating is enabled, get the appropriate data in the background and cache it.
void sync(PresetBundle *preset_bundle);
// If version check is enabled, check if chaced online slic3r version is newer, notify if so.
void slic3r_update_notify();
// If updating is enabled, check if updates are available in cache, if so, ask about installation.
void config_update() const;
void install_bundles_rsrc(std::vector<std::string> &&bundles, bool snapshot = true);
// "Update" a list of bundles from resources (behaves like an online update).
void install_bundles_rsrc(std::vector<std::string> bundles, bool snapshot = true);
private:
struct priv;
std::unique_ptr<priv> p;