Rework refreshing in RadarProductManager to allow for multiple refreshes at once.

This commit is contained in:
AdenKoperczak 2025-04-25 12:24:45 -04:00
parent 2daf4d8ba4
commit 3288ba30ec
No known key found for this signature in database
GPG key ID: 9843017036F62EE7

View file

@ -15,6 +15,7 @@
#include <mutex> #include <mutex>
#include <shared_mutex> #include <shared_mutex>
#include <unordered_set> #include <unordered_set>
#include <utility>
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(push, 0) # pragma warning(push, 0)
@ -87,16 +88,14 @@ class ProviderManager : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit ProviderManager(RadarProductManager* self, explicit ProviderManager(RadarProductManager* self,
const std::string& radarId, std::string radarId,
common::RadarProductGroup group) :
ProviderManager(self, radarId, group, "???")
{
}
explicit ProviderManager(RadarProductManager* self,
const std::string& radarId,
common::RadarProductGroup group, common::RadarProductGroup group,
const std::string& product) : std::string product = "???",
radarId_ {radarId}, group_ {group}, product_ {product} bool fastRefresh = false) :
radarId_ {std::move(radarId)},
group_ {group},
product_ {std::move(product)},
fastRefresh_ {fastRefresh}
{ {
connect(this, connect(this,
&ProviderManager::NewDataAvailable, &ProviderManager::NewDataAvailable,
@ -114,10 +113,12 @@ public:
const std::string radarId_; const std::string radarId_;
const common::RadarProductGroup group_; const common::RadarProductGroup group_;
const std::string product_; const std::string product_;
const bool fastRefresh_;
bool refreshEnabled_ {false}; bool refreshEnabled_ {false};
boost::asio::steady_timer refreshTimer_ {threadPool_}; boost::asio::steady_timer refreshTimer_ {threadPool_};
std::mutex refreshTimerMutex_ {}; std::mutex refreshTimerMutex_ {};
std::shared_ptr<provider::NexradDataProvider> provider_ {nullptr}; std::shared_ptr<provider::NexradDataProvider> provider_ {nullptr};
size_t refreshCount_ {0};
signals: signals:
void NewDataAvailable(common::RadarProductGroup group, void NewDataAvailable(common::RadarProductGroup group,
@ -138,7 +139,7 @@ public:
level2ProviderManager_ {std::make_shared<ProviderManager>( level2ProviderManager_ {std::make_shared<ProviderManager>(
self_, radarId_, common::RadarProductGroup::Level2)}, self_, radarId_, common::RadarProductGroup::Level2)},
level2ChunksProviderManager_ {std::make_shared<ProviderManager>( level2ChunksProviderManager_ {std::make_shared<ProviderManager>(
self_, radarId_, common::RadarProductGroup::Level2)} self_, radarId_, common::RadarProductGroup::Level2, "???", true)}
{ {
if (radarSite_ == nullptr) if (radarSite_ == nullptr)
{ {
@ -191,8 +192,9 @@ public:
std::shared_ptr<ProviderManager> std::shared_ptr<ProviderManager>
GetLevel3ProviderManager(const std::string& product); GetLevel3ProviderManager(const std::string& product);
void EnableRefresh(boost::uuids::uuid uuid, void EnableRefresh(
std::shared_ptr<ProviderManager> providerManager, boost::uuids::uuid uuid,
const std::set<std::shared_ptr<ProviderManager>>& providerManagers,
bool enabled); bool enabled);
void RefreshData(std::shared_ptr<ProviderManager> providerManager); void RefreshData(std::shared_ptr<ProviderManager> providerManager);
void RefreshDataSync(std::shared_ptr<ProviderManager> providerManager); void RefreshDataSync(std::shared_ptr<ProviderManager> providerManager);
@ -285,7 +287,7 @@ public:
std::optional<float> incomingLevel2Elevation_ {}; std::optional<float> incomingLevel2Elevation_ {};
std::unordered_map<boost::uuids::uuid, std::unordered_map<boost::uuids::uuid,
std::shared_ptr<ProviderManager>, std::set<std::shared_ptr<ProviderManager>>,
boost::hash<boost::uuids::uuid>> boost::hash<boost::uuids::uuid>>
refreshMap_ {}; refreshMap_ {};
std::shared_mutex refreshMapMutex_ {}; std::shared_mutex refreshMapMutex_ {};
@ -664,8 +666,10 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group,
{ {
if (group == common::RadarProductGroup::Level2) if (group == common::RadarProductGroup::Level2)
{ {
// p->EnableRefresh(uuid, p->level2ProviderManager_, enabled); p->EnableRefresh(
p->EnableRefresh(uuid, p->level2ChunksProviderManager_, enabled); uuid,
{p->level2ProviderManager_, p->level2ChunksProviderManager_},
enabled);
} }
else else
{ {
@ -688,7 +692,7 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group,
availableProducts.cend(), availableProducts.cend(),
product) != availableProducts.cend()) product) != availableProducts.cend())
{ {
p->EnableRefresh(uuid, providerManager, enabled); p->EnableRefresh(uuid, {providerManager}, enabled);
} }
} }
catch (const std::exception& ex) catch (const std::exception& ex)
@ -701,49 +705,44 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group,
void RadarProductManagerImpl::EnableRefresh( void RadarProductManagerImpl::EnableRefresh(
boost::uuids::uuid uuid, boost::uuids::uuid uuid,
std::shared_ptr<ProviderManager> providerManager, const std::set<std::shared_ptr<ProviderManager>>& providerManagers,
bool enabled) bool enabled)
{ {
// Lock the refresh map // Lock the refresh map
std::unique_lock lock {refreshMapMutex_}; std::unique_lock lock {refreshMapMutex_};
auto currentProviderManager = refreshMap_.find(uuid); auto currentProviderManagers = refreshMap_.find(uuid);
if (currentProviderManager != refreshMap_.cend()) if (currentProviderManagers != refreshMap_.cend())
{ {
// If the enabling refresh for a different product, or disabling refresh for (const auto& currentProviderManager : currentProviderManagers->second)
if (currentProviderManager->second != providerManager || !enabled) {
currentProviderManager->refreshCount_ -= 1;
// If the enabling refresh for a different product, or disabling
// refresh
if (!providerManagers.contains(currentProviderManager) || !enabled)
{ {
// Determine number of entries in the map for the current provider
// manager
auto currentProviderManagerCount = std::count_if(
refreshMap_.cbegin(),
refreshMap_.cend(),
[&](const auto& provider)
{ return provider.second == currentProviderManager->second; });
// If this is the last reference to the provider in the refresh map // If this is the last reference to the provider in the refresh map
if (currentProviderManagerCount == 1) if (currentProviderManager->refreshCount_ == 0)
{ {
// Disable current provider // Disable current provider
currentProviderManager->second->Disable(); currentProviderManager->Disable();
}
}
} }
// Dissociate uuid from current provider manager // Dissociate uuid from current provider managers
refreshMap_.erase(currentProviderManager); refreshMap_.erase(currentProviderManagers);
}
// If we are enabling a new provider manager
if (enabled) if (enabled)
{ {
// Associate uuid to providerManager // We are enabling provider managers
refreshMap_.emplace(uuid, providerManager);
}
}
}
else if (enabled)
{
// We are enabling a new provider manager
// Associate uuid to provider manager // Associate uuid to provider manager
refreshMap_.emplace(uuid, providerManager); refreshMap_.emplace(uuid, providerManagers);
for (const auto& providerManager : providerManagers)
{
providerManager->refreshCount_ += 1;
}
} }
// Release the refresh map mutex // Release the refresh map mutex
@ -751,15 +750,17 @@ void RadarProductManagerImpl::EnableRefresh(
// We have already handled a disable request by this point. If enabling, and // We have already handled a disable request by this point. If enabling, and
// the provider manager refresh isn't already enabled, enable it. // the provider manager refresh isn't already enabled, enable it.
if (enabled && providerManager->refreshEnabled_ != enabled)
{
providerManager->refreshEnabled_ = enabled;
if (enabled) if (enabled)
{ {
for (const auto& providerManager : providerManagers)
{
if (providerManager->refreshEnabled_ != enabled)
{
providerManager->refreshEnabled_ = enabled;
RefreshData(providerManager); RefreshData(providerManager);
} }
} }
}
} }
void RadarProductManagerImpl::RefreshData( void RadarProductManagerImpl::RefreshData(
@ -795,12 +796,10 @@ void RadarProductManagerImpl::RefreshDataSync(
// Level2 chunked data is updated quickly and uses a faster interval // Level2 chunked data is updated quickly and uses a faster interval
const std::chrono::milliseconds fastRetryInterval = const std::chrono::milliseconds fastRetryInterval =
providerManager == level2ChunksProviderManager_ ? providerManager->fastRefresh_ ? kFastRetryIntervalChunks_ :
kFastRetryIntervalChunks_ :
kFastRetryInterval_; kFastRetryInterval_;
const std::chrono::milliseconds slowRetryInterval = const std::chrono::milliseconds slowRetryInterval =
providerManager == level2ChunksProviderManager_ ? providerManager->fastRefresh_ ? kSlowRetryIntervalChunks_ :
kSlowRetryIntervalChunks_ :
kSlowRetryInterval_; kSlowRetryInterval_;
std::chrono::milliseconds interval = fastRetryInterval; std::chrono::milliseconds interval = fastRetryInterval;
@ -896,10 +895,13 @@ RadarProductManager::GetActiveVolumeTimes(
std::shared_lock refreshLock {p->refreshMapMutex_}; std::shared_lock refreshLock {p->refreshMapMutex_};
// For each entry in the refresh map (refresh is enabled) // For each entry in the refresh map (refresh is enabled)
for (auto& refreshEntry : p->refreshMap_) for (auto& refreshSet : p->refreshMap_)
{
for (const auto& refreshEntry : refreshSet.second)
{ {
// Add the provider for the current entry // Add the provider for the current entry
providers.insert(refreshEntry.second->provider_); providers.insert(refreshEntry->provider_);
}
} }
// Unlock the refresh map // Unlock the refresh map