#include <boost/foreach.hpp>
#include <cstring>
+#include <map>
+#include <deque>
+#include <set>
#include <simgear/debug/logstream.hxx>
#include <simgear/props/props_io.hxx>
namespace pkg {
+typedef std::map<std::string, Catalog*> CatalogDict;
+
+class Root::RootPrivate
+{
+public:
+ RootPrivate() :
+ http(NULL),
+ maxAgeSeconds(60 * 60 * 24),
+ delegate(NULL)
+ {
+
+ }
+
+ SGPath path;
+ std::string locale;
+ HTTP::Client* http;
+ CatalogDict catalogs;
+ unsigned int maxAgeSeconds;
+ Delegate* delegate;
+ std::string version;
+
+ std::set<Catalog*> refreshing;
+ std::deque<Install*> updateDeque;
+ std::deque<HTTP::Request_ptr> httpPendingRequests;
+};
+
+SGPath Root::path() const
+{
+ return d->path;
+}
+
void Root::setMaxAgeSeconds(int seconds)
{
- m_maxAgeSeconds = seconds;
+ d->maxAgeSeconds = seconds;
}
void Root::setHTTPClient(HTTP::Client* aHTTP)
{
- m_http = aHTTP;
+ d->http = aHTTP;
+ BOOST_FOREACH(HTTP::Request_ptr req, d->httpPendingRequests) {
+ d->http->makeRequest(req);
+ }
+
+ d->httpPendingRequests.clear();
}
-HTTP::Client* Root::getHTTPClient() const
+void Root::makeHTTPRequest(HTTP::Request *req)
{
- return m_http;
+ if (d->http) {
+ d->http->makeRequest(req);
+ return;
+ }
+
+ d->httpPendingRequests.push_back(req);
}
-
+
Root::Root(const SGPath& aPath, const std::string& aVersion) :
- m_path(aPath),
- m_http(NULL),
- m_maxAgeSeconds(60 * 60 * 24),
- m_delegate(NULL),
- m_version(aVersion)
+ d(new RootPrivate)
{
+ d->path = aPath;
+ d->version = aVersion;
if (getenv("LOCALE")) {
- m_locale = getenv("LOCALE");
+ d->locale = getenv("LOCALE");
}
- Dir d(aPath);
- if (!d.exists()) {
- d.create(0755);
+ Dir dir(aPath);
+ if (!dir.exists()) {
+ dir.create(0755);
return;
}
- BOOST_FOREACH(SGPath c, d.children(Dir::TYPE_DIR)) {
+ BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR)) {
Catalog* cat = Catalog::createFromPath(this, c);
if (cat) {
- m_catalogs[cat->id()] = cat;
+ d->catalogs[cat->id()] = cat;
}
} // of child directories iteration
}
std::string Root::catalogVersion() const
{
- return m_version;
+ return d->version;
}
Catalog* Root::getCatalogById(const std::string& aId) const
{
- CatalogDict::const_iterator it = m_catalogs.find(aId);
- if (it == m_catalogs.end()) {
+ CatalogDict::const_iterator it = d->catalogs.find(aId);
+ if (it == d->catalogs.end()) {
return NULL;
}
Package* pkg = NULL;
if (lastDot == std::string::npos) {
// naked package ID
- CatalogDict::const_iterator it = m_catalogs.begin();
- for (; it != m_catalogs.end(); ++it) {
+ CatalogDict::const_iterator it = d->catalogs.begin();
+ for (; it != d->catalogs.end(); ++it) {
pkg = it->second->getPackageById(aName);
if (pkg) {
return pkg;
CatalogList Root::catalogs() const
{
CatalogList r;
- CatalogDict::const_iterator it = m_catalogs.begin();
- for (; it != m_catalogs.end(); ++it) {
+ CatalogDict::const_iterator it = d->catalogs.begin();
+ for (; it != d->catalogs.end(); ++it) {
r.push_back(it->second);
}
{
PackageList r;
- CatalogDict::const_iterator it = m_catalogs.begin();
- for (; it != m_catalogs.end(); ++it) {
+ CatalogDict::const_iterator it = d->catalogs.begin();
+ for (; it != d->catalogs.end(); ++it) {
PackageList r2(it->second->packagesMatching(aFilter));
r.insert(r.end(), r2.begin(), r2.end());
}
{
PackageList r;
- CatalogDict::const_iterator it = m_catalogs.begin();
- for (; it != m_catalogs.end(); ++it) {
+ CatalogDict::const_iterator it = d->catalogs.begin();
+ for (; it != d->catalogs.end(); ++it) {
PackageList r2(it->second->packagesNeedingUpdate());
r.insert(r.end(), r2.begin(), r2.end());
}
void Root::refresh(bool aForce)
{
- CatalogDict::iterator it = m_catalogs.begin();
- for (; it != m_catalogs.end(); ++it) {
- if (aForce || (it->second->ageInSeconds() > m_maxAgeSeconds)) {
+ CatalogDict::iterator it = d->catalogs.begin();
+ for (; it != d->catalogs.end(); ++it) {
+ if (aForce || (it->second->ageInSeconds() > d->maxAgeSeconds)) {
it->second->refresh();
}
}
void Root::setDelegate(simgear::pkg::Delegate *aDelegate)
{
- m_delegate = aDelegate;
+ d->delegate = aDelegate;
}
void Root::setLocale(const std::string& aLocale)
{
- m_locale = aLocale;
+ d->locale = aLocale;
}
std::string Root::getLocale() const
{
- return m_locale;
+ return d->locale;
}
void Root::scheduleToUpdate(Install* aInstall)
dep->install();
}
- bool wasEmpty = m_updateDeque.empty();
- m_updateDeque.push_back(aInstall);
+ bool wasEmpty = d->updateDeque.empty();
+ d->updateDeque.push_back(aInstall);
if (wasEmpty) {
aInstall->startUpdate();
void Root::startInstall(Install* aInstall)
{
- if (m_delegate) {
- m_delegate->startInstall(aInstall);
+ if (d->delegate) {
+ d->delegate->startInstall(aInstall);
}
}
void Root::installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal)
{
- if (m_delegate) {
- m_delegate->installProgress(aInstall, aBytes, aTotal);
+ if (d->delegate) {
+ d->delegate->installProgress(aInstall, aBytes, aTotal);
}
}
void Root::startNext(Install* aCurrent)
{
- if (m_updateDeque.front() != aCurrent) {
+ if (d->updateDeque.front() != aCurrent) {
SG_LOG(SG_GENERAL, SG_ALERT, "current install of package not head of the deque");
} else {
- m_updateDeque.pop_front();
+ d->updateDeque.pop_front();
}
- if (!m_updateDeque.empty()) {
- m_updateDeque.front()->startUpdate();
+ if (!d->updateDeque.empty()) {
+ d->updateDeque.front()->startUpdate();
}
}
void Root::finishInstall(Install* aInstall)
{
- if (m_delegate) {
- m_delegate->finishInstall(aInstall);
+ if (d->delegate) {
+ d->delegate->finishInstall(aInstall);
}
startNext(aInstall);
{
SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
<< aInstall->package()->id() << ":" << aReason);
- if (m_delegate) {
- m_delegate->failedInstall(aInstall, aReason);
+ if (d->delegate) {
+ d->delegate->failedInstall(aInstall, aReason);
}
startNext(aInstall);
void Root::catalogRefreshBegin(Catalog* aCat)
{
- m_refreshing.insert(aCat);
+ d->refreshing.insert(aCat);
}
void Root::catalogRefreshComplete(Catalog* aCat, Delegate::FailureCode aReason)
{
- CatalogDict::iterator catIt = m_catalogs.find(aCat->id());
+ CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
if (aReason != Delegate::FAIL_SUCCESS) {
- if (m_delegate) {
- m_delegate->failedRefresh(aCat, aReason);
+ if (d->delegate) {
+ d->delegate->failedRefresh(aCat, aReason);
}
// if the failure is permanent, delete the catalog from our
bool isPermanentFailure = (aReason == Delegate::FAIL_VERSION);
if (isPermanentFailure) {
SG_LOG(SG_GENERAL, SG_WARN, "permanent failure for catalog:" << aCat->id());
- m_catalogs.erase(catIt);
+ d->catalogs.erase(catIt);
}
- } else if (catIt == m_catalogs.end()) {
+ } else if (catIt == d->catalogs.end()) {
// first fresh, add to our storage now
- m_catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
+ d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
}
- m_refreshing.erase(aCat);
- if (m_refreshing.empty()) {
- if (m_delegate) {
- m_delegate->refreshComplete();
+ d->refreshing.erase(aCat);
+ if (d->refreshing.empty()) {
+ if (d->delegate) {
+ d->delegate->refreshComplete();
}
}
}
#define SG_PACKAGE_ROOT_HXX
#include <vector>
-#include <map>
-#include <deque>
-#include <set>
+#include <memory> // for auto_ptr
#include <simgear/misc/sg_path.hxx>
#include <simgear/package/Delegate.hxx>
namespace simgear
{
-namespace HTTP { class Client; }
+namespace HTTP {
+ class Client;
+ class Request;
+}
namespace pkg
{
typedef std::vector<Package*> PackageList;
typedef std::vector<Catalog*> CatalogList;
-typedef std::map<std::string, Catalog*> CatalogDict;
-
class Root
{
public:
Root(const SGPath& aPath, const std::string& aVersion);
virtual ~Root();
- SGPath path() const
- { return m_path; }
+ SGPath path() const;
void setLocale(const std::string& aLocale);
void setHTTPClient(HTTP::Client* aHTTP);
- HTTP::Client* getHTTPClient() const;
-
+ /**
+ * Submit an HTTP request. The Root may delay or queue requests if it needs
+ * too, for example during startup when the HTTP engine may not have been
+ * set yet.
+ */
+ void makeHTTPRequest(HTTP::Request* req);
+
/**
* the version string of the root. Catalogs must match this version,
* or they will be ignored / rejected.
void installProgress(Install* aInstall, unsigned int aBytes, unsigned int aTotal);
void finishInstall(Install* aInstall);
void failedInstall(Install* aInstall, Delegate::FailureCode aReason);
-
- SGPath m_path;
- std::string m_locale;
- HTTP::Client* m_http;
- CatalogDict m_catalogs;
- unsigned int m_maxAgeSeconds;
- Delegate* m_delegate;
- std::string m_version;
-
- std::set<Catalog*> m_refreshing;
- std::deque<Install*> m_updateDeque;
-};
+
+ class RootPrivate;
+ std::auto_ptr<RootPrivate> d;
+};
} // of namespace pkg