diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c4832bdb..d029bbea0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ - Fixed an issue that would detect turning circles as sliproads - Fixed a bug where post-processing instructions (e.g. left + left -> uturn) could result in false pronunciations - Fixes a bug where a bearing range of zero would cause exhaustive graph traversals + - Infrastructure: + - Adds a feature to limit results in nearest service with a default of 100 in `osrm-routed` # 5.3.0 Changes from 5.3.0-rc.3 diff --git a/include/engine/engine_config.hpp b/include/engine/engine_config.hpp index eb627198c..e73b37482 100644 --- a/include/engine/engine_config.hpp +++ b/include/engine/engine_config.hpp @@ -51,6 +51,7 @@ namespace engine * - Route * - Table * - Match + * - Nearest * * In addition, shared memory can be used for datasets loaded with osrm-datastore. * @@ -65,6 +66,7 @@ struct EngineConfig final int max_locations_viaroute = -1; int max_locations_distance_table = -1; int max_locations_map_matching = -1; + int max_results_nearest = -1; bool use_shared_memory = true; }; } diff --git a/include/engine/plugins/nearest.hpp b/include/engine/plugins/nearest.hpp index 657aec928..f2e2551e2 100644 --- a/include/engine/plugins/nearest.hpp +++ b/include/engine/plugins/nearest.hpp @@ -15,9 +15,12 @@ namespace plugins class NearestPlugin final : public BasePlugin { public: - explicit NearestPlugin(datafacade::BaseDataFacade &facade); + explicit NearestPlugin(datafacade::BaseDataFacade &facade, const int max_results); Status HandleRequest(const api::NearestParameters ¶ms, util::json::Object &result); + + private: + const int max_results; }; } } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 22eb15066..7b621b853 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -146,7 +146,7 @@ Engine::Engine(EngineConfig &config) route_plugin = create(*query_data_facade, config.max_locations_viaroute); table_plugin = create(*query_data_facade, config.max_locations_distance_table); - nearest_plugin = create(*query_data_facade); + nearest_plugin = create(*query_data_facade, config.max_results_nearest); trip_plugin = create(*query_data_facade, config.max_locations_trip); match_plugin = create(*query_data_facade, config.max_locations_map_matching); tile_plugin = create(*query_data_facade); diff --git a/src/engine/engine_config.cpp b/src/engine/engine_config.cpp index e26a67eed..9d322486f 100644 --- a/src/engine/engine_config.cpp +++ b/src/engine/engine_config.cpp @@ -15,11 +15,15 @@ bool EngineConfig::IsValid() const storage_config.datasource_names_path.empty() && storage_config.datasource_indexes_path.empty() && storage_config.names_data_path.empty(); - const bool limits_valid = - (max_locations_distance_table == -1 || max_locations_distance_table > 2) && - (max_locations_map_matching == -1 || max_locations_map_matching > 2) && - (max_locations_trip == -1 || max_locations_trip > 2) && - (max_locations_viaroute == -1 || max_locations_viaroute > 2); + const auto unlimited_or_more_than = [](const int v, const int limit) { + return v == -1 || v > limit; + }; + + const bool limits_valid = unlimited_or_more_than(max_locations_distance_table, 2) && + unlimited_or_more_than(max_locations_map_matching, 2) && + unlimited_or_more_than(max_locations_trip, 2) && + unlimited_or_more_than(max_locations_viaroute, 2) && + unlimited_or_more_than(max_results_nearest, 0); return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid; } diff --git a/src/engine/plugins/nearest.cpp b/src/engine/plugins/nearest.cpp index 3e54d3393..c3f83b866 100644 --- a/src/engine/plugins/nearest.cpp +++ b/src/engine/plugins/nearest.cpp @@ -16,13 +16,24 @@ namespace engine namespace plugins { -NearestPlugin::NearestPlugin(datafacade::BaseDataFacade &facade) : BasePlugin{facade} {} +NearestPlugin::NearestPlugin(datafacade::BaseDataFacade &facade, const int max_results_) + : BasePlugin{facade}, max_results{max_results_} +{ +} Status NearestPlugin::HandleRequest(const api::NearestParameters ¶ms, util::json::Object &json_result) { BOOST_ASSERT(params.IsValid()); + if (params.number_of_results > max_results) + { + return Error("TooBig", + "Number of results " + std::to_string(params.number_of_results) + + " is higher than current maximum (" + std::to_string(max_results) + ")", + json_result); + } + if (!CheckAllCoordinates(params.coordinates)) return Error("InvalidOptions", "Coordinates are invalid", json_result); diff --git a/src/tools/routed.cpp b/src/tools/routed.cpp index fc439ee7c..d08730251 100644 --- a/src/tools/routed.cpp +++ b/src/tools/routed.cpp @@ -63,7 +63,8 @@ inline unsigned generateServerProgramOptions(const int argc, int &max_locations_trip, int &max_locations_viaroute, int &max_locations_distance_table, - int &max_locations_map_matching) + int &max_locations_map_matching, + int &max_results_nearest) { using boost::program_options::value; using boost::filesystem::path; @@ -100,7 +101,10 @@ inline unsigned generateServerProgramOptions(const int argc, "Max. locations supported in distance table query") // ("max-matching-size", value(&max_locations_map_matching)->default_value(100), - "Max. locations supported in map matching query"); + "Max. locations supported in map matching query") // + ("max-nearest-size", + value(&max_results_nearest)->default_value(100), + "Max. results supported in nearest query"); // hidden options, will be allowed on command line, but will not be shown to the user boost::program_options::options_description hidden_options("Hidden options"); @@ -189,7 +193,8 @@ int main(int argc, const char *argv[]) try config.max_locations_trip, config.max_locations_viaroute, config.max_locations_distance_table, - config.max_locations_map_matching); + config.max_locations_map_matching, + config.max_results_nearest); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { return EXIT_SUCCESS; diff --git a/unit_tests/library/limits.cpp b/unit_tests/library/limits.cpp index ad4b3fbe9..b8f721b8d 100644 --- a/unit_tests/library/limits.cpp +++ b/unit_tests/library/limits.cpp @@ -4,6 +4,7 @@ #include "args.hpp" #include "osrm/match_parameters.hpp" +#include "osrm/nearest_parameters.hpp" #include "osrm/route_parameters.hpp" #include "osrm/table_parameters.hpp" #include "osrm/trip_parameters.hpp" @@ -136,4 +137,33 @@ BOOST_AUTO_TEST_CASE(test_match_limits) BOOST_CHECK(code == "TooBig"); // per the New-Server API spec } +BOOST_AUTO_TEST_CASE(test_nearest_limits) +{ + const auto args = get_args(); + BOOST_REQUIRE_EQUAL(args.size(), 1); + + using namespace osrm; + + EngineConfig config; + config.storage_config = {args[0]}; + config.use_shared_memory = false; + config.max_results_nearest = 2; + + OSRM osrm{config}; + + NearestParameters params; + params.coordinates.emplace_back(util::FloatLongitude{}, util::FloatLatitude{}); + params.number_of_results = 10000; + + json::Object result; + + const auto rc = osrm.Nearest(params, result); + + BOOST_CHECK(rc == Status::Error); + + // Make sure we're not accidentally hitting a guard code path before + const auto code = result.values["code"].get().value; + BOOST_CHECK(code == "TooBig"); // per the New-Server API spec +} + BOOST_AUTO_TEST_SUITE_END()