diff --git a/assets/scenehelper.asset b/assets/scenehelper.asset new file mode 100644 index 0000000000..53f052ae89 --- /dev/null +++ b/assets/scenehelper.asset @@ -0,0 +1,11 @@ +local markInterestingNodes = function(nodes) + for _, n in pairs(nodes) do + if openspace.hasSceneGraphNode(n) then + openspace.addTag(n, "GUI.Interesting") + else + openspace.printWarning("Cannot mark non-existing node '" .. n .. "' as interesting.") + end + end +end + +asset.export("markInterestingNodes", markInterestingNodes); \ No newline at end of file diff --git a/assets/solarsystem.asset b/assets/solarsystem.asset index e95bdf28b3..c0848d6cb0 100644 --- a/assets/solarsystem.asset +++ b/assets/solarsystem.asset @@ -4,6 +4,78 @@ asset.import("sun/sun") asset.import("planets/trails") -- asset.import("dwarfplanets/pluto") +local sceneHelper = asset.import("scenehelper") + asset.onInitialize(function () dofile(openspace.absPath('${SCRIPTS}/bind_common_keys.lua')) -end) \ No newline at end of file + openspace.time.setTime(openspace.time.currentWallTime()) + + + -- Toggle night texture, shading, atmosphere and water + openspace.bindKey("s", + helper.property.invert('Earth.RenderableGlobe.Layers.NightLayers.Earth at Night 2012.Enabled') .. + helper.property.invert('Earth.RenderableGlobe.PerformShading') .. + helper.property.invert('Earth.RenderableGlobe.Atmosphere') .. + helper.property.invert('Earth.RenderableGlobe.Layers.WaterMasks.MODIS_Water_Mask.Enabled'), + "Toggle night texture, shading, atmosphere, and water for Earth." + ) + + -- Toggle background + openspace.bindKey("b", + helper.property.invert('MilkyWay.renderable.Enabled') .. + helper.property.invert('Stars.renderable.Enabled'), + "Toggle background (Stars and Milkyway)." + ) + + openspace.bindKey("g", + helper.property.invert('MilkyWay.renderable.Enabled') .. + helper.property.invert('Stars.renderable.Enabled') .. + helper.property.invert('Earth.RenderableGlobe.Layers.NightLayers.Earth at Night 2012.Enabled') .. + helper.property.invert('Earth.RenderableGlobe.PerformShading') .. + helper.property.invert('Mars.RenderableGlobe.PerformShading') .. + helper.property.invert('Earth.RenderableGlobe.Atmosphere') .. + helper.property.invert('Earth.RenderableGlobe.Layers.WaterMasks.MODIS_Water_Mask.Enabled') .. + helper.property.invert('Moon.RenderableGlobe.Enabled') .. + helper.property.invert('Sun.renderable.Enabled'), + "Toogles background and shading mode on the Earth and Mars alongside visibility of the Moon and the Sun" + ) + + openspace.bindKey("h", + "openspace.setPropertyValue('*Trail.renderable.Enabled', false)", + "Disables visibility of the trails" + ) + + openspace.globebrowsing.loadWMSServersFromFile( + openspace.absPath("${OPENSPACE_DATA}/globebrowsing_servers.lua") + ) + + openspace.addVirtualProperty( + "BoolProperty", + "Show Trails", + "*Trail.renderable.Enabled", + "Disable or enable all trails of the scene at the same time", + true, + nil, + nil + ) + + + openspace.setPropertyValueSingle("Global Properties.GlobeBrowsing.GdalWrapper.LogGdalErrors", false) + --openspace.setPropertyValueSingle("Earth.RenderableGlobe.Debug.LevelByProjectedAreaElseDistance", false) + --openspace.globebrowsing.goToGeo(58.5877, 16.1924, 20000000) + + openspace.printInfo("Done setting default values") + + -- Add local patches described at the top of this file + --for obj, list in pairs(vrt_folders) do + -- for _, dir in pairs(list) do + -- openspace.globebrowsing.addBlendingLayersFromDirectory(dir, obj) + -- end + --end + + -- Defined in scene_helper.lua + -- Used to create focus buttons for a subset of scenegraph nodes + sceneHelper.markInterestingNodes({ + "Earth", "Mars", "Moon" + }) +end) diff --git a/assets/spice/base.asset b/assets/spice/base.asset index 71b9075e4a..afc2b7c600 100644 --- a/assets/spice/base.asset +++ b/assets/spice/base.asset @@ -1,11 +1,11 @@ local AssetHelper = asset.import("assethelper") local kernels = { - -- Leapseconds: - asset.syncedResource("naif0012.tls"), + -- Leapseconds: + asset.syncedResource("naif0012.tls"), - -- Orientation and radii of sun, planets, asteroids, satellites, comets: - asset.syncedResource("pck00010.tpc"), - asset.syncedResource("de430_1850-2150.bsp") + -- Orientation and radii of sun, planets, asteroids, satellites, comets: + asset.syncedResource("pck00010.tpc"), + asset.syncedResource("de430_1850-2150.bsp") } AssetHelper.registerSpiceKernels(asset, kernels) \ No newline at end of file diff --git a/assets/sun/sun.asset b/assets/sun/sun.asset index 9ca1b8aaa0..1878e34e57 100644 --- a/assets/sun/sun.asset +++ b/assets/sun/sun.asset @@ -4,20 +4,19 @@ local transforms = asset.import('./transforms') local sunParentName = transforms.SunIau.Name; local texturesPath = asset.syncedResource("textures"); -asset.sync = { - { - Type = "ResourceSynchronization", - Destination = texturesPath, - Identifier = "sun_textures", - Version = 1 - }, - { - Type = "TorrentSynchronization", - Destination = texturesPath, - File = "torrentFilePath.torrent", - } -} +asset.addSynchronization({ + Type = "HttpSynchronization", + Destination = texturesPath, + Identifier = "sun_textures", + Version = 1 +}) + +--asset.addSynchronization({ +-- Type = "TorrentSynchronization", +-- Destination = texturesPath, +-- File = "torrentFilePath.torrent", +--}) -- Simple sphere to represent the Sun local Sun = { diff --git a/assets/sun/transforms.asset b/assets/sun/transforms.asset index 5377c8b4d1..5a0e39f172 100644 --- a/assets/sun/transforms.asset +++ b/assets/sun/transforms.asset @@ -4,14 +4,14 @@ asset.import("spice/base") -- Barycenter of the solar system, expressed in the Galactic frame local SolarSystemBarycenter = { Name = "SolarSystemBarycenter" - -- No parent; this node is attached to the scene graph root + -- No parent; this node is attached to the scene graph root } -- Spice frame for the Sun local SunIau = { - Name = "SunIau", - Parent = SolarSystemBarycenter.Name, - Transform = { + Name = "SunIau", + Parent = SolarSystemBarycenter.Name, + Transform = { Translation = { Type = "SpiceTranslation", Target = "SUN", diff --git a/include/openspace/scene/assetmanager.h b/include/openspace/scene/assetmanager.h index 16b90d60c3..33a1d7b961 100644 --- a/include/openspace/scene/assetmanager.h +++ b/include/openspace/scene/assetmanager.h @@ -49,10 +49,13 @@ public: ); enum class AssetState : int { - Unloaded = 0, - Loaded = 1, - Synchronized = 2, - Initialized = 3 + Unloaded, + Loaded, + LoadingFailed, + Synchronized, + SynchronizatoinFailed, + Initialized, + InitializationFailed }; bool update(); @@ -63,6 +66,7 @@ public: scripting::LuaLibrary luaLibrary(); private: + std::shared_ptr tryLoadAsset(const std::string& path); bool tryInitializeAsset(Asset& asset); std::unordered_map _pendingStateChangeCommands; diff --git a/include/openspace/scene/assetsynchronizer.h b/include/openspace/scene/assetsynchronizer.h index 9949151b93..6e6b3db048 100644 --- a/include/openspace/scene/assetsynchronizer.h +++ b/include/openspace/scene/assetsynchronizer.h @@ -70,7 +70,7 @@ private: std::unordered_map _managedAssets; std::unordered_map _resourceToAssetMap; - std::vector _finishedSynchronizations; + std::vector _trivialSynchronizations; }; diff --git a/include/openspace/util/resourcesynchronization.h b/include/openspace/util/resourcesynchronization.h index dbdf72f7d0..e670813069 100644 --- a/include/openspace/util/resourcesynchronization.h +++ b/include/openspace/util/resourcesynchronization.h @@ -30,38 +30,44 @@ #include #include +#include + namespace openspace { class ResourceSynchronization; struct SynchronizationProduct { - std::shared_ptr synchronization; + ResourceSynchronization* synchronization; }; class SynchronizationJob : public Job { public: - SynchronizationJob(std::shared_ptr synchronization); - void execute() = 0; -protected: - void resolve(); - void updateProgress(float t); + SynchronizationJob(ResourceSynchronization* synchronization); + void execute() override; + std::shared_ptr product() override; private: - std::shared_ptr _synchronization; + ResourceSynchronization* _synchronization; }; -class ResourceSynchronization { +class ResourceSynchronization + : protected std::enable_shared_from_this +{ public: - ResourceSynchronization(); + static documentation::Documentation Documentation(); static std::unique_ptr createFromDictionary( const ghoul::Dictionary& dictionary); - virtual std::shared_ptr job(); + ResourceSynchronization(); + virtual void synchronize() = 0; + void wait(); bool isResolved(); void resolve(); float progress(); void updateProgress(float t); + std::shared_ptr job(); private: + std::shared_ptr _job; std::atomic _started; std::atomic _resolved; std::atomic _progress; diff --git a/include/openspace/util/resourcesynchronizer.h b/include/openspace/util/resourcesynchronizer.h index 24b71f8225..f6d9b193b5 100644 --- a/include/openspace/util/resourcesynchronizer.h +++ b/include/openspace/util/resourcesynchronizer.h @@ -34,12 +34,29 @@ class ResourceSyncClient {}; class ResourceSynchronizer { public: - void enqueueSynchronization(std::shared_ptr sync, ResourceSyncClient* client); - void cancelSynchronization(ResourceSynchronization* sync, ResourceSyncClient* client); - std::vector> finishedSynchronizations(ResourceSyncClient* client); + ResourceSynchronizer(); + + void enqueueSynchronization( + std::shared_ptr sync, + ResourceSyncClient* client); + + void cancelSynchronization( + ResourceSynchronization* sync, + ResourceSyncClient* client); + + std::vector> + finishedSynchronizations(ResourceSyncClient* client); + private: - std::map, - std::shared_ptr> _origin; + std::unordered_map _clientMap; + + std::unordered_map> + _managedSynchronizations; + + std::unordered_map> + _finishedSynchronizations; + + ConcurrentJobManager _jobManager; }; diff --git a/modules/sync/syncmodule.cpp b/modules/sync/syncmodule.cpp index d933645a57..1fde400c18 100644 --- a/modules/sync/syncmodule.cpp +++ b/modules/sync/syncmodule.cpp @@ -1,4 +1,4 @@ -/***************************************************************************************** +/***************************************************************************************** * * * OpenSpace * * * @@ -44,12 +44,10 @@ SyncModule::SyncModule() {} void SyncModule::internalInitialize() { - - auto fSynchronization = FactoryManager::ref().factory(); - ghoul_assert(fSynchronization, "Synchronization factory was not created"); + ghoul_assert(fSynchronization, "ResourceSynchronization factory was not created"); - fSynchronization->registerClass("HttpSyncrhonization"); + fSynchronization->registerClass("HttpSynchronization"); } std::vector SyncModule::documentations() const { diff --git a/modules/sync/syncs/httpsynchronization.cpp b/modules/sync/syncs/httpsynchronization.cpp index e093185d88..fb4a8f0e42 100644 --- a/modules/sync/syncs/httpsynchronization.cpp +++ b/modules/sync/syncs/httpsynchronization.cpp @@ -25,7 +25,11 @@ #include "httpsynchronization.h" #include +#include +namespace { + const char* _loggerCat = "HttpSynchronization"; +} namespace openspace { @@ -39,7 +43,12 @@ documentation::Documentation HttpSynchronization::Documentation() { return {}; } - - +void HttpSynchronization::synchronize() { + // TODO: Download files, synchronously. + // First check if files exist. + + LINFO("Synchronizing!"); + resolve(); +} } // namespace openspace diff --git a/modules/sync/syncs/httpsynchronization.h b/modules/sync/syncs/httpsynchronization.h index 27c43d603a..2fd4fc67c3 100644 --- a/modules/sync/syncs/httpsynchronization.h +++ b/modules/sync/syncs/httpsynchronization.h @@ -31,19 +31,17 @@ #include namespace openspace { - + +class HttpSynchronizationJob; + class HttpSynchronization : public ResourceSynchronization { public: HttpSynchronization(const ghoul::Dictionary& dict); static documentation::Documentation Documentation(); -}; -class HttpSynchronizationJob : public SynchronizationJob { - HttpSynchronizationJob(std::shared_ptr synchronization); - void execute() override; + void synchronize() override; }; - } // namespace openspace #endif // __OPENSPACE_MODULE_SYNC___HTTPSYNCHRONIZATION___H__ diff --git a/modules/sync/syncs/resourcesynchronization.cpp b/modules/sync/syncs/resourcesynchronization.cpp deleted file mode 100644 index 6a7b35a031..0000000000 --- a/modules/sync/syncs/resourcesynchronization.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include "resourcesynchronization.h" - -namespace openspace { - - - -} // namespace openspace diff --git a/scripts/scene_helper.lua b/scripts/scene_helper.lua deleted file mode 100644 index b97a32d37c..0000000000 --- a/scripts/scene_helper.lua +++ /dev/null @@ -1,7 +0,0 @@ -mark_interesting_nodes = function(nodes) - for _, n in pairs(nodes) do - if openspace.hasSceneGraphNode(n) then - openspace.addTag(n, "GUI.Interesting") - end - end -end diff --git a/src/scene/assetmanager.cpp b/src/scene/assetmanager.cpp index f93cc8aff1..b0ed9281e7 100644 --- a/src/scene/assetmanager.cpp +++ b/src/scene/assetmanager.cpp @@ -63,9 +63,13 @@ bool AssetManager::update() { _assetLoader->unloadAsset(asset.get()); } else if (!isLoaded && shouldBeLoaded) { - std::shared_ptr loadedAsset = _assetLoader->loadAsset(path); - loadedAssets.emplace(path, loadedAsset); - _currentStates[loadedAsset.get()] = AssetState::Loaded; + std::shared_ptr loadedAsset = tryLoadAsset(path); + if (loadedAsset) { + loadedAssets.emplace(path, loadedAsset); + _currentStates[loadedAsset.get()] = AssetState::Loaded; + } else { + _currentStates[loadedAsset.get()] = AssetState::LoadingFailed; + } } } @@ -81,13 +85,16 @@ bool AssetManager::update() { continue; } - std::vector> importedAssets = loadedAsset.second->allAssets(); + std::vector> importedAssets = + loadedAsset.second->allAssets(); + for (const auto& a : importedAssets) { _assetSynchronizer->addAsset(a); _syncAncestors[a].insert(loadedAsset.second); } _stateChangesInProgress.emplace( - std::make_pair(loadedAsset.second, _pendingStateChangeCommands[loadedAsset.first]) + loadedAsset.second, + _pendingStateChangeCommands[loadedAsset.first] ); } @@ -95,7 +102,9 @@ bool AssetManager::update() { _assetSynchronizer->syncUnsynced(); // Collect finished synchronizations and initialize assets - std::vector> syncedAssets = _assetSynchronizer->getSynchronizedAssets(); + std::vector> syncedAssets = + _assetSynchronizer->getSynchronizedAssets(); + for (const auto& syncedAsset : syncedAssets) { // Retrieve ancestors that were waiting for this asset to sync const auto it = _syncAncestors.find(syncedAsset); @@ -114,7 +123,12 @@ bool AssetManager::update() { if (shouldInit) { if (tryInitializeAsset(*ancestor)) { changedInititializations = true; + _currentStates[ancestor.get()] = AssetState::Initialized; + } else { + _currentStates[ancestor.get()] = AssetState::InitializationFailed; } + } else { + _currentStates[ancestor.get()] = AssetState::Synchronized; } } } @@ -161,7 +175,7 @@ scripting::LuaLibrary AssetManager::luaLibrary() { "" }, { - "unimportAsset", + "unloadAsset", &luascriptfunctions::unloadAsset, {this}, "string", @@ -171,6 +185,15 @@ scripting::LuaLibrary AssetManager::luaLibrary() { }; } +std::shared_ptr AssetManager::tryLoadAsset(const std::string& path) { + try { + return _assetLoader->loadAsset(path); + } catch (const ghoul::RuntimeError& e) { + LERROR(e.message); + return nullptr; + } +} + bool AssetManager::tryInitializeAsset(Asset& asset) { try { asset.initialize(); diff --git a/src/scene/assetsynchronizer.cpp b/src/scene/assetsynchronizer.cpp index 549a8d2118..72b828cab9 100644 --- a/src/scene/assetsynchronizer.cpp +++ b/src/scene/assetsynchronizer.cpp @@ -37,18 +37,12 @@ AssetSynchronizer::AssetSynchronizer(ResourceSynchronizer* resourceSynchronizer) } void AssetSynchronizer::addAsset(std::shared_ptr asset) { - const bool resolved = assetIsSynchronized(asset.get()); - _managedAssets.emplace(asset.get(), - AssetSynchronization{ asset, - resolved ? - SynchronizationState::Added : - SynchronizationState::Synchronized - } + AssetSynchronization{ asset, SynchronizationState::Added } ); - if (resolved) { - _finishedSynchronizations.push_back(asset.get()); + for (const auto& sync : asset->synchronizations()) { + _resourceToAssetMap[sync.get()] = asset.get(); } } @@ -70,9 +64,14 @@ void AssetSynchronizer::syncAsset(Asset* asset) { std::vector> resourceSyncs = asset->synchronizations(); + if (resourceSyncs.empty()) { + _trivialSynchronizations.push_back(asset); + } + + _managedAssets[asset].state = SynchronizationState::Synchronizing; + for (const auto& s : resourceSyncs) { if (!s->isResolved()) { - _managedAssets[asset].state = SynchronizationState::Synchronizing; _resourceSynchronizer->enqueueSynchronization(s, this); } } @@ -87,13 +86,11 @@ void AssetSynchronizer::syncUnsynced() { } std::vector> AssetSynchronizer::getSynchronizedAssets() { - std::vector> products = + std::vector> syncs = _resourceSynchronizer->finishedSynchronizations(this); std::vector affectedAssets; - for (const auto& p : products) { - std::shared_ptr sync = p->synchronization; - + for (const auto& sync : syncs) { const auto& it = _resourceToAssetMap.find(sync.get()); if (it != _resourceToAssetMap.end()) { affectedAssets.push_back(it->second); @@ -112,26 +109,27 @@ std::vector> AssetSynchronizer::getSynchronizedAssets() { } } - for (auto& finished : _finishedSynchronizations) { + for (auto& finished : _trivialSynchronizations) { auto it = _managedAssets.find(finished); if (it != _managedAssets.end()) { - synchronizedAssets.push_back(it->second.asset); + std::shared_ptr asset = it->second.asset; + _managedAssets[asset.get()].state = SynchronizationState::Synchronized; + synchronizedAssets.push_back(asset); } } - _finishedSynchronizations.clear(); + _trivialSynchronizations.clear(); return synchronizedAssets; } bool AssetSynchronizer::assetIsSynchronized(Asset * asset) { std::vector> syncs = asset->synchronizations(); - bool resolved = true; for (const auto& s : syncs) { if (!s->isResolved()) { - resolved = false; + return false; } } - return resolved; + return true; } } diff --git a/src/util/resourcesynchronization.cpp b/src/util/resourcesynchronization.cpp index c8353fe277..1f400ead42 100644 --- a/src/util/resourcesynchronization.cpp +++ b/src/util/resourcesynchronization.cpp @@ -24,19 +24,68 @@ #include +#include +#include +#include + +#include + +#include + +namespace { + const char* KeyType = "Type"; + const char* _loggerCat = "ResourceSynchronization"; +} + namespace openspace { -ResourceSynchronization::ResourceSynchronization() {} +documentation::Documentation ResourceSynchronization::Documentation() { + using namespace openspace::documentation; + + return { + "ResourceSynchronization", + "resourceSynchronization", + { + { + KeyType, + new StringAnnotationVerifier( + "A valid ResourceSyncrhonization created by a factory" + ), + Optional::No, + "This key specifies the type of ResourceSyncrhonization that gets created. " + "It has to be one of the valid ResourceSyncrhonizations that are available " + "for creation (see the FactoryDocumentation for a list of possible " + "ResourceSyncrhonizations), which depends on the configration of the application" + } + } + }; +} + +ResourceSynchronization::ResourceSynchronization() + : _job(std::make_shared(this)) + , _resolved(false) +{} std::unique_ptr ResourceSynchronization::createFromDictionary( const ghoul::Dictionary & dictionary) { - return std::unique_ptr(); + documentation::testSpecificationAndThrow(Documentation(), dictionary, "ResourceSynchronization"); + + std::string synchronizationType = dictionary.value(KeyType); + + auto factory = FactoryManager::ref().factory(); + ghoul_assert(factory, "ResourceSynchronization factory did not exist"); + std::unique_ptr result = factory->create(synchronizationType, dictionary); + if (result == nullptr) { + LERROR("Failed to create a ResourceSynchronization object of type '" << synchronizationType << "'"); + return nullptr; + } + + return result; } -std::shared_ptr ResourceSynchronization::job() -{ - return std::shared_ptr(); +std::shared_ptr ResourceSynchronization::job() { + return _job; } void ResourceSynchronization::wait() { @@ -58,18 +107,20 @@ void ResourceSynchronization::updateProgress(float t) { _progress = std::min(1.0f, std::max(t, 0.0f)); } -SynchronizationJob::SynchronizationJob( - std::shared_ptr synchronization) -{ +// SynchronizationJob methods + +SynchronizationJob::SynchronizationJob(ResourceSynchronization* synchronization) { _synchronization = synchronization; } -void SynchronizationJob::resolve() { - _synchronization->resolve(); +void SynchronizationJob::execute() { + _synchronization->synchronize(); } -void SynchronizationJob::updateProgress(float t) { - _synchronization->updateProgress(t); +std::shared_ptr SynchronizationJob::product() { + return std::make_shared( + SynchronizationProduct{ _synchronization } + ); } } diff --git a/src/util/resourcesynchronizer.cpp b/src/util/resourcesynchronizer.cpp index b88b0369f3..8b94f5a918 100644 --- a/src/util/resourcesynchronizer.cpp +++ b/src/util/resourcesynchronizer.cpp @@ -24,21 +24,67 @@ #include +namespace { + size_t NumberOfThreads = 8; +} + namespace openspace { + +ResourceSynchronizer::ResourceSynchronizer() + : _jobManager(ThreadPool(NumberOfThreads)) +{} + void ResourceSynchronizer::enqueueSynchronization( std::shared_ptr sync, ResourceSyncClient* client) { - + _managedSynchronizations.emplace(sync.get(), sync); + _clientMap[sync.get()] = client; + + std::shared_ptr job = sync->job(); + _jobManager.enqueueJob(job); } -void ResourceSynchronizer::cancelSynchronization(ResourceSynchronization * sync, ResourceSyncClient * client) { - // TODO: Implement this -} - -std::vector> ResourceSynchronizer::finishedSynchronizations(ResourceSyncClient * client) +void ResourceSynchronizer::cancelSynchronization( + ResourceSynchronization* sync, + ResourceSyncClient* client) { - return std::vector>(); + _managedSynchronizations.erase(sync); + _clientMap.erase(sync); +} + +std::vector> + ResourceSynchronizer::finishedSynchronizations(ResourceSyncClient* client) +{ + // Fetch all finished jobs + while (_jobManager.numFinishedJobs() > 0) { + std::shared_ptr> j = _jobManager.popFinishedJob(); + ResourceSynchronization* sync = j->product()->synchronization; + const auto it = _clientMap.find(sync); + if (it != _clientMap.end()) { + ResourceSyncClient* c = it->second; + _finishedSynchronizations[c].push_back(sync); + } + } + + // Extract the ones that were queried by the client + const auto finishedIt = _finishedSynchronizations.find(client); + if (finishedIt == _finishedSynchronizations.end()) { + return std::vector>(); + } + + std::vector& rawSyncs = finishedIt->second; + + std::vector> syncs(rawSyncs.size()); + std::transform(rawSyncs.begin(), rawSyncs.end(), syncs.begin(), + [this](ResourceSynchronization* raw) { + return _managedSynchronizations[raw]; + } + ); + + _finishedSynchronizations.erase(finishedIt); + + return syncs; } } // namespace openspace