Transit read manager realization.

This commit is contained in:
Daria Volvenkova 2017-11-13 13:34:41 +03:00 committed by Vladimir Byko-Ianko
parent 7ec0eb4dce
commit 9cdf58ca77
8 changed files with 384 additions and 2 deletions

View file

@ -70,6 +70,8 @@ set(
track.hpp
traffic_manager.cpp
traffic_manager.hpp
transit_reader.cpp
transit_reader.hpp
user.cpp
user.hpp
user_mark_container.cpp

View file

@ -364,6 +364,11 @@ Framework::Framework(FrameworkParams const & params)
[this]() -> storage::CountryInfoGetter & { return GetCountryInfoGetter(); },
[this](string const & id) -> string {
return m_storage.GetParentIdFor(id);
},
[this](RoutingManager::Callbacks::FeatureCallback const & fn,
std::vector<FeatureID> const & features)
{
return m_model.ReadFeatures(fn, features);
}),
static_cast<RoutingManager::Delegate &>(*this))
, m_trafficManager(bind(&Framework::GetMwmsByRect, this, _1, false /* rough */),

View file

@ -41,6 +41,7 @@ HEADERS += \
taxi_delegate.hpp \
track.hpp \
traffic_manager.hpp \
transit_reader.hpp \
user.hpp \
user_mark.hpp \
user_mark_container.hpp \
@ -78,6 +79,7 @@ SOURCES += \
taxi_delegate.cpp \
track.cpp \
traffic_manager.cpp \
transit_reader.cpp \
user.cpp \
user_mark.cpp \
user_mark_container.cpp \

View file

@ -238,6 +238,7 @@ RoutingManager::RoutingManager(Callbacks && callbacks, Delegate & delegate)
, m_delegate(delegate)
, m_trackingReporter(platform::CreateSocket(), TRACKING_REALTIME_HOST, TRACKING_REALTIME_PORT,
tracking::Reporter::kPushDelayMs)
, m_transitReadManager(m_callbacks.m_indexGetter(), m_callbacks.m_readFeaturesFn)
{
auto const routingStatisticsFn = [](map<string, string> const & statistics) {
alohalytics::LogEvent("Routing_CalculatingRoute", statistics);

View file

@ -2,6 +2,7 @@
#include "map/bookmark_manager.hpp"
#include "map/routing_mark.hpp"
#include "map/transit_reader.hpp"
#include "routing/route.hpp"
#include "routing/routing_session.hpp"
@ -66,18 +67,23 @@ public:
using IndexGetterFn = std::function<Index &()>;
using CountryInfoGetterFn = std::function<storage::CountryInfoGetter &()>;
using CountryParentNameGetterFn = std::function<std::string(std::string const &)>;
using FeatureCallback = std::function<void (FeatureType const &)>;
using ReadFeaturesFn = std::function<void (FeatureCallback const &, std::vector<FeatureID> const &)>;
template <typename IndexGetter, typename CountryInfoGetter, typename CountryParentNameGetter>
template <typename IndexGetter, typename CountryInfoGetter, typename CountryParentNameGetter, typename FeatureReader>
Callbacks(IndexGetter && featureIndexGetter, CountryInfoGetter && countryInfoGetter,
CountryParentNameGetter && countryParentNameGetter)
CountryParentNameGetter && countryParentNameGetter, FeatureReader && readFeatures)
: m_indexGetter(std::forward<IndexGetter>(featureIndexGetter))
, m_countryInfoGetter(std::forward<CountryInfoGetter>(countryInfoGetter))
, m_countryParentNameGetterFn(std::forward<CountryParentNameGetter>(countryParentNameGetter))
, m_readFeaturesFn(std::forward<FeatureReader>(readFeatures))
{}
IndexGetterFn m_indexGetter;
CountryInfoGetterFn m_countryInfoGetter;
CountryParentNameGetterFn m_countryParentNameGetterFn;
TReadFeaturesFn m_readFeaturesFn;
};
using RouteBuildingCallback =
@ -287,5 +293,7 @@ private:
std::map<uint32_t, RoutePointsTransaction> m_routePointsTransactions;
std::chrono::steady_clock::time_point m_loadRoutePointsTimestamp;
TransitReadManager m_transitReadManager;
DECLARE_THREAD_CHECKER(m_threadChecker);
};

176
map/transit_reader.cpp Normal file
View file

@ -0,0 +1,176 @@
#include "map/transit_reader.hpp"
using namespace routing;
using namespace std;
void TransitReader::ReadStops(MwmSet::MwmId const & mwmId, std::vector<transit::Stop> & stops)
{
ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_stopsOffset; }, stops);
}
void TransitReader::ReadShapes(MwmSet::MwmId const & mwmId, std::vector<transit::Shape> & shapes)
{
ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_shapesOffset; }, shapes);
}
void TransitReader::ReadTransfers(MwmSet::MwmId const & mwmId, std::vector<transit::Transfer> & transfers)
{
ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_transfersOffset; }, transfers);
}
void TransitReader::ReadLines(MwmSet::MwmId const & mwmId, std::vector<transit::Line> & lines)
{
ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_linesOffset; }, lines);
}
void TransitReader::ReadNetworks(MwmSet::MwmId const & mwmId, std::vector<transit::Network> & networks)
{
ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_networksOffset; }, networks);
}
void ReadTransitTask::Init(uint64_t id, MwmSet::MwmId const & mwmId, std::unique_ptr<TransitDisplayInfo> && transitInfo)
{
m_id = id;
m_mwmId = mwmId;
if (transitInfo == nullptr)
{
m_loadSubset = false;
m_transitInfo = make_unique<TransitDisplayInfo>();
}
else
{
m_loadSubset = true;
m_transitInfo = std::move(transitInfo);
}
}
void ReadTransitTask::Do()
{
std::vector<transit::Stop> stops;
m_transitReader.ReadStops(m_mwmId, stops);
FillItemsByIdMap(stops, m_transitInfo->m_stops);
stops.clear();
std::vector<transit::Line> lines;
m_transitReader.ReadLines(m_mwmId, lines);
FillItemsByIdMap(lines, m_transitInfo->m_lines);
lines.clear();
std::vector<transit::Shape> shapes;
m_transitReader.ReadShapes(m_mwmId, shapes);
FillItemsByIdMap(shapes, m_transitInfo->m_shapes);
shapes.clear();
for (auto const & stop : m_transitInfo->m_stops)
{
if (stop.second.GetFeatureId() != transit::kInvalidFeatureId)
{
auto const featureId = FeatureID(m_mwmId, stop.second.GetFeatureId());
m_transitInfo->m_features[featureId] = {};
}
else
{
LOG(LWARNING, ("Invalid feature id for transit stop", stop.first));
}
if (stop.second.GetTransferId() != transit::kInvalidTransferId)
m_transitInfo->m_transfers[stop.second.GetTransferId()] = {};
}
std::vector<transit::Transfer> transfers;
m_transitReader.ReadTransfers(m_mwmId, transfers);
FillItemsByIdMap(transfers, m_transitInfo->m_transfers);
transfers.clear();
std::vector<FeatureID> features;
for (auto & id : m_transitInfo->m_features)
features.push_back(id.first);
m_readFeaturesFn([this](FeatureType const & ft)
{
auto & featureInfo = m_transitInfo->m_features[ft.GetID()];
ft.GetReadableName(featureInfo.m_title);
featureInfo.m_point = ft.GetCenter();
}, features);
}
void ReadTransitTask::Reset()
{
m_transitInfo.reset();
IRoutine::Reset();
}
std::unique_ptr<TransitDisplayInfo> && ReadTransitTask::GetTransitInfo()
{
return std::move(m_transitInfo);
}
TransitReadManager::TransitReadManager(Index & index, TReadFeaturesFn const & readFeaturesFn)
: m_nextTasksGroupId(0)
, m_transitReader(index)
, m_readFeaturesFn(readFeaturesFn)
{
Start();
}
TransitReadManager::~TransitReadManager()
{
Stop();
}
void TransitReadManager::Start()
{
if (m_threadsPool != nullptr)
return;
using namespace std::placeholders;
uint8_t constexpr kThreadsCount = 2;
m_threadsPool = my::make_unique<threads::ThreadPool>(
kThreadsCount, std::bind(&TransitReadManager::OnTaskCompleted, this, _1));
}
void TransitReadManager::Stop()
{
if (m_threadsPool != nullptr)
m_threadsPool->Stop();
m_threadsPool.reset();
}
void TransitReadManager::GetTransitDisplayInfo(TransitDisplayInfos & transitDisplayInfos)
{
auto const groupId = m_nextTasksGroupId++;
std::map<MwmSet::MwmId, unique_ptr<ReadTransitTask>> transitTasks;
for (auto & mwmTransitPair : transitDisplayInfos)
{
auto task = my::make_unique<ReadTransitTask>(m_transitReader, m_readFeaturesFn);
task->Init(groupId, mwmTransitPair.first, std::move(mwmTransitPair.second));
transitTasks[mwmTransitPair.first] = std::move(task);
}
{
std::unique_lock<std::mutex> lock(m_mutex);
m_tasksGroups[groupId] = transitTasks.size();
lock.unlock();
for (auto const &task : transitTasks)
{
m_threadsPool->PushBack(task.second.get());
}
lock.lock();
m_event.wait(lock, [&]() { return m_tasksGroups[groupId] == 0; });
m_tasksGroups.erase(groupId);
}
for (auto const & transitTask : transitTasks)
{
transitDisplayInfos[transitTask.first] = transitTask.second->GetTransitInfo();
}
}
void TransitReadManager::OnTaskCompleted(threads::IRoutine * task)
{
ASSERT(dynamic_cast<ReadTransitTask *>(task) != nullptr, ());
ReadTransitTask * t = static_cast<ReadTransitTask *>(task);
std::unique_lock<std::mutex> m_lock(m_mutex);
if (--m_tasksGroups[t->GetId()] == 0)
m_event.notify_all();
}

180
map/transit_reader.hpp Normal file
View file

@ -0,0 +1,180 @@
#pragma once
#include "routing_common/transit_serdes.hpp"
#include "indexer/feature_decl.hpp"
#include "indexer/index.hpp"
#include "base/thread.hpp"
#include "base/thread_pool.hpp"
#include <condition_variable>
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
class TransitReader
{
public:
TransitReader(Index & index)
: m_index(index)
{}
void ReadStops(MwmSet::MwmId const & mwmId, std::vector<routing::transit::Stop> & stops);
void ReadShapes(MwmSet::MwmId const & mwmId, std::vector<routing::transit::Shape> & shapes);
void ReadTransfers(MwmSet::MwmId const & mwmId, std::vector<routing::transit::Transfer> & transfers);
void ReadLines(MwmSet::MwmId const & mwmId, std::vector<routing::transit::Line> & lines);
void ReadNetworks(MwmSet::MwmId const & mwmId, std::vector<routing::transit::Network> & networks);
private:
using GetItemsOffsetFn = std::function<uint32_t (routing::transit::TransitHeader const & header)>;
template <typename T>
void ReadTable(MwmSet::MwmId const & mwmId, GetItemsOffsetFn getItemsOffsetFn, std::vector<T> & items)
{
items.clear();
try
{
MwmSet::MwmHandle handle = m_index.GetMwmHandleById(mwmId);
if (!handle.IsAlive())
{
LOG(LWARNING, ("Can't get mwm handle for", mwmId));
return;
}
MwmValue const & mwmValue = *handle.GetValue<MwmValue>();
if (!mwmValue.m_cont.IsExist(TRANSIT_FILE_TAG))
{
LOG(LWARNING, ("Can't get transit for", mwmId));
return;
}
FilesContainerR::TReader reader = mwmValue.m_cont.GetReader(TRANSIT_FILE_TAG);
ReaderSource<FilesContainerR::TReader> src(reader);
routing::transit::FixedSizeDeserializer<ReaderSource<FilesContainerR::TReader>> fixedSizeDeserializer(src);
routing::transit::TransitHeader header;
fixedSizeDeserializer(header);
auto const offset = getItemsOffsetFn(header);
CHECK_GREATER_OR_EQUAL(offset, src.Pos(), ("Wrong section format."));
src.Skip(offset - src.Pos());
routing::transit::Deserializer<ReaderSource<FilesContainerR::TReader>> deserializer(src);
deserializer(items);
}
catch (Reader::OpenException const & e)
{
LOG(LERROR, ("Error while reading", TRANSIT_FILE_TAG, "section.", e.Msg()));
throw;
}
}
Index & m_index;
};
struct TransitFeatureInfo
{
std::string m_title;
m2::PointD m_point;
};
using TransitFeaturesInfo = std::map<FeatureID, TransitFeatureInfo>;
using TransitStopsInfo = std::map<routing::transit::StopId, routing::transit::Stop>;
using TransitTransfersInfo = std::map<routing::transit::TransferId, routing::transit::Transfer>;
using TransitShapesInfo = std::map<routing::transit::ShapeId, routing::transit::Shape>;
using TransitLinesInfo = std::map<routing::transit::LineId, routing::transit::Line>;
using TransitNetworksInfo = std::map<routing::transit::NetworkId, routing::transit::Network>;
struct TransitDisplayInfo
{
TransitNetworksInfo m_networks;
TransitLinesInfo m_lines;
TransitStopsInfo m_stops;
TransitTransfersInfo m_transfers;
TransitShapesInfo m_shapes;
TransitFeaturesInfo m_features;
};
template <typename T> using TReadCallback = std::function<void (T const &)>;
using TReadFeaturesFn = std::function<void (TReadCallback<FeatureType> const & , std::vector<FeatureID> const &)>;
class ReadTransitTask: public threads::IRoutine
{
public:
ReadTransitTask(TransitReader & reader,
TReadFeaturesFn const & readFeaturesFn)
: m_transitReader(reader), m_readFeaturesFn(readFeaturesFn)
{}
void Init(uint64_t id, MwmSet::MwmId const & mwmId, std::unique_ptr<TransitDisplayInfo> && transitInfo = nullptr);
uint64_t GetId() const { return m_id; }
void Do() override;
void Reset() override;
std::unique_ptr<TransitDisplayInfo> && GetTransitInfo();
private:
template <typename T, typename TID>
void FillItemsByIdMap(std::vector<T> const & items, std::map<TID, T> & itemsById)
{
for (auto const & item : items)
{
if (!m_loadSubset)
{
itemsById.insert(make_pair(item.GetId(), item));
}
else
{
auto it = itemsById.find(item.GetId());
if (it != itemsById.end())
it->second = item;
}
}
};
TransitReader & m_transitReader;
TReadFeaturesFn m_readFeaturesFn;
uint64_t m_id;
MwmSet::MwmId m_mwmId;
std::unique_ptr<TransitDisplayInfo> m_transitInfo;
bool m_loadSubset = false;
};
using TransitDisplayInfos = std::map<MwmSet::MwmId, unique_ptr<TransitDisplayInfo>>;
class TransitReadManager
{
public:
TransitReadManager(Index & index, TReadFeaturesFn const & readFeaturesFn);
~TransitReadManager();
void Start();
void Stop();
void GetTransitDisplayInfo(TransitDisplayInfos & transitDisplayInfos);
// TODO(@darina) Clear cache for deleted mwm.
//void OnMwmDeregistered(MwmSet::MwmId const & mwmId);
private:
void OnTaskCompleted(threads::IRoutine * task);
std::unique_ptr<threads::ThreadPool> m_threadsPool;
std::mutex m_mutex;
std::condition_variable m_event;
std::atomic<uint64_t> m_nextTasksGroupId;
std::map<uint64_t, size_t> m_tasksGroups;
TransitReader m_transitReader;
TReadFeaturesFn m_readFeaturesFn;
// TODO(@darina) In case of reading the whole mwm transit section, save it in the cache for transit scheme rendering.
//TransitDisplayInfos m_transitDisplayCache;
};

View file

@ -110,6 +110,8 @@
67F183811BD5049500AB1840 /* libagg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F1837D1BD5049500AB1840 /* libagg.a */; };
67F183831BD5049500AB1840 /* libminizip.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F1837F1BD5049500AB1840 /* libminizip.a */; };
67F183841BD5049500AB1840 /* libtess2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F183801BD5049500AB1840 /* libtess2.a */; };
BB25B1A31FB320B2007276FA /* transit_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB25B1A11FB320B1007276FA /* transit_reader.cpp */; };
BB25B1A41FB320B2007276FA /* transit_reader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB25B1A21FB320B2007276FA /* transit_reader.hpp */; };
BB421D6C1E8C0031005BFA4D /* transliteration_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB421D6A1E8C0026005BFA4D /* transliteration_test.cpp */; };
BBD9E2C61EE9D01900DF189A /* routing_mark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBD9E2C41EE9D01900DF189A /* routing_mark.cpp */; };
BBD9E2C71EE9D01900DF189A /* routing_mark.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BBD9E2C51EE9D01900DF189A /* routing_mark.hpp */; };
@ -256,6 +258,8 @@
67F183801BD5049500AB1840 /* libtess2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtess2.a; path = "../../../omim-xcode-build/Debug/libtess2.a"; sourceTree = "<group>"; };
67F183851BD504ED00AB1840 /* libsystem_configuration.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsystem_configuration.tbd; path = usr/lib/system/libsystem_configuration.tbd; sourceTree = SDKROOT; };
67F183871BD5050900AB1840 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
BB25B1A11FB320B1007276FA /* transit_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_reader.cpp; sourceTree = "<group>"; };
BB25B1A21FB320B2007276FA /* transit_reader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_reader.hpp; sourceTree = "<group>"; };
BB421D6A1E8C0026005BFA4D /* transliteration_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transliteration_test.cpp; sourceTree = "<group>"; };
BBD9E2C41EE9D01900DF189A /* routing_mark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = routing_mark.cpp; sourceTree = "<group>"; };
BBD9E2C51EE9D01900DF189A /* routing_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_mark.hpp; sourceTree = "<group>"; };
@ -513,6 +517,8 @@
6753462D1A4054E800A0A8C3 /* track.hpp */,
347B60741DD9926D0050FA24 /* traffic_manager.cpp */,
347B60751DD9926D0050FA24 /* traffic_manager.hpp */,
BB25B1A11FB320B1007276FA /* transit_reader.cpp */,
BB25B1A21FB320B2007276FA /* transit_reader.hpp */,
6753462E1A4054E800A0A8C3 /* user_mark_container.cpp */,
6753462F1A4054E800A0A8C3 /* user_mark_container.hpp */,
674C385F1BFF3095000D603B /* user_mark.cpp */,
@ -535,6 +541,7 @@
347B60771DD9926D0050FA24 /* traffic_manager.hpp in Headers */,
45F6EE9E1FB1C77600019892 /* mwm_tree.hpp in Headers */,
6753466B1A4054E800A0A8C3 /* geourl_process.hpp in Headers */,
BB25B1A41FB320B2007276FA /* transit_reader.hpp in Headers */,
F6B283081C1B03320081957A /* gps_track_storage.hpp in Headers */,
675346671A4054E800A0A8C3 /* ge0_parser.hpp in Headers */,
675346A21A4054E800A0A8C3 /* user_mark.hpp in Headers */,
@ -691,6 +698,7 @@
342D833A1D5233E8000D8AEA /* displacement_mode_manager.cpp in Sources */,
3D47B2C71F20EF06000828D2 /* displayed_categories_modifiers.cpp in Sources */,
45201E931CE4AC90008A4842 /* api_mark_point.cpp in Sources */,
BB25B1A31FB320B2007276FA /* transit_reader.cpp in Sources */,
675346661A4054E800A0A8C3 /* ge0_parser.cpp in Sources */,
F6D2CE7E1EDEB7F500636DFD /* routing_manager.cpp in Sources */,
3D74ABBE1EA76F1D0063A898 /* local_ads_supported_types.cpp in Sources */,