[traffic] Implement Clear()

Signed-off-by: mvglasow <michael -at- vonglasow.com>
This commit is contained in:
mvglasow
2025-06-07 14:41:24 +03:00
parent f30316d868
commit 488159e2f9
2 changed files with 117 additions and 53 deletions

View File

@@ -136,17 +136,38 @@ void TrafficManager::SetEnabled(bool enabled)
void TrafficManager::Clear()
{
// TODO no longer needed
{
std::lock_guard<std::mutex> lock(m_mutex);
LOG(LINFO, ("Messages in cache:", m_messageCache.size()));
LOG(LINFO, ("Feeds in queue:", m_feedQueue.size()));
LOG(LINFO, ("MWMs with coloring:", m_allMwmColoring.size()));
LOG(LINFO, ("MWM cache size:", m_mwmCache.size()));
LOG(LINFO, ("Clearing..."));
// TODO no longer needed
#ifdef traffic_dead_code
m_currentCacheSizeBytes = 0;
m_currentCacheSizeBytes = 0;
#endif
m_mwmCache.clear();
m_lastDrapeMwmsByRect.clear();
m_lastRoutingMwmsByRect.clear();
m_activeDrapeMwms.clear();
m_activeRoutingMwms.clear();
m_requestedMwms.clear();
m_trafficETags.clear();
m_messageCache.clear();
m_feedQueue.clear();
m_allMwmColoring.clear();
m_mwmCache.clear();
// TODO figure out which of the ones below we still need
m_lastDrapeMwmsByRect.clear();
m_lastRoutingMwmsByRect.clear();
// TODO clearing these breaks ForEachActiveMwm, can we leave them?
//m_activeDrapeMwms.clear();
//m_activeRoutingMwms.clear();
m_requestedMwms.clear();
m_trafficETags.clear();
LOG(LINFO, ("Messages in cache:", m_messageCache.size()));
LOG(LINFO, ("Feeds in queue:", m_feedQueue.size()));
LOG(LINFO, ("MWMs with coloring:", m_allMwmColoring.size()));
LOG(LINFO, ("MWM cache size:", m_mwmCache.size()));
}
OnTrafficDataUpdate();
}
void TrafficManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine)
@@ -450,21 +471,29 @@ void TrafficManager::DecodeFirstMessage()
m_feedQueue.erase(m_feedQueue.begin());
}
// check if message is actually newer
auto it = m_messageCache.find(message.m_id);
bool process = (it == m_messageCache.end());
if (!process)
process = (it->second.m_updateTime < message.m_updateTime);
if (!process)
{
LOG(LINFO, ("message", message.m_id, "is already in cache, skipping"));
return;
std::lock_guard<std::mutex> lock(m_mutex);
// check if message is actually newer
auto it = m_messageCache.find(message.m_id);
bool process = (it == m_messageCache.end());
if (!process)
process = (it->second.m_updateTime < message.m_updateTime);
if (!process)
{
LOG(LINFO, ("message", message.m_id, "is already in cache, skipping"));
return;
}
}
LOG(LINFO, (" ", message.m_id, ":", message));
m_traffDecoder->DecodeMessage(message);
// store message in cache
m_messageCache.insert_or_assign(message.m_id, message);
{
std::lock_guard<std::mutex> lock(m_mutex);
// store message in cache
m_messageCache.insert_or_assign(message.m_id, message);
}
// store message coloring in AllMwmColoring
// TODO trigger full cache processing if segments were removed or traffic has eased
traffxml::MergeMultiMwmColoring(message.m_decoded, m_allMwmColoring);
@@ -518,7 +547,9 @@ void TrafficManager::ThreadRoutine()
DecodeFirstMessage();
// set new coloring for MWMs
OnTrafficDataUpdate(m_allMwmColoring);
// `m_mutex` is obtained inside the method, no need to do it here
// TODO drop the argument, use class member inside method
OnTrafficDataUpdate();
// TODO no longer needed
#ifdef traffic_dead_code
@@ -688,15 +719,21 @@ void TrafficManager::OnTrafficRequestFailed(traffic::TrafficInfo && info)
}
#endif
void TrafficManager::OnTrafficDataUpdate(std::map<MwmSet::MwmId, traffic::TrafficInfo::Coloring> & trafficCache)
void TrafficManager::OnTrafficDataUpdate()
{
bool feedQueueEmpty = false;
{
std::lock_guard<std::mutex> lock(m_mutex);
feedQueueEmpty = m_feedQueue.empty();
}
// Whether to notify the Drape engine of the update.
bool notifyDrape = (m_feedQueue.empty());
bool notifyDrape = (feedQueueEmpty);
// Whether to notify the observer of the update.
bool notifyObserver = (m_feedQueue.empty());
bool notifyObserver = (feedQueueEmpty);
if (!m_feedQueue.empty())
if (!feedQueueEmpty)
{
auto const currentTime = steady_clock::now();
auto const drapeAge = currentTime - m_lastDrapeUpdate;
@@ -720,13 +757,14 @@ void TrafficManager::OnTrafficDataUpdate(std::map<MwmSet::MwmId, traffic::Traffi
* The remainder of the loop is from OnTrafficDataResponse(traffic::TrafficInfo &&), with some modifications
* (deciding whether to notify a component and managing timestamps is original code)
*/
ForEachActiveMwm([this, trafficCache, notifyDrape, notifyObserver](MwmSet::MwmId const & mwmId) {
ASSERT(mwmId.IsAlive(), ());
auto tcit = trafficCache.find(mwmId);
if (tcit != trafficCache.end())
{
std::lock_guard<std::mutex> lock(m_mutex);
// TODO do this for each MWM, active or not
ForEachActiveMwm([this, notifyDrape, notifyObserver](MwmSet::MwmId const & mwmId) {
std::lock_guard<std::mutex> lock(m_mutex);
ASSERT(mwmId.IsAlive(), ());
auto tcit = m_allMwmColoring.find(mwmId);
if (tcit != m_allMwmColoring.end())
{
traffic::TrafficInfo::Coloring coloring = tcit->second;
LOG(LINFO, ("Setting new coloring for", mwmId, "with", coloring.size(), "entries"));
traffic::TrafficInfo info(mwmId, std::move(coloring));
@@ -758,6 +796,24 @@ void TrafficManager::OnTrafficDataUpdate(std::map<MwmSet::MwmId, traffic::Traffi
}
}
}
else
{
LOG(LINFO, ("Removing coloring for", mwmId));
if (notifyDrape)
{
m_drapeEngine.SafeCall(&df::DrapeEngine::ClearTrafficCache,
static_cast<MwmSet::MwmId const &>(mwmId));
m_lastDrapeUpdate = steady_clock::now();
}
if (notifyObserver)
{
// Update traffic colors for routing.
m_observer.OnTrafficInfoRemoved(mwmId);
m_lastObserverUpdate = steady_clock::now();
}
}
});
}

View File

@@ -215,6 +215,26 @@ public:
*/
void Push(traffxml::TraffFeed feed);
/**
* @brief Clears the entire traffic cache.
*
* This is currently called when the traffic manager is enabled or disabled.
*
* The old MWM traffic architecture was somewhat liberal in clearing its cache and re-fetching
* traffic data. This was possible because data was pre-processed and required no processing
* beyond deserialization, whereas TraFF data is more expensive to recreate. Also, the old
* architecture lacked any explicit notion of expiration; the app decided that data was to be
* considered stale after a certain period of time. TraFF, in contrast, has an explicit expiration
* time for each message, which can be anywhere from a few minutes to several weeks or months.
* Messages that have expired get deleted individually.
* For this reason, the TraFF message cache should not be cleared out under normal conditions
* (the main exception being tests).
*
* @todo Currently not implemented for TraFF; implement it for test purposes but do not call when
* the enabled state changes.
*/
void Clear();
private:
/**
* @brief Holds information about pending or previous traffic requests pertaining to an MWM.
@@ -365,9 +385,9 @@ private:
/**
* @brief Processes new traffic data.
*
* @param trafficCache The new per-MWM colorings (preprocessed traffic information).
* The new per-MWM colorings (preprocessed traffic information) are taken from `m_allMmColoring`.
*/
void OnTrafficDataUpdate(std::map<MwmSet::MwmId, traffic::TrafficInfo::Coloring> &trafficCache);
void OnTrafficDataUpdate();
// TODO no longer needed
#ifdef traffic_dead_code
@@ -444,26 +464,6 @@ private:
*/
void RequestTrafficData(MwmSet::MwmId const & mwmId, bool force);
/**
* @brief Clears the entire traffic cache.
*
* This is currently called when the traffic manager is enabled or disabled.
*
* The old MWM traffic architecture was somewhat liberal in clearing its cache and re-fetching
* traffic data. This was possible because data was pre-processed and required no processing
* beyond deserialization, whereas TraFF data is more expensive to recreate. Also, the old
* architecture lacked any explicit notion of expiration; the app decided that data was to be
* considered stale after a certain period of time. TraFF, in contrast, has an explicit expiration
* time for each message, which can be anywhere from a few minutes to several weeks or months.
* Messages that have expired get deleted individually.
* For this reason, the TraFF message cache should not be cleared out under normal conditions
* (the main exception being tests).
*
* @todo Currently not implemented for TraFF; implement it for test purposes but do not call when
* the enabled state changes.
*/
void Clear();
/**
* @brief Removes traffic data for one specific MWM from the cache.
*
@@ -575,7 +575,7 @@ private:
* * Invalidate(), clears the vector but not the set.
* * UpdateActiveMwms(), uses the vector to detect changes. If so, it updates both vector and set.
*
* Clear() clears both the set and the vector.
* Clear() clears both the set and the vector. (Clearing the set is currently disabled as it breaks ForEachActiveMwm.)
*/
std::vector<MwmSet::MwmId> m_lastDrapeMwmsByRect;
std::set<MwmSet::MwmId> m_activeDrapeMwms;
@@ -647,6 +647,10 @@ private:
* @brief Cache of all currently active TraFF messages.
*
* Keys are message IDs, values are messages.
*
* Threads must lock `m_mutex` before accessing `m_messageCache`, as access can happen from
* multiple threads (messages are added by the worker thread, `Clear()` can be called from the UI
* thread).
*/
std::map<std::string, traffxml::TraffMessage> m_messageCache;
@@ -659,6 +663,10 @@ private:
/**
* @brief Map between MWM IDs and their colorings.
*
* Threads must lock `m_mutex` before accessing `m_allMwmColoring`, as access can happen from
* multiple threads (messages are added by the worker thread, `Clear()` can be called from the UI
* thread).
*/
std::map<MwmSet::MwmId, traffic::TrafficInfo::Coloring> m_allMwmColoring;
};