#include "storage/storage.hpp" #include "storage/io.hpp" #include "storage/shared_datatype.hpp" #include "storage/shared_memory.hpp" #include "storage/shared_memory_ownership.hpp" #include "storage/shared_monitor.hpp" #include "contractor/files.hpp" #include "contractor/query_graph.hpp" #include "customizer/edge_based_graph.hpp" #include "customizer/files.hpp" #include "extractor/class_data.hpp" #include "extractor/compressed_edge_container.hpp" #include "extractor/edge_based_edge.hpp" #include "extractor/edge_based_node.hpp" #include "extractor/files.hpp" #include "extractor/maneuver_override.hpp" #include "extractor/name_table.hpp" #include "extractor/packed_osm_ids.hpp" #include "extractor/profile_properties.hpp" #include "extractor/query_node.hpp" #include "extractor/travel_mode.hpp" #include "guidance/files.hpp" #include "guidance/turn_instruction.hpp" #include "partitioner/cell_storage.hpp" #include "partitioner/edge_based_graph_reader.hpp" #include "partitioner/files.hpp" #include "partitioner/multi_level_partition.hpp" #include "engine/datafacade/datafacade_base.hpp" #include "util/coordinate.hpp" #include "util/exception.hpp" #include "util/exception_utils.hpp" #include "util/fingerprint.hpp" #include "util/log.hpp" #include "util/packed_vector.hpp" #include "util/range_table.hpp" #include "util/static_graph.hpp" #include "util/static_rtree.hpp" #include "util/typedefs.hpp" #include "util/vector_view.hpp" #ifdef __linux__ #include #endif #include #include #include #include #include #include #include #include #include #include #include namespace osrm { namespace storage { namespace { inline void readBlocks(const boost::filesystem::path &path, DataLayout &layout) { tar::FileReader reader(path, tar::FileReader::VerifyFingerprint); std::vector entries; reader.List(std::back_inserter(entries)); for (const auto &entry : entries) { const auto name_end = entry.name.rfind(".meta"); if (name_end == std::string::npos) { auto number_of_elements = reader.ReadElementCount64(entry.name); layout.SetBlock(entry.name, Block{number_of_elements, entry.size}); } } } } using RTreeLeaf = engine::datafacade::BaseDataFacade::RTreeLeaf; using RTreeNode = util::StaticRTree::TreeNode; using QueryGraph = util::StaticGraph; using EdgeBasedGraph = util::StaticGraph; using Monitor = SharedMonitor; Storage::Storage(StorageConfig config_) : config(std::move(config_)) {} int Storage::Run(int max_wait) { BOOST_ASSERT_MSG(config.IsValid(), "Invalid storage config"); util::LogPolicy::GetInstance().Unmute(); boost::filesystem::path lock_path = boost::filesystem::temp_directory_path() / "osrm-datastore.lock"; if (!boost::filesystem::exists(lock_path)) { boost::filesystem::ofstream ofs(lock_path); } boost::interprocess::file_lock file_lock(lock_path.string().c_str()); boost::interprocess::scoped_lock datastore_lock( file_lock, boost::interprocess::defer_lock); if (!datastore_lock.try_lock()) { util::UnbufferedLog(logWARNING) << "Data update in progress, waiting until it finishes... "; datastore_lock.lock(); util::UnbufferedLog(logWARNING) << "ok."; } #ifdef __linux__ // try to disable swapping on Linux const bool lock_flags = MCL_CURRENT | MCL_FUTURE; if (-1 == mlockall(lock_flags)) { util::Log(logWARNING) << "Could not request RAM lock"; } #endif // Get the next region ID and time stamp without locking shared barriers. // Because of datastore_lock the only write operation can occur sequentially later. Monitor monitor(SharedDataTimestamp{REGION_NONE, 0}); auto in_use_region = monitor.data().region; auto next_timestamp = monitor.data().timestamp + 1; auto next_region = in_use_region == REGION_2 || in_use_region == REGION_NONE ? REGION_1 : REGION_2; // ensure that the shared memory region we want to write to is really removed // this is only needef for failure recovery because we actually wait for all clients // to detach at the end of the function if (storage::SharedMemory::RegionExists(next_region)) { util::Log(logWARNING) << "Old shared memory region " << regionToString(next_region) << " still exists."; util::UnbufferedLog() << "Retrying removal... "; storage::SharedMemory::Remove(next_region); util::UnbufferedLog() << "ok."; } util::Log() << "Loading data into " << regionToString(next_region); // Populate a memory layout into stack memory DataLayout layout; PopulateLayout(layout); io::BufferWriter writer; serialization::write(writer, layout); auto encoded_layout = writer.GetBuffer(); // Allocate shared memory block auto regions_size = encoded_layout.size() + layout.GetSizeOfLayout(); util::Log() << "Data layout has a size of " << encoded_layout.size() << " bytes"; util::Log() << "Allocating shared memory of " << regions_size << " bytes"; auto data_memory = makeSharedMemory(next_region, regions_size); // Copy memory layout to shared memory and populate data char *shared_memory_ptr = static_cast(data_memory->Ptr()); std::copy_n(encoded_layout.data(), encoded_layout.size(), shared_memory_ptr); PopulateData(layout, shared_memory_ptr + encoded_layout.size()); { // Lock for write access shared region mutex boost::interprocess::scoped_lock lock(monitor.get_mutex(), boost::interprocess::defer_lock); if (max_wait >= 0) { if (!lock.timed_lock(boost::posix_time::microsec_clock::universal_time() + boost::posix_time::seconds(max_wait))) { util::Log(logWARNING) << "Could not aquire current region lock after " << max_wait << " seconds. Removing locked block and creating a new one. All currently " "attached processes will not receive notifications and must be restarted"; Monitor::remove(); in_use_region = REGION_NONE; monitor = Monitor(SharedDataTimestamp{REGION_NONE, 0}); } } else { lock.lock(); } // Update the current region ID and timestamp monitor.data().region = next_region; monitor.data().timestamp = next_timestamp; } util::Log() << "All data loaded. Notify all client about new data in " << regionToString(next_region) << " with timestamp " << next_timestamp; monitor.notify_all(); // SHMCTL(2): Mark the segment to be destroyed. The segment will actually be destroyed // only after the last process detaches it. if (in_use_region != REGION_NONE && storage::SharedMemory::RegionExists(in_use_region)) { util::UnbufferedLog() << "Marking old shared memory region " << regionToString(in_use_region) << " for removal... "; // aquire a handle for the old shared memory region before we mark it for deletion // we will need this to wait for all users to detach auto in_use_shared_memory = makeSharedMemory(in_use_region); storage::SharedMemory::Remove(in_use_region); util::UnbufferedLog() << "ok."; util::UnbufferedLog() << "Waiting for clients to detach... "; in_use_shared_memory->WaitForDetach(); util::UnbufferedLog() << " ok."; } util::Log() << "All clients switched."; return EXIT_SUCCESS; } /** * This function examines all our data files and figures out how much * memory needs to be allocated, and the position of each data structure * in that big block. It updates the fields in the DataLayout parameter. */ void Storage::PopulateLayout(DataLayout &layout) { { auto absolute_file_index_path = boost::filesystem::absolute(config.GetPath(".osrm.fileIndex")); layout.SetBlock("/common/rtree/file_index_path", make_block(absolute_file_index_path.string().length() + 1)); } constexpr bool REQUIRED = true; constexpr bool OPTIONAL = false; std::vector> tar_files = { {OPTIONAL, config.GetPath(".osrm.mldgr")}, {OPTIONAL, config.GetPath(".osrm.cells")}, {OPTIONAL, config.GetPath(".osrm.partition")}, {OPTIONAL, config.GetPath(".osrm.cell_metrics")}, {OPTIONAL, config.GetPath(".osrm.hsgr")}, {REQUIRED, config.GetPath(".osrm.icd")}, {REQUIRED, config.GetPath(".osrm.properties")}, {REQUIRED, config.GetPath(".osrm.nbg_nodes")}, {REQUIRED, config.GetPath(".osrm.datasource_names")}, {REQUIRED, config.GetPath(".osrm.geometry")}, {REQUIRED, config.GetPath(".osrm.ebg_nodes")}, {REQUIRED, config.GetPath(".osrm.tls")}, {REQUIRED, config.GetPath(".osrm.tld")}, {REQUIRED, config.GetPath(".osrm.maneuver_overrides")}, {REQUIRED, config.GetPath(".osrm.turn_weight_penalties")}, {REQUIRED, config.GetPath(".osrm.turn_duration_penalties")}, {REQUIRED, config.GetPath(".osrm.edges")}, {REQUIRED, config.GetPath(".osrm.names")}, {REQUIRED, config.GetPath(".osrm.ramIndex")}, }; for (const auto &file : tar_files) { if (boost::filesystem::exists(file.second)) { readBlocks(file.second, layout); } else { if (file.first == REQUIRED) { throw util::exception("Could not find required filed: " + std::get<1>(file).string()); } } } } void Storage::PopulateData(const DataLayout &layout, char *memory_ptr) { BOOST_ASSERT(memory_ptr != nullptr); // Connectivity matrix checksum std::uint32_t turns_connectivity_checksum = 0; // read actual data into shared memory object // // store the filename of the on-disk portion of the RTree { const auto file_index_path_ptr = layout.GetBlockPtr(memory_ptr, "/common/rtree/file_index_path"); // make sure we have 0 ending std::fill(file_index_path_ptr, file_index_path_ptr + layout.GetBlockSize("/common/rtree/file_index_path"), 0); const auto absolute_file_index_path = boost::filesystem::absolute(config.GetPath(".osrm.fileIndex")).string(); BOOST_ASSERT(static_cast(layout.GetBlockSize( "/common/rtree/file_index_path")) >= absolute_file_index_path.size()); std::copy( absolute_file_index_path.begin(), absolute_file_index_path.end(), file_index_path_ptr); } // Name data { const auto name_blocks_ptr = layout.GetBlockPtr( memory_ptr, "/common/names/blocks"); const auto name_values_ptr = layout.GetBlockPtr( memory_ptr, "/common/names/values"); util::vector_view blocks( name_blocks_ptr, layout.GetBlockEntries("/common/names/blocks")); util::vector_view values( name_values_ptr, layout.GetBlockEntries("/common/names/values")); extractor::NameTableView::IndexedData index_data_view{std::move(blocks), std::move(values)}; extractor::NameTableView name_table{index_data_view}; extractor::files::readNames(config.GetPath(".osrm.names"), name_table); } // Turn lane data { const auto turn_lane_data_ptr = layout.GetBlockPtr( memory_ptr, "/common/turn_lanes/data"); util::vector_view turn_lane_data( turn_lane_data_ptr, layout.GetBlockEntries("/common/turn_lanes/data")); extractor::files::readTurnLaneData(config.GetPath(".osrm.tld"), turn_lane_data); } // Turn lane descriptions { auto offsets_ptr = layout.GetBlockPtr(memory_ptr, "/common/turn_lanes/offsets"); util::vector_view offsets( offsets_ptr, layout.GetBlockEntries("/common/turn_lanes/offsets")); auto masks_ptr = layout.GetBlockPtr( memory_ptr, "/common/turn_lanes/masks"); util::vector_view masks( masks_ptr, layout.GetBlockEntries("/common/turn_lanes/masks")); extractor::files::readTurnLaneDescriptions(config.GetPath(".osrm.tls"), offsets, masks); } // Load edge-based nodes data { auto edge_based_node_data_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/ebg_node_data/nodes"); util::vector_view edge_based_node_data( edge_based_node_data_list_ptr, layout.GetBlockEntries("/common/ebg_node_data/nodes")); 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")); extractor::EdgeBasedNodeDataView node_data(std::move(edge_based_node_data), std::move(annotation_data)); extractor::files::readNodeData(config.GetPath(".osrm.ebg_nodes"), node_data); } // Load original edge data { 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")); guidance::TurnDataView turn_data(std::move(turn_instructions), std::move(lane_data_ids), std::move(entry_class_ids), std::move(pre_turn_bearings), std::move(post_turn_bearings)); auto connectivity_checksum_ptr = layout.GetBlockPtr(memory_ptr, "/common/connectivity_checksum"); guidance::files::readTurnData( config.GetPath(".osrm.edges"), turn_data, *connectivity_checksum_ptr); turns_connectivity_checksum = *connectivity_checksum_ptr; } // load compressed geometry { auto geometries_index_ptr = layout.GetBlockPtr(memory_ptr, "/common/segment_data/index"); util::vector_view geometry_begin_indices( geometries_index_ptr, layout.GetBlockEntries("/common/segment_data/index")); auto num_entries = layout.GetBlockEntries("/common/segment_data/nodes"); auto geometries_node_list_ptr = layout.GetBlockPtr(memory_ptr, "/common/segment_data/nodes"); util::vector_view geometry_node_list(geometries_node_list_ptr, num_entries); auto geometries_fwd_weight_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/segment_data/forward_weights/packed"); extractor::SegmentDataView::SegmentWeightVector geometry_fwd_weight_list( util::vector_view( geometries_fwd_weight_list_ptr, layout.GetBlockEntries("/common/segment_data/forward_weights/packed")), num_entries); auto geometries_rev_weight_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/segment_data/reverse_weights/packed"); extractor::SegmentDataView::SegmentWeightVector geometry_rev_weight_list( util::vector_view( geometries_rev_weight_list_ptr, layout.GetBlockEntries("/common/segment_data/reverse_weights/packed")), num_entries); auto geometries_fwd_duration_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/segment_data/forward_durations/packed"); extractor::SegmentDataView::SegmentDurationVector geometry_fwd_duration_list( util::vector_view( geometries_fwd_duration_list_ptr, layout.GetBlockEntries("/common/segment_data/forward_durations/packed")), num_entries); auto geometries_rev_duration_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/segment_data/reverse_durations/packed"); extractor::SegmentDataView::SegmentDurationVector geometry_rev_duration_list( util::vector_view( geometries_rev_duration_list_ptr, layout.GetBlockEntries("/common/segment_data/reverse_durations/packed")), num_entries); auto geometries_fwd_datasources_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/segment_data/forward_data_sources"); util::vector_view geometry_fwd_datasources_list( geometries_fwd_datasources_list_ptr, layout.GetBlockEntries("/common/segment_data/forward_data_sources")); auto geometries_rev_datasources_list_ptr = layout.GetBlockPtr( memory_ptr, "/common/segment_data/reverse_data_sources"); util::vector_view geometry_rev_datasources_list( geometries_rev_datasources_list_ptr, layout.GetBlockEntries("/common/segment_data/reverse_data_sources")); extractor::SegmentDataView segment_data{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)}; extractor::files::readSegmentData(config.GetPath(".osrm.geometry"), segment_data); } { const auto datasources_names_ptr = layout.GetBlockPtr( memory_ptr, "/common/data_sources_names"); extractor::files::readDatasources(config.GetPath(".osrm.datasource_names"), *datasources_names_ptr); } // Loading list of coordinates { const auto coordinates_ptr = layout.GetBlockPtr(memory_ptr, "/common/coordinates"); const auto osmnodeid_ptr = layout.GetBlockPtr( memory_ptr, "/common/osm_node_ids/packed"); util::vector_view coordinates( coordinates_ptr, layout.GetBlockEntries("/common/coordinates")); extractor::PackedOSMIDsView osm_node_ids( util::vector_view( osmnodeid_ptr, layout.GetBlockEntries("/common/osm_node_ids/packed")), layout.GetBlockEntries("/common/coordinates")); extractor::files::readNodes(config.GetPath(".osrm.nbg_nodes"), coordinates, osm_node_ids); } // load turn weight penalties { auto turn_duration_penalties_ptr = layout.GetBlockPtr(memory_ptr, "/common/turn_penalty/weight"); util::vector_view turn_duration_penalties( turn_duration_penalties_ptr, layout.GetBlockEntries("/common/turn_penalty/weight")); extractor::files::readTurnWeightPenalty(config.GetPath(".osrm.turn_weight_penalties"), turn_duration_penalties); } // load turn duration penalties { auto turn_duration_penalties_ptr = layout.GetBlockPtr(memory_ptr, "/common/turn_penalty/duration"); util::vector_view turn_duration_penalties( turn_duration_penalties_ptr, layout.GetBlockEntries("/common/turn_penalty/duration")); extractor::files::readTurnDurationPenalty(config.GetPath(".osrm.turn_duration_penalties"), turn_duration_penalties); } // store search tree portion of rtree { const auto rtree_ptr = layout.GetBlockPtr(memory_ptr, "/common/rtree/search_tree"); util::vector_view search_tree( rtree_ptr, layout.GetBlockEntries("/common/rtree/search_tree")); const auto rtree_levelstarts_ptr = layout.GetBlockPtr( memory_ptr, "/common/rtree/search_tree_level_starts"); util::vector_view rtree_level_starts( rtree_levelstarts_ptr, layout.GetBlockEntries("/common/rtree/search_tree_level_starts")); // we need this purely for the interface util::vector_view empty_coords; util::StaticRTree rtree{ std::move(search_tree), std::move(rtree_level_starts), config.GetPath(".osrm.fileIndex"), empty_coords}; extractor::files::readRamIndex(config.GetPath(".osrm.ramIndex"), rtree); } // FIXME we only need to get the weight name std::string metric_name; // load profile properties { const auto profile_properties_ptr = layout.GetBlockPtr( memory_ptr, "/common/properties"); extractor::files::readProfileProperties(config.GetPath(".osrm.properties"), *profile_properties_ptr); metric_name = profile_properties_ptr->GetWeightName(); } // Load intersection data { auto bearing_class_id_ptr = layout.GetBlockPtr( memory_ptr, "/common/intersection_bearings/node_to_class_id"); util::vector_view bearing_class_id( bearing_class_id_ptr, layout.GetBlockEntries("/common/intersection_bearings/node_to_class_id")); auto bearing_values_ptr = layout.GetBlockPtr( memory_ptr, "/common/intersection_bearings/bearing_values"); util::vector_view bearing_values( bearing_values_ptr, layout.GetBlockEntries("/common/intersection_bearings/bearing_values")); auto offsets_ptr = layout.GetBlockPtr( memory_ptr, "/common/intersection_bearings/class_id_to_ranges/block_offsets"); auto blocks_ptr = layout.GetBlockPtr::BlockT, true>( memory_ptr, "/common/intersection_bearings/class_id_to_ranges/diff_blocks"); util::vector_view bearing_offsets( offsets_ptr, layout.GetBlockEntries( "/common/intersection_bearings/class_id_to_ranges/block_offsets")); util::vector_view::BlockT> bearing_blocks( blocks_ptr, 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())); extractor::IntersectionBearingsView intersection_bearings_view{ std::move(bearing_values), std::move(bearing_class_id), std::move(bearing_range_table)}; auto entry_class_ptr = layout.GetBlockPtr( memory_ptr, "/common/entry_classes"); util::vector_view entry_classes( entry_class_ptr, layout.GetBlockEntries("/common/entry_classes")); extractor::files::readIntersections( config.GetPath(".osrm.icd"), intersection_bearings_view, entry_classes); } if (boost::filesystem::exists(config.GetPath(".osrm.hsgr"))) { const std::string metric_prefix = "/ch/metrics/" + metric_name; auto graph_nodes_ptr = layout.GetBlockPtr( memory_ptr, metric_prefix + "/contracted_graph/node_array"); auto graph_edges_ptr = layout.GetBlockPtr( memory_ptr, metric_prefix + "/contracted_graph/edge_array"); util::vector_view node_list( graph_nodes_ptr, layout.GetBlockEntries(metric_prefix + "/contracted_graph/node_array")); util::vector_view edge_list( graph_edges_ptr, layout.GetBlockEntries(metric_prefix + "/contracted_graph/edge_array")); std::vector> edge_filter; layout.List( metric_prefix + "/exclude", boost::make_function_output_iterator([&](const auto &name) { auto data_ptr = layout.GetBlockPtr::Word, true>(memory_ptr, name); auto num_entries = layout.GetBlockEntries(name); edge_filter.emplace_back(data_ptr, num_entries); })); std::uint32_t graph_connectivity_checksum = 0; std::unordered_map metrics = { {metric_name, {{std::move(node_list), std::move(edge_list)}, std::move(edge_filter)}}}; contractor::files::readGraph( config.GetPath(".osrm.hsgr"), metrics, graph_connectivity_checksum); if (turns_connectivity_checksum != graph_connectivity_checksum) { throw util::exception( "Connectivity checksum " + std::to_string(graph_connectivity_checksum) + " in " + config.GetPath(".osrm.hsgr").string() + " does not equal to checksum " + std::to_string(turns_connectivity_checksum) + " in " + config.GetPath(".osrm.edges").string()); } } if (boost::filesystem::exists(config.GetPath(".osrm.partition"))) { BOOST_ASSERT(layout.GetBlockSize("/mld/multilevelpartition/level_data") > 0); BOOST_ASSERT(layout.GetBlockSize("/mld/multilevelpartition/cell_to_children") > 0); BOOST_ASSERT(layout.GetBlockSize("/mld/multilevelpartition/partition") > 0); auto level_data = layout.GetBlockPtr( memory_ptr, "/mld/multilevelpartition/level_data"); auto mld_partition_ptr = layout.GetBlockPtr(memory_ptr, "/mld/multilevelpartition/partition"); auto partition_entries_count = layout.GetBlockEntries("/mld/multilevelpartition/partition"); util::vector_view partition(mld_partition_ptr, partition_entries_count); auto mld_chilren_ptr = layout.GetBlockPtr( memory_ptr, "/mld/multilevelpartition/cell_to_children"); auto children_entries_count = layout.GetBlockEntries("/mld/multilevelpartition/cell_to_children"); util::vector_view cell_to_children(mld_chilren_ptr, children_entries_count); partitioner::MultiLevelPartitionView mlp{ std::move(level_data), std::move(partition), std::move(cell_to_children)}; partitioner::files::readPartition(config.GetPath(".osrm.partition"), mlp); } if (boost::filesystem::exists(config.GetPath(".osrm.cells"))) { BOOST_ASSERT(layout.GetBlockSize("/mld/cellstorage/cells") > 0); BOOST_ASSERT(layout.GetBlockSize("/mld/cellstorage/level_to_cell_offset") > 0); auto mld_source_boundary_ptr = layout.GetBlockPtr(memory_ptr, "/mld/cellstorage/source_boundary"); auto mld_destination_boundary_ptr = layout.GetBlockPtr(memory_ptr, "/mld/cellstorage/destination_boundary"); auto mld_cells_ptr = layout.GetBlockPtr( memory_ptr, "/mld/cellstorage/cells"); auto mld_cell_level_offsets_ptr = layout.GetBlockPtr( memory_ptr, "/mld/cellstorage/level_to_cell_offset"); auto source_boundary_entries_count = layout.GetBlockEntries("/mld/cellstorage/source_boundary"); auto destination_boundary_entries_count = layout.GetBlockEntries("/mld/cellstorage/destination_boundary"); auto cells_entries_counts = layout.GetBlockEntries("/mld/cellstorage/cells"); auto cell_level_offsets_entries_count = 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); partitioner::CellStorageView storage{std::move(source_boundary), std::move(destination_boundary), std::move(cells), std::move(level_offsets)}; partitioner::files::readCells(config.GetPath(".osrm.cells"), storage); } if (boost::filesystem::exists(config.GetPath(".osrm.cell_metrics"))) { BOOST_ASSERT(layout.GetBlockSize("/mld/cellstorage/cells") > 0); BOOST_ASSERT(layout.GetBlockSize("/mld/cellstorage/level_to_cell_offset") > 0); std::unordered_map> metrics = { {metric_name, {}}, }; std::vector metric_prefix_names; layout.List("/mld/metrics/" + metric_name + "/exclude/", std::back_inserter(metric_prefix_names)); for (const auto &prefix : metric_prefix_names) { auto weights_block_id = prefix + "/weights"; auto durations_block_id = prefix + "/durations"; auto weight_entries_count = layout.GetBlockEntries(weights_block_id); auto duration_entries_count = layout.GetBlockEntries(durations_block_id); auto mld_cell_weights_ptr = layout.GetBlockPtr(memory_ptr, weights_block_id); auto mld_cell_duration_ptr = layout.GetBlockPtr(memory_ptr, durations_block_id); util::vector_view weights(mld_cell_weights_ptr, weight_entries_count); util::vector_view durations(mld_cell_duration_ptr, duration_entries_count); metrics[metric_name].push_back( customizer::CellMetricView{std::move(weights), std::move(durations)}); } customizer::files::readCellMetrics(config.GetPath(".osrm.cell_metrics"), metrics); } if (boost::filesystem::exists(config.GetPath(".osrm.mldgr"))) { auto graph_nodes_ptr = layout.GetBlockPtr( memory_ptr, "/mld/multilevelgraph/node_array"); auto graph_edges_ptr = layout.GetBlockPtr( memory_ptr, "/mld/multilevelgraph/edge_array"); auto graph_node_to_offset_ptr = layout.GetBlockPtr( memory_ptr, "/mld/multilevelgraph/node_to_edge_offset"); util::vector_view node_list( graph_nodes_ptr, layout.GetBlockEntries("/mld/multilevelgraph/node_array")); util::vector_view edge_list( graph_edges_ptr, layout.GetBlockEntries("/mld/multilevelgraph/edge_array")); util::vector_view node_to_offset( graph_node_to_offset_ptr, layout.GetBlockEntries("/mld/multilevelgraph/node_to_edge_offset")); std::uint32_t graph_connectivity_checksum = 0; customizer::MultiLevelEdgeBasedGraphView graph_view( std::move(node_list), std::move(edge_list), std::move(node_to_offset)); partitioner::files::readGraph( config.GetPath(".osrm.mldgr"), graph_view, graph_connectivity_checksum); if (turns_connectivity_checksum != graph_connectivity_checksum) { throw util::exception( "Connectivity checksum " + std::to_string(graph_connectivity_checksum) + " in " + config.GetPath(".osrm.mldgr").string() + " does not equal to checksum " + std::to_string(turns_connectivity_checksum) + " in " + config.GetPath(".osrm.edges").string()); } } // load maneuver overrides { const auto maneuver_overrides_ptr = layout.GetBlockPtr( memory_ptr, "/common/maneuver_overrides/overrides"); const auto maneuver_override_node_sequences_ptr = layout.GetBlockPtr( memory_ptr, "/common/maneuver_overrides/node_sequences"); util::vector_view maneuver_overrides( maneuver_overrides_ptr, layout.GetBlockEntries("/common/maneuver_overrides/overrides")); util::vector_view maneuver_override_node_sequences( maneuver_override_node_sequences_ptr, layout.GetBlockEntries("/common/maneuver_overrides/node_sequences")); extractor::files::readManeuverOverrides(config.GetPath(".osrm.maneuver_overrides"), maneuver_overrides, maneuver_override_node_sequences); } } } }