void RequestHandler::HandleRequest(const http::request ¤t_request, http::reply ¤t_reply) { if (!service_handler) { current_reply = http::reply::stock_reply(http::reply::internal_server_error); util::Log(logWARNING) << "No service handler registered." << std::endl; return; } // parse command try { TIMER_START(request_duration); std::string request_string; util::URIDecode(current_request.uri, request_string); util::Log(logDEBUG) << "req: " << request_string; auto api_iterator = request_string.begin(); auto maybe_parsed_url = api::parseURL(api_iterator, request_string.end()); ServiceHandler::ResultT result; // check if the was an error with the request if (maybe_parsed_url && api_iterator == request_string.end()) { const engine::Status status = service_handler->RunQuery(*std::move(maybe_parsed_url), result); if (status != engine::Status::Ok) { // 4xx bad request return code current_reply.status = http::reply::bad_request; } else { BOOST_ASSERT(status == engine::Status::Ok); } } else { const auto position = std::distance(request_string.begin(), api_iterator); BOOST_ASSERT(position >= 0); const auto context_begin = request_string.begin() + ((position < 3) ? 0 : (position - 3UL)); BOOST_ASSERT(context_begin >= request_string.begin()); const auto context_end = request_string.begin() + std::min<std::size_t>(position + 3UL, request_string.size()); BOOST_ASSERT(context_end <= request_string.end()); std::string context(context_begin, context_end); current_reply.status = http::reply::bad_request; result = util::json::Object(); auto &json_result = result.get<util::json::Object>(); json_result.values["code"] = "InvalidUrl"; json_result.values["message"] = "URL string malformed close to position " + std::to_string(position) + ": \"" + context + "\""; } current_reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); current_reply.headers.emplace_back("Access-Control-Allow-Methods", "GET"); current_reply.headers.emplace_back("Access-Control-Allow-Headers", "X-Requested-With, Content-Type"); if (result.is<util::json::Object>()) { current_reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8"); current_reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\""); util::json::render(current_reply.content, result.get<util::json::Object>()); } else { BOOST_ASSERT(result.is<std::string>()); current_reply.content.resize(result.get<std::string>().size()); std::copy(result.get<std::string>().cbegin(), result.get<std::string>().cend(), current_reply.content.begin()); current_reply.headers.emplace_back("Content-Type", "application/x-protobuf"); } // set headers current_reply.headers.emplace_back("Content-Length", std::to_string(current_reply.content.size())); if (!std::getenv("DISABLE_ACCESS_LOGGING")) { // deactivated as GCC apparently does not implement that, not even in 4.9 // std::time_t t = std::time(nullptr); // util::Log() << std::put_time(std::localtime(&t), "%m-%d-%Y // %H:%M:%S") << // " " << current_request.endpoint.to_string() << " " << // current_request.referrer << ( 0 == current_request.referrer.length() ? "- " :" ") // << // current_request.agent << ( 0 == current_request.agent.length() ? "- " :" ") << // request; time_t ltime; struct tm *time_stamp; TIMER_STOP(request_duration); ltime = time(nullptr); time_stamp = localtime(<ime); // log timestamp util::Log() << (time_stamp->tm_mday < 10 ? "0" : "") << time_stamp->tm_mday << "-" << (time_stamp->tm_mon + 1 < 10 ? "0" : "") << (time_stamp->tm_mon + 1) << "-" << 1900 + time_stamp->tm_year << " " << (time_stamp->tm_hour < 10 ? "0" : "") << time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "") << time_stamp->tm_min << ":" << (time_stamp->tm_sec < 10 ? "0" : "") << time_stamp->tm_sec << " " << TIMER_MSEC(request_duration) << "ms " << current_request.endpoint.to_string() << " " << current_request.referrer << (0 == current_request.referrer.length() ? "- " : " ") << current_request.agent << (0 == current_request.agent.length() ? "- " : " ") << current_reply.status << " " // << request_string; } } catch (const std::exception &e) { current_reply = http::reply::stock_reply(http::reply::internal_server_error); util::Log(logWARNING) << "[server error] code: " << e.what() << ", uri: " << current_request.uri; } }
int main(int argc, char *argv[]) { LogPolicy::GetInstance().Unmute(); try { // enable logging if (argc < 3) { SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm> <osrm.restrictions>"; return -1; } SimpleLogger().Write() << "Using restrictions from file: " << argv[2]; std::ifstream restriction_ifstream(argv[2], std::ios::binary); const FingerPrint fingerprint_orig; FingerPrint fingerprint_loaded; restriction_ifstream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); // check fingerprint and warn if necessary if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig)) { SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. " "Reprocess to get rid of this warning."; } if (!restriction_ifstream.good()) { throw osrm::exception("Could not access <osrm-restrictions> files"); } uint32_t usable_restrictions = 0; restriction_ifstream.read((char *)&usable_restrictions, sizeof(uint32_t)); restriction_list.resize(usable_restrictions); // load restrictions if (usable_restrictions > 0) { restriction_ifstream.read((char *)&(restriction_list[0]), usable_restrictions * sizeof(TurnRestriction)); } restriction_ifstream.close(); std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary); if (!input_stream.is_open()) { throw osrm::exception("Cannot open osrm file"); } // load graph data std::vector<ImportEdge> edge_list; const NodeID number_of_nodes = readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list, traffic_lights_list, &coordinate_list, restriction_list); input_stream.close(); BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions, "size of restriction_list changed"); SimpleLogger().Write() << restriction_list.size() << " restrictions, " << bollard_node_list.size() << " bollard nodes, " << traffic_lights_list.size() << " traffic lights"; traffic_lights_list.clear(); traffic_lights_list.shrink_to_fit(); // Building an node-based graph DeallocatingVector<TarjanEdge> graph_edge_list; for (const NodeBasedEdge &input_edge : edge_list) { if (input_edge.source == input_edge.target) { continue; } if (input_edge.forward) { graph_edge_list.emplace_back(input_edge.source, input_edge.target, (std::max)((int)input_edge.weight, 1), input_edge.name_id); } if (input_edge.backward) { graph_edge_list.emplace_back(input_edge.target, input_edge.source, (std::max)((int)input_edge.weight, 1), input_edge.name_id); } } edge_list.clear(); edge_list.shrink_to_fit(); BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(), "input edge vector not properly deallocated"); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); auto graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, graph_edge_list); edge_list.clear(); edge_list.shrink_to_fit(); SimpleLogger().Write() << "Starting SCC graph traversal"; RestrictionMap restriction_map(restriction_list); auto tarjan = osrm::make_unique<TarjanSCC<TarjanDynamicGraph>>(graph, restriction_map, bollard_node_list); tarjan->run(); SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() << " many components"; SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() << " SCCs of size 1"; // output TIMER_START(SCC_RUN_SETUP); // remove files from previous run if exist DeleteFileIfExists("component.dbf"); DeleteFileIfExists("component.shx"); DeleteFileIfExists("component.shp"); Percent p(graph->GetNumberOfNodes()); OGRRegisterAll(); const char *pszDriverName = "ESRI Shapefile"; OGRSFDriver *poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName); if (nullptr == poDriver) { throw osrm::exception("ESRI Shapefile driver not available"); } OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr); if (nullptr == poDS) { throw osrm::exception("Creation of output file failed"); } OGRSpatialReference *poSRS = new OGRSpatialReference(); poSRS->importFromEPSG(4326); OGRLayer *poLayer = poDS->CreateLayer("component", poSRS, wkbLineString, nullptr); if (nullptr == poLayer) { throw osrm::exception("Layer creation failed."); } TIMER_STOP(SCC_RUN_SETUP); SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP)/1000. << "s"; uint64_t total_network_distance = 0; p.reinit(graph->GetNumberOfNodes()); TIMER_START(SCC_OUTPUT); for (const NodeID source : osrm::irange(0u, graph->GetNumberOfNodes())) { p.printIncrement(); for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { const TarjanDynamicGraph::NodeIterator target = graph->GetTarget(current_edge); if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) { total_network_distance += 100 * FixedPointCoordinate::ApproximateEuclideanDistance( coordinate_list[source].lat, coordinate_list[source].lon, coordinate_list[target].lat, coordinate_list[target].lon); BOOST_ASSERT(current_edge != SPECIAL_EDGEID); BOOST_ASSERT(source != SPECIAL_NODEID); BOOST_ASSERT(target != SPECIAL_NODEID); const unsigned size_of_containing_component = std::min(tarjan->get_component_size(source), tarjan->get_component_size(target)); // edges that end on bollard nodes may actually be in two distinct components if (size_of_containing_component < 1000) { OGRLineString lineString; lineString.addPoint(coordinate_list[source].lon / COORDINATE_PRECISION, coordinate_list[source].lat / COORDINATE_PRECISION); lineString.addPoint(coordinate_list[target].lon / COORDINATE_PRECISION, coordinate_list[target].lat / COORDINATE_PRECISION); OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn()); poFeature->SetGeometry(&lineString); if (OGRERR_NONE != poLayer->CreateFeature(poFeature)) { throw osrm::exception("Failed to create feature in shapefile."); } OGRFeature::DestroyFeature(poFeature); } } } } OGRSpatialReference::DestroySpatialReference(poSRS); OGRDataSource::DestroyDataSource(poDS); TIMER_STOP(SCC_OUTPUT); SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT)/1000. << "s"; SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance / 100 / 1000. << " km"; SimpleLogger().Write() << "finished component analysis"; } catch (const std::exception &e) { SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); } return 0; }
void Benchmark(BenchStaticRTree &rtree, unsigned num_queries) { std::mt19937 mt_rand(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<FixedPointCoordinate> queries; for (unsigned i = 0; i < num_queries; i++) { queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand))); } { const unsigned num_results = 5; std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results << " phantom nodes" << "\n"; TIMER_START(query_phantom); std::vector<PhantomNode> phantom_node_vector; for (const auto &q : queries) { phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results); phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results); } TIMER_STOP(query_phantom); std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query." << "\n"; std::cout << "#### LocateClosestEndPointForCoordinate" << "\n"; } TIMER_START(query_endpoint); FixedPointCoordinate result; for (const auto &q : queries) { rtree.LocateClosestEndPointForCoordinate(q, result, 3); } TIMER_STOP(query_endpoint); std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query." << "\n"; std::cout << "#### FindPhantomNodeForCoordinate" << "\n"; TIMER_START(query_node); for (const auto &q : queries) { PhantomNode phantom; rtree.FindPhantomNodeForCoordinate(q, phantom, 3); } TIMER_STOP(query_node); std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_node) / ((double)num_queries) << " msec/query." << "\n"; { const unsigned num_results = 1; std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results << " phantom nodes" << "\n"; TIMER_START(query_phantom); std::vector<PhantomNode> phantom_node_vector; for (const auto &q : queries) { phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results); phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results); } TIMER_STOP(query_phantom); std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query." << "\n"; std::cout << "#### LocateClosestEndPointForCoordinate" << "\n"; } }
void Run() { TIMER_START(SCC_RUN); const NodeID max_node_id = m_graph->GetNumberOfNodes(); // The following is a hack to distinguish between stuff that happens // before the recursive call and stuff that happens after std::stack<TarjanStackFrame> recursion_stack; // true = stuff before, false = stuff after call std::stack<NodeID> tarjan_stack; std::vector<TarjanNode> tarjan_node_list(max_node_id); unsigned component_index = 0, size_of_current_component = 0; unsigned index = 0; std::vector<bool> processing_node_before_recursion(max_node_id, true); for (const NodeID node : util::irange(0u, max_node_id)) { if (SPECIAL_NODEID == components_index[node]) { recursion_stack.emplace(TarjanStackFrame(node, node)); } while (!recursion_stack.empty()) { TarjanStackFrame currentFrame = recursion_stack.top(); const NodeID u = currentFrame.parent; const NodeID v = currentFrame.v; recursion_stack.pop(); const bool before_recursion = processing_node_before_recursion[v]; if (before_recursion && tarjan_node_list[v].index != UINT_MAX) { continue; } if (before_recursion) { // Mark frame to handle tail of recursion recursion_stack.emplace(currentFrame); processing_node_before_recursion[v] = false; // Mark essential information for SCC tarjan_node_list[v].index = index; tarjan_node_list[v].low_link = index; tarjan_stack.push(v); tarjan_node_list[v].on_stack = true; ++index; for (const auto current_edge : m_graph->GetAdjacentEdgeRange(v)) { const auto vprime = m_graph->GetTarget(current_edge); if (SPECIAL_NODEID == tarjan_node_list[vprime].index) { recursion_stack.emplace(TarjanStackFrame(vprime, v)); } else { if (tarjan_node_list[vprime].on_stack && tarjan_node_list[vprime].index < tarjan_node_list[v].low_link) { tarjan_node_list[v].low_link = tarjan_node_list[vprime].index; } } } } else { processing_node_before_recursion[v] = true; tarjan_node_list[u].low_link = std::min(tarjan_node_list[u].low_link, tarjan_node_list[v].low_link); // after recursion, lets do cycle checking // Check if we found a cycle. This is the bottom part of the recursion if (tarjan_node_list[v].low_link == tarjan_node_list[v].index) { NodeID vprime; do { vprime = tarjan_stack.top(); tarjan_stack.pop(); tarjan_node_list[vprime].on_stack = false; components_index[vprime] = component_index; ++size_of_current_component; } while (v != vprime); component_size_vector.emplace_back(size_of_current_component); if (size_of_current_component > 1000) { util::SimpleLogger().Write() << "large component [" << component_index << "]=" << size_of_current_component; } ++component_index; size_of_current_component = 0; } } } } TIMER_STOP(SCC_RUN); util::SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s"; size_one_counter = std::count_if(component_size_vector.begin(), component_size_vector.end(), [](unsigned value) { return 1 == value; }); }
int main(int argc, char *argv[]) { std::vector<osrm::extractor::QueryNode> coordinate_list; osrm::util::LogPolicy::GetInstance().Unmute(); // enable logging if (argc < 2) { osrm::util::Log(logWARNING) << "usage:\n" << argv[0] << " <osrm>"; return EXIT_FAILURE; } std::vector<osrm::tools::TarjanEdge> graph_edge_list; auto number_of_nodes = osrm::tools::loadGraph(std::string(argv[1]), coordinate_list, graph_edge_list); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); const auto graph = std::make_shared<osrm::tools::TarjanGraph>(number_of_nodes, graph_edge_list); graph_edge_list.clear(); graph_edge_list.shrink_to_fit(); osrm::util::Log() << "Starting SCC graph traversal"; auto tarjan = std::make_unique<osrm::extractor::TarjanSCC<osrm::tools::TarjanGraph>>(graph); tarjan->Run(); osrm::util::Log() << "identified: " << tarjan->GetNumberOfComponents() << " many components"; osrm::util::Log() << "identified " << tarjan->GetSizeOneCount() << " size 1 SCCs"; // output TIMER_START(SCC_RUN_SETUP); // remove files from previous run if exist osrm::tools::deleteFileIfExists("component.dbf"); osrm::tools::deleteFileIfExists("component.shx"); osrm::tools::deleteFileIfExists("component.shp"); OGRRegisterAll(); const char *psz_driver_name = "ESRI Shapefile"; auto *po_driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(psz_driver_name); if (nullptr == po_driver) { throw osrm::util::exception("ESRI Shapefile driver not available" + SOURCE_REF); } auto *po_datasource = po_driver->CreateDataSource("component.shp", nullptr); if (nullptr == po_datasource) { throw osrm::util::exception("Creation of output file failed" + SOURCE_REF); } auto *po_srs = new OGRSpatialReference(); po_srs->importFromEPSG(4326); auto *po_layer = po_datasource->CreateLayer("component", po_srs, wkbLineString, nullptr); if (nullptr == po_layer) { throw osrm::util::exception("Layer creation failed." + SOURCE_REF); } TIMER_STOP(SCC_RUN_SETUP); osrm::util::Log() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP) / 1000. << "s"; TIMER_START(SCC_OUTPUT); uint64_t total_network_length = 0; { osrm::util::UnbufferedLog log; log << "Constructing geometry "; osrm::util::Percent percentage(log, graph->GetNumberOfNodes()); for (const NodeID source : osrm::util::irange(0u, graph->GetNumberOfNodes())) { percentage.PrintIncrement(); for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { const auto target = graph->GetTarget(current_edge); if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source)) { total_network_length += 100 * osrm::util::coordinate_calculation::greatCircleDistance( coordinate_list[source], coordinate_list[target]); BOOST_ASSERT(current_edge != SPECIAL_EDGEID); BOOST_ASSERT(source != SPECIAL_NODEID); BOOST_ASSERT(target != SPECIAL_NODEID); const unsigned size_of_containing_component = std::min(tarjan->GetComponentSize(tarjan->GetComponentID(source)), tarjan->GetComponentSize(tarjan->GetComponentID(target))); // edges that end on bollard nodes may actually be in two distinct components if (size_of_containing_component < 1000) { OGRLineString line_string; line_string.addPoint(static_cast<double>(osrm::util::toFloating( coordinate_list[source].lon)), static_cast<double>(osrm::util::toFloating( coordinate_list[source].lat))); line_string.addPoint(static_cast<double>(osrm::util::toFloating( coordinate_list[target].lon)), static_cast<double>(osrm::util::toFloating( coordinate_list[target].lat))); OGRFeature *po_feature = OGRFeature::CreateFeature(po_layer->GetLayerDefn()); po_feature->SetGeometry(&line_string); if (OGRERR_NONE != po_layer->CreateFeature(po_feature)) { throw osrm::util::exception("Failed to create feature in shapefile." + SOURCE_REF); } OGRFeature::DestroyFeature(po_feature); } } } } } OGRSpatialReference::DestroySpatialReference(po_srs); OGRDataSource::DestroyDataSource(po_datasource); TIMER_STOP(SCC_OUTPUT); osrm::util::Log() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT) / 1000. << "s"; osrm::util::Log() << "total network distance: " << static_cast<uint64_t>(total_network_length / 100 / 1000.) << " km"; osrm::util::Log() << "finished component analysis"; return EXIT_SUCCESS; }