diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 16d9464dc..082583dfc 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -8,7 +8,7 @@ #include "engine/algorithm.hpp" #include "engine/geospatial_query.hpp" -#include "extractor/compressed_edge_container.hpp" +#include "extractor/segment_data_container.hpp" #include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_lane_types.hpp" #include "extractor/profile_properties.hpp" @@ -218,18 +218,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade util::ShM::vector m_post_turn_bearing; util::NameTable m_names_table; util::ShM::vector m_name_begin_indices; - util::ShM::vector m_geometry_indices; - util::ShM::vector m_geometry_node_list; - util::ShM::vector m_geometry_fwd_weight_list; - util::ShM::vector m_geometry_rev_weight_list; - util::ShM::vector m_geometry_fwd_duration_list; - util::ShM::vector m_geometry_rev_duration_list; util::ShM::vector m_is_core_node; util::ShM::vector m_datasource_list; 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; @@ -441,48 +436,49 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade 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]); - m_geometry_indices = std::move(geometry_begin_indices); 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]); - m_geometry_node_list = std::move(geometry_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]); - m_geometry_fwd_weight_list = std::move(geometry_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]); - m_geometry_rev_weight_list = std::move(geometry_rev_weight_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]); - m_datasource_list = std::move(datasources_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]); - m_geometry_fwd_duration_list = std::move(geometry_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]); - m_geometry_rev_duration_list = std::move(geometry_rev_duration_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)}; + + 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]); + m_datasource_list = std::move(datasources_list); auto datasource_name_data_ptr = data_layout.GetBlockPtr(memory_block, storage::DataLayout::DATASOURCE_NAME_DATA); @@ -576,144 +572,43 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade virtual std::vector GetUncompressedForwardGeometry(const EdgeID id) const override final { - /* - * NodeID's for geometries are stored in one place for - * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores - * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_node_list vector. For - * forward geometries of bi-directional edges, edges 2 to - * n of that edge need to be read. - */ - const auto begin = m_geometry_indices.at(id); - const auto end = m_geometry_indices.at(id + 1); - std::vector result_nodes; - result_nodes.reserve(end - begin); - - std::copy(m_geometry_node_list.begin() + begin, - m_geometry_node_list.begin() + end, - std::back_inserter(result_nodes)); - - return result_nodes; + auto range = segment_data.GetForwardGeometry(id); + return std::vector {range.begin(), range.end()}; } virtual std::vector GetUncompressedReverseGeometry(const EdgeID id) const override final { - /* - * NodeID's for geometries are stored in one place for - * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores - * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_node_list vector. - * */ - const auto begin = m_geometry_indices.at(id); - const auto end = m_geometry_indices.at(id + 1); - - std::vector result_nodes; - result_nodes.reserve(end - begin); - - std::reverse_copy(m_geometry_node_list.begin() + begin, - m_geometry_node_list.begin() + end, - std::back_inserter(result_nodes)); - - return result_nodes; + auto range = segment_data.GetReverseGeometry(id); + return std::vector {range.begin(), range.end()}; } virtual std::vector GetUncompressedForwardDurations(const EdgeID id) const override final { - /* - * EdgeWeights's for geometries are stored in one place for - * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores - * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_fwd_weight_list vector. - * */ - const auto begin = m_geometry_indices.at(id) + 1; - const auto end = m_geometry_indices.at(id + 1); - - std::vector result_durations; - result_durations.reserve(end - begin); - - std::copy(m_geometry_fwd_duration_list.begin() + begin, - m_geometry_fwd_duration_list.begin() + end, - std::back_inserter(result_durations)); - - return result_durations; + auto range = segment_data.GetForwardDurations(id); + return std::vector {range.begin(), range.end()}; } virtual std::vector GetUncompressedReverseDurations(const EdgeID id) const override final { - /* - * EdgeWeights for geometries are stored in one place for - * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores - * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_rev_weight_list vector. For - * reverse durations of bi-directional edges, edges 1 to - * n-1 of that edge need to be read in reverse. - */ - const auto begin = m_geometry_indices.at(id); - const auto end = m_geometry_indices.at(id + 1) - 1; - - std::vector result_durations; - result_durations.reserve(end - begin); - - std::reverse_copy(m_geometry_rev_duration_list.begin() + begin, - m_geometry_rev_duration_list.begin() + end, - std::back_inserter(result_durations)); - - return result_durations; + auto range = segment_data.GetReverseDurations(id); + return std::vector {range.begin(), range.end()}; } virtual std::vector GetUncompressedForwardWeights(const EdgeID id) const override final { - /* - * EdgeWeights's for geometries are stored in one place for - * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores - * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_fwd_weight_list vector. - * */ - const auto begin = m_geometry_indices.at(id) + 1; - const auto end = m_geometry_indices.at(id + 1); - - std::vector result_weights; - result_weights.reserve(end - begin); - - std::copy(m_geometry_fwd_weight_list.begin() + begin, - m_geometry_fwd_weight_list.begin() + end, - std::back_inserter(result_weights)); - - return result_weights; + auto range = segment_data.GetForwardWeights(id); + return std::vector {range.begin(), range.end()}; } virtual std::vector GetUncompressedReverseWeights(const EdgeID id) const override final { - /* - * EdgeWeights for geometries are stored in one place for - * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores - * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_rev_weight_list vector. For - * reverse weights of bi-directional edges, edges 1 to - * n-1 of that edge need to be read in reverse. - */ - const auto begin = m_geometry_indices.at(id); - const auto end = m_geometry_indices.at(id + 1) - 1; - - std::vector result_weights; - result_weights.reserve(end - begin); - - std::reverse_copy(m_geometry_rev_weight_list.begin() + begin, - m_geometry_rev_weight_list.begin() + end, - std::back_inserter(result_weights)); - - return result_weights; + auto range = segment_data.GetReverseWeights(id); + return std::vector {range.begin(), range.end()}; } virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final @@ -894,14 +789,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade /* * Data sources for geometries are stored in one place for * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores + * directional edge. The indices stores * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_list vector. For + * directional edge in the list vector. For * forward datasources of bi-directional edges, edges 2 to * n of that edge need to be read. */ - const auto begin = m_geometry_indices.at(id) + 1; - const auto end = m_geometry_indices.at(id + 1); + const auto begin = segment_data.GetOffset(id, 0) + 1; + const auto end = segment_data.GetOffset(id + 1, 0); std::vector result_datasources; result_datasources.reserve(end - begin); @@ -929,14 +824,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade /* * Datasources for geometries are stored in one place for * both forward and reverse segments along the same bi- - * directional edge. The m_geometry_indices stores + * directional edge. The indices stores * refences to where to find the beginning of the bi- - * directional edge in the m_geometry_list vector. For + * directional edge in the list vector. For * reverse datasources of bi-directional edges, edges 1 to * n-1 of that edge need to be read in reverse. */ - const unsigned begin = m_geometry_indices.at(id); - const unsigned end = m_geometry_indices.at(id + 1) - 1; + const auto begin = segment_data.GetOffset(id, 0); + const auto end = segment_data.GetOffset(id + 1, 0) - 1; std::vector result_datasources; result_datasources.reserve(end - begin); diff --git a/include/extractor/segment_data_container.hpp b/include/extractor/segment_data_container.hpp index 6e860027f..099f87992 100644 --- a/include/extractor/segment_data_container.hpp +++ b/include/extractor/segment_data_container.hpp @@ -42,7 +42,9 @@ template class SegmentDataContainerImpl friend CompressedEdgeContainer; public: - using SegmentID = std::uint32_t; + // FIXME We should change the indexing to Edge-Based-Node id + using DirectionalGeometryID = std::uint32_t; + using SegmentOffset = std::uint32_t; SegmentDataContainerImpl() = default; @@ -58,51 +60,80 @@ template class SegmentDataContainerImpl { } - auto GetForwardGeometry(const SegmentID id) const + // TODO these random access functions can be removed after we implemented #3737 + auto& ForwardDuration(const DirectionalGeometryID id, const SegmentOffset offset) { - const auto begin = nodes.begin() + index.at(id); - const auto end = nodes.begin() + index.at(id + 1); + return fwd_durations[index[id] + 1 + offset]; + } + auto& ReverseDuration(const DirectionalGeometryID id, const SegmentOffset offset) + { + return rev_durations[index[id] + offset]; + } + auto& ForwardWeight(const DirectionalGeometryID id, const SegmentOffset offset) + { + return fwd_weights[index[id] + 1 + offset]; + } + auto& ReverseWeight(const DirectionalGeometryID id, const SegmentOffset offset) + { + return rev_weights[index[id] + offset]; + } + // TODO we only need this for the datasource file since it breaks this + // abstraction, but uses this index + auto GetOffset(const DirectionalGeometryID id, const SegmentOffset offset) const + { + return index[id] + offset; + } + + auto GetForwardGeometry(const DirectionalGeometryID id) const + { + const auto begin = nodes.cbegin() + index.at(id); + const auto end = nodes.cbegin() + index.at(id + 1); return boost::make_iterator_range(begin, end); } - auto GetReverseGeometry(const SegmentID id) const + auto GetReverseGeometry(const DirectionalGeometryID id) const { return boost::adaptors::reverse(GetForwardGeometry(id)); } - auto GetForwardDurations(const SegmentID id) const + auto GetForwardDurations(const DirectionalGeometryID id) const { - const auto begin = fwd_durations.begin() + index.at(id) + 1; - const auto end = fwd_durations.begin() + index.at(id + 1); + const auto begin = fwd_durations.cbegin() + index.at(id) + 1; + const auto end = fwd_durations.cbegin() + index.at(id + 1); return boost::make_iterator_range(begin, end); } - auto GetReverseDurations(const SegmentID id) const + auto GetReverseDurations(const DirectionalGeometryID id) const { - const auto begin = rev_durations.begin() + index.at(id); - const auto end = rev_durations.begin() + index.at(id + 1) - 1; + const auto begin = rev_durations.cbegin() + index.at(id); + const auto end = rev_durations.cbegin() + index.at(id + 1) - 1; return boost::adaptors::reverse(boost::make_iterator_range(begin, end)); } - auto GetForwardWeights(const SegmentID id) const + auto GetForwardWeights(const DirectionalGeometryID id) const { - const auto begin = fwd_weights.begin() + index.at(id) + 1; - const auto end = fwd_weights.begin() + index.at(id + 1); + const auto begin = fwd_weights.cbegin() + index.at(id) + 1; + const auto end = fwd_weights.cbegin() + index.at(id + 1); return boost::make_iterator_range(begin, end); } - auto GetReverseWeights(const SegmentID id) const + auto GetReverseWeights(const DirectionalGeometryID id) const { - const auto begin = rev_weights.begin() + index.at(id); - const auto end = rev_weights.begin() + index.at(id + 1) - 1; + const auto begin = rev_weights.cbegin() + index.at(id); + const auto end = rev_weights.cbegin() + index.at(id + 1) - 1; return boost::adaptors::reverse(boost::make_iterator_range(begin, end)); } + auto GetNumberOfSegments() const + { + return fwd_weights.size(); + } + friend void io::read(const boost::filesystem::path &path, detail::SegmentDataContainerImpl &segment_data); friend void io::write(const boost::filesystem::path &path, diff --git a/include/util/shared_memory_vector_wrapper.hpp b/include/util/shared_memory_vector_wrapper.hpp index 3f6affcfe..dacc18b2c 100644 --- a/include/util/shared_memory_vector_wrapper.hpp +++ b/include/util/shared_memory_vector_wrapper.hpp @@ -34,6 +34,7 @@ class ShMemIterator typedef typename base_t::reference reference; typedef std::random_access_iterator_tag iterator_category; + explicit ShMemIterator() : m_value(nullptr) {} explicit ShMemIterator(DataT *x) : m_value(x) {} private: @@ -60,6 +61,7 @@ template class SharedMemoryWrapper public: using value_type = DataT; using iterator = ShMemIterator; + using const_iterator = ShMemIterator; using reverse_iterator = boost::reverse_iterator; SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {} @@ -86,6 +88,10 @@ template class SharedMemoryWrapper auto end() const { return iterator(m_ptr + m_size); } + auto cbegin() const { return const_iterator(m_ptr); } + + auto cend() const { return const_iterator(m_ptr + m_size); } + auto rbegin() const { return reverse_iterator(iterator(m_ptr + m_size)); } auto rend() const { return reverse_iterator(iterator(m_ptr)); } diff --git a/src/updater/updater.cpp b/src/updater/updater.cpp index 32ee19921..8c6afb19f 100644 --- a/src/updater/updater.cpp +++ b/src/updater/updater.cpp @@ -5,6 +5,7 @@ #include "extractor/compressed_edge_container.hpp" #include "extractor/edge_based_graph_factory.hpp" #include "extractor/node_based_edge.hpp" +#include "extractor/io.hpp" #include "storage/io.hpp" #include "util/exception.hpp" @@ -268,12 +269,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e std::vector geometry_datasource; std::vector internal_to_external_node_map; - std::vector geometry_indices; - std::vector geometry_node_list; - std::vector geometry_fwd_weight_list; - std::vector geometry_rev_weight_list; - std::vector geometry_fwd_duration_list; - std::vector geometry_rev_duration_list; + extractor::SegmentDataContainer segment_data; const auto maybe_load_internal_to_external_node_map = [&] { if (!update_edge_weights) @@ -289,33 +285,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e if (!update_edge_weights) return; - storage::io::FileReader geometry_file(config.geometry_path, - storage::io::FileReader::HasNoFingerprint); - const auto number_of_indices = geometry_file.ReadElementCount32(); - geometry_indices.resize(number_of_indices); - geometry_file.ReadInto(geometry_indices.data(), number_of_indices); - - const auto number_of_compressed_geometries = geometry_file.ReadElementCount32(); - - BOOST_ASSERT(geometry_indices.back() == number_of_compressed_geometries); - geometry_node_list.resize(number_of_compressed_geometries); - geometry_fwd_weight_list.resize(number_of_compressed_geometries); - geometry_rev_weight_list.resize(number_of_compressed_geometries); - geometry_fwd_duration_list.resize(number_of_compressed_geometries); - geometry_rev_duration_list.resize(number_of_compressed_geometries); - - if (number_of_compressed_geometries > 0) - { - geometry_file.ReadInto(geometry_node_list.data(), number_of_compressed_geometries); - geometry_file.ReadInto(geometry_fwd_weight_list.data(), - number_of_compressed_geometries); - geometry_file.ReadInto(geometry_rev_weight_list.data(), - number_of_compressed_geometries); - geometry_file.ReadInto(geometry_fwd_duration_list.data(), - number_of_compressed_geometries); - geometry_file.ReadInto(geometry_rev_duration_list.data(), - number_of_compressed_geometries); - } + extractor::io::read(config.geometry_path, segment_data); }; // Folds all our actions into independently concurrently executing lambdas @@ -332,7 +302,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e // CSV file that supplied the value that gets used for that segment, then // we write out this list so that it can be returned by the debugging // vector tiles later on. - geometry_datasource.resize(geometry_fwd_weight_list.size(), 0); + geometry_datasource.resize(segment_data.GetNumberOfSegments(), 0); // Now, we iterate over all the segments stored in the StaticRTree, updating // the packed geometry weights in the `.geometries` file (note: we do not @@ -363,14 +333,20 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e { const auto &leaf_object = current_node.objects[i]; - const auto forward_begin = geometry_indices.at(leaf_object.packed_geometry_id); - const auto u_index = forward_begin + leaf_object.fwd_segment_position; - const auto v_index = forward_begin + leaf_object.fwd_segment_position + 1; + const auto geometry_id = leaf_object.packed_geometry_id; + auto nodes_range = segment_data.GetForwardGeometry(geometry_id); + + const auto segment_offset = leaf_object.fwd_segment_position; + const auto u_index = segment_offset; + const auto v_index = segment_offset + 1; + + BOOST_ASSERT(u_index < nodes_range.size()); + BOOST_ASSERT(v_index < nodes_range.size()); const extractor::QueryNode &u = - internal_to_external_node_map[geometry_node_list[u_index]]; + internal_to_external_node_map[nodes_range[u_index]]; const extractor::QueryNode &v = - internal_to_external_node_map[geometry_node_list[v_index]]; + internal_to_external_node_map[nodes_range[v_index]]; const double segment_length = util::coordinate_calculation::greatCircleDistance( util::Coordinate{u.lon, u.lat}, util::Coordinate{v.lon, v.lat}); @@ -383,15 +359,15 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e weight_multiplier, *value, segment_length, - geometry_fwd_duration_list[u_index], + segment_data.ForwardWeight(geometry_id, segment_offset), u.node_id, v.node_id, new_segment_weight, new_segment_duration); - geometry_fwd_weight_list[v_index] = new_segment_weight; - geometry_fwd_duration_list[v_index] = new_segment_duration; - geometry_datasource[v_index] = value->source; + segment_data.ForwardWeight(geometry_id, segment_offset) = new_segment_weight; + segment_data.ForwardDuration(geometry_id, segment_offset) = new_segment_duration; + geometry_datasource[segment_data.GetOffset(geometry_id, segment_offset)+1] = value->source; fwd_source = value->source; } @@ -402,15 +378,15 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e weight_multiplier, *value, segment_length, - geometry_rev_duration_list[u_index], + segment_data.ReverseWeight(geometry_id, segment_offset), v.node_id, u.node_id, new_segment_weight, new_segment_duration); - geometry_rev_weight_list[u_index] = new_segment_weight; - geometry_rev_duration_list[u_index] = new_segment_duration; - geometry_datasource[u_index] = value->source; + segment_data.ReverseWeight(geometry_id, segment_offset) = new_segment_weight; + segment_data.ReverseDuration(geometry_id, segment_offset) = new_segment_duration; + geometry_datasource[segment_data.GetOffset(geometry_id, segment_offset)] = value->source; rev_source = value->source; } @@ -451,29 +427,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e return; // Now save out the updated compressed geometries - std::ofstream geometry_stream(config.geometry_path, std::ios::binary); - if (!geometry_stream) - { - const std::string message{"Failed to open " + config.geometry_path + " for writing"}; - throw util::exception(message + SOURCE_REF); - } - const unsigned number_of_indices = geometry_indices.size(); - const unsigned number_of_compressed_geometries = geometry_node_list.size(); - geometry_stream.write(reinterpret_cast(&number_of_indices), sizeof(unsigned)); - geometry_stream.write(reinterpret_cast(&(geometry_indices[0])), - number_of_indices * sizeof(unsigned)); - geometry_stream.write(reinterpret_cast(&number_of_compressed_geometries), - sizeof(unsigned)); - geometry_stream.write(reinterpret_cast(&(geometry_node_list[0])), - number_of_compressed_geometries * sizeof(NodeID)); - geometry_stream.write(reinterpret_cast(&(geometry_fwd_weight_list[0])), - number_of_compressed_geometries * sizeof(EdgeWeight)); - geometry_stream.write(reinterpret_cast(&(geometry_rev_weight_list[0])), - number_of_compressed_geometries * sizeof(EdgeWeight)); - geometry_stream.write(reinterpret_cast(&(geometry_fwd_duration_list[0])), - number_of_compressed_geometries * sizeof(EdgeWeight)); - geometry_stream.write(reinterpret_cast(&(geometry_rev_duration_list[0])), - number_of_compressed_geometries * sizeof(EdgeWeight)); + extractor::io::write(config.geometry_path, segment_data); }; const auto save_datasource_indexes = [&] {