]> git.mxchange.org Git - simgear.git/blobdiff - simgear/package/Root.cxx
Package: expose file size property.
[simgear.git] / simgear / package / Root.cxx
index 197f96c9b42f09af8422bb7015da70098f655b44..adc7b25723f3ee20252c42d9a22538a7fd98e62e 100644 (file)
@@ -19,6 +19,9 @@
 
 #include <boost/foreach.hpp>
 #include <cstring>
+#include <map>
+#include <deque>
+#include <set>
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/props/props_io.hxx>
@@ -34,41 +37,86 @@ namespace simgear {
     
 namespace pkg {
 
-void Root::setMaxAgeSeconds(int seconds)
+typedef std::map<std::string, CatalogRef> 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<CatalogRef> refreshing;
+    std::deque<InstallRef> updateDeque;
+    std::deque<HTTP::Request_ptr> httpPendingRequests;
+};
+    
+SGPath Root::path() const
+{
+    return d->path;
+}
+    
+void Root::setMaxAgeSeconds(unsigned int seconds)
 {
-    m_maxAgeSeconds = seconds;
+    d->maxAgeSeconds = seconds;
+}
+    
+unsigned int Root::maxAgeSeconds() const
+{
+    return d->maxAgeSeconds;
 }
 
 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) :
-    m_path(aPath),
-    m_http(NULL),
-    m_maxAgeSeconds(60 * 60 * 24),
-    m_delegate(NULL)
+    
+Root::Root(const SGPath& aPath, const std::string& 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)) {
-        Catalog* cat = Catalog::createFromPath(this, c);
+    BOOST_FOREACH(SGPath c, dir.children(Dir::TYPE_DIR)) {
+        CatalogRef cat = Catalog::createFromPath(this, c);
         if (cat) {
-           m_catalogs[cat->id()] = cat;     
+           d->catalogs[cat->id()] = cat;
         }
     } // of child directories iteration
 }
@@ -77,26 +125,31 @@ Root::~Root()
 {
     
 }
-
-Catalog* Root::getCatalogById(const std::string& aId) const
+    
+std::string Root::catalogVersion() const
 {
-    CatalogDict::const_iterator it = m_catalogs.find(aId);
-    if (it == m_catalogs.end()) {
+    return d->version;
+}
+    
+CatalogRef Root::getCatalogById(const std::string& aId) const
+{
+    CatalogDict::const_iterator it = d->catalogs.find(aId);
+    if (it == d->catalogs.end()) {
         return NULL;
     }
     
     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 = 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;
@@ -108,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;
     }
@@ -119,8 +172,8 @@ Package* Root::getPackageById(const std::string& aName) const
 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);
     }
     
@@ -132,8 +185,8 @@ Root::packagesMatching(const SGPropertyNode* aFilter) const
 {
     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());
     }
@@ -146,8 +199,8 @@ Root::packagesNeedingUpdate() const
 {
     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());
     }
@@ -157,28 +210,33 @@ Root::packagesNeedingUpdate() const
 
 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->needsRefresh()) {
             it->second->refresh();
         }
     }
 }
 
+void Root::setDelegate(simgear::pkg::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)
+void Root::scheduleToUpdate(InstallRef aInstall)
 {
     if (!aInstall) {
-        sg_exception("missing argument to scheduleToUpdate");
+        throw sg_exception("missing argument to scheduleToUpdate");
     }
     
     PackageList deps = aInstall->package()->dependencies();
@@ -188,71 +246,92 @@ 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)
+void Root::startInstall(InstallRef aInstall)
 {
-    if (m_delegate) {
-        m_delegate->startInstall(aInstall);
+    if (d->delegate) {
+        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 (m_delegate) {
-        m_delegate->installProgress(aInstall, aBytes, aTotal);
+    if (d->delegate) {
+        d->delegate->installProgress(aInstall.ptr(), aBytes, aTotal);
     }
 }
 
-void Root::startNext(Install* aCurrent)
+void Root::startNext(InstallRef 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)
+void Root::finishInstall(InstallRef aInstall)
 {
-    if (m_delegate) {
-        m_delegate->finishInstall(aInstall);
+    if (d->delegate) {
+        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 (m_delegate) {
-        m_delegate->failedInstall(aInstall, aReason);
+    if (d->delegate) {
+        d->delegate->failedInstall(aInstall.ptr(), aReason);
     }
     
     startNext(aInstall);
 }
 
-void Root::catalogRefreshBegin(Catalog* aCat)
+void Root::catalogRefreshBegin(CatalogRef aCat)
 {
-    m_refreshing.insert(aCat);
+    d->refreshing.insert(aCat);
 }
 
-void Root::catalogRefreshComplete(Catalog* aCat, bool aSuccess)
+void Root::catalogRefreshComplete(CatalogRef aCat, Delegate::FailureCode aReason)
 {
-    m_refreshing.erase(aCat);
-    if (m_refreshing.empty()) {
-        if (m_delegate) {
-            m_delegate->refreshComplete();
+    CatalogDict::iterator catIt = d->catalogs.find(aCat->id());
+    if (aReason != Delegate::FAIL_SUCCESS) {
+        if (d->delegate) {
+            d->delegate->failedRefresh(aCat, aReason);
+        }
+        
+        // if the failure is permanent, delete the catalog from our
+        // list (don't touch it on disk)
+        bool isPermanentFailure = (aReason == Delegate::FAIL_VERSION);
+        if (isPermanentFailure) {
+            SG_LOG(SG_GENERAL, SG_WARN, "permanent failure for catalog:" << aCat->id());
+            if (catIt != d->catalogs.end()) {
+                d->catalogs.erase(catIt);
+            }
+        }
+    } else if (catIt == d->catalogs.end()) {
+        // first fresh, add to our storage now
+        d->catalogs.insert(catIt, CatalogDict::value_type(aCat->id(), aCat));
+    }
+    
+    d->refreshing.erase(aCat);
+    if (d->refreshing.empty()) {
+        if (d->delegate) {
+            d->delegate->refreshComplete();
         }
     }
 }