From d7d59b08a2f1a77a4247ec1a89d6ff48ed73f5c7 Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 18 Aug 2016 16:21:31 +0100 Subject: [PATCH] Copy-from-install support in TerraSync Allows repositories to be initialised based on data in the install. This avoids duplicate downloading of the Model and Airport data, and the starting scenery. Requires a corresponding FlightGear change to be functional. --- simgear/io/HTTPRepository.cxx | 56 +++++++++++++++++++++++++++++++ simgear/io/HTTPRepository.hxx | 6 ++++ simgear/scene/tsync/terrasync.cxx | 12 +++++++ 3 files changed, 74 insertions(+) diff --git a/simgear/io/HTTPRepository.cxx b/simgear/io/HTTPRepository.cxx index 6a631423..d36117be 100644 --- a/simgear/io/HTTPRepository.cxx +++ b/simgear/io/HTTPRepository.cxx @@ -150,6 +150,7 @@ public: typedef std::vector DirectoryVector; DirectoryVector directories; + SGPath installedCopyPath; }; class HTTPDirectory @@ -255,6 +256,54 @@ public: } } + void copyInstalledChildren() + { + if (_repository->installedCopyPath.isNull()) { + return; + } + + string_list indexNames = indexChildren(); + const_string_list_iterator nameIt = indexNames.begin(); + for (; nameIt != indexNames.end(); ++nameIt) { + SGPath p(absolutePath()); + p.append(*nameIt); + if (p.exists()) { + continue; // only copy if the file is missing entirely + } + + ChildInfoList::iterator c = findIndexChild(*nameIt); + if (c->type == ChildInfo::DirectoryType) { + continue; // only care about files + } + + SGPath cp = _repository->installedCopyPath; + cp.append(relativePath()); + cp.append(*nameIt); + if (!cp.exists()) { + continue; + } + + SG_LOG(SG_TERRASYNC, SG_BULK, "new child, copying existing file" << cp << p); + + SGBinaryFile src(cp); + SGBinaryFile dst(p); + src.open(SG_IO_IN); + dst.open(SG_IO_OUT); + + char* buf = (char*) malloc(cp.sizeInBytes()); + if (!buf) { + continue; + } + + src.read(buf, cp.sizeInBytes()); + dst.write(buf, cp.sizeInBytes()); + src.close(); + dst.close(); + + free(buf); + } + } + void updateChildrenBasedOnHash() { // if we got here for a dir which is still updating or excluded @@ -263,6 +312,8 @@ public: return; } + copyInstalledChildren(); + string_list indexNames = indexChildren(), toBeUpdated, orphans; simgear::Dir d(absolutePath()); @@ -723,6 +774,11 @@ size_t HTTPRepository::bytesDownloaded() const return result; } +void HTTPRepository::setInstalledCopyPath(const SGPath& copyPath) +{ + _d->installedCopyPath = copyPath; +} + HTTPRepository::ResultCode HTTPRepository::failure() const { diff --git a/simgear/io/HTTPRepository.hxx b/simgear/io/HTTPRepository.hxx index 7d46c3dd..a46ba083 100644 --- a/simgear/io/HTTPRepository.hxx +++ b/simgear/io/HTTPRepository.hxx @@ -71,6 +71,12 @@ public: virtual size_t bytesToDownload() const; virtual size_t bytesDownloaded() const; + + /** + * optionally provide the location of an installer copy of this + * repository. When a file is missing it will be copied from this tree. + */ + void setInstalledCopyPath(const SGPath& copyPath); private: bool isBare() const; diff --git a/simgear/scene/tsync/terrasync.cxx b/simgear/scene/tsync/terrasync.cxx index df660d86..1f3f8d2b 100644 --- a/simgear/scene/tsync/terrasync.cxx +++ b/simgear/scene/tsync/terrasync.cxx @@ -274,6 +274,8 @@ public: void setLocalDir(string dir) { _local_dir = stripPath(dir);} string getLocalDir() { return _local_dir;} + void setInstalledDir(const SGPath& p) { _installRoot = p; } + void setAllowedErrorCount(int errors) { SGGuard g(_stateLock); @@ -331,6 +333,7 @@ private: string _local_dir; SGPath _persistentCachePath; string _httpServer; + SGPath _installRoot; TerrasyncThreadState _state; SGMutex _stateLock; @@ -547,6 +550,12 @@ void SGTerraSync::WorkerThread::updateSyncSlot(SyncSlot &slot) slot.repository->setEntireRepositoryMode(); slot.repository->setBaseUrl(_httpServer + "/" + slot.currentItem._dir); + if (_installRoot.exists()) { + SGPath p = _installRoot; + p.append(slot.currentItem._dir); + slot.repository->setInstalledCopyPath(p); + } + try { slot.repository->update(); } catch (sg_exception& e) { @@ -825,6 +834,9 @@ void SGTerraSync::reinit() std::string httpServer(_terraRoot->getStringValue("http-server","")); _workerThread->setHTTPServer(httpServer); _workerThread->setLocalDir(_terraRoot->getStringValue("scenery-dir","")); + + SGPath installPath(_terraRoot->getStringValue("installation-dir")); + _workerThread->setInstalledDir(installPath); _workerThread->setAllowedErrorCount(_terraRoot->getIntValue("max-errors",5)); _workerThread->setCacheHits(_terraRoot->getIntValue("cache-hit", 0));