Update package classes ownership model.

Use SGReferences as the base for package classes, so they can be
exposed directly to Nasal by cppbind.
This commit is contained in:
James Turner 2014-05-31 16:46:49 +01:00
parent b36cdebe8b
commit e3ddcbe2dd
9 changed files with 128 additions and 81 deletions

View File

@ -43,7 +43,7 @@ CatalogList static_catalogs;
class Catalog::Downloader : public HTTP::Request
{
public:
Downloader(Catalog* aOwner, const std::string& aUrl) :
Downloader(CatalogRef aOwner, const std::string& aUrl) :
HTTP::Request(aUrl),
m_owner(aOwner)
{
@ -106,7 +106,7 @@ private:
return false;
}
Catalog* m_owner;
CatalogRef m_owner;
std::string m_buffer;
};
@ -130,16 +130,17 @@ Catalog::~Catalog()
static_catalogs.erase(it);
}
Catalog* Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
CatalogRef Catalog::createFromUrl(Root* aRoot, const std::string& aUrl)
{
Catalog* c = new Catalog(aRoot);
CatalogRef c = new Catalog(aRoot);
c->m_url = aUrl;
Downloader* dl = new Downloader(c, aUrl);
aRoot->makeHTTPRequest(dl);
return c;
}
Catalog* Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
{
SGPath xml = aPath;
xml.append("catalog.xml");
@ -161,7 +162,7 @@ Catalog* Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
return NULL;
}
Catalog* c = new Catalog(aRoot);
CatalogRef c = new Catalog(aRoot);
c->m_installRoot = aPath;
c->parseProps(props);
c->parseTimestamp();
@ -173,7 +174,7 @@ PackageList
Catalog::packagesMatching(const SGPropertyNode* aFilter) const
{
PackageList r;
BOOST_FOREACH(Package* p, m_packages) {
BOOST_FOREACH(PackageRef p, m_packages) {
if (p->matches(aFilter)) {
r.push_back(p);
}
@ -185,7 +186,7 @@ PackageList
Catalog::packagesNeedingUpdate() const
{
PackageList r;
BOOST_FOREACH(Package* p, m_packages) {
BOOST_FOREACH(PackageRef p, m_packages) {
if (!p->isInstalled()) {
continue;
}
@ -213,14 +214,26 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
for (int i = 0; i < nChildren; i++) {
const SGPropertyNode* pkgProps = aProps->getChild(i);
if (strcmp(pkgProps->getName(), "package") == 0) {
Package* p = new Package(pkgProps, this);
PackageRef p = new Package(pkgProps, this);
m_packages.push_back(p);
} else {
SGPropertyNode* c = m_props->getChild(pkgProps->getName(), pkgProps->getIndex(), true);
copyProperties(pkgProps, c);
}
} // of children iteration
if (!m_url.empty()) {
if (m_url != m_props->getStringValue("url")) {
// this effectively allows packages to migrate to new locations,
// although if we're going to rely on that feature we should
// maybe formalise it!
SG_LOG(SG_GENERAL, SG_WARN, "package downloaded from:" << m_url
<< " is now at: " << m_props->getStringValue("url"));
}
}
m_url = m_props->getStringValue("url");
if (m_installRoot.isNull()) {
m_installRoot = m_root->path();
m_installRoot.append(id());
@ -230,9 +243,9 @@ void Catalog::parseProps(const SGPropertyNode* aProps)
}
}
Package* Catalog::getPackageById(const std::string& aId) const
PackageRef Catalog::getPackageById(const std::string& aId) const
{
BOOST_FOREACH(Package* p, m_packages) {
BOOST_FOREACH(PackageRef p, m_packages) {
if (p->id() == aId) {
return p;
}
@ -248,7 +261,7 @@ std::string Catalog::id() const
std::string Catalog::url() const
{
return m_props->getStringValue("url");
return m_url;
}
std::string Catalog::description() const

View File

@ -24,6 +24,9 @@
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/package/Delegate.hxx>
namespace simgear
@ -39,17 +42,21 @@ class Package;
class Catalog;
class Root;
typedef std::vector<Package*> PackageList;
typedef std::vector<Catalog*> CatalogList;
typedef SGSharedPtr<Package> PackageRef;
typedef SGSharedPtr<Catalog> CatalogRef;
typedef SGSharedPtr<Install> InstallRef;
typedef std::vector<PackageRef> PackageList;
typedef std::vector<CatalogRef> CatalogList;
class Catalog
class Catalog : public SGReferenced
{
public:
virtual ~Catalog();
static Catalog* createFromUrl(Root* aRoot, const std::string& aUrl);
static CatalogRef createFromUrl(Root* aRoot, const std::string& aUrl);
static Catalog* createFromPath(Root* aRoot, const SGPath& aPath);
static CatalogRef createFromPath(Root* aRoot, const SGPath& aPath);
static CatalogList allCatalogs();
@ -81,7 +88,7 @@ public:
std::string description() const;
Package* getPackageById(const std::string& aId) const;
PackageRef getPackageById(const std::string& aId) const;
/**
* test if the catalog data was retrieved longer ago than the
@ -113,7 +120,8 @@ private:
Root* m_root;
SGPropertyNode_ptr m_props;
SGPath m_installRoot;
std::string m_url;
PackageList m_packages;
time_t m_retrievedTime;
};

View File

@ -42,7 +42,7 @@ namespace pkg {
class Install::PackageArchiveDownloader : public HTTP::Request
{
public:
PackageArchiveDownloader(Install* aOwner) :
PackageArchiveDownloader(InstallRef aOwner) :
HTTP::Request("" /* dummy URL */),
m_owner(aOwner)
{
@ -247,7 +247,7 @@ private:
m_urls.erase(m_urls.begin()); // pop first URL
}
Install* m_owner;
InstallRef m_owner;
string_list m_urls;
SG_MD5_CTX m_md5;
std::string m_buffer;
@ -256,7 +256,7 @@ private:
////////////////////////////////////////////////////////////////////
Install::Install(Package* aPkg, const SGPath& aPath) :
Install::Install(PackageRef aPkg, const SGPath& aPath) :
m_package(aPkg),
m_path(aPath),
m_download(NULL)
@ -264,10 +264,10 @@ Install::Install(Package* aPkg, const SGPath& aPath) :
parseRevision();
}
Install* Install::createFromPath(const SGPath& aPath, Catalog* aCat)
InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
{
std::string id = aPath.file();
Package* pkg = aCat->getPackageById(id);
PackageRef pkg = aCat->getPackageById(id);
if (!pkg)
throw sg_exception("no package with id:" + id);

View File

@ -23,6 +23,9 @@
#include <simgear/misc/sg_path.hxx>
#include <simgear/package/Delegate.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
namespace simgear
{
@ -32,22 +35,27 @@ namespace pkg
// forward decls
class Package;
class Catalog;
class Install;
typedef SGSharedPtr<Package> PackageRef;
typedef SGSharedPtr<Catalog> CatalogRef;
typedef SGSharedPtr<Install> InstallRef;
/**
*
*/
class Install
class Install : public SGReferenced
{
public:
/**
* create from a directory on disk, or fail.
*/
static Install* createFromPath(const SGPath& aPath, Catalog* aCat);
static InstallRef createFromPath(const SGPath& aPath, CatalogRef aCat);
unsigned int revsion() const
{ return m_revision; }
Package* package() const
PackageRef package() const
{ return m_package; }
SGPath path() const
@ -70,7 +78,7 @@ private:
class PackageArchiveDownloader;
friend class PackageArchiveDownloader;
Install(Package* aPkg, const SGPath& aPath);
Install(PackageRef aPkg, const SGPath& aPath);
void parseRevision();
void writeRevisionFile();
@ -78,7 +86,7 @@ private:
void installResult(Delegate::FailureCode aReason);
void installProgress(unsigned int aBytes, unsigned int aTotal);
Package* m_package;
PackageRef m_package;
unsigned int m_revision; ///< revision on disk
SGPath m_path; ///< installation point on disk

View File

@ -31,7 +31,7 @@ namespace simgear {
namespace pkg {
Package::Package(const SGPropertyNode* aProps, Catalog* aCatalog) :
Package::Package(const SGPropertyNode* aProps, CatalogRef aCatalog) :
m_catalog(aCatalog)
{
initWithProps(aProps);
@ -83,7 +83,7 @@ bool Package::isInstalled() const
return p.exists();
}
Install* Package::install()
InstallRef Package::install()
{
SGPath p(m_catalog->installRoot());
p.append("Aircraft");
@ -92,7 +92,7 @@ Install* Package::install()
return Install::createFromPath(p, m_catalog);
}
Install* ins = new Install(this, p);
InstallRef ins(new Install(this, p));
m_catalog->root()->scheduleToUpdate(ins);
return ins;
}
@ -174,7 +174,7 @@ PackageList Package::dependencies() const
// prefer local hangar package if possible, in case someone does something
// silly with naming. Of course flightgear's aircraft search doesn't know
// about hanagrs, so names still need to be unique.
Package* depPkg = m_catalog->getPackageById(depName);
PackageRef depPkg = m_catalog->getPackageById(depName);
if (!depPkg) {
Root* rt = m_catalog->root();
depPkg = rt->getPackageById(depName);

View File

@ -24,6 +24,9 @@
#include <simgear/props/props.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
typedef std::set<std::string> string_set;
namespace simgear
@ -36,16 +39,20 @@ namespace pkg
class Install;
class Catalog;
class Package;
typedef SGSharedPtr<Package> PackageRef;
typedef SGSharedPtr<Catalog> CatalogRef;
typedef SGSharedPtr<Install> InstallRef;
typedef std::vector<Package*> PackageList;
typedef std::vector<PackageRef> PackageList;
class Package
class Package : public SGReferenced
{
public:
/**
* get or create an install for the package
*/
Install* install();
InstallRef install();
bool isInstalled() const;
@ -76,7 +83,7 @@ public:
unsigned int revision() const;
Catalog* catalog() const
CatalogRef catalog() const
{ return m_catalog; }
bool matches(const SGPropertyNode* aFilter) const;
@ -97,7 +104,7 @@ public:
private:
friend class Catalog;
Package(const SGPropertyNode* aProps, Catalog* aCatalog);
Package(const SGPropertyNode* aProps, CatalogRef aCatalog);
void initWithProps(const SGPropertyNode* aProps);
@ -105,7 +112,7 @@ private:
SGPropertyNode_ptr m_props;
string_set m_tags;
Catalog* m_catalog;
CatalogRef m_catalog;
};

View File

@ -37,7 +37,7 @@ namespace simgear {
namespace pkg {
typedef std::map<std::string, Catalog*> CatalogDict;
typedef std::map<std::string, CatalogRef> CatalogDict;
class Root::RootPrivate
{
@ -58,8 +58,8 @@ public:
Delegate* delegate;
std::string version;
std::set<Catalog*> refreshing;
std::deque<Install*> updateDeque;
std::set<CatalogRef> refreshing;
std::deque<InstallRef> updateDeque;
std::deque<HTTP::Request_ptr> httpPendingRequests;
};
@ -114,7 +114,7 @@ Root::Root(const SGPath& aPath, const std::string& aVersion) :
}
BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR)) {
Catalog* cat = Catalog::createFromPath(this, c);
CatalogRef cat = Catalog::createFromPath(this, c);
if (cat) {
d->catalogs[cat->id()] = cat;
}
@ -131,7 +131,7 @@ std::string Root::catalogVersion() const
return d->version;
}
Catalog* Root::getCatalogById(const std::string& aId) const
CatalogRef Root::getCatalogById(const std::string& aId) const
{
CatalogDict::const_iterator it = d->catalogs.find(aId);
if (it == d->catalogs.end()) {
@ -141,11 +141,11 @@ Catalog* Root::getCatalogById(const std::string& aId) const
return it->second;
}
Package* Root::getPackageById(const std::string& aName) const
PackageRef Root::getPackageById(const std::string& aName) const
{
size_t lastDot = aName.rfind('.');
Package* pkg = NULL;
PackageRef pkg = NULL;
if (lastDot == std::string::npos) {
// naked package ID
CatalogDict::const_iterator it = d->catalogs.begin();
@ -161,7 +161,7 @@ Package* Root::getPackageById(const std::string& aName) const
std::string catalogId = aName.substr(0, lastDot);
std::string id = aName.substr(lastDot + 1);
Catalog* catalog = getCatalogById(catalogId);
CatalogRef catalog = getCatalogById(catalogId);
if (!catalog) {
return NULL;
}
@ -233,7 +233,7 @@ std::string Root::getLocale() const
return d->locale;
}
void Root::scheduleToUpdate(Install* aInstall)
void Root::scheduleToUpdate(InstallRef aInstall)
{
if (!aInstall) {
throw sg_exception("missing argument to scheduleToUpdate");
@ -254,21 +254,21 @@ void Root::scheduleToUpdate(Install* aInstall)
}
}
void Root::startInstall(Install* aInstall)
void Root::startInstall(InstallRef aInstall)
{
if (d->delegate) {
d->delegate->startInstall(aInstall);
d->delegate->startInstall(aInstall.ptr());
}
}
void Root::installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal)
void Root::installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal)
{
if (d->delegate) {
d->delegate->installProgress(aInstall, aBytes, aTotal);
d->delegate->installProgress(aInstall.ptr(), aBytes, aTotal);
}
}
void Root::startNext(Install* aCurrent)
void Root::startNext(InstallRef aCurrent)
{
if (d->updateDeque.front() != aCurrent) {
SG_LOG(SG_GENERAL, SG_ALERT, "current install of package not head of the deque");
@ -281,32 +281,32 @@ void Root::startNext(Install* aCurrent)
}
}
void Root::finishInstall(Install* aInstall)
void Root::finishInstall(InstallRef aInstall)
{
if (d->delegate) {
d->delegate->finishInstall(aInstall);
d->delegate->finishInstall(aInstall.ptr());
}
startNext(aInstall);
}
void Root::failedInstall(Install* aInstall, Delegate::FailureCode aReason)
void Root::failedInstall(InstallRef aInstall, Delegate::FailureCode aReason)
{
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
<< aInstall->package()->id() << ":" << aReason);
if (d->delegate) {
d->delegate->failedInstall(aInstall, aReason);
d->delegate->failedInstall(aInstall.ptr(), aReason);
}
startNext(aInstall);
}
void Root::catalogRefreshBegin(Catalog* aCat)
void Root::catalogRefreshBegin(CatalogRef aCat)
{
d->refreshing.insert(aCat);
}
void Root::catalogRefreshComplete(Catalog* aCat, Delegate::FailureCode aReason)
void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason)
{
CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
if (aReason != Delegate::FAIL_SUCCESS) {
@ -319,7 +319,9 @@ void Root::catalogRefreshComplete(Catalog* aCat, Delegate::FailureCode aReason)
bool isPermanentFailure = (aReason == Delegate::FAIL_VERSION);
if (isPermanentFailure) {
SG_LOG(SG_GENERAL, SG_WARN, "permanent failure for catalog:" << aCat->id());
d->catalogs.erase(catIt);
if (catIt != d->catalogs.end()) {
d->catalogs.erase(catIt);
}
}
} else if (catIt == d->catalogs.end()) {
// first fresh, add to our storage now

View File

@ -24,6 +24,9 @@
#include <simgear/misc/sg_path.hxx>
#include <simgear/package/Delegate.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
class SGPropertyNode;
namespace simgear
@ -41,11 +44,15 @@ namespace pkg
class Package;
class Catalog;
class Install;
typedef SGSharedPtr<Package> PackageRef;
typedef SGSharedPtr<Catalog> CatalogRef;
typedef SGSharedPtr<Install> InstallRef;
typedef std::vector<PackageRef> PackageList;
typedef std::vector<CatalogRef> CatalogList;
typedef std::vector<Package*> PackageList;
typedef std::vector<Catalog*> CatalogList;
class Root
class Root : public SGReferenced
{
public:
Root(const SGPath& aPath, const std::string& aVersion);
@ -97,30 +104,32 @@ public:
*/
PackageList packagesNeedingUpdate() const;
Package* getPackageById(const std::string& aId) const;
PackageRef getPackageById(const std::string& aId) const;
Catalog* getCatalogById(const std::string& aId) const;
CatalogRef getCatalogById(const std::string& aId) const;
void scheduleToUpdate(Install* aInstall);
void scheduleToUpdate(InstallRef aInstall);
private:
friend class Install;
friend class Catalog;
void catalogRefreshBegin(Catalog* aCat);
void catalogRefreshComplete(Catalog* aCat, Delegate::FailureCode aReason);
void catalogRefreshBegin(CatalogRef aCat);
void catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason);
void startNext(Install* aCurrent);
void startNext(InstallRef aCurrent);
void startInstall(Install* aInstall);
void installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal);
void finishInstall(Install* aInstall);
void failedInstall(Install* aInstall, Delegate::FailureCode aReason);
void startInstall(InstallRef aInstall);
void installProgress(InstallRef aInstall, unsigned int aBytes, unsigned int aTotal);
void finishInstall(InstallRef aInstall);
void failedInstall(InstallRef aInstall, Delegate::FailureCode aReason);
class RootPrivate;
std::auto_ptr<RootPrivate> d;
};
typedef SGSharedPtr<Root> RootRef;
} // of namespace pkg
} // of namespace simgear

View File

@ -132,7 +132,7 @@ int main(int argc, char** argv)
} else if (!strcmp(argv[1], "refresh")) {
root->refresh(true);
} else if (!strcmp(argv[1], "install")) {
pkg::Package* pkg = root->getPackageById(argv[2]);
pkg::PackageRef pkg = root->getPackageById(argv[2]);
if (!pkg) {
cerr << "unknown package:" << argv[2] << endl;
return EXIT_FAILURE;
@ -143,12 +143,12 @@ int main(int argc, char** argv)
return EXIT_SUCCESS;
}
pkg::Catalog* catalog = pkg->catalog();
pkg::CatalogRef catalog = pkg->catalog();
cout << "Will install:" << pkg->id() << " from " << catalog->id() <<
"(" << catalog->description() << ")" << endl;
pkg->install();
} else if (!strcmp(argv[1], "uninstall") || !strcmp(argv[1], "remove")) {
pkg::Package* pkg = root->getPackageById(argv[2]);
pkg::PackageRef pkg = root->getPackageById(argv[2]);
if (!pkg) {
cerr << "unknown package:" << argv[2] << endl;
return EXIT_FAILURE;
@ -178,7 +178,7 @@ int main(int argc, char** argv)
cout << "\t" << p->id() << " " << p->getLocalisedProp("name") << endl;
}
} else if (!strcmp(argv[1], "info")) {
pkg::Package* pkg = root->getPackageById(argv[2]);
pkg::PackageRef pkg = root->getPackageById(argv[2]);
if (!pkg) {
cerr << "unknown package:" << argv[2] << endl;
return EXIT_FAILURE;