From 4e40913aefd3dd5c031eda47f15b76a12c0f5ae2 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 27 Sep 2015 19:42:08 -0500 Subject: [PATCH] Package support progress - check the catalog version explicitly when refreshing - handle packages with distinct dir name / primary ID correctly (requires an updated catalog XML format) --- simgear/package/Catalog.cxx | 37 ++++++++++++++++++++++++++++++------ simgear/package/Catalog.hxx | 2 ++ simgear/package/Delegate.hxx | 9 +++++---- simgear/package/Install.cxx | 18 ++++++++++++------ simgear/package/Package.cxx | 17 +++++++++++++++-- simgear/package/Package.hxx | 6 ++++++ simgear/package/Root.cxx | 20 ++++++++++++++----- simgear/package/Root.hxx | 12 +++++++++--- 8 files changed, 95 insertions(+), 26 deletions(-) diff --git a/simgear/package/Catalog.cxx b/simgear/package/Catalog.cxx index 5d407fe5..1a810af8 100644 --- a/simgear/package/Catalog.cxx +++ b/simgear/package/Catalog.cxx @@ -90,8 +90,13 @@ protected: virtual void onDone() { if (responseCode() != 200) { - SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url()); - m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD); + Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD; + SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url() + << "\n\t" << responseCode()); + if (responseCode() == 404) { + code = Delegate::FAIL_NOT_FOUND; + } + m_owner->refreshComplete(code); return; } @@ -106,7 +111,15 @@ protected: return; } - std::string ver(m_owner->root()->catalogVersion()); + if (m_owner->root()->catalogVersion() != props->getIntValue("catalog-version")) { + SG_LOG(SG_GENERAL, SG_WARN, "catalog:" << m_owner->url() << " is not version " + << m_owner->root()->catalogVersion()); + m_owner->refreshComplete(Delegate::FAIL_VERSION); + return; + } + + + std::string ver(m_owner->root()->applicationVersion()); if (!checkVersion(ver, props)) { SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t" << props->getStringValue("version") << " vs required " << ver); @@ -186,8 +199,8 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath) return NULL; } - if (!checkVersion(aRoot->catalogVersion(), props)) { - std::string redirect = redirectUrlForVersion(aRoot->catalogVersion(), props); + if (!checkVersion(aRoot->applicationVersion(), props)) { + std::string redirect = redirectUrlForVersion(aRoot->applicationVersion(), props); if (!redirect.empty()) { SG_LOG(SG_GENERAL, SG_WARN, "catalog at " << aPath << ", version mismatch:\n\t" << "redirecting to alternate URL:" << redirect); @@ -385,11 +398,23 @@ PackageRef Catalog::getPackageById(const std::string& aId) const // works as expected. PackageWeakMap::const_iterator it = m_variantDict.find(aId); if (it == m_variantDict.end()) - return NULL; + return PackageRef(); return it->second; } +PackageRef Catalog::getPackageByPath(const std::string& aPath) const +{ + PackageList::const_iterator it; + for (it = m_packages.begin(); it != m_packages.end(); ++it) { + if ((*it)->dirName() == aPath) { + return *it; + } + } + + return PackageRef(); +} + std::string Catalog::id() const { return m_props->getStringValue("id"); diff --git a/simgear/package/Catalog.hxx b/simgear/package/Catalog.hxx index e21df6a1..65e3f992 100644 --- a/simgear/package/Catalog.hxx +++ b/simgear/package/Catalog.hxx @@ -109,6 +109,8 @@ public: PackageRef getPackageById(const std::string& aId) const; + PackageRef getPackageByPath(const std::string& aPath) const; + /** * test if the catalog data was retrieved longer ago than the * maximum permitted age for this catalog. diff --git a/simgear/package/Delegate.hxx b/simgear/package/Delegate.hxx index 145f6a2e..8de67aa5 100644 --- a/simgear/package/Delegate.hxx +++ b/simgear/package/Delegate.hxx @@ -44,11 +44,12 @@ public: STATUS_SUCCESS = 0, FAIL_UNKNOWN = 1, STATUS_IN_PROGRESS, ///< downloading/installation in progress - FAIL_CHECKSUM, ///< package MD5 verificstion failed - FAIL_DOWNLOAD, ///< network issue - FAIL_EXTRACT, ///< package archive failed to extract cleanly + FAIL_CHECKSUM, ///< package MD5 verificstion failed + 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 + FAIL_NOT_FOUND, ///< package URL returned a 404 STATUS_REFRESHED, USER_CANCELLED } StatusCode; diff --git a/simgear/package/Install.cxx b/simgear/package/Install.cxx index 0217e457..b91d2552 100644 --- a/simgear/package/Install.cxx +++ b/simgear/package/Install.cxx @@ -106,8 +106,14 @@ protected: virtual void onDone() { if (responseCode() != 200) { - SG_LOG(SG_GENERAL, SG_ALERT, "download failure"); - doFailure(Delegate::FAIL_DOWNLOAD); + SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() << + "\n\t" << url()); + Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD; + if (responseCode() == 404) { + code = Delegate::FAIL_NOT_FOUND; + } + + doFailure(code); return; } @@ -137,7 +143,7 @@ protected: destDir.remove(true /* recursive */); } - m_extractPath.append(m_owner->package()->id()); + m_extractPath.append(m_owner->package()->dirName()); bool ok = m_extractPath.rename(m_owner->path()); if (!ok) { doFailure(Delegate::FAIL_FILESYSTEM); @@ -296,10 +302,10 @@ Install::~Install() InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat) { - std::string id = aPath.file(); - PackageRef pkg = aCat->getPackageById(id); + std::string path = aPath.file(); + PackageRef pkg = aCat->getPackageByPath(path); if (!pkg) - throw sg_exception("no package with id:" + id); + throw sg_exception("no package with path:" + path); return new Install(pkg, aPath); } diff --git a/simgear/package/Package.cxx b/simgear/package/Package.cxx index 5f76d746..bd25fb3c 100644 --- a/simgear/package/Package.cxx +++ b/simgear/package/Package.cxx @@ -117,7 +117,7 @@ SGPath Package::pathOnDisk() const { SGPath p(m_catalog->installRoot()); p.append("Aircraft"); - p.append(id()); + p.append(dirName()); return p; } @@ -139,7 +139,12 @@ InstallRef Package::install() InstallRef Package::existingInstall(const InstallCallback& cb) const { - InstallRef install = m_catalog->root()->existingInstallForPackage(const_cast(this)); + InstallRef install; + try { + install = m_catalog->root()->existingInstallForPackage(const_cast(this)); + } catch (std::exception& e) { + return InstallRef(); + } if( cb ) { @@ -167,6 +172,14 @@ std::string Package::md5() const return m_props->getStringValue("md5"); } +std::string Package::dirName() const +{ + std::string r(m_props->getStringValue("dir")); + if (r.empty()) + throw sg_exception("missing dir property on catalog package entry for " + m_id); + return r; +} + unsigned int Package::revision() const { if (!m_props) { diff --git a/simgear/package/Package.hxx b/simgear/package/Package.hxx index 9293ca0d..606185fd 100644 --- a/simgear/package/Package.hxx +++ b/simgear/package/Package.hxx @@ -133,6 +133,12 @@ public: * this will raise an sg_exception. */ PackageList dependencies() const; + + /** + * Name of the package directory on disk. This may or may not be the + * same as the primary ID, depending on the aircraft author + */ + std::string dirName() const; private: SGPath pathOnDisk() const; diff --git a/simgear/package/Root.cxx b/simgear/package/Root.cxx index a0bef7c3..2fca504f 100644 --- a/simgear/package/Root.cxx +++ b/simgear/package/Root.cxx @@ -246,8 +246,13 @@ Root::~Root() { } + +int Root::catalogVersion() const +{ + return 4; +} -std::string Root::catalogVersion() const +std::string Root::applicationVersion() const { return d->version; } @@ -442,11 +447,13 @@ void Root::finishInstall(InstallRef aInstall, Delegate::StatusCode aReason) SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:" << aInstall->package()->id() << ":" << aReason); } - - d->fireFinishInstall(aInstall, aReason); + + // order matters here, so a call to 'isQueued' from a finish-install + // callback returns false, not true startNext(aInstall); + d->fireFinishInstall(aInstall, aReason); } - + void Root::cancelDownload(InstallRef aInstall) { RootPrivate::UpdateDeque::iterator it = @@ -544,7 +551,10 @@ InstallRef Root::existingInstallForPackage(PackageRef p) const // this will add to our cache, and hence, modify m_installs return Install::createFromPath(path, p->catalog()); } - + + // insert a null reference into the dictionary, so we don't call + // the pathOnDisk -> exists codepath repeatedley + d->m_installs[p] = InstallRef(); return InstallRef(); } diff --git a/simgear/package/Root.hxx b/simgear/package/Root.hxx index 11e9a647..eadfac88 100644 --- a/simgear/package/Root.hxx +++ b/simgear/package/Root.hxx @@ -83,11 +83,17 @@ public: void makeHTTPRequest(HTTP::Request* req); /** - * the version string of the root. Catalogs must match this version, + * The catalog XML/property version in use. This is used to make incomaptible + * changes to the package/catalog syntax + */ + int catalogVersion() const; + + /** + * the version string of the application. Catalogs must match this version, * or they will be ignored / rejected. */ - std::string catalogVersion() const; - + std::string applicationVersion() const; + /** * refresh catalogs which are more than the maximum age (24 hours by default) * set force to true, to download all catalogs regardless of age. -- 2.39.5