Added Hyper Local Ads (HLA) manager

This commit is contained in:
r.kuznetsov 2017-03-30 18:41:45 +03:00
parent 363dbb83ef
commit 454ba88167
16 changed files with 556 additions and 30 deletions

1
.gitignore vendored
View file

@ -16,6 +16,7 @@ data/*.mwm.osm2ft
data/*.mwm.routing
data/*.mwmmeta
data/[!W]*.mwm
data/hla*.dat
# Compiled Python
*.pyc

View file

@ -440,7 +440,13 @@ void FilesContainerW::Write(ModelReaderPtr reader, Tag const & tag)
void FilesContainerW::Write(vector<char> const & buffer, Tag const & tag)
{
if (!buffer.empty())
GetWriter(tag).Write(&buffer[0], buffer.size());
GetWriter(tag).Write(buffer.data(), buffer.size());
}
void FilesContainerW::Write(vector<uint8_t> const & buffer, Tag const & tag)
{
if (!buffer.empty())
GetWriter(tag).Write(buffer.data(), buffer.size());
}
void FilesContainerW::Finish()

View file

@ -238,6 +238,7 @@ public:
void Write(string const & fPath, Tag const & tag);
void Write(ModelReaderPtr reader, Tag const & tag);
void Write(vector<char> const & buffer, Tag const & tag);
void Write(vector<uint8_t> const & buffer, Tag const & tag);
void Finish();

View file

@ -428,9 +428,9 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
case Message::SetCustomSymbols:
case Message::AddCustomSymbols:
{
ref_ptr<SetCustomSymbolsMessage> msg = message;
ref_ptr<AddCustomSymbolsMessage> msg = message;
CustomSymbols customSymbols = msg->AcceptSymbols();
std::vector<FeatureID> features;
for (auto const & symbol : customSymbols)
@ -442,6 +442,20 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
case Message::RemoveCustomSymbols:
{
ref_ptr<RemoveCustomSymbolsMessage> msg = message;
std::vector<FeatureID> leftoverIds;
if (msg->NeedRemoveAll())
m_readManager->RemoveAllCustomSymbols();
else
m_readManager->RemoveCustomSymbols(msg->GetMwmId(), leftoverIds);
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<UpdateCustomSymbolsMessage>(std::move(leftoverIds)),
MessagePriority::Normal);
break;
}
default:
ASSERT(false, ());
break;

View file

@ -580,10 +580,24 @@ void DrapeEngine::RunScenario(ScenarioManager::ScenarioData && scenarioData,
manager->RunScenario(move(scenarioData), onStartFn, onFinishFn);
}
void DrapeEngine::SetCustomSymbols(CustomSymbols && symbols)
void DrapeEngine::AddCustomSymbols(CustomSymbols && symbols)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<SetCustomSymbolsMessage>(std::move(symbols)),
make_unique_dp<AddCustomSymbolsMessage>(std::move(symbols)),
MessagePriority::Normal);
}
void DrapeEngine::RemoveCustomSymbols(MwmSet::MwmId const & mwmId)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<RemoveCustomSymbolsMessage>(mwmId),
MessagePriority::Normal);
}
void DrapeEngine::RemoveAllCustomSymbols()
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<RemoveCustomSymbolsMessage>(),
MessagePriority::Normal);
}

View file

@ -192,7 +192,9 @@ public:
ScenarioManager::ScenarioCallback const & onStartFn,
ScenarioManager::ScenarioCallback const & onFinishFn);
void SetCustomSymbols(CustomSymbols && symbols);
void AddCustomSymbols(CustomSymbols && symbols);
void RemoveCustomSymbols(MwmSet::MwmId const & mwmId);
void RemoveAllCustomSymbols();
private:
void AddUserEvent(drape_ptr<UserEvent> && e);

View file

@ -75,7 +75,8 @@ public:
DrapeApiAddLines,
DrapeApiRemove,
DrapeApiFlush,
SetCustomSymbols,
AddCustomSymbols,
RemoveCustomSymbols,
UpdateCustomSymbols,
};

View file

@ -1151,14 +1151,14 @@ private:
TProperties m_properties;
};
class SetCustomSymbolsMessage : public Message
class AddCustomSymbolsMessage : public Message
{
public:
explicit SetCustomSymbolsMessage(CustomSymbols && symbols)
explicit AddCustomSymbolsMessage(CustomSymbols && symbols)
: m_symbols(std::move(symbols))
{}
Type GetType() const override { return Message::SetCustomSymbols; }
Type GetType() const override { return Message::AddCustomSymbols; }
CustomSymbols && AcceptSymbols() { return std::move(m_symbols); }
@ -1166,6 +1166,23 @@ private:
CustomSymbols m_symbols;
};
class RemoveCustomSymbolsMessage : public Message
{
public:
RemoveCustomSymbolsMessage() = default;
explicit RemoveCustomSymbolsMessage(MwmSet::MwmId const & mwmId)
: m_mwmId(mwmId), m_removeAll(false)
{}
Type GetType() const override { return Message::RemoveCustomSymbols; }
bool NeedRemoveAll() const { return m_removeAll; }
MwmSet::MwmId const & GetMwmId() const { return m_mwmId; }
private:
MwmSet::MwmId m_mwmId;
bool m_removeAll = true;
};
class UpdateCustomSymbolsMessage : public Message
{
public:

View file

@ -280,18 +280,36 @@ void ReadManager::SetTrafficEnabled(bool trafficEnabled)
}
}
void ReadManager::UpdateCustomSymbols(CustomSymbols && symbols)
void ReadManager::UpdateCustomSymbols(CustomSymbols const & symbols)
{
auto customSymbolsContext = std::make_shared<CustomSymbolsContext>(std::move(symbols));
CustomSymbols currentSymbols = m_customSymbolsContext ? m_customSymbolsContext->m_symbols :
CustomSymbols();
for (auto const & s : symbols)
currentSymbols[s.first] = s.second;
m_customSymbolsContext = std::make_shared<CustomSymbolsContext>(std::move(currentSymbols));
}
#if !defined(OMIM_OS_LINUX)
std::atomic_exchange(&m_customSymbolsContext, customSymbolsContext);
#else
void ReadManager::RemoveCustomSymbols(MwmSet::MwmId const & mwmId, std::vector<FeatureID> & leftoverIds)
{
if (!m_customSymbolsContext)
return;
CustomSymbols currentSymbols;
leftoverIds.reserve(m_customSymbolsContext->m_symbols.size());
for (auto const & s : m_customSymbolsContext->m_symbols)
{
lock_guard<mutex> guard(m_customSymbolsContextMutex);
std::swap(m_customSymbolsContext, customSymbolsContext);
if (s.first.m_mwmId != mwmId)
{
currentSymbols.insert(std::make_pair(s.first, s.second));
leftoverIds.push_back(s.first);
}
}
#endif
m_customSymbolsContext = std::make_shared<CustomSymbolsContext>(std::move(currentSymbols));
}
void ReadManager::RemoveAllCustomSymbols()
{
m_customSymbolsContext = std::make_shared<CustomSymbolsContext>(CustomSymbols());
}
} // namespace df

View file

@ -43,7 +43,9 @@ public:
void SetTrafficEnabled(bool trafficEnabled);
void UpdateCustomSymbols(CustomSymbols && symbols);
void UpdateCustomSymbols(CustomSymbols const & symbols);
void RemoveCustomSymbols(MwmSet::MwmId const & mwmId, std::vector<FeatureID> & leftoverIds);
void RemoveAllCustomSymbols();
static uint32_t ReadCount();
@ -53,7 +55,6 @@ private:
void PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr<dp::TextureManager> texMng);
private:
ref_ptr<ThreadsCommutator> m_commutator;
MapDataProvider & m_model;
@ -88,13 +89,6 @@ private:
CustomSymbolsContextPtr m_customSymbolsContext;
// TODO (@y): unfortunately on Debian Jessie libstdc++ does not
// support atomic_exchange for shared pointers, so mutex is used
// instead. Get rid of this as soon as new libstdc++ is released.
#if defined(OMIM_OS_LINUX)
mutex m_customSymbolsContextMutex;
#endif
void CancelTileInfo(shared_ptr<TileInfo> const & tileToCancel);
void ClearTileInfo(shared_ptr<TileInfo> const & tileToClear);
void IncreaseCounter(int value);

View file

@ -43,6 +43,8 @@ set(
gps_track.hpp
gps_tracker.cpp
gps_tracker.hpp
hla_manager.cpp
hla_manager.hpp
mwm_url.cpp
mwm_url.hpp
place_page_info.cpp

View file

@ -276,6 +276,11 @@ TrafficManager & Framework::GetTrafficManager()
return m_trafficManager;
}
HLAManager & Framework::GetHLAManager()
{
return m_hlaManager;
}
bool Framework::IsTrackingReporterEnabled() const
{
if (m_currentRouterType != routing::RouterType::Vehicle)
@ -309,6 +314,7 @@ void Framework::OnViewportChanged(ScreenBase const & screen)
m_currentModelView = screen;
m_trafficManager.UpdateViewport(m_currentModelView);
m_hlaManager.UpdateViewport(m_currentModelView);
if (m_viewportChanged != nullptr)
m_viewportChanged(screen);
@ -393,6 +399,7 @@ Framework::Framework()
, m_trafficManager(bind(&Framework::GetMwmsByRect, this, _1), kMaxTrafficCacheSizeBytes,
// Note. |m_routingSession| should be declared before |m_trafficManager|.
m_routingSession)
, m_hlaManager(bind(&Framework::GetMwmsByRect, this, _1), bind(&Framework::GetMwmIdByName, this, _1))
, m_displacementModeManager([this](bool show) {
int const mode = show ? dp::displacement::kHotelMode : dp::displacement::kDefaultMode;
CallDrapeFunction(bind(&df::DrapeEngine::SetDisplacementMode, _1, mode));
@ -499,6 +506,7 @@ Framework::Framework()
Framework::~Framework()
{
m_trafficManager.Teardown();
m_hlaManager.Teardown();
DestroyDrapeEngine();
m_model.SetOnMapDeregisteredCallback(nullptr);
}
@ -615,6 +623,7 @@ void Framework::OnCountryFileDownloaded(storage::TCountryId const & countryId, s
rect = id.GetInfo()->m_limitRect;
}
m_trafficManager.Invalidate();
m_hlaManager.OnDownloadCountry(countryId);
InvalidateRect(rect);
m_searchEngine->ClearCaches();
}
@ -639,6 +648,7 @@ bool Framework::OnCountryFileDelete(storage::TCountryId const & countryId, stora
m_model.DeregisterMap(platform::CountryFile(countryId));
deferredDelete = true;
m_trafficManager.OnMwmDelete(mwmId);
m_hlaManager.OnDeleteCountry(countryId);
}
InvalidateRect(rect);
@ -1785,6 +1795,7 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> contextFactory,
m_drapeApi.SetEngine(make_ref(m_drapeEngine));
m_trafficManager.SetDrapeEngine(make_ref(m_drapeEngine));
m_hlaManager.SetDrapeEngine(make_ref(m_drapeEngine));
benchmark::RunGraphicsBenchmark(this);
}
@ -1821,6 +1832,7 @@ void Framework::DestroyDrapeEngine()
{
m_drapeApi.SetEngine(nullptr);
m_trafficManager.Teardown();
m_hlaManager.Teardown();
GpsTracker::Instance().Disconnect();
m_drapeEngine.reset();
}
@ -3432,7 +3444,7 @@ void Framework::VisualizeRoadsInRect(m2::RectD const & rect)
}, kScale);
}
vector<MwmSet::MwmId> Framework::GetMwmsByRect(m2::RectD const & rect)
vector<MwmSet::MwmId> Framework::GetMwmsByRect(m2::RectD const & rect) const
{
vector<MwmSet::MwmId> result;
if (!m_infoGetter)
@ -3440,7 +3452,12 @@ vector<MwmSet::MwmId> Framework::GetMwmsByRect(m2::RectD const & rect)
auto countryIds = m_infoGetter->GetRegionsCountryIdByRect(rect);
for (auto const & countryId : countryIds)
result.push_back(m_model.GetIndex().GetMwmIdByCountryFile(platform::CountryFile(countryId)));
result.push_back(GetMwmIdByName(countryId));
return result;
}
MwmSet::MwmId Framework::GetMwmIdByName(std::string const & name) const
{
return m_model.GetIndex().GetMwmIdByCountryFile(platform::CountryFile(name));
}

View file

@ -6,6 +6,7 @@
#include "map/city_finder.hpp"
#include "map/displacement_mode_manager.hpp"
#include "map/feature_vec_model.hpp"
#include "map/hla_manager.hpp"
#include "map/mwm_url.hpp"
#include "map/place_page_info.hpp"
#include "map/track.hpp"
@ -176,6 +177,8 @@ protected:
TrafficManager m_trafficManager;
HLAManager m_hlaManager;
/// This function will be called by m_storage when latest local files
/// is downloaded.
void OnCountryFileDownloaded(storage::TCountryId const & countryId, storage::Storage::TLocalFilePtr const localFile);
@ -369,7 +372,8 @@ public:
/// Guarantees that listener is called in the main thread context.
void SetCurrentCountryChangedListener(TCurrentCountryChanged const & listener);
vector<MwmSet::MwmId> GetMwmsByRect(m2::RectD const & rect);
vector<MwmSet::MwmId> GetMwmsByRect(m2::RectD const & rect) const;
MwmSet::MwmId GetMwmIdByName(std::string const & name) const;
private:
struct TapEvent
@ -789,6 +793,8 @@ public:
TrafficManager & GetTrafficManager();
HLAManager & GetHLAManager();
bool LoadTrafficEnabled();
void SaveTrafficEnabled(bool trafficEnabled);

350
map/hla_manager.cpp Normal file
View file

@ -0,0 +1,350 @@
#include "map/hla_manager.hpp"
#include "drape_frontend/drape_engine.hpp"
#include "drape_frontend/visual_params.hpp"
#include "indexer/scales.hpp"
#include "platform/http_client.hpp"
#include "platform/platform.hpp"
#include "coding/file_container.hpp"
#include "coding/file_name_utils.hpp"
namespace
{
std::string const kCampaignFile = "hla_campaigns.dat";
std::string const kExpirationFile = "hla_expiration.dat";
auto constexpr kWWanUpdateTimeout = std::chrono::hours(12);
std::vector<uint8_t> SerializeTimestamp(std::chrono::steady_clock::time_point ts)
{
long hours = std::chrono::duration_cast<std::chrono::hours>(ts.time_since_epoch()).count();
std::vector<uint8_t> result;
MemWriter<decltype(result)> writer(result);
writer.Write(&hours, sizeof(hours));
return result;
}
std::chrono::steady_clock::time_point DeserializeTimestamp(ModelReaderPtr const & reader)
{
ASSERT_EQUAL(reader.Size(), sizeof(long), ());
std::vector<uint8_t> bytes(reader.Size());
reader.Read(0, bytes.data(), bytes.size());
MemReaderWithExceptions memReader(bytes.data(), bytes.size());
ReaderSource<decltype(memReader)> src(memReader);
long hours = ReadPrimitiveFromSource<long>(src);
return std::chrono::steady_clock::time_point(std::chrono::hours(hours));
}
std::string GetPath(std::string const & fileName)
{
return my::JoinFoldersToPath(GetPlatform().WritableDir(), fileName);
}
} // namespace
HLAManager::HLAManager(GetMwmsByRectFn const & getMwmsByRectFn,
GetMwmIdByName const & getMwmIdByName)
: m_getMwmsByRectFn(getMwmsByRectFn)
, m_getMwmIdByNameFn(getMwmIdByName)
, m_thread(&HLAManager::ThreadRoutine, this)
{
CHECK(m_getMwmsByRectFn != nullptr, ());
CHECK(m_getMwmIdByNameFn != nullptr, ());
}
HLAManager::~HLAManager()
{
#ifdef DEBUG
{
std::lock_guard<std::mutex> lock(m_mutex);
ASSERT(!m_isRunning, ());
}
#endif
}
void HLAManager::Teardown()
{
{
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_isRunning)
return;
m_isRunning = false;
}
m_condition.notify_one();
m_thread.join();
}
void HLAManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine)
{
m_drapeEngine = engine;
{
std::lock_guard<std::mutex> lock(m_symbolsCacheMutex);
if (!m_symbolsCache.empty())
m_drapeEngine->AddCustomSymbols(std::move(m_symbolsCache));
}
}
void HLAManager::UpdateViewport(ScreenBase const & screen)
{
auto connectionStatus = GetPlatform().ConnectionStatus();
if (connectionStatus == Platform::EConnectionType::CONNECTION_NONE ||
df::GetZoomLevel(screen.GetScale()) <= scales::GetUpperWorldScale())
{
return;
}
std::vector<std::string> requestedCampaigns;
auto mwms = m_getMwmsByRectFn(screen.ClipRect());
if (mwms.empty())
return;
// Request HLA campaigns.
{
std::lock_guard<std::mutex> lock(m_mutex);
for (auto const & mwm : mwms)
{
auto info = mwm.GetInfo();
if (!info)
continue;
std::string const & mwmName = info->GetCountryName();
auto campaignIt = m_campaigns.find(mwmName);
if (campaignIt == m_campaigns.end())
{
requestedCampaigns.push_back(mwmName);
continue;
}
// If a campaign has not been requested from server this session.
if (!campaignIt->second)
{
auto const it = m_expiration.find(mwmName);
bool needUpdateByTimeout = (connectionStatus == Platform::EConnectionType::CONNECTION_WIFI);
if (!needUpdateByTimeout && it != m_expiration.end())
{
auto const currentTime = std::chrono::steady_clock::now();
needUpdateByTimeout = (currentTime - it->second) > kWWanUpdateTimeout;
}
if (needUpdateByTimeout || it == m_expiration.end())
requestedCampaigns.push_back(mwmName);
}
}
if (!requestedCampaigns.empty())
{
m_requestedCampaigns.reserve(m_requestedCampaigns.size() + requestedCampaigns.size());
for (auto const & campaign : requestedCampaigns)
m_requestedCampaigns.push_back(std::make_pair(m_getMwmIdByNameFn(campaign), RequestType::Download));
m_condition.notify_one();
}
}
}
void HLAManager::ThreadRoutine()
{
std::string const campaignFile = GetPath(kCampaignFile);
std::string const expirationFile = GetPath(kExpirationFile);
// Read persistence data (expiration file must be read the first).
ReadExpirationFile(expirationFile);
ReadCampaignFile(campaignFile);
std::vector<Request> campaignMwms;
while (WaitForRequest(campaignMwms))
{
try
{
FilesContainerW campaignsContainer(campaignFile, FileWriter::OP_WRITE_EXISTING);
FilesContainerW expirationContainer(expirationFile, FileWriter::OP_WRITE_EXISTING);
for (auto const & mwm : campaignMwms)
{
if (!mwm.first.IsAlive())
continue;
std::string const countryName = mwm.first.GetInfo()->GetCountryName();
if (mwm.second == RequestType::Download)
{
// Download campaign data from server.
std::vector<uint8_t> rawData = DownloadCampaign(mwm.first);
if (rawData.empty())
continue;
// Save data persistently.
campaignsContainer.Write(rawData, countryName);
auto ts = std::chrono::steady_clock::now();
expirationContainer.Write(SerializeTimestamp(ts), countryName);
// Update run-time data.
{
std::lock_guard<std::mutex> lock(m_mutex);
m_campaigns[countryName] = true;
m_expiration[countryName] = ts;
}
// Deserialize and send data to rendering.
auto symbols = DeserializeCampaign(std::move(rawData), ts);
if (symbols.empty())
DeleteSymbolsFromRendering(mwm.first);
else
SendSymbolsToRendering(std::move(symbols));
}
else if (mwm.second == RequestType::Delete)
{
campaignsContainer.DeleteSection(countryName);
expirationContainer.DeleteSection(countryName);
DeleteSymbolsFromRendering(mwm.first);
}
}
campaignsContainer.Finish();
expirationContainer.Finish();
}
catch (RootException const & ex)
{
LOG(LWARNING, (ex.Msg()));
}
campaignMwms.clear();
}
}
bool HLAManager::WaitForRequest(std::vector<Request> & campaignMwms)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock, [this] {return !m_isRunning || !m_requestedCampaigns.empty();});
if (!m_isRunning)
return false;
if (!m_requestedCampaigns.empty())
campaignMwms.swap(m_requestedCampaigns);
return true;
}
void HLAManager::OnDownloadCountry(std::string const & countryName)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_campaigns.erase(countryName);
m_expiration.erase(countryName);
}
void HLAManager::OnDeleteCountry(std::string const & countryName)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_campaigns.erase(countryName);
m_expiration.erase(countryName);
m_requestedCampaigns.push_back(std::make_pair(m_getMwmIdByNameFn(countryName), RequestType::Delete));
m_condition.notify_one();
}
string HLAManager::MakeRemoteURL(MwmSet::MwmId const &mwmId) const
{
// TODO: build correct URL after server completion.
return "http://172.27.15.68/campaigns.data";
}
std::vector<uint8_t> HLAManager::DownloadCampaign(MwmSet::MwmId const & mwmId) const
{
platform::HttpClient request(MakeRemoteURL(mwmId));
if (!request.RunHttpRequest() || request.ErrorCode() != 200)
return std::vector<uint8_t>();
string const & response = request.ServerResponse();
return std::vector<uint8_t>(response.cbegin(), response.cend());
}
df::CustomSymbols HLAManager::DeserializeCampaign(std::vector<uint8_t> && rawData,
std::chrono::steady_clock::time_point timestamp)
{
df::CustomSymbols symbols;
// TODO: Deserialize campaign.
// TODO: Filter by timestamp.
// TEMP!
//auto mwmId = m_getMwmIdByNameFn("Russia_Moscow");
//symbols.insert(std::make_pair(FeatureID(mwmId, 371323), df::CustomSymbol("test-m", true)));
//symbols.insert(std::make_pair(FeatureID(mwmId, 371363), df::CustomSymbol("test-m", true)));
//symbols.insert(std::make_pair(FeatureID(mwmId, 373911), df::CustomSymbol("test-m", true)));
return symbols;
}
void HLAManager::ReadExpirationFile(std::string const & expirationFile)
{
if (!GetPlatform().IsFileExistsByFullPath(expirationFile))
{
FilesContainerW f(expirationFile);
return;
}
try
{
std::lock_guard<std::mutex> lock(m_mutex);
FilesContainerR expirationContainer(expirationFile);
expirationContainer.ForEachTag([this, &expirationContainer](FilesContainerR::Tag const & tag)
{
m_expiration[tag] = DeserializeTimestamp(expirationContainer.GetReader(tag));
});
}
catch (Reader::Exception const & ex)
{
LOG(LWARNING, ("Error reading file:", expirationFile, ex.Msg()));
}
}
void HLAManager::ReadCampaignFile(std::string const & campaignFile)
{
if (!GetPlatform().IsFileExistsByFullPath(campaignFile))
{
FilesContainerW f(campaignFile);
return;
}
try
{
std::lock_guard<std::mutex> lock(m_mutex);
df::CustomSymbols allSymbols;
FilesContainerR campaignContainer(campaignFile);
campaignContainer.ForEachTag([this, &campaignContainer, &allSymbols](FilesContainerR::Tag const & tag)
{
auto const & reader = campaignContainer.GetReader(tag);
std::vector<uint8_t> rawData(reader.Size());
reader.Read(0, rawData.data(), rawData.size());
m_campaigns[tag] = false;
ASSERT(m_expiration.find(tag) != m_expiration.end(), ());
auto ts = m_expiration[tag];
auto symbols = DeserializeCampaign(std::move(rawData), ts);
allSymbols.insert(symbols.begin(), symbols.end());
});
SendSymbolsToRendering(std::move(allSymbols));
}
catch (Reader::Exception const & ex)
{
LOG(LWARNING, ("Error reading file:", campaignFile, ex.Msg()));
}
}
void HLAManager::SendSymbolsToRendering(df::CustomSymbols && symbols)
{
if (m_drapeEngine == nullptr)
{
std::lock_guard<std::mutex> lock(m_symbolsCacheMutex);
m_symbolsCache.insert(symbols.begin(), symbols.end());
return;
}
m_drapeEngine->AddCustomSymbols(std::move(symbols));
}
void HLAManager::DeleteSymbolsFromRendering(MwmSet::MwmId const & mwmId)
{
if (m_drapeEngine != nullptr)
m_drapeEngine->RemoveCustomSymbols(mwmId);
}

81
map/hla_manager.hpp Normal file
View file

@ -0,0 +1,81 @@
#pragma once
#include "drape_frontend/custom_symbol.hpp"
#include "drape/pointers.hpp"
#include "geometry/rect2d.hpp"
#include "geometry/screenbase.hpp"
#include "indexer/index.hpp"
#include "indexer/mwm_set.hpp"
#include "base/thread.hpp"
#include <chrono>
#include <map>
#include <mutex>
#include <string>
#include <vector>
namespace df
{
class DrapeEngine;
} // namespace df
// Hyper Local Ads (HLA) manager.
class HLAManager final
{
public:
using GetMwmsByRectFn = function<std::vector<MwmSet::MwmId>(m2::RectD const &)>;
using GetMwmIdByName = function<MwmSet::MwmId(std::string const &)>;
HLAManager(GetMwmsByRectFn const & getMwmsByRectFn, GetMwmIdByName const & getMwmIdByName);
HLAManager(HLAManager && /* hlaManager */) = default;
~HLAManager();
void Teardown();
void SetDrapeEngine(ref_ptr<df::DrapeEngine> engine);
void UpdateViewport(ScreenBase const & screen);
void OnDownloadCountry(std::string const & countryName);
void OnDeleteCountry(std::string const & countryName);
private:
enum class RequestType
{
Download,
Delete
};
using Request = std::pair<MwmSet::MwmId, RequestType>;
void ThreadRoutine();
bool WaitForRequest(std::vector<Request> & campaignMwms);
std::string MakeRemoteURL(MwmSet::MwmId const & mwmId) const;
std::vector<uint8_t> DownloadCampaign(MwmSet::MwmId const & mwmId) const;
df::CustomSymbols DeserializeCampaign(std::vector<uint8_t> && rawData,
std::chrono::steady_clock::time_point timestamp);
void SendSymbolsToRendering(df::CustomSymbols && symbols);
void DeleteSymbolsFromRendering(MwmSet::MwmId const & mwmId);
void ReadExpirationFile(std::string const & expirationFile);
void ReadCampaignFile(std::string const & campaignFile);
GetMwmsByRectFn m_getMwmsByRectFn;
GetMwmIdByName m_getMwmIdByNameFn;
ref_ptr<df::DrapeEngine> m_drapeEngine;
std::map<std::string, bool> m_campaigns;
std::map<std::string, std::chrono::steady_clock::time_point> m_expiration;
df::CustomSymbols m_symbolsCache;
std::mutex m_symbolsCacheMutex;
bool m_isRunning = true;
std::condition_variable m_condition;
std::vector<Request> m_requestedCampaigns;
std::mutex m_mutex;
threads::SimpleThread m_thread;
};

View file

@ -27,6 +27,7 @@ HEADERS += \
gps_track_filter.hpp \
gps_track_storage.hpp \
gps_tracker.hpp \
hla_manager.hpp \
mwm_url.hpp \
place_page_info.hpp \
reachable_by_taxi_checker.hpp \
@ -53,6 +54,7 @@ SOURCES += \
gps_track_filter.cpp \
gps_track_storage.cpp \
gps_tracker.cpp \
hla_manager.cpp \
mwm_url.cpp \
place_page_info.cpp \
reachable_by_taxi_checker.cpp \