diff --git a/AUTHORS.TXT b/AUTHORS.TXT index 97bcf54e2..5a9fd9565 100644 --- a/AUTHORS.TXT +++ b/AUTHORS.TXT @@ -2,6 +2,4 @@ The following people contributed code to the Open Source Routing Machine: Christian Vetter Dennis Luxen - -Note: -http server ripped from Boost http example 3 \ No newline at end of file +Ruslan Krenzler \ No newline at end of file diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index cf1b0c02d..2d1a08398 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -301,7 +301,7 @@ public: _LogData log; Percent p (numberOfNodes); - int maxThreads = omp_get_max_threads(); + unsigned maxThreads = omp_get_max_threads(); std::vector < _ThreadData* > threadData; for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) { threadData.push_back( new _ThreadData( numberOfNodes ) ); diff --git a/DataStructures/BinaryHeap.h b/DataStructures/BinaryHeap.h new file mode 100644 index 000000000..fc8bbe6b6 --- /dev/null +++ b/DataStructures/BinaryHeap.h @@ -0,0 +1,274 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef BINARYHEAP_H_INCLUDED +#define BINARYHEAP_H_INCLUDED + +//Not compatible with non contiguous node ids + +#include +#include +#include +#include +#include +#include + +template< typename NodeID, typename Key > +class ArrayStorage { +public: + + ArrayStorage( size_t size ) + : positions( new Key[size] ) {} + + ~ArrayStorage() { + delete[] positions; + } + + Key &operator[]( NodeID node ) { + return positions[node]; + } + + void Clear() {} + +private: + Key* positions; +}; + +template< typename NodeID, typename Key > +class MapStorage { +public: + + MapStorage( size_t size = 0 ) {} + + Key &operator[]( NodeID node ) { + return nodes[node]; + } + + void Clear() { + nodes.clear(); + } + +private: + std::map< NodeID, Key > nodes; + +}; + +template< typename NodeID, typename Key > +class DenseStorage { +public: + + DenseStorage( size_t size = 0 ) { nodes.set_empty_key(UINT_MAX); } + + Key &operator[]( NodeID node ) { + return nodes[node]; + } + + void Clear() { + nodes.clear(); + } + +private: + google::dense_hash_map< NodeID, Key > nodes; +}; + +template< typename NodeID, typename Key > +class SparseStorage { +public: + + SparseStorage( size_t size = 0 ) { } + + Key &operator[]( NodeID node ) { + return nodes[node]; + } + + void Clear() { + nodes.clear(); + } + +private: + google::sparse_hash_map< NodeID, Key > nodes; +}; + + +template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage< NodeID, Key > > +class BinaryHeap { +private: + BinaryHeap( const BinaryHeap& right ); + void operator=( const BinaryHeap& right ); +public: + typedef Weight WeightType; + typedef Data DataType; + + BinaryHeap( size_t maxID ) + : nodeIndex( maxID ) { + Clear(); + } + + void Clear() { + heap.resize( 1 ); + insertedNodes.clear(); + heap[0].weight = 0; + nodeIndex.Clear(); + } + + Key Size() const { + return ( Key )( heap.size() - 1 ); + } + + void Insert( NodeID node, Weight weight, const Data &data ) { + HeapElement element; + element.index = ( NodeID ) insertedNodes.size(); + element.weight = weight; + const Key key = ( Key ) heap.size(); + heap.push_back( element ); + insertedNodes.push_back( HeapNode( node, key, weight, data ) ); + nodeIndex[node] = element.index; + Upheap( key ); + CheckHeap(); + } + + Data& GetData( NodeID node ) { + const Key index = nodeIndex[node]; + return insertedNodes[index].data; + } + + Weight& GetKey( NodeID node ) { + const Key index = nodeIndex[node]; + return insertedNodes[index].weight; + } + + bool WasRemoved( NodeID node ) { + assert( WasInserted( node ) ); + const Key index = nodeIndex[node]; + return insertedNodes[index].key == 0; + } + + bool WasInserted( NodeID node ) { + const Key index = nodeIndex[node]; + if ( index >= ( Key ) insertedNodes.size() ) + return false; + return insertedNodes[index].node == node; + } + + NodeID Min() const { + assert( heap.size() > 1 ); + return insertedNodes[heap[1].index].node; + } + + NodeID DeleteMin() { + assert( heap.size() > 1 ); + const Key removedIndex = heap[1].index; + heap[1] = heap[heap.size()-1]; + heap.pop_back(); + if ( heap.size() > 1 ) + Downheap( 1 ); + insertedNodes[removedIndex].key = 0; + CheckHeap(); + return insertedNodes[removedIndex].node; + } + + void DeleteAll() { + for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i ) + insertedNodes[i->index].key = 0; + heap.resize( 1 ); + heap[0].weight = 0; + } + + void DecreaseKey( NodeID node, Weight weight ) { + const Key index = nodeIndex[node]; + Key key = insertedNodes[index].key; + assert ( key != 0 ); + + insertedNodes[index].weight = weight; + heap[key].weight = weight; + Upheap( key ); + CheckHeap(); + } + +private: + class HeapNode { + public: + HeapNode() { + } + HeapNode( NodeID n, Key k, Weight w, Data d ) + : node( n ), key( k ), weight( w ), data( d ) { + } + + NodeID node; + Key key; + Weight weight; + Data data; + }; + struct HeapElement { + Key index; + Weight weight; + }; + + std::vector< HeapNode > insertedNodes; + std::vector< HeapElement > heap; + IndexStorage nodeIndex; + + void Downheap( Key key ) { + const Key droppingIndex = heap[key].index; + const Weight weight = heap[key].weight; + Key nextKey = key << 1; + while ( nextKey < ( Key ) heap.size() ) { + const Key nextKeyOther = nextKey + 1; + if ( ( nextKeyOther < ( Key ) heap.size() ) ) + if ( heap[nextKey].weight > heap[nextKeyOther].weight ) + nextKey = nextKeyOther; + + if ( weight <= heap[nextKey].weight ) + break; + + heap[key] = heap[nextKey]; + insertedNodes[heap[key].index].key = key; + key = nextKey; + nextKey <<= 1; + } + heap[key].index = droppingIndex; + heap[key].weight = weight; + insertedNodes[droppingIndex].key = key; + } + + void Upheap( Key key ) { + const Key risingIndex = heap[key].index; + const Weight weight = heap[key].weight; + Key nextKey = key >> 1; + while ( heap[nextKey].weight > weight ) { + assert( nextKey != 0 ); + heap[key] = heap[nextKey]; + insertedNodes[heap[key].index].key = key; + key = nextKey; + nextKey >>= 1; + } + heap[key].index = risingIndex; + heap[key].weight = weight; + insertedNodes[risingIndex].key = key; + } + + void CheckHeap() { + /*for ( Key i = 2; i < heap.size(); ++i ) { + assert( heap[i].weight >= heap[i >> 1].weight ); + }*/ + } +}; + +#endif //#ifndef BINARYHEAP_H_INCLUDED diff --git a/DataStructures/HashTable.h b/DataStructures/HashTable.h index 0599fea2f..9d58e04d0 100644 --- a/DataStructures/HashTable.h +++ b/DataStructures/HashTable.h @@ -37,9 +37,23 @@ public: void Add(const keyT& key, const valueT& value){ table[key] = value; } + void Set(const keyT& key, const valueT& value){ + table[key] = value; + } valueT Find(const keyT& key) { + if(table.find(key) == table.end()) + return valueT(); return table.find(key)->second; } + + bool Holds(const keyT& key) { + if(table.find(key) == table.end()) + return false; + return true; + } + void EraseAll() { + table.clear(); + } private: MyHashTable table; }; diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 84759c47d..a0f9d8fa0 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -60,8 +60,7 @@ static unsigned getFileIndexForLatLon(const int lt, const int ln) return fileIndex; } -static unsigned getRAMIndexFromFileIndex(const int fileIndex) -{ +static unsigned getRAMIndexFromFileIndex(const int fileIndex) { unsigned fileLine = fileIndex / 32768; fileLine = fileLine / 32; fileLine = fileLine * 1024; @@ -158,22 +157,17 @@ class NNGrid { ifstream stream; }; - struct ThreadLookupTable{ - HashTable table; - }; + typedef HashTable ThreadLookupTable; public: ThreadLookupTable threadLookup; - NNGrid() { ramIndexTable.resize((1024*1024), UINT_MAX); if( WriteAccess) { entries = new stxxl::vector(); }} - NNGrid(const char* rif, const char* iif) { + NNGrid(const char* rif, const char* iif, unsigned numberOfThreads = omp_get_num_procs()) { ramIndexTable.resize((1024*1024), UINT_MAX); // indexInFile.open(iif, std::ios::in | std::ios::binary); ramInFile.open(rif, std::ios::in | std::ios::binary); - cout << "opening grid file for " << omp_get_num_procs() << " threads" << endl; - for(int i = 0; i< omp_get_num_procs(); i++) { indexFileStreams.push_back(new _ThreadData(iif)); } @@ -183,19 +177,17 @@ public: if(ramInFile.is_open()) ramInFile.close(); // if(indexInFile.is_open()) indexInFile.close(); - if (WriteAccess) - { + if (WriteAccess) { delete entries; } -#pragma omp parallel for for(int i = 0; i< indexFileStreams.size(); i++) { delete indexFileStreams[i]; } + threadLookup.EraseAll(); } - void OpenIndexFiles() - { + void OpenIndexFiles() { assert(ramInFile.is_open()); // assert(indexInFile.is_open()); @@ -513,7 +505,7 @@ private: void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_Edge>& result) { // cout << "thread: " << boost::this_thread::get_id() << ", hash: " << boost_thread_id_hash(boost::this_thread::get_id()) << ", id: " << threadLookup.table.Find(boost_thread_id_hash(boost::this_thread::get_id())) << endl; - unsigned threadID = threadLookup.table.Find(boost_thread_id_hash(boost::this_thread::get_id())); + unsigned threadID = threadLookup.Find(boost_thread_id_hash(boost::this_thread::get_id())); unsigned ramIndex = getRAMIndexFromFileIndex(fileIndex); unsigned startIndexInFile = ramIndexTable[ramIndex]; // ifstream indexInFile( indexFileStreams[threadID]->stream ); diff --git a/DataStructures/NodeInformationHelpDesk.h b/DataStructures/NodeInformationHelpDesk.h index d7fd46da9..4b082c4e0 100644 --- a/DataStructures/NodeInformationHelpDesk.h +++ b/DataStructures/NodeInformationHelpDesk.h @@ -33,19 +33,24 @@ typedef NNGrid::NNGrid ReadOnlyGrid; class NodeInformationHelpDesk{ public: - NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput) { numberOfNodes = 0; int2ExtNodeMap = new vector<_Coordinate>(); g = new ReadOnlyGrid(ramIndexInput,fileIndexInput); } - ~NodeInformationHelpDesk() { delete int2ExtNodeMap; delete g; } - void initNNGrid(ifstream& in) - { - while(!in.eof()) - { - NodeInfo b; - in.read((char *)&b, sizeof(b)); - int2ExtNodeMap->push_back(_Coordinate(b.lat, b.lon)); - numberOfNodes++; - } - in.close(); - g->OpenIndexFiles(); + NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput) { + readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput); + int2ExtNodeMap = new vector<_Coordinate>(); + numberOfNodes = 0; + } + ~NodeInformationHelpDesk() { + delete int2ExtNodeMap; + delete readOnlyGrid; + } + void initNNGrid(ifstream& in) { + while(!in.eof()) { + NodeInfo b; + in.read((char *)&b, sizeof(b)); + int2ExtNodeMap->push_back(_Coordinate(b.lat, b.lon)); + numberOfNodes++; + } + in.close(); + readOnlyGrid->OpenIndexFiles(); } inline int getLatitudeOfNode(const NodeID node) const { return int2ExtNodeMap->at(node).lat; } @@ -53,21 +58,22 @@ public: inline int getLongitudeOfNode(const NodeID node) const { return int2ExtNodeMap->at(node).lon; } NodeID getNumberOfNodes() const { return numberOfNodes; } + NodeID getNumberOfNodes2() const { return int2ExtNodeMap->size(); } inline void findNearestNodeCoordForLatLon(const _Coordinate coord, _Coordinate& result) { - result = g->FindNearestPointOnEdge(coord); + result = readOnlyGrid->FindNearestPointOnEdge(coord); } inline bool FindRoutingStarts(const _Coordinate start, const _Coordinate target, PhantomNodes * phantomNodes) { - g->FindRoutingStarts(start, target, phantomNodes); + readOnlyGrid->FindRoutingStarts(start, target, phantomNodes); } inline void RegisterThread(const unsigned k, const unsigned v) { - g->threadLookup.table.Add(k, v); + readOnlyGrid->threadLookup.Add(k, v); } private: vector<_Coordinate> * int2ExtNodeMap; - ReadOnlyGrid * g; + ReadOnlyGrid * readOnlyGrid; unsigned numberOfNodes; }; diff --git a/Docs/KnownBugs.txt b/Docs/KnownBugs.txt new file mode 100644 index 000000000..35afbf188 --- /dev/null +++ b/Docs/KnownBugs.txt @@ -0,0 +1,5 @@ +- extractorLargeNetwork finishes with: + terminate called after throwing an instance of 'stxxl::resource_error' + what(): Error in function void stxxl::mutex::lock() pthread_mutex_lock(&_mutex) Invalid argument + + This ist a known, albeit odd behavior that is caused by a bug in stxxl. It can be ignored \ No newline at end of file diff --git a/HttpServer/connection.h b/HttpServer/connection.h deleted file mode 100644 index e5c5c294c..000000000 --- a/HttpServer/connection.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, others 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. -*/ - -#ifndef HTTP_SERVER3_CONNECTION_HPP -#define HTTP_CONNECTION_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include "reply.h" -#include "request.h" -#include "request_handler.h" -#include "request_parser.h" - -namespace http { - - -/// Represents a single connection from a client. -template -class connection -: public boost::enable_shared_from_this >, -private boost::noncopyable -{ -public: - /// Construct a connection with the given io_service. - explicit connection(boost::asio::io_service& io_service, - request_handler& handler) - : strand_(io_service), - socket_(io_service), - request_handler_(handler) - { - } - - /// Get the socket associated with the connection. - boost::asio::ip::tcp::socket& socket() - { - return socket_; - } - - /// Start the first asynchronous operation for the connection. - void start() - { - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, this->shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } - -private: - /// Handle completion of a read operation. - void handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) - { - if (!e) - { - boost::tribool result; - boost::tie(result, boost::tuples::ignore) = request_parser_.parse( - request_, buffer_.data(), buffer_.data() + bytes_transferred); - - if (result) - { - request_handler_.handle_request(request_, reply_); - boost::asio::async_write(socket_, reply_.to_buffers(), - strand_.wrap( - boost::bind(&connection::handle_write, this->shared_from_this(), - boost::asio::placeholders::error))); - } - else if (!result) - { - reply_ = reply::stock_reply(reply::bad_request); - boost::asio::async_write(socket_, reply_.to_buffers(), - strand_.wrap( - boost::bind(&connection::handle_write, this->shared_from_this(), - boost::asio::placeholders::error))); - } - else - { - socket_.async_read_some(boost::asio::buffer(buffer_), - strand_.wrap( - boost::bind(&connection::handle_read, this->shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } - } - } - - /// Handle completion of a write operation. - void handle_write(const boost::system::error_code& e) - { - if (!e) - { - // Initiate graceful connection closure. - boost::system::error_code ignored_ec; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec); - } - - // No new asynchronous operations are started. This means that all shared_ptr - // references to the connection object will disappear and the object will be - // destroyed automatically after this handler returns. The connection class's - // destructor closes the socket. - } - - /// Strand to ensure the connection's handlers are not called concurrently. - boost::asio::io_service::strand strand_; - - /// Socket for the connection. - boost::asio::ip::tcp::socket socket_; - - /// The handler used to process the incoming request. - request_handler& request_handler_; - - /// Buffer for incoming data. - boost::array buffer_; - - /// The incoming request. - Request request_; - - /// The parser for the incoming request. - request_parser request_parser_; - - /// The reply to be sent back to the client. - reply reply_; - -}; - -} // namespace http - -#endif /* CONNECTION_HPP_ */ diff --git a/HttpServer/reply.h b/HttpServer/reply.h deleted file mode 100644 index 13c3f9469..000000000 --- a/HttpServer/reply.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ - - -#ifndef HTTP_SERVER3_REPLY_HPP -#define HTTP_SERVER3_REPLY_HPP - -#include -#include -#include -#include - -#include "header.h" - -namespace http { - -/// A reply to be sent to a client. -struct reply -{ - reply() { content.reserve(1000000); } - /// The status of the reply. - enum status_type - { - ok = 200, - bad_request = 400, - internal_server_error = 500 - } status; - - std::vector
headers; - - /// The content to be sent in the reply. - std::string content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector to_buffers(); - - /// Get a stock reply. - static reply stock_reply(status_type status); -}; - -namespace status_strings { - -const std::string ok = - "HTTP/1.0 200 OK\r\n"; -const std::string bad_request = - "HTTP/1.0 400 Bad Request\r\n"; -const std::string internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; - -boost::asio::const_buffer to_buffer(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return boost::asio::buffer(ok); - case reply::bad_request: - return boost::asio::buffer(bad_request); - case reply::internal_server_error: - return boost::asio::buffer(internal_server_error); - default: - return boost::asio::buffer(bad_request); - } -} - -} // namespace status_strings - -namespace misc_strings { - -const char name_value_separator[] = { ':', ' ' }; -const char crlf[] = { '\r', '\n' }; - -} // namespace misc_strings - -std::vector reply::to_buffers() -{ - std::vector buffers; - buffers.push_back(status_strings::to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) - { - header& h = headers[i]; - buffers.push_back(boost::asio::buffer(h.name)); - buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator)); - buffers.push_back(boost::asio::buffer(h.value)); - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - } - buffers.push_back(boost::asio::buffer(misc_strings::crlf)); - buffers.push_back(boost::asio::buffer(content)); - return buffers; -} - -namespace stock_replies { - -const char ok[] = ""; -const char bad_request[] = - "" - "Bad Request" - "

400 Bad Request

" - ""; -const char internal_server_error[] = - "" - "Internal Server Error" - "

500 Internal Server Error

" - ""; - -std::string to_string(reply::status_type status) -{ - switch (status) - { - case reply::ok: - return ok; - case reply::bad_request: - return bad_request; - case reply::internal_server_error: - return internal_server_error; - default: - return internal_server_error; - } -} - -} // namespace stock_replies - -reply reply::stock_reply(reply::status_type status) -{ - reply rep; - rep.status = status; - rep.content = stock_replies::to_string(status); - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; -} - -} // namespace http - -#endif // HTTP_SERVER3_REPLY_HPP diff --git a/HttpServer/request_handler.h b/HttpServer/request_handler.h deleted file mode 100644 index 17ab64a41..000000000 --- a/HttpServer/request_handler.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ - -#ifndef HTTP_ROUTER_REQUEST_HANDLER_HPP -#define HTTP_ROUTER_REQUEST_HANDLER_HPP - -#include -#include -#include -#include -#include -#include - -#include "reply.h" -#include "request.h" - -#include "../typedefs.h" - -namespace http { - -struct reply; -struct Request; - -/// The common handler for all incoming requests. -template -class request_handler : private boost::noncopyable -{ -public: - explicit request_handler(SearchEngine * s) : sEngine(s){} - - /// Handle a request and produce a reply. - void handle_request(const Request& req, reply& rep){ - try { - std::string request(req.uri); - std::string command; - std::size_t first_amp_pos = request.find_first_of("&"); - command = request.substr(1,first_amp_pos-1); - if(command == "locate") - { - std::size_t last_amp_pos = request.find_last_of("&"); - int lat = static_cast(100000*atof(request.substr(first_amp_pos+1, request.length()-last_amp_pos-1).c_str())); - int lon = static_cast(100000*atof(request.substr(last_amp_pos+1).c_str())); - _Coordinate result; - sEngine->findNearestNodeForLatLon(_Coordinate(lat, lon), result); - - rep.status = reply::ok; - rep.content.append(""); - rep.content.append(""); - rep.content.append(""); - - std::stringstream out1; - out1 << setprecision(10); - out1 << "Nearest Place in map to " << lat/100000. << "," << lon/100000. << ""; - rep.content.append(out1.str()); - rep.content.append(""); - - std::stringstream out2; - out2 << setprecision(10); - out2 << "" << result.lon / 100000. << "," << result.lat / 100000. << ""; - rep.content.append(out2.str()); - rep.content.append(""); - rep.content.append(""); - rep.content.append(""); - - rep.headers.resize(3); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = boost::lexical_cast(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "application/vnd.google-earth.kml+xml"; - rep.headers[2].name = "Content-Disposition"; - rep.headers[2].value = "attachment; filename=\"placemark.kml\""; - return; - } - if(command == "route") - { - double timestamp = get_timestamp(); - //http://localhost:5000/route&45.1427&12.14144&54.8733&8.59438 - std::size_t second_amp_pos = request.find_first_of("&", first_amp_pos+1); - std::size_t third_amp_pos = request.find_first_of("&", second_amp_pos+1); - std::size_t fourth_amp_pos = request.find_last_of("&"); - - int lat1 = static_cast(100000*atof(request.substr(first_amp_pos+1, request.length()-second_amp_pos-1).c_str())); - int lon1 = static_cast(100000*atof(request.substr(second_amp_pos+1, request.length()-third_amp_pos-1).c_str())); - int lat2 = static_cast(100000*atof(request.substr(third_amp_pos+1, request.length()-fourth_amp_pos-1).c_str())); - int lon2 = static_cast(100000*atof(request.substr(fourth_amp_pos+1).c_str())); - - _Coordinate startCoord(lat1, lon1); - _Coordinate targetCoord(lat2, lon2); - - vector< _PathData > * path = new vector< _PathData >(); - PhantomNodes * phantomNodes = new PhantomNodes(); - sEngine->FindRoutingStarts(startCoord, targetCoord, phantomNodes); - unsigned int distance = sEngine->ComputeRoute(phantomNodes, path, startCoord, targetCoord); - rep.status = reply::ok; - - string tmp; - - rep.content += (""); - rep.content += (""); - rep.content += (""); - -/* if(distance != std::numeric_limits::max()) - computeDescription(tmp, path, phantomNodes); - cout << tmp << endl; -*/ -// rep.content += tmp; - rep.content += (""); - rep.content += ("OSM Routing Engine (c) Dennis Luxen and others "); - - rep.content += "Route from "; - convertLatLon(lat1, tmp); - rep.content += tmp; - rep.content += ","; - convertLatLon(lon1, tmp); - rep.content += tmp; - rep.content += " to "; - convertLatLon(lat2, tmp); - rep.content += tmp; - rep.content += ","; - convertLatLon(lon2, tmp); - rep.content += tmp; - rep.content += " "; - rep.content += (""); - rep.content += ("1"); - rep.content += ("1"); - rep.content += ("absolute"); - rep.content += (""); - - - if(distance != std::numeric_limits::max()) - { //A route has been found - convertLatLon(phantomNodes->startCoord.lon, tmp); - rep.content += tmp; - rep.content += (","); - doubleToString(phantomNodes->startCoord.lat/100000., tmp); - rep.content += tmp; - rep.content += (" "); - _Coordinate result; - for(vector< _PathData >::iterator it = path->begin(); it != path->end(); it++) - { - sEngine->getNodeInfo(it->node, result); - convertLatLon(result.lon, tmp); - rep.content += tmp; - rep.content += (","); - convertLatLon(result.lat, tmp); - rep.content += tmp; - rep.content += (" "); - } - - convertLatLon(phantomNodes->targetCoord.lon, tmp); - rep.content += tmp; - rep.content += (","); - convertLatLon(phantomNodes->targetCoord.lat, tmp); - rep.content += tmp; - } - - rep.content += (""); - rep.content += (""); - rep.content += (""); - rep.content += (""); - rep.content += (""); - - rep.headers.resize(3); - rep.headers[0].name = "Content-Length"; - intToString(rep.content.size(), tmp); - rep.headers[0].value = tmp; - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "application/vnd.google-earth.kml+xml"; - rep.headers[2].name = "Content-Disposition"; - rep.headers[2].value = "attachment; filename=\"route.kml\""; - - delete path; - delete phantomNodes; -// timestamp2 = get_timestamp(); - //cout << "description in " << timestamp2 - timestamp << "s" << endl; - return; - } - rep = reply::stock_reply(reply::bad_request); - return; - } catch(std::exception& e) - { - //TODO: log exception somewhere - rep = reply::stock_reply(reply::internal_server_error); - return; - } - }; - -private: - //SearchEngine object that is queried - SearchEngine * sEngine; - - /* used to be boosts lexical cast, but this was too slow */ - inline void doubleToString(const double value, std::string & output) - { - // The largest 32-bit integer is 4294967295, that is 10 chars - // On the safe side, add 1 for sign, and 1 for trailing zero - char buffer[12] ; - sprintf(buffer, "%f", value) ; - output = buffer ; - } - - inline void intToString(const int value, std::string & output) - { - // The largest 32-bit integer is 4294967295, that is 10 chars - // On the safe side, add 1 for sign, and 1 for trailing zero - char buffer[12] ; - sprintf(buffer, "%i", value) ; - output = buffer ; - } - - inline void convertLatLon(const int value, std::string & output) - { - char buffer[100]; - buffer[10] = 0; // Nullterminierung - char* string = printInt< 10, 5 >( buffer, value ); - output = string; - } - - // precision: position after decimal point - // length: maximum number of digits including comma and decimals - template< int length, int precision > - inline char* printInt( char* buffer, int value ) - { - bool minus = false; - if ( value < 0 ) { - minus = true; - value = -value; - } - buffer += length - 1; - for ( int i = 0; i < precision; i++ ) { - *buffer = '0' + ( value % 10 ); - value /= 10; - buffer--; - } - *buffer = '.'; - buffer--; - for ( int i = precision + 1; i < length; i++ ) { - *buffer = '0' + ( value % 10 ); - value /= 10; - if ( value == 0 ) break; - buffer--; - } - if ( minus ) { - buffer--; - *buffer = '-'; - } - return buffer; - } - - void computeDescription(string &tmp, vector< _PathData > * path, PhantomNodes * phantomNodes) - { - _Coordinate previous(phantomNodes->startCoord.lat, phantomNodes->startCoord.lon); - _Coordinate next, current, lastPlace; - stringstream numberString; - - double tempDist = 0; - NodeID nextID = UINT_MAX; - NodeID nameID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); - short type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); - lastPlace.lat = phantomNodes->startCoord.lat; - lastPlace.lon = phantomNodes->startCoord.lon; - short nextType = SHRT_MAX; - short prevType = SHRT_MAX; - tmp += "\n "; - for(vector< _PathData >::iterator it = path->begin(); it != path->end(); it++) - { - sEngine->getNodeInfo(it->node, current); - if(it==path->end()-1){ - next = _Coordinate(phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon); - nextID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); - nextType = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); - } else { - sEngine->getNodeInfo((it+1)->node, next); - nextID = sEngine->GetNameIDForOriginDestinationNodeID(it->node, (it+1)->node); - nextType = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(it->node, (it+1)->node); - } - if(nextID == nameID) { - tempDist += ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon); - } else { - if(type == 0 && prevType != 0) - tmp += "enter motorway and "; - if(type != 0 && prevType == 0 ) - tmp += "leave motorway and "; - - double angle = GetAngleBetweenTwoEdges(previous, current, next); -// if(it->turn) -// tmp += " turn! "; - tmp += "follow road "; - if(nameID != 0) - tmp += sEngine->GetNameForNameID(nameID); - tmp += " (type: "; - numberString << type; - tmp += numberString.str(); - numberString.str(""); - tmp += ", id: "; - numberString << nameID; - tmp += numberString.str(); - numberString.str(""); - tmp += ")\n drive for "; - numberString << ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon)+tempDist; - tmp += numberString.str(); - numberString.str(""); - tmp += "m "; - string lat; string lon; - convertLatLon(lastPlace.lon, lon); - convertLatLon(lastPlace.lat, lat); - lastPlace = current; - tmp += "\n "; - tmp += lon; - tmp += ","; - tmp += lat; - tmp += ""; - tmp += "\n\n"; - tmp += "\n ("; - numberString << angle; - tmp += numberString.str(); - numberString.str(""); - tmp +=") "; - if(angle > 160 && angle < 200) { - tmp += /* " (" << angle << ")*/"drive ahead, "; - } else if (angle > 290 && angle <= 360) { - tmp += /*" (" << angle << ")*/ "turn sharp left, "; - } else if (angle > 230 && angle <= 290) { - tmp += /*" (" << angle << ")*/ "turn left, "; - } else if (angle > 200 && angle <= 230) { - tmp += /*" (" << angle << ") */"bear left, "; - } else if (angle > 130 && angle <= 160) { - tmp += /*" (" << angle << ") */"bear right, "; - } else if (angle > 70 && angle <= 130) { - tmp += /*" (" << angle << ") */"turn right, "; - } else { - tmp += /*" (" << angle << ") */"turn sharp right, "; - } - tempDist = 0; - prevType = type; - } - nameID = nextID; - previous = current; - type = nextType; - } - nameID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); - type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); - tmp += "follow road "; - tmp += sEngine->GetNameForNameID(nameID); - tmp += " (type: "; - numberString << type; - tmp += numberString.str(); - numberString.str(""); - tmp += ", id: "; - numberString << nameID; - tmp += numberString.str(); - numberString.str(""); - tmp += ")\n drive for "; - numberString << ApproximateDistance(previous.lat, previous.lon, phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon) + tempDist; - tmp += numberString.str(); - numberString.str(""); - tmp += "m\n "; - string lat; string lon; - convertLatLon(lastPlace.lon, lon); - convertLatLon(lastPlace.lat, lat); - tmp += ""; - tmp += lon; - tmp += ","; - tmp += lat; - tmp += ""; - tmp += "\n"; - tmp += "\n you have reached your destination\n "; - tmp += "End of Route"; - convertLatLon(phantomNodes->targetCoord.lon, lon); - convertLatLon(phantomNodes->targetCoord.lat, lat); - tmp += "\n "; - tmp += lon; - tmp += ","; - tmp += lat; - tmp +="\n"; - tmp += ""; - } - -}; -} - -#endif // HTTP_ROUTER_REQUEST_HANDLER_HPP diff --git a/HttpServer/request_parser.h b/HttpServer/request_parser.h deleted file mode 100644 index eeadc3dc2..000000000 --- a/HttpServer/request_parser.h +++ /dev/null @@ -1,402 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ - - -#ifndef HTTP_REQUEST_PARSER_HPP -#define HTTP_REQUEST_PARSER_HPP - -#include -#include - -namespace http { - -struct Request; - -/// Parser for incoming requests. -class request_parser -{ -public: - /// Construct ready to parse the request method. - request_parser(); - - /// Reset to initial parser state. - void reset(); - - /// Parse some data. The tribool return value is true when a complete request - /// has been parsed, false if the data is invalid, indeterminate when more - /// data is required. The InputIterator return value indicates how much of the - /// input has been consumed. - template - boost::tuple parse(Request& req, - InputIterator begin, InputIterator end) - { - while (begin != end) - { - boost::tribool result = consume(req, *begin++); - if (result || !result) - return boost::make_tuple(result, begin); - } - boost::tribool result = boost::indeterminate; - return boost::make_tuple(result, begin); - } - -private: - /// Handle the next character of input. - boost::tribool consume(Request& req, char input); - - /// Check if a byte is an HTTP character. - static bool is_char(int c); - - /// Check if a byte is an HTTP control character. - static bool is_ctl(int c); - - /// Check if a byte is defined as an HTTP tspecial character. - static bool is_tspecial(int c); - - /// Check if a byte is a digit. - static bool is_digit(int c); - - /// The current state of the parser. - enum state - { - method_start, - method, - uri_start, - uri, - http_version_h, - http_version_t_1, - http_version_t_2, - http_version_p, - http_version_slash, - http_version_major_start, - http_version_major, - http_version_minor_start, - http_version_minor, - expecting_newline_1, - header_line_start, - header_lws, - header_name, - space_before_header_value, - header_value, - expecting_newline_2, - expecting_newline_3 - } state_; -}; - - -} // namespace http - -#include "request.h" - -namespace http { - -request_parser::request_parser() -: state_(method_start) -{ -} - -void request_parser::reset() -{ - state_ = method_start; -} - -boost::tribool request_parser::consume(Request& req, char input) -{ - switch (state_) - { - case method_start: - if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - state_ = method; - return boost::indeterminate; - } - case method: - if (input == ' ') - { - state_ = uri; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - return boost::indeterminate; - } - case uri_start: - if (is_ctl(input)) - { - return false; - } - else - { - state_ = uri; - req.uri.push_back(input); - return boost::indeterminate; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.uri.push_back(input); - return boost::indeterminate; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_slash: - if (input == '/') - { - state_ = http_version_major_start; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major_start: - if (is_digit(input)) - { - state_ = http_version_major; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return boost::indeterminate; - } - else if (is_digit(input)) - { - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor_start: - if (is_digit(input)) - { - state_ = http_version_minor; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return boost::indeterminate; - } - else if (is_digit(input)) - { - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - state_ = header_name; - return boost::indeterminate; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (input == ' ' || input == '\t') - { - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - state_ = header_value; - return boost::indeterminate; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - return boost::indeterminate; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return boost::indeterminate; - } - else - { - return false; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - return boost::indeterminate; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_3: - return (input == '\n'); - default: - return false; - } -} - -bool request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -bool request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -bool request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -bool request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -} // namespace http - -#endif // HTTP_SERVER3_REQUEST_PARSER_HPP diff --git a/HttpServer/server.h b/HttpServer/server.h deleted file mode 100644 index 75c25c6c2..000000000 --- a/HttpServer/server.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - open source routing machine - Copyright (C) Dennis Luxen, 2010 - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU AFFERO General Public License as published by -the Free Software Foundation; either version 3 of the License, or -any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -or see http://www.gnu.org/licenses/agpl.txt. - */ - -#ifndef HTTP_ROUTER_SERVER_HPP -#define HTTP_ROUTER_SERVER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../typedefs.h" - -#include "connection.h" -#include "request_handler.h" - -namespace http { - -/// The top-level class of the HTTP server. -template -class server: private boost::noncopyable -{ -public: - /// Construct the server to listen on the specified TCP address and port - explicit server(const std::string& address, const std::string& port, std::size_t thread_pool_size, SearchEngine * s) - : thread_pool_size_(thread_pool_size), - acceptor_(io_service_), - new_connection_(new connection(io_service_, request_handler_)), - request_handler_(s), - sEngine(s) - { - // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). - boost::asio::ip::tcp::resolver resolver(io_service_); - boost::asio::ip::tcp::resolver::query query(address, port); - boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); - - acceptor_.open(endpoint.protocol()); - acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); - acceptor_.bind(endpoint); - acceptor_.listen(); - acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); - } - - /// Run the server's io_service loop. - void run() - { - // Create a pool of threads to run all of the io_services. - std::vector > threads; - for (std::size_t i = 0; i < thread_pool_size_; ++i) - { - boost::shared_ptr thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_))); - sEngine->RegisterThread( boost_thread_id_hash( thread->get_id() ), threads.size()); - threads.push_back(thread); - } - - // Wait for all threads in the pool to exit. - for (std::size_t i = 0; i < threads.size(); ++i) - threads[i]->join(); - } - - /// Stop the server. - void stop() - { - io_service_.stop(); - } - -private: - typedef boost::shared_ptr > connection_ptr; - - /// Handle completion of an asynchronous accept operation. - void handle_accept(const boost::system::error_code& e) - { - if (!e) - { - new_connection_->start(); - new_connection_.reset(new connection(io_service_, request_handler_)); - acceptor_.async_accept(new_connection_->socket(), boost::bind(&server::handle_accept, this, boost::asio::placeholders::error)); - } - } - - /// The number of threads that will call io_service::run(). - std::size_t thread_pool_size_; - - /// The io_service used to perform asynchronous operations. - boost::asio::io_service io_service_; - - /// Acceptor used to listen for incoming connections. - boost::asio::ip::tcp::acceptor acceptor_; - - /// The next connection to be accepted. - connection_ptr new_connection_; - - /// The handler for all incoming requests. - request_handler request_handler_; - - /// The object to query the Routing Engine - SearchEngine * sEngine; - -}; - -} // namespace http - -#endif // HTTP_ROUTER_SERVER_HPP diff --git a/HttpServer/header.h b/Plugins/BasePlugin.h similarity index 60% rename from HttpServer/header.h rename to Plugins/BasePlugin.h index 7abc8e443..316b992ce 100644 --- a/HttpServer/header.h +++ b/Plugins/BasePlugin.h @@ -1,6 +1,6 @@ /* open source routing machine - Copyright (C) Dennis Luxen, others 2010 + Copyright (C) Dennis Luxen, 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU AFFERO General Public License as published by @@ -16,22 +16,24 @@ You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. -*/ + */ -#ifndef HTTP_HEADER_HPP -#define HTTP_HEADER_HPP +#ifndef BASEPLUGIN_H_ +#define BASEPLUGIN_H_ +#include #include +#include +#include "../Server/BasicDatastructures.h" -namespace http { - - -struct header -{ - std::string name; - std::string value; +class BasePlugin { +public: + BasePlugin() { } + //Maybe someone can explain the pure virtual destructor thing to me (dennis) + virtual ~BasePlugin() { } + virtual std::string GetDescriptor() = 0; + virtual std::string GetVersionString() = 0; + virtual void HandleRequest(std::vector parameters, http::Reply& reply) = 0; }; -} - -#endif +#endif /* BASEPLUGIN_H_ */ diff --git a/Plugins/HelloWorldPlugin.h b/Plugins/HelloWorldPlugin.h new file mode 100644 index 000000000..d9ca34cfd --- /dev/null +++ b/Plugins/HelloWorldPlugin.h @@ -0,0 +1,35 @@ +/* + * LocatePlugin.h + * + * Created on: 01.01.2011 + * Author: dennis + */ + +#ifndef HELLOWORLDPLUGIN_H_ +#define HELLOWORLDPLUGIN_H_ + +#include + +#include "BasePlugin.h" + +class HelloWorldPlugin : public BasePlugin { +public: + HelloWorldPlugin() {} + ~HelloWorldPlugin() { std::cout << GetDescriptor() << " destructor" << std::endl; } + std::string GetDescriptor() { return std::string("hello"); } + void HandleRequest(std::vector parameters, http::Reply& reply) { + std::cout << "[hello world]: runnning handler" << std::endl; + reply.status = http::Reply::ok; + reply.content.append("Hello World Demonstration Document

Hello, World!

"); + std::stringstream content; + content << "Number of parameters: " << parameters.size() << "
"; + for(int i = 0; i < parameters.size(); i++) { + content << parameters[i] << "
"; + } + reply.content.append(content.str()); + reply.content.append(""); + } + std::string GetVersionString() { return std::string("0.1a"); } +}; + +#endif /* HELLOWORLDPLUGIN_H_ */ diff --git a/Plugins/LocatePlugin.h b/Plugins/LocatePlugin.h new file mode 100644 index 000000000..bc1483bca --- /dev/null +++ b/Plugins/LocatePlugin.h @@ -0,0 +1,91 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef LOCATEPLUGIN_H_ +#define LOCATEPLUGIN_H_ + +#include + +#include "BasePlugin.h" + +#include "../DataStructures/NodeInformationHelpDesk.h" + +/* + * This Plugin locates the nearest point on a street in the road network for a given coordinate. + */ +class LocatePlugin : public BasePlugin { +public: + LocatePlugin(std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath) { + nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str()); + ifstream nodesInStream(nodesPath.c_str(), ios::binary); + nodeHelpDesk->initNNGrid(nodesInStream); + } + ~LocatePlugin() { + delete nodeHelpDesk; + } + std::string GetDescriptor() { return std::string("locate"); } + std::string GetVersionString() { return std::string("0.2a (DL)"); } + void HandleRequest(std::vector parameters, http::Reply& reply) { + //check number of parameters + if(parameters.size() != 2) { + reply = http::Reply::stockReply(http::Reply::badRequest); + return; + } + + int lat = static_cast(100000.*atof(parameters[0].c_str())); + int lon = static_cast(100000.*atof(parameters[1].c_str())); + //query to helpdesk + _Coordinate result; + nodeHelpDesk->findNearestNodeCoordForLatLon(_Coordinate(lat, lon), result); + + //Write to stream + reply.status = http::Reply::ok; + reply.content.append(""); + reply.content.append(""); + reply.content.append(""); + + std::stringstream out1; + out1 << setprecision(10); + out1 << "Nearest Place in map to " << lat/100000. << "," << lon/100000. << ""; + reply.content.append(out1.str()); + reply.content.append(""); + + std::stringstream out2; + out2 << setprecision(10); + out2 << "" << result.lon / 100000. << "," << result.lat / 100000. << ""; + reply.content.append(out2.str()); + reply.content.append(""); + reply.content.append(""); + reply.content.append(""); + + reply.headers.resize(3); + reply.headers[0].name = "Content-Length"; + reply.headers[0].value = boost::lexical_cast(reply.content.size()); + reply.headers[1].name = "Content-Type"; + reply.headers[1].value = "application/vnd.google-earth.kml+xml"; + reply.headers[2].name = "Content-Disposition"; + reply.headers[2].value = "attachment; filename=\"placemark.kml\""; + return; + } +private: + NodeInformationHelpDesk * nodeHelpDesk; +}; + +#endif /* LOCATEPLUGIN_H_ */ diff --git a/HttpServer/request.h b/Plugins/PluginMapFactory.h similarity index 64% rename from HttpServer/request.h rename to Plugins/PluginMapFactory.h index 4c185c899..9027b184b 100644 --- a/HttpServer/request.h +++ b/Plugins/PluginMapFactory.h @@ -1,6 +1,6 @@ /* open source routing machine - Copyright (C) Dennis Luxen, others 2010 + Copyright (C) Dennis Luxen, 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU AFFERO General Public License as published by @@ -18,21 +18,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ -#ifndef HTTP_REQUEST_HPP -#define HTTP_REQUEST_HPP +#ifndef PLUGINMAPFACTORY_H_ +#define PLUGINMAPFACTORY_H_ -#include -#include -#include "header.h" +//#include "../DataStructures/HashTable.h" +//#include "../Plugins/BasePlugin.h" +// +//struct PluginMapFactory { +// static HashTable * CreatePluginMap() { +// HashTable * map = new HashTable(); +// +// } +//}; -namespace http { - -/// A request received from a client. -struct Request -{ - std::string uri; -}; - -} - -#endif // HTTP_REQUEST_HPP +#endif /* PLUGINMAPFACTORY_H_ */ diff --git a/Plugins/RoutePlugin.h b/Plugins/RoutePlugin.h new file mode 100644 index 000000000..17a033537 --- /dev/null +++ b/Plugins/RoutePlugin.h @@ -0,0 +1,311 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef ROUTEPLUGIN_H_ +#define ROUTEPLUGIN_H_ + +#include +#include +#include +#include + +#include "BasePlugin.h" +#include "../DataStructures/StaticGraph.h" +#include "../DataStructures/SearchEngine.h" + +#include "../Util/GraphLoader.h" +#include "../Util/StrIngUtil.h" + +typedef ContractionCleanup::Edge::EdgeData EdgeData; +typedef StaticGraph::InputEdge GridEdge; + +class RoutePlugin : public BasePlugin { +public: + RoutePlugin(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string namesPath) { + //Init nearest neighbor data structure + nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str()); + ifstream nodesInStream(nodesPath.c_str(), ios::binary); + ifstream hsgrInStream(hsgrPath.c_str(), ios::binary); + nodeHelpDesk->initNNGrid(nodesInStream); + + //Deserialize road network graph + std::vector< GridEdge> * edgeList = new std::vector< GridEdge>(); + readHSGRFromStream(hsgrInStream, edgeList); + hsgrInStream.close(); + + graph = new StaticGraph(nodeHelpDesk->getNumberOfNodes()-1, *edgeList); + delete edgeList; + + //deserialize street name list + ifstream namesInStream(namesPath.c_str(), ios::binary); + unsigned size = 0; + namesInStream.read((char *)&size, sizeof(unsigned)); + names = new std::vector(); + + //init complete search engine + sEngine = new SearchEngine >(graph, nodeHelpDesk, names); + } + ~RoutePlugin() { + delete names; + delete sEngine; + delete graph; + delete nodeHelpDesk; + } + std::string GetDescriptor() { return std::string("route"); } + std::string GetVersionString() { return std::string("0.2a (DL)"); } + void HandleRequest(std::vector parameters, http::Reply& reply) { + //check number of parameters + if(parameters.size() != 4) { + reply = http::Reply::stockReply(http::Reply::badRequest); + return; + } + + int lat1 = static_cast(100000.*atof(parameters[0].c_str())); + int lon1 = static_cast(100000.*atof(parameters[1].c_str())); + int lat2 = static_cast(100000.*atof(parameters[2].c_str())); + int lon2 = static_cast(100000.*atof(parameters[3].c_str())); + + _Coordinate startCoord(lat1, lon1); + _Coordinate targetCoord(lat2, lon2); + + vector< _PathData > * path = new vector< _PathData >(); + PhantomNodes * phantomNodes = new PhantomNodes(); + sEngine->FindRoutingStarts(startCoord, targetCoord, phantomNodes); + unsigned int distance = sEngine->ComputeRoute(phantomNodes, path, startCoord, targetCoord); + reply.status = http::Reply::ok; + + string tmp; + + reply.content += (""); + reply.content += (""); + reply.content += (""); + + /* if(distance != std::numeric_limits::max()) + computeDescription(tmp, path, phantomNodes); + cout << tmp << endl; + */ + // reply.content += tmp; + reply.content += (""); + reply.content += ("OSM Routing Engine (c) Dennis Luxen and others "); + + reply.content += "Route from "; + convertLatLon(lat1, tmp); + reply.content += tmp; + reply.content += ","; + convertLatLon(lon1, tmp); + reply.content += tmp; + reply.content += " to "; + convertLatLon(lat2, tmp); + reply.content += tmp; + reply.content += ","; + convertLatLon(lon2, tmp); + reply.content += tmp; + reply.content += " "; + reply.content += (""); + reply.content += ("1"); + reply.content += ("1"); + reply.content += ("absolute"); + reply.content += (""); + + + if(distance != std::numeric_limits::max()) + { //A route has been found + convertLatLon(phantomNodes->startCoord.lon, tmp); + reply.content += tmp; + reply.content += (","); + doubleToString(phantomNodes->startCoord.lat/100000., tmp); + reply.content += tmp; + reply.content += (" "); + _Coordinate result; + for(vector< _PathData >::iterator it = path->begin(); it != path->end(); it++) + { + sEngine->getNodeInfo(it->node, result); + convertLatLon(result.lon, tmp); + reply.content += tmp; + reply.content += (","); + convertLatLon(result.lat, tmp); + reply.content += tmp; + reply.content += (" "); + } + + convertLatLon(phantomNodes->targetCoord.lon, tmp); + reply.content += tmp; + reply.content += (","); + convertLatLon(phantomNodes->targetCoord.lat, tmp); + reply.content += tmp; + } + + reply.content += (""); + reply.content += (""); + reply.content += (""); + reply.content += (""); + reply.content += (""); + + reply.headers.resize(3); + reply.headers[0].name = "Content-Length"; + intToString(reply.content.size(), tmp); + reply.headers[0].value = tmp; + reply.headers[1].name = "Content-Type"; + reply.headers[1].value = "application/vnd.google-earth.kml+xml"; + reply.headers[2].name = "Content-Disposition"; + reply.headers[2].value = "attachment; filename=\"route.kml\""; + + delete path; + delete phantomNodes; + return; + } +private: +// void computeDescription(string &tmp, vector< _PathData > * path, PhantomNodes * phantomNodes) +// { +// _Coordinate previous(phantomNodes->startCoord.lat, phantomNodes->startCoord.lon); +// _Coordinate next, current, lastPlace; +// stringstream numberString; +// +// double tempDist = 0; +// NodeID nextID = UINT_MAX; +// NodeID nameID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); +// short type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->startNode1, phantomNodes->startNode2); +// lastPlace.lat = phantomNodes->startCoord.lat; +// lastPlace.lon = phantomNodes->startCoord.lon; +// short nextType = SHRT_MAX; +// short prevType = SHRT_MAX; +// tmp += "\n "; +// for(vector< _PathData >::iterator it = path->begin(); it != path->end(); it++) +// { +// sEngine->getNodeInfo(it->node, current); +// if(it==path->end()-1){ +// next = _Coordinate(phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon); +// nextID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); +// nextType = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); +// } else { +// sEngine->getNodeInfo((it+1)->node, next); +// nextID = sEngine->GetNameIDForOriginDestinationNodeID(it->node, (it+1)->node); +// nextType = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(it->node, (it+1)->node); +// } +// if(nextID == nameID) { +// tempDist += ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon); +// } else { +// if(type == 0 && prevType != 0) +// tmp += "enter motorway and "; +// if(type != 0 && prevType == 0 ) +// tmp += "leave motorway and "; +// +// double angle = GetAngleBetweenTwoEdges(previous, current, next); +//// if(it->turn) +//// tmp += " turn! "; +// tmp += "follow road "; +// if(nameID != 0) +// tmp += sEngine->GetNameForNameID(nameID); +// tmp += " (type: "; +// numberString << type; +// tmp += numberString.str(); +// numberString.str(""); +// tmp += ", id: "; +// numberString << nameID; +// tmp += numberString.str(); +// numberString.str(""); +// tmp += ")\n drive for "; +// numberString << ApproximateDistance(previous.lat, previous.lon, current.lat, current.lon)+tempDist; +// tmp += numberString.str(); +// numberString.str(""); +// tmp += "m "; +// string lat; string lon; +// convertLatLon(lastPlace.lon, lon); +// convertLatLon(lastPlace.lat, lat); +// lastPlace = current; +// tmp += "\n "; +// tmp += lon; +// tmp += ","; +// tmp += lat; +// tmp += ""; +// tmp += "\n\n"; +// tmp += "\n ("; +// numberString << angle; +// tmp += numberString.str(); +// numberString.str(""); +// tmp +=") "; +// if(angle > 160 && angle < 200) { +// tmp += /* " (" << angle << ")*/"drive ahead, "; +// } else if (angle > 290 && angle <= 360) { +// tmp += /*" (" << angle << ")*/ "turn sharp left, "; +// } else if (angle > 230 && angle <= 290) { +// tmp += /*" (" << angle << ")*/ "turn left, "; +// } else if (angle > 200 && angle <= 230) { +// tmp += /*" (" << angle << ") */"bear left, "; +// } else if (angle > 130 && angle <= 160) { +// tmp += /*" (" << angle << ") */"bear right, "; +// } else if (angle > 70 && angle <= 130) { +// tmp += /*" (" << angle << ") */"turn right, "; +// } else { +// tmp += /*" (" << angle << ") */"turn sharp right, "; +// } +// tempDist = 0; +// prevType = type; +// } +// nameID = nextID; +// previous = current; +// type = nextType; +// } +// nameID = sEngine->GetNameIDForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); +// type = sEngine->GetTypeOfEdgeForOriginDestinationNodeID(phantomNodes->targetNode1, phantomNodes->targetNode2); +// tmp += "follow road "; +// tmp += sEngine->GetNameForNameID(nameID); +// tmp += " (type: "; +// numberString << type; +// tmp += numberString.str(); +// numberString.str(""); +// tmp += ", id: "; +// numberString << nameID; +// tmp += numberString.str(); +// numberString.str(""); +// tmp += ")\n drive for "; +// numberString << ApproximateDistance(previous.lat, previous.lon, phantomNodes->targetCoord.lat, phantomNodes->targetCoord.lon) + tempDist; +// tmp += numberString.str(); +// numberString.str(""); +// tmp += "m\n "; +// string lat; string lon; +// convertLatLon(lastPlace.lon, lon); +// convertLatLon(lastPlace.lat, lat); +// tmp += ""; +// tmp += lon; +// tmp += ","; +// tmp += lat; +// tmp += ""; +// tmp += "\n"; +// tmp += "\n you have reached your destination\n "; +// tmp += "End of Route"; +// convertLatLon(phantomNodes->targetCoord.lon, lon); +// convertLatLon(phantomNodes->targetCoord.lat, lat); +// tmp += "\n "; +// tmp += lon; +// tmp += ","; +// tmp += lat; +// tmp +="\n"; +// tmp += ""; +// } + + NodeInformationHelpDesk * nodeHelpDesk; + SearchEngine > * sEngine; + std::vector * names; + StaticGraph * graph; +}; + + +#endif /* ROUTEPLUGIN_H_ */ diff --git a/Server/BasicDatastructures.h b/Server/BasicDatastructures.h new file mode 100644 index 000000000..b951b5c58 --- /dev/null +++ b/Server/BasicDatastructures.h @@ -0,0 +1,112 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +#ifndef BASIC_DATASTRUCTURES_H +#define BASIC_DATASTRUCTURES_H + +#include +#include + +namespace http { + +const std::string okString = "HTTP/1.0 200 OK\r\n"; +const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; +const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; + +const char okHTML[] = ""; +const char badRequestHTML[] = "Bad Request

400 Bad Request

"; +const char internalServerErrorHTML[] = "Internal Server Error

500 Internal Server Error

"; +const char seperators[] = { ':', ' ' }; +const char crlf[] = { '\r', '\n' }; + +struct Header { + std::string name; + std::string value; +}; + +struct Request { + std::string uri; +}; + +struct Reply { + Reply() { content.reserve(1000000); } + enum status_type { + ok = 200, + badRequest = 400, + internalServerError = 500 + } status; + + std::vector
headers; + std::string content; + std::vector toBuffers(); + static Reply stockReply(status_type status); +}; + +boost::asio::const_buffer ToBuffer(Reply::status_type status) { + switch (status) { + case Reply::ok: + return boost::asio::buffer(okString); + case Reply::internalServerError: + return boost::asio::buffer(internalServerErrorString); + default: + return boost::asio::buffer(badRequestString); + } +} + +std::string ToString(Reply::status_type status) { + switch (status) { + case Reply::ok: + return okHTML; + case Reply::badRequest: + return badRequestHTML; + default: + return internalServerErrorHTML; + } +} + +std::vector Reply::toBuffers(){ + std::vector buffers; + buffers.push_back(ToBuffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) { + Header& h = headers[i]; + buffers.push_back(boost::asio::buffer(h.name)); + buffers.push_back(boost::asio::buffer(seperators)); + buffers.push_back(boost::asio::buffer(h.value)); + buffers.push_back(boost::asio::buffer(crlf)); + } + buffers.push_back(boost::asio::buffer(crlf)); + buffers.push_back(boost::asio::buffer(content)); + return buffers; +} + +Reply Reply::stockReply(Reply::status_type status) { + Reply rep; + rep.status = status; + rep.content = ToString(status); + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = boost::lexical_cast(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; +} +} // namespace http + +#endif //BASIC_DATASTRUCTURES_H diff --git a/Server/Connection.h b/Server/Connection.h new file mode 100644 index 000000000..c5a675c69 --- /dev/null +++ b/Server/Connection.h @@ -0,0 +1,94 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +#ifndef CONNECTION_H +#define CONNECTION_H + +#include + +#include +#include +#include +#include +#include +#include +#include "BasicDatastructures.h" +#include "RequestHandler.h" +#include "RequestParser.h" + +namespace http { + +/// Represents a single connection from a client. +class Connection : public boost::enable_shared_from_this, private boost::noncopyable { +public: + explicit Connection(boost::asio::io_service& io_service, RequestHandler& handler) : strand(io_service), TCPsocket(io_service), requestHandler(handler) {} + + boost::asio::ip::tcp::socket& socket() { + return TCPsocket; + } + + /// Start the first asynchronous operation for the connection. + void start() { + TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); + } + +private: + void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred) { + if (!e) { + boost::tribool result; + boost::tie(result, boost::tuples::ignore) = requestParser.Parse( request, incomingDataBuffer.data(), incomingDataBuffer.data() + bytes_transferred); + + if (result) { + requestHandler.handle_request(request, reply); + boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error))); + } else if (!result) { + reply = Reply::stockReply(Reply::badRequest); + boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error))); + } else { + TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); + } + } + } + + /// Handle completion of a write operation. + void handleWrite(const boost::system::error_code& e) { + if (!e) { + // Initiate graceful connection closure. + boost::system::error_code ignoredEC; + TCPsocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC); + } + // No new asynchronous operations are started. This means that all shared_ptr + // references to the connection object will disappear and the object will be + // destroyed automatically after this handler returns. The connection class's + // destructor closes the socket. + } + + boost::asio::io_service::strand strand; + boost::asio::ip::tcp::socket TCPsocket; + RequestHandler& requestHandler; + boost::array incomingDataBuffer; + Request request; + RequestParser requestParser; + Reply reply; +}; + +} // namespace http + +#endif // CONNECTION_H diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h new file mode 100644 index 000000000..032b7f87f --- /dev/null +++ b/Server/RequestHandler.h @@ -0,0 +1,85 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef REQUEST_HANDLER_H +#define REQUEST_HANDLER_H + +#include +#include +#include + +#include "BasicDatastructures.h" + +#include "../DataStructures/HashTable.h" +#include "../Plugins/BasePlugin.h" + +namespace http { + +class RequestHandler : private boost::noncopyable { +public: + explicit RequestHandler() { } + + ~RequestHandler() { + pluginMap.EraseAll(); + } + + void handle_request(const Request& req, Reply& rep){ + //parse command + std::string request(req.uri); + std::string command; + std::size_t firstAmpPosition = request.find_first_of("&"); + command = request.substr(1,firstAmpPosition-1); + std::cout << "[debug] looking for handler for command: " << command << std::endl; + try { + if(pluginMap.Holds(command)) { + + std::vector parameters; + std::stringstream ss(( firstAmpPosition == std::string::npos ? "" : request.substr(firstAmpPosition+1) )); + std::string item; + while(std::getline(ss, item, '&')) { + parameters.push_back(item); + } +// 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; + pluginMap.Find(command)->HandleRequest(parameters, rep ); + } 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(), plugin); + } + +private: + boost::mutex pluginMutex; + HashTable pluginMap; +}; +} // namespace http + +#endif // REQUEST_HANDLER_H diff --git a/Server/RequestParser.h b/Server/RequestParser.h new file mode 100644 index 000000000..e2fef57c4 --- /dev/null +++ b/Server/RequestParser.h @@ -0,0 +1,271 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef REQUEST_PARSER_H +#define REQUEST_PARSER_H + +#include +#include +#include "BasicDatastructures.h" + +namespace http { + +class RequestParser { +public: + RequestParser() : state_(method_start) { } + void Reset() { state_ = method_start; } + + boost::tuple Parse(Request& req, char* begin, char* end) { + while (begin != end) { + boost::tribool result = consume(req, *begin++); + if (result || !result){ + return boost::make_tuple(result, begin); + } + } + boost::tribool result = boost::indeterminate; + return boost::make_tuple(result, begin); + } + +private: + boost::tribool consume(Request& req, char input) { + switch (state_) { + case method_start: + if (!isChar(input) || isCTL(input) || isTSpecial(input)) { + return false; + } else { + state_ = method; + return boost::indeterminate; + } + case method: + if (input == ' ') { + state_ = uri; + return boost::indeterminate; + } else if (!isChar(input) || isCTL(input) || isTSpecial(input)) { + return false; + } else { + return boost::indeterminate; + } + case uri_start: + if (isCTL(input)) { + return false; + } else { + state_ = uri; + req.uri.push_back(input); + return boost::indeterminate; + } + case uri: + if (input == ' ') { + state_ = http_version_h; + return boost::indeterminate; + } else if (isCTL(input)) { + return false; + } else { + req.uri.push_back(input); + return boost::indeterminate; + } + case http_version_h: + if (input == 'H') { + state_ = http_version_t_1; + return boost::indeterminate; + } else { + return false; + } + case http_version_t_1: + if (input == 'T') { + state_ = http_version_t_2; + return boost::indeterminate; + } else { + return false; + } + case http_version_t_2: + if (input == 'T') { + state_ = http_version_p; + return boost::indeterminate; + } else { + return false; + } + case http_version_p: + if (input == 'P') { + state_ = http_version_slash; + return boost::indeterminate; + } else { + return false; + } + case http_version_slash: + if (input == '/') { + state_ = http_version_major_start; + return boost::indeterminate; + } else { + return false; + } + case http_version_major_start: + if (isDigit(input)) { + state_ = http_version_major; + return boost::indeterminate; + } else { + return false; + } + case http_version_major: + if (input == '.') { + state_ = http_version_minor_start; + return boost::indeterminate; + } else if (isDigit(input)) { + return boost::indeterminate; + } else { + return false; + } + case http_version_minor_start: + if (isDigit(input)) { + state_ = http_version_minor; + return boost::indeterminate; + } else { + return false; + } + case http_version_minor: + if (input == '\r') { + state_ = expecting_newline_1; + return boost::indeterminate; + } else if (isDigit(input)) { + return boost::indeterminate; + } + else { + return false; + } + case expecting_newline_1: + if (input == '\n') { + state_ = header_line_start; + return boost::indeterminate; + } else { + return false; + } + case header_line_start: + if (input == '\r') { + state_ = expecting_newline_3; + return boost::indeterminate; + } else if (!isChar(input) || isCTL(input) || isTSpecial(input)) { + return false; + } else { + state_ = header_name; + return boost::indeterminate; + } + case header_lws: + if (input == '\r') { + state_ = expecting_newline_2; + return boost::indeterminate; + } else if (input == ' ' || input == '\t') { + return boost::indeterminate; + } + else if (isCTL(input)) { + return false; + } else { + state_ = header_value; + return boost::indeterminate; + } + case header_name: + if (input == ':') { + state_ = space_before_header_value; + return boost::indeterminate; + } else if (!isChar(input) || isCTL(input) || isTSpecial(input)) { + return false; + } else { + return boost::indeterminate; + } + case space_before_header_value: + if (input == ' ') { + state_ = header_value; + return boost::indeterminate; + } else { + return false; + } + case header_value: + if (input == '\r') { + state_ = expecting_newline_2; + return boost::indeterminate; + } else if (isCTL(input)) { + return false; + } else { + return boost::indeterminate; + } + case expecting_newline_2: + if (input == '\n') { + state_ = header_line_start; + return boost::indeterminate; + } else { + return false; + } + case expecting_newline_3: + return (input == '\n'); + default: + return false; + } + } + + inline bool isChar(int c) { + return c >= 0 && c <= 127; + } + + inline bool isCTL(int c) { + return (c >= 0 && c <= 31) || (c == 127); + } + + inline bool isTSpecial(int c) { + switch (c) { + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + return true; + default: + return false; + } + } + + inline bool isDigit(int c) { + return c >= '0' && c <= '9'; + } + + enum state { + method_start, + method, + uri_start, + uri, + http_version_h, + http_version_t_1, + http_version_t_2, + http_version_p, + http_version_slash, + http_version_major_start, + http_version_major, + http_version_minor_start, + http_version_minor, + expecting_newline_1, + header_line_start, + header_lws, + header_name, + space_before_header_value, + header_value, + expecting_newline_2, + expecting_newline_3 + } state_; +}; + +} // namespace http + +#endif // REQUEST_PARSER_H diff --git a/Server/Server.h b/Server/Server.h new file mode 100644 index 000000000..1b82c0a79 --- /dev/null +++ b/Server/Server.h @@ -0,0 +1,90 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef SERVER_H +#define SERVER_H + +#include +#include +#include +#include +#include +#include + +#include "Connection.h" +#include "RequestHandler.h" + +namespace http { + +class Server: private boost::noncopyable { +public: + explicit Server(const std::string& address, const std::string& port, unsigned thread_pool_size) : threadPoolSize(thread_pool_size), acceptor(ioService), newConnection(new Connection(ioService, requestHandler)), requestHandler(){ + boost::asio::ip::tcp::resolver resolver(ioService); + boost::asio::ip::tcp::resolver::query query(address, port); + boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); + + acceptor.open(endpoint.protocol()); + acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + acceptor.bind(endpoint); + acceptor.listen(); + acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error)); + } + + void Run() { + std::vector > threads; + for (unsigned i = 0; i < threadPoolSize; ++i) { + boost::shared_ptr thread(new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService))); + threads.push_back(thread); + } + for (unsigned i = 0; i < threads.size(); ++i) + threads[i]->join(); + } + + void Stop() { + ioService.stop(); + } + + + + RequestHandler * GetRequestHandlerPtr() { + return &requestHandler; + } + +private: + typedef boost::shared_ptr ConnectionPtr; + + void handleAccept(const boost::system::error_code& e) { + if (!e) { + newConnection->start(); + newConnection.reset(new Connection(ioService, requestHandler)); + acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error)); + } + } + + unsigned threadPoolSize; + boost::asio::io_service ioService; + boost::asio::ip::tcp::acceptor acceptor; + ConnectionPtr newConnection; + RequestHandler requestHandler; +}; + +} // namespace http + +#endif // SERVER_H diff --git a/Server/ServerConfiguration.h b/Server/ServerConfiguration.h new file mode 100644 index 000000000..e1237d58d --- /dev/null +++ b/Server/ServerConfiguration.h @@ -0,0 +1,15 @@ +/* + * ServerConfiguration.h + * + * Created on: 26.11.2010 + * Author: dennis + */ + +#ifndef SERVERCONFIGURATION_H_ +#define SERVERCONFIGURATION_H_ + +#include "../Util/BaseConfiguration.h" + +typedef BaseConfiguration ServerConfiguration; + +#endif /* SERVERCONFIGURATION_H_ */ diff --git a/Server/ServerFactory.h b/Server/ServerFactory.h new file mode 100644 index 000000000..b380165f4 --- /dev/null +++ b/Server/ServerFactory.h @@ -0,0 +1,88 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + + Created on: 26.11.2010 + Author: dennis + + */ + +#ifndef SERVERFACTORY_H_ +#define SERVERFACTORY_H_ + +#include + +#ifdef _OPENMP +#include +#endif + +#include "Server.h" +#include "ServerConfiguration.h" + +#include "../Util/InputFileUtil.h" + +typedef http::Server Server; + +struct ServerFactory { + static Server * CreateServer(ServerConfiguration& serverConfig) { + + if(!testDataFile(serverConfig.GetParameter("nodesData").c_str())) { + std::cerr << "[error] nodes file not found" << std::endl; + exit(-1); + } + + if(!testDataFile(serverConfig.GetParameter("hsgrData").c_str())) { + std::cerr << "[error] hsgr file not found" << std::endl; + exit(-1); + } + + if(!testDataFile(serverConfig.GetParameter("namesData").c_str())) { + std::cerr << "[error] names file not found" << std::endl; + exit(-1); + } + + if(!testDataFile(serverConfig.GetParameter("ramIndex").c_str())) { + std::cerr << "[error] ram index file not found" << std::endl; + exit(-1); + } + + if(!testDataFile(serverConfig.GetParameter("fileIndex").c_str())) { + std::cerr << "[error] file index file not found" << std::endl; + exit(-1); + } + + unsigned threads = omp_get_num_procs(); + if(serverConfig.GetParameter("IP") == "") + serverConfig.SetParameter("IP", "0.0.0.0"); + if(serverConfig.GetParameter("Port") == "") + serverConfig.SetParameter("Port", "5000"); + + if(atoi(serverConfig.GetParameter("Threads").c_str()) != 0 && atoi(serverConfig.GetParameter("Threads").c_str()) <= threads) + threads = atoi( serverConfig.GetParameter("Threads").c_str() ); + + Server * server = new Server(serverConfig.GetParameter("IP"), serverConfig.GetParameter("Port"), threads); + return server; + } + + static Server * CreateServer(const char * iniFile) { + ServerConfiguration serverConfig(iniFile); + return CreateServer(serverConfig); + } +}; + +#endif /* SERVERFACTORY_H_ */ diff --git a/Util/BaseConfiguration.h b/Util/BaseConfiguration.h new file mode 100644 index 000000000..2db9d5438 --- /dev/null +++ b/Util/BaseConfiguration.h @@ -0,0 +1,68 @@ +/* + * BaseConfiguration.h + * + * Created on: 26.11.2010 + * Author: dennis + */ + +#ifndef BASECONFIGURATION_H_ +#define BASECONFIGURATION_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../DataStructures/HashTable.h" + +class BaseConfiguration { +public: + BaseConfiguration(const char * configFile) { + std::ifstream config( configFile ); + if(!config) { + std::cerr << "[config] .ini not found" << std::endl; + return; + } + + //parameters + options.insert("*"); + + try { + for (boost::program_options::detail::config_file_iterator i(config, options), e ; i != e; ++i) { + std::cout << "[config] " << i->string_key << " = " << i->value[0] << std::endl; + parameters.Add(i->string_key, i->value[0]); + } + } catch(std::exception& e) { + std::cerr << "[config] .ini not found -> Exception: " < options; + HashTable parameters; + //Speichert alle Einträge aus INI Datei +}; + +#endif /* BASECONFIGURATION_H_ */ diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h new file mode 100644 index 000000000..955a619a3 --- /dev/null +++ b/Util/GraphLoader.h @@ -0,0 +1,142 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef CREATEGRAPH_H +#define GRAPHLOADER_H + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef _GLIBCXX_PARALLEL +#include +#else +#include +#endif + +#include "../DataStructures/ImportEdge.h" +#include "../typedefs.h" + +typedef google::dense_hash_map ExternalNodeMap; + +template +NodeID readOSRMGraphFromStream(istream &in, vector& edgeList, vector * int2ExtNodeMap) { + NodeID n, source, target, id; + EdgeID m; + short locatable; + int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open) + ExternalNodeMap ext2IntNodeMap; + ext2IntNodeMap.set_empty_key(UINT_MAX); + in >> n; + VERBOSE(cout << "Importing n = " << n << " nodes ..." << flush;) + for (NodeID i=0; i> id >> ycoord >> xcoord; + int2ExtNodeMap->push_back(NodeInfo(xcoord, ycoord, id)); + ext2IntNodeMap.insert(make_pair(id, i)); + } + in >> m; + VERBOSE(cout << " and " << m << " edges ..." << flush;) + + edgeList.reserve(m); + for (EdgeID i=0; i> source >> target >> length >> dir >> weight >> type >> nameID; + assert(length > 0); + assert(weight > 0); + assert(0<=dir && dir<=2); + + bool forward = true; + bool backward = true; + if (dir == 1) backward = false; + if (dir == 2) forward = false; + + if(length == 0) + { cerr << "loaded null length edge" << endl; exit(1); } + + // translate the external NodeIDs to internal IDs + ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source); + if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) + { + cerr << "after " << edgeList.size() << " edges" << endl; + cerr << "->" << source << "," << target << "," << length << "," << dir << "," << weight << endl; + cerr << "unresolved source NodeID: " << source << endl; exit(0); + } + source = intNodeID->second; + intNodeID = ext2IntNodeMap.find(target); + if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) { cerr << "unresolved target NodeID : " << target << endl; exit(0); } + target = intNodeID->second; + + if(source == UINT_MAX || target == UINT_MAX) { cerr << "nonexisting source or target" << endl; exit(0); } + + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type ); + edgeList.push_back(inputEdge); + } + ext2IntNodeMap.clear(); + vector(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates. + cout << "ok" << endl; + return n; +} + +template +void readHSGRFromStream(istream &in, vector * edgeList) { + while(!in.eof()) + { + EdgeT g; + EdgeData e; + + int distance; + bool shortcut; + bool forward; + bool backward; + bool forwardTurn; + bool backwardTurn; + short type; + NodeID middle; + NodeID source; + NodeID target; + + in.read((char *)&(distance), sizeof(int)); + assert(distance > 0); + in.read((char *)&(forwardTurn), sizeof(bool)); + in.read((char *)&(backwardTurn), sizeof(bool)); + in.read((char *)&(shortcut), sizeof(bool)); + in.read((char *)&(forward), sizeof(bool)); + in.read((char *)&(backward), sizeof(bool)); + in.read((char *)&(middle), sizeof(NodeID)); + in.read((char *)&(type), sizeof(short)); + in.read((char *)&(source), sizeof(NodeID)); + in.read((char *)&(target), sizeof(NodeID)); + e.backward = backward; e.distance = distance; e.forward = forward; e.middleName.middle = middle; e.shortcut = shortcut; e.type = type; + e.forwardTurn = forwardTurn; e.backwardTurn = backwardTurn; + g.data = e; g.source = source; g.target = target; + + edgeList->push_back(g); + } + +} +#endif // CREATEGRAPH_H diff --git a/Util/InputFileUtil.h b/Util/InputFileUtil.h new file mode 100644 index 000000000..70026a758 --- /dev/null +++ b/Util/InputFileUtil.h @@ -0,0 +1,43 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef INPUTFILEUTIL_H_ +#define INPUTFILEUTIL_H_ + +#include + +// Check if file exists and if it can be opened for reading with ifstream an object +bool testDataFile(const char *filename){ + std::ifstream in(filename, std::ios::binary); + if(in.fail()) { + std::cerr << "[error] Failed to open file " << filename << " for reading." << std::endl; + return false; + } + return true; +} +bool testDataFiles(int argc, char *argv[]){ + for(int i = 0; i < argc; ++i) { + if(testDataFile(argv[i])==false) + return false; + } + return true; +} + +#endif /* INPUTFILEUTIL_H_ */ diff --git a/Util/StrIngUtil.h b/Util/StrIngUtil.h new file mode 100644 index 000000000..1df6c7f9c --- /dev/null +++ b/Util/StrIngUtil.h @@ -0,0 +1,82 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef STRINGUTIL_H_ +#define STRINGUTIL_H_ + +// precision: position after decimal point +// length: maximum number of digits including comma and decimals +template< int length, int precision > +inline char* printInt( char* buffer, int value ) +{ + bool minus = false; + if ( value < 0 ) { + minus = true; + value = -value; + } + buffer += length - 1; + for ( int i = 0; i < precision; i++ ) { + *buffer = '0' + ( value % 10 ); + value /= 10; + buffer--; + } + *buffer = '.'; + buffer--; + for ( int i = precision + 1; i < length; i++ ) { + *buffer = '0' + ( value % 10 ); + value /= 10; + if ( value == 0 ) break; + buffer--; + } + if ( minus ) { + buffer--; + *buffer = '-'; + } + return buffer; +} + +inline void intToString(const int value, std::string & output) +{ + // The largest 32-bit integer is 4294967295, that is 10 chars + // On the safe side, add 1 for sign, and 1 for trailing zero + char buffer[12] ; + sprintf(buffer, "%i", value) ; + output = buffer ; +} + +inline void convertLatLon(const int value, std::string & output) +{ + char buffer[100]; + buffer[10] = 0; // Nullterminierung + char* string = printInt< 10, 5 >( buffer, value ); + output = string; +} + +/* used to be boosts lexical cast, but this was too slow */ +inline void doubleToString(const double value, std::string & output) +{ + // The largest 32-bit integer is 4294967295, that is 10 chars + // On the safe side, add 1 for sign, and 1 for trailing zero + char buffer[12] ; + sprintf(buffer, "%f", value) ; + output = buffer ; +} + +#endif /* STRINGUTIL_H_ */ diff --git a/contractor.ini b/contractor.ini new file mode 100644 index 000000000..4da33c7ef --- /dev/null +++ b/contractor.ini @@ -0,0 +1 @@ +Threads = 4 diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 6d49e1548..20ef370b8 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -41,12 +41,14 @@ or see http://www.gnu.org/licenses/agpl.txt. #endif #include "typedefs.h" -#include "Contractor/GraphLoader.h" -#include "Contractor/BinaryHeap.h" #include "Contractor/Contractor.h" #include "Contractor/ContractionCleanup.h" +#include "DataStructures/BinaryHeap.h" #include "DataStructures/NNGrid.h" #include "DataStructures/TurnInfoFactory.h" +#include "Util/BaseConfiguration.h" +#include "Util/InputFileUtil.h" +#include "Util/GraphLoader.h" using namespace std; @@ -54,6 +56,7 @@ typedef ContractionCleanup::Edge::EdgeData EdgeData; typedef DynamicGraph::InputEdge GridEdge; typedef StaticGraph::InputEdge StaticEdge; typedef NNGrid::NNGrid WritableGrid; +typedef BaseConfiguration ContractorConfiguration; vector * int2ExtNodeMap = new vector(); @@ -64,6 +67,16 @@ int main (int argc, char *argv[]) cerr << "usage: " << endl << argv[0] << " " << endl; exit(-1); } + + //todo: check if contractor exists + unsigned numberOfThreads = omp_get_num_procs(); + if(testDataFile("contractor.ini")) { + ContractorConfiguration contractorConfig("contractor.ini"); + if(atoi(contractorConfig.GetParameter("Threads").c_str()) != 0 && atoi(contractorConfig.GetParameter("Threads").c_str()) <= numberOfThreads) + numberOfThreads = atoi( contractorConfig.GetParameter("Threads").c_str() ); + } + omp_set_num_threads(numberOfThreads); + cout << "preprocessing data from input file " << argv[1] << endl; ifstream in; diff --git a/extractLargeNetwork.cpp b/extractLargeNetwork.cpp index b7f859903..aea4f6280 100644 --- a/extractLargeNetwork.cpp +++ b/extractLargeNetwork.cpp @@ -27,6 +27,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include #include +#include #include #include #include @@ -58,284 +59,284 @@ STXXLStringVector nameVector; NodeMap * nodeMap = new NodeMap(); StringMap * stringMap = new StringMap(); -int main (int argc, char *argv[]) -{ - if(argc <= 1) - { - cerr << "usage: " << endl << argv[0] << " " << endl; - exit(-1); - } - cout << "extracting data from input file " << argv[1] << endl; - cout << "reading input file. This may take some time ..." << flush; - xmlTextReaderPtr inputReader = inputReaderFactory(argv[1]); - double time = get_timestamp(); - settings.speedProfile.names.insert(settings.speedProfile.names.begin(), names, names+14); - settings.speedProfile.speed.insert(settings.speedProfile.speed.begin(), speeds, speeds+14); +int main (int argc, char *argv[]) { + if(argc <= 1) { + cerr << "usage: " << endl << argv[0] << " " << endl; + exit(-1); + } - nodeMap->set_empty_key(UINT_MAX); - stringMap->set_empty_key(GetRandomString()); - stringMap->insert(std::make_pair("", 0)); - try { - while ( xmlTextReaderRead( inputReader ) == 1 ) { - const int type = xmlTextReaderNodeType( inputReader ); + cout << "extracting data from input file " << argv[1] << endl; + cout << "reading input file. This may take some time ..." << flush; + xmlTextReaderPtr inputReader = inputReaderFactory(argv[1]); - //1 is Element - if ( type != 1 ) - continue; + double time = get_timestamp(); + settings.speedProfile.names.insert(settings.speedProfile.names.begin(), names, names+14); + settings.speedProfile.speed.insert(settings.speedProfile.speed.begin(), speeds, speeds+14); - xmlChar* currentName = xmlTextReaderName( inputReader ); - if ( currentName == NULL ) - continue; + nodeMap->set_empty_key(UINT_MAX); + stringMap->set_empty_key(GetRandomString()); + stringMap->insert(std::make_pair("", 0)); + try { + while ( xmlTextReaderRead( inputReader ) == 1 ) { + const int type = xmlTextReaderNodeType( inputReader ); - if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { - _Node node = _ReadXMLNode( inputReader ); - allNodes.push_back(node); - if ( node.trafficSignal ) - SignalNodes.push_back( node.id ); + //1 is Element + if ( type != 1 ) + continue; - } - if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - string name; - _Way way = _ReadXMLWay( inputReader, settings, name ); + xmlChar* currentName = xmlTextReaderName( inputReader ); + if ( currentName == NULL ) + continue; - if ( way.usefull && way.access && way.path.size() ) { - StringMap::iterator strit = stringMap->find(name); - if(strit == stringMap->end()) - { - way.nameID = nameVector.size(); - nameVector.push_back(name); - stringMap->insert(std::make_pair(name, way.nameID) ); - // cout << "found name ID: " << way.nameID << " (" << name << ")" << endl; - } else { - way.nameID = strit->second; - // cout << "name with ID " << way.nameID << " already existing (" << name << ")" << endl; - } - for ( unsigned i = 0; i < way.path.size(); ++i ) { - usedNodes.push_back(way.path[i]); - } + if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { + _Node node = _ReadXMLNode( inputReader ); + allNodes.push_back(node); + if ( node.trafficSignal ) + SignalNodes.push_back( node.id ); - if ( way.direction == _Way::opposite ){ - std::reverse( way.path.begin(), way.path.end() ); - } - vector< NodeID > & path = way.path; - assert(way.type > -1 || way.maximumSpeed != -1); - assert(path.size()>0); + } + if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { + string name; + _Way way = _ReadXMLWay( inputReader, settings, name ); - if(way.maximumSpeed == -1) - way.maximumSpeed = settings.speedProfile.speed[way.type]; + if ( way.usefull && way.access && way.path.size() ) { + StringMap::iterator strit = stringMap->find(name); + if(strit == stringMap->end()) + { + way.nameID = nameVector.size(); + nameVector.push_back(name); + stringMap->insert(std::make_pair(name, way.nameID) ); + // cout << "found name ID: " << way.nameID << " (" << name << ")" << endl; + } else { + way.nameID = strit->second; + // cout << "name with ID " << way.nameID << " already existing (" << name << ")" << endl; + } + for ( unsigned i = 0; i < way.path.size(); ++i ) { + usedNodes.push_back(way.path[i]); + } - for(vector< NodeID >::size_type n = 0; n < path.size()-1; n++) - { - _Edge e; - e.start = way.path[n]; - e.target = way.path[n+1]; - e.type = way.type; - e.direction = way.direction; - e.speed = way.maximumSpeed; - e.nameID = way.nameID; - allEdges.push_back(e); - } - } - } - if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { + if ( way.direction == _Way::opposite ){ + std::reverse( way.path.begin(), way.path.end() ); + } + vector< NodeID > & path = way.path; + assert(way.type > -1 || way.maximumSpeed != -1); + assert(path.size()>0); - } - xmlFree( currentName ); - } - cout << "raw no. of names: " << nameVector.size() << endl; - cout << "raw no. of nodes: " << allNodes.size() << endl; - cout << "raw no. of edges: " << allEdges.size() << endl; + if(way.maximumSpeed == -1) + way.maximumSpeed = settings.speedProfile.speed[way.type]; - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); - unsigned memory_to_use = 1024 * 1024 * 1024; + for(vector< NodeID >::size_type n = 0; n < path.size()-1; n++) + { + _Edge e; + e.start = way.path[n]; + e.target = way.path[n+1]; + e.type = way.type; + e.direction = way.direction; + e.speed = way.maximumSpeed; + e.nameID = way.nameID; + allEdges.push_back(e); + } + } + } + if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { - cout << "Sorting used nodes ..." << flush; - stxxl::sort(usedNodes.begin(), usedNodes.end(), Cmp(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); - cout << "Erasing duplicate entries ..." << flush; - stxxl::vector::iterator NewEnd = unique ( usedNodes.begin(),usedNodes.end() ) ; - usedNodes.resize ( NewEnd - usedNodes.begin() ); - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); + } + xmlFree( currentName ); + } + cout << "raw no. of names: " << nameVector.size() << endl; + cout << "raw no. of nodes: " << allNodes.size() << endl; + cout << "raw no. of edges: " << allEdges.size() << endl; - cout << "Sorting all nodes ..." << flush; - stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use); - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); + unsigned memory_to_use = 1024 * 1024 * 1024; - string name(argv[1]); - int pos; - pos = name.find(".osm.bz2"); - if(pos!=string::npos) - { - name.replace(pos, 8, ".osrm"); - } else { - pos=name.find(".osm"); - if(pos!=string::npos) - { - name.replace(pos, 5, ".osrm"); - } else { - name.append(".osrm"); - } - } + cout << "Sorting used nodes ..." << flush; + stxxl::sort(usedNodes.begin(), usedNodes.end(), Cmp(), memory_to_use); + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); + cout << "Erasing duplicate entries ..." << flush; + stxxl::vector::iterator NewEnd = unique ( usedNodes.begin(),usedNodes.end() ) ; + usedNodes.resize ( NewEnd - usedNodes.begin() ); + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); - ofstream fout; - fout.open(name.c_str()); + cout << "Sorting all nodes ..." << flush; + stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use); + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); - cout << "Confirming used nodes ..." << flush; - NodeID counter = 0; - NodeID notfound = 0; - STXXLNodeVector::iterator nvit = allNodes.begin(); - STXXLNodeIDVector::iterator niit = usedNodes.begin(); - while(niit != usedNodes.end() && nvit != allNodes.end()) - { - if(*niit < nvit->id){ - niit++; - continue; - } - if(*niit > nvit->id) - { - nvit++; - continue; - } - if(*niit == nvit->id) - { - confirmedNodes.push_back(*nvit); - nodeMap->insert(std::make_pair(nvit->id, *nvit)); - niit++; - nvit++; - } - } - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); + string name(argv[1]); + int pos; + pos = name.find(".osm.bz2"); + if(pos!=string::npos) + { + name.replace(pos, 8, ".osrm"); + } else { + pos=name.find(".osm"); + if(pos!=string::npos) + { + name.replace(pos, 5, ".osrm"); + } else { + name.append(".osrm"); + } + } - cout << "Writing used nodes ..." << flush; - fout << confirmedNodes.size() << endl; - for(STXXLNodeVector::iterator ut = confirmedNodes.begin(); ut != confirmedNodes.end(); ut++) - { - fout << ut->id<< " " << ut->lon << " " << ut->lat << "\n"; - } + ofstream fout; + fout.open(name.c_str()); - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); + cout << "Confirming used nodes ..." << flush; + NodeID counter = 0; + NodeID notfound = 0; + STXXLNodeVector::iterator nvit = allNodes.begin(); + STXXLNodeIDVector::iterator niit = usedNodes.begin(); + while(niit != usedNodes.end() && nvit != allNodes.end()) + { + if(*niit < nvit->id){ + niit++; + continue; + } + if(*niit > nvit->id) + { + nvit++; + continue; + } + if(*niit == nvit->id) + { + confirmedNodes.push_back(*nvit); + nodeMap->insert(std::make_pair(nvit->id, *nvit)); + niit++; + nvit++; + } + } + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); - cout << "confirming used ways ..." << flush; - for(STXXLEdgeVector::iterator eit = allEdges.begin(); eit != allEdges.end(); eit++) - { - assert(eit->type > -1 || eit->speed != -1); + cout << "Writing used nodes ..." << flush; + fout << confirmedNodes.size() << endl; + for(STXXLNodeVector::iterator ut = confirmedNodes.begin(); ut != confirmedNodes.end(); ut++) + { + fout << ut->id<< " " << ut->lon << " " << ut->lat << "\n"; + } - NodeMap::iterator startit = nodeMap->find(eit->start); - if(startit == nodeMap->end()) - { - continue; - } - NodeMap::iterator targetit = nodeMap->find(eit->target); + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); - if(targetit == nodeMap->end()) - { - continue; - } - confirmedEdges.push_back(*eit); - } - fout << confirmedEdges.size() << "\n"; - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); + cout << "confirming used ways ..." << flush; + for(STXXLEdgeVector::iterator eit = allEdges.begin(); eit != allEdges.end(); eit++) + { + assert(eit->type > -1 || eit->speed != -1); - cout << "writing confirmed ways ..." << flush; + NodeMap::iterator startit = nodeMap->find(eit->start); + if(startit == nodeMap->end()) + { + continue; + } + NodeMap::iterator targetit = nodeMap->find(eit->target); - for(STXXLEdgeVector::iterator eit = confirmedEdges.begin(); eit != confirmedEdges.end(); eit++) - { - NodeMap::iterator startit = nodeMap->find(eit->start); - if(startit == nodeMap->end()) - { - continue; - } - NodeMap::iterator targetit = nodeMap->find(eit->target); + if(targetit == nodeMap->end()) + { + continue; + } + confirmedEdges.push_back(*eit); + } + fout << confirmedEdges.size() << "\n"; + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); - if(targetit == nodeMap->end()) - { - continue; - } - double distance = ApproximateDistance(startit->second.lat, startit->second.lon, targetit->second.lat, targetit->second.lon); - if(eit->speed == -1) - eit->speed = settings.speedProfile.speed[eit->type]; - double weight = ( distance * 10. ) / (eit->speed / 3.6); - int intWeight = max(1, (int) weight); - int intDist = max(1, (int)distance); - int ferryIndex = settings.indexInAccessListOf("ferry"); - assert(ferryIndex != -1); + cout << "writing confirmed ways ..." << flush; - switch(eit->direction) - { - case _Way::notSure: - fout << startit->first << " " << targetit->first << " " << intDist << " " << 0 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; - break; - case _Way::oneway: - fout << startit->first << " " << targetit->first << " " << intDist << " " << 1 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; - break; - case _Way::bidirectional: - fout << startit->first << " " << targetit->first << " " << intDist << " " << 0 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; - break; - case _Way::opposite: - fout << startit->first << " " << targetit->first << " " << intDist << " " << 1 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; - break; - default: - assert(false); - break; - } - } - fout.close(); + for(STXXLEdgeVector::iterator eit = confirmedEdges.begin(); eit != confirmedEdges.end(); eit++) + { + NodeMap::iterator startit = nodeMap->find(eit->start); + if(startit == nodeMap->end()) + { + continue; + } + NodeMap::iterator targetit = nodeMap->find(eit->target); - name.append(".names"); - cout << "ok, after " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); - cout << "writing street name index ..." << flush; + if(targetit == nodeMap->end()) + { + continue; + } + double distance = ApproximateDistance(startit->second.lat, startit->second.lon, targetit->second.lat, targetit->second.lon); + if(eit->speed == -1) + eit->speed = settings.speedProfile.speed[eit->type]; + double weight = ( distance * 10. ) / (eit->speed / 3.6); + int intWeight = max(1, (int) weight); + int intDist = max(1, (int)distance); + int ferryIndex = settings.indexInAccessListOf("ferry"); + assert(ferryIndex != -1); - vector * nameIndex = new vector(nameVector.size()+1, 0); - unsigned currentNameIndex = 0; - for(int i = 0; i < nameVector.size(); i++) { - nameIndex->at(i) = currentNameIndex; - currentNameIndex += nameVector[i].length(); - } - nameIndex->at(nameVector.size()) = currentNameIndex; - ofstream nameOutFile(name.c_str(), ios::binary); - unsigned sizeOfNameIndex = nameIndex->size(); - nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned)); + switch(eit->direction) + { + case _Way::notSure: + fout << startit->first << " " << targetit->first << " " << intDist << " " << 0 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; + break; + case _Way::oneway: + fout << startit->first << " " << targetit->first << " " << intDist << " " << 1 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; + break; + case _Way::bidirectional: + fout << startit->first << " " << targetit->first << " " << intDist << " " << 0 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; + break; + case _Way::opposite: + fout << startit->first << " " << targetit->first << " " << intDist << " " << 1 << " " << intWeight << " " << eit->type << " " << eit->nameID << "\n"; + break; + default: + assert(false); + break; + } + } + fout.close(); - for(int i = 0; i < nameIndex->size(); i++) { - nameOutFile.write((char *)&(nameIndex->at(i)), sizeof(unsigned)); - } - for(int i = 0; i < nameVector.size(); i++){ - nameOutFile << nameVector[i]; - } + name.append(".names"); + cout << "ok, after " << get_timestamp() - time << "s" << endl; + time = get_timestamp(); + cout << "writing street name index ..." << flush; - nameOutFile.close(); - delete nameIndex; - cout << "ok, after " << get_timestamp() - time << "s" << endl; + vector * nameIndex = new vector(nameVector.size()+1, 0); + unsigned currentNameIndex = 0; + for(int i = 0; i < nameVector.size(); i++) { + nameIndex->at(i) = currentNameIndex; + currentNameIndex += nameVector[i].length(); + } + nameIndex->at(nameVector.size()) = currentNameIndex; + ofstream nameOutFile(name.c_str(), ios::binary); + unsigned sizeOfNameIndex = nameIndex->size(); + nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned)); - } catch ( const std::exception& e ) { - cerr << "Caught Execption:" << e.what() << endl; - return false; - } + for(int i = 0; i < nameIndex->size(); i++) { + nameOutFile.write((char *)&(nameIndex->at(i)), sizeof(unsigned)); + } + for(int i = 0; i < nameVector.size(); i++){ + nameOutFile << nameVector[i]; + } - cout << endl << "Statistics:" << endl; - cout << "-----------" << endl; - cout << "Usable Nodes: " << confirmedNodes.size() << endl; - cout << "Usable Ways : " << confirmedEdges.size() << endl; + nameOutFile.close(); + delete nameIndex; + cout << "ok, after " << get_timestamp() - time << "s" << endl; - SignalNodes.clear(); - usedNodes.clear(); - allNodes.clear(); - confirmedNodes.clear(); - allEdges.clear(); - confirmedEdges.clear(); - nameVector.clear(); - xmlFreeTextReader(inputReader); - delete nodeMap; - delete stringMap; - cout << "finished." << endl; - return 0; + } catch ( const std::exception& e ) { + cerr << "Caught Execption:" << e.what() << endl; + return false; + } + + cout << endl << "Statistics:" << endl; + cout << "-----------" << endl; + cout << "Usable Nodes: " << confirmedNodes.size() << endl; + cout << "Usable Ways : " << confirmedEdges.size() << endl; + + SignalNodes.clear(); + usedNodes.clear(); + allNodes.clear(); + confirmedNodes.clear(); + allEdges.clear(); + confirmedEdges.clear(); + nameVector.clear(); + xmlFreeTextReader(inputReader); + delete nodeMap; + delete stringMap; + cout << "finished." << endl; + return 0; } diff --git a/routed.cpp b/routed.cpp index def5d65f0..9d2a9ea32 100644 --- a/routed.cpp +++ b/routed.cpp @@ -16,132 +16,84 @@ You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. - */ +*/ -#include -#include -#include #include -#include -#include -#include #ifdef _OPENMP #include #endif -#include "typedefs.h" - -#include #include #include -#include "HttpServer/server.h" -#include "Contractor/GraphLoader.h" -#include "DataStructures/StaticGraph.h" + +#include "Server/ServerConfiguration.h" +#include "Server/ServerFactory.h" + +#include "Plugins/HelloWorldPlugin.h" +#include "Plugins/LocatePlugin.h" +#include "Plugins/RoutePlugin.h" +#include "Util/InputFileUtil.h" using namespace std; -typedef ContractionCleanup::Edge::EdgeData EdgeData; -typedef StaticGraph::InputEdge GridEdge; -typedef http::server > server; +typedef http::RequestHandler RequestHandler; -/* - * TODO: Description of command line arguments - */ int main (int argc, char *argv[]) { - if(argc < 6) - { - cerr << "Correct usage:" << endl << argv[0] << " " << endl; - exit(-1); - } + if(testDataFiles(argc, argv)==false) { + std::cerr << "[error] at least one data file name seems to be bogus!" << std::endl; + exit(-1); + } - ifstream hsgrInStream(argv[1], ios::binary); - ifstream nodesInStream(argv[2], ios::binary); - NodeInformationHelpDesk * nodeInfoHelper = new NodeInformationHelpDesk(argv[3], argv[4]); + try { + std::cout << "[server] starting up engines" << std::endl; + int sig = 0; + sigset_t new_mask; + sigset_t old_mask; + sigfillset(&new_mask); + pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); - double time = get_timestamp(); - cout << "deserializing edge data from " << argv[1] << " ..." << flush; + ServerConfiguration serverConfig("server.ini"); + Server * s = ServerFactory::CreateServer(serverConfig); + RequestHandler * h = s->GetRequestHandlerPtr(); - std::vector< GridEdge> * edgeList = new std::vector< GridEdge>(); - readHSGRFromStream(hsgrInStream, edgeList); - hsgrInStream.close(); - cout << "in " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); - cout << "deserializing node map and building nearest neighbor grid ..." << flush; - nodeInfoHelper->initNNGrid(nodesInStream); - cout << "in " << get_timestamp() - time << "s" << endl; - StaticGraph * graph = new StaticGraph(nodeInfoHelper->getNumberOfNodes()-1, *edgeList); - delete edgeList; - time = get_timestamp(); - cout << "deserializing street names ..." << flush; - ifstream namesInStream(argv[5], ios::binary); - unsigned size = 0; - namesInStream.read((char *)&size, sizeof(unsigned)); - vector * nameIndex = new vector(size, 0); - vector * names = new vector(); - for(int i = 0; iat(i)), sizeof(unsigned)); + BasePlugin * helloWorld = new HelloWorldPlugin(); + h->RegisterPlugin(helloWorld); - for(int i = 0; iat(i+1) - nameIndex->at(i); j++){ - char c; - namesInStream.read(&c, sizeof(char)); - tempString.append(1, c); - } - names->push_back(tempString); - tempString = ""; - } - delete nameIndex; + BasePlugin * locate = new LocatePlugin( + serverConfig.GetParameter("ramIndex"), + serverConfig.GetParameter("fileIndex"), + serverConfig.GetParameter("nodesData")); + h->RegisterPlugin(locate); - namesInStream.close(); - cout << "in " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); + BasePlugin * route = new RoutePlugin( + serverConfig.GetParameter("hsgrData"), + serverConfig.GetParameter("ramIndex"), + serverConfig.GetParameter("fileIndex"), + serverConfig.GetParameter("nodesData"), + serverConfig.GetParameter("namesData")); + h->RegisterPlugin(route); - cout << "constructing search graph ..." << flush; + boost::thread t(boost::bind(&Server::Run, s)); - SearchEngine > * sEngine = new SearchEngine >(graph, nodeInfoHelper, names); - cout << "in " << get_timestamp() - time << "s" << endl; - time = get_timestamp(); - - try { - // Block all signals for background thread. - sigset_t new_mask; - sigfillset(&new_mask); - sigset_t old_mask; - pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); - - cout << "starting web server ..." << flush; - // Run server in background thread. - server s("0.0.0.0", "5000", omp_get_num_procs(), sEngine); - boost::thread t(boost::bind(&server::run, &s)); - cout << "ok" << endl; - - // Restore previous signals. - pthread_sigmask(SIG_SETMASK, &old_mask, 0); - - // Wait for signal indicating time to shut down. - sigset_t wait_mask; - sigemptyset(&wait_mask); - sigaddset(&wait_mask, SIGINT); - sigaddset(&wait_mask, SIGQUIT); - sigaddset(&wait_mask, SIGTERM); - pthread_sigmask(SIG_BLOCK, &wait_mask, 0); - int sig = 0; - sigwait(&wait_mask, &sig); - // Stop the server. - s.stop(); - t.join(); - } - catch (std::exception& e) - { - std::cerr << "exception: " << e.what() << "\n"; - } - cout << "graceful shutdown after " << get_timestamp() - time << "s" << endl; - delete names; - delete sEngine; - delete graph; - delete nodeInfoHelper; - return 0; + sigset_t wait_mask; + pthread_sigmask(SIG_SETMASK, &old_mask, 0); + sigemptyset(&wait_mask); + sigaddset(&wait_mask, SIGINT); + sigaddset(&wait_mask, SIGQUIT); + sigaddset(&wait_mask, SIGTERM); + pthread_sigmask(SIG_BLOCK, &wait_mask, 0); + std::cout << "[server] running and waiting for requests" << std::endl; + sigwait(&wait_mask, &sig); + std::cout << std::endl << "[server] shutting down" << std::endl; + s->Stop(); + t.join(); + delete helloWorld; + delete locate; + delete s; + } catch (std::exception& e) { + std::cerr << "[fatal error] exception: " << e.what() << std::endl; + } + return 0; } diff --git a/server.ini b/server.ini new file mode 100644 index 000000000..fbf0108d2 --- /dev/null +++ b/server.ini @@ -0,0 +1,9 @@ +Threads = 8 +IP = 0.0.0.0 +Port = 5000 + +hsgrData=/opt/osm/germany.osrm.hsgr +nodesData=/opt/osm/germany.osrm.nodes +ramIndex=/opt/osm/germany.osrm.ramIndex +fileIndex=/opt/osm/germany.osrm.fileIndex +namesData=/opt/osm/germany.osrm.names diff --git a/typedefs.h b/typedefs.h index fb0b487fa..898622a05 100644 --- a/typedefs.h +++ b/typedefs.h @@ -52,11 +52,11 @@ static const EdgeID SPECIAL_EDGEID = UINT_MAX; typedef NodeCoords NodeInfo; #include "DataStructures/Util.h" #include "DataStructures/NodeInformationHelpDesk.h" -#include "Contractor/BinaryHeap.h" +#include "DataStructures/BinaryHeap.h" #include "Contractor/Contractor.h" #include "Contractor/ContractionCleanup.h" typedef ContractionCleanup::Edge::EdgeData EdgeData; #include "DataStructures/DynamicGraph.h" -#include "Contractor/SearchEngine.h" +//#include "Contractor/SearchEngine.h" #endif /* TYPEDEFS_H_ */