diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index bdcfd9224..4d90b55c9 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -254,17 +254,21 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade "Is any data loaded into shared memory?" + SOURCE_REF); } - auto tree_nodes_ptr = + const auto rtree_ptr = data_layout.GetBlockPtr(memory_block, storage::DataLayout::R_SEARCH_TREE); - auto tree_level_sizes_ptr = data_layout.GetBlockPtr( - memory_block, storage::DataLayout::R_SEARCH_TREE_LEVELS); - m_static_rtree.reset( - new SharedRTree(tree_nodes_ptr, - data_layout.GetBlockEntries(storage::DataLayout::R_SEARCH_TREE), - tree_level_sizes_ptr, - data_layout.GetBlockEntries(storage::DataLayout::R_SEARCH_TREE_LEVELS), - file_index_path, - m_coordinate_list)); + util::vector_view search_tree( + rtree_ptr, data_layout.GetBlockEntries(storage::DataLayout::R_SEARCH_TREE)); + + const auto rtree_levelstarts_ptr = data_layout.GetBlockPtr( + memory_block, storage::DataLayout::R_SEARCH_TREE_LEVEL_STARTS); + util::vector_view rtree_level_starts( + rtree_levelstarts_ptr, + data_layout.GetBlockEntries(storage::DataLayout::R_SEARCH_TREE_LEVEL_STARTS)); + + m_static_rtree.reset(new SharedRTree{std::move(search_tree), + std::move(rtree_level_starts), + file_index_path, + m_coordinate_list}); m_geospatial_query.reset( new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this)); } diff --git a/include/extractor/files.hpp b/include/extractor/files.hpp index dd5793905..0d0820cff 100644 --- a/include/extractor/files.hpp +++ b/include/extractor/files.hpp @@ -450,13 +450,32 @@ void readEdgeBasedNodeWeights(const boost::filesystem::path &path, NodeWeigtsVec } template -void writeEdgeBasedNodeWeights(const boost::filesystem::path &path, const NodeWeigtsVectorT &weights) +void writeEdgeBasedNodeWeights(const boost::filesystem::path &path, + const NodeWeigtsVectorT &weights) { const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint; storage::tar::FileWriter writer{path, fingerprint}; storage::serialization::write(writer, "/extractor/edge_based_node_weights", weights); } + +template +void writeRamIndex(const boost::filesystem::path &path, const RTreeT &rtree) +{ + const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint; + storage::tar::FileWriter writer{path, fingerprint}; + + util::serialization::write(writer, "/common/rtree", rtree); +} + +template +void readRamIndex(const boost::filesystem::path &path, RTreeT &rtree) +{ + const auto fingerprint = storage::tar::FileReader::VerifyFingerprint; + storage::tar::FileReader reader{path, fingerprint}; + + util::serialization::read(reader, "/common/rtree", rtree); +} } } } diff --git a/include/storage/shared_datatype.hpp b/include/storage/shared_datatype.hpp index 1345f656a..56e6c99ba 100644 --- a/include/storage/shared_datatype.hpp +++ b/include/storage/shared_datatype.hpp @@ -40,7 +40,7 @@ const constexpr char *block_id_to_name[] = {"IGNORE_BLOCK", "TURN_INSTRUCTION", "ENTRY_CLASSID", "R_SEARCH_TREE", - "R_SEARCH_TREE_LEVELS", + "R_SEARCH_TREE_LEVEL_STARTS", "GEOMETRIES_INDEX", "GEOMETRIES_NODE_LIST", "GEOMETRIES_FWD_WEIGHT_LIST", @@ -120,7 +120,7 @@ class DataLayout TURN_INSTRUCTION, ENTRY_CLASSID, R_SEARCH_TREE, - R_SEARCH_TREE_LEVELS, + R_SEARCH_TREE_LEVEL_STARTS, GEOMETRIES_INDEX, GEOMETRIES_NODE_LIST, GEOMETRIES_FWD_WEIGHT_LIST, diff --git a/include/util/serialization.hpp b/include/util/serialization.hpp index 7210ce63a..314497812 100644 --- a/include/util/serialization.hpp +++ b/include/util/serialization.hpp @@ -6,6 +6,7 @@ #include "util/range_table.hpp" #include "util/static_graph.hpp" #include "util/indexed_data.hpp" +#include "util/static_rtree.hpp" #include "storage/io.hpp" #include "storage/serialization.hpp" @@ -185,6 +186,26 @@ inline void write(storage::tar::FileWriter &writer, storage::serialization::write(writer, name + "/blocks", index_data.blocks); storage::serialization::write(writer, name + "/values", index_data.values); } + +template +void read(storage::tar::FileReader &reader, const std::string& name, util::StaticRTree &rtree) +{ + storage::serialization::read(reader, name + "/search_tree", rtree.m_search_tree); + storage::serialization::read(reader, name + "/search_tree_level_starts", rtree.m_tree_level_starts); +} + +template +void write(storage::tar::FileWriter &writer, const std::string& name, const util::StaticRTree &rtree){ + storage::serialization::write(writer, name + "/search_tree", rtree.m_search_tree); + storage::serialization::write(writer, name + "/search_tree_level_starts", rtree.m_tree_level_starts); +} + } } } diff --git a/include/util/static_rtree.hpp b/include/util/static_rtree.hpp index cefa7517b..4c0116cba 100644 --- a/include/util/static_rtree.hpp +++ b/include/util/static_rtree.hpp @@ -1,7 +1,8 @@ #ifndef STATIC_RTREE_HPP #define STATIC_RTREE_HPP -#include "storage/io.hpp" +#include "storage/tar_fwd.hpp" + #include "util/bearing.hpp" #include "util/coordinate_calculation.hpp" #include "util/deallocating_vector.hpp" @@ -35,20 +36,35 @@ #include #include -// An extended alignment is implementation-defined, so use compiler attributes -// until alignas(LEAF_PAGE_SIZE) is compiler-independent. -#if defined(_MSC_VER) -#define ALIGNED(x) __declspec(align(x)) -#elif defined(__GNUC__) -#define ALIGNED(x) __attribute__((aligned(x))) -#else -#define ALIGNED(x) -#endif - namespace osrm { namespace util { +template +class StaticRTree; + +namespace serialization +{ +template +inline void read(storage::tar::FileReader &reader, + const std::string &name, + util::StaticRTree &rtree); + +template +inline void +write(storage::tar::FileWriter &writer, + const std::string &name, + const util::StaticRTree &rtree); +} /*** * Static RTree for serving nearest neighbour queries @@ -57,9 +73,9 @@ namespace util */ template + storage::Ownership Ownership, + std::uint32_t BRANCHING_FACTOR, + std::uint32_t LEAF_PAGE_SIZE> class StaticRTree { /********************************************************** @@ -236,39 +252,31 @@ class StaticRTree std::uint32_t segment_index; }; - // We use a const view type when we don't own the data, otherwise - // we use a mutable type (usually becase we're building the tree) - using TreeViewType = typename std::conditional, - Vector>::type; - TreeViewType m_search_tree; - + // Representation of the in-memory search tree + Vector m_search_tree; // Reference to the actual lon/lat data we need for doing math const Vector &m_coordinate_list; - - // Holds the number of TreeNodes in each level. - // We always start with the root node, so - // m_tree_level_sizes[0] should always be 1 - std::vector m_tree_level_sizes; - // Holds the start indexes of each level in m_search_tree - std::vector m_tree_level_starts; - + Vector m_tree_level_starts; // mmap'd .fileIndex file - boost::iostreams::mapped_file_source m_objects_region; + boost::iostreams::mapped_file m_objects_region; // This is a view of the EdgeDataT data mmap'd from the .fileIndex file - util::vector_view m_objects; + util::vector_view m_objects; public: StaticRTree(const StaticRTree &) = delete; StaticRTree &operator=(const StaticRTree &) = delete; + StaticRTree(StaticRTree &&) = default; + StaticRTree &operator=(StaticRTree &&) = default; // Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1] explicit StaticRTree(const std::vector &input_data_vector, - const std::string &tree_node_filename, - const std::string &leaf_node_filename, - const Vector &coordinate_list) - : m_coordinate_list(coordinate_list) + const Vector &coordinate_list, + const boost::filesystem::path &on_disk_file_name) + : m_coordinate_list(coordinate_list), m_objects{mmapFile( + on_disk_file_name, + m_objects_region, + input_data_vector.size() * sizeof(EdgeDataT))} { const auto element_count = input_data_vector.size(); std::vector input_wrapper_vector(element_count); @@ -304,8 +312,7 @@ class StaticRTree // sort the hilbert-value representatives tbb::parallel_sort(input_wrapper_vector.begin(), input_wrapper_vector.end()); { - storage::io::FileWriter leaf_node_file(leaf_node_filename, - storage::io::FileWriter::HasNoFingerprint); + // Note, we can't just write everything in one go, because the input_data_vector // is not sorted by hilbert code, only the input_wrapper_vector is in the correct // order. Instead, we iterate over input_wrapper_vector, copy the hilbert-indexed @@ -315,13 +322,12 @@ class StaticRTree // Create the first level of TreeNodes - each bounding LEAF_NODE_COUNT EdgeDataT // objects. std::size_t wrapped_element_index = 0; + auto objects_iter = m_objects.begin(); + while (wrapped_element_index < element_count) { TreeNode current_node; - std::array objects; - std::uint32_t object_count = 0; - // Loop over the next block of EdgeDataT, calculate the bounding box // for the block, and save the data to write to disk in the correct // order. @@ -333,8 +339,7 @@ class StaticRTree input_wrapper_vector[wrapped_element_index].m_original_index; const EdgeDataT &object = input_data_vector[input_object_index]; - object_count += 1; - objects[object_index] = object; + *objects_iter++ = object; Coordinate projected_u{ web_mercator::fromWGS84(Coordinate{m_coordinate_list[object.u]})}; @@ -361,19 +366,19 @@ class StaticRTree current_node.minimum_bounding_rectangle.MergeBoundingBoxes(rectangle); } - // Write out our EdgeDataT block to the leaf node file - leaf_node_file.WriteFrom(objects.data(), object_count); - m_search_tree.emplace_back(current_node); } - - // leaf_node_file wil be RAII closed at this point } // Should hold the number of nodes at the lowest level of the graph (closest // to the data) std::uint32_t nodes_in_previous_level = m_search_tree.size(); - m_tree_level_sizes.push_back(nodes_in_previous_level); + + // Holds the number of TreeNodes in each level. + // We always start with the root node, so + // m_tree_level_sizes[0] should always be 1 + std::vector tree_level_sizes; + tree_level_sizes.push_back(nodes_in_previous_level); // Now, repeatedly create levels of nodes that contain BRANCHING_FACTOR // nodes from the previous level. @@ -408,7 +413,7 @@ class StaticRTree m_search_tree.emplace_back(parent_node); } nodes_in_previous_level = nodes_in_current_level; - m_tree_level_sizes.push_back(nodes_in_previous_level); + tree_level_sizes.push_back(nodes_in_previous_level); } // At this point, we've got our tree built, but the nodes are in a weird order. // Next thing we'll do is flip it around so that we don't end up with a lot of @@ -419,14 +424,15 @@ class StaticRTree std::reverse(m_search_tree.begin(), m_search_tree.end()); // Same for the level sizes - root node / base level is at 0 - std::reverse(m_tree_level_sizes.begin(), m_tree_level_sizes.end()); + std::reverse(tree_level_sizes.begin(), tree_level_sizes.end()); // The first level starts at 0 m_tree_level_starts = {0}; // The remaining levels start at the partial sum of the preceeding level sizes - std::partial_sum(m_tree_level_sizes.begin(), - m_tree_level_sizes.end() - 1, + std::partial_sum(tree_level_sizes.begin(), + tree_level_sizes.end(), std::back_inserter(m_tree_level_starts)); + BOOST_ASSERT(m_tree_level_starts.size() >= 2); // Now we have to flip the coordinates within each level so that math is easier // later on. The workflow here is: @@ -438,58 +444,22 @@ class StaticRTree // 0 12 345 6789 // This ordering keeps the position math easy to understand during later // searches - for (auto i : irange(0, m_tree_level_sizes.size())) + for (auto i : irange(0, tree_level_sizes.size())) { std::reverse(m_search_tree.begin() + m_tree_level_starts[i], - m_search_tree.begin() + m_tree_level_starts[i] + m_tree_level_sizes[i]); + m_search_tree.begin() + m_tree_level_starts[i] + tree_level_sizes[i]); } - - // Write all the TreeNode data to disk - { - storage::io::FileWriter tree_node_file(tree_node_filename, - storage::io::FileWriter::GenerateFingerprint); - - std::uint64_t size_of_tree = m_search_tree.size(); - BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty"); - - tree_node_file.WriteFrom(size_of_tree); - tree_node_file.WriteFrom(m_search_tree); - - tree_node_file.WriteFrom(static_cast(m_tree_level_sizes.size())); - tree_node_file.WriteFrom(m_tree_level_sizes); - } - - m_objects = mmapFile(leaf_node_filename, m_objects_region); } /** - * Constructs an r-tree from already prepared files on disk (generated by the previous - * constructor) + * Constructs an empty RTree for de-serialization. */ - explicit StaticRTree(const boost::filesystem::path &node_file, - const boost::filesystem::path &leaf_file, + template > + explicit StaticRTree(const boost::filesystem::path &on_disk_file_name, const Vector &coordinate_list) : m_coordinate_list(coordinate_list) { - storage::io::FileReader tree_node_file(node_file, - storage::io::FileReader::VerifyFingerprint); - - const auto tree_size = tree_node_file.ReadElementCount64(); - m_search_tree.resize(tree_size); - tree_node_file.ReadInto(m_search_tree); - - const auto levels_array_size = tree_node_file.ReadElementCount64(); - m_tree_level_sizes.resize(levels_array_size); - tree_node_file.ReadInto(m_tree_level_sizes); - - // The first level always starts at 0 - m_tree_level_starts = {0}; - // The remaining levels start at the partial sum of the preceeding level sizes - std::partial_sum(m_tree_level_sizes.begin(), - m_tree_level_sizes.end() - 1, - std::back_inserter(m_tree_level_starts)); - - m_objects = mmapFile(leaf_file, m_objects_region); + m_objects = mmapFile(on_disk_file_name, m_objects_region); } /** @@ -498,22 +468,15 @@ class StaticRTree * These memory blocks basically just contain the files read into RAM, * excep the .fileIndex file always stays on disk, and we mmap() it as usual */ - explicit StaticRTree(const TreeNode *tree_node_ptr, - const uint64_t number_of_nodes, - const std::uint64_t *level_sizes_ptr, - const std::size_t number_of_levels, - const boost::filesystem::path &leaf_file, + explicit StaticRTree(Vector search_tree_, + Vector tree_level_starts, + const boost::filesystem::path &on_disk_file_name, const Vector &coordinate_list) - : m_search_tree(tree_node_ptr, number_of_nodes), m_coordinate_list(coordinate_list), - m_tree_level_sizes(level_sizes_ptr, level_sizes_ptr + number_of_levels) + : m_search_tree(std::move(search_tree_)), m_coordinate_list(coordinate_list), + m_tree_level_starts(std::move(tree_level_starts)) { - // The first level starts at 0 - m_tree_level_starts = {0}; - // The remaining levels start at the partial sum of the preceeding level sizes - std::partial_sum(m_tree_level_sizes.begin(), - m_tree_level_sizes.end() - 1, - std::back_inserter(m_tree_level_starts)); - m_objects = mmapFile(leaf_file, m_objects_region); + BOOST_ASSERT(m_tree_level_starts.size() >= 2); + m_objects = mmapFile(on_disk_file_name, m_objects_region); } /* Returns all features inside the bounding box. @@ -734,6 +697,13 @@ class StaticRTree } } + std::uint64_t GetLevelSize(const std::size_t level) const + { + BOOST_ASSERT(m_tree_level_starts.size() > level + 1); + BOOST_ASSERT(m_tree_level_starts[level + 1] >= m_tree_level_starts[level]); + return m_tree_level_starts[level + 1] - m_tree_level_starts[level]; + } + /** * Calculates the absolute position of child data in our packed data * vectors. @@ -769,22 +739,31 @@ class StaticRTree const std::uint64_t first_child_index = m_tree_level_starts[parent.level + 1] + parent.offset * BRANCHING_FACTOR; - const std::uint64_t end_child_index = std::min( - first_child_index + BRANCHING_FACTOR, - m_tree_level_starts[parent.level + 1] + m_tree_level_sizes[parent.level + 1]); + const std::uint64_t end_child_index = + std::min(first_child_index + BRANCHING_FACTOR, + m_tree_level_starts[parent.level + 1] + GetLevelSize(parent.level + 1)); BOOST_ASSERT(first_child_index < std::numeric_limits::max()); BOOST_ASSERT(end_child_index < std::numeric_limits::max()); BOOST_ASSERT(end_child_index <= m_search_tree.size()); - BOOST_ASSERT(end_child_index <= m_tree_level_starts[parent.level + 1] + - m_tree_level_sizes[parent.level + 1]); + BOOST_ASSERT(end_child_index <= + m_tree_level_starts[parent.level + 1] + GetLevelSize(parent.level + 1)); return irange(first_child_index, end_child_index); } } bool is_leaf(const TreeIndex &treeindex) const { - return treeindex.level == m_tree_level_starts.size() - 1; + BOOST_ASSERT(m_tree_level_starts.size() >= 2); + return treeindex.level == m_tree_level_starts.size() - 2; } + + friend void serialization::read( + storage::tar::FileReader &reader, + const std::string &name, + StaticRTree &rtree); + + friend void serialization::write( + storage::tar::FileWriter &writer, const std::string &name, const StaticRTree &rtree); }; //[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403 diff --git a/src/benchmarks/CMakeLists.txt b/src/benchmarks/CMakeLists.txt index 460c6a9b2..6a6986a22 100644 --- a/src/benchmarks/CMakeLists.txt +++ b/src/benchmarks/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB PackedVectorBenchmarkSources packed_vector.cpp) add_executable(rtree-bench EXCLUDE_FROM_ALL ${RTreeBenchmarkSources} - $) + $ $) target_include_directories(rtree-bench PUBLIC diff --git a/src/benchmarks/static_rtree.cpp b/src/benchmarks/static_rtree.cpp index 4a4880e1f..05ca8bd5c 100644 --- a/src/benchmarks/static_rtree.cpp +++ b/src/benchmarks/static_rtree.cpp @@ -1,6 +1,9 @@ #include "util/static_rtree.hpp" #include "extractor/edge_based_node_segment.hpp" #include "extractor/query_node.hpp" +#include "extractor/files.hpp" +#include "extractor/packed_osm_ids.hpp" + #include "mocks/mock_datafacade.hpp" #include "storage/io.hpp" #include "engine/geospatial_query.hpp" @@ -32,11 +35,10 @@ using BenchStaticRTree = util::StaticRTree loadCoordinates(const boost::filesystem::path &nodes_file) { - storage::io::FileReader nodes_path_file_reader(nodes_file, - storage::io::FileReader::VerifyFingerprint); - std::vector coords; - storage::serialization::read(nodes_path_file_reader, coords); + extractor::PackedOSMIDs nodes; + extractor::files::readNodes(nodes_file, coords, nodes); + return coords; } @@ -99,7 +101,8 @@ int main(int argc, char **argv) auto coords = osrm::benchmarks::loadCoordinates(nodes_path); - osrm::benchmarks::BenchStaticRTree rtree(ram_path, file_path, coords); + osrm::benchmarks::BenchStaticRTree rtree(file_path, coords); + osrm::extractor::files::readRamIndex(ram_path, rtree); osrm::benchmarks::benchmark(rtree, 10000); diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp index a7dca09dc..e6c70d137 100644 --- a/src/extractor/extractor.cpp +++ b/src/extractor/extractor.cpp @@ -805,10 +805,10 @@ void Extractor::BuildRTree(std::vector edge_based_node_seg edge_based_node_segments.resize(new_size); TIMER_START(construction); - util::StaticRTree rtree(edge_based_node_segments, - config.GetPath(".osrm.ramIndex").string(), - config.GetPath(".osrm.fileIndex").string(), - coordinates); + util::StaticRTree rtree(edge_based_node_segments, coordinates, + config.GetPath(".osrm.fileIndex")); + + files::writeRamIndex(config.GetPath(".osrm.ramIndex"), rtree); TIMER_STOP(construction); util::Log() << "finished r-tree construction in " << TIMER_SEC(construction) << " seconds"; diff --git a/src/storage/storage.cpp b/src/storage/storage.cpp index eec903bcc..54afe9284 100644 --- a/src/storage/storage.cpp +++ b/src/storage/storage.cpp @@ -244,19 +244,6 @@ void Storage::PopulateLayout(DataLayout &layout) make_block(absolute_file_index_path.string().length() + 1)); } - // load rsearch tree size - { - io::FileReader tree_node_file(config.GetPath(".osrm.ramIndex"), - io::FileReader::VerifyFingerprint); - - const auto tree_size = tree_node_file.ReadElementCount64(); - layout.SetBlock(DataLayout::R_SEARCH_TREE, make_block(tree_size)); - tree_node_file.Skip(tree_size); - const auto tree_levels_size = tree_node_file.ReadElementCount64(); - layout.SetBlock(DataLayout::R_SEARCH_TREE_LEVELS, - make_block(tree_levels_size)); - } - std::unordered_map name_to_block_id = { {"/mld/multilevelgraph/node_array", DataLayout::MLD_GRAPH_NODE_LIST}, {"/mld/multilevelgraph/edge_array", DataLayout::MLD_GRAPH_EDGE_LIST}, @@ -333,6 +320,8 @@ void Storage::PopulateLayout(DataLayout &layout) {"/common/turn_data/connectivity_checksum", DataLayout::IGNORE_BLOCK}, {"/common/names/blocks", DataLayout::NAME_BLOCKS}, {"/common/names/values", DataLayout::NAME_VALUES}, + {"/common/rtree/search_tree", DataLayout::R_SEARCH_TREE}, + {"/common/rtree/search_tree_level_starts", DataLayout::R_SEARCH_TREE_LEVEL_STARTS}, }; std::vector blocks; @@ -357,6 +346,7 @@ void Storage::PopulateLayout(DataLayout &layout) {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) @@ -636,22 +626,27 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr) // store search tree portion of rtree { - io::FileReader tree_node_file(config.GetPath(".osrm.ramIndex"), - io::FileReader::VerifyFingerprint); - // perform this read so that we're at the right stream position for the next - // read. - tree_node_file.Skip(1); + const auto rtree_ptr = layout.GetBlockPtr(memory_ptr, DataLayout::R_SEARCH_TREE); + util::vector_view search_tree( + rtree_ptr, layout.GetBlockEntries(storage::DataLayout::R_SEARCH_TREE)); - tree_node_file.ReadInto(rtree_ptr, layout.GetBlockEntries(DataLayout::R_SEARCH_TREE)); + const auto rtree_levelstarts_ptr = layout.GetBlockPtr( + memory_ptr, DataLayout::R_SEARCH_TREE_LEVEL_STARTS); + util::vector_view rtree_level_starts( + rtree_levelstarts_ptr, + layout.GetBlockEntries(storage::DataLayout::R_SEARCH_TREE_LEVEL_STARTS)); - tree_node_file.Skip(1); - const auto rtree_levelsizes_ptr = - layout.GetBlockPtr(memory_ptr, DataLayout::R_SEARCH_TREE_LEVELS); + // we need this purely for the interface + util::vector_view empty_coords; - tree_node_file.ReadInto(rtree_levelsizes_ptr, - layout.GetBlockEntries(DataLayout::R_SEARCH_TREE_LEVELS)); + 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); } // load profile properties diff --git a/unit_tests/util/static_rtree.cpp b/unit_tests/util/static_rtree.cpp index 4ba5c17cc..d7a808f83 100644 --- a/unit_tests/util/static_rtree.cpp +++ b/unit_tests/util/static_rtree.cpp @@ -8,6 +8,7 @@ #include "util/typedefs.hpp" #include "mocks/mock_datafacade.hpp" +#include "../common/temporary_file.hpp" #include #include @@ -244,60 +245,53 @@ void sampling_verify_rtree(RTreeT &rtree, } } -template -void build_rtree(const std::string &prefix, - FixtureT *fixture, - std::string &leaves_path, - std::string &nodes_path) +template +auto make_rtree(const boost::filesystem::path &path, FixtureT &fixture) { - nodes_path = prefix + ".ramIndex"; - leaves_path = prefix + ".fileIndex"; - - RTreeT r(fixture->edges, nodes_path, leaves_path, fixture->coords); + return RTreeT(fixture.edges, fixture.coords, path); } template -void construction_test(const std::string &prefix, FixtureT *fixture) +void construction_test(const std::string &path, 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); + auto rtree = make_rtree(path, fixture); + LinearSearchNN lsnn(fixture.coords, fixture.edges); - simple_verify_rtree(rtree, fixture->coords, fixture->edges); - sampling_verify_rtree(rtree, lsnn, fixture->coords, 100); + 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; - construction_test("test_tiny", this); + construction_test("test_tiny", *this); } BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull) { - construction_test("test_1", this); + construction_test("test_1", *this); } BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull) { - construction_test("test_2", this); + construction_test("test_2", *this); } BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves) { - construction_test("test_3", this); + construction_test("test_3", *this); } BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch) { - construction_test("test_4", this); + construction_test("test_4", *this); } BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels) { - construction_test("test_5", this); + construction_test("test_5", *this); } // Bug: If you querry a point that lies between two BBs that have a gap, @@ -321,11 +315,8 @@ BOOST_AUTO_TEST_CASE(regression_test) }, {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); + TemporaryFile tmp; + auto rtree = make_rtree(tmp.path, fixture); LinearSearchNN lsnn(fixture.coords, fixture.edges); // query a node just right of the center of the gap @@ -352,10 +343,8 @@ BOOST_AUTO_TEST_CASE(radius_regression_test) }, {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); + TemporaryFile tmp; + auto rtree = make_rtree(tmp.path, fixture); TestDataFacade mockfacade; engine::GeospatialQuery query( rtree, fixture.coords, mockfacade); @@ -380,10 +369,8 @@ BOOST_AUTO_TEST_CASE(bearing_tests) }, {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); + TemporaryFile tmp; + auto rtree = make_rtree(tmp.path, fixture); TestDataFacade mockfacade; engine::GeospatialQuery query( rtree, fixture.coords, mockfacade); @@ -459,10 +446,8 @@ BOOST_AUTO_TEST_CASE(bbox_search_tests) }, {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); + TemporaryFile tmp; + auto rtree = make_rtree(tmp.path, fixture); TestDataFacade mockfacade; engine::GeospatialQuery query( rtree, fixture.coords, mockfacade);