From e83891b4fc0a7fbf105c1ae1f5f6cafd32e74dd8 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Mon, 5 Mar 2012 19:08:10 +0100 Subject: [PATCH] API Breaking change. Location of nodes can be specified by a hint. --- Algorithms/ObjectToBase64.h | 23 ++++-- DataStructures/PhantomNodes.h | 3 + DataStructures/StaticGraph.h | 17 ++++ Descriptors/JSONDescriptor.h | 4 +- Plugins/RawRouteData.h | 2 +- Plugins/ViaRoutePlugin.h | 48 +++++------- Server/RequestHandler.h | 144 +++++++++++++++++----------------- 7 files changed, 132 insertions(+), 109 deletions(-) diff --git a/Algorithms/ObjectToBase64.h b/Algorithms/ObjectToBase64.h index 1b44411df..6c6e6784f 100644 --- a/Algorithms/ObjectToBase64.h +++ b/Algorithms/ObjectToBase64.h @@ -32,27 +32,36 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../Util/StringUtil.h" typedef - boost::archive::iterators::base64_from_binary< + boost::archive::iterators::base64_from_binary< boost::archive::iterators::transform_width > base64_t; typedef - boost::archive::iterators::transform_width< + boost::archive::iterators::transform_width< boost::archive::iterators::binary_from_base64, 8, 6 -> binary_t; + > binary_t; template static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) { assert(0 == encoded.length()); char * pointerToOriginalObject = (char *)&object; encoded = std::string(base64_t(pointerToOriginalObject), base64_t(pointerToOriginalObject+sizeof(ToEncodeT))); + //replace "+" with "-" and "/" with "_" + replaceAll(encoded, "+", "-"); + replaceAll(encoded, "/", "_"); } template -static void DecodeObjectFraBase64(ToEncodeT & object, const std::string& encoded) { - char * pointerToDecodedObject = (char *)&object; - std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1)); - std::copy ( dec.begin(), dec.end(), pointerToDecodedObject ); +static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) { + try { + string encoded(_encoded); + //replace "-" with "+" and "_" with "/" + replaceAll(encoded, "-", "+"); + replaceAll(encoded, "_", "/"); + char * pointerToDecodedObject = (char *)&object; + std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1)); + std::copy ( dec.begin(), dec.end(), pointerToDecodedObject ); + } catch(...) {} } #endif /* OBJECTTOBASE64_H_ */ diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h index 7e95a6f2c..6725cef87 100644 --- a/DataStructures/PhantomNodes.h +++ b/DataStructures/PhantomNodes.h @@ -42,6 +42,9 @@ struct PhantomNode { bool isBidirected() const { return weight2 != INT_MAX; } + bool isValid(const unsigned numberOfNodes) const { + return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX); + } }; struct PhantomNodes { diff --git a/DataStructures/StaticGraph.h b/DataStructures/StaticGraph.h index 62c8295c2..53a818530 100644 --- a/DataStructures/StaticGraph.h +++ b/DataStructures/StaticGraph.h @@ -91,6 +91,23 @@ public: _nodes.swap(nodes); _edges.swap(edges); + +#ifndef NDEBUG + Percent p(GetNumberOfNodes()); + for(unsigned u = 0; u < GetNumberOfNodes(); ++u) { + for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) { + unsigned v = GetTarget(eid); + EdgeData & data = GetEdgeData(eid); + if(data.shortcut) { + unsigned eid2 = FindEdgeInEitherDirection(u, data.via); + assert(eid2 != UINT_MAX); + eid2 = FindEdgeInEitherDirection(data.via, v); + assert(eid2 != UINT_MAX); + } + } + p.printIncrement(); + } +#endif } unsigned GetNumberOfNodes() const { diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index d874cf8c4..c1dc46b9f 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -167,11 +167,11 @@ public: } } reply.content += "],"; - reply.content += "\"route_data\": {"; + reply.content += "\"hint_data\": {"; reply.content += "\"checksum\":"; intToString(rawRoute.checkSum, tmp); reply.content += tmp; - reply.content += ", \"hint_array\": ["; + reply.content += ", \"locations\": ["; for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) { std::string hint; diff --git a/Plugins/RawRouteData.h b/Plugins/RawRouteData.h index 4a6f53a43..18e210297 100644 --- a/Plugins/RawRouteData.h +++ b/Plugins/RawRouteData.h @@ -25,7 +25,7 @@ struct RawRouteData { std::vector< _PathData > computedRouted; std::vector< PhantomNodes > segmentEndCoordinates; std::vector< _Coordinate > rawViaNodeCoordinates; - unsigned checkSum; + int checkSum; }; #endif /* RAWROUTEDATA_H_ */ diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 529c8acbf..9f7ad8ba1 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -31,6 +31,9 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "BasePlugin.h" #include "RouteParameters.h" + +#include "../Algorithms/ObjectToBase64.h" + #include "../Descriptors/BaseDescriptor.h" #include "../Descriptors/GPXDescriptor.h" #include "../Descriptors/JSONDescriptor.h" @@ -48,7 +51,7 @@ private: StaticGraph * graph; HashTable descriptorTable; std::string pluginDescriptorString; - + bool checksumOK; SearchEngine > * searchEngine; public: @@ -62,6 +65,7 @@ public: descriptorTable.Set("", 0); //default descriptor descriptorTable.Set("json", 0); descriptorTable.Set("gpx", 1); + checksumOK = false; } virtual ~ViaRoutePlugin() { @@ -72,35 +76,19 @@ public: std::string GetVersionString() const { return std::string("0.3 (DL)"); } void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { //check number of parameters - if(0 == routeParameters.options["start"].size() || 0 == routeParameters.options["dest"].size() ) { + if( 2 > routeParameters.viaPoints.size() ) { reply = http::Reply::stockReply(http::Reply::badRequest); return; } - //Get start and end Coordinate - std::string start = routeParameters.options["start"]; - std::string dest = routeParameters.options["dest"]; - - std::vector textCoord = split (start, ','); - - int lat1 = static_cast(100000.*atof(textCoord[0].c_str())); - int lon1 = static_cast(100000.*atof(textCoord[1].c_str())); - - textCoord = split (dest, ','); - - int lat2 = static_cast(100000.*atof(textCoord[0].c_str())); - int lon2 = static_cast(100000.*atof(textCoord[1].c_str())); - - _Coordinate startCoord(lat1, lon1); - _Coordinate targetCoord(lat2, lon2); RawRouteData rawRoute; rawRoute.checkSum = nodeHelpDesk->GetCheckSum(); - if(false == checkCoord(startCoord) || false == checkCoord(targetCoord)) { - reply = http::Reply::stockReply(http::Reply::badRequest); - return; + checksumOK = (atoi(routeParameters.options.Find("checksum").c_str()) == rawRoute.checkSum); + if(!checksumOK) { + INFO(atoi(routeParameters.options.Find("checksum").c_str()) << "!=" << rawRoute.checkSum); + INFO("mismatching checksum"); } - rawRoute.rawViaNodeCoordinates.push_back(startCoord); - + std::vector textCoord; for(unsigned i = 0; i < routeParameters.viaPoints.size(); ++i) { textCoord = split (routeParameters.viaPoints[i], ','); if(textCoord.size() != 2) { @@ -109,7 +97,6 @@ public: } int vialat = static_cast(100000.*atof(textCoord[0].c_str())); int vialon = static_cast(100000.*atof(textCoord[1].c_str())); -// INFO("[debug] via" << i << ": " << vialat << "," << vialon); _Coordinate viaCoord(vialat, vialon); if(false == checkCoord(viaCoord)) { reply = http::Reply::stockReply(http::Reply::badRequest); @@ -117,11 +104,18 @@ public: } rawRoute.rawViaNodeCoordinates.push_back(viaCoord); } - rawRoute.rawViaNodeCoordinates.push_back(targetCoord); - vector phantomNodeVector(rawRoute.rawViaNodeCoordinates.size()); + std::vector phantomNodeVector(rawRoute.rawViaNodeCoordinates.size()); for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) { + if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) { + INFO("Decoding hint: " << routeParameters.hints[i] << " for location index " << i); + DecodeObjectFromBase64(phantomNodeVector[i], routeParameters.hints[i]); + if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) { + INFO("Decoded hint " << i << " successfully"); + continue; + } + } + INFO("Brute force lookup of coordinate " << i); searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i]); -// INFO("found coord [" << i << "|" << rawRoute.rawViaNodeCoordinates.size()); } unsigned distance = 0; //single route or via point routing diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h index 3e76be4b4..6f8ee368f 100644 --- a/Server/RequestHandler.h +++ b/Server/RequestHandler.h @@ -38,88 +38,88 @@ namespace http { class RequestHandler : private boost::noncopyable { public: - explicit RequestHandler() : _pluginCount(0) { } + explicit RequestHandler() : _pluginCount(0) { } - ~RequestHandler() { + ~RequestHandler() { - for(unsigned i = 0; i < _pluginVector.size(); i++) { - BasePlugin * tempPointer = _pluginVector[i]; - DELETE( tempPointer ); - } - } + for(unsigned i = 0; i < _pluginVector.size(); i++) { + BasePlugin * tempPointer = _pluginVector[i]; + DELETE( tempPointer ); + } + } - void handle_request(const Request& req, Reply& rep){ - //parse command + void handle_request(const Request& req, Reply& rep){ + //parse command std::string request(req.uri); -// time_t ltime; -// struct tm *Tm; -// -// ltime=time(NULL); -// Tm=localtime(<ime); -// -// INFO( Tm->tm_mday << "-" << (Tm->tm_mon < 10 ? "0" : "" ) << Tm->tm_mon << "-" << 1900+Tm->tm_year << " " << Tm->tm_hour << ":" << Tm->tm_min << ":" << Tm->tm_sec << " " << -// req.endpoint.to_string() << " " << request ); - std::string command; - std::size_t firstAmpPosition = request.find_first_of("?"); - command = request.substr(1,firstAmpPosition-1); -// DEBUG("[debug] looking for handler for command: " << command); - try { - if(pluginMap.Holds(command)) { + time_t ltime; + struct tm *Tm; - RouteParameters routeParameters; - std::stringstream ss(( firstAmpPosition == std::string::npos ? "" : request.substr(firstAmpPosition+1) )); - std::string item; - while(std::getline(ss, item, '&')) { - size_t found = item.find('='); - if(found == std::string::npos) { - routeParameters.parameters.push_back(item); - } else { - std::string p = item.substr(0, found); - std::transform(p.begin(), p.end(), p.begin(), (int(*)(int)) std::tolower); - std::string o = item.substr(found+1); - if("jsonp" != p) - std::transform(o.begin(), o.end(), o.begin(), (int(*)(int)) std::tolower); - if("via" == p ) { - if(25 >= routeParameters.viaPoints.size()) { - routeParameters.viaPoints.push_back(o); - } - } else if("hint" == p) { - routeParameters.hints.resize(routeParameters.viaPoints.size(), 0); - routeParameters.hints.back() = o; - } else { - routeParameters.options.Set(p, o); - } - } - } + ltime=time(NULL); + Tm=localtime(<ime); -// std::cout << "[debug] found handler for '" << command << "' at version: " << pluginMap.Find(command)->GetVersionString() << std::endl; -// std::cout << "[debug] remaining parameters: " << parameters.size() << std::endl; - rep.status = Reply::ok; - _pluginVector[pluginMap.Find(command)]->HandleRequest(routeParameters, rep ); + INFO((Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" << (Tm->tm_mon < 10 ? "0" : "" ) << Tm->tm_mon << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " << + req.endpoint.to_string() << " " << request ); + std::string command; + std::size_t firstAmpPosition = request.find_first_of("?"); + command = request.substr(1,firstAmpPosition-1); + //DEBUG("[debug] looking for handler for command: " << command); + try { + if(pluginMap.Holds(command)) { -// std::cout << rep.content << std::endl; - } else { - rep = Reply::stockReply(Reply::badRequest); - } - return; - } catch(std::exception& e) { - rep = Reply::stockReply(Reply::internalServerError); - std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl; - return; - } - }; + RouteParameters routeParameters; + std::stringstream ss(( firstAmpPosition == std::string::npos ? "" : request.substr(firstAmpPosition+1) )); + std::string item; + while(std::getline(ss, item, '&')) { + size_t found = item.find('='); + if(found == std::string::npos) { + routeParameters.parameters.push_back(item); + } else { + std::string p = item.substr(0, found); + std::transform(p.begin(), p.end(), p.begin(), (int(*)(int)) std::tolower); + std::string o = item.substr(found+1); + if("jsonp" != p && "hint" != p) + std::transform(o.begin(), o.end(), o.begin(), (int(*)(int)) std::tolower); + if("loc" == p) { + if(25 >= routeParameters.viaPoints.size()) { + routeParameters.viaPoints.push_back(o); + } + } else if("hint" == p) { + routeParameters.hints.resize(routeParameters.viaPoints.size()); + if(routeParameters.viaPoints.size()) + routeParameters.hints.back() = o; + } else { + routeParameters.options.Set(p, o); + } + } + } + // std::cout << "[debug] found handler for '" << command << "' at version: " << pluginMap.Find(command)->GetVersionString() << std::endl; + // std::cout << "[debug] remaining parameters: " << parameters.size() << std::endl; + rep.status = Reply::ok; + _pluginVector[pluginMap.Find(command)]->HandleRequest(routeParameters, rep ); - void RegisterPlugin(BasePlugin * plugin) { - std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl; - pluginMap.Add(plugin->GetDescriptor(), _pluginCount); - _pluginVector.push_back(plugin); - _pluginCount++; - } + // std::cout << rep.content << std::endl; + } else { + rep = Reply::stockReply(Reply::badRequest); + } + return; + } catch(std::exception& e) { + rep = Reply::stockReply(Reply::internalServerError); + std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl; + return; + } + }; + + void RegisterPlugin(BasePlugin * plugin) { + std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl; + pluginMap.Add(plugin->GetDescriptor(), _pluginCount); + _pluginVector.push_back(plugin); + _pluginCount++; + } private: - HashTable pluginMap; - std::vector _pluginVector; - unsigned _pluginCount; + HashTable pluginMap; + std::vector _pluginVector; + unsigned _pluginCount; }; } // namespace http