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)
This commit is contained in:
James Turner
2015-09-27 19:42:08 -05:00
parent 3bc53474ed
commit 4e40913aef
8 changed files with 95 additions and 26 deletions

View File

@@ -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");

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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<Package*>(this));
InstallRef install;
try {
install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(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) {

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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.