From 4a32bc33e666fe2ddc2f785e434a2dc50cc409b8 Mon Sep 17 00:00:00 2001 From: vng Date: Fri, 3 Oct 2014 21:38:56 +0300 Subject: [PATCH] [routing] Check that .mwm and .routing have similar timestamp before calculating route. --- routing/osrm2feature_map.cpp | 17 ++++++- routing/osrm2feature_map.hpp | 4 ++ routing/osrm_router.cpp | 86 ++++++++++++++++++++++++++---------- routing/osrm_router.hpp | 5 +-- routing/router.hpp | 1 + 5 files changed, 85 insertions(+), 28 deletions(-) diff --git a/routing/osrm2feature_map.cpp b/routing/osrm2feature_map.cpp index 81ac787454..1af5df7bd1 100644 --- a/routing/osrm2feature_map.cpp +++ b/routing/osrm2feature_map.cpp @@ -108,7 +108,7 @@ void OsrmFtSegMapping::Load(FilesMappingContainer & cont) Clear(); { - ReaderSource src = cont.GetReader(ROUTING_NODEIND_TO_FTSEGIND_FILE_TAG); + ReaderSource src(cont.GetReader(ROUTING_NODEIND_TO_FTSEGIND_FILE_TAG)); uint32_t const count = ReadVarUint(src); m_offsets.resize(count); for (uint32_t i = 0; i < count; ++i) @@ -118,11 +118,26 @@ void OsrmFtSegMapping::Load(FilesMappingContainer & cont) } } + Map(cont); +} + +void OsrmFtSegMapping::Map(FilesMappingContainer & cont) +{ m_handle.Assign(cont.Map(ROUTING_FTSEG_FILE_TAG)); ASSERT(m_handle.IsValid(), ()); succinct::mapper::map(m_segments, m_handle.GetData()); } +void OsrmFtSegMapping::Unmap() +{ + m_handle.Unmap(); +} + +bool OsrmFtSegMapping::IsMapped() const +{ + return m_handle.IsValid(); +} + void OsrmFtSegMapping::DumpSegmentsByFID(uint32_t fID) const { #ifdef DEBUG diff --git a/routing/osrm2feature_map.hpp b/routing/osrm2feature_map.hpp index d3109789d8..67bd344a0f 100644 --- a/routing/osrm2feature_map.hpp +++ b/routing/osrm2feature_map.hpp @@ -84,6 +84,10 @@ public: void Clear(); void Load(FilesMappingContainer & cont); + void Map(FilesMappingContainer & cont); + void Unmap(); + bool IsMapped() const; + template void ForEachFtSeg(OsrmNodeIdT nodeId, ToDo toDo) const { pair r = GetSegmentsRange(nodeId); diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 44b657a9ac..168f7ff63f 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -6,9 +6,13 @@ #include "../indexer/mercator.hpp" #include "../indexer/index.hpp" +#include "../indexer/scales.hpp" +#include "../indexer/mwm_version.hpp" #include "../platform/platform.hpp" +#include "../coding/reader_wrapper.hpp" + #include "../base/logging.hpp" #include "../3party/osrm/osrm-backend/DataStructures/SearchEngineData.h" @@ -20,6 +24,7 @@ namespace routing { size_t const MAX_NODE_CANDIDATES = 10; +double const FEATURE_BY_POINT_RADIUS_M = 1000.0; namespace { @@ -215,13 +220,30 @@ void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback con callback(route, code); } +namespace +{ + +bool IsRouteExist(RawRouteData const & r) +{ + return !(INVALID_EDGE_WEIGHT == r.shortest_path_length || + r.segment_end_coordinates.empty() || + r.source_traversed_in_reverse.empty()); +} + +} + OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & finalPt, Route & route) { - string const fName = m_countryFn(startPt); + // 1. Find country file name and check that we are in the same MWM. + string fName = m_countryFn(startPt); if (fName != m_countryFn(finalPt)) return PointsInDifferentMWM; - string const fPath = GetPlatform().WritablePathForFile(fName + DATA_FILE_EXTENSION + ROUTING_FILE_EXTENSION); + // 2. Open routing file index if needed. + Platform & pl = GetPlatform(); + fName += DATA_FILE_EXTENSION; + + string const fPath = pl.WritablePathForFile(fName + ROUTING_FILE_EXTENSION); if (NeedReload(fPath)) { LOG(LDEBUG, ("Load routing index for file:", fPath)); @@ -230,34 +252,46 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt m_dataFacade.Clear(); m_mapping.Clear(); + // Open new container and check that mwm and routing have equal timestamp. m_container.Open(fPath); + { + FileReader r1 = m_container.GetReader(VERSION_FILE_TAG); + ReaderSrc src1(r1); + ModelReaderPtr r2 = FilesContainerR(pl.GetReader(fName)).GetReader(VERSION_FILE_TAG); + ReaderSrc src2(r2.GetPtr()); + + if (ver::ReadTimestamp(src1) != ver::ReadTimestamp(src2)) + { + m_container.Close(); + return InconsistentMWMandRoute; + } + } m_mapping.Load(m_container); } - SearchEngineData engineData; - ShortestPathRouting pathFinder(&m_dataFacade, engineData); - RawRouteData rawRoute; + // 3. Find start/end nodes. + if (!m_mapping.IsMapped()) + m_mapping.Map(m_container); FeatureGraphNodeVecT graphNodes; uint32_t mwmId = -1; + ResultCode const code = FindPhantomNodes(fName, startPt, finalPt, graphNodes, MAX_NODE_CANDIDATES, mwmId); + + m_mapping.Unmap(); - ResultCode code = FindPhantomNodes(fName + ".mwm", startPt, finalPt, graphNodes, MAX_NODE_CANDIDATES, mwmId); if (code != NoError) return code; - m_mapping.Clear(); + // 4. Find route. m_dataFacade.Load(m_container); - auto checkRouteExist = [](RawRouteData const & r) - { - return !(INVALID_EDGE_WEIGHT == r.shortest_path_length || - r.segment_end_coordinates.empty() || - r.source_traversed_in_reverse.empty()); - }; - ASSERT_EQUAL(graphNodes.size(), MAX_NODE_CANDIDATES * 2, ()); + SearchEngineData engineData; + ShortestPathRouting pathFinder(&m_dataFacade, engineData); + RawRouteData rawRoute; + size_t ni = 0, nj = 0; while (ni < MAX_NODE_CANDIDATES && nj < MAX_NODE_CANDIDATES) { @@ -267,15 +301,17 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt rawRoute = RawRouteData(); - if ((nodes.source_phantom.forward_node_id != INVALID_NODE_ID || nodes.source_phantom.reverse_node_id != INVALID_NODE_ID) && - (nodes.target_phantom.forward_node_id != INVALID_NODE_ID || nodes.target_phantom.reverse_node_id != INVALID_NODE_ID)) + if ((nodes.source_phantom.forward_node_id != INVALID_NODE_ID || + nodes.source_phantom.reverse_node_id != INVALID_NODE_ID) && + (nodes.target_phantom.forward_node_id != INVALID_NODE_ID || + nodes.target_phantom.reverse_node_id != INVALID_NODE_ID)) { rawRoute.segment_end_coordinates.push_back(nodes); pathFinder({nodes}, {}, rawRoute); } - if (!checkRouteExist(rawRoute)) + if (!IsRouteExist(rawRoute)) { ++ni; if (ni == MAX_NODE_CANDIDATES) @@ -289,16 +325,16 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt } m_dataFacade.Clear(); - m_mapping.Load(m_container); - if (!checkRouteExist(rawRoute)) + if (!IsRouteExist(rawRoute)) return RouteNotFound; + // 5. Restore route. + m_mapping.Map(m_container); + ASSERT_LESS(ni, MAX_NODE_CANDIDATES, ()); ASSERT_LESS(nj, MAX_NODE_CANDIDATES, ()); - - // restore route typedef OsrmFtSegMapping::FtSeg SegT; FeatureGraphNode const & sNode = graphNodes[ni]; @@ -384,7 +420,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt return NoError; } -IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fPath, m2::PointD const & startPt, m2::PointD const & finalPt, +IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fName, m2::PointD const & startPt, m2::PointD const & finalPt, FeatureGraphNodeVecT & res, size_t maxCount, uint32_t & mwmId) { Point2PhantomNode getter(m_mapping); @@ -392,8 +428,10 @@ IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fPath, m2::Point auto processPt = [&](m2::PointD const & p, size_t idx) { getter.SetPoint(p, idx); - /// @todo Review radius of rect and read index scale. - m_pIndex->ForEachInRectForMWM(getter, MercatorBounds::RectByCenterXYAndSizeInMeters(p, 1000.0), 17, fPath); + + m_pIndex->ForEachInRectForMWM(getter, + MercatorBounds::RectByCenterXYAndSizeInMeters(p, FEATURE_BY_POINT_RADIUS_M), + scales::GetUpperScale(), fName); }; processPt(startPt, 0); diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp index 4677778a6b..d1946cf9c8 100644 --- a/routing/osrm_router.hpp +++ b/routing/osrm_router.hpp @@ -17,13 +17,13 @@ namespace routing class OsrmRouter : public IRouter { - m2::PointD m_finalPt; typedef function CountryFileFnT; CountryFileFnT m_countryFn; public: + struct FeatureGraphNode { PhantomNode m_node; @@ -38,9 +38,8 @@ public: virtual void SetFinalPoint(m2::PointD const & finalPt); virtual void CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback); - protected: - IRouter::ResultCode FindPhantomNodes(string const & fPath, m2::PointD const & startPt, m2::PointD const & finalPt, + IRouter::ResultCode FindPhantomNodes(string const & fName, m2::PointD const & startPt, m2::PointD const & finalPt, FeatureGraphNodeVecT & res, size_t maxCount, uint32_t & mwmId); bool NeedReload(string const & fPath) const; diff --git a/routing/router.hpp b/routing/router.hpp index 34e4c205e2..9a457bf555 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -17,6 +17,7 @@ public: enum ResultCode { NoError = 0, + InconsistentMWMandRoute, StartPointNotFound, EndPointNotFound, PointsInDifferentMWM,