#ifndef CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP #define CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP #include "engine/datafacade/algorithm_datafacade.hpp" #include "engine/datafacade/contiguous_block_allocator.hpp" #include "engine/datafacade/datafacade_base.hpp" #include "engine/algorithm.hpp" #include "engine/approach.hpp" #include "engine/geospatial_query.hpp" #include "customizer/edge_based_graph.hpp" #include "extractor/datasources.hpp" #include "extractor/edge_based_node.hpp" #include "extractor/intersection_bearings_container.hpp" #include "extractor/maneuver_override.hpp" #include "extractor/name_table.hpp" #include "extractor/node_data_container.hpp" #include "extractor/packed_osm_ids.hpp" #include "extractor/profile_properties.hpp" #include "extractor/segment_data_container.hpp" #include "extractor/turn_lane_types.hpp" #include "guidance/turn_bearing.hpp" #include "guidance/turn_data_container.hpp" #include "guidance/turn_instruction.hpp" #include "contractor/query_graph.hpp" #include "partitioner/cell_storage.hpp" #include "partitioner/multi_level_partition.hpp" #include "storage/shared_datatype.hpp" #include "storage/shared_memory_ownership.hpp" #include "util/exception.hpp" #include "util/exception_utils.hpp" #include "util/filtered_graph.hpp" #include "util/guidance/bearing_class.hpp" #include "util/guidance/entry_class.hpp" #include "util/guidance/turn_lanes.hpp" #include "util/log.hpp" #include "util/packed_vector.hpp" #include "util/range_table.hpp" #include "util/rectangle.hpp" #include "util/static_graph.hpp" #include "util/static_rtree.hpp" #include "util/typedefs.hpp" #include #include #include #include #include #include #include #include #include namespace osrm { namespace engine { namespace datafacade { template class ContiguousInternalMemoryAlgorithmDataFacade; template <> class ContiguousInternalMemoryAlgorithmDataFacade : public datafacade::AlgorithmDataFacade { private: using QueryGraph = util::FilteredGraphView; using GraphNode = QueryGraph::NodeArrayEntry; using GraphEdge = QueryGraph::EdgeArrayEntry; QueryGraph m_query_graph; // allocator that keeps the allocation data std::shared_ptr allocator; void InitializeGraphPointer(const storage::DataLayout &data_layout, char *memory_block, const std::string &metric_name, const std::size_t exclude_index) { const std::string metric_prefix = "/ch/metrics/" + metric_name; auto graph_nodes_ptr = data_layout.GetBlockPtr( memory_block, metric_prefix + "/contracted_graph/node_array"); auto graph_edges_ptr = data_layout.GetBlockPtr( memory_block, metric_prefix + "/contracted_graph/edge_array"); auto exclude_prefix = metric_prefix + "/exclude/" + std::to_string(exclude_index); auto filter_block_id = exclude_prefix + "/edge_filter"; auto edge_filter_ptr = data_layout.GetBlockPtr::Word>(memory_block, filter_block_id); util::vector_view node_list( graph_nodes_ptr, data_layout.GetBlockEntries(metric_prefix + "/contracted_graph/node_array")); util::vector_view edge_list( graph_edges_ptr, data_layout.GetBlockEntries(metric_prefix + "/contracted_graph/edge_array")); util::vector_view edge_filter(edge_filter_ptr, data_layout.GetBlockEntries(filter_block_id)); m_query_graph = QueryGraph({node_list, edge_list}, edge_filter); } public: ContiguousInternalMemoryAlgorithmDataFacade( std::shared_ptr allocator_, const std::string &metric_name, std::size_t exclude_index) : allocator(std::move(allocator_)) { InitializeInternalPointers( allocator->GetLayout(), allocator->GetMemory(), metric_name, exclude_index); } void InitializeInternalPointers(const storage::DataLayout &data_layout, char *memory_block, const std::string &metric_name, const std::size_t exclude_index) { InitializeGraphPointer(data_layout, memory_block, metric_name, exclude_index); } // search graph access unsigned GetNumberOfNodes() const override final { return m_query_graph.GetNumberOfNodes(); } unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); } unsigned GetOutDegree(const NodeID n) const override final { return m_query_graph.GetOutDegree(n); } NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); } const EdgeData &GetEdgeData(const EdgeID e) const override final { return m_query_graph.GetEdgeData(e); } EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return m_query_graph.GetAdjacentEdgeRange(node); } // searches for a specific edge EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return m_query_graph.FindEdge(from, to); } EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final { return m_query_graph.FindEdgeInEitherDirection(from, to); } EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final { return m_query_graph.FindEdgeIndicateIfReverse(from, to, result); } EdgeID FindSmallestEdge(const NodeID from, const NodeID to, std::function filter) const override final { return m_query_graph.FindSmallestEdge(from, to, filter); } }; /** * This base class implements the Datafacade interface for accessing * data that's stored in a single large block of memory (RAM). * * In this case "internal memory" refers to RAM - as opposed to "external memory", * which usually refers to disk. */ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade { private: using super = BaseDataFacade; using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT; using RTreeLeaf = super::RTreeLeaf; using SharedRTree = util::StaticRTree; using SharedGeospatialQuery = GeospatialQuery; using RTreeNode = SharedRTree::TreeNode; extractor::ClassData exclude_mask; std::string m_timestamp; extractor::ProfileProperties *m_profile_properties; extractor::Datasources *m_datasources; std::uint32_t m_check_sum; util::vector_view m_coordinate_list; extractor::PackedOSMIDsView m_osmnodeid_list; util::vector_view m_lane_description_offsets; util::vector_view m_lane_description_masks; util::vector_view m_turn_weight_penalties; util::vector_view m_turn_duration_penalties; extractor::SegmentDataView segment_data; extractor::EdgeBasedNodeDataView edge_based_node_data; guidance::TurnDataView turn_data; util::vector_view m_datasource_name_data; util::vector_view m_datasource_name_offsets; util::vector_view m_datasource_name_lengths; util::vector_view m_lane_tupel_id_pairs; util::vector_view m_maneuver_overrides; util::vector_view m_maneuver_override_node_sequences; std::unique_ptr m_static_rtree; std::unique_ptr m_geospatial_query; boost::filesystem::path file_index_path; extractor::IntersectionBearingsView intersection_bearings_view; extractor::NameTableView m_name_table; // the look-up table for entry classes. An entry class lists the possibility of entry for all // available turns. Such a class id is stored with every edge. util::vector_view m_entry_class_table; // allocator that keeps the allocation data std::shared_ptr allocator; void InitializeProfilePropertiesPointer(const storage::DataLayout &data_layout, char *memory_block, const std::string &metric_name, const std::size_t exclude_index) { // TODO: For multi-metric support we need to have separate exclude classes per metric (void)metric_name; m_profile_properties = data_layout.GetBlockPtr( memory_block, "/common/properties"); exclude_mask = m_profile_properties->excludable_classes[exclude_index]; } void InitializeChecksumPointer(const storage::DataLayout &data_layout, char *memory_block) { m_check_sum = *data_layout.GetBlockPtr(memory_block, "/common/connectivity_checksum"); util::Log() << "set checksum: " << m_check_sum; } void InitializeRTreePointers(const storage::DataLayout &data_layout, char *memory_block) { BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree"); const auto file_index_ptr = data_layout.GetBlockPtr(memory_block, "/common/rtree/file_index_path"); file_index_path = boost::filesystem::path(file_index_ptr); if (!boost::filesystem::exists(file_index_path)) { util::Log(logDEBUG) << "Leaf file name " << file_index_path.string(); throw util::exception("Could not load " + file_index_path.string() + "Is any data loaded into shared memory?" + SOURCE_REF); } const auto rtree_ptr = data_layout.GetBlockPtr(memory_block, "/common/rtree/search_tree"); util::vector_view search_tree( rtree_ptr, data_layout.GetBlockEntries("/common/rtree/search_tree")); const auto rtree_levelstarts_ptr = data_layout.GetBlockPtr( memory_block, "/common/rtree/search_tree_level_starts"); util::vector_view rtree_level_starts( rtree_levelstarts_ptr, data_layout.GetBlockEntries("/common/rtree/search_tree_level_starts")); m_static_rtree.reset(new SharedRTree{std::move(search_tree), std::move(rtree_level_starts), file_index_path, m_coordinate_list}); m_geospatial_query.reset( new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this)); } void InitializeNodeInformationPointers(const storage::DataLayout &layout, char *memory_ptr) { const auto coordinate_list_ptr = layout.GetBlockPtr(memory_ptr, "/common/coordinates"); m_coordinate_list.reset(coordinate_list_ptr, layout.GetBlockEntries("/common/coordinates")); const auto osmnodeid_ptr = layout.GetBlockPtr( memory_ptr, "/common/osm_node_ids/packed"); m_osmnodeid_list = extractor::PackedOSMIDsView( util::vector_view( osmnodeid_ptr, layout.GetBlockEntries("/common/osm_node_ids/packed")), // We (ab)use the number of coordinates here because we know we have the same amount of // ids layout.GetBlockEntries("/common/coordinates")); } void InitializeEdgeBasedNodeDataInformationPointers(const storage::DataLayout &layout, char *memory_ptr) { const auto edge_based_node_list_ptr = layout.GetBlockPtr(memory_ptr, "/common/ebg_node_data/nodes"); util::vector_view edge_based_node_data_list( edge_based_node_list_ptr, layout.GetBlockEntries("/common/ebg_node_data/nodes")); const auto annotation_data_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/ebg_node_data/annotations"); util::vector_view annotation_data( annotation_data_list_ptr, layout.GetBlockEntries("/common/ebg_node_data/annotations")); edge_based_node_data = extractor::EdgeBasedNodeDataView( std::move(edge_based_node_data_list), std::move(annotation_data)); } void InitializeEdgeInformationPointers(const storage::DataLayout &layout, char *memory_ptr) { const auto lane_data_id_ptr = layout.GetBlockPtr(memory_ptr, "/common/turn_data/lane_data_ids"); util::vector_view lane_data_ids( lane_data_id_ptr, layout.GetBlockEntries("/common/turn_data/lane_data_ids")); const auto turn_instruction_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/turn_data/turn_instructions"); util::vector_view turn_instructions( turn_instruction_list_ptr, layout.GetBlockEntries("/common/turn_data/turn_instructions")); const auto entry_class_id_list_ptr = layout.GetBlockPtr(memory_ptr, "/common/turn_data/entry_class_ids"); util::vector_view entry_class_ids( entry_class_id_list_ptr, layout.GetBlockEntries("/common/turn_data/entry_class_ids")); const auto pre_turn_bearing_ptr = layout.GetBlockPtr( memory_ptr, "/common/turn_data/pre_turn_bearings"); util::vector_view pre_turn_bearings( pre_turn_bearing_ptr, layout.GetBlockEntries("/common/turn_data/pre_turn_bearings")); const auto post_turn_bearing_ptr = layout.GetBlockPtr( memory_ptr, "/common/turn_data/post_turn_bearings"); util::vector_view post_turn_bearings( post_turn_bearing_ptr, layout.GetBlockEntries("/common/turn_data/post_turn_bearings")); turn_data = guidance::TurnDataView(std::move(turn_instructions), std::move(lane_data_ids), std::move(entry_class_ids), std::move(pre_turn_bearings), std::move(post_turn_bearings)); } void InitializeNamePointers(const storage::DataLayout &data_layout, char *memory_block) { const auto name_blocks_ptr = data_layout.GetBlockPtr( memory_block, "/common/names/blocks"); const auto name_values_ptr = data_layout.GetBlockPtr( memory_block, "/common/names/values"); util::vector_view blocks( name_blocks_ptr, data_layout.GetBlockEntries("/common/names/blocks")); util::vector_view values( name_values_ptr, data_layout.GetBlockEntries("/common/names/values")); extractor::NameTableView::IndexedData index_data_view{std::move(blocks), std::move(values)}; m_name_table = extractor::NameTableView{std::move(index_data_view)}; } void InitializeTurnLaneDescriptionsPointers(const storage::DataLayout &data_layout, char *memory_block) { auto offsets_ptr = data_layout.GetBlockPtr(memory_block, "/common/turn_lanes/offsets"); util::vector_view offsets( offsets_ptr, data_layout.GetBlockEntries("/common/turn_lanes/offsets")); m_lane_description_offsets = std::move(offsets); auto masks_ptr = data_layout.GetBlockPtr( memory_block, "/common/turn_lanes/masks"); util::vector_view masks( masks_ptr, data_layout.GetBlockEntries("/common/turn_lanes/masks")); m_lane_description_masks = std::move(masks); const auto lane_tupel_id_pair_ptr = data_layout.GetBlockPtr(memory_block, "/common/turn_lanes/data"); util::vector_view lane_tupel_id_pair( lane_tupel_id_pair_ptr, data_layout.GetBlockEntries("/common/turn_lanes/data")); m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair); } void InitializeTurnPenalties(const storage::DataLayout &data_layout, char *memory_block) { auto turn_weight_penalties_ptr = data_layout.GetBlockPtr(memory_block, "/common/turn_penalty/weight"); m_turn_weight_penalties = util::vector_view( turn_weight_penalties_ptr, data_layout.GetBlockEntries("/common/turn_penalty/weight")); auto turn_duration_penalties_ptr = data_layout.GetBlockPtr(memory_block, "/common/turn_penalty/duration"); m_turn_duration_penalties = util::vector_view( turn_duration_penalties_ptr, data_layout.GetBlockEntries("/common/turn_penalty/duration")); } void InitializeGeometryPointers(const storage::DataLayout &data_layout, char *memory_block) { auto geometries_index_ptr = data_layout.GetBlockPtr(memory_block, "/common/segment_data/index"); util::vector_view geometry_begin_indices( geometries_index_ptr, data_layout.GetBlockEntries("/common/segment_data/index")); auto num_entries = data_layout.GetBlockEntries("/common/segment_data/nodes"); auto geometries_node_list_ptr = data_layout.GetBlockPtr(memory_block, "/common/segment_data/nodes"); util::vector_view geometry_node_list(geometries_node_list_ptr, num_entries); auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr( memory_block, "/common/segment_data/forward_weights/packed"); extractor::SegmentDataView::SegmentWeightVector geometry_fwd_weight_list( util::vector_view( geometries_fwd_weight_list_ptr, data_layout.GetBlockEntries("/common/segment_data/forward_weights/packed")), num_entries); auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr( memory_block, "/common/segment_data/reverse_weights/packed"); extractor::SegmentDataView::SegmentWeightVector geometry_rev_weight_list( util::vector_view( geometries_rev_weight_list_ptr, data_layout.GetBlockEntries("/common/segment_data/reverse_weights/packed")), num_entries); auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr( memory_block, "/common/segment_data/forward_durations/packed"); extractor::SegmentDataView::SegmentDurationVector geometry_fwd_duration_list( util::vector_view( geometries_fwd_duration_list_ptr, data_layout.GetBlockEntries("/common/segment_data/forward_durations/packed")), num_entries); auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr( memory_block, "/common/segment_data/reverse_durations/packed"); extractor::SegmentDataView::SegmentDurationVector geometry_rev_duration_list( util::vector_view( geometries_rev_duration_list_ptr, data_layout.GetBlockEntries("/common/segment_data/reverse_durations/packed")), num_entries); auto geometries_fwd_datasources_list_ptr = data_layout.GetBlockPtr( memory_block, "/common/segment_data/forward_data_sources"); util::vector_view geometry_fwd_datasources_list( geometries_fwd_datasources_list_ptr, data_layout.GetBlockEntries("/common/segment_data/forward_data_sources")); auto geometries_rev_datasources_list_ptr = data_layout.GetBlockPtr( memory_block, "/common/segment_data/reverse_data_sources"); util::vector_view geometry_rev_datasources_list( geometries_rev_datasources_list_ptr, data_layout.GetBlockEntries("/common/segment_data/reverse_data_sources")); segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices), std::move(geometry_node_list), std::move(geometry_fwd_weight_list), std::move(geometry_rev_weight_list), std::move(geometry_fwd_duration_list), std::move(geometry_rev_duration_list), std::move(geometry_fwd_datasources_list), std::move(geometry_rev_datasources_list)}; m_datasources = data_layout.GetBlockPtr( memory_block, "/common/data_sources_names"); } void InitializeIntersectionClassPointers(const storage::DataLayout &data_layout, char *memory_block) { auto bearing_class_id_ptr = data_layout.GetBlockPtr( memory_block, "/common/intersection_bearings/node_to_class_id"); util::vector_view bearing_class_id( bearing_class_id_ptr, data_layout.GetBlockEntries("/common/intersection_bearings/node_to_class_id")); auto bearing_values_ptr = data_layout.GetBlockPtr( memory_block, "/common/intersection_bearings/bearing_values"); util::vector_view bearing_values( bearing_values_ptr, data_layout.GetBlockEntries("/common/intersection_bearings/bearing_values")); auto offsets_ptr = data_layout.GetBlockPtr( memory_block, "/common/intersection_bearings/class_id_to_ranges/block_offsets"); auto blocks_ptr = data_layout.GetBlockPtr( memory_block, "/common/intersection_bearings/class_id_to_ranges/diff_blocks"); util::vector_view bearing_offsets( offsets_ptr, data_layout.GetBlockEntries( "/common/intersection_bearings/class_id_to_ranges/block_offsets")); util::vector_view bearing_blocks( blocks_ptr, data_layout.GetBlockEntries( "/common/intersection_bearings/class_id_to_ranges/diff_blocks")); util::RangeTable<16, storage::Ownership::View> bearing_range_table( bearing_offsets, bearing_blocks, static_cast(bearing_values.size())); intersection_bearings_view = extractor::IntersectionBearingsView{ std::move(bearing_values), std::move(bearing_class_id), std::move(bearing_range_table)}; auto entry_class_ptr = data_layout.GetBlockPtr( memory_block, "/common/entry_classes"); util::vector_view entry_class_table( entry_class_ptr, data_layout.GetBlockEntries("/common/entry_classes")); m_entry_class_table = std::move(entry_class_table); } void InitializeManeuverOverridePointers(const storage::DataLayout &data_layout, char *memory_block) { auto maneuver_overrides_ptr = data_layout.GetBlockPtr( memory_block, "/common/maneuver_overrides/overrides"); m_maneuver_overrides = util::vector_view( maneuver_overrides_ptr, data_layout.GetBlockEntries("/common/maneuver_overrides/overrides")); auto maneuver_override_node_sequences_ptr = data_layout.GetBlockPtr( memory_block, "/common/maneuver_overrides/node_sequences"); m_maneuver_override_node_sequences = util::vector_view( maneuver_override_node_sequences_ptr, data_layout.GetBlockEntries("/common/maneuver_overrides/node_sequences")); } void InitializeInternalPointers(const storage::DataLayout &data_layout, char *memory_block, const std::string &metric_name, const std::size_t exclude_index) { InitializeChecksumPointer(data_layout, memory_block); InitializeNodeInformationPointers(data_layout, memory_block); InitializeEdgeBasedNodeDataInformationPointers(data_layout, memory_block); InitializeEdgeInformationPointers(data_layout, memory_block); InitializeTurnPenalties(data_layout, memory_block); InitializeGeometryPointers(data_layout, memory_block); InitializeNamePointers(data_layout, memory_block); InitializeTurnLaneDescriptionsPointers(data_layout, memory_block); InitializeProfilePropertiesPointer(data_layout, memory_block, metric_name, exclude_index); InitializeRTreePointers(data_layout, memory_block); InitializeIntersectionClassPointers(data_layout, memory_block); InitializeManeuverOverridePointers(data_layout, memory_block); } public: // allows switching between process_memory/shared_memory datafacade, based on the type of // allocator ContiguousInternalMemoryDataFacadeBase(std::shared_ptr allocator_, const std::string &metric_name, const std::size_t exclude_index) : allocator(std::move(allocator_)) { InitializeInternalPointers( allocator->GetLayout(), allocator->GetMemory(), metric_name, exclude_index); } // node and edge information access util::Coordinate GetCoordinateOfNode(const NodeID id) const override final { return m_coordinate_list[id]; } OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const override final { return m_osmnodeid_list[id]; } std::vector GetUncompressedForwardGeometry(const EdgeID id) const override final { auto range = segment_data.GetForwardGeometry(id); return std::vector{range.begin(), range.end()}; } virtual std::vector GetUncompressedReverseGeometry(const EdgeID id) const override final { auto range = segment_data.GetReverseGeometry(id); return std::vector{range.begin(), range.end()}; } virtual std::vector GetUncompressedForwardDurations(const EdgeID id) const override final { auto range = segment_data.GetForwardDurations(id); return std::vector{range.begin(), range.end()}; } virtual std::vector GetUncompressedReverseDurations(const EdgeID id) const override final { auto range = segment_data.GetReverseDurations(id); return std::vector{range.begin(), range.end()}; } virtual std::vector GetUncompressedForwardWeights(const EdgeID id) const override final { auto range = segment_data.GetForwardWeights(id); return std::vector{range.begin(), range.end()}; } virtual std::vector GetUncompressedReverseWeights(const EdgeID id) const override final { auto range = segment_data.GetReverseWeights(id); return std::vector{range.begin(), range.end()}; } // Returns the data source ids that were used to supply the edge // weights. virtual std::vector GetUncompressedForwardDatasources(const EdgeID id) const override final { auto range = segment_data.GetForwardDatasources(id); return std::vector{range.begin(), range.end()}; } // Returns the data source ids that were used to supply the edge // weights. virtual std::vector GetUncompressedReverseDatasources(const EdgeID id) const override final { auto range = segment_data.GetReverseDatasources(id); return std::vector{range.begin(), range.end()}; } virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final { BOOST_ASSERT(m_turn_weight_penalties.size() > id); return m_turn_weight_penalties[id]; } virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const override final { BOOST_ASSERT(m_turn_duration_penalties.size() > id); return m_turn_duration_penalties[id]; } osrm::guidance::TurnInstruction GetTurnInstructionForEdgeID(const EdgeID id) const override final { return turn_data.GetTurnInstruction(id); } std::vector GetEdgesInBox(const util::Coordinate south_west, const util::Coordinate north_east) const override final { BOOST_ASSERT(m_geospatial_query.get()); const util::RectangleInt2D bbox{ south_west.lon, north_east.lon, south_west.lat, north_east.lat}; return m_geospatial_query->Search(bbox); } std::vector NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const float max_distance, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodesInRange( input_coordinate, max_distance, approach); } std::vector NearestPhantomNodesInRange(const util::Coordinate input_coordinate, const float max_distance, const int bearing, const int bearing_range, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodesInRange( input_coordinate, max_distance, bearing, bearing_range, approach); } std::vector NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, approach); } std::vector NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results, const double max_distance, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodes( input_coordinate, max_results, max_distance, approach); } std::vector NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results, const int bearing, const int bearing_range, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodes( input_coordinate, max_results, bearing, bearing_range, approach); } std::vector NearestPhantomNodes(const util::Coordinate input_coordinate, const unsigned max_results, const double max_distance, const int bearing, const int bearing_range, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodes( input_coordinate, max_results, max_distance, bearing, bearing_range, approach); } std::pair NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( input_coordinate, approach); } std::pair NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate, const double max_distance, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( input_coordinate, max_distance, approach); } std::pair NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate, const double max_distance, const int bearing, const int bearing_range, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( input_coordinate, max_distance, bearing, bearing_range, approach); } std::pair NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate, const int bearing, const int bearing_range, const Approach approach) const override final { BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( input_coordinate, bearing, bearing_range, approach); } std::uint32_t GetCheckSum() const override final { return m_check_sum; } GeometryID GetGeometryIndex(const NodeID id) const override final { return edge_based_node_data.GetGeometryID(id); } ComponentID GetComponentID(const NodeID id) const override final { return edge_based_node_data.GetComponentID(id); } extractor::TravelMode GetTravelMode(const NodeID id) const override final { return edge_based_node_data.GetTravelMode(id); } extractor::ClassData GetClassData(const NodeID id) const override final { return edge_based_node_data.GetClassData(id); } bool ExcludeNode(const NodeID id) const override final { return (edge_based_node_data.GetClassData(id) & exclude_mask) > 0; } std::vector GetClasses(const extractor::ClassData class_data) const override final { auto indexes = extractor::getClassIndexes(class_data); std::vector classes(indexes.size()); std::transform(indexes.begin(), indexes.end(), classes.begin(), [this](const auto index) { return m_profile_properties->GetClassName(index); }); return classes; } NameID GetNameIndex(const NodeID id) const override final { return edge_based_node_data.GetNameID(id); } StringView GetNameForID(const NameID id) const override final { return m_name_table.GetNameForID(id); } StringView GetRefForID(const NameID id) const override final { return m_name_table.GetRefForID(id); } StringView GetPronunciationForID(const NameID id) const override final { return m_name_table.GetPronunciationForID(id); } StringView GetDestinationsForID(const NameID id) const override final { return m_name_table.GetDestinationsForID(id); } StringView GetExitsForID(const NameID id) const override final { return m_name_table.GetExitsForID(id); } StringView GetDatasourceName(const DatasourceID id) const override final { return m_datasources->GetSourceName(id); } bool GetContinueStraightDefault() const override final { return m_profile_properties->continue_straight_at_waypoint; } double GetMapMatchingMaxSpeed() const override final { return m_profile_properties->max_speed_for_map_matching; } const char *GetWeightName() const override final { return m_profile_properties->weight_name; } unsigned GetWeightPrecision() const override final { return m_profile_properties->weight_precision; } double GetWeightMultiplier() const override final { return m_profile_properties->GetWeightMultiplier(); } util::guidance::BearingClass GetBearingClass(const NodeID node) const override final { return intersection_bearings_view.GetBearingClass(node); } guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final { return turn_data.GetPreTurnBearing(eid); } guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final { return turn_data.GetPostTurnBearing(eid); } util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const override final { auto entry_class_id = turn_data.GetEntryClassID(turn_id); return m_entry_class_table.at(entry_class_id); } bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); } util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final { BOOST_ASSERT(HasLaneData(id)); return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id)); } extractor::TurnLaneDescription GetTurnDescription(const LaneDescriptionID lane_description_id) const override final { if (lane_description_id == INVALID_LANE_DESCRIPTIONID) return {}; else return extractor::TurnLaneDescription( m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id], m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id + 1]); } bool IsLeftHandDriving(const NodeID id) const override final { // TODO: can be moved to a data block indexed by GeometryID return edge_based_node_data.IsLeftHandDriving(id); } bool IsSegregated(const NodeID id) const override final { return edge_based_node_data.IsSegregated(id); } std::vector GetOverridesThatStartAt(const NodeID edge_based_node_id) const override final { std::vector results; // heterogeneous comparison: struct Comp { bool operator()(const extractor::StorageManeuverOverride &s, NodeID i) const { return s.start_node < i; } bool operator()(NodeID i, const extractor::StorageManeuverOverride &s) const { return i < s.start_node; } }; auto found_range = std::equal_range( m_maneuver_overrides.begin(), m_maneuver_overrides.end(), edge_based_node_id, Comp{}); std::for_each(found_range.first, found_range.second, [&](const auto & override) { std::vector sequence( m_maneuver_override_node_sequences.begin() + override.node_sequence_offset_begin, m_maneuver_override_node_sequences.begin() + override.node_sequence_offset_end); results.push_back(extractor::ManeuverOverride{std::move(sequence), override.instruction_node, override.override_type, override.direction}); }); return results; } }; template class ContiguousInternalMemoryDataFacade; template <> class ContiguousInternalMemoryDataFacade : public ContiguousInternalMemoryDataFacadeBase, public ContiguousInternalMemoryAlgorithmDataFacade { public: ContiguousInternalMemoryDataFacade(std::shared_ptr allocator, const std::string &metric_name, const std::size_t exclude_index) : ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index), ContiguousInternalMemoryAlgorithmDataFacade(allocator, metric_name, exclude_index) { } }; template <> class ContiguousInternalMemoryAlgorithmDataFacade : public AlgorithmDataFacade { // MLD data partitioner::MultiLevelPartitionView mld_partition; partitioner::CellStorageView mld_cell_storage; customizer::CellMetricView mld_cell_metric; using QueryGraph = customizer::MultiLevelEdgeBasedGraphView; using GraphNode = QueryGraph::NodeArrayEntry; using GraphEdge = QueryGraph::EdgeArrayEntry; QueryGraph query_graph; void InitializeInternalPointers(const storage::DataLayout &data_layout, char *memory_block, const std::string &metric_name, const std::size_t exclude_index) { InitializeMLDDataPointers(data_layout, memory_block, metric_name, exclude_index); InitializeGraphPointer(data_layout, memory_block); } void InitializeMLDDataPointers(const storage::DataLayout &data_layout, char *memory_block, const std::string &metric_name, const std::size_t exclude_index) { if (data_layout.GetBlockSize("/mld/multilevelpartition/partition") > 0) { BOOST_ASSERT(data_layout.GetBlockSize("/mld/multilevelpartition/level_data") > 0); BOOST_ASSERT(data_layout.GetBlockSize("/mld/multilevelpartition/cell_to_children") > 0); auto level_data = data_layout.GetBlockPtr( memory_block, "/mld/multilevelpartition/level_data"); auto mld_partition_ptr = data_layout.GetBlockPtr( memory_block, "/mld/multilevelpartition/partition"); auto partition_entries_count = data_layout.GetBlockEntries("/mld/multilevelpartition/partition"); util::vector_view partition(mld_partition_ptr, partition_entries_count); auto mld_chilren_ptr = data_layout.GetBlockPtr( memory_block, "/mld/multilevelpartition/cell_to_children"); auto children_entries_count = data_layout.GetBlockEntries("/mld/multilevelpartition/cell_to_children"); util::vector_view cell_to_children(mld_chilren_ptr, children_entries_count); mld_partition = partitioner::MultiLevelPartitionView{level_data, partition, cell_to_children}; } const auto exclude_prefix = "/mld/metrics/" + metric_name + "/exclude/" + std::to_string(exclude_index); const auto weights_block_id = exclude_prefix + "/weights"; const auto durations_block_id = exclude_prefix + "/durations"; if (data_layout.GetBlockSize(weights_block_id) > 0) { auto mld_cell_weights_ptr = data_layout.GetBlockPtr(memory_block, weights_block_id); auto mld_cell_durations_ptr = data_layout.GetBlockPtr(memory_block, durations_block_id); auto weight_entries_count = data_layout.GetBlockEntries(weights_block_id); auto duration_entries_count = data_layout.GetBlockEntries(durations_block_id); BOOST_ASSERT(weight_entries_count == duration_entries_count); util::vector_view weights(mld_cell_weights_ptr, weight_entries_count); util::vector_view durations(mld_cell_durations_ptr, duration_entries_count); mld_cell_metric = customizer::CellMetricView{std::move(weights), std::move(durations)}; } if (data_layout.GetBlockSize("/mld/cellstorage/cells") > 0) { auto mld_source_boundary_ptr = data_layout.GetBlockPtr(memory_block, "/mld/cellstorage/source_boundary"); auto mld_destination_boundary_ptr = data_layout.GetBlockPtr( memory_block, "/mld/cellstorage/destination_boundary"); auto mld_cells_ptr = data_layout.GetBlockPtr( memory_block, "/mld/cellstorage/cells"); auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr( memory_block, "/mld/cellstorage/level_to_cell_offset"); auto source_boundary_entries_count = data_layout.GetBlockEntries("/mld/cellstorage/source_boundary"); auto destination_boundary_entries_count = data_layout.GetBlockEntries("/mld/cellstorage/destination_boundary"); auto cells_entries_counts = data_layout.GetBlockEntries("/mld/cellstorage/cells"); auto cell_level_offsets_entries_count = data_layout.GetBlockEntries("/mld/cellstorage/level_to_cell_offset"); util::vector_view source_boundary(mld_source_boundary_ptr, source_boundary_entries_count); util::vector_view destination_boundary(mld_destination_boundary_ptr, destination_boundary_entries_count); util::vector_view cells(mld_cells_ptr, cells_entries_counts); util::vector_view level_offsets(mld_cell_level_offsets_ptr, cell_level_offsets_entries_count); mld_cell_storage = partitioner::CellStorageView{std::move(source_boundary), std::move(destination_boundary), std::move(cells), std::move(level_offsets)}; } } void InitializeGraphPointer(const storage::DataLayout &data_layout, char *memory_block) { auto graph_nodes_ptr = data_layout.GetBlockPtr(memory_block, "/mld/multilevelgraph/node_array"); auto graph_edges_ptr = data_layout.GetBlockPtr(memory_block, "/mld/multilevelgraph/edge_array"); auto graph_node_to_offset_ptr = data_layout.GetBlockPtr( memory_block, "/mld/multilevelgraph/node_to_edge_offset"); util::vector_view node_list( graph_nodes_ptr, data_layout.GetBlockEntries("/mld/multilevelgraph/node_array")); util::vector_view edge_list( graph_edges_ptr, data_layout.GetBlockEntries("/mld/multilevelgraph/edge_array")); util::vector_view node_to_offset( graph_node_to_offset_ptr, data_layout.GetBlockEntries("/mld/multilevelgraph/node_to_edge_offset")); query_graph = QueryGraph(std::move(node_list), std::move(edge_list), std::move(node_to_offset)); } // allocator that keeps the allocation data std::shared_ptr allocator; public: ContiguousInternalMemoryAlgorithmDataFacade( std::shared_ptr allocator_, const std::string &metric_name, const std::size_t exclude_index) : allocator(std::move(allocator_)) { InitializeInternalPointers( allocator->GetLayout(), allocator->GetMemory(), metric_name, exclude_index); } const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const override { return mld_partition; } const partitioner::CellStorageView &GetCellStorage() const override { return mld_cell_storage; } const customizer::CellMetricView &GetCellMetric() const override { return mld_cell_metric; } // search graph access unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); } unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); } unsigned GetOutDegree(const NodeID n) const override final { return query_graph.GetOutDegree(n); } NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); } const EdgeData &GetEdgeData(const EdgeID e) const override final { return query_graph.GetEdgeData(e); } EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final { return query_graph.GetAdjacentEdgeRange(node); } EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final { return query_graph.GetBorderEdgeRange(level, node); } // searches for a specific edge EdgeID FindEdge(const NodeID from, const NodeID to) const override final { return query_graph.FindEdge(from, to); } }; template <> class ContiguousInternalMemoryDataFacade final : public ContiguousInternalMemoryDataFacadeBase, public ContiguousInternalMemoryAlgorithmDataFacade { private: public: ContiguousInternalMemoryDataFacade(std::shared_ptr allocator, const std::string &metric_name, const std::size_t exclude_index) : ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index), ContiguousInternalMemoryAlgorithmDataFacade(allocator, metric_name, exclude_index) { } }; } } } #endif // CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP