Merge pull request #4927 from bykoianko/master-loading-traffic-for-routing

Requesting traffic info for routing mwm.
This commit is contained in:
ygorshenin 2016-12-13 17:17:45 +03:00 committed by GitHub
commit 7bf549cba1
2 changed files with 120 additions and 71 deletions

View file

@ -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(), ());

View file

@ -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.