Requesting traffic info for mwm under current possition and near current possition.

This commit is contained in:
Vladimir Byko-Ianko 2016-12-09 13:07:10 +03:00
parent 657bd88190
commit 5a89f88c03
2 changed files with 117 additions and 73 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"
@ -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<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;
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<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()
@ -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<MwmSet::MwmId> & 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<MwmSet::MwmId> activeMwms;
UniteActiveMwms(activeMwms);
size_t const activeMwmsSize = m_activeDrapeMwms.size();
if (m_currentCacheSizeBytes > m_maxCacheSizeBytes && m_mwmCache.size() > activeMwmsSize)
{
std::multimap<time_point<steady_clock>, 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);

View file

@ -86,34 +86,10 @@ private:
void OnTrafficDataResponse(traffic::TrafficInfo && info);
void OnTrafficRequestFailed(traffic::TrafficInfo && info);
void UpdateActiveMwms(m2::RectD const & rect, vector<MwmSet::MwmId> & lastMwmsByRect,
set<MwmSet::MwmId> & 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<df::DrapeEngine> m_drapeEngine;
atomic<int64_t> m_currentDataVersion;
// These fields have a flag of their initialization.
pair<MyPosition, bool> m_currentPosition = {MyPosition(), false};
pair<ScreenBase, bool> m_currentModelView = {ScreenBase(), false};
atomic<TrafficState> 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<MwmSet::MwmId> & activeMwms) const;
template <class F>
void ForEachActiveMwm(F && f) const
{
set<MwmSet::MwmId> activeMwms;
UniteActiveMwms(activeMwms);
for (MwmSet::MwmId const & mwmId : activeMwms)
f(mwmId);
}
GetMwmsByRectFn m_getMwmsByRectFn;
traffic::TrafficObserver & m_observer;
ref_ptr<df::DrapeEngine> m_drapeEngine;
atomic<int64_t> m_currentDataVersion;
// These fields have a flag of their initialization.
pair<MyPosition, bool> m_currentPosition = {MyPosition(), false};
pair<ScreenBase, bool> m_currentModelView = {ScreenBase(), false};
atomic<TrafficState> 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<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.