diff --git a/include/customizer/edge_based_graph.hpp b/include/customizer/edge_based_graph.hpp index 63e0b0fef..de10a20af 100644 --- a/include/customizer/edge_based_graph.hpp +++ b/include/customizer/edge_based_graph.hpp @@ -18,16 +18,21 @@ namespace customizer using EdgeBasedGraphEdgeData = partition::EdgeBasedGraphEdgeData; -struct MultiLevelEdgeBasedGraph : public partition::MultiLevelGraph +struct MultiLevelEdgeBasedGraph + : public partition::MultiLevelGraph { - using Base = partition::MultiLevelGraph; + using Base = partition::MultiLevelGraph; using Base::Base; }; struct MultiLevelEdgeBasedGraphView - : public partition::MultiLevelGraph + : public partition::MultiLevelGraph { - using Base = partition::MultiLevelGraph; + using Base = partition::MultiLevelGraph; using Base::Base; }; diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index ad1bc01a4..1ad3f13ec 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -202,8 +202,10 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade using super = BaseDataFacade; using IndexBlock = util::RangeTable<16, osrm::storage::MemorySetting::SharedMemory>::BlockT; using RTreeLeaf = super::RTreeLeaf; - using SharedRTree = - util::StaticRTree::vector, osrm::storage::MemorySetting::SharedMemory>; + using SharedRTree = util::StaticRTree< + RTreeLeaf, + util::ShM::vector, + osrm::storage::MemorySetting::SharedMemory>; using SharedGeospatialQuery = GeospatialQuery; using RTreeNode = SharedRTree::TreeNode; @@ -212,28 +214,40 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade extractor::Datasources *m_datasources; unsigned m_check_sum; - util::ShM::vector m_coordinate_list; + util::ShM::vector + m_coordinate_list; util::PackedVector m_osmnodeid_list; util::ShM::vector m_via_geometry_list; util::ShM::vector m_name_ID_list; util::ShM::vector m_lane_data_id; - util::ShM::vector m_turn_instruction_list; - util::ShM::vector m_travel_mode_list; - util::ShM::vector m_pre_turn_bearing; - util::ShM::vector m_post_turn_bearing; + util::ShM::vector m_turn_instruction_list; + util::ShM::vector + m_travel_mode_list; + util::ShM::vector + m_pre_turn_bearing; + util::ShM::vector + m_post_turn_bearing; util::NameTable m_names_table; util::ShM::vector m_name_begin_indices; util::ShM::vector m_is_core_node; - util::ShM::vector m_lane_description_offsets; - util::ShM::vector m_lane_description_masks; - util::ShM::vector m_turn_weight_penalties; - util::ShM::vector m_turn_duration_penalties; + util::ShM::vector + m_lane_description_offsets; + util::ShM::vector m_lane_description_masks; + util::ShM::vector + m_turn_weight_penalties; + util::ShM::vector + m_turn_duration_penalties; extractor::SegmentDataView segment_data; util::ShM::vector m_datasource_name_data; - util::ShM::vector m_datasource_name_offsets; - util::ShM::vector m_datasource_name_lengths; - util::ShM::vector m_lane_tupel_id_pairs; + util::ShM::vector + m_datasource_name_offsets; + util::ShM::vector + m_datasource_name_lengths; + util::ShM::vector + m_lane_tupel_id_pairs; std::unique_ptr m_static_rtree; std::unique_ptr m_geospatial_query; @@ -241,17 +255,22 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade util::NameTable m_name_table; // bearing classes by node based node - util::ShM::vector m_bearing_class_id_table; + util::ShM::vector + m_bearing_class_id_table; // entry class IDs - util::ShM::vector m_entry_class_id_list; + util::ShM::vector + m_entry_class_id_list; // 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::ShM::vector m_entry_class_table; + util::ShM::vector + m_entry_class_table; // the look-up table for distinct bearing classes. A bearing class lists the available bearings // at an intersection - std::shared_ptr> m_bearing_ranges_table; - util::ShM::vector m_bearing_values_table; + std::shared_ptr> + m_bearing_ranges_table; + util::ShM::vector + m_bearing_values_table; // allocator that keeps the allocation data std::shared_ptr allocator; @@ -327,8 +346,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade const auto travel_mode_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::TRAVEL_MODE); - util::ShM::vector travel_mode_list( - travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]); + util::ShM::vector + travel_mode_list(travel_mode_list_ptr, + data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]); m_travel_mode_list = std::move(travel_mode_list); const auto lane_data_id_ptr = @@ -340,16 +360,19 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade const auto lane_tupel_id_pair_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::TURN_LANE_DATA); - util::ShM::vector lane_tupel_id_pair( - lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]); + util::ShM::vector + lane_tupel_id_pair(lane_tupel_id_pair_ptr, + data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]); m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair); const auto turn_instruction_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::TURN_INSTRUCTION); - util::ShM::vector turn_instruction_list( - turn_instruction_list_ptr, - data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]); + util::ShM::vector + turn_instruction_list(turn_instruction_list_ptr, + data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]); m_turn_instruction_list = std::move(turn_instruction_list); const auto name_id_list_ptr = @@ -360,20 +383,25 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade const auto entry_class_id_list_ptr = data_layout.GetBlockPtr(memory_block, storage::DataLayout::ENTRY_CLASSID); - typename util::ShM::vector entry_class_id_list( - entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]); + typename util::ShM::vector + entry_class_id_list(entry_class_id_list_ptr, + data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]); m_entry_class_id_list = std::move(entry_class_id_list); const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::PRE_TURN_BEARING); - typename util::ShM::vector pre_turn_bearing( - pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]); + typename util::ShM::vector + pre_turn_bearing(pre_turn_bearing_ptr, + data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]); m_pre_turn_bearing = std::move(pre_turn_bearing); const auto post_turn_bearing_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::POST_TURN_BEARING); - typename util::ShM::vector post_turn_bearing( - post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]); + typename util::ShM::vector + post_turn_bearing(post_turn_bearing_ptr, + data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]); m_post_turn_bearing = std::move(post_turn_bearing); } @@ -406,8 +434,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade auto masks_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS); - util::ShM::vector masks( - masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]); + util::ShM::vector + masks(masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]); m_lane_description_masks = std::move(masks); } @@ -415,22 +444,25 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade { auto turn_weight_penalties_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES); - m_turn_weight_penalties = util::ShM::vector( - turn_weight_penalties_ptr, - data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]); + m_turn_weight_penalties = + util::ShM::vector( + turn_weight_penalties_ptr, + data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]); auto turn_duration_penalties_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::TURN_DURATION_PENALTIES); - m_turn_duration_penalties = util::ShM::vector( - turn_duration_penalties_ptr, - data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]); + m_turn_duration_penalties = + util::ShM::vector( + turn_duration_penalties_ptr, + data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]); } void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block) { auto geometries_index_ptr = data_layout.GetBlockPtr(memory_block, storage::DataLayout::GEOMETRIES_INDEX); - util::ShM::vector geometry_begin_indices( - geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]); + util::ShM::vector + geometry_begin_indices(geometries_index_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]); auto geometries_node_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST); @@ -440,32 +472,37 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST); - util::ShM::vector geometry_fwd_weight_list( - geometries_fwd_weight_list_ptr, - data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]); + util::ShM::vector + geometry_fwd_weight_list( + geometries_fwd_weight_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]); auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST); - util::ShM::vector geometry_rev_weight_list( - geometries_rev_weight_list_ptr, - data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]); + util::ShM::vector + geometry_rev_weight_list( + geometries_rev_weight_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]); auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST); - util::ShM::vector geometry_fwd_duration_list( - geometries_fwd_duration_list_ptr, - data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]); + util::ShM::vector + geometry_fwd_duration_list( + geometries_fwd_duration_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]); auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST); - util::ShM::vector geometry_rev_duration_list( - geometries_rev_duration_list_ptr, - data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]); + util::ShM::vector + geometry_rev_duration_list( + geometries_rev_duration_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]); auto datasources_list_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::DATASOURCES_LIST); - util::ShM::vector datasources_list( - datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]); + util::ShM::vector + datasources_list(datasources_list_ptr, + data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]); segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices), std::move(geometry_node_list), @@ -483,14 +520,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade { auto bearing_class_id_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::BEARING_CLASSID); - typename util::ShM::vector bearing_class_id_table( - bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]); + typename util::ShM::vector + bearing_class_id_table(bearing_class_id_ptr, + data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]); m_bearing_class_id_table = std::move(bearing_class_id_table); auto bearing_class_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::BEARING_VALUES); - typename util::ShM::vector bearing_class_table( - bearing_class_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]); + typename util::ShM::vector + bearing_class_table(bearing_class_ptr, + data_layout.num_entries[storage::DataLayout::BEARING_VALUES]); m_bearing_values_table = std::move(bearing_class_table); auto offsets_ptr = @@ -502,13 +541,18 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade util::ShM::vector bearing_blocks( blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]); - m_bearing_ranges_table = std::make_unique>( - bearing_offsets, bearing_blocks, static_cast(m_bearing_values_table.size())); + m_bearing_ranges_table = + std::make_unique>( + bearing_offsets, + bearing_blocks, + static_cast(m_bearing_values_table.size())); auto entry_class_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::ENTRY_CLASS); - typename util::ShM::vector entry_class_table( - entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]); + typename util::ShM::vector + entry_class_table(entry_class_ptr, + data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]); m_entry_class_table = std::move(entry_class_table); } @@ -930,15 +974,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade memory_block, storage::DataLayout::MLD_PARTITION); auto partition_entries_count = data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION); - util::ShM::vector partition(mld_partition_ptr, - partition_entries_count); + util::ShM::vector partition( + mld_partition_ptr, partition_entries_count); auto mld_chilren_ptr = data_layout.GetBlockPtr( memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN); auto children_entries_count = data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN); - util::ShM::vector cell_to_children(mld_chilren_ptr, - children_entries_count); + util::ShM::vector cell_to_children( + mld_chilren_ptr, children_entries_count); mld_partition = partition::MultiLevelPartitionView{level_data, partition, cell_to_children}; @@ -970,15 +1014,18 @@ class ContiguousInternalMemoryAlgorithmDataFacade auto cell_level_offsets_entries_count = data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS); - util::ShM::vector weights(mld_cell_weights_ptr, weight_entries_count); - util::ShM::vector source_boundary(mld_source_boundary_ptr, - source_boundary_entries_count); - util::ShM::vector destination_boundary( - mld_destination_boundary_ptr, destination_boundary_entries_count); - util::ShM::vector cells( - mld_cells_ptr, cells_entries_counts); - util::ShM::vector level_offsets(mld_cell_level_offsets_ptr, - cell_level_offsets_entries_count); + util::ShM::vector weights( + mld_cell_weights_ptr, weight_entries_count); + util::ShM::vector source_boundary( + mld_source_boundary_ptr, source_boundary_entries_count); + util::ShM::vector + destination_boundary(mld_destination_boundary_ptr, + destination_boundary_entries_count); + util::ShM::vector + cells(mld_cells_ptr, cells_entries_counts); + util::ShM::vector + level_offsets(mld_cell_level_offsets_ptr, cell_level_offsets_entries_count); mld_cell_storage = partition::CellStorageView{std::move(weights), std::move(source_boundary), @@ -1002,9 +1049,9 @@ class ContiguousInternalMemoryAlgorithmDataFacade graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]); util::ShM::vector edge_list( graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]); - util::ShM::vector node_to_offset( - graph_node_to_offset_ptr, - data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]); + util::ShM::vector + node_to_offset(graph_node_to_offset_ptr, + data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]); query_graph = QueryGraph(std::move(node_list), std::move(edge_list), std::move(node_to_offset)); diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp~RF1bba25.TMP b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp~RF1bba25.TMP new file mode 100644 index 000000000..ad1bc01a4 --- /dev/null +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp~RF1bba25.TMP @@ -0,0 +1,1087 @@ +#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/geospatial_query.hpp" + +#include "customizer/edge_based_graph.hpp" + +#include "extractor/datasources.hpp" +#include "extractor/guidance/turn_instruction.hpp" +#include "extractor/guidance/turn_lane_types.hpp" +#include "extractor/profile_properties.hpp" +#include "extractor/segment_data_container.hpp" + +#include "partition/cell_storage.hpp" +#include "partition/multi_level_partition.hpp" + +#include "storage/shared_datatype.hpp" +#include "storage/shared_memory.hpp" + +#include "util/exception.hpp" +#include "util/exception_utils.hpp" +#include "util/guidance/bearing_class.hpp" +#include "util/guidance/entry_class.hpp" +#include "util/guidance/turn_bearing.hpp" +#include "util/guidance/turn_lanes.hpp" +#include "util/log.hpp" +#include "util/name_table.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::StaticGraph; + using GraphNode = QueryGraph::NodeArrayEntry; + using GraphEdge = QueryGraph::EdgeArrayEntry; + + std::unique_ptr m_query_graph; + + // allocator that keeps the allocation data + std::shared_ptr allocator; + + void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block) + { + auto graph_nodes_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::CH_GRAPH_NODE_LIST); + + auto graph_edges_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST); + + util::ShM::vector node_list( + graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]); + util::ShM::vector edge_list( + graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]); + m_query_graph.reset(new QueryGraph(node_list, edge_list)); + } + + public: + ContiguousInternalMemoryAlgorithmDataFacade( + std::shared_ptr allocator_) + : allocator(std::move(allocator_)) + { + InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory()); + } + + void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block) + { + InitializeGraphPointer(data_layout, memory_block); + } + + // 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); } + + EdgeData &GetEdgeData(const EdgeID e) const override final + { + return m_query_graph->GetEdgeData(e); + } + + EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); } + + EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); } + + 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); + } +}; + +template <> +class ContiguousInternalMemoryAlgorithmDataFacade + : public datafacade::AlgorithmDataFacade +{ + private: + util::ShM::vector m_is_core_node; + + // allocator that keeps the allocation data + std::shared_ptr allocator; + + void InitializeCoreInformationPointer(storage::DataLayout &data_layout, char *memory_block) + { + auto core_marker_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::CH_CORE_MARKER); + util::ShM::vector is_core_node( + core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]); + m_is_core_node = std::move(is_core_node); + } + + public: + ContiguousInternalMemoryAlgorithmDataFacade( + std::shared_ptr allocator_) + : allocator(std::move(allocator_)) + { + InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory()); + } + + void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block) + { + InitializeCoreInformationPointer(data_layout, memory_block); + } + + bool IsCoreNode(const NodeID id) const override final + { + BOOST_ASSERT(id < m_is_core_node.size()); + return m_is_core_node[id]; + } +}; + +/** + * 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, osrm::storage::MemorySetting::SharedMemory>::BlockT; + using RTreeLeaf = super::RTreeLeaf; + using SharedRTree = + util::StaticRTree::vector, osrm::storage::MemorySetting::SharedMemory>; + using SharedGeospatialQuery = GeospatialQuery; + using RTreeNode = SharedRTree::TreeNode; + + std::string m_timestamp; + extractor::ProfileProperties *m_profile_properties; + extractor::Datasources *m_datasources; + + unsigned m_check_sum; + util::ShM::vector m_coordinate_list; + util::PackedVector m_osmnodeid_list; + util::ShM::vector m_via_geometry_list; + util::ShM::vector m_name_ID_list; + util::ShM::vector m_lane_data_id; + util::ShM::vector m_turn_instruction_list; + util::ShM::vector m_travel_mode_list; + util::ShM::vector m_pre_turn_bearing; + util::ShM::vector m_post_turn_bearing; + util::NameTable m_names_table; + util::ShM::vector m_name_begin_indices; + util::ShM::vector m_is_core_node; + util::ShM::vector m_lane_description_offsets; + util::ShM::vector m_lane_description_masks; + util::ShM::vector m_turn_weight_penalties; + util::ShM::vector m_turn_duration_penalties; + extractor::SegmentDataView segment_data; + + util::ShM::vector m_datasource_name_data; + util::ShM::vector m_datasource_name_offsets; + util::ShM::vector m_datasource_name_lengths; + util::ShM::vector m_lane_tupel_id_pairs; + + std::unique_ptr m_static_rtree; + std::unique_ptr m_geospatial_query; + boost::filesystem::path file_index_path; + + util::NameTable m_name_table; + // bearing classes by node based node + util::ShM::vector m_bearing_class_id_table; + // entry class IDs + util::ShM::vector m_entry_class_id_list; + + // 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::ShM::vector m_entry_class_table; + // the look-up table for distinct bearing classes. A bearing class lists the available bearings + // at an intersection + std::shared_ptr> m_bearing_ranges_table; + util::ShM::vector m_bearing_values_table; + + // allocator that keeps the allocation data + std::shared_ptr allocator; + + void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout, char *memory_block) + { + m_profile_properties = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::PROPERTIES); + } + + void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block) + { + auto timestamp_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::TIMESTAMP); + m_timestamp.resize(data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP)); + std::copy(timestamp_ptr, + timestamp_ptr + data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP), + m_timestamp.begin()); + } + + void InitializeChecksumPointer(storage::DataLayout &data_layout, char *memory_block) + { + m_check_sum = + *data_layout.GetBlockPtr(memory_block, storage::DataLayout::HSGR_CHECKSUM); + util::Log() << "set checksum: " << m_check_sum; + } + + void InitializeRTreePointers(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, storage::DataLayout::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); + } + + auto tree_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::R_SEARCH_TREE); + m_static_rtree.reset( + new SharedRTree(tree_ptr, + data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE], + file_index_path, + m_coordinate_list)); + m_geospatial_query.reset( + new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this)); + } + + void InitializeNodeAndEdgeInformationPointers(storage::DataLayout &data_layout, + char *memory_block) + { + const auto coordinate_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::COORDINATE_LIST); + m_coordinate_list.reset(coordinate_list_ptr, + data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]); + + for (unsigned i = 0; i < m_coordinate_list.size(); ++i) + { + BOOST_ASSERT(GetCoordinateOfNode(i).IsValid()); + } + + const auto osmnodeid_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::OSM_NODE_ID_LIST); + m_osmnodeid_list.reset(osmnodeid_list_ptr, + data_layout.num_entries[storage::DataLayout::OSM_NODE_ID_LIST]); + // We (ab)use the number of coordinates here because we know we have the same amount of ids + m_osmnodeid_list.set_number_of_entries( + data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]); + + const auto travel_mode_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::TRAVEL_MODE); + util::ShM::vector travel_mode_list( + travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]); + m_travel_mode_list = std::move(travel_mode_list); + + const auto lane_data_id_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::LANE_DATA_ID); + util::ShM::vector lane_data_id( + lane_data_id_ptr, data_layout.num_entries[storage::DataLayout::LANE_DATA_ID]); + m_lane_data_id = std::move(lane_data_id); + + const auto lane_tupel_id_pair_ptr = + data_layout.GetBlockPtr( + memory_block, storage::DataLayout::TURN_LANE_DATA); + util::ShM::vector lane_tupel_id_pair( + lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]); + m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair); + + const auto turn_instruction_list_ptr = + data_layout.GetBlockPtr( + memory_block, storage::DataLayout::TURN_INSTRUCTION); + util::ShM::vector turn_instruction_list( + turn_instruction_list_ptr, + data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]); + m_turn_instruction_list = std::move(turn_instruction_list); + + const auto name_id_list_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::NAME_ID_LIST); + util::ShM::vector name_id_list( + name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]); + m_name_ID_list = std::move(name_id_list); + + const auto entry_class_id_list_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::ENTRY_CLASSID); + typename util::ShM::vector entry_class_id_list( + entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]); + m_entry_class_id_list = std::move(entry_class_id_list); + + const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::PRE_TURN_BEARING); + typename util::ShM::vector pre_turn_bearing( + pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]); + m_pre_turn_bearing = std::move(pre_turn_bearing); + + const auto post_turn_bearing_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::POST_TURN_BEARING); + typename util::ShM::vector post_turn_bearing( + post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]); + m_post_turn_bearing = std::move(post_turn_bearing); + } + + void InitializeViaNodeListPointer(storage::DataLayout &data_layout, char *memory_block) + { + auto via_geometry_list_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::VIA_NODE_LIST); + util::ShM::vector via_geometry_list( + via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]); + m_via_geometry_list = std::move(via_geometry_list); + } + + void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block) + { + auto name_data_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::NAME_CHAR_DATA); + const auto name_data_size = data_layout.num_entries[storage::DataLayout::NAME_CHAR_DATA]; + m_name_table.reset(name_data_ptr, name_data_ptr + name_data_size); + } + + void InitializeTurnLaneDescriptionsPointers(storage::DataLayout &data_layout, + char *memory_block) + { + auto offsets_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS); + util::ShM::vector offsets( + offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]); + m_lane_description_offsets = std::move(offsets); + + auto masks_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS); + + util::ShM::vector masks( + masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]); + m_lane_description_masks = std::move(masks); + } + + void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block) + { + auto turn_weight_penalties_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES); + m_turn_weight_penalties = util::ShM::vector( + turn_weight_penalties_ptr, + data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]); + auto turn_duration_penalties_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::TURN_DURATION_PENALTIES); + m_turn_duration_penalties = util::ShM::vector( + turn_duration_penalties_ptr, + data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]); + } + + void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block) + { + auto geometries_index_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::GEOMETRIES_INDEX); + util::ShM::vector geometry_begin_indices( + geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]); + + auto geometries_node_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST); + util::ShM::vector geometry_node_list( + geometries_node_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]); + + auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST); + util::ShM::vector geometry_fwd_weight_list( + geometries_fwd_weight_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]); + + auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST); + util::ShM::vector geometry_rev_weight_list( + geometries_rev_weight_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]); + + auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST); + util::ShM::vector geometry_fwd_duration_list( + geometries_fwd_duration_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]); + + auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST); + util::ShM::vector geometry_rev_duration_list( + geometries_rev_duration_list_ptr, + data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]); + + auto datasources_list_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::DATASOURCES_LIST); + util::ShM::vector datasources_list( + datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]); + + 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(datasources_list)}; + + m_datasources = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::DATASOURCES_NAMES); + } + + void InitializeIntersectionClassPointers(storage::DataLayout &data_layout, char *memory_block) + { + auto bearing_class_id_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::BEARING_CLASSID); + typename util::ShM::vector bearing_class_id_table( + bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]); + m_bearing_class_id_table = std::move(bearing_class_id_table); + + auto bearing_class_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::BEARING_VALUES); + typename util::ShM::vector bearing_class_table( + bearing_class_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]); + m_bearing_values_table = std::move(bearing_class_table); + + auto offsets_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::BEARING_OFFSETS); + auto blocks_ptr = + data_layout.GetBlockPtr(memory_block, storage::DataLayout::BEARING_BLOCKS); + util::ShM::vector bearing_offsets( + offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]); + util::ShM::vector bearing_blocks( + blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]); + + m_bearing_ranges_table = std::make_unique>( + bearing_offsets, bearing_blocks, static_cast(m_bearing_values_table.size())); + + auto entry_class_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::ENTRY_CLASS); + typename util::ShM::vector entry_class_table( + entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]); + m_entry_class_table = std::move(entry_class_table); + } + + void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block) + { + InitializeChecksumPointer(data_layout, memory_block); + InitializeNodeAndEdgeInformationPointers(data_layout, memory_block); + InitializeTurnPenalties(data_layout, memory_block); + InitializeGeometryPointers(data_layout, memory_block); + InitializeTimestampPointer(data_layout, memory_block); + InitializeViaNodeListPointer(data_layout, memory_block); + InitializeNamePointers(data_layout, memory_block); + InitializeTurnLaneDescriptionsPointers(data_layout, memory_block); + InitializeProfilePropertiesPointer(data_layout, memory_block); + InitializeRTreePointers(data_layout, memory_block); + InitializeIntersectionClassPointers(data_layout, memory_block); + } + + public: + // allows switching between process_memory/shared_memory datafacade, based on the type of + // allocator + ContiguousInternalMemoryDataFacadeBase(std::shared_ptr allocator_) + : allocator(std::move(allocator_)) + { + InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory()); + } + + // 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.at(id); + } + + virtual 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 GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final + { + return m_via_geometry_list.at(id); + } + + 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]; + } + + extractor::guidance::TurnInstruction + GetTurnInstructionForEdgeID(const EdgeID id) const override final + { + return m_turn_instruction_list.at(id); + } + + extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final + { + return m_travel_mode_list.at(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 override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodesInRange(input_coordinate, max_distance); + } + + std::vector + NearestPhantomNodesInRange(const util::Coordinate input_coordinate, + const float max_distance, + const int bearing, + const int bearing_range) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodesInRange( + input_coordinate, max_distance, bearing, bearing_range); + } + + std::vector + NearestPhantomNodes(const util::Coordinate input_coordinate, + const unsigned max_results) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results); + } + + std::vector + NearestPhantomNodes(const util::Coordinate input_coordinate, + const unsigned max_results, + const double max_distance) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodes(input_coordinate, max_results, max_distance); + } + + std::vector + NearestPhantomNodes(const util::Coordinate input_coordinate, + const unsigned max_results, + const int bearing, + const int bearing_range) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodes( + input_coordinate, max_results, bearing, bearing_range); + } + + std::vector + NearestPhantomNodes(const util::Coordinate input_coordinate, + const unsigned max_results, + const double max_distance, + const int bearing, + const int bearing_range) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodes( + input_coordinate, max_results, max_distance, bearing, bearing_range); + } + + std::pair NearestPhantomNodeWithAlternativeFromBigComponent( + const util::Coordinate input_coordinate) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( + input_coordinate); + } + + std::pair NearestPhantomNodeWithAlternativeFromBigComponent( + const util::Coordinate input_coordinate, const double max_distance) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( + input_coordinate, max_distance); + } + + std::pair + NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate, + const double max_distance, + const int bearing, + const int bearing_range) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( + input_coordinate, max_distance, bearing, bearing_range); + } + + std::pair + NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate, + const int bearing, + const int bearing_range) const override final + { + BOOST_ASSERT(m_geospatial_query.get()); + + return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent( + input_coordinate, bearing, bearing_range); + } + + unsigned GetCheckSum() const override final { return m_check_sum; } + + NameID GetNameIndexFromEdgeID(const EdgeID id) const override final + { + return m_name_ID_list.at(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 GetDatasourceName(const DatasourceID id) const override final + { + return m_datasources->GetSourceName(id); + } + + std::string GetTimestamp() const override final { return m_timestamp; } + + 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(); + } + + BearingClassID GetBearingClassID(const NodeID id) const override final + { + return m_bearing_class_id_table.at(id); + } + + util::guidance::BearingClass + GetBearingClass(const BearingClassID bearing_class_id) const override final + { + BOOST_ASSERT(bearing_class_id != INVALID_BEARING_CLASSID); + auto range = m_bearing_ranges_table->GetRange(bearing_class_id); + util::guidance::BearingClass result; + for (auto itr = m_bearing_values_table.begin() + range.front(); + itr != m_bearing_values_table.begin() + range.back() + 1; + ++itr) + result.add(*itr); + return result; + } + + EntryClassID GetEntryClassID(const EdgeID eid) const override final + { + return m_entry_class_id_list.at(eid); + } + + util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final + { + return m_pre_turn_bearing.at(eid); + } + util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final + { + return m_post_turn_bearing.at(eid); + } + + util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final + { + return m_entry_class_table.at(entry_class_id); + } + + bool hasLaneData(const EdgeID id) const override final + { + return INVALID_LANE_DATAID != m_lane_data_id.at(id); + } + + util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final + { + BOOST_ASSERT(hasLaneData(id)); + return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id)); + } + + extractor::guidance::TurnLaneDescription + GetTurnDescription(const LaneDescriptionID lane_description_id) const override final + { + if (lane_description_id == INVALID_LANE_DESCRIPTIONID) + return {}; + else + return extractor::guidance::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]); + } +}; + +template class ContiguousInternalMemoryDataFacade; + +template <> +class ContiguousInternalMemoryDataFacade + : public ContiguousInternalMemoryDataFacadeBase, + public ContiguousInternalMemoryAlgorithmDataFacade +{ + public: + ContiguousInternalMemoryDataFacade(std::shared_ptr allocator) + : ContiguousInternalMemoryDataFacadeBase(allocator), + ContiguousInternalMemoryAlgorithmDataFacade(allocator) + + { + } +}; + +template <> +class ContiguousInternalMemoryDataFacade final + : public ContiguousInternalMemoryDataFacade, + public ContiguousInternalMemoryAlgorithmDataFacade +{ + public: + ContiguousInternalMemoryDataFacade(std::shared_ptr allocator) + : ContiguousInternalMemoryDataFacade(allocator), + ContiguousInternalMemoryAlgorithmDataFacade(allocator) + + { + } +}; + +template <> +class ContiguousInternalMemoryAlgorithmDataFacade + : public datafacade::AlgorithmDataFacade +{ + // MLD data + partition::MultiLevelPartitionView mld_partition; + partition::CellStorageView mld_cell_storage; + using QueryGraph = customizer::MultiLevelEdgeBasedGraphView; + using GraphNode = QueryGraph::NodeArrayEntry; + using GraphEdge = QueryGraph::EdgeArrayEntry; + + QueryGraph query_graph; + + void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block) + { + InitializeMLDDataPointers(data_layout, memory_block); + InitializeGraphPointer(data_layout, memory_block); + } + + void InitializeMLDDataPointers(storage::DataLayout &data_layout, char *memory_block) + { + if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0) + { + BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0); + BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0); + + auto level_data = + *data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_LEVEL_DATA); + + auto mld_partition_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_PARTITION); + auto partition_entries_count = + data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION); + util::ShM::vector partition(mld_partition_ptr, + partition_entries_count); + + auto mld_chilren_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN); + auto children_entries_count = + data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN); + util::ShM::vector cell_to_children(mld_chilren_ptr, + children_entries_count); + + mld_partition = + partition::MultiLevelPartitionView{level_data, partition, cell_to_children}; + } + + if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_WEIGHTS) > 0) + { + BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0); + BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS) > 0); + + auto mld_cell_weights_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_CELL_WEIGHTS); + auto mld_source_boundary_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY); + auto mld_destination_boundary_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_CELL_DESTINATION_BOUNDARY); + auto mld_cells_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_CELLS); + auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_CELL_LEVEL_OFFSETS); + + auto weight_entries_count = + data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS); + auto source_boundary_entries_count = + data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY); + auto destination_boundary_entries_count = + data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DESTINATION_BOUNDARY); + auto cells_entries_counts = data_layout.GetBlockEntries(storage::DataLayout::MLD_CELLS); + auto cell_level_offsets_entries_count = + data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS); + + util::ShM::vector weights(mld_cell_weights_ptr, weight_entries_count); + util::ShM::vector source_boundary(mld_source_boundary_ptr, + source_boundary_entries_count); + util::ShM::vector destination_boundary( + mld_destination_boundary_ptr, destination_boundary_entries_count); + util::ShM::vector cells( + mld_cells_ptr, cells_entries_counts); + util::ShM::vector level_offsets(mld_cell_level_offsets_ptr, + cell_level_offsets_entries_count); + + mld_cell_storage = partition::CellStorageView{std::move(weights), + std::move(source_boundary), + std::move(destination_boundary), + std::move(cells), + std::move(level_offsets)}; + } + } + void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block) + { + auto graph_nodes_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_GRAPH_NODE_LIST); + + auto graph_edges_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_GRAPH_EDGE_LIST); + + auto graph_node_to_offset_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET); + + util::ShM::vector node_list( + graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]); + util::ShM::vector edge_list( + graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]); + util::ShM::vector node_to_offset( + graph_node_to_offset_ptr, + data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_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_) + : allocator(std::move(allocator_)) + { + InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory()); + } + + const partition::MultiLevelPartitionView &GetMultiLevelPartition() const override + { + return mld_partition; + } + + const partition::CellStorageView &GetCellStorage() const override { return mld_cell_storage; } + + // 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); + } + + EdgeID BeginEdges(const NodeID n) const override final { return query_graph.BeginEdges(n); } + + EdgeID EndEdges(const NodeID n) const override final { return query_graph.EndEdges(n); } + + 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) + : ContiguousInternalMemoryDataFacadeBase(allocator), + ContiguousInternalMemoryAlgorithmDataFacade(allocator) + + { + } +}; +} +} +} + +#endif // CONTIGUOUS_INTERNALMEM_DATAFACADE_HPP diff --git a/include/extractor/segment_data_container.hpp b/include/extractor/segment_data_container.hpp index 3dcb5b7d6..2d8b01f79 100644 --- a/include/extractor/segment_data_container.hpp +++ b/include/extractor/segment_data_container.hpp @@ -192,10 +192,10 @@ template class SegmentDataContainer friend void io::read(const boost::filesystem::path &path, - detail::SegmentDataContainerImpl &segment_data); + detail::SegmentDataContainerImpl &segment_data); friend void io::write(const boost::filesystem::path &path, - const detail::SegmentDataContainerImpl &segment_data); + const detail::SegmentDataContainerImpl &segment_data); private: Vector index; @@ -208,8 +208,10 @@ template class SegmentDataContainer }; } -using SegmentDataView = detail::SegmentDataContainerImpl; -using SegmentDataContainer = detail::SegmentDataContainerImpl; +using SegmentDataView = + detail::SegmentDataContainerImpl; +using SegmentDataContainer = + detail::SegmentDataContainerImpl; } } diff --git a/include/partition/cell_storage.hpp b/include/partition/cell_storage.hpp index b5d2d1bd4..666f3bdc7 100644 --- a/include/partition/cell_storage.hpp +++ b/include/partition/cell_storage.hpp @@ -186,7 +186,9 @@ template class CellStorageImpl CellStorageImpl() {} - template > + template < + typename GraphT, + typename = std::enable_if> CellStorageImpl(const partition::MultiLevelPartition &partition, const GraphT &base_graph) { // pre-allocate storge for CellData so we can have random access to it by cell id @@ -315,7 +317,8 @@ template class CellStorageImpl weights.resize(weight_offset + 1, INVALID_EDGE_WEIGHT); } - template > + template < + typename = std::enable_if> CellStorageImpl(Vector weights_, Vector source_boundary_, Vector destination_boundary_, @@ -340,7 +343,9 @@ template class CellStorageImpl destination_boundary.empty() ? nullptr : destination_boundary.data()}; } - template > Cell GetCell(LevelID level, CellID id) + template < + typename = std::enable_if> + Cell GetCell(LevelID level, CellID id) { const auto level_index = LevelIDToIndex(level); BOOST_ASSERT(level_index < level_to_cell_offset.size()); @@ -352,9 +357,9 @@ template class CellStorageImpl } friend void io::read(const boost::filesystem::path &path, - detail::CellStorageImpl &storage); + detail::CellStorageImpl &storage); friend void io::write(const boost::filesystem::path &path, - const detail::CellStorageImpl &storage); + const detail::CellStorageImpl &storage); private: Vector weights; diff --git a/include/partition/multi_level_graph.hpp b/include/partition/multi_level_graph.hpp index 387255433..663d59958 100644 --- a/include/partition/multi_level_graph.hpp +++ b/include/partition/multi_level_graph.hpp @@ -193,10 +193,10 @@ class MultiLevelGraph : public util::StaticGraph friend void io::read(const boost::filesystem::path &path, - MultiLevelGraph &graph); + MultiLevelGraph &graph); friend void io::write(const boost::filesystem::path &path, - const MultiLevelGraph &graph); + const MultiLevelGraph &graph); Vector node_to_edge_offset; }; diff --git a/include/partition/multi_level_partition.hpp b/include/partition/multi_level_partition.hpp index 0fbdf5264..a37cfbd3b 100644 --- a/include/partition/multi_level_partition.hpp +++ b/include/partition/multi_level_partition.hpp @@ -28,14 +28,15 @@ namespace detail { template class MultiLevelPartitionImpl; } -using MultiLevelPartition = detail::MultiLevelPartitionImpl; -using MultiLevelPartitionView = detail::MultiLevelPartitionImpl; +using MultiLevelPartition = + detail::MultiLevelPartitionImpl; +using MultiLevelPartitionView = + detail::MultiLevelPartitionImpl; namespace io { template -void read(const boost::filesystem::path &file, - detail::MultiLevelPartitionImpl &mlp); +void read(const boost::filesystem::path &file, detail::MultiLevelPartitionImpl &mlp); template void write(const boost::filesystem::path &file, const detail::MultiLevelPartitionImpl &mlp); @@ -69,7 +70,8 @@ template class MultiLevelPartitionI // cell_sizes is index by level (starting at 0, the base graph). // However level 0 always needs to have cell size 1, since it is the // basegraph. - template > + template > MultiLevelPartitionImpl(const std::vector> &partitions, const std::vector &lidx_to_num_cells) : level_data(MakeLevelData(lidx_to_num_cells)) @@ -77,7 +79,8 @@ template class MultiLevelPartitionI InitializePartitionIDs(partitions); } - template > + template > MultiLevelPartitionImpl(LevelData level_data, Vector partition_, Vector cell_to_children_) @@ -136,9 +139,9 @@ template class MultiLevelPartitionI } friend void io::read(const boost::filesystem::path &file, - MultiLevelPartitionImpl &mlp); + MultiLevelPartitionImpl &mlp); friend void io::write(const boost::filesystem::path &file, - const MultiLevelPartitionImpl &mlp); + const MultiLevelPartitionImpl &mlp); private: auto MakeLevelData(const std::vector &lidx_to_num_cells) diff --git a/include/storage/shared_memory.hpp b/include/storage/shared_memory.hpp index 112767d09..54bf79bbf 100644 --- a/include/storage/shared_memory.hpp +++ b/include/storage/shared_memory.hpp @@ -32,8 +32,8 @@ namespace storage enum class MemorySetting { - SharedMemory, - InternalMemory + SharedMemory, + InternalMemory }; struct OSRMLockFile diff --git a/include/util/packed_vector.hpp b/include/util/packed_vector.hpp index f1ef97779..28822003f 100644 --- a/include/util/packed_vector.hpp +++ b/include/util/packed_vector.hpp @@ -22,7 +22,9 @@ namespace util * NOTE: this type is templated for future use, but will require a slight refactor to * configure BITSIZE and ELEMSIZE */ -template class PackedVector +template +class PackedVector { static const constexpr std::size_t BITSIZE = 33; static const constexpr std::size_t ELEMSIZE = 64; diff --git a/include/util/range_table.hpp b/include/util/range_table.hpp index ab88909ec..2073a453c 100644 --- a/include/util/range_table.hpp +++ b/include/util/range_table.hpp @@ -2,8 +2,8 @@ #define RANGE_TABLE_HPP #include "storage/io.hpp" -#include "util/integer_range.hpp" #include "storage/shared_memory.hpp" +#include "util/integer_range.hpp" #include "util/shared_memory_vector_wrapper.hpp" #include @@ -19,7 +19,9 @@ namespace util * and otherwise the compiler gets confused. */ -template class RangeTable; +template +class RangeTable; template std::ostream &operator<<(std::ostream &out, const RangeTable &table); @@ -215,7 +217,7 @@ template class template unsigned RangeTable::PrefixSumAtIndex(int index, - const BlockT &block) const + const BlockT &block) const { // this loop looks inefficent, but a modern compiler // will emit nice SIMD here, at least for sensible block sizes. (I checked.) diff --git a/include/util/shared_memory_vector_wrapper.hpp b/include/util/shared_memory_vector_wrapper.hpp index 642e907db..46d5128e2 100644 --- a/include/util/shared_memory_vector_wrapper.hpp +++ b/include/util/shared_memory_vector_wrapper.hpp @@ -177,9 +177,10 @@ void swap(SharedMemoryWrapper &lhs, SharedMemoryWrapper &rhs) noex template struct ShM { - using vector = typename std::conditional, - std::vector>::type; + using vector = + typename std::conditional, + std::vector>::type; }; } } diff --git a/include/util/static_graph.hpp b/include/util/static_graph.hpp index 1af6afb4a..bff17eeb7 100644 --- a/include/util/static_graph.hpp +++ b/include/util/static_graph.hpp @@ -99,7 +99,9 @@ EntryT edgeToEntry(const OtherEdge &from, std::false_type) } // namespace static_graph_details -template class StaticGraph +template +class StaticGraph { public: using InputEdge = static_graph_details::SortableEdgeWithData; diff --git a/src/benchmarks/static_rtree.cpp b/src/benchmarks/static_rtree.cpp index 2da043d61..0ef7d9ab7 100644 --- a/src/benchmarks/static_rtree.cpp +++ b/src/benchmarks/static_rtree.cpp @@ -27,8 +27,10 @@ constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION; constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION; using RTreeLeaf = extractor::EdgeBasedNode; -using BenchStaticRTree = - util::StaticRTree::vector, osrm::storage::MemorySetting::InternalMemory>; +using BenchStaticRTree = util::StaticRTree< + RTreeLeaf, + util::ShM::vector, + osrm::storage::MemorySetting::InternalMemory>; std::vector loadCoordinates(const boost::filesystem::path &nodes_file) { diff --git a/src/customize/customizer.cpp b/src/customize/customizer.cpp index 3415beccc..7333e650a 100644 --- a/src/customize/customizer.cpp +++ b/src/customize/customizer.cpp @@ -85,7 +85,8 @@ auto LoadAndUpdateEdgeExpandedGraph(const CustomizationConfig &config, auto tidied = partition::prepareEdgesForUsageInGraph(std::move(directed)); auto edge_based_graph = - std::make_unique>( + std::make_unique>( mlp, num_nodes, std::move(tidied)); util::Log() << "Loaded edge based graph for mapping partition ids: " diff --git a/src/storage/storage.cpp b/src/storage/storage.cpp index b0971bd0c..04f970c4d 100644 --- a/src/storage/storage.cpp +++ b/src/storage/storage.cpp @@ -55,8 +55,10 @@ namespace storage { using RTreeLeaf = engine::datafacade::BaseDataFacade::RTreeLeaf; -using RTreeNode = - util::StaticRTree::vector, osrm::storage::MemorySetting::SharedMemory>::TreeNode; +using RTreeNode = util::StaticRTree< + RTreeLeaf, + util::ShM::vector, + osrm::storage::MemorySetting::SharedMemory>::TreeNode; using QueryGraph = util::StaticGraph; using EdgeBasedGraph = util::StaticGraph; @@ -364,12 +366,15 @@ void Storage::PopulateLayout(DataLayout &layout) intersection_file.Skip(1); // sum_lengths layout.SetBlockSize(DataLayout::BEARING_OFFSETS, bearing_blocks); - layout.SetBlockSize::BlockT>(DataLayout::BEARING_BLOCKS, - bearing_blocks); + layout.SetBlockSize< + typename util::RangeTable<16, osrm::storage::MemorySetting::SharedMemory>::BlockT>( + DataLayout::BEARING_BLOCKS, bearing_blocks); // No need to read the data intersection_file.Skip(bearing_blocks); - intersection_file.Skip::BlockT>(bearing_blocks); + intersection_file.Skip< + typename util::RangeTable<16, osrm::storage::MemorySetting::SharedMemory>::BlockT>( + bearing_blocks); const auto num_bearings = intersection_file.ReadElementCount64(); @@ -803,8 +808,9 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr) intersection_file.Skip(1); // sum_lengths std::vector bearing_offsets_data(bearing_blocks); - std::vector::BlockT> bearing_blocks_data( - bearing_blocks); + std::vector< + typename util::RangeTable<16, osrm::storage::MemorySetting::SharedMemory>::BlockT> + bearing_blocks_data(bearing_blocks); intersection_file.ReadInto(bearing_offsets_data.data(), bearing_blocks); intersection_file.ReadInto(bearing_blocks_data.data(), bearing_blocks); @@ -843,9 +849,9 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr) if (layout.GetBlockSize(DataLayout::BEARING_BLOCKS) > 0) { - const auto bearing_blocks_ptr = - layout.GetBlockPtr::BlockT, true>( - memory_ptr, DataLayout::BEARING_BLOCKS); + const auto bearing_blocks_ptr = layout.GetBlockPtr< + typename util::RangeTable<16, osrm::storage::MemorySetting::SharedMemory>::BlockT, + true>(memory_ptr, DataLayout::BEARING_BLOCKS); BOOST_ASSERT( static_cast(layout.GetBlockSize(DataLayout::BEARING_BLOCKS)) >= std::distance(bearing_blocks_data.begin(), bearing_blocks_data.end()) * diff --git a/unit_tests/customizer/cell_customization.cpp b/unit_tests/customizer/cell_customization.cpp index 52ac3ec8c..b2cea2b9e 100644 --- a/unit_tests/customizer/cell_customization.cpp +++ b/unit_tests/customizer/cell_customization.cpp @@ -38,7 +38,8 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector &mock edges.push_back(Edge{m.target, m.start, m.weight, false, true}); } std::sort(edges.begin(), edges.end()); - return partition::MultiLevelGraph(mlp, max_id + 1, edges); + return partition::MultiLevelGraph( + mlp, max_id + 1, edges); } } diff --git a/unit_tests/partition/multi_level_graph.cpp b/unit_tests/partition/multi_level_graph.cpp index 2841887e7..eea019837 100644 --- a/unit_tests/partition/multi_level_graph.cpp +++ b/unit_tests/partition/multi_level_graph.cpp @@ -38,7 +38,8 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector &mock edges.push_back(Edge{m.target, m.source, false, true}); } std::sort(edges.begin(), edges.end()); - return MultiLevelGraph(mlp, max_id + 1, edges); + return MultiLevelGraph( + mlp, max_id + 1, edges); } } diff --git a/unit_tests/util/static_rtree.cpp b/unit_tests/util/static_rtree.cpp index 199697440..b82c01447 100644 --- a/unit_tests/util/static_rtree.cpp +++ b/unit_tests/util/static_rtree.cpp @@ -45,7 +45,11 @@ using TestStaticRTree = StaticRTree; -using MiniStaticRTree = StaticRTree, osrm::storage::MemorySetting::InternalMemory, 2, 128>; +using MiniStaticRTree = StaticRTree, + osrm::storage::MemorySetting::InternalMemory, + 2, + 128>; // Choosen by a fair W20 dice roll (this value is completely arbitrary) constexpr unsigned RANDOM_SEED = 42; @@ -273,7 +277,11 @@ void construction_test(const std::string &prefix, FixtureT *fixture) BOOST_FIXTURE_TEST_CASE(construct_tiny, TestRandomGraphFixture_10_30) { - using TinyTestTree = StaticRTree, osrm::storage::MemorySetting::InternalMemory, 2, 64>; + using TinyTestTree = StaticRTree, + osrm::storage::MemorySetting::InternalMemory, + 2, + 64>; construction_test("test_tiny", this); } diff --git a/unit_tests/util/static_rtree.cpp~RF1bf682.TMP b/unit_tests/util/static_rtree.cpp~RF1bf682.TMP new file mode 100644 index 000000000..199697440 --- /dev/null +++ b/unit_tests/util/static_rtree.cpp~RF1bf682.TMP @@ -0,0 +1,481 @@ +#include "util/static_rtree.hpp" +#include "extractor/edge_based_node.hpp" +#include "engine/geospatial_query.hpp" +#include "util/coordinate.hpp" +#include "util/coordinate_calculation.hpp" +#include "util/exception.hpp" +#include "util/rectangle.hpp" +#include "util/typedefs.hpp" + +#include "mocks/mock_datafacade.hpp" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +// explicit TBB scheduler init to register resources cleanup at exit +tbb::task_scheduler_init init(2); + +BOOST_AUTO_TEST_SUITE(static_rtree) + +using namespace osrm; +using namespace osrm::util; +using namespace osrm::test; + +constexpr uint32_t TEST_BRANCHING_FACTOR = 8; +constexpr uint32_t TEST_LEAF_NODE_SIZE = 64; + +using TestData = extractor::EdgeBasedNode; +using TestStaticRTree = StaticRTree, + osrm::storage::MemorySetting::InternalMemory, + TEST_BRANCHING_FACTOR, + TEST_LEAF_NODE_SIZE>; +using MiniStaticRTree = StaticRTree, osrm::storage::MemorySetting::InternalMemory, 2, 128>; + +// Choosen by a fair W20 dice roll (this value is completely arbitrary) +constexpr unsigned RANDOM_SEED = 42; +static const int32_t WORLD_MIN_LAT = -85 * COORDINATE_PRECISION; +static const int32_t WORLD_MAX_LAT = 85 * COORDINATE_PRECISION; +static const int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION; +static const int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION; + +template class LinearSearchNN +{ + public: + LinearSearchNN(const std::vector &coords, const std::vector &edges) + : coords(coords), edges(edges) + { + } + + std::vector Nearest(const Coordinate &input_coordinate, const unsigned num_results) + { + std::vector local_edges(edges); + + auto projected_input = web_mercator::fromWGS84(input_coordinate); + const auto segment_comparator = [this, &projected_input](const DataT &lhs, + const DataT &rhs) { + using web_mercator::fromWGS84; + const auto lhs_result = coordinate_calculation::projectPointOnSegment( + fromWGS84(coords[lhs.u]), fromWGS84(coords[lhs.v]), projected_input); + const auto rhs_result = coordinate_calculation::projectPointOnSegment( + fromWGS84(coords[rhs.u]), fromWGS84(coords[rhs.v]), projected_input); + const auto lhs_squared_dist = coordinate_calculation::squaredEuclideanDistance( + lhs_result.second, projected_input); + const auto rhs_squared_dist = coordinate_calculation::squaredEuclideanDistance( + rhs_result.second, projected_input); + return lhs_squared_dist < rhs_squared_dist; + }; + + std::nth_element(local_edges.begin(), + local_edges.begin() + num_results, + local_edges.end(), + segment_comparator); + local_edges.resize(num_results); + + return local_edges; + } + + private: + const std::vector &coords; + const std::vector &edges; +}; + +template struct RandomGraphFixture +{ + struct TupleHash + { + typedef std::pair argument_type; + typedef std::size_t result_type; + + result_type operator()(const argument_type &t) const + { + std::size_t val{0}; + boost::hash_combine(val, t.first); + boost::hash_combine(val, t.second); + return val; + } + }; + + RandomGraphFixture() + { + std::mt19937 g(RANDOM_SEED); + + std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT); + std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON); + + for (unsigned i = 0; i < NUM_NODES; i++) + { + int lon = lon_udist(g); + int lat = lat_udist(g); + coords.emplace_back(Coordinate(FixedLongitude{lon}, FixedLatitude{lat})); + } + + std::uniform_int_distribution<> edge_udist(0, coords.size() - 1); + + std::unordered_set, TupleHash> used_edges; + + while (edges.size() < NUM_EDGES) + { + TestData data; + data.u = edge_udist(g); + data.v = edge_udist(g); + if (used_edges.find(std::pair( + std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end()) + { + data.component.id = 0; + edges.emplace_back(data); + used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v)); + } + } + } + + std::vector coords; + std::vector edges; +}; + +struct GraphFixture +{ + GraphFixture(const std::vector> &input_coords, + const std::vector> &input_edges) + { + + for (unsigned i = 0; i < input_coords.size(); i++) + { + coords.emplace_back(input_coords[i].first, input_coords[i].second); + } + + for (const auto &pair : input_edges) + { + TestData d; + d.u = pair.first; + d.v = pair.second; + // We set the forward nodes to the target node-based-node IDs, just + // so we have something to test against. Because this isn't a real + // graph, the actual values aren't important, we just need something + // to examine during tests. + d.forward_segment_id = {pair.second, true}; + d.reverse_segment_id = {pair.first, true}; + d.fwd_segment_position = 0; + d.packed_geometry_id = 0; + edges.emplace_back(d); + } + } + + std::vector coords; + std::vector edges; +}; + +typedef RandomGraphFixture + TestRandomGraphFixture_LeafHalfFull; +typedef RandomGraphFixture + TestRandomGraphFixture_LeafFull; +typedef RandomGraphFixture + TestRandomGraphFixture_TwoLeaves; +typedef RandomGraphFixture + TestRandomGraphFixture_Branch; +typedef RandomGraphFixture + TestRandomGraphFixture_MultipleLevels; +typedef RandomGraphFixture<10, 30> TestRandomGraphFixture_10_30; + +template +void simple_verify_rtree(RTreeT &rtree, + const std::vector &coords, + const std::vector &edges) +{ + for (const auto &e : edges) + { + const Coordinate &pu = coords[e.u]; + const Coordinate &pv = coords[e.v]; + auto result_u = rtree.Nearest(pu, 1); + auto result_v = rtree.Nearest(pv, 1); + BOOST_CHECK(result_u.size() == 1 && result_v.size() == 1); + BOOST_CHECK(result_u.front().u == e.u || result_u.front().v == e.u); + BOOST_CHECK(result_v.front().u == e.v || result_v.front().v == e.v); + } +} + +template +void sampling_verify_rtree(RTreeT &rtree, + LinearSearchNN &lsnn, + const std::vector &coords, + unsigned num_samples) +{ + std::mt19937 g(RANDOM_SEED); + std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT); + std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON); + std::vector queries; + for (unsigned i = 0; i < num_samples; i++) + { + queries.emplace_back(FixedLongitude{lon_udist(g)}, FixedLatitude{lat_udist(g)}); + } + + for (const auto &q : queries) + { + auto result_rtree = rtree.Nearest(q, 1); + auto result_lsnn = lsnn.Nearest(q, 1); + BOOST_CHECK(result_rtree.size() == 1); + BOOST_CHECK(result_lsnn.size() == 1); + auto rtree_u = result_rtree.back().u; + auto rtree_v = result_rtree.back().v; + auto lsnn_u = result_lsnn.back().u; + auto lsnn_v = result_lsnn.back().v; + + const double rtree_dist = + coordinate_calculation::perpendicularDistance(coords[rtree_u], coords[rtree_v], q); + const double lsnn_dist = + coordinate_calculation::perpendicularDistance(coords[lsnn_u], coords[lsnn_v], q); + + BOOST_CHECK_CLOSE(rtree_dist, lsnn_dist, 0.0001); + } +} + +template +void build_rtree(const std::string &prefix, + FixtureT *fixture, + std::string &leaves_path, + std::string &nodes_path) +{ + nodes_path = prefix + ".ramIndex"; + leaves_path = prefix + ".fileIndex"; + + RTreeT r(fixture->edges, nodes_path, leaves_path, fixture->coords); +} + +template +void construction_test(const std::string &prefix, FixtureT *fixture) +{ + std::string leaves_path; + std::string nodes_path; + build_rtree(prefix, fixture, leaves_path, nodes_path); + RTreeT rtree(nodes_path, leaves_path, fixture->coords); + LinearSearchNN lsnn(fixture->coords, fixture->edges); + + simple_verify_rtree(rtree, fixture->coords, fixture->edges); + sampling_verify_rtree(rtree, lsnn, fixture->coords, 100); +} + +BOOST_FIXTURE_TEST_CASE(construct_tiny, TestRandomGraphFixture_10_30) +{ + using TinyTestTree = StaticRTree, osrm::storage::MemorySetting::InternalMemory, 2, 64>; + construction_test("test_tiny", this); +} + +BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull) +{ + construction_test("test_1", this); +} + +BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull) +{ + construction_test("test_2", this); +} + +BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves) +{ + construction_test("test_3", this); +} + +BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch) +{ + construction_test("test_4", this); +} + +BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels) +{ + construction_test("test_5", this); +} + +// Bug: If you querry a point that lies between two BBs that have a gap, +// one BB will be pruned, even if it could contain a nearer match. +BOOST_AUTO_TEST_CASE(regression_test) +{ + using Coord = std::pair; + using Edge = std::pair; + GraphFixture fixture( + { + Coord{FloatLongitude{0.0}, FloatLatitude{40.0}}, // + Coord{FloatLongitude{5.0}, FloatLatitude{35.0}}, // + Coord{FloatLongitude{5.0}, FloatLatitude{5.0}}, // + Coord{FloatLongitude{10.0}, FloatLatitude{0.0}}, // + Coord{FloatLongitude{10.0}, FloatLatitude{20.0}}, // + Coord{FloatLongitude{5.0}, FloatLatitude{20.0}}, // + Coord{FloatLongitude{100.0}, FloatLatitude{40.0}}, // + Coord{FloatLongitude{105.0}, FloatLatitude{35.0}}, // + Coord{FloatLongitude{105.0}, FloatLatitude{5.0}}, // + Coord{FloatLongitude{110.0}, FloatLatitude{0.0}}, // + }, + {Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)}); + + std::string leaves_path; + std::string nodes_path; + build_rtree( + "test_regression", &fixture, leaves_path, nodes_path); + MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords); + LinearSearchNN lsnn(fixture.coords, fixture.edges); + + // query a node just right of the center of the gap + Coordinate input(FloatLongitude{55.1}, FloatLatitude{20.0}); + auto result_rtree = rtree.Nearest(input, 1); + auto result_ls = lsnn.Nearest(input, 1); + + BOOST_CHECK(result_rtree.size() == 1); + BOOST_CHECK(result_ls.size() == 1); + + BOOST_CHECK_EQUAL(result_ls.front().u, result_rtree.front().u); + BOOST_CHECK_EQUAL(result_ls.front().v, result_rtree.front().v); +} + +// Bug: If you querry a point with a narrow radius, no result should be returned +BOOST_AUTO_TEST_CASE(radius_regression_test) +{ + using Coord = std::pair; + using Edge = std::pair; + GraphFixture fixture( + { + Coord(FloatLongitude{0.0}, FloatLatitude{0.0}), + Coord(FloatLongitude{10.0}, FloatLatitude{10.0}), + }, + {Edge(0, 1), Edge(1, 0)}); + + std::string leaves_path; + std::string nodes_path; + build_rtree("test_angle", &fixture, leaves_path, nodes_path); + MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords); + MockDataFacade mockfacade; + engine::GeospatialQuery> query( + rtree, fixture.coords, mockfacade); + + Coordinate input(FloatLongitude{5.2}, FloatLatitude{5.0}); + + { + auto results = query.NearestPhantomNodesInRange(input, 0.01); + BOOST_CHECK_EQUAL(results.size(), 0); + } +} + +BOOST_AUTO_TEST_CASE(bearing_tests) +{ + using Coord = std::pair; + using Edge = std::pair; + GraphFixture fixture( + { + Coord(FloatLongitude{0.0}, FloatLatitude{0.0}), + Coord(FloatLongitude{10.0}, FloatLatitude{10.0}), + }, + {Edge(0, 1), Edge(1, 0)}); + + std::string leaves_path; + std::string nodes_path; + build_rtree("test_bearing", &fixture, leaves_path, nodes_path); + MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords); + MockDataFacade mockfacade; + engine::GeospatialQuery> query( + rtree, fixture.coords, mockfacade); + + Coordinate input(FloatLongitude{5.1}, FloatLatitude{5.0}); + + { + auto results = query.NearestPhantomNodes(input, 5); + BOOST_CHECK_EQUAL(results.size(), 2); + BOOST_CHECK_EQUAL(results.back().phantom_node.forward_segment_id.id, 0); + BOOST_CHECK_EQUAL(results.back().phantom_node.reverse_segment_id.id, 1); + } + + { + auto results = query.NearestPhantomNodes(input, 5, 270, 10); + BOOST_CHECK_EQUAL(results.size(), 0); + } + + { + auto results = query.NearestPhantomNodes(input, 5, 45, 10); + BOOST_CHECK_EQUAL(results.size(), 2); + + BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled); + BOOST_CHECK(!results[0].phantom_node.reverse_segment_id.enabled); + BOOST_CHECK_EQUAL(results[0].phantom_node.forward_segment_id.id, 1); + + BOOST_CHECK(!results[1].phantom_node.forward_segment_id.enabled); + BOOST_CHECK(results[1].phantom_node.reverse_segment_id.enabled); + BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_segment_id.id, 1); + } + + { + auto results = query.NearestPhantomNodesInRange(input, 11000); + BOOST_CHECK_EQUAL(results.size(), 2); + } + + { + auto results = query.NearestPhantomNodesInRange(input, 11000, 270, 10); + BOOST_CHECK_EQUAL(results.size(), 0); + } + + { + auto results = query.NearestPhantomNodesInRange(input, 11000, 45, 10); + BOOST_CHECK_EQUAL(results.size(), 2); + + BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled); + BOOST_CHECK(!results[0].phantom_node.reverse_segment_id.enabled); + BOOST_CHECK_EQUAL(results[0].phantom_node.forward_segment_id.id, 1); + + BOOST_CHECK(!results[1].phantom_node.forward_segment_id.enabled); + BOOST_CHECK(results[1].phantom_node.reverse_segment_id.enabled); + BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_segment_id.id, 1); + } +} + +BOOST_AUTO_TEST_CASE(bbox_search_tests) +{ + using Coord = std::pair; + using Edge = std::pair; + + GraphFixture fixture( + { + Coord(FloatLongitude{0.0}, FloatLatitude{0.0}), + Coord(FloatLongitude{1.0}, FloatLatitude{1.0}), + Coord(FloatLongitude{2.0}, FloatLatitude{2.0}), + Coord(FloatLongitude{3.0}, FloatLatitude{3.0}), + Coord(FloatLongitude{4.0}, FloatLatitude{4.0}), + }, + {Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(3, 4)}); + + std::string leaves_path; + std::string nodes_path; + build_rtree("test_bbox", &fixture, leaves_path, nodes_path); + MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords); + MockDataFacade mockfacade; + engine::GeospatialQuery> query( + rtree, fixture.coords, mockfacade); + + { + RectangleInt2D bbox = { + FloatLongitude{0.5}, FloatLongitude{1.5}, FloatLatitude{0.5}, FloatLatitude{1.5}}; + auto results = query.Search(bbox); + BOOST_CHECK_EQUAL(results.size(), 2); + } + + { + RectangleInt2D bbox = { + FloatLongitude{1.5}, FloatLongitude{3.5}, FloatLatitude{1.5}, FloatLatitude{3.5}}; + auto results = query.Search(bbox); + BOOST_CHECK_EQUAL(results.size(), 3); + } +} + +BOOST_AUTO_TEST_SUITE_END()