From: James Turner Date: Thu, 12 Mar 2015 14:27:29 +0000 (+0000) Subject: Catalog install feedback. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=596591bb641cb1747dd631ea79dc7163eb876469;p=simgear.git Catalog install feedback. - also support removing (uninstalling) a catalog and all installs relating to it. --- diff --git a/simgear/package/Catalog.cxx b/simgear/package/Catalog.cxx index b1a31b56..1150969f 100644 --- a/simgear/package/Catalog.cxx +++ b/simgear/package/Catalog.cxx @@ -45,6 +45,8 @@ public: HTTP::Request(aUrl), m_owner(aOwner) { + // refreshing + m_owner->changeStatus(Delegate::FAIL_IN_PROGRESS); } protected: @@ -90,7 +92,7 @@ protected: time(&m_owner->m_retrievedTime); m_owner->writeTimestamp(); - m_owner->refreshComplete(Delegate::FAIL_SUCCESS); + m_owner->refreshComplete(Delegate::CATALOG_REFRESHED); } private: @@ -112,6 +114,7 @@ private: Catalog::Catalog(Root *aRoot) : m_root(aRoot), + m_status(Delegate::FAIL_UNKNOWN), m_retrievedTime(0) { } @@ -154,12 +157,39 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath) CatalogRef c = new Catalog(aRoot); c->m_installRoot = aPath; - c->parseProps(props); + c->parseProps(props); // will set status c->parseTimestamp(); return c; } +bool Catalog::uninstall() +{ + bool ok; + bool atLeastOneFailure = false; + + BOOST_FOREACH(PackageRef p, installedPackages()) { + ok = p->existingInstall()->uninstall(); + if (!ok) { + SG_LOG(SG_GENERAL, SG_WARN, "uninstall of package " << + p->id() << " failed"); + // continue trying other packages, bailing out here + // gains us nothing + atLeastOneFailure = true; + } + } + + Dir d(m_installRoot); + ok = d.remove(true /* recursive */); + if (!ok) { + atLeastOneFailure = true; + } + + changeStatus(atLeastOneFailure ? Delegate::FAIL_FILESYSTEM + : Delegate::FAIL_SUCCESS); + return ok; +} + PackageList const& Catalog::packages() const { @@ -226,6 +256,7 @@ InstallRef Catalog::installForPackage(PackageRef pkg) const void Catalog::refresh() { Downloader* dl = new Downloader(this, url()); + // will iupdate status to IN_PROGRESS m_root->makeHTTPRequest(dl); m_root->catalogRefreshBegin(this); } @@ -294,6 +325,9 @@ void Catalog::parseProps(const SGPropertyNode* aProps) Dir d(m_installRoot); d.create(0755); } + + // parsed XML ok, mark status as valid + changeStatus(Delegate::FAIL_SUCCESS); } PackageRef Catalog::getPackageById(const std::string& aId) const @@ -372,6 +406,7 @@ std::string Catalog::getLocalisedString(const SGPropertyNode* aRoot, const char* void Catalog::refreshComplete(Delegate::FailureCode aReason) { m_root->catalogRefreshComplete(this, aReason); + changeStatus(aReason); } void Catalog::registerInstall(Install* ins) @@ -392,6 +427,26 @@ void Catalog::unregisterInstall(Install* ins) m_installed.erase(ins->package()); } +void Catalog::changeStatus(Delegate::FailureCode newStatus) +{ + if (m_status == newStatus) { + return; + } + + m_status = newStatus; + m_statusCallbacks(this); +} + +void Catalog::addStatusCallback(const Callback& cb) +{ + m_statusCallbacks.push_back(cb); +} + +Delegate::FailureCode Catalog::status() const +{ + return m_status; +} + } // of namespace pkg } // of namespace simgear diff --git a/simgear/package/Catalog.hxx b/simgear/package/Catalog.hxx index d3d685e9..4a21dc9d 100644 --- a/simgear/package/Catalog.hxx +++ b/simgear/package/Catalog.hxx @@ -22,11 +22,14 @@ #include #include +#include + #include #include #include #include +#include #include @@ -63,6 +66,11 @@ public: Root* root() const { return m_root;}; + /** + * uninstall this catalog entirely, including all installed packages + */ + bool uninstall(); + /** * perform a refresh of the catalog contents */ @@ -115,6 +123,18 @@ public: * access the raw property data in the catalog */ SGPropertyNode* properties() const; + + Delegate::FailureCode status() const; + + typedef boost::function Callback; + + void addStatusCallback(const Callback& cb); + + template + void addStatusCallback(C* instance, void (C::*mem_func)(Catalog*)) + { + return addStatusCallback(boost::bind(mem_func, instance, _1)); + } private: Catalog(Root* aRoot); @@ -134,11 +154,14 @@ private: std::string getLocalisedString(const SGPropertyNode* aRoot, const char* aName) const; + void changeStatus(Delegate::FailureCode newStatus); + Root* m_root; SGPropertyNode_ptr m_props; SGPath m_installRoot; std::string m_url; - + Delegate::FailureCode m_status; + PackageList m_packages; time_t m_retrievedTime; @@ -149,6 +172,8 @@ private: // since it is only cleaned up in the Install destructor typedef std::map PackageInstallDict; PackageInstallDict m_installed; + + function_list m_statusCallbacks; }; } // of namespace pkg diff --git a/simgear/package/Delegate.hxx b/simgear/package/Delegate.hxx index 8bb23a33..799823fe 100644 --- a/simgear/package/Delegate.hxx +++ b/simgear/package/Delegate.hxx @@ -42,7 +42,8 @@ public: FAIL_DOWNLOAD, ///< network issue FAIL_EXTRACT, ///< package archive failed to extract cleanly FAIL_FILESYSTEM, ///< unknown filesystem error occurred - FAIL_VERSION ///< version check mismatch + FAIL_VERSION, ///< version check mismatch + CATALOG_REFRESHED } FailureCode; diff --git a/simgear/package/Install.cxx b/simgear/package/Install.cxx index c50e31d9..2ca01122 100644 --- a/simgear/package/Install.cxx +++ b/simgear/package/Install.cxx @@ -313,11 +313,21 @@ void Install::startUpdate() m_package->catalog()->root()->startInstall(this); } -void Install::uninstall() +bool Install::uninstall() { Dir d(m_path); - d.remove(true); + if (!d.remove(true)) { + SG_LOG(SG_GENERAL, SG_ALERT, "package uninstall failed: couldn't remove path " << m_path); + return false; + } + m_package->catalog()->unregisterInstall(this); + return true; +} + +bool Install::isDownloading() const +{ + return (m_download != NULL); } //------------------------------------------------------------------------------ diff --git a/simgear/package/Install.hxx b/simgear/package/Install.hxx index e65789c4..ae90353d 100644 --- a/simgear/package/Install.hxx +++ b/simgear/package/Install.hxx @@ -73,9 +73,11 @@ public: bool hasUpdate() const; void startUpdate(); - - void uninstall(); + bool uninstall(); + + bool isDownloading() const; + /** * Set the handler to be called when the installation successfully * completes. diff --git a/simgear/package/Root.cxx b/simgear/package/Root.cxx index adc7b257..a9127b1f 100644 --- a/simgear/package/Root.cxx +++ b/simgear/package/Root.cxx @@ -336,6 +336,28 @@ void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason } } +bool Root::removeCatalogById(const std::string& aId) +{ + CatalogDict::iterator catIt = d->catalogs.find(aId); + if (catIt == d->catalogs.end()) { + SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: unknown ID:" << aId); + return false; + } + + CatalogRef cat = catIt->second; + + // drop the reference + d->catalogs.erase(catIt); + + bool ok = cat->uninstall(); + if (!ok) { + SG_LOG(SG_GENERAL, SG_WARN, "removeCatalogById: catalog :" << aId + << "failed to uninstall"); + } + + return ok; +} + } // of namespace pkg } // of namespace simgear diff --git a/simgear/package/Root.hxx b/simgear/package/Root.hxx index c0a53a44..2a06a6b1 100644 --- a/simgear/package/Root.hxx +++ b/simgear/package/Root.hxx @@ -109,6 +109,12 @@ public: CatalogRef getCatalogById(const std::string& aId) const; void scheduleToUpdate(InstallRef aInstall); + + /** + * remove a catalog. Will uninstall all packages originating + * from the catalog too. + */ + bool removeCatalogById(const std::string& aId); private: friend class Install; friend class Catalog;