diff --git a/CMakeLists.txt b/CMakeLists.txt index 0019c8d1a..3de4c4f13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ file(GLOB PrepareGlob Contractor/*.cpp) set(PrepareSources createHierarchy.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources}) -file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp) +file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp DataStructures/SearchEngine*.cpp) set(RoutedSources routed.cpp ${RoutedGlob}) add_executable(osrm-routed ${RoutedSources}) set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED) diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index b9059ca62..35d2aa29e 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -20,17 +20,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef CONTRACTOR_H_INCLUDED #define CONTRACTOR_H_INCLUDED -#include -#include -#include - -#include -#include - -#include -#include -#include -#include #include "TemporaryStorage.h" #include "../DataStructures/BinaryHeap.h" @@ -42,6 +31,19 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../Util/OpenMPWrapper.h" #include "../Util/StringUtil.h" +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + class Contractor { private: @@ -119,7 +121,7 @@ public: newEdge.target = diter->target(); newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward()); - assert( newEdge.data.distance > 0 ); + BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" ); #ifndef NDEBUG if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) { WARN("Edge weight large -> " << newEdge.data.distance); @@ -232,8 +234,9 @@ public: //initialize the variables #pragma omp parallel for schedule ( guided ) - for ( int x = 0; x < ( int ) numberOfNodes; ++x ) + for ( int x = 0; x < ( int ) numberOfNodes; ++x ) { remainingNodes[x].id = x; + } std::cout << "initializing elimination PQ ..." << std::flush; #pragma omp parallel @@ -247,7 +250,7 @@ public: std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush; bool flushedContractor = false; - while ( numberOfContractedNodes < numberOfNodes ) { + while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) { if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){ DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush; @@ -282,7 +285,6 @@ public: //walk over all nodes for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) { - //INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes()); const NodeID start = i; for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) { _DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge); @@ -301,8 +303,14 @@ public: newEdge.target = newNodeIDFromOldNodeIDMap[target]; newEdge.data = data; newEdge.data.originalViaNodeID = true; - assert(UINT_MAX != newNodeIDFromOldNodeIDMap[start] ); - assert(UINT_MAX != newNodeIDFromOldNodeIDMap[target]); + BOOST_ASSERT_MSG( + UINT_MAX != newNodeIDFromOldNodeIDMap[start], + "new start id not resolveable" + ); + BOOST_ASSERT_MSG( + UINT_MAX != newNodeIDFromOldNodeIDMap[target], + "new target id not resolveable" + ); newSetOfEdges.push_back(newEdge); } } @@ -311,8 +319,6 @@ public: tempStorage.seek(temporaryStorageSlotID, initialFilePosition); tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); - // INFO("Flushed " << numberOfTemporaryEdges << " edges to disk"); - //Delete map from old NodeIDs to new ones. std::vector().swap(newNodeIDFromOldNodeIDMap); @@ -438,38 +444,48 @@ public: Percent p (_graph->GetNumberOfNodes()); INFO("Getting edges of minimized graph"); NodeID numberOfNodes = _graph->GetNumberOfNodes(); - if(oldNodeIDFromNewNodeIDMap.size()) { + if(_graph->GetNumberOfNodes()) { for ( NodeID node = 0; node < numberOfNodes; ++node ) { p.printStatus(node); for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) { const NodeID target = _graph->GetTarget( edge ); const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge ); Edge newEdge; - newEdge.source = oldNodeIDFromNewNodeIDMap[node]; - newEdge.target = oldNodeIDFromNewNodeIDMap[target]; - assert(UINT_MAX != newEdge.source); - assert(UINT_MAX != newEdge.target); - + if(0 != oldNodeIDFromNewNodeIDMap.size()) { + newEdge.source = oldNodeIDFromNewNodeIDMap[node]; + newEdge.target = oldNodeIDFromNewNodeIDMap[target]; + } else { + newEdge.source = node; + newEdge.target = target; + } + BOOST_ASSERT_MSG( + UINT_MAX != newEdge.source, + "Source id invalid" + ); + BOOST_ASSERT_MSG( + UINT_MAX != newEdge.target, + "Target id invalid" + ); newEdge.data.distance = data.distance; newEdge.data.shortcut = data.shortcut; - if(!data.originalViaNodeID) + if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) { newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id]; - else + } else { newEdge.data.id = data.id; - - assert(newEdge.data.id != UINT_MAX); + } + BOOST_ASSERT_MSG( + newEdge.data.id <= INT_MAX, //2^31 + "edge id invalid" + ); newEdge.data.forward = data.forward; newEdge.data.backward = data.backward; edges.push_back( newEdge ); } } } - INFO("Renumbered edges of minimized graph, freeing space"); _graph.reset(); std::vector().swap(oldNodeIDFromNewNodeIDMap); - INFO("Loading temporary edges"); - // std::ifstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary); TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); //Also get the edges from temporary storage unsigned numberOfTemporaryEdges = 0; @@ -494,7 +510,6 @@ public: edges.push_back( newEdge ); } tempStorage.deallocateSlot(temporaryStorageSlotID); - INFO("Hierarchy has " << edges.size() << " edges"); } private: @@ -517,24 +532,27 @@ private: if ( heap.GetData( node ).target ) { ++targetsFound; - if ( targetsFound >= numTargets ) + if ( targetsFound >= numTargets ) { return; + } } //iterate over all edges of node for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) { const _ContractorEdgeData& data = _graph->GetEdgeData( edge ); - if ( !data.forward ) + if ( !data.forward ){ continue; + } const NodeID to = _graph->GetTarget( edge ); - if(middleNode == to) + if(middleNode == to) { continue; + } const int toDistance = distance + data.distance; //New Node discovered -> Add to Heap + Node Info Storage - if ( !heap.WasInserted( to ) ) + if ( !heap.WasInserted( to ) ) { heap.Insert( to, toDistance, _HeapData(currentHop, false) ); - + } //Found a shorter Path -> Update distance else if ( toDistance < heap.GetKey( to ) ) { heap.DecreaseKey( to, toDistance ); @@ -584,8 +602,9 @@ private: for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); - if ( !outData.forward ) + if ( !outData.forward ) { continue; + } const NodeID target = _graph->GetTarget( outEdge ); const int pathDistance = inData.distance + outData.distance; maxDistance = std::max( maxDistance, pathDistance ); @@ -595,15 +614,16 @@ private: } } - if( Simulate ) + if( Simulate ) { _Dijkstra( maxDistance, numTargets, 1000, data, node ); - else + } else { _Dijkstra( maxDistance, numTargets, 2000, data, node ); - + } for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); - if ( !outData.forward ) + if ( !outData.forward ) { continue; + } const NodeID target = _graph->GetTarget( outEdge ); const int pathDistance = inData.distance + outData.distance; const int distance = heap.GetKey( target ); @@ -643,8 +663,9 @@ private: found = true; break; } - if ( !found ) + if ( !found ) { insertedEdges[insertedEdgesSize++] = insertedEdges[i]; + } } insertedEdges.resize( insertedEdgesSize ); } diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index fce247d31..0f313e339 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -89,7 +89,10 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector& outputEdgeList ) { - GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty"); + BOOST_ASSERT_MSG( + 0 == outputEdgeList.size(), + "Vector is not empty" + ); edgeBasedEdges.swap(outputEdgeList); } @@ -282,7 +285,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State // turnInstruction |= TurnInstructions.AccessRestrictionFlag; // } distance += penalty; - + //distance += heightPenalty; //distance += ComputeTurnPenalty(u, v, w); @@ -328,7 +331,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const { const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); - + if( speedProfile.has_turn_penalty_function ) { try { //call lua profile to compute turn penalty @@ -340,7 +343,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID } else { penalty = 0; } - + if(u == w) { return TurnInstructions.UTurn; } diff --git a/DataStructures/Coordinate.h b/DataStructures/Coordinate.h index c1d9c4167..bc6328991 100644 --- a/DataStructures/Coordinate.h +++ b/DataStructures/Coordinate.h @@ -21,7 +21,10 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef COORDINATE_H_ #define COORDINATE_H_ +#include +#include #include + #include struct _Coordinate { @@ -102,5 +105,4 @@ inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordina return d; } - #endif /* COORDINATE_H_ */ diff --git a/DataStructures/DynamicGraph.h b/DataStructures/DynamicGraph.h index 6730babdf..537ec3d65 100644 --- a/DataStructures/DynamicGraph.h +++ b/DataStructures/DynamicGraph.h @@ -21,18 +21,20 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef DYNAMICGRAPH_H_INCLUDED #define DYNAMICGRAPH_H_INCLUDED -#include +#include "../DataStructures/DeallocatingVector.h" + +#include + #include #include - -#include "../DataStructures/DeallocatingVector.h" +#include template< typename EdgeDataT> class DynamicGraph { public: typedef EdgeDataT EdgeData; - typedef unsigned NodeIterator; - typedef unsigned EdgeIterator; + typedef uint32_t NodeIterator; + typedef uint32_t EdgeIterator; class InputEdge { public: @@ -47,16 +49,16 @@ class DynamicGraph { }; //Constructs an empty graph with a given number of nodes. - DynamicGraph( int nodes ) : m_numNodes(nodes), m_numEdges(0) { + DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) { m_nodes.reserve( m_numNodes ); m_nodes.resize( m_numNodes ); m_edges.reserve( m_numNodes * 1.1 ); m_edges.resize( m_numNodes ); } + template - DynamicGraph( const int nodes, const ContainerT &graph ) - { + DynamicGraph( const int32_t nodes, const ContainerT &graph ) { m_numNodes = nodes; m_numEdges = ( EdgeIterator ) graph.size(); m_nodes.reserve( m_numNodes +1); @@ -80,7 +82,10 @@ class DynamicGraph { for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) { m_edges[i].target = graph[edge].target; m_edges[i].data = graph[edge].data; - GUARANTEE(graph[edge].data.distance > 0, "edge: " << edge << "(" << graph[edge].source << "," << graph[edge].target << ")=" << graph[edge].data.distance); + BOOST_ASSERT_MSG( + graph[edge].data.distance > 0, + "edge distance invalid" + ); ++edge; } } @@ -88,17 +93,15 @@ class DynamicGraph { ~DynamicGraph(){ } - unsigned GetNumberOfNodes() const - { + uint32_t GetNumberOfNodes() const { return m_numNodes; } - unsigned GetNumberOfEdges() const - { + uint32_t GetNumberOfEdges() const { return m_numEdges; } - unsigned GetOutDegree( const NodeIterator n ) const { + uint32_t GetOutDegree( const NodeIterator n ) const { return m_nodes[n].edges; } @@ -133,7 +136,7 @@ class DynamicGraph { m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges]; } else { EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size(); - unsigned newSize = node.edges * 1.1 + 2; + uint32_t newSize = node.edges * 1.1 + 2; EdgeIterator requiredCapacity = newSize + m_edges.size(); EdgeIterator oldCapacity = m_edges.capacity(); if ( requiredCapacity >= oldCapacity ) { @@ -162,15 +165,15 @@ class DynamicGraph { Node &node = m_nodes[source]; --m_numEdges; --node.edges; - const unsigned last = node.firstEdge + node.edges; + const uint32_t last = node.firstEdge + node.edges; //swap with last edge m_edges[e] = m_edges[last]; makeDummy( last ); } //removes all edges (source,target) - int DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) { - int deleted = 0; + int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) { + int32_t deleted = 0; for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) { if ( m_edges[i].target == target ) { do { @@ -212,7 +215,7 @@ class DynamicGraph { //index of the first edge EdgeIterator firstEdge; //amount of edges - unsigned edges; + uint32_t edges; }; struct Edge { diff --git a/DataStructures/SearchEngine.cpp b/DataStructures/SearchEngine.cpp new file mode 100644 index 000000000..2a538a7ac --- /dev/null +++ b/DataStructures/SearchEngine.cpp @@ -0,0 +1,89 @@ +/* + 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. + */ + +#include "SearchEngine.h" + +SearchEngine::SearchEngine( + QueryGraph * g, + NodeInformationHelpDesk * nh, + std::vector & n + ) : + _queryData(g, nh, n), + shortestPath(_queryData), + alternativePaths(_queryData) + {} + SearchEngine::~SearchEngine() {} + +void SearchEngine::GetCoordinatesForNodeID( + NodeID id, + _Coordinate& result + ) const { + result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id); + result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id); +} + +void SearchEngine::FindPhantomNodeForCoordinate( + const _Coordinate & location, + PhantomNode & result, + const unsigned zoomLevel + ) const { + _queryData.nodeHelpDesk->FindPhantomNodeForCoordinate( + location, + result, zoomLevel + ); +} + +NodeID SearchEngine::GetNameIDForOriginDestinationNodeID( + const NodeID s, + const NodeID t + ) const { + if(s == t){ + return 0; + } + EdgeID e = _queryData.graph->FindEdge(s, t); + if(e == UINT_MAX) { + e = _queryData.graph->FindEdge( t, s ); + } + if(UINT_MAX == e) { + return 0; + } + assert(e != UINT_MAX); + const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e); + return ed.id; +} + +std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const { + bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0); + if (is_name_invalid) { + return std::string(""); + } + + return HTMLEntitize(_queryData.names.at(nameID)); +} + +SearchEngineHeapPtr SearchEngineData::forwardHeap; +SearchEngineHeapPtr SearchEngineData::backwardHeap; + +SearchEngineHeapPtr SearchEngineData::forwardHeap2; +SearchEngineHeapPtr SearchEngineData::backwardHeap2; + +SearchEngineHeapPtr SearchEngineData::forwardHeap3; +SearchEngineHeapPtr SearchEngineData::backwardHeap3; + diff --git a/DataStructures/SearchEngine.h b/DataStructures/SearchEngine.h index 505d3f905..64d273bb0 100644 --- a/DataStructures/SearchEngine.h +++ b/DataStructures/SearchEngine.h @@ -21,152 +21,48 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef SEARCHENGINE_H_ #define SEARCHENGINE_H_ -#include -#include -#include "SimpleStack.h" - -#include - -#include "BinaryHeap.h" +#include "Coordinate.h" #include "NodeInformationHelpDesk.h" #include "PhantomNodes.h" +#include "QueryEdge.h" +#include "SearchEngineData.h" #include "../RoutingAlgorithms/AlternativePathRouting.h" -#include "../RoutingAlgorithms/BasicRoutingInterface.h" #include "../RoutingAlgorithms/ShortestPathRouting.h" #include "../Util/StringUtil.h" #include "../typedefs.h" -struct _HeapData { - NodeID parent; - _HeapData( NodeID p ) : parent(p) { } -}; +#include +#include +#include -typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage > QueryHeapType; -typedef boost::thread_specific_ptr SearchEngineHeapPtr; - -template -struct SearchEngineData { - typedef GraphT Graph; - typedef QueryHeapType QueryHeap; - SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) :graph(g), nodeHelpDesk(nh), names(n) {} - const GraphT * graph; - NodeInformationHelpDesk * nodeHelpDesk; - std::vector & names; - static SearchEngineHeapPtr forwardHeap; - static SearchEngineHeapPtr backwardHeap; - static SearchEngineHeapPtr forwardHeap2; - static SearchEngineHeapPtr backwardHeap2; - static SearchEngineHeapPtr forwardHeap3; - static SearchEngineHeapPtr backwardHeap3; - - inline void InitializeOrClearFirstThreadLocalStorage() { - if(!forwardHeap.get()) { - forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); - } - else - forwardHeap->Clear(); - - if(!backwardHeap.get()) { - backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); - } - else - backwardHeap->Clear(); - } - - inline void InitializeOrClearSecondThreadLocalStorage() { - if(!forwardHeap2.get()) { - forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); - } - else - forwardHeap2->Clear(); - - if(!backwardHeap2.get()) { - backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); - } - else - backwardHeap2->Clear(); - } - - inline void InitializeOrClearThirdThreadLocalStorage() { - if(!forwardHeap3.get()) { - forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); - } - else - forwardHeap3->Clear(); - - if(!backwardHeap3.get()) { - backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); - } - else - backwardHeap3->Clear(); - } -}; - -template class SearchEngine { private: - typedef SearchEngineData SearchEngineDataT; - SearchEngineDataT _queryData; + SearchEngineData _queryData; - inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;} public: - ShortestPathRouting shortestPath; - AlternativeRouting alternativePaths; + ShortestPathRouting shortestPath; + AlternativeRouting alternativePaths; - SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector & n) : - _queryData(g, nh, n), - shortestPath(_queryData), - alternativePaths(_queryData) - {} - ~SearchEngine() {} + SearchEngine( + QueryGraph * g, + NodeInformationHelpDesk * nh, + std::vector & n + ); + ~SearchEngine(); - inline void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const { - result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id); - result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id); - } + void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const; - inline void FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const { - _queryData.nodeHelpDesk->FindRoutingStarts(start, target, routingStarts); - } + void FindPhantomNodeForCoordinate( + const _Coordinate & location, + PhantomNode & result, + unsigned zoomLevel + ) const; - inline void FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result, unsigned zoomLevel) const { - _queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(location, result, zoomLevel); - } - - inline NodeID GetNameIDForOriginDestinationNodeID(const NodeID s, const NodeID t) const { - if(s == t) - return 0; - - EdgeID e = _queryData.graph->FindEdge(s, t); - if(e == UINT_MAX) - e = _queryData.graph->FindEdge( t, s ); - if(UINT_MAX == e) { - return 0; - } - assert(e != UINT_MAX); - const EdgeData ed = _queryData.graph->GetEdgeData(e); - return ed.via; - } - - inline std::string GetEscapedNameForNameID(const unsigned nameID) const { - return ((nameID >= _queryData.names.size() || nameID == 0) ? std::string("") : HTMLEntitize(_queryData.names.at(nameID))); - } - - inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const { - const unsigned nameID = _queryData.graph->GetEdgeData(edgeID).nameID1; - return GetEscapedNameForNameID(nameID); - } + NodeID GetNameIDForOriginDestinationNodeID( + const NodeID s, const NodeID t) const; + std::string GetEscapedNameForNameID(const unsigned nameID) const; }; -template SearchEngineHeapPtr SearchEngineData::forwardHeap; -template SearchEngineHeapPtr SearchEngineData::backwardHeap; - -template SearchEngineHeapPtr SearchEngineData::forwardHeap2; -template SearchEngineHeapPtr SearchEngineData::backwardHeap2; - -template SearchEngineHeapPtr SearchEngineData::forwardHeap3; -template SearchEngineHeapPtr SearchEngineData::backwardHeap3; - #endif /* SEARCHENGINE_H_ */ diff --git a/DataStructures/SearchEngineData.cpp b/DataStructures/SearchEngineData.cpp new file mode 100644 index 000000000..77492f69e --- /dev/null +++ b/DataStructures/SearchEngineData.cpp @@ -0,0 +1,60 @@ +/* + 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. + */ + +#include "SearchEngineData.h" + +void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() { + if(!forwardHeap.get()) { + forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); + } else { + forwardHeap->Clear(); + } + if(!backwardHeap.get()) { + backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); + } else { + backwardHeap->Clear(); + } +} + +void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() { + if(!forwardHeap2.get()) { + forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); + } else { + forwardHeap2->Clear(); + } + if(!backwardHeap2.get()) { + backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); + } else { + backwardHeap2->Clear(); + } +} + +void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() { + if(!forwardHeap3.get()) { + forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); + } else { + forwardHeap3->Clear(); + } + if(!backwardHeap3.get()) { + backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes())); + } else { + backwardHeap3->Clear(); + } +} diff --git a/DataStructures/SearchEngineData.h b/DataStructures/SearchEngineData.h new file mode 100644 index 000000000..f9a2623a0 --- /dev/null +++ b/DataStructures/SearchEngineData.h @@ -0,0 +1,60 @@ +/* + 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. + */ + +#include "BinaryHeap.h" +#include "QueryEdge.h" +#include "NodeInformationHelpDesk.h" +#include "StaticGraph.h" + +#include "../typedefs.h" + +#include + +#include +#include + +struct _HeapData { + NodeID parent; + _HeapData( NodeID p ) : parent(p) { } +}; +typedef StaticGraph QueryGraph; +typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage > QueryHeapType; +typedef boost::thread_specific_ptr SearchEngineHeapPtr; + +struct SearchEngineData { + typedef QueryGraph Graph; + typedef QueryHeapType QueryHeap; + SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector & n) :graph(g), nodeHelpDesk(nh), names(n) {} + const QueryGraph * graph; + NodeInformationHelpDesk * nodeHelpDesk; + std::vector & names; + static SearchEngineHeapPtr forwardHeap; + static SearchEngineHeapPtr backwardHeap; + static SearchEngineHeapPtr forwardHeap2; + static SearchEngineHeapPtr backwardHeap2; + static SearchEngineHeapPtr forwardHeap3; + static SearchEngineHeapPtr backwardHeap3; + + void InitializeOrClearFirstThreadLocalStorage(); + + void InitializeOrClearSecondThreadLocalStorage(); + + void InitializeOrClearThirdThreadLocalStorage(); +}; diff --git a/Descriptors/BaseDescriptor.h b/Descriptors/BaseDescriptor.h index 6a49bd81b..2ead8bdae 100644 --- a/Descriptors/BaseDescriptor.h +++ b/Descriptors/BaseDescriptor.h @@ -28,8 +28,9 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include "../typedefs.h" -#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/HashTable.h" +#include "../DataStructures/PhantomNodes.h" +#include "../DataStructures/SearchEngine.h" #include "../Util/StringUtil.h" #include "../Plugins/RawRouteData.h" @@ -42,13 +43,12 @@ struct _DescriptorConfig { unsigned short z; }; -template class BaseDescriptor { public: BaseDescriptor() { } //Maybe someone can explain the pure virtual destructor thing to me (dennis) virtual ~BaseDescriptor() { } - virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) = 0; + virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0; virtual void SetConfig(const _DescriptorConfig & config) = 0; }; diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp index 46a1d5b82..b1f2f8538 100644 --- a/Descriptors/DescriptionFactory.cpp +++ b/Descriptors/DescriptionFactory.cpp @@ -82,7 +82,7 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) { pc.printUnencodedString(pathDescription, output); } -void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) { +void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) { if(0 == pathDescription.size()) return; diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h index 52adc2713..911aae7de 100644 --- a/Descriptors/DescriptionFactory.h +++ b/Descriptors/DescriptionFactory.h @@ -27,7 +27,6 @@ #include "../Algorithms/DouglasPeucker.h" #include "../Algorithms/PolylineCompressor.h" #include "../DataStructures/Coordinate.h" -#include "../DataStructures/QueryEdge.h" #include "../DataStructures/SearchEngine.h" #include "../DataStructures/SegmentInformation.h" #include "../DataStructures/TurnInstructions.h" @@ -40,8 +39,6 @@ class DescriptionFactory { PolylineCompressor pc; PhantomNode startPhantom, targetPhantom; - typedef SearchEngine > SearchEngineT; - double DegreeToRadian(const double degree) const; double RadianToDegree(const double degree) const; public: @@ -73,7 +70,7 @@ public: void SetStartSegment(const PhantomNode & startPhantom); void SetEndSegment(const PhantomNode & startPhantom); void AppendEncodedPolylineString(std::string & output, bool isEncoded); - void Run(const SearchEngineT &sEngine, const unsigned zoomLevel); + void Run(const SearchEngine &sEngine, const unsigned zoomLevel); }; #endif /* DESCRIPTIONFACTORY_H_ */ diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 5096468fb..1d3389ade 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -24,8 +24,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include "BaseDescriptor.h" -template -class GPXDescriptor : public BaseDescriptor{ +class GPXDescriptor : public BaseDescriptor{ private: _DescriptorConfig config; _Coordinate current; @@ -33,7 +32,7 @@ private: std::string tmp; public: void SetConfig(const _DescriptorConfig& c) { config = c; } - void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) { + void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) { reply.content += (""); reply.content += " -class JSONDescriptor : public BaseDescriptor{ +class JSONDescriptor : public BaseDescriptor{ private: _DescriptorConfig config; DescriptionFactory descriptionFactory; @@ -68,7 +67,7 @@ public: JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {} void SetConfig(const _DescriptorConfig & c) { config = c; } - void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) { + void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) { WriteHeaderToOutput(reply.content); @@ -246,7 +245,7 @@ public: reply.content += "}"; } - void GetRouteNames(std::vector & shortestSegments, std::vector & alternativeSegments, const SearchEngineT &sEngine, RouteNames & routeNames) { + void GetRouteNames(std::vector & shortestSegments, std::vector & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) { /*** extract names for both alternatives ***/ Segment shortestSegment1, shortestSegment2; @@ -304,7 +303,7 @@ public: "\"status\":"; } - inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngineT &sEngine, std::vector & segmentVector) { + inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector & segmentVector) { //Segment information has following format: //["instruction","streetname",length,position,time,"length","earth_direction",azimuth] //Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5] diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index b2476bc86..2cb2baf22 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -257,8 +257,8 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool)); fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool)); fout.write((char*)&edgeIT->isContraFlow, sizeof(bool)); + ++usedEdgeCounter; } - ++usedEdgeCounter; ++edgeIT; } } diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index d1e5bbc08..8249d991b 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -52,14 +52,14 @@ private: StaticGraph * graph; HashTable descriptorTable; std::string pluginDescriptorString; - SearchEngine > * searchEngine; + SearchEngine * searchEnginePtr; public: ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) { nodeHelpDesk = objects->nodeHelpDesk; graph = objects->graph; - searchEngine = new SearchEngine >(graph, nodeHelpDesk, names); + searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names); descriptorTable.Set("", 0); //default descriptor descriptorTable.Set("json", 0); @@ -67,7 +67,7 @@ public: } virtual ~ViaRoutePlugin() { - delete searchEngine; + delete searchEnginePtr; } std::string GetDescriptor() const { return pluginDescriptorString; } @@ -101,7 +101,7 @@ public: } } // INFO("Brute force lookup of coordinate " << i); - searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel); + searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel); } for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) { @@ -112,10 +112,10 @@ public: } if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) { // INFO("Checking for alternative paths"); - searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute); + searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute); } else { - searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute); + searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute); } @@ -125,7 +125,7 @@ public: reply.status = http::Reply::ok; //TODO: Move to member as smart pointer - BaseDescriptor > > * desc; + BaseDescriptor * desc; if("" != routeParameters.jsonpParameter) { reply.content += routeParameters.jsonpParameter; reply.content += "("; @@ -140,15 +140,15 @@ public: switch(descriptorType){ case 0: - desc = new JSONDescriptor > >(); + desc = new JSONDescriptor(); break; case 1: - desc = new GPXDescriptor > >(); + desc = new GPXDescriptor(); break; default: - desc = new JSONDescriptor > >(); + desc = new JSONDescriptor(); break; } @@ -161,7 +161,7 @@ public: // INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size()); desc->SetConfig(descriptorConfig); - desc->Run(reply, rawRoute, phantomNodes, *searchEngine); + desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr); if("" != routeParameters.jsonpParameter) { reply.content += ")\n"; } diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index f329c697b..a42a95e35 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -23,13 +23,15 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef BASICROUTINGINTERFACE_H_ #define BASICROUTINGINTERFACE_H_ +#include "../Plugins/RawRouteData.h" +#include "../Util/ContainerUtils.h" + #include #include #include -#include "../Plugins/RawRouteData.h" -#include "../Util/ContainerUtils.h" +#include template class BasicRoutingInterface : boost::noncopyable{ diff --git a/Server/DataStructures/QueryObjectsStorage.cpp b/Server/DataStructures/QueryObjectsStorage.cpp index 325cdb97d..df15f532c 100644 --- a/Server/DataStructures/QueryObjectsStorage.cpp +++ b/Server/DataStructures/QueryObjectsStorage.cpp @@ -22,14 +22,27 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "QueryObjectsStorage.h" #include "../../Util/GraphLoader.h" -QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath) { +QueryObjectsStorage::QueryObjectsStorage( + std::string hsgrPath, + std::string ramIndexPath, + std::string fileIndexPath, + std::string nodesPath, + std::string edgesPath, + std::string namesPath, + std::string timestampPath +) { INFO("loading graph data"); std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary); if(!hsgrInStream) { ERR(hsgrPath << " not found"); } //Deserialize road network graph std::vector< QueryGraph::_StrNode> nodeList; std::vector< QueryGraph::_StrEdge> edgeList; - const int n = readHSGRFromStream(hsgrInStream, nodeList, edgeList, &checkSum); + const int n = readHSGRFromStream( + hsgrInStream, + nodeList, + edgeList, + &checkSum + ); INFO("Data checksum is " << checkSum); graph = new QueryGraph(nodeList, edgeList); @@ -39,7 +52,7 @@ QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIn if(timestampPath.length()) { INFO("Loading Timestamp"); std::ifstream timestampInStream(timestampPath.c_str()); - if(!timestampInStream) { ERR(timestampPath << " not found"); } + if(!timestampInStream) { WARN(timestampPath << " not found"); } getline(timestampInStream, timestamp); timestampInStream.close(); diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index 66401548c..5dc50f888 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -21,6 +21,15 @@ or see http://www.gnu.org/licenses/agpl.txt. #ifndef GRAPHLOADER_H #define GRAPHLOADER_H +#include "../DataStructures/ImportNode.h" +#include "../DataStructures/ImportEdge.h" +#include "../DataStructures/NodeCoords.h" +#include "../DataStructures/Restriction.h" +#include "../typedefs.h" + +#include +#include + #include #include @@ -30,19 +39,11 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include -#include - -#include "../DataStructures/ImportNode.h" -#include "../DataStructures/ImportEdge.h" -#include "../DataStructures/NodeCoords.h" -#include "../DataStructures/Restriction.h" -#include "../typedefs.h" - typedef boost::unordered_map ExternalNodeMap; template struct _ExcessRemover { - inline bool operator()( EdgeT & edge ) const { + inline bool operator()( const EdgeT & edge ) const { return edge.source() == UINT_MAX; } }; @@ -116,9 +117,9 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL in.read((char*)&isAccessRestricted, sizeof(bool)); in.read((char*)&isContraFlow, sizeof(bool)); - GUARANTEE(length > 0, "loaded null length edge" ); - GUARANTEE(weight > 0, "loaded null weight"); - GUARANTEE(0<=dir && dir<=2, "loaded bogus direction"); + BOOST_ASSERT_MSG(length > 0, "loaded null length edge" ); + BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); + BOOST_ASSERT_MSG(0<=dir && dir<=2, "loaded bogus direction"); bool forward = true; bool backward = true; @@ -144,7 +145,9 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL continue; } target = intNodeID->second; - GUARANTEE(source != UINT_MAX && target != UINT_MAX, "nonexisting source or target"); + BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX, + "nonexisting source or target" + ); if(source > target) { std::swap(source, target); diff --git a/Util/LuaUtil.h b/Util/LuaUtil.h index fadf78d6f..3e2e590b9 100644 --- a/Util/LuaUtil.h +++ b/Util/LuaUtil.h @@ -18,14 +18,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ - - #ifndef LUAUTIL_H_ #define LUAUTIL_H_ +extern "C" { + #include + #include + #include +} + +#include + #include #include -#include template void LUA_print(T number) { diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 7156cef32..5da8ecde3 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -18,25 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or see http://www.gnu.org/licenses/agpl.txt. */ -extern "C" { -#include -#include -#include -} -#include - -#include - -#include -#include -#include -#include -#include -#include - #include "Algorithms/IteratorBasedCRC32.h" -#include "Util/OpenMPWrapper.h" -#include "typedefs.h" #include "Contractor/Contractor.h" #include "Contractor/EdgeBasedGraphFactory.h" #include "DataStructures/BinaryHeap.h" @@ -47,7 +29,20 @@ extern "C" { #include "Util/GraphLoader.h" #include "Util/InputFileUtil.h" #include "Util/LuaUtil.h" +#include "Util/OpenMPWrapper.h" #include "Util/StringUtil.h" +#include "typedefs.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include typedef QueryEdge::EdgeData EdgeData; typedef DynamicGraph::InputEdge InputEdge; @@ -61,212 +56,216 @@ std::vector trafficLightNodes; std::vector edgeList; int main (int argc, char *argv[]) { - if(argc < 3) { - ERR("usage: " << std::endl << argv[0] << " []"); - } - - double startupTime = get_timestamp(); - unsigned numberOfThreads = omp_get_num_procs(); - if(testDataFile("contractor.ini")) { - ContractorConfiguration contractorConfig("contractor.ini"); - unsigned rawNumber = stringToInt(contractorConfig.GetParameter("Threads")); - if(rawNumber != 0 && rawNumber <= numberOfThreads) - numberOfThreads = rawNumber; - } - omp_set_num_threads(numberOfThreads); - - INFO("Using restrictions from file: " << argv[2]); - std::ifstream restrictionsInstream(argv[2], std::ios::binary); - if(!restrictionsInstream.good()) { - ERR("Could not access files"); - } - _Restriction restriction; - unsigned usableRestrictionsCounter(0); - restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned)); - inputRestrictions.resize(usableRestrictionsCounter); - restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction)); - restrictionsInstream.close(); - - std::ifstream in; - in.open (argv[1], std::ifstream::in | std::ifstream::binary); - if (!in.is_open()) { - ERR("Cannot open " << argv[1]); - } - - std::string nodeOut(argv[1]); nodeOut += ".nodes"; - std::string edgeOut(argv[1]); edgeOut += ".edges"; - std::string graphOut(argv[1]); graphOut += ".hsgr"; - std::string ramIndexOut(argv[1]); ramIndexOut += ".ramIndex"; - std::string fileIndexOut(argv[1]); fileIndexOut += ".fileIndex"; - - /*** Setup Scripting Environment ***/ - if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) { - ERR("Need profile.lua to apply traffic signal penalty"); - } - - // Create a new lua state - lua_State *myLuaState = luaL_newstate(); - - // Connect LuaBind to this lua state - luabind::open(myLuaState); - - //open utility libraries string library; - luaL_openlibs(myLuaState); - - //adjust lua load path - luaAddScriptFolderToLoadPath( myLuaState, (argc > 3 ? argv[3] : "profile.lua") ); - - // Now call our function in a lua script - INFO("Parsing speedprofile from " << (argc > 3 ? argv[3] : "profile.lua") ); - if(0 != luaL_dofile(myLuaState, (argc > 3 ? argv[3] : "profile.lua") )) { - ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); - } - - EdgeBasedGraphFactory::SpeedProfileProperties speedProfile; - - if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) { - ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); - } - speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1); - - if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) { - ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); - } - speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); - - speedProfile.has_turn_penalty_function = lua_function_exists( myLuaState, "turn_function" ); - - std::vector edgeList; - NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); - in.close(); - INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights"); - if(0 == edgeList.size()) - ERR("The input data is broken. It is impossible to do any turns in this graph"); - - - /*** - * Building an edge-expanded graph from node-based input an turn restrictions - */ - - INFO("Generating edge-expanded graph representation"); - EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile); - std::vector().swap(edgeList); - edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState); - std::vector<_Restriction>().swap(inputRestrictions); - std::vector().swap(bollardNodes); - std::vector().swap(trafficLightNodes); - NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes(); - DeallocatingVector edgeBasedEdgeList; - edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList); - DeallocatingVector nodeBasedEdgeList; - edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList); - delete edgeBasedGraphFactory; - - /*** - * Writing info on original (node-based) nodes - */ - - INFO("writing node map ..."); - std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary); - mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo)); - mapOutFile.close(); - std::vector().swap(internalToExternalNodeMapping); - - double expansionHasFinishedTime = get_timestamp() - startupTime; - - /*** - * Building grid-like nearest-neighbor data structure - */ - - INFO("building grid ..."); - WritableGrid * writeableGrid = new WritableGrid(); - writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut.c_str(), fileIndexOut.c_str()); - delete writeableGrid; - IteratorbasedCRC32 > crc32; - unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() ); - nodeBasedEdgeList.clear(); - INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList); - - /*** - * Contracting the edge-expanded graph - */ - - INFO("initializing contractor"); - Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList ); - double contractionStartedTimestamp(get_timestamp()); - contractor->Run(); - INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec"); - - DeallocatingVector< QueryEdge > contractedEdgeList; - contractor->GetEdges( contractedEdgeList ); - delete contractor; - - /*** - * Sorting contracted edges in a way that the static query graph can read some in in-place. - */ - - INFO("Building Node Array"); - std::sort(contractedEdgeList.begin(), contractedEdgeList.end()); - unsigned numberOfNodes = 0; - unsigned numberOfEdges = contractedEdgeList.size(); - INFO("Serializing compacted graph"); - std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary); - - BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { - if(edge.source > numberOfNodes) { - numberOfNodes = edge.source; + try { + if(argc < 3) { + ERR("usage: " << std::endl << argv[0] << " []"); } - if(edge.target > numberOfNodes) { - numberOfNodes = edge.target; + + double startupTime = get_timestamp(); + unsigned numberOfThreads = omp_get_num_procs(); + if(testDataFile("contractor.ini")) { + ContractorConfiguration contractorConfig("contractor.ini"); + unsigned rawNumber = stringToInt(contractorConfig.GetParameter("Threads")); + if(rawNumber != 0 && rawNumber <= numberOfThreads) + numberOfThreads = rawNumber; } - } - numberOfNodes+=1; + omp_set_num_threads(numberOfThreads); - std::vector< StaticGraph::_StrNode > _nodes; - _nodes.resize( numberOfNodes + 1 ); + INFO("Using restrictions from file: " << argv[2]); + std::ifstream restrictionsInstream(argv[2], std::ios::binary); + if(!restrictionsInstream.good()) { + ERR("Could not access files"); + } + _Restriction restriction; + unsigned usableRestrictionsCounter(0); + restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned)); + inputRestrictions.resize(usableRestrictionsCounter); + restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction)); + restrictionsInstream.close(); - StaticGraph::EdgeIterator edge = 0; - StaticGraph::EdgeIterator position = 0; - for ( StaticGraph::NodeIterator node = 0; node <= numberOfNodes; ++node ) { - StaticGraph::EdgeIterator lastEdge = edge; - while ( edge < numberOfEdges && contractedEdgeList[edge].source == node ) - ++edge; - _nodes[node].firstEdge = position; //=edge - position += edge - lastEdge; //remove - } - ++numberOfNodes; - //Serialize numberOfNodes, nodes - edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned)); - edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned)); - edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph::_StrNode)*(numberOfNodes)); - //Serialize number of Edges - edgeOutFile.write((char*) &position, sizeof(unsigned)); - --numberOfNodes; - edge = 0; - int usedEdgeCounter = 0; - StaticGraph::_StrEdge currentEdge; - for ( StaticGraph::NodeIterator node = 0; node < numberOfNodes; ++node ) { - for ( StaticGraph::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) { - assert(node != contractedEdgeList[edge].target); - currentEdge.target = contractedEdgeList[edge].target; - currentEdge.data = contractedEdgeList[edge].data; - if(currentEdge.data.distance <= 0) { - INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance); - ERR("Failed at edges of node " << node << " of " << numberOfNodes); + std::ifstream in; + in.open (argv[1], std::ifstream::in | std::ifstream::binary); + if (!in.is_open()) { + ERR("Cannot open " << argv[1]); + } + + std::string nodeOut(argv[1]); nodeOut += ".nodes"; + std::string edgeOut(argv[1]); edgeOut += ".edges"; + std::string graphOut(argv[1]); graphOut += ".hsgr"; + std::string ramIndexOut(argv[1]); ramIndexOut += ".ramIndex"; + std::string fileIndexOut(argv[1]); fileIndexOut += ".fileIndex"; + + /*** Setup Scripting Environment ***/ + if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) { + ERR("Need profile.lua to apply traffic signal penalty"); + } + + // Create a new lua state + lua_State *myLuaState = luaL_newstate(); + + // Connect LuaBind to this lua state + luabind::open(myLuaState); + + //open utility libraries string library; + luaL_openlibs(myLuaState); + + //adjust lua load path + luaAddScriptFolderToLoadPath( myLuaState, (argc > 3 ? argv[3] : "profile.lua") ); + + // Now call our function in a lua script + INFO("Parsing speedprofile from " << (argc > 3 ? argv[3] : "profile.lua") ); + if(0 != luaL_dofile(myLuaState, (argc > 3 ? argv[3] : "profile.lua") )) { + ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); + } + + EdgeBasedGraphFactory::SpeedProfileProperties speedProfile; + + if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) { + ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); + } + speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1); + + if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) { + ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block"); + } + speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1); + + speedProfile.has_turn_penalty_function = lua_function_exists( myLuaState, "turn_function" ); + + std::vector edgeList; + NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions); + in.close(); + INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights"); + if(0 == edgeList.size()) + ERR("The input data is broken. It is impossible to do any turns in this graph"); + + + /*** + * Building an edge-expanded graph from node-based input an turn restrictions + */ + + INFO("Generating edge-expanded graph representation"); + EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile); + std::vector().swap(edgeList); + edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState); + std::vector<_Restriction>().swap(inputRestrictions); + std::vector().swap(bollardNodes); + std::vector().swap(trafficLightNodes); + NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes(); + DeallocatingVector edgeBasedEdgeList; + edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList); + DeallocatingVector nodeBasedEdgeList; + edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList); + delete edgeBasedGraphFactory; + + /*** + * Writing info on original (node-based) nodes + */ + + INFO("writing node map ..."); + std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary); + mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo)); + mapOutFile.close(); + std::vector().swap(internalToExternalNodeMapping); + + double expansionHasFinishedTime = get_timestamp() - startupTime; + + /*** + * Building grid-like nearest-neighbor data structure + */ + + INFO("building grid ..."); + WritableGrid * writeableGrid = new WritableGrid(); + writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut.c_str(), fileIndexOut.c_str()); + delete writeableGrid; + IteratorbasedCRC32 > crc32; + unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() ); + nodeBasedEdgeList.clear(); + INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList); + + /*** + * Contracting the edge-expanded graph + */ + + INFO("initializing contractor"); + Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList ); + double contractionStartedTimestamp(get_timestamp()); + contractor->Run(); + INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec"); + + DeallocatingVector< QueryEdge > contractedEdgeList; + contractor->GetEdges( contractedEdgeList ); + delete contractor; + + /*** + * Sorting contracted edges in a way that the static query graph can read some in in-place. + */ + + INFO("Building Node Array"); + std::sort(contractedEdgeList.begin(), contractedEdgeList.end()); + unsigned numberOfNodes = 0; + unsigned numberOfEdges = contractedEdgeList.size(); + INFO("Serializing compacted graph of " << numberOfEdges << " edges"); + std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary); + + BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { + if(edge.source > numberOfNodes) { + numberOfNodes = edge.source; + } + if(edge.target > numberOfNodes) { + numberOfNodes = edge.target; } - //Serialize edges - edgeOutFile.write((char*) ¤tEdge, sizeof(StaticGraph::_StrEdge)); - ++edge; - ++usedEdgeCounter; } - } - double endTime = (get_timestamp() - startupTime); - INFO("Expansion : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec"); - INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec"); + numberOfNodes+=1; - edgeOutFile.close(); - //cleanedEdgeList.clear(); - _nodes.clear(); - INFO("finished preprocessing"); + std::vector< StaticGraph::_StrNode > _nodes; + _nodes.resize( numberOfNodes + 1 ); + + StaticGraph::EdgeIterator edge = 0; + StaticGraph::EdgeIterator position = 0; + for ( StaticGraph::NodeIterator node = 0; node <= numberOfNodes; ++node ) { + StaticGraph::EdgeIterator lastEdge = edge; + while ( edge < numberOfEdges && contractedEdgeList[edge].source == node ) + ++edge; + _nodes[node].firstEdge = position; //=edge + position += edge - lastEdge; //remove + } + ++numberOfNodes; + //Serialize numberOfNodes, nodes + edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned)); + edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned)); + edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph::_StrNode)*(numberOfNodes)); + //Serialize number of Edges + edgeOutFile.write((char*) &position, sizeof(unsigned)); + --numberOfNodes; + edge = 0; + int usedEdgeCounter = 0; + StaticGraph::_StrEdge currentEdge; + for ( StaticGraph::NodeIterator node = 0; node < numberOfNodes; ++node ) { + for ( StaticGraph::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) { + assert(node != contractedEdgeList[edge].target); + currentEdge.target = contractedEdgeList[edge].target; + currentEdge.data = contractedEdgeList[edge].data; + if(currentEdge.data.distance <= 0) { + INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance); + ERR("Failed at edges of node " << node << " of " << numberOfNodes); + } + //Serialize edges + edgeOutFile.write((char*) ¤tEdge, sizeof(StaticGraph::_StrEdge)); + ++edge; + ++usedEdgeCounter; + } + } + double endTime = (get_timestamp() - startupTime); + INFO("Expansion : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec"); + INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec"); + + edgeOutFile.close(); + //cleanedEdgeList.clear(); + _nodes.clear(); + INFO("finished preprocessing"); + } catch (std::exception &e) { + ERR("Exception occured: " << e.what()); + } return 0; } diff --git a/extractor.cpp b/extractor.cpp index 4912c9b67..3beeef510 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -18,12 +18,6 @@ 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 "typedefs.h" #include "Extractor/ExtractorCallbacks.h" #include "Extractor/ExtractionContainers.h" #include "Extractor/ScriptingEnvironment.h" @@ -34,6 +28,13 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "Util/MachineInfo.h" #include "Util/OpenMPWrapper.h" #include "Util/StringUtil.h" +#include "typedefs.h" + +#include +#include +#include + +#include typedef BaseConfiguration ExtractorConfiguration; @@ -84,11 +85,11 @@ int main (int argc, char *argv[]) { } unsigned amountOfRAM = 1; - unsigned installedRAM = GetPhysicalmemory(); + unsigned installedRAM = GetPhysicalmemory(); if(installedRAM < 2048264) { WARN("Machine has less than 2GB RAM."); } - + StringMap stringMap; ExtractionContainers externalMemory; @@ -100,7 +101,7 @@ int main (int argc, char *argv[]) { } else { parser = new XMLParser(argv[1], extractCallBacks, scriptingEnvironment); } - + if(!parser->ReadHeader()) { ERR("Parser not initialized!"); } diff --git a/features/car/shuttle_train.feature b/features/car/shuttle_train.feature index ed2187c27..e58ffa210 100644 --- a/features/car/shuttle_train.feature +++ b/features/car/shuttle_train.feature @@ -3,23 +3,24 @@ Feature: Car - Handle ferryshuttle train routes Background: Given the profile "car" - + Scenario: Car - Use a ferry route Given the node map - | a | b | c | | | - | | | d | | | - | | | e | f | g | - + | a | b | c | | | | + | | | d | | | | + | | | e | f | g | h | + And the ways | nodes | highway | route | bicycle | | abc | primary | | | | cde | | shuttle_train | yes | | ef | primary | | | | fg | | ferry_man | | - + | gh | primary | | no | + When I route I should get | from | to | route | - | a | g | abc,cde,ef | + | a | f | abc,cde,ef | | b | f | abc,cde,ef | | e | c | cde | | e | b | cde,abc | @@ -27,5 +28,6 @@ Feature: Car - Handle ferryshuttle train routes | c | e | cde | | c | f | cde,ef | | f | g | | + | g | h | gh | diff --git a/typedefs.h b/typedefs.h index 32807130e..a962598e9 100644 --- a/typedefs.h +++ b/typedefs.h @@ -35,16 +35,14 @@ or see http://www.gnu.org/licenses/agpl.txt. #include -#define INFO(x) do {std::cout << "[info " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); -#define ERR(x) do {std::cerr << "[error " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl; std::exit(-1);} while(0); -#define WARN(x) do {std::cerr << "[warn " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); +#define INFO(x) do {std::cout << "[i " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); +#define ERR(x) do {std::cerr << "[! " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl; std::exit(-1);} while(0); +#define WARN(x) do {std::cerr << "[? " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); #ifdef NDEBUG #define DEBUG(x) -#define GUARANTEE(x,y) #else -#define DEBUG(x) do {std::cout << "[debug " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); -#define GUARANTEE(x,y) do { {do{ if(false == (x)) { ERR(y) } } while(0);} } while(0); +#define DEBUG(x) do {std::cout << "[d " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0); #endif #ifndef M_PI