forked from organicmaps/organicmaps
Merge pull request #4927 from bykoianko/master-loading-traffic-for-routing
Requesting traffic info for routing mwm.
This commit is contained in:
commit
7bf549cba1
2 changed files with 120 additions and 71 deletions
|
@ -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"
|
||||
|
@ -33,7 +35,7 @@ TrafficManager::CacheEntry::CacheEntry()
|
|||
TrafficManager::CacheEntry::CacheEntry(time_point<steady_clock> const & requestTime)
|
||||
: m_isLoaded(false)
|
||||
, m_dataSize(0)
|
||||
, m_lastSeenTime(requestTime)
|
||||
, m_lastActiveTime(requestTime)
|
||||
, m_lastRequestTime(requestTime)
|
||||
, m_retriesCount(0)
|
||||
, m_isWaitingForResponse(true)
|
||||
|
@ -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,45 @@ void TrafficManager::Invalidate()
|
|||
UpdateMyPosition(m_currentPosition.first);
|
||||
}
|
||||
|
||||
void TrafficManager::UpdateActiveMwms(m2::RectD const & rect,
|
||||
vector<MwmSet::MwmId> & lastMwmsByRect,
|
||||
set<MwmSet::MwmId> & activeMwms)
|
||||
{
|
||||
auto mwms = m_getMwmsByRectFn(rect);
|
||||
if (lastMwmsByRect == mwms)
|
||||
return;
|
||||
lastMwmsByRect = mwms;
|
||||
|
||||
{
|
||||
lock_guard<mutex> 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.0;
|
||||
m_currentPosition = {myPosition, true /* initialized */};
|
||||
|
||||
if (!IsEnabled() || IsInvalidState())
|
||||
return;
|
||||
|
||||
m2::RectD const rect =
|
||||
MercatorBounds::RectByCenterXYAndSizeInMeters(myPosition.m_position, kSquareSideM / 2.0);
|
||||
// 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 +231,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<mutex> 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()
|
||||
|
@ -288,7 +302,7 @@ void TrafficManager::RequestTrafficData(MwmSet::MwmId const & mwmId, bool force)
|
|||
it->second.m_lastRequestTime = currentTime;
|
||||
}
|
||||
if (!force)
|
||||
it->second.m_lastSeenTime = currentTime;
|
||||
it->second.m_lastActiveTime = currentTime;
|
||||
}
|
||||
|
||||
if (needRequesting)
|
||||
|
@ -300,14 +314,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 +341,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 */);
|
||||
|
@ -361,7 +378,7 @@ void TrafficManager::OnTrafficDataResponse(traffic::TrafficInfo && info)
|
|||
size_t const dataSize = info.GetColoring().size() * kElementSize;
|
||||
m_currentCacheSizeBytes += (dataSize - it->second.m_dataSize);
|
||||
it->second.m_dataSize = dataSize;
|
||||
CheckCacheSize();
|
||||
ShrinkCacheToAllowableSize();
|
||||
}
|
||||
|
||||
UpdateState();
|
||||
|
@ -376,17 +393,27 @@ void TrafficManager::OnTrafficDataResponse(traffic::TrafficInfo && info)
|
|||
}
|
||||
}
|
||||
|
||||
void TrafficManager::CheckCacheSize()
|
||||
void TrafficManager::UniteActiveMwms(set<MwmSet::MwmId> & activeMwms) const
|
||||
{
|
||||
if (m_currentCacheSizeBytes > m_maxCacheSizeBytes && m_mwmCache.size() > m_activeMwms.size())
|
||||
activeMwms.insert(m_activeDrapeMwms.cbegin(), m_activeDrapeMwms.cend());
|
||||
activeMwms.insert(m_activeRoutingMwms.cbegin(), m_activeRoutingMwms.cend());
|
||||
}
|
||||
|
||||
void TrafficManager::ShrinkCacheToAllowableSize()
|
||||
{
|
||||
// Calculating number of different active mwms.
|
||||
set<MwmSet::MwmId> activeMwms;
|
||||
UniteActiveMwms(activeMwms);
|
||||
size_t const numActiveMwms = activeMwms.size();
|
||||
|
||||
if (m_currentCacheSizeBytes > m_maxCacheSizeBytes && m_mwmCache.size() > numActiveMwms)
|
||||
{
|
||||
std::multimap<time_point<steady_clock>, MwmSet::MwmId> seenTimings;
|
||||
for (auto const & mwmInfo : m_mwmCache)
|
||||
seenTimings.insert(make_pair(mwmInfo.second.m_lastSeenTime, mwmInfo.first));
|
||||
seenTimings.insert(make_pair(mwmInfo.second.m_lastActiveTime, mwmInfo.first));
|
||||
|
||||
auto itSeen = seenTimings.begin();
|
||||
while (m_currentCacheSizeBytes > m_maxCacheSizeBytes &&
|
||||
m_mwmCache.size() > m_activeMwms.size())
|
||||
while (m_currentCacheSizeBytes > m_maxCacheSizeBytes && m_mwmCache.size() > numActiveMwms)
|
||||
{
|
||||
ClearCache(itSeen->second);
|
||||
++itSeen;
|
||||
|
@ -438,7 +465,7 @@ void TrafficManager::UpdateState()
|
|||
bool expiredData = false;
|
||||
bool noData = false;
|
||||
|
||||
for (auto const & mwmId : m_activeMwms)
|
||||
for (MwmSet::MwmId const & mwmId : m_activeDrapeMwms)
|
||||
{
|
||||
auto it = m_mwmCache.find(mwmId);
|
||||
ASSERT(it != m_mwmCache.end(), ());
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "base/thread.hpp"
|
||||
|
||||
#include "std/algorithm.hpp"
|
||||
#include "std/atomic.hpp"
|
||||
#include "std/chrono.hpp"
|
||||
#include "std/map.hpp"
|
||||
|
@ -60,6 +61,7 @@ public:
|
|||
|
||||
TrafficManager(GetMwmsByRectFn const & getMwmsByRectFn, size_t maxCacheSizeBytes,
|
||||
traffic::TrafficObserver & observer);
|
||||
TrafficManager(TrafficManager && /* trafficManager */) = default;
|
||||
~TrafficManager();
|
||||
|
||||
void Teardown();
|
||||
|
@ -80,20 +82,45 @@ public:
|
|||
void OnMwmDelete(MwmSet::MwmId const & mwmId);
|
||||
|
||||
private:
|
||||
struct CacheEntry
|
||||
{
|
||||
CacheEntry();
|
||||
CacheEntry(time_point<steady_clock> const & requestTime);
|
||||
|
||||
bool m_isLoaded;
|
||||
size_t m_dataSize;
|
||||
|
||||
time_point<steady_clock> m_lastActiveTime;
|
||||
time_point<steady_clock> m_lastRequestTime;
|
||||
time_point<steady_clock> m_lastResponseTime;
|
||||
|
||||
int m_retriesCount;
|
||||
bool m_isWaitingForResponse;
|
||||
|
||||
traffic::TrafficInfo::Availability m_lastAvailability;
|
||||
};
|
||||
|
||||
void ThreadRoutine();
|
||||
bool WaitForRequest(vector<MwmSet::MwmId> & mwms);
|
||||
|
||||
void OnTrafficDataResponse(traffic::TrafficInfo && info);
|
||||
void OnTrafficRequestFailed(traffic::TrafficInfo && info);
|
||||
|
||||
private:
|
||||
/// \brief Updates |activeMwms| and request traffic data.
|
||||
/// \param rect is a rectangle covering a new active mwm set.
|
||||
/// \note |lastMwmsByRect|/|activeMwms| may be either |m_lastDrapeMwmsByRect/|m_activeDrapeMwms|
|
||||
/// or |m_lastRoutingMwmsByRect|/|m_activeRoutingMwms|.
|
||||
/// \note |m_mutex| is locked inside the method. So the method should be called without |m_mutex|.
|
||||
void UpdateActiveMwms(m2::RectD const & rect, vector<MwmSet::MwmId> & lastMwmsByRect,
|
||||
set<MwmSet::MwmId> & activeMwms);
|
||||
|
||||
// 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 ShrinkCacheToAllowableSize();
|
||||
|
||||
void UpdateState();
|
||||
void ChangeState(TrafficState newState);
|
||||
|
@ -101,6 +128,16 @@ private:
|
|||
bool IsInvalidState() const;
|
||||
bool IsEnabled() const;
|
||||
|
||||
void UniteActiveMwms(set<MwmSet::MwmId> & activeMwms) const;
|
||||
|
||||
template <class F>
|
||||
void ForEachActiveMwm(F && f) const
|
||||
{
|
||||
set<MwmSet::MwmId> activeMwms;
|
||||
UniteActiveMwms(activeMwms);
|
||||
for_each(activeMwms.begin(), activeMwms.end(), forward<F>(f));
|
||||
}
|
||||
|
||||
GetMwmsByRectFn m_getMwmsByRectFn;
|
||||
traffic::TrafficObserver & m_observer;
|
||||
|
||||
|
@ -114,24 +151,6 @@ private:
|
|||
atomic<TrafficState> m_state;
|
||||
TrafficStateChangedFn m_onStateChangedFn;
|
||||
|
||||
struct CacheEntry
|
||||
{
|
||||
CacheEntry();
|
||||
CacheEntry(time_point<steady_clock> const & requestTime);
|
||||
|
||||
bool m_isLoaded;
|
||||
size_t m_dataSize;
|
||||
|
||||
time_point<steady_clock> m_lastSeenTime;
|
||||
time_point<steady_clock> m_lastRequestTime;
|
||||
time_point<steady_clock> m_lastResponseTime;
|
||||
|
||||
int m_retriesCount;
|
||||
bool m_isWaitingForResponse;
|
||||
|
||||
traffic::TrafficInfo::Availability m_lastAvailability;
|
||||
};
|
||||
|
||||
size_t m_maxCacheSizeBytes;
|
||||
size_t m_currentCacheSizeBytes = 0;
|
||||
|
||||
|
@ -140,8 +159,11 @@ private:
|
|||
bool m_isRunning;
|
||||
condition_variable m_condition;
|
||||
|
||||
vector<MwmSet::MwmId> m_lastMwmsByRect;
|
||||
set<MwmSet::MwmId> m_activeMwms;
|
||||
vector<MwmSet::MwmId> m_lastDrapeMwmsByRect;
|
||||
set<MwmSet::MwmId> m_activeDrapeMwms;
|
||||
vector<MwmSet::MwmId> m_lastRoutingMwmsByRect;
|
||||
set<MwmSet::MwmId> 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.
|
||||
|
|
Loading…
Add table
Reference in a new issue