From 5a89f88c0380d8c8c6d903827d8f1195b650863e Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Fri, 9 Dec 2016 13:07:10 +0300 Subject: [PATCH] Requesting traffic info for mwm under current possition and near current possition. --- map/traffic_manager.cpp | 115 +++++++++++++++++++++++++--------------- map/traffic_manager.hpp | 75 ++++++++++++++++---------- 2 files changed, 117 insertions(+), 73 deletions(-) diff --git a/map/traffic_manager.cpp b/map/traffic_manager.cpp index 4e004245e3..d6d4f5479a 100644 --- a/map/traffic_manager.cpp +++ b/map/traffic_manager.cpp @@ -8,6 +8,8 @@ #include "indexer/ftypes_matcher.hpp" #include "indexer/scales.hpp" +#include "geometry/mercator.hpp" + #include "platform/platform.hpp" #include "3party/Alohalytics/src/alohalytics.h" @@ -120,8 +122,10 @@ void TrafficManager::Clear() { m_currentCacheSizeBytes = 0; m_mwmCache.clear(); - m_lastMwmsByRect.clear(); - m_activeMwms.clear(); + m_lastDrapeMwmsByRect.clear(); + m_lastRoutingMwmsByRect.clear(); + m_activeDrapeMwms.clear(); + m_activeRoutingMwms.clear(); m_requestedMwms.clear(); } @@ -168,7 +172,8 @@ void TrafficManager::Invalidate() if (!IsEnabled()) return; - m_lastMwmsByRect.clear(); + m_lastDrapeMwmsByRect.clear(); + m_lastRoutingMwmsByRect.clear(); if (m_currentModelView.second) UpdateViewport(m_currentModelView.first); @@ -176,6 +181,44 @@ void TrafficManager::Invalidate() UpdateMyPosition(m_currentPosition.first); } +void TrafficManager::UpdateActiveMwms(m2::RectD const & rect, + vector & lastMwmsByRect, + set & activeMwms) +{ + auto mwms = m_getMwmsByRectFn(rect); + if (lastMwmsByRect == mwms) + return; + lastMwmsByRect = mwms; + + { + lock_guard lock(m_mutex); + activeMwms.clear(); + for (auto const & mwm : mwms) + { + if (mwm.IsAlive()) + activeMwms.insert(mwm); + } + RequestTrafficData(); + } +} + +void TrafficManager::UpdateMyPosition(MyPosition const & myPosition) +{ + // Side of square around |myPosition|. Every mwm which is covered by the square + // will get traffic info. + double const kSquareSideM = 5000; + m_currentPosition = {myPosition, true /* initialized */}; + + if (!IsEnabled() || IsInvalidState()) + return; + + m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(myPosition.m_position, kSquareSideM); + // Request traffic. + UpdateActiveMwms(rect, m_lastRoutingMwmsByRect, m_activeRoutingMwms); + + // @TODO Do all routing stuff. +} + void TrafficManager::UpdateViewport(ScreenBase const & screen) { m_currentModelView = {screen, true /* initialized */}; @@ -187,37 +230,7 @@ void TrafficManager::UpdateViewport(ScreenBase const & screen) return; // Request traffic. - auto mwms = m_getMwmsByRectFn(screen.ClipRect()); - if (m_lastMwmsByRect == mwms) - return; - m_lastMwmsByRect = mwms; - - { - lock_guard lock(m_mutex); - - m_activeMwms.clear(); - for (auto const & mwm : mwms) - { - if (mwm.IsAlive()) - m_activeMwms.insert(mwm); - } - - RequestTrafficData(); - } -} - -void TrafficManager::UpdateMyPosition(MyPosition const & myPosition) -{ - m_currentPosition = {myPosition, true /* initialized */}; - - if (!IsEnabled() || IsInvalidState()) - return; - - // 1. Determine mwm's nearby "my position". - - // 2. Request traffic for this mwm's. - - // 3. Do all routing stuff. + UpdateActiveMwms(screen.ClipRect(), m_lastDrapeMwmsByRect, m_activeDrapeMwms); } void TrafficManager::ThreadRoutine() @@ -300,14 +313,16 @@ void TrafficManager::RequestTrafficData(MwmSet::MwmId const & mwmId, bool force) void TrafficManager::RequestTrafficData() { - if (m_activeMwms.empty() || !IsEnabled() || IsInvalidState()) - return; - - for (auto const & mwmId : m_activeMwms) + if ((m_activeDrapeMwms.empty() && m_activeRoutingMwms.empty()) + || !IsEnabled() || IsInvalidState()) { + return; + } + + ForEachActiveMwm([this](MwmSet::MwmId const & mwmId){ ASSERT(mwmId.IsAlive(), ()); RequestTrafficData(mwmId, false /* force */); - } + }); UpdateState(); } @@ -325,7 +340,8 @@ void TrafficManager::OnTrafficRequestFailed(traffic::TrafficInfo && info) if (info.GetAvailability() == traffic::TrafficInfo::Availability::Unknown && !it->second.m_isLoaded) { - if (m_activeMwms.find(info.GetMwmId()) != m_activeMwms.end()) + if (m_activeDrapeMwms.find(info.GetMwmId()) != m_activeDrapeMwms.cend() + || m_activeRoutingMwms.find(info.GetMwmId()) != m_activeRoutingMwms.cend()) { if (it->second.m_retriesCount < kMaxRetriesCount) RequestTrafficData(info.GetMwmId(), true /* force */); @@ -376,9 +392,20 @@ void TrafficManager::OnTrafficDataResponse(traffic::TrafficInfo && info) } } +void TrafficManager::UniteActiveMwms(set & activeMwms) const +{ + activeMwms.insert(m_activeDrapeMwms.cbegin(), m_activeDrapeMwms.cend()); + activeMwms.insert(m_activeRoutingMwms.cbegin(), m_activeRoutingMwms.cend()); +} + void TrafficManager::CheckCacheSize() { - if (m_currentCacheSizeBytes > m_maxCacheSizeBytes && m_mwmCache.size() > m_activeMwms.size()) + // Calculating number of different active mwms. + set activeMwms; + UniteActiveMwms(activeMwms); + size_t const activeMwmsSize = m_activeDrapeMwms.size(); + + if (m_currentCacheSizeBytes > m_maxCacheSizeBytes && m_mwmCache.size() > activeMwmsSize) { std::multimap, MwmSet::MwmId> seenTimings; for (auto const & mwmInfo : m_mwmCache) @@ -386,7 +413,7 @@ void TrafficManager::CheckCacheSize() auto itSeen = seenTimings.begin(); while (m_currentCacheSizeBytes > m_maxCacheSizeBytes && - m_mwmCache.size() > m_activeMwms.size()) + m_mwmCache.size() > activeMwmsSize) { ClearCache(itSeen->second); ++itSeen; @@ -438,7 +465,7 @@ void TrafficManager::UpdateState() bool expiredData = false; bool noData = false; - for (auto const & mwmId : m_activeMwms) + ForEachActiveMwm([&](MwmSet::MwmId const & mwmId) { auto it = m_mwmCache.find(mwmId); ASSERT(it != m_mwmCache.end(), ()); @@ -464,7 +491,7 @@ void TrafficManager::UpdateState() { networkError = true; } - } + }); if (networkError || maxPassedTime >= kNetworkErrorTimeout) ChangeState(TrafficState::NetworkError); diff --git a/map/traffic_manager.hpp b/map/traffic_manager.hpp index 82a913535f..f29f4e888d 100644 --- a/map/traffic_manager.hpp +++ b/map/traffic_manager.hpp @@ -86,34 +86,10 @@ private: void OnTrafficDataResponse(traffic::TrafficInfo && info); void OnTrafficRequestFailed(traffic::TrafficInfo && info); + void UpdateActiveMwms(m2::RectD const & rect, vector & lastMwmsByRect, + set & activeMwms); + private: - // This is a group of methods that haven't their own synchronization inside. - void RequestTrafficData(); - void RequestTrafficData(MwmSet::MwmId const & mwmId, bool force); - - void Clear(); - void ClearCache(MwmSet::MwmId const & mwmId); - void CheckCacheSize(); - - void UpdateState(); - void ChangeState(TrafficState newState); - - bool IsInvalidState() const; - bool IsEnabled() const; - - GetMwmsByRectFn m_getMwmsByRectFn; - traffic::TrafficObserver & m_observer; - - ref_ptr m_drapeEngine; - atomic m_currentDataVersion; - - // These fields have a flag of their initialization. - pair m_currentPosition = {MyPosition(), false}; - pair m_currentModelView = {ScreenBase(), false}; - - atomic m_state; - TrafficStateChangedFn m_onStateChangedFn; - struct CacheEntry { CacheEntry(); @@ -132,6 +108,44 @@ private: traffic::TrafficInfo::Availability m_lastAvailability; }; + // This is a group of methods that haven't their own synchronization inside. + void RequestTrafficData(); + void RequestTrafficData(MwmSet::MwmId const & mwmId, bool force); + + void Clear(); + void ClearCache(MwmSet::MwmId const & mwmId); + void CheckCacheSize(); + + void UpdateState(); + void ChangeState(TrafficState newState); + + bool IsInvalidState() const; + bool IsEnabled() const; + + void UniteActiveMwms(set & activeMwms) const; + + template + void ForEachActiveMwm(F && f) const + { + set activeMwms; + UniteActiveMwms(activeMwms); + for (MwmSet::MwmId const & mwmId : activeMwms) + f(mwmId); + } + + GetMwmsByRectFn m_getMwmsByRectFn; + traffic::TrafficObserver & m_observer; + + ref_ptr m_drapeEngine; + atomic m_currentDataVersion; + + // These fields have a flag of their initialization. + pair m_currentPosition = {MyPosition(), false}; + pair m_currentModelView = {ScreenBase(), false}; + + atomic m_state; + TrafficStateChangedFn m_onStateChangedFn; + size_t m_maxCacheSizeBytes; size_t m_currentCacheSizeBytes = 0; @@ -140,8 +154,11 @@ private: bool m_isRunning; condition_variable m_condition; - vector m_lastMwmsByRect; - set m_activeMwms; + vector m_lastDrapeMwmsByRect; + set m_activeDrapeMwms; + vector m_lastRoutingMwmsByRect; + set m_activeRoutingMwms; + // The ETag or entity tag is part of HTTP, the protocol for the World Wide Web. // It is one of several mechanisms that HTTP provides for web cache validation, // which allows a client to make conditional requests.