From 05f266ac10aa025c35c1bc3e85a2049aec7f9135 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 28 Jul 2013 21:07:40 +0100 Subject: [PATCH] HTTP SVN fixes, cap max update-report depth. --- simgear/io/DAVMultiStatus.cxx | 5 ++++- simgear/io/SVNDirectory.cxx | 40 +++++++++++++++++++++++++---------- simgear/io/SVNDirectory.hxx | 6 +----- simgear/io/SVNRepository.cxx | 13 +++++++++++- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/simgear/io/DAVMultiStatus.cxx b/simgear/io/DAVMultiStatus.cxx index 5270fca6..6e1425dc 100644 --- a/simgear/io/DAVMultiStatus.cxx +++ b/simgear/io/DAVMultiStatus.cxx @@ -58,7 +58,10 @@ DAVResource::DAVResource(const string& href) : _url(href), _container(NULL) { - assert(!href.empty()); + assert(!href.empty()); + if (strutils::ends_with(href, "/")) { + _url = href.substr(0, _url.size() - 1); + } } void DAVResource::setVersionName(const std::string& aVersion) diff --git a/simgear/io/SVNDirectory.cxx b/simgear/io/SVNDirectory.cxx index 311fc4f9..cc572fc1 100644 --- a/simgear/io/SVNDirectory.cxx +++ b/simgear/io/SVNDirectory.cxx @@ -28,7 +28,12 @@ typedef std::map DAVResourceMap; const char* DAV_CACHE_NAME = ".terrasync_cache"; const char* CACHE_VERSION_4_TOKEN = "terrasync-cache-4"; -const unsigned int MAX_UPDATE_REPORT_DEPTH = 3; + +// important: with the Google servers, setting this higher than '1' causes +// server internal errors (500, the connection is closed). In other words we +// can only specify update report items one level deep at most and no more. +// (the root and its direct children, not NOT grand-children) +const unsigned int MAX_UPDATE_REPORT_DEPTH = 1; enum LineState { @@ -90,11 +95,15 @@ void SVNDirectory::parseCache() char versionName[128]; LineState lineState = LINESTATE_HREF; std::ifstream file(p.c_str()); + if (!file.is_open()) { + SG_LOG(SG_IO, SG_WARN, "unable to open cache file for reading:" << p); + return; + } bool doneSelf = false; file.getline(href, 1024); if (strcmp(CACHE_VERSION_4_TOKEN, href)) { - SG_LOG(SG_IO, SG_WARN, "invalid cache file:" << p.str()); + SG_LOG(SG_IO, SG_WARN, "invalid cache file [missing header token]:" << p << " '" << href << "'"); return; } @@ -128,8 +137,11 @@ void SVNDirectory::parseCache() doneSelf = true; } else { DAVResource* child = addChildDirectory(hrefPtr)->collection(); - child->setVersionName(versionName); - } + string s = strutils::strip(versionName); + if (!s.empty()) { + child->setVersionName(versionName); + } + } // of done self test } // of line-state switching } // of file get-line loop } @@ -142,7 +154,7 @@ void SVNDirectory::writeCache() d.create(0755); } - p.append(DAV_CACHE_NAME); + p.append(string(DAV_CACHE_NAME) + ".new"); std::ofstream file(p.c_str(), std::ios::trunc); // first, cache file version header @@ -159,6 +171,16 @@ void SVNDirectory::writeCache() file << child->name() << '\n' << child->versionName() << "\n"; } } // of child iteration + + file.close(); + +// approximately atomic delete + rename operation + SGPath cacheName(localPath); + cacheName.append(DAV_CACHE_NAME); + if (cacheName.exists()) { + cacheName.remove(); + } + p.rename(cacheName); } void SVNDirectory::setBaseUrl(const string& url) @@ -210,6 +232,7 @@ SVNDirectory::addChildDirectory(const std::string& dirName) DAVCollection* childCol = dav->createChildCollection(dirName); SVNDirectory* child = new SVNDirectory(this, childCol); + childCol->setVersionName(child->cachedRevision()); _children.push_back(child); writeCache(); return child; @@ -245,11 +268,6 @@ void SVNDirectory::deleteChildByName(const std::string& nm) writeCache(); } -void SVNDirectory::requestFailed(HTTP::Request *req) -{ - SG_LOG(SG_IO, SG_WARN, "Request failed for:" << req->url()); -} - bool SVNDirectory::isDoingSync() const { if (_doingUpdateReport) { @@ -303,7 +321,7 @@ void SVNDirectory::mergeUpdateReportDetails(unsigned int depth, Dir d(localPath); if (depth >= MAX_UPDATE_REPORT_DEPTH) { - std::cerr << localPath << "exceeded MAX_UPDATE_REPORT_DEPTH, cleaning" << std::endl; + SG_LOG(SG_IO, SG_INFO, localPath << "exceeded MAX_UPDATE_REPORT_DEPTH, cleaning"); d.removeChildren(); return; } diff --git a/simgear/io/SVNDirectory.hxx b/simgear/io/SVNDirectory.hxx index 06876dd4..68bca1b0 100644 --- a/simgear/io/SVNDirectory.hxx +++ b/simgear/io/SVNDirectory.hxx @@ -51,11 +51,7 @@ public: // init from a collection SVNDirectory(SVNDirectory* pr, DAVCollection* col); - -// void update(); - // void gotResource(HTTP::Request* get, const std::string& etag); - void requestFailed(HTTP::Request* req); - + void beginUpdateReport(); void updateReportComplete(); diff --git a/simgear/io/SVNRepository.cxx b/simgear/io/SVNRepository.cxx index 339323ef..80dec23d 100644 --- a/simgear/io/SVNRepository.cxx +++ b/simgear/io/SVNRepository.cxx @@ -184,6 +184,13 @@ namespace { // anonmouse } _davStatus.parseXML(s, n); } + + virtual void failed() + { + HTTP::Request::failed(); + _repo->propFindFailed(this, SVNRepository::SVN_ERROR_SOCKET); + } + private: SVNRepoPrivate* _repo; DAVMultiStatus _davStatus; @@ -291,7 +298,11 @@ protected: } } - + virtual void failed() + { + HTTP::Request::failed(); + _repo->updateFailed(this, SVNRepository::SVN_ERROR_SOCKET); + } private: string _request; mutable int _requestSent;