From 9cdf58ca77a700bb36ccb967a2c75a3649690b87 Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Mon, 13 Nov 2017 13:34:41 +0300 Subject: [PATCH] Transit read manager realization. --- map/CMakeLists.txt | 2 + map/framework.cpp | 5 + map/map.pro | 2 + map/routing_manager.cpp | 1 + map/routing_manager.hpp | 12 +- map/transit_reader.cpp | 176 +++++++++++++++++++++++ map/transit_reader.hpp | 180 ++++++++++++++++++++++++ xcode/map/map.xcodeproj/project.pbxproj | 8 ++ 8 files changed, 384 insertions(+), 2 deletions(-) create mode 100644 map/transit_reader.cpp create mode 100644 map/transit_reader.hpp diff --git a/map/CMakeLists.txt b/map/CMakeLists.txt index 18e8a986ce..c95b0d4cfb 100644 --- a/map/CMakeLists.txt +++ b/map/CMakeLists.txt @@ -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 diff --git a/map/framework.cpp b/map/framework.cpp index 0b65d90e5a..3632ca92ea 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -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 const & features) + { + return m_model.ReadFeatures(fn, features); }), static_cast(*this)) , m_trafficManager(bind(&Framework::GetMwmsByRect, this, _1, false /* rough */), diff --git a/map/map.pro b/map/map.pro index d0fdbd53eb..c059472acf 100644 --- a/map/map.pro +++ b/map/map.pro @@ -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 \ diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 0a81c1a7f7..2adf40c7b2 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -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 const & statistics) { alohalytics::LogEvent("Routing_CalculatingRoute", statistics); diff --git a/map/routing_manager.hpp b/map/routing_manager.hpp index 1751226ae7..a8003cfb26 100644 --- a/map/routing_manager.hpp +++ b/map/routing_manager.hpp @@ -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; using CountryInfoGetterFn = std::function; using CountryParentNameGetterFn = std::function; + using FeatureCallback = std::function; + using ReadFeaturesFn = std::function const &)>; - template + + template Callbacks(IndexGetter && featureIndexGetter, CountryInfoGetter && countryInfoGetter, - CountryParentNameGetter && countryParentNameGetter) + CountryParentNameGetter && countryParentNameGetter, FeatureReader && readFeatures) : m_indexGetter(std::forward(featureIndexGetter)) , m_countryInfoGetter(std::forward(countryInfoGetter)) , m_countryParentNameGetterFn(std::forward(countryParentNameGetter)) + , m_readFeaturesFn(std::forward(readFeatures)) {} IndexGetterFn m_indexGetter; CountryInfoGetterFn m_countryInfoGetter; CountryParentNameGetterFn m_countryParentNameGetterFn; + TReadFeaturesFn m_readFeaturesFn; }; using RouteBuildingCallback = @@ -287,5 +293,7 @@ private: std::map m_routePointsTransactions; std::chrono::steady_clock::time_point m_loadRoutePointsTimestamp; + TransitReadManager m_transitReadManager; + DECLARE_THREAD_CHECKER(m_threadChecker); }; diff --git a/map/transit_reader.cpp b/map/transit_reader.cpp new file mode 100644 index 0000000000..c6965a1075 --- /dev/null +++ b/map/transit_reader.cpp @@ -0,0 +1,176 @@ +#include "map/transit_reader.hpp" + +using namespace routing; +using namespace std; + +void TransitReader::ReadStops(MwmSet::MwmId const & mwmId, std::vector & stops) +{ + ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_stopsOffset; }, stops); +} + +void TransitReader::ReadShapes(MwmSet::MwmId const & mwmId, std::vector & shapes) +{ + ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_shapesOffset; }, shapes); +} + +void TransitReader::ReadTransfers(MwmSet::MwmId const & mwmId, std::vector & transfers) +{ + ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_transfersOffset; }, transfers); +} + +void TransitReader::ReadLines(MwmSet::MwmId const & mwmId, std::vector & lines) +{ + ReadTable(mwmId, [](transit::TransitHeader const & header){ return header.m_linesOffset; }, lines); +} + +void TransitReader::ReadNetworks(MwmSet::MwmId const & mwmId, std::vector & 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 && transitInfo) +{ + m_id = id; + m_mwmId = mwmId; + if (transitInfo == nullptr) + { + m_loadSubset = false; + m_transitInfo = make_unique(); + } + else + { + m_loadSubset = true; + m_transitInfo = std::move(transitInfo); + } +} + +void ReadTransitTask::Do() +{ + std::vector stops; + m_transitReader.ReadStops(m_mwmId, stops); + FillItemsByIdMap(stops, m_transitInfo->m_stops); + stops.clear(); + + std::vector lines; + m_transitReader.ReadLines(m_mwmId, lines); + FillItemsByIdMap(lines, m_transitInfo->m_lines); + lines.clear(); + + std::vector 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 transfers; + m_transitReader.ReadTransfers(m_mwmId, transfers); + FillItemsByIdMap(transfers, m_transitInfo->m_transfers); + transfers.clear(); + + std::vector 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 && 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( + 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> transitTasks; + for (auto & mwmTransitPair : transitDisplayInfos) + { + auto task = my::make_unique(m_transitReader, m_readFeaturesFn); + task->Init(groupId, mwmTransitPair.first, std::move(mwmTransitPair.second)); + transitTasks[mwmTransitPair.first] = std::move(task); + } + + { + std::unique_lock 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(task) != nullptr, ()); + ReadTransitTask * t = static_cast(task); + std::unique_lock m_lock(m_mutex); + if (--m_tasksGroups[t->GetId()] == 0) + m_event.notify_all(); +} diff --git a/map/transit_reader.hpp b/map/transit_reader.hpp new file mode 100644 index 0000000000..8512a8e886 --- /dev/null +++ b/map/transit_reader.hpp @@ -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 +#include +#include +#include +#include +#include +#include + +class TransitReader +{ +public: + TransitReader(Index & index) + : m_index(index) + {} + + void ReadStops(MwmSet::MwmId const & mwmId, std::vector & stops); + void ReadShapes(MwmSet::MwmId const & mwmId, std::vector & shapes); + void ReadTransfers(MwmSet::MwmId const & mwmId, std::vector & transfers); + void ReadLines(MwmSet::MwmId const & mwmId, std::vector & lines); + void ReadNetworks(MwmSet::MwmId const & mwmId, std::vector & networks); + +private: + using GetItemsOffsetFn = std::function; + template + void ReadTable(MwmSet::MwmId const & mwmId, GetItemsOffsetFn getItemsOffsetFn, std::vector & 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(); + 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 src(reader); + + routing::transit::FixedSizeDeserializer> 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> 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; + +using TransitStopsInfo = std::map; +using TransitTransfersInfo = std::map; +using TransitShapesInfo = std::map; +using TransitLinesInfo = std::map; +using TransitNetworksInfo = std::map; + +struct TransitDisplayInfo +{ + TransitNetworksInfo m_networks; + TransitLinesInfo m_lines; + TransitStopsInfo m_stops; + TransitTransfersInfo m_transfers; + TransitShapesInfo m_shapes; + TransitFeaturesInfo m_features; +}; + +template using TReadCallback = std::function; +using TReadFeaturesFn = std::function const & , std::vector 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 && transitInfo = nullptr); + uint64_t GetId() const { return m_id; } + + void Do() override; + void Reset() override; + + std::unique_ptr && GetTransitInfo(); + +private: + template + void FillItemsByIdMap(std::vector const & items, std::map & 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 m_transitInfo; + + bool m_loadSubset = false; +}; + +using TransitDisplayInfos = std::map>; + +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 m_threadsPool; + + std::mutex m_mutex; + std::condition_variable m_event; + + std::atomic m_nextTasksGroupId; + std::map 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; +}; diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index 5c3404a693..a1696077c7 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ""; }; + BB25B1A21FB320B2007276FA /* transit_reader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_reader.hpp; sourceTree = ""; }; BB421D6A1E8C0026005BFA4D /* transliteration_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transliteration_test.cpp; sourceTree = ""; }; BBD9E2C41EE9D01900DF189A /* routing_mark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = routing_mark.cpp; sourceTree = ""; }; BBD9E2C51EE9D01900DF189A /* routing_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_mark.hpp; sourceTree = ""; }; @@ -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 */,