From e2c093856c494c813bebd64d22aa7596ad8e1927 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 22 Nov 2013 18:05:41 +0100 Subject: [PATCH 01/29] move Hilbert curve computation in compile unit --- CMakeLists.txt | 4 +- DataStructures/HilbertValue.cpp | 84 +++++++++++++++++++++++++++++++++ DataStructures/HilbertValue.h | 55 ++------------------- 3 files changed, 89 insertions(+), 54 deletions(-) create mode 100644 DataStructures/HilbertValue.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index af8258d5c..223c59217 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,13 +36,13 @@ file(GLOB ExtractorGlob Extractor/*.cpp) set(ExtractorSources extractor.cpp ${ExtractorGlob}) add_executable(osrm-extract ${ExtractorSources} ) -file( GLOB PrepareGlob Contractor/*.cpp ) +file( GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp) set( PrepareSources prepare.cpp ${PrepareGlob} ) add_executable( osrm-prepare ${PrepareSources} ) file(GLOB ServerGlob Server/*.cpp) file(GLOB DescriptorGlob Descriptors/*.cpp) -file(GLOB DatastructureGlob DataStructures/*.cpp) +file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp) file(GLOB AlgorithmGlob Algorithms/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) diff --git a/DataStructures/HilbertValue.cpp b/DataStructures/HilbertValue.cpp new file mode 100644 index 000000000..55427bb92 --- /dev/null +++ b/DataStructures/HilbertValue.cpp @@ -0,0 +1,84 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "HilbertValue.h" + +uint64_t HilbertCode::GetHilbertNumberForCoordinate( + const FixedPointCoordinate & current_coordinate +) { + unsigned location[2]; + location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION); + location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION); + + TransposeCoordinate(location); + const uint64_t result = BitInterleaving(location[0], location[1]); + return result; +} + +uint64_t HilbertCode::BitInterleaving(const uint32_t a, const uint32_t b) { + uint64_t result = 0; + for(int8_t index = 31; index >= 0; --index){ + result |= (a >> index) & 1; + result <<= 1; + result |= (b >> index) & 1; + if(0 != index){ + result <<= 1; + } + } + return result; +} + +void HilbertCode::TransposeCoordinate( uint32_t * X) { + uint32_t M = 1 << (32-1), P, Q, t; + int i; + // Inverse undo + for( Q = M; Q > 1; Q >>= 1 ) { + P=Q-1; + for( i = 0; i < 2; ++i ) { + if( X[i] & Q ) { + X[0] ^= P; // invert + } else { + t = (X[0]^X[i]) & P; + X[0] ^= t; + X[i] ^= t; + } + } // exchange + } + // Gray encode + for( i = 1; i < 2; ++i ) { + X[i] ^= X[i-1]; + } + t=0; + for( Q = M; Q > 1; Q >>= 1 ) { + if( X[2-1] & Q ) { + t ^= Q-1; + } + } //check if this for loop is wrong + for( i = 0; i < 2; ++i ) { + X[i] ^= t; + } +} diff --git a/DataStructures/HilbertValue.h b/DataStructures/HilbertValue.h index d0d49f655..9cfbc98f2 100644 --- a/DataStructures/HilbertValue.h +++ b/DataStructures/HilbertValue.h @@ -39,59 +39,10 @@ class HilbertCode : boost::noncopyable { public: static uint64_t GetHilbertNumberForCoordinate( const FixedPointCoordinate & current_coordinate - ) { - unsigned location[2]; - location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION); - location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION); - - TransposeCoordinate(location); - const uint64_t result = BitInterleaving(location[0], location[1]); - return result; - } + ); private: - static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) { - uint64_t result = 0; - for(int8_t index = 31; index >= 0; --index){ - result |= (a >> index) & 1; - result <<= 1; - result |= (b >> index) & 1; - if(0 != index){ - result <<= 1; - } - } - return result; - } - - static inline void TransposeCoordinate( uint32_t * X) { - uint32_t M = 1 << (32-1), P, Q, t; - int i; - // Inverse undo - for( Q = M; Q > 1; Q >>= 1 ) { - P=Q-1; - for( i = 0; i < 2; ++i ) { - if( X[i] & Q ) { - X[0] ^= P; // invert - } else { - t = (X[0]^X[i]) & P; - X[0] ^= t; - X[i] ^= t; - } - } // exchange - } - // Gray encode - for( i = 1; i < 2; ++i ) { - X[i] ^= X[i-1]; - } - t=0; - for( Q = M; Q > 1; Q >>= 1 ) { - if( X[2-1] & Q ) { - t ^= Q-1; - } - } //check if this for loop is wrong - for( i = 0; i < 2; ++i ) { - X[i] ^= t; - } - } + static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b); + static inline void TransposeCoordinate( uint32_t * X); }; #endif /* HILBERTVALUE_H_ */ From 50ccfbf554fe339222c018bae757244294f4d32c Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 22 Nov 2013 18:05:47 +0100 Subject: [PATCH 02/29] move distance computation from r-tree to element type class --- DataStructures/EdgeBasedNode.h | 52 +++++++++++- DataStructures/StaticRTree.h | 141 ++++++++++----------------------- 2 files changed, 95 insertions(+), 98 deletions(-) diff --git a/DataStructures/EdgeBasedNode.h b/DataStructures/EdgeBasedNode.h index 542eda451..654de96de 100644 --- a/DataStructures/EdgeBasedNode.h +++ b/DataStructures/EdgeBasedNode.h @@ -4,6 +4,7 @@ #include "Coordinate.h" struct EdgeBasedNode { + EdgeBasedNode() : id(INT_MAX), lat1(INT_MAX), @@ -16,6 +17,55 @@ struct EdgeBasedNode { ignoreInGrid(false) { } + + double ComputePerpendicularDistance( + const FixedPointCoordinate& inputPoint, + FixedPointCoordinate & nearest_location, + double & r + ) const { + const double x = inputPoint.lat/COORDINATE_PRECISION; + const double y = inputPoint.lon/COORDINATE_PRECISION; + const double a = lat1/COORDINATE_PRECISION; + const double b = lon1/COORDINATE_PRECISION; + const double c = lat2/COORDINATE_PRECISION; + const double d = lon2/COORDINATE_PRECISION; + double p,q,mX,nY; + if(std::fabs(a-c) > std::numeric_limits::epsilon() ){ + const double m = (d-b)/(c-a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m); + q = b + m*(p - a); + } else { + p = c; + q = y; + } + nY = (d*p - c*q)/(a*d - b*c); + mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if(std::isnan(mX)) { + r = ((lat2 == inputPoint.lat) && (lon2 == inputPoint.lon)) ? 1. : 0.; + } else { + r = mX; + } + if(r<=0.){ + nearest_location.lat = lat1; + nearest_location.lon = lon1; + return ((b - y)*(b - y) + (a - x)*(a - x)); +// return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x))); + } else if(r >= 1.){ + nearest_location.lat = lat2; + nearest_location.lon = lon2; + return ((d - y)*(d - y) + (c - x)*(c - x)); +// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x))); + } + // point lies in between + nearest_location.lat = p*COORDINATE_PRECISION; + nearest_location.lon = q*COORDINATE_PRECISION; +// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y)); + return (p-x)*(p-x) + (q-y)*(q-y); + } + bool operator<(const EdgeBasedNode & other) const { return other.id < id; } @@ -48,4 +98,4 @@ struct EdgeBasedNode { bool ignoreInGrid:1; }; -#endif //EDGE_BASED_NODE_H \ No newline at end of file +#endif //EDGE_BASED_NODE_H diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h index 5feab4c7d..62ca89530 100644 --- a/DataStructures/StaticRTree.h +++ b/DataStructures/StaticRTree.h @@ -124,10 +124,10 @@ public: FixedPointCoordinate lower_left (other.min_lat, other.min_lon); return ( - Contains(upper_left) - || Contains(upper_right) - || Contains(lower_right) - || Contains(lower_left) + Contains(upper_left ) || + Contains(upper_right) || + Contains(lower_right) || + Contains(lower_left ) ); } @@ -188,32 +188,32 @@ public: min_max_dist = std::min( min_max_dist, std::max( - ApproximateDistance(location, upper_left ), - ApproximateDistance(location, upper_right) + ApproximateDistance(location, upper_left ), + ApproximateDistance(location, upper_right) ) ); min_max_dist = std::min( min_max_dist, std::max( - ApproximateDistance(location, upper_right), - ApproximateDistance(location, lower_right) + ApproximateDistance(location, upper_right), + ApproximateDistance(location, lower_right) ) ); min_max_dist = std::min( min_max_dist, std::max( - ApproximateDistance(location, lower_right), - ApproximateDistance(location, lower_left ) + ApproximateDistance(location, lower_right), + ApproximateDistance(location, lower_left ) ) ); min_max_dist = std::min( min_max_dist, std::max( - ApproximateDistance(location, lower_left ), - ApproximateDistance(location, upper_left ) + ApproximateDistance(location, lower_left ), + ApproximateDistance(location, upper_left ) ) ); return min_max_dist; @@ -318,8 +318,8 @@ public: uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid); input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value; - } + //open leaf file boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary); leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t)); @@ -334,6 +334,7 @@ public: LeafNode current_leaf; TreeNode current_node; + //SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes"; for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) { if(m_element_count > (processed_objects_count + current_element_index)) { uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index; @@ -391,6 +392,7 @@ public: //reverse and renumber tree to have root at index 0 std::reverse(m_search_tree.begin(), m_search_tree.end()); + #pragma omp parallel for schedule(guided) for(uint32_t i = 0; i < m_search_tree.size(); ++i) { TreeNode & current_tree_node = m_search_tree[i]; @@ -435,7 +437,7 @@ public: uint32_t tree_size = 0; tree_node_file.read((char*)&tree_size, sizeof(uint32_t)); - //SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes"; + m_search_tree.resize(tree_size); tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size); tree_node_file.close(); @@ -526,12 +528,10 @@ public: } double current_ratio = 0.; - double current_perpendicular_distance = ComputePerpendicularDistance( + double current_perpendicular_distance = current_edge.ComputePerpendicularDistance( input_coordinate, - FixedPointCoordinate(current_edge.lat1, current_edge.lon1), - FixedPointCoordinate(current_edge.lat2, current_edge.lon2), nearest, - ¤t_ratio + current_ratio ); if( @@ -556,7 +556,7 @@ public: } else if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) - && CoordinatesAreEquivalent( + && EdgesAreEquivalent( current_start_coordinate, FixedPointCoordinate( current_edge.lat1, @@ -736,7 +736,6 @@ public: return found_a_nearest_edge; } - bool FindPhantomNodeForCoordinate( const FixedPointCoordinate & input_coordinate, PhantomNode & result_phantom_node, @@ -746,7 +745,7 @@ public: bool ignore_tiny_components = (zoom_level <= 14); DataT nearest_edge; - uint32_t io_count = 0; + // uint32_t io_count = 0; uint32_t explored_tree_nodes_count = 0; //SimpleLogger().Write() << "searching for coordinate " << input_coordinate; double min_dist = std::numeric_limits::max(); @@ -758,9 +757,7 @@ public: //initialize queue with root element std::priority_queue traversal_queue; double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate); - traversal_queue.push( - QueryCandidate(0, current_min_dist) - ); + traversal_queue.push( QueryCandidate(0, current_min_dist) ); BOOST_ASSERT_MSG( std::numeric_limits::epsilon() > (0. - traversal_queue.top().min_dist), @@ -778,7 +775,7 @@ public: if (current_tree_node.child_is_on_disk) { LeafNode current_leaf_node; LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node); - ++io_count; + // ++io_count; for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) { DataT & current_edge = current_leaf_node.objects[i]; if(ignore_tiny_components && current_edge.belongsToTinyComponent) { @@ -788,21 +785,20 @@ public: continue; } - double current_ratio = 0.; - double current_perpendicular_distance = ComputePerpendicularDistance( - input_coordinate, - FixedPointCoordinate(current_edge.lat1, current_edge.lon1), - FixedPointCoordinate(current_edge.lat2, current_edge.lon2), - nearest, - ¤t_ratio + double current_ratio = 0.; + double current_perpendicular_distance = current_edge.ComputePerpendicularDistance( + input_coordinate, + nearest, + current_ratio ); + BOOST_ASSERT( 0 <= current_perpendicular_distance ); if( - current_perpendicular_distance < min_dist - && !DoubleEpsilonCompare( - current_perpendicular_distance, - min_dist - ) + ( current_perpendicular_distance < min_dist ) && + !DoubleEpsilonCompare( + current_perpendicular_distance, + min_dist + ) ) { //found a new minimum min_dist = current_perpendicular_distance; result_phantom_node.edgeBasedNode = current_edge.id; @@ -816,10 +812,10 @@ public: current_end_coordinate.lon = current_edge.lon2; nearest_edge = current_edge; found_a_nearest_edge = true; - } else if( - DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && - 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) - && CoordinatesAreEquivalent( + } else + if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && + ( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) && + EdgesAreEquivalent( current_start_coordinate, FixedPointCoordinate( current_edge.lat1, @@ -853,10 +849,10 @@ public: if( current_min_max_dist < min_max_dist ) { min_max_dist = current_min_max_dist; } - if (current_min_dist > min_max_dist) { + if( current_min_dist > min_max_dist ) { continue; } - if (current_min_dist > min_dist) { //upward pruning + if( current_min_dist > min_dist ) { //upward pruning continue; } traversal_queue.push(QueryCandidate(child_id, current_min_dist)); @@ -866,10 +862,10 @@ public: } const double ratio = (found_a_nearest_edge ? - std::min(1., ApproximateDistance(current_start_coordinate, - result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate) - ) : 0 - ); + std::min(1., ApproximateDistance(current_start_coordinate, + result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate) + ) : 0 + ); result_phantom_node.weight1 *= ratio; if(INT_MAX != result_phantom_node.weight2) { result_phantom_node.weight2 *= (1.-ratio); @@ -885,7 +881,6 @@ public: } return found_a_nearest_edge; - } private: @@ -910,55 +905,7 @@ private: thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode)); } - inline double ComputePerpendicularDistance( - const FixedPointCoordinate& inputPoint, - const FixedPointCoordinate& source, - const FixedPointCoordinate& target, - FixedPointCoordinate& nearest, double *r) const { - const double x = inputPoint.lat/COORDINATE_PRECISION; - const double y = inputPoint.lon/COORDINATE_PRECISION; - const double a = source.lat/COORDINATE_PRECISION; - const double b = source.lon/COORDINATE_PRECISION; - const double c = target.lat/COORDINATE_PRECISION; - const double d = target.lon/COORDINATE_PRECISION; - double p,q,mX,nY; - if(std::fabs(a-c) > std::numeric_limits::epsilon() ){ - const double m = (d-b)/(c-a); // slope - // Projection of (x,y) on line joining (a,b) and (c,d) - p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m); - q = b + m*(p - a); - } else { - p = c; - q = y; - } - nY = (d*p - c*q)/(a*d - b*c); - mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need - // not calculate the explicit values of m an n as we - // are just interested in the ratio - if(std::isnan(mX)) { - *r = (target == inputPoint) ? 1. : 0.; - } else { - *r = mX; - } - if(*r<=0.){ - nearest.lat = source.lat; - nearest.lon = source.lon; - return ((b - y)*(b - y) + (a - x)*(a - x)); -// return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x))); - } else if(*r >= 1.){ - nearest.lat = target.lat; - nearest.lon = target.lon; - return ((d - y)*(d - y) + (c - x)*(c - x)); -// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x))); - } - // point lies in between - nearest.lat = p*COORDINATE_PRECISION; - nearest.lon = q*COORDINATE_PRECISION; -// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y)); - return (p-x)*(p-x) + (q-y)*(q-y); - } - - inline bool CoordinatesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const { + inline bool EdgesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const { return (a == b && c == d) || (a == c && b == d) || (a == d && b == c); } From 0e33f638e64f36dff59b158f7c9cee47fc6b48af Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 22 Nov 2013 18:43:01 +0100 Subject: [PATCH 03/29] move implementation details out of templat'ized container code --- DataStructures/EdgeBasedNode.h | 10 +++++++--- DataStructures/StaticRTree.h | 6 ------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/DataStructures/EdgeBasedNode.h b/DataStructures/EdgeBasedNode.h index 654de96de..8fafed71c 100644 --- a/DataStructures/EdgeBasedNode.h +++ b/DataStructures/EdgeBasedNode.h @@ -23,6 +23,10 @@ struct EdgeBasedNode { FixedPointCoordinate & nearest_location, double & r ) const { + if( ignoreInGrid ) { + return std::numeric_limits::max(); + } + const double x = inputPoint.lat/COORDINATE_PRECISION; const double y = inputPoint.lon/COORDINATE_PRECISION; const double a = lat1/COORDINATE_PRECISION; @@ -83,9 +87,9 @@ struct EdgeBasedNode { return centroid; } - inline bool isIgnored() const { - return ignoreInGrid; - } + // inline bool isIgnored() const { + // return ignoreInGrid; + // } NodeID id; int lat1; diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h index 62ca89530..6d9464b1c 100644 --- a/DataStructures/StaticRTree.h +++ b/DataStructures/StaticRTree.h @@ -675,9 +675,6 @@ public: ) { continue; } - if(current_edge.isIgnored()) { - continue; - } double current_minimum_distance = ApproximateDistance( input_coordinate.lat, @@ -781,9 +778,6 @@ public: if(ignore_tiny_components && current_edge.belongsToTinyComponent) { continue; } - if(current_edge.isIgnored()) { - continue; - } double current_ratio = 0.; double current_perpendicular_distance = current_edge.ComputePerpendicularDistance( From 349df0dc94cbabe7b2e23fd5c2e1248284ff4694 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 22 Nov 2013 18:58:58 +0100 Subject: [PATCH 04/29] make rtree query do O(1) allocations only --- DataStructures/StaticRTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h index 6d9464b1c..ed1e5d4bb 100644 --- a/DataStructures/StaticRTree.h +++ b/DataStructures/StaticRTree.h @@ -761,6 +761,7 @@ public: "Root element in NN Search has min dist != 0." ); + LeafNode current_leaf_node; while(!traversal_queue.empty()) { const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop(); @@ -770,7 +771,6 @@ public: if( !prune_downward && !prune_upward ) { //downward pruning TreeNode & current_tree_node = m_search_tree[current_query_node.node_id]; if (current_tree_node.child_is_on_disk) { - LeafNode current_leaf_node; LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node); // ++io_count; for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) { From a8e8833a8dc6102c6d09f56767969167b52f83ff Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 25 Nov 2013 19:05:58 +0100 Subject: [PATCH 05/29] add geometry compressor --- Contractor/EdgeBasedGraphFactory.h | 6 +- Contractor/GeometryCompressor.cpp | 94 ++++++++++++++++++++++++++++++ Contractor/GeometryCompressor.h | 58 ++++++++++++++++++ 3 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 Contractor/GeometryCompressor.cpp create mode 100644 Contractor/GeometryCompressor.h diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 0bd2fc6b2..5b28725c6 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -34,15 +34,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DynamicGraph.h" #include "../DataStructures/EdgeBasedNode.h" -#include "../Extractor/ExtractorStructs.h" #include "../DataStructures/HashTable.h" #include "../DataStructures/ImportEdge.h" -#include "../DataStructures/QueryEdge.h" #include "../DataStructures/Percent.h" +#include "../DataStructures/QueryEdge.h" #include "../DataStructures/TurnInstructions.h" +#include "../Extractor/ExtractorStructs.h" #include "../Util/LuaUtil.h" #include "../Util/SimpleLogger.h" +#include "GeometryCompressor.h" + #include #include #include diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp new file mode 100644 index 000000000..e4b553116 --- /dev/null +++ b/Contractor/GeometryCompressor.cpp @@ -0,0 +1,94 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "GeometryCompressor.h" + +int current_free_list_maximum = 0; +int UniqueNumber () { return ++current_free_list_maximum; } + +GeometryCompressor::GeometryCompressor() { + m_free_list.resize(100); + IncreaseFreeList(); +} + +void GeometryCompressor::IncreaseFreeList() { + m_compressed_geometries.resize(m_compressed_geometries.size() + 100); + std::generate_n (m_free_list.rend(), 100, UniqueNumber); +} + +void GeometryCompressor::AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ) { + //check if node_id already has a list + boost::unordered_map::const_iterator map_iterator; + map_iterator = m_node_id_to_index_map.find( node_id ); + + unsigned geometry_bucket_index = std::numeric_limits::max(); + if( m_node_id_to_index_map.end() == map_iterator ) { + //if not, create one + if( m_free_list.empty() ) { + IncreaseFreeList(); + } + geometry_bucket_index = m_free_list.back(); + m_free_list.pop_back(); + } else { + geometry_bucket_index = map_iterator->second; + } + + BOOST_ASSERT( std::numeric_limits::max() != geometry_bucket_index ); + BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() ); + + //append contracted_node_id to m_compressed_geometries[node_id] + m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id); + + //append m_compressed_geometries[contracted_node_id] to m_compressed_geometries[node_id] + map_iterator = m_node_id_to_index_map.find(contracted_node_id); + if ( m_node_id_to_index_map.end() != map_iterator) { + const unsigned bucket_index_to_remove = map_iterator->second; + BOOST_ASSERT( bucket_index_to_remove < m_compressed_geometries.size() ); + + m_compressed_geometries[geometry_bucket_index].insert( + m_compressed_geometries[geometry_bucket_index].end(), + m_compressed_geometries[bucket_index_to_remove].begin(), + m_compressed_geometries[bucket_index_to_remove].end() + ); + //remove m_compressed_geometries[contracted_node_id], add to free list + m_compressed_geometries[bucket_index_to_remove].clear(); + m_free_list.push_back(bucket_index_to_remove); + } +} + +void GeometryCompressor::PrintStatistics() const { + unsigned compressed_node_count = 0; + const unsigned surviving_node_count = m_compressed_geometries.size(); + + BOOST_FOREACH(const std::vector & current_vector, m_compressed_geometries) { + compressed_node_count += current_vector.size(); + } + SimpleLogger().Write() << + "surv: " << surviving_node_count << + ", comp: " << compressed_node_count << + ", comp ratio: " << ((float)surviving_node_count/compressed_node_count); +} diff --git a/Contractor/GeometryCompressor.h b/Contractor/GeometryCompressor.h new file mode 100644 index 000000000..8d2bf66a6 --- /dev/null +++ b/Contractor/GeometryCompressor.h @@ -0,0 +1,58 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../Util/SimpleLogger.h" +#include "../typedefs.h" + +#include +#include +#include + +#include +#include +#include + +#ifndef GEOMETRY_COMPRESSOR_H +#define GEOMETRY_COMPRESSOR_H + +class GeometryCompressor { +public: + GeometryCompressor(); + void AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ); + void PrintStatistics() const; + +private: + + void IncreaseFreeList(); + + std::vector > m_compressed_geometries; + std::vector m_free_list; + boost::unordered_map m_node_id_to_index_map; +}; + + +#endif //GEOMETRY_COMPRESSOR_H From cf527ed819926f0cc4b4b96ef81db305ce0ebbd1 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 14:25:53 +0100 Subject: [PATCH 06/29] remove potential division by zero --- Contractor/GeometryCompressor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp index e4b553116..5f5a7fcf7 100644 --- a/Contractor/GeometryCompressor.cpp +++ b/Contractor/GeometryCompressor.cpp @@ -90,5 +90,5 @@ void GeometryCompressor::PrintStatistics() const { SimpleLogger().Write() << "surv: " << surviving_node_count << ", comp: " << compressed_node_count << - ", comp ratio: " << ((float)surviving_node_count/compressed_node_count); + ", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count), 1); } From e36a27307bb98802eabe5391afbd25aaeac7edcf Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 14:27:19 +0100 Subject: [PATCH 07/29] use explicit unsigned type in max operation --- Contractor/GeometryCompressor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp index 5f5a7fcf7..5f97a751c 100644 --- a/Contractor/GeometryCompressor.cpp +++ b/Contractor/GeometryCompressor.cpp @@ -90,5 +90,5 @@ void GeometryCompressor::PrintStatistics() const { SimpleLogger().Write() << "surv: " << surviving_node_count << ", comp: " << compressed_node_count << - ", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count), 1); + ", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) ); } From d5f6c1c15c49bb37c8c8e25048043b5b31508dbc Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 19:41:32 +0100 Subject: [PATCH 08/29] renaming file --- Algorithms/DouglasePeucker.cpp | 166 --------------------------------- 1 file changed, 166 deletions(-) delete mode 100644 Algorithms/DouglasePeucker.cpp diff --git a/Algorithms/DouglasePeucker.cpp b/Algorithms/DouglasePeucker.cpp deleted file mode 100644 index 8baaf8a24..000000000 --- a/Algorithms/DouglasePeucker.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - -Copyright (c) 2013, Project OSRM, Dennis Luxen, others -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list -of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "DouglasPeucker.h" - -//These thresholds are more or less heuristically chosen. -static double DouglasPeuckerThresholds[19] = { - 32000000., //z0 - 16240000., //z1 - 8240000., //z2 - 4240000., //z3 - 2000000., //z4 - 1000000., //z5 - 500000., //z6 - 240000., //z7 - 120000., //z8 - 60000., //z9 - 30000., //z10 - 19000., //z11 - 5000., //z12 - 2000., //z13 - 200., //z14 - 16., //z15 - 6., //z16 - 3., //z17 - 3. //z18 -}; - -/** - * This distance computation does integer arithmetic only and is about twice as - * fast as the other distance function. It is an approximation only, but works - * more or less ok. - */ -int DouglasPeucker::fastDistance( - const FixedPointCoordinate& point, - const FixedPointCoordinate& segA, - const FixedPointCoordinate& segB -) const { - const int p2x = (segB.lon - segA.lon); - const int p2y = (segB.lat - segA.lat); - const int something = p2x*p2x + p2y*p2y; - double u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something); - - if (u > 1) { - u = 1; - } else if (u < 0) { - u = 0; - } - - const int x = segA.lon + u * p2x; - const int y = segA.lat + u * p2y; - - const int dx = x - point.lon; - const int dy = y - point.lat; - - const int dist = (dx*dx + dy*dy); - - return dist; -} - -void DouglasPeucker::Run( - std::vector & input_geometry, - const unsigned zoom_level -) { - { - BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level"); - BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid"); - std::size_t left_border = 0; - std::size_t right_border = 1; - //Sweep linerarily over array and identify those ranges that need to be checked - do { - BOOST_ASSERT_MSG( - input_geometry[left_border].necessary, - "left border must be necessary" - ); - BOOST_ASSERT_MSG( - input_geometry.back().necessary, - "right border must be necessary" - ); - - if(input_geometry[right_border].necessary) { - recursion_stack.push(std::make_pair(left_border, right_border)); - left_border = right_border; - } - ++right_border; - } while( right_border < input_geometry.size()); - } - while(!recursion_stack.empty()) { - //pop next element - const PairOfPoints pair = recursion_stack.top(); - recursion_stack.pop(); - BOOST_ASSERT_MSG( - input_geometry[pair.first].necessary, - "left border mus be necessary" - ); - BOOST_ASSERT_MSG( - input_geometry[pair.second].necessary, - "right border must be necessary" - ); - BOOST_ASSERT_MSG( - pair.second < input_geometry.size(), - "right border outside of geometry" - ); - BOOST_ASSERT_MSG( - pair.first < pair.second, - "left border on the wrong side" - ); - int max_distance = INT_MIN; - - std::size_t farthest_element_index = pair.second; - //find index idx of element with max_distance - for(std::size_t i = pair.first+1; i < pair.second; ++i){ - const int temp_dist = fastDistance( - input_geometry[i].location, - input_geometry[pair.first].location, - input_geometry[pair.second].location - ); - const double distance = std::fabs(temp_dist); - if( - distance > DouglasPeuckerThresholds[zoom_level] && - distance > max_distance - ) { - farthest_element_index = i; - max_distance = distance; - } - } - if (max_distance > DouglasPeuckerThresholds[zoom_level]) { - // mark idx as necessary - input_geometry[farthest_element_index].necessary = true; - if (1 < (farthest_element_index - pair.first) ) { - recursion_stack.push( - std::make_pair(pair.first, farthest_element_index) - ); - } - if (1 < (pair.second - farthest_element_index) ) { - recursion_stack.push( - std::make_pair(farthest_element_index, pair.second) - ); - } - } - } -} From 2233c44d36fd2a369f805e965b45400d89acf535 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 19:41:36 +0100 Subject: [PATCH 09/29] renaming file --- Algorithms/DouglasPeucker.cpp | 166 ++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 Algorithms/DouglasPeucker.cpp diff --git a/Algorithms/DouglasPeucker.cpp b/Algorithms/DouglasPeucker.cpp new file mode 100644 index 000000000..8baaf8a24 --- /dev/null +++ b/Algorithms/DouglasPeucker.cpp @@ -0,0 +1,166 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "DouglasPeucker.h" + +//These thresholds are more or less heuristically chosen. +static double DouglasPeuckerThresholds[19] = { + 32000000., //z0 + 16240000., //z1 + 8240000., //z2 + 4240000., //z3 + 2000000., //z4 + 1000000., //z5 + 500000., //z6 + 240000., //z7 + 120000., //z8 + 60000., //z9 + 30000., //z10 + 19000., //z11 + 5000., //z12 + 2000., //z13 + 200., //z14 + 16., //z15 + 6., //z16 + 3., //z17 + 3. //z18 +}; + +/** + * This distance computation does integer arithmetic only and is about twice as + * fast as the other distance function. It is an approximation only, but works + * more or less ok. + */ +int DouglasPeucker::fastDistance( + const FixedPointCoordinate& point, + const FixedPointCoordinate& segA, + const FixedPointCoordinate& segB +) const { + const int p2x = (segB.lon - segA.lon); + const int p2y = (segB.lat - segA.lat); + const int something = p2x*p2x + p2y*p2y; + double u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something); + + if (u > 1) { + u = 1; + } else if (u < 0) { + u = 0; + } + + const int x = segA.lon + u * p2x; + const int y = segA.lat + u * p2y; + + const int dx = x - point.lon; + const int dy = y - point.lat; + + const int dist = (dx*dx + dy*dy); + + return dist; +} + +void DouglasPeucker::Run( + std::vector & input_geometry, + const unsigned zoom_level +) { + { + BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level"); + BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid"); + std::size_t left_border = 0; + std::size_t right_border = 1; + //Sweep linerarily over array and identify those ranges that need to be checked + do { + BOOST_ASSERT_MSG( + input_geometry[left_border].necessary, + "left border must be necessary" + ); + BOOST_ASSERT_MSG( + input_geometry.back().necessary, + "right border must be necessary" + ); + + if(input_geometry[right_border].necessary) { + recursion_stack.push(std::make_pair(left_border, right_border)); + left_border = right_border; + } + ++right_border; + } while( right_border < input_geometry.size()); + } + while(!recursion_stack.empty()) { + //pop next element + const PairOfPoints pair = recursion_stack.top(); + recursion_stack.pop(); + BOOST_ASSERT_MSG( + input_geometry[pair.first].necessary, + "left border mus be necessary" + ); + BOOST_ASSERT_MSG( + input_geometry[pair.second].necessary, + "right border must be necessary" + ); + BOOST_ASSERT_MSG( + pair.second < input_geometry.size(), + "right border outside of geometry" + ); + BOOST_ASSERT_MSG( + pair.first < pair.second, + "left border on the wrong side" + ); + int max_distance = INT_MIN; + + std::size_t farthest_element_index = pair.second; + //find index idx of element with max_distance + for(std::size_t i = pair.first+1; i < pair.second; ++i){ + const int temp_dist = fastDistance( + input_geometry[i].location, + input_geometry[pair.first].location, + input_geometry[pair.second].location + ); + const double distance = std::fabs(temp_dist); + if( + distance > DouglasPeuckerThresholds[zoom_level] && + distance > max_distance + ) { + farthest_element_index = i; + max_distance = distance; + } + } + if (max_distance > DouglasPeuckerThresholds[zoom_level]) { + // mark idx as necessary + input_geometry[farthest_element_index].necessary = true; + if (1 < (farthest_element_index - pair.first) ) { + recursion_stack.push( + std::make_pair(pair.first, farthest_element_index) + ); + } + if (1 < (pair.second - farthest_element_index) ) { + recursion_stack.push( + std::make_pair(farthest_element_index, pair.second) + ); + } + } + } +} From f5d22c904f66847286b4f2803de79428ea2d98a3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 19:41:55 +0100 Subject: [PATCH 10/29] fixing coverity issue --- Util/ProgramOptions.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 83b9daa9d..4d0c64c57 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -231,7 +231,10 @@ inline bool GenerateServerProgramOptions( } if( !use_shared_memory && option_variables.count("base") ) { - std::string base_string = paths["base"].string(); + path_iterator = paths.find("base"); + BOOST_ASSERT( paths.end() != path_iterator ); + std::string base_string = path_iterator->second.string(); + path_iterator = paths.find("hsgrdata"); if( path_iterator != paths.end() && From 3df89c0dfed7e6d3418284995ff72411b932bccc Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 19:43:30 +0100 Subject: [PATCH 11/29] moving BFS exploration into its own function --- Contractor/EdgeBasedGraphFactory.cpp | 207 +++++++++++++++------------ Contractor/EdgeBasedGraphFactory.h | 16 ++- 2 files changed, 124 insertions(+), 99 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 32389f1f2..ceabf3bfa 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -43,7 +43,8 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( std::pair restriction_source = std::make_pair(restriction.fromNode, restriction.viaNode); unsigned index; - RestrictionMap::iterator restriction_iter = m_restriction_map.find(restriction_source); + RestrictionMap::iterator restriction_iter; + restriction_iter = m_restriction_map.find(restriction_source); if(restriction_iter == m_restriction_map.end()) { index = m_restriction_bucket_list.size(); m_restriction_bucket_list.resize(index+1); @@ -93,7 +94,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( continue; } edge.data.distance = (std::max)((int)import_edge.weight(), 1 ); - assert( edge.data.distance > 0 ); + BOOST_ASSERT( edge.data.distance > 0 ); edge.data.shortcut = false; edge.data.roundabout = import_edge.isRoundabout(); edge.data.ignoreInGrid = import_edge.ignoreInGrid(); @@ -131,8 +132,8 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges( void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector & nodes) { #ifndef NDEBUG BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){ - assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX); - assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX); + BOOST_ASSERT(node.lat1 != INT_MAX); BOOST_ASSERT(node.lon1 != INT_MAX); + BOOST_ASSERT(node.lat2 != INT_MAX); BOOST_ASSERT(node.lon2 != INT_MAX); } #endif nodes.swap(m_edge_based_node_list); @@ -143,7 +144,8 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn( const NodeID v ) const { const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); - RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source); + RestrictionMap::const_iterator restriction_iter; + restriction_iter = m_restriction_map.find(restriction_source); if (restriction_iter != m_restriction_map.end()) { const unsigned index = restriction_iter->second; BOOST_FOREACH( @@ -165,7 +167,8 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( ) const { //only add an edge if turn is not a U-turn except it is the end of dead-end street. const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); - RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source); + RestrictionMap::const_iterator restriction_iter; + restriction_iter = m_restriction_map.find(restriction_source); if (restriction_iter != m_restriction_map.end()) { const unsigned index = restriction_iter->second; BOOST_FOREACH( @@ -203,9 +206,11 @@ void EdgeBasedGraphFactory::Run( const char * original_edge_data_filename, lua_State *lua_state ) { + SimpleLogger().Write() << "Compressing geometry of input graph"; + + SimpleLogger().Write() << "Identifying components of the road network"; - Percent p(m_node_based_graph->GetNumberOfNodes()); unsigned skipped_turns_counter = 0; unsigned node_based_edge_counter = 0; unsigned original_edges_counter = 0; @@ -221,93 +226,21 @@ void EdgeBasedGraphFactory::Run( sizeof(unsigned) ); - unsigned current_component = 0, current_component_size = 0; //Run a BFS on the undirected graph and identify small components - std::queue > bfs_queue; - std::vector component_index_list( - m_node_based_graph->GetNumberOfNodes(), - UINT_MAX - ); + std::vector component_index_list; + std::vector component_index_size; + BFSCompentExplorer( component_index_list, component_index_size); - std::vector component_size_list; - //put unexplorered node with parent pointer into queue - for( - NodeID node = 0, - last_node = m_node_based_graph->GetNumberOfNodes(); - node < last_node; - ++node - ) { - if(UINT_MAX == component_index_list[node]) { - bfs_queue.push(std::make_pair(node, node)); - //mark node as read - component_index_list[node] = current_component; - p.printIncrement(); - while(!bfs_queue.empty()) { - //fetch element from BFS queue - std::pair current_queue_item = bfs_queue.front(); - bfs_queue.pop(); - // SimpleLogger().Write() << "sizeof queue: " << bfs_queue.size() << - // ", current_component_sizes: " << current_component_size << - //", settled nodes: " << settledNodes++ << ", max: " << endNodes; - const NodeID v = current_queue_item.first; //current node - const NodeID u = current_queue_item.second; //parent - //increment size counter of current component - ++current_component_size; - const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); - if(!is_barrier_node) { - const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); - - //relaxieren edge outgoing edge like below where edge-expanded graph - for( - EdgeIterator e2 = m_node_based_graph->BeginEdges(v); - e2 < m_node_based_graph->EndEdges(v); - ++e2 - ) { - NodeIterator w = m_node_based_graph->GetTarget(e2); - - if( - to_node_of_only_restriction != UINT_MAX && - w != to_node_of_only_restriction - ) { - //We are at an only_-restriction but not at the right turn. - continue; - } - if( u != w ) { - //only add an edge if turn is not a U-turn except - //when it is at the end of a dead-end street. - if (!CheckIfTurnIsRestricted(u, v, w) ) { - //only add an edge if turn is not prohibited - if(UINT_MAX == component_index_list[w]) { - //insert next (node, parent) only if w has - //not yet been explored - //mark node as read - component_index_list[w] = current_component; - bfs_queue.push(std::make_pair(w,v)); - p.printIncrement(); - } - } - } - } - } - } - //push size into vector - component_size_list.push_back(current_component_size); - //reset counters; - current_component_size = 0; - ++current_component; - } - } SimpleLogger().Write() << - "identified: " << component_size_list.size() << " many components"; + "identified: " << component_index_size.size() << " many components"; SimpleLogger().Write() << "generating edge-expanded nodes"; - p.reinit(m_node_based_graph->GetNumberOfNodes()); + Percent p(m_node_based_graph->GetNumberOfNodes()); //loop over all edges and generate new set of nodes. for( - NodeIterator u = 0, - number_of_nodes = m_node_based_graph->GetNumberOfNodes(); - u < number_of_nodes; + NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); + u < end; ++u ) { p.printIncrement(); @@ -326,8 +259,8 @@ void EdgeBasedGraphFactory::Run( //Note: edges that end on barrier nodes or on a turn restriction //may actually be in two distinct components. We choose the smallest const unsigned size_of_component = std::min( - component_size_list[component_index_list[u]], - component_size_list[component_index_list[v]] + component_index_size[component_index_list[u]], + component_index_size[component_index_list[v]] ); InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 ); @@ -341,9 +274,9 @@ void EdgeBasedGraphFactory::Run( SimpleLogger().Write() << "generating edge-expanded edges"; - std::vector().swap(component_size_list); + std::vector().swap(component_index_size); BOOST_ASSERT_MSG( - 0 == component_size_list.capacity(), + 0 == component_index_size.capacity(), "component size vector not deallocated" ); std::vector().swap(component_index_list); @@ -372,7 +305,7 @@ void EdgeBasedGraphFactory::Run( ) { ++node_based_edge_counter; NodeIterator v = m_node_based_graph->GetTarget(e1); - bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); + const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); for( EdgeIterator e2 = m_node_based_graph->BeginEdges(v), @@ -403,8 +336,12 @@ void EdgeBasedGraphFactory::Run( ) { //only add an edge if turn is not prohibited const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1); const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2); - assert(edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()); - assert(edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()); + BOOST_ASSERT( + edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() + ); + BOOST_ASSERT( + edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() + ); if(!edge_data1.forward || !edge_data2.forward) { continue; @@ -422,7 +359,10 @@ void EdgeBasedGraphFactory::Run( } distance += penalty; - assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID); + BOOST_ASSERT( + edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID + ); + original_edge_data_vector.push_back( OriginalEdgeData( v, @@ -576,3 +516,82 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const { return m_node_based_graph->GetNumberOfEdges(); } + +void EdgeBasedGraphFactory::BFSCompentExplorer( + std::vector & component_index_list, + std::vector & component_index_size +) const { + std::queue > bfs_queue; + Percent p( m_node_based_graph->GetNumberOfNodes() ); + unsigned current_component, current_component_size; + current_component = current_component_size = 0; + + BOOST_ASSERT( component_index_list.empty() ); + BOOST_ASSERT( component_index_size.empty() ); + + component_index_list.resize( + m_node_based_graph->GetNumberOfNodes(), + UINT_MAX + ); + + //put unexplorered node with parent pointer into queue + for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) { + if(UINT_MAX == component_index_list[node]) { + bfs_queue.push(std::make_pair(node, node)); + //mark node as read + component_index_list[node] = current_component; + p.printIncrement(); + while(!bfs_queue.empty()) { + //fetch element from BFS queue + std::pair current_queue_item = bfs_queue.front(); + bfs_queue.pop(); + + const NodeID v = current_queue_item.first; //current node + const NodeID u = current_queue_item.second; //parent + //increment size counter of current component + ++current_component_size; + const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); + if(!is_barrier_node) { + const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); + + //relaxieren edge outgoing edge like below where edge-expanded m_node_based_graph + for( + EdgeIterator e2 = m_node_based_graph->BeginEdges(v); + e2 < m_node_based_graph->EndEdges(v); + ++e2 + ) { + NodeIterator w = m_node_based_graph->GetTarget(e2); + + if( + to_node_of_only_restriction != UINT_MAX && + w != to_node_of_only_restriction + ) { + //We are at an only_-restriction but not at the right turn. + continue; + } + if( u != w ) { + //only add an edge if turn is not a U-turn except + //when it is at the end of a dead-end street. + if (!CheckIfTurnIsRestricted(u, v, w) ) { + //only add an edge if turn is not prohibited + if(UINT_MAX == component_index_list[w]) { + //insert next (node, parent) only if w has + //not yet been explored + //mark node as read + component_index_list[w] = current_component; + bfs_queue.push(std::make_pair(w,v)); + p.printIncrement(); + } + } + } + } + } + } + //push size into vector + component_index_size.push_back(current_component_size); + //reset counters; + current_component_size = 0; + ++current_component; + } + } +} diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 5b28725c6..dd2edb94f 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "GeometryCompressor.h" +#include #include #include #include @@ -146,7 +147,6 @@ private: RestrictionMap m_restriction_map; - NodeID CheckForEmanatingIsOnlyTurn( const NodeID u, const NodeID v @@ -159,10 +159,16 @@ private: ) const; void InsertEdgeBasedNode( - NodeBasedDynamicGraph::EdgeIterator e1, - NodeBasedDynamicGraph::NodeIterator u, - NodeBasedDynamicGraph::NodeIterator v, - bool belongsToTinyComponent); + NodeBasedDynamicGraph::EdgeIterator e1, + NodeBasedDynamicGraph::NodeIterator u, + NodeBasedDynamicGraph::NodeIterator v, + bool belongsToTinyComponent + ); + + void BFSCompentExplorer( + std::vector & component_index_list, + std::vector & component_index_size + ) const; }; #endif /* EDGEBASEDGRAPHFACTORY_H_ */ From 4455e816aa8339105d872b6dffd56978d5bb6877 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Tue, 26 Nov 2013 19:56:45 +0100 Subject: [PATCH 12/29] clear memory early by swap trick --- prepare.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/prepare.cpp b/prepare.cpp index a432c7eaa..6bc98967c 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -296,6 +296,7 @@ int main (int argc, char *argv[]) { IteratorbasedCRC32 > crc32; unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() ); nodeBasedEdgeList.clear(); + std::vector(nodeBasedEdgeList).swap(nodeBasedEdgeList); SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList; /*** From ec84b3a0cad9e21fe74a3cfd9a0b7abd82d42213 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Tue, 26 Nov 2013 22:41:01 +0100 Subject: [PATCH 13/29] cast to larger data type on 32bits, probably fixes #809 --- datastore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datastore.cpp b/datastore.cpp index 74a7bcd0b..7619a4a3a 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -160,7 +160,7 @@ int main( const int argc, const char * argv[] ) { shared_layout_ptr->ram_index_file_name ); // add zero termination - unsigned end_of_string_index = std::min(1023ul, file_index_file_name.length()); + unsigned end_of_string_index = std::min((std::size_t)1023, file_index_file_name.length()); shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0'; // collect number of elements to store in shared memory object From 02e2b3bd478013bab88ca9c197fd6f981ce2f85e Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 27 Nov 2013 16:37:40 +0100 Subject: [PATCH 14/29] temporarily fixes #811 plus 16 others --- profiles/car.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/profiles/car.lua b/profiles/car.lua index d334b9153..f0b6713df 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -1,5 +1,5 @@ -- Begin of globals -require("lib/access") +--require("lib/access") --function temporarily inlined barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true} access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true } @@ -41,6 +41,15 @@ traffic_signal_penalty = 2 u_turn_penalty = 20 -- End of globals +function find_access_tag(source,access_tags_hierachy) + for i,v in ipairs(access_tags_hierachy) do + local tag = source.tags:Find(v) + if tag ~= '' then + return tag + end + end + return nil +end function get_exceptions(vector) for i,v in ipairs(restriction_exception_tags) do @@ -64,7 +73,7 @@ end function node_function (node) local barrier = node.tags:Find("barrier") - local access = Access.find_access_tag(node, access_tags_hierachy) + local access = find_access_tag(node, access_tags_hierachy) local traffic_signal = node.tags:Find("highway") --flag node if it carries a traffic light @@ -112,7 +121,7 @@ function way_function (way) end -- Check if we are allowed to access the way - local access = Access.find_access_tag(way, access_tags_hierachy) + local access = find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then return end From cb86d3d829609dfdf0cc6792c95d5433373d12d0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 27 Nov 2013 17:27:47 +0100 Subject: [PATCH 15/29] clean up of build config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index af602bdd4..523e79599 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ compiler: # Make sure CMake is installed install: - sudo apt-get update >/dev/null - - sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis + - sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis before_script: - sudo gem install bundler - bundle install From 4911601b243fe97f6978199e825cb6ca6a5aca8a Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 27 Nov 2013 23:24:00 +0100 Subject: [PATCH 16/29] implements #801 --- Contractor/Contractor.h | 30 ++++---- Contractor/TemporaryStorage.cpp | 120 +++++++++++++++++++------------- Contractor/TemporaryStorage.h | 100 ++++++++++++-------------- 3 files changed, 133 insertions(+), 117 deletions(-) diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 976cd9124..46925603e 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -214,14 +214,14 @@ public: //Create temporary file // GetTemporaryFileName(temporaryEdgeStorageFilename); - temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot(); + temporaryStorageSlotID = TemporaryStorage::GetInstance().AllocateSlot(); std::cout << "contractor finished initalization" << std::endl; } ~Contractor() { //Delete temporary file // remove(temporaryEdgeStorageFilename.c_str()); - TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID); + TemporaryStorage::GetInstance().DeallocateSlot(temporaryStorageSlotID); } void Run() { @@ -287,9 +287,9 @@ public: TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); //Write dummy number of edges to temporary file // std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary); - uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID); + uint64_t initialFilePosition = tempStorage.Tell(temporaryStorageSlotID); unsigned numberOfTemporaryEdges = 0; - tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); + tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); //walk over all nodes for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) { @@ -299,11 +299,11 @@ public: const NodeID target = _graph->GetTarget(currentEdge); if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){ //Save edges of this node w/o renumbering. - tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); - tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); - tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); + tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); + tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); + tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); ++numberOfTemporaryEdges; - }else { + } else { //node is not yet contracted. //add (renumbered) outgoing edges to new DynamicGraph. _ContractorEdge newEdge; @@ -324,8 +324,8 @@ public: } } //Note the number of temporarily stored edges - tempStorage.seek(temporaryStorageSlotID, initialFilePosition); - tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); + tempStorage.Seek(temporaryStorageSlotID, initialFilePosition); + tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); //Delete map from old NodeIDs to new ones. std::vector().swap(newNodeIDFromOldNodeIDMap); @@ -498,16 +498,16 @@ public: TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); //Also get the edges from temporary storage unsigned numberOfTemporaryEdges = 0; - tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); + tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); //loads edges of graph before renumbering, no need for further numbering action. NodeID start; NodeID target; //edges.reserve(edges.size()+numberOfTemporaryEdges); _DynamicGraph::EdgeData data; for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) { - tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); - tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); - tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); + tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); + tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); + tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); Edge newEdge; newEdge.source = start; newEdge.target = target; @@ -518,7 +518,7 @@ public: newEdge.data.backward = data.backward; edges.push_back( newEdge ); } - tempStorage.deallocateSlot(temporaryStorageSlotID); + tempStorage.DeallocateSlot(temporaryStorageSlotID); } private: diff --git a/Contractor/TemporaryStorage.cpp b/Contractor/TemporaryStorage.cpp index 0a4fcb6ae..be56b2693 100644 --- a/Contractor/TemporaryStorage.cpp +++ b/Contractor/TemporaryStorage.cpp @@ -28,113 +28,137 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TemporaryStorage.h" TemporaryStorage::TemporaryStorage() { - tempDirectory = boost::filesystem::temp_directory_path(); + temp_directory = boost::filesystem::temp_directory_path(); } TemporaryStorage & TemporaryStorage::GetInstance(){ - static TemporaryStorage runningInstance; - return runningInstance; + static TemporaryStorage static_instance; + return static_instance; } TemporaryStorage::~TemporaryStorage() { - removeAll(); + RemoveAll(); + mutex.unlock(); } -void TemporaryStorage::removeAll() { +void TemporaryStorage::RemoveAll() { boost::mutex::scoped_lock lock(mutex); - for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) { - deallocateSlot(slot_id); + for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) { + DeallocateSlot(slot_id); } - vectorOfStreamDatas.clear(); + stream_data_list.clear(); } -int TemporaryStorage::allocateSlot() { +int TemporaryStorage::AllocateSlot() { boost::mutex::scoped_lock lock(mutex); try { - vectorOfStreamDatas.push_back(StreamData()); - //SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile; + stream_data_list.push_back(StreamData()); } catch(boost::filesystem::filesystem_error & e) { - abort(e); + Abort(e); } - return vectorOfStreamDatas.size() - 1; + CheckIfTemporaryDeviceFull(); + return stream_data_list.size() - 1; } -void TemporaryStorage::deallocateSlot(int slotID) { +void TemporaryStorage::DeallocateSlot(const int slot_id) { try { - StreamData & data = vectorOfStreamDatas[slotID]; + StreamData & data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - if(!boost::filesystem::exists(data.pathToTemporaryFile)) { + if(!boost::filesystem::exists(data.temp_path)) { return; } - if(data.streamToTemporaryFile->is_open()) { - data.streamToTemporaryFile->close(); + if(data.temp_file->is_open()) { + data.temp_file->close(); } - boost::filesystem::remove(data.pathToTemporaryFile); + boost::filesystem::remove(data.temp_path); } catch(boost::filesystem::filesystem_error & e) { - abort(e); + Abort(e); } } -void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) { +void TemporaryStorage::WriteToSlot( + const int slot_id, + char * pointer, + std::streamsize size +) { try { - StreamData & data = vectorOfStreamDatas[slotID]; + StreamData & data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); BOOST_ASSERT_MSG( - data.writeMode, + data.write_mode, "Writing after first read is not allowed" ); - data.streamToTemporaryFile->write(pointer, size); + data.temp_file->write(pointer, size); + CheckIfTemporaryDeviceFull(); } catch(boost::filesystem::filesystem_error & e) { - abort(e); + Abort(e); } } -void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) { +void TemporaryStorage::ReadFromSlot( + const int slot_id, + char * pointer, + std::streamsize size +) { try { - StreamData & data = vectorOfStreamDatas[slotID]; + StreamData & data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - if(data.writeMode) { - data.writeMode = false; - data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg); + if(data.write_mode) { + data.write_mode = false; + data.temp_file->seekg(0, data.temp_file->beg); } - data.streamToTemporaryFile->read(pointer, size); + data.temp_file->read(pointer, size); } catch(boost::filesystem::filesystem_error & e) { - abort(e); + Abort(e); } } -unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() { - boost::filesystem::space_info tempSpaceInfo; +uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() { + uint64_t value = -1; try { - tempSpaceInfo = boost::filesystem::space(tempDirectory); + boost::filesystem::path p = boost::filesystem::temp_directory_path(); + boost::filesystem::space_info s = boost::filesystem::space( p ); + value = s.free; } catch(boost::filesystem::filesystem_error & e) { - abort(e); + Abort(e); } - return tempSpaceInfo.available; + return value; } -boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) { +void TemporaryStorage::CheckIfTemporaryDeviceFull() { + boost::filesystem::path p = boost::filesystem::temp_directory_path(); + boost::filesystem::space_info s = boost::filesystem::space( p ); + if(1024*1024 > s.free) { + throw OSRMException("temporary device is full"); + } +} + +boost::filesystem::fstream::pos_type TemporaryStorage::Tell(int slot_id) { boost::filesystem::fstream::pos_type position; try { - StreamData & data = vectorOfStreamDatas[slotID]; + StreamData & data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - position = data.streamToTemporaryFile->tellp(); + position = data.temp_file->tellp(); } catch(boost::filesystem::filesystem_error & e) { - abort(e); - } + Abort(e); + } return position; } -void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) { - removeAll(); +void TemporaryStorage::Abort(boost::filesystem::filesystem_error& e) { + RemoveAll(); + throw OSRMException(e.what()); } -void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) { +void TemporaryStorage::Seek( + const int slot_id, + const boost::filesystem::fstream::pos_type position +) { try { - StreamData & data = vectorOfStreamDatas[slotID]; + StreamData & data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - data.streamToTemporaryFile->seekg(position); + data.temp_file->seekg(position); } catch(boost::filesystem::filesystem_error & e) { - abort(e); + Abort(e); } } diff --git a/Contractor/TemporaryStorage.h b/Contractor/TemporaryStorage.h index 214d0b325..9a2a19d01 100644 --- a/Contractor/TemporaryStorage.h +++ b/Contractor/TemporaryStorage.h @@ -28,46 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TEMPORARYSTORAGE_H_ #define TEMPORARYSTORAGE_H_ -#include -#include - -#include -#include -#include -#include -#include -#include - +#include "../Util/BoostFileSystemFix.h" #include "../Util/OSRMException.h" #include "../Util/SimpleLogger.h" #include "../typedefs.h" -//This is one big workaround for latest boost renaming woes. +#include +#include +#include +#include +#include +#include +#include +#include -#if BOOST_FILESYSTEM_VERSION < 3 -#warning Boost Installation with Filesystem3 missing, activating workaround -#include -namespace boost { -namespace filesystem { -inline path temp_directory_path() { - char * buffer; - buffer = tmpnam (NULL); +#include +#include - return path(buffer); -} - -inline path unique_path(const path&) { - return temp_directory_path(); -} - -} -} - -#endif - -#ifndef BOOST_FILESYSTEM_VERSION -#define BOOST_FILESYSTEM_VERSION 3 -#endif /** * This class implements a singleton file storage for temporary data. * temporary slots can be accessed by other objects through an int @@ -77,48 +54,63 @@ inline path unique_path(const path&) { * -> Data is written in first phase and reread in second. */ -static boost::filesystem::path tempDirectory; +static boost::filesystem::path temp_directory; static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%"); class TemporaryStorage { public: static TemporaryStorage & GetInstance(); virtual ~TemporaryStorage(); - int allocateSlot(); - void deallocateSlot(int slotID); - void writeToSlot(int slotID, char * pointer, std::streamsize size); - void readFromSlot(int slotID, char * pointer, std::streamsize size); + int AllocateSlot(); + void DeallocateSlot(const int slot_id); + void WriteToSlot(const int slot_id, char * pointer, std::streamsize size); + void ReadFromSlot(const int slot_id, char * pointer, std::streamsize size); //returns the number of free bytes - unsigned getFreeBytesOnTemporaryDevice(); - boost::filesystem::fstream::pos_type tell(int slotID); - void seek(int slotID, boost::filesystem::fstream::pos_type); - void removeAll(); + uint64_t GetFreeBytesOnTemporaryDevice(); + boost::filesystem::fstream::pos_type Tell(int slot_id); + void Seek(const int slot_id, boost::filesystem::fstream::pos_type); + void RemoveAll(); private: TemporaryStorage(); TemporaryStorage(TemporaryStorage const &){}; - TemporaryStorage& operator=(TemporaryStorage const &) { + + TemporaryStorage & operator=(TemporaryStorage const &) { return *this; } - void abort(boost::filesystem::filesystem_error& e); + + void Abort(boost::filesystem::filesystem_error& e); + void CheckIfTemporaryDeviceFull(); struct StreamData { - bool writeMode; - boost::filesystem::path pathToTemporaryFile; - boost::shared_ptr streamToTemporaryFile; + bool write_mode; + boost::filesystem::path temp_path; + boost::shared_ptr temp_file; boost::shared_ptr readWriteMutex; StreamData() : - writeMode(true), - pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))), - streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)), - readWriteMutex(new boost::mutex) + write_mode(true), + temp_path( + boost::filesystem::unique_path( + temp_directory.append( + TemporaryFilePattern.begin(), + TemporaryFilePattern.end() + ) + ) + ), + temp_file( + new boost::filesystem::fstream( + temp_path, + std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary + ) + ), + readWriteMutex(boost::make_shared()) { - if(streamToTemporaryFile->fail()) { + if(temp_file->fail()) { throw OSRMException("temporary file could not be created"); } } }; //vector of file streams that is used to store temporary data - std::vector vectorOfStreamDatas; + std::vector stream_data_list; boost::mutex mutex; }; From ad5d8c6f9a9f4636b5feff260b2d3d5fca5f0879 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 28 Nov 2013 15:24:23 +0100 Subject: [PATCH 17/29] remove dead code --- Contractor/EdgeBasedGraphFactory.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index dd2edb94f..1f4e4c883 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -115,15 +115,6 @@ private: bool contraFlow:1; }; - struct _EdgeBasedEdgeData { - int distance; - unsigned via; - unsigned nameID; - bool forward; - bool backward; - TurnInstruction turnInstruction; - }; - unsigned m_turn_restrictions_count; typedef DynamicGraph NodeBasedDynamicGraph; From 94d5bcbf1cf5ccf33831db59eb269945a4e960d3 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 28 Nov 2013 15:26:13 +0100 Subject: [PATCH 18/29] partially fixes #768, #794, #812 --- Contractor/EdgeBasedGraphFactory.cpp | 158 ++++++++++++++------------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index ceabf3bfa..b9219fcab 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -292,9 +292,8 @@ void EdgeBasedGraphFactory::Run( //linear number of turns only. p.reinit(m_node_based_graph->GetNumberOfNodes()); for( - NodeIterator u = 0, - last_node = m_node_based_graph->GetNumberOfNodes(); - u < last_node; + NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); + u < end; ++u ) { for( @@ -304,9 +303,12 @@ void EdgeBasedGraphFactory::Run( ++e1 ) { ++node_based_edge_counter; - NodeIterator v = m_node_based_graph->GetTarget(e1); - const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); - NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); + const NodeIterator v = m_node_based_graph->GetTarget(e1); + const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); + + + bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); + for( EdgeIterator e2 = m_node_based_graph->BeginEdges(v), last_edge_v = m_node_based_graph->EndEdges(v); @@ -323,77 +325,82 @@ void EdgeBasedGraphFactory::Run( continue; } + if( is_barrier_node && (u != w) ) { + ++skipped_turns_counter; + continue; + } + if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) { continue; } - if( !is_barrier_node ) { - //only add an edge if turn is not a U-turn except when it is - //at the end of a dead-end street - if ( - !CheckIfTurnIsRestricted(u, v, w) || - (to_node_of_only_restriction != UINT_MAX && w == to_node_of_only_restriction) - ) { //only add an edge if turn is not prohibited - const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1); - const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2); - BOOST_ASSERT( - edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() - ); - BOOST_ASSERT( - edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() - ); - - if(!edge_data1.forward || !edge_data2.forward) { - continue; - } - - unsigned distance = edge_data1.distance; - if(m_traffic_lights.find(v) != m_traffic_lights.end()) { - distance += speed_profile.trafficSignalPenalty; - } - const unsigned penalty = - GetTurnPenalty(u, v, w, lua_state); - TurnInstruction turnInstruction = AnalyzeTurn(u, v, w); - if(turnInstruction == TurnInstructions.UTurn){ - distance += speed_profile.uTurnPenalty; - } - distance += penalty; - - BOOST_ASSERT( - edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID - ); - - original_edge_data_vector.push_back( - OriginalEdgeData( - v, - edge_data2.nameID, - turnInstruction - ) - ); - ++original_edges_counter; - - if(original_edge_data_vector.size() > 100000) { - edge_data_file.write( - (char*)&(original_edge_data_vector[0]), - original_edge_data_vector.size()*sizeof(OriginalEdgeData) - ); - original_edge_data_vector.clear(); - } - - m_edge_based_edge_list.push_back( - EdgeBasedEdge( - edge_data1.edgeBasedNodeID, - edge_data2.edgeBasedNodeID, - m_edge_based_edge_list.size(), - distance, - true, - false - ) - ); - } else { - ++skipped_turns_counter; - } + //only add an edge if turn is not a U-turn except when it is + //at the end of a dead-end street + if ( + CheckIfTurnIsRestricted(u, v, w) && + (to_node_of_only_restriction == UINT_MAX) && + (w != to_node_of_only_restriction) + ) { + ++skipped_turns_counter; + continue; } + + //only add an edge if turn is not prohibited + const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1); + const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2); + BOOST_ASSERT( + edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() + ); + BOOST_ASSERT( + edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() + ); + + if(!edge_data1.forward || !edge_data2.forward) { + continue; + } + + unsigned distance = edge_data1.distance; + if(m_traffic_lights.find(v) != m_traffic_lights.end()) { + distance += speed_profile.trafficSignalPenalty; + } + const unsigned penalty = GetTurnPenalty(u, v, w, lua_state); + TurnInstruction turnInstruction = AnalyzeTurn(u, v, w); + if(turnInstruction == TurnInstructions.UTurn){ + distance += speed_profile.uTurnPenalty; + } + distance += penalty; + + BOOST_ASSERT( + edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID + ); + + original_edge_data_vector.push_back( + OriginalEdgeData( + v, + edge_data2.nameID, + turnInstruction + ) + ); + ++original_edges_counter; + + if(original_edge_data_vector.size() > 100000) { + edge_data_file.write( + (char*)&(original_edge_data_vector[0]), + original_edge_data_vector.size()*sizeof(OriginalEdgeData) + ); + original_edge_data_vector.clear(); + } + + m_edge_based_edge_list.push_back( + EdgeBasedEdge( + edge_data1.edgeBasedNodeID, + edge_data2.edgeBasedNodeID, + m_edge_based_edge_list.size(), + distance, + true, + false + ) + ); } } p.printIncrement(); @@ -402,11 +409,8 @@ void EdgeBasedGraphFactory::Run( (char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData) ); - edge_data_file.seekp(std::ios::beg); - edge_data_file.write( - (char*)&original_edges_counter, - sizeof(unsigned) - ); + edge_data_file.seekp( std::ios::beg ); + edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); edge_data_file.close(); SimpleLogger().Write() << From 78f8124c630ecdeb0ef9caddd458b2f9aab51f5b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Thu, 28 Nov 2013 18:50:12 +0100 Subject: [PATCH 19/29] further refactoring and code simplification --- Contractor/EdgeBasedGraphFactory.cpp | 72 ++++++++++++++++------------ Contractor/EdgeBasedGraphFactory.h | 5 ++ 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index b9219fcab..5ce7434b6 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -202,11 +202,30 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( m_edge_based_node_list.push_back(currentNode); } + +void EdgeBasedGraphFactory::FlushVectorToStream( + std::ofstream & edge_data_file, + std::vector & original_edge_data_vector +) const { + edge_data_file.write( + (char*)&(original_edge_data_vector[0]), + original_edge_data_vector.size()*sizeof(OriginalEdgeData) + ); + original_edge_data_vector.clear(); +} + void EdgeBasedGraphFactory::Run( const char * original_edge_data_filename, lua_State *lua_state ) { SimpleLogger().Write() << "Compressing geometry of input graph"; + //TODO: iterate over all turns + + //TODO: compress geometries + + //TODO: update turn restrictions if concerned by compression + + //TODO: do some compression statistics SimpleLogger().Write() << "Identifying components of the road network"; @@ -271,8 +290,7 @@ void EdgeBasedGraphFactory::Run( SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " nodes in " << "edge-expanded graph"; - SimpleLogger().Write() << - "generating edge-expanded edges"; + SimpleLogger().Write() << "generating edge-expanded edges"; std::vector().swap(component_index_size); BOOST_ASSERT_MSG( @@ -305,9 +323,7 @@ void EdgeBasedGraphFactory::Run( ++node_based_edge_counter; const NodeIterator v = m_node_based_graph->GetTarget(e1); const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); - - - bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); + const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); for( EdgeIterator e2 = m_node_based_graph->BeginEdges(v), @@ -330,7 +346,7 @@ void EdgeBasedGraphFactory::Run( continue; } - if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) { + if( (u == w) && (1 != m_node_based_graph->GetOutDegree(v)) ) { continue; } @@ -348,19 +364,22 @@ void EdgeBasedGraphFactory::Run( //only add an edge if turn is not prohibited const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1); const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2); + BOOST_ASSERT( edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() ); BOOST_ASSERT( edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() ); + BOOST_ASSERT( + edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID + ); + BOOST_ASSERT( edge_data1.forward ); + BOOST_ASSERT( edge_data2.forward ); - if(!edge_data1.forward || !edge_data2.forward) { - continue; - } - + // the following is the core of the loop. unsigned distance = edge_data1.distance; - if(m_traffic_lights.find(v) != m_traffic_lights.end()) { + if( m_traffic_lights.find(v) != m_traffic_lights.end() ) { distance += speed_profile.trafficSignalPenalty; } const unsigned penalty = GetTurnPenalty(u, v, w, lua_state); @@ -370,10 +389,6 @@ void EdgeBasedGraphFactory::Run( } distance += penalty; - BOOST_ASSERT( - edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID - ); - original_edge_data_vector.push_back( OriginalEdgeData( v, @@ -384,11 +399,10 @@ void EdgeBasedGraphFactory::Run( ++original_edges_counter; if(original_edge_data_vector.size() > 100000) { - edge_data_file.write( - (char*)&(original_edge_data_vector[0]), - original_edge_data_vector.size()*sizeof(OriginalEdgeData) + FlushVectorToStream( + edge_data_file, + original_edge_data_vector ); - original_edge_data_vector.clear(); } m_edge_based_edge_list.push_back( @@ -405,10 +419,8 @@ void EdgeBasedGraphFactory::Run( } p.printIncrement(); } - edge_data_file.write( - (char*)&(original_edge_data_vector[0]), - original_edge_data_vector.size()*sizeof(OriginalEdgeData) - ); + FlushVectorToStream( edge_data_file, original_edge_data_vector ); + edge_data_file.seekp( std::ios::beg ); edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); edge_data_file.close(); @@ -462,11 +474,11 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( return TurnInstructions.UTurn; } - EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v); - EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w); + const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v); + const EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w); - EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1); - EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2); + const EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1); + const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2); if(!data1.contraFlow && data2.contraFlow) { return TurnInstructions.EnterAgainstAllowedDirection; @@ -513,7 +525,6 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( m_node_info_list[v], m_node_info_list[w] ); - return TurnInstructions.GetTurnDirectionOfInstruction(angle); } @@ -538,7 +549,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( UINT_MAX ); - //put unexplorered node with parent pointer into queue + //put unexplorered node with parent pointer into queue for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) { if(UINT_MAX == component_index_list[node]) { bfs_queue.push(std::make_pair(node, node)); @@ -558,7 +569,6 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( if(!is_barrier_node) { const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); - //relaxieren edge outgoing edge like below where edge-expanded m_node_based_graph for( EdgeIterator e2 = m_node_based_graph->BeginEdges(v); e2 < m_node_based_graph->EndEdges(v); @@ -570,7 +580,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( to_node_of_only_restriction != UINT_MAX && w != to_node_of_only_restriction ) { - //We are at an only_-restriction but not at the right turn. + // At an only_-restriction but not at the right turn continue; } if( u != w ) { diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 1f4e4c883..053a6bfe9 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -160,6 +160,11 @@ private: std::vector & component_index_list, std::vector & component_index_size ) const; + + void FlushVectorToStream( + std::ofstream & edge_data_file, + std::vector & original_edge_data_vector + ) const; }; #endif /* EDGEBASEDGRAPHFACTORY_H_ */ From 40bb27c95fda8cac2b131f00d1d0846da6ab1acf Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 29 Nov 2013 15:38:15 +0100 Subject: [PATCH 20/29] add buffering to temporary storage --- Contractor/TemporaryStorage.cpp | 45 ++++++++++++++++----------------- prepare.cpp | 5 +++- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Contractor/TemporaryStorage.cpp b/Contractor/TemporaryStorage.cpp index be56b2693..acb88f8a9 100644 --- a/Contractor/TemporaryStorage.cpp +++ b/Contractor/TemporaryStorage.cpp @@ -80,17 +80,25 @@ void TemporaryStorage::DeallocateSlot(const int slot_id) { void TemporaryStorage::WriteToSlot( const int slot_id, char * pointer, - std::streamsize size + const std::size_t size ) { try { StreamData & data = stream_data_list[slot_id]; + BOOST_ASSERT(data.write_mode); + boost::mutex::scoped_lock lock(*data.readWriteMutex); BOOST_ASSERT_MSG( data.write_mode, "Writing after first read is not allowed" ); - data.temp_file->write(pointer, size); - CheckIfTemporaryDeviceFull(); + if( 1073741824 < data.buffer.size() ) { + data.temp_file->write(&data.buffer[0], data.buffer.size()); + // data.temp_file->write(pointer, size); + data.buffer.clear(); + CheckIfTemporaryDeviceFull(); + } + data.buffer.insert(data.buffer.end(), pointer, pointer+size); + } catch(boost::filesystem::filesystem_error & e) { Abort(e); } @@ -98,15 +106,19 @@ void TemporaryStorage::WriteToSlot( void TemporaryStorage::ReadFromSlot( const int slot_id, char * pointer, - std::streamsize size + const std::size_t size ) { try { StreamData & data = stream_data_list[slot_id]; boost::mutex::scoped_lock lock(*data.readWriteMutex); - if(data.write_mode) { + if( data.write_mode ) { data.write_mode = false; - data.temp_file->seekg(0, data.temp_file->beg); + data.temp_file->write(&data.buffer[0], data.buffer.size()); + data.buffer.clear(); + data.temp_file->seekg( data.temp_file->beg ); + BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() ); } + BOOST_ASSERT( !data.write_mode ); data.temp_file->read(pointer, size); } catch(boost::filesystem::filesystem_error & e) { Abort(e); @@ -126,14 +138,14 @@ uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() { } void TemporaryStorage::CheckIfTemporaryDeviceFull() { - boost::filesystem::path p = boost::filesystem::temp_directory_path(); + boost::filesystem::path p = boost::filesystem::temp_directory_path(); boost::filesystem::space_info s = boost::filesystem::space( p ); - if(1024*1024 > s.free) { + if( (1024*1024) > s.free ) { throw OSRMException("temporary device is full"); } } -boost::filesystem::fstream::pos_type TemporaryStorage::Tell(int slot_id) { +boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) { boost::filesystem::fstream::pos_type position; try { StreamData & data = stream_data_list[slot_id]; @@ -145,20 +157,7 @@ boost::filesystem::fstream::pos_type TemporaryStorage::Tell(int slot_id) { return position; } -void TemporaryStorage::Abort(boost::filesystem::filesystem_error& e) { +void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) { RemoveAll(); throw OSRMException(e.what()); } - -void TemporaryStorage::Seek( - const int slot_id, - const boost::filesystem::fstream::pos_type position -) { - try { - StreamData & data = stream_data_list[slot_id]; - boost::mutex::scoped_lock lock(*data.readWriteMutex); - data.temp_file->seekg(position); - } catch(boost::filesystem::filesystem_error & e) { - Abort(e); - } -} diff --git a/prepare.cpp b/prepare.cpp index 6bc98967c..3374c2722 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -321,7 +321,6 @@ int main (int argc, char *argv[]) { * Sorting contracted edges in a way that the static query graph can read some in in-place. */ - SimpleLogger().Write() << "Building Node Array"; std::sort(contractedEdgeList.begin(), contractedEdgeList.end()); unsigned numberOfNodes = 0; unsigned numberOfEdges = contractedEdgeList.size(); @@ -333,6 +332,8 @@ int main (int argc, char *argv[]) { std::ofstream hsgr_output_stream(graphOut.c_str(), std::ios::binary); hsgr_output_stream.write((char*)&uuid_orig, sizeof(UUID) ); BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { + BOOST_ASSERT( UINT32_MAX != edge.source ); + BOOST_ASSERT( UINT32_MAX != edge.target ); if(edge.source > numberOfNodes) { numberOfNodes = edge.source; } @@ -373,8 +374,10 @@ int main (int argc, char *argv[]) { hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph::_StrNode)*(numberOfNodes)); //serialize all edges --numberOfNodes; + edge = 0; int usedEdgeCounter = 0; + SimpleLogger().Write() << "Building Node Array"; 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 ) { From c8f7e6331be7ae6da62c8cead5a601e4c9e46682 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 29 Nov 2013 15:38:21 +0100 Subject: [PATCH 21/29] add buffering to temporary storage --- Contractor/TemporaryStorage.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Contractor/TemporaryStorage.h b/Contractor/TemporaryStorage.h index 9a2a19d01..e929836c5 100644 --- a/Contractor/TemporaryStorage.h +++ b/Contractor/TemporaryStorage.h @@ -63,12 +63,11 @@ public: int AllocateSlot(); void DeallocateSlot(const int slot_id); - void WriteToSlot(const int slot_id, char * pointer, std::streamsize size); - void ReadFromSlot(const int slot_id, char * pointer, std::streamsize size); + void WriteToSlot(const int slot_id, char * pointer, const std::size_t size); + void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size); //returns the number of free bytes uint64_t GetFreeBytesOnTemporaryDevice(); - boost::filesystem::fstream::pos_type Tell(int slot_id); - void Seek(const int slot_id, boost::filesystem::fstream::pos_type); + boost::filesystem::fstream::pos_type Tell(const int slot_id); void RemoveAll(); private: TemporaryStorage(); @@ -78,7 +77,7 @@ private: return *this; } - void Abort(boost::filesystem::filesystem_error& e); + void Abort(const boost::filesystem::filesystem_error& e); void CheckIfTemporaryDeviceFull(); struct StreamData { @@ -86,6 +85,8 @@ private: boost::filesystem::path temp_path; boost::shared_ptr temp_file; boost::shared_ptr readWriteMutex; + std::vector buffer; + StreamData() : write_mode(true), temp_path( @@ -104,14 +105,14 @@ private: ), readWriteMutex(boost::make_shared()) { - if(temp_file->fail()) { + if( temp_file->fail() ) { throw OSRMException("temporary file could not be created"); } } }; //vector of file streams that is used to store temporary data - std::vector stream_data_list; boost::mutex mutex; + std::vector stream_data_list; }; #endif /* TEMPORARYSTORAGE_H_ */ From 48355447f9796ff3ab99ff6b6c0db3817860abfe Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 29 Nov 2013 16:27:26 +0100 Subject: [PATCH 22/29] do not seek in temporary storage --- Contractor/Contractor.h | 93 +++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 46925603e..469248700 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -54,10 +54,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class Contractor { private: - struct _ContractorEdgeData { - _ContractorEdgeData() : + struct ContractorEdgeData { + ContractorEdgeData() : distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {} - _ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) : + ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) : distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {} unsigned distance; unsigned id; @@ -75,7 +75,7 @@ private: _HeapData( short h, bool t ) : hop(h), target(t) {} }; - typedef DynamicGraph< _ContractorEdgeData > _DynamicGraph; + typedef DynamicGraph< ContractorEdgeData > _DynamicGraph; // typedef BinaryHeap< NodeID, NodeID, int, _HeapData, ArrayStorage > _Heap; typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage > _Heap; typedef _DynamicGraph::InputEdge _ContractorEdge; @@ -118,6 +118,7 @@ public: Contractor( int nodes, ContainerT& inputEdges) { std::vector< _ContractorEdge > edges; edges.reserve(inputEdges.size()*2); + temp_edge_counter = 0; typename ContainerT::deallocation_iterator diter = inputEdges.dbegin(); typename ContainerT::deallocation_iterator dend = inputEdges.dend(); @@ -126,7 +127,7 @@ public: while(diter!=dend) { newEdge.source = diter->source(); newEdge.target = diter->target(); - newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward()); + newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward()); BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" ); #ifndef NDEBUG @@ -195,6 +196,7 @@ public: _graph = boost::make_shared<_DynamicGraph>( nodes, edges ); edges.clear(); std::vector<_ContractorEdge>().swap(edges); + BOOST_ASSERT( 0 == edges.capacity() ); // unsigned maxdegree = 0; // NodeID highestNode = 0; // @@ -214,14 +216,14 @@ public: //Create temporary file // GetTemporaryFileName(temporaryEdgeStorageFilename); - temporaryStorageSlotID = TemporaryStorage::GetInstance().AllocateSlot(); + edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot(); std::cout << "contractor finished initalization" << std::endl; } ~Contractor() { //Delete temporary file // remove(temporaryEdgeStorageFilename.c_str()); - TemporaryStorage::GetInstance().DeallocateSlot(temporaryStorageSlotID); + TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot); } void Run() { @@ -264,11 +266,11 @@ public: std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush; //Delete old heap data to free memory that we need for the coming operations - BOOST_FOREACH(_ThreadData * data, threadData) + BOOST_FOREACH(_ThreadData * data, threadData) { delete data; + } threadData.clear(); - //Create new priority array std::vector newNodePriority(remainingNodes.size()); //this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction @@ -285,12 +287,6 @@ public: remainingNodes[newNodeID].id = newNodeID; } TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); - //Write dummy number of edges to temporary file - // std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary); - uint64_t initialFilePosition = tempStorage.Tell(temporaryStorageSlotID); - unsigned numberOfTemporaryEdges = 0; - tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); - //walk over all nodes for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) { const NodeID start = i; @@ -299,10 +295,10 @@ public: const NodeID target = _graph->GetTarget(currentEdge); if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){ //Save edges of this node w/o renumbering. - tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); - tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); - tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); - ++numberOfTemporaryEdges; + tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID)); + tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID)); + tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData)); + ++temp_edge_counter; } else { //node is not yet contracted. //add (renumbered) outgoing edges to new DynamicGraph. @@ -323,9 +319,6 @@ public: } } } - //Note the number of temporarily stored edges - tempStorage.Seek(temporaryStorageSlotID, initialFilePosition); - tempStorage.WriteToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); //Delete map from old NodeIDs to new ones. std::vector().swap(newNodeIDFromOldNodeIDMap); @@ -454,13 +447,13 @@ public: SimpleLogger().Write() << "Getting edges of minimized graph"; NodeID numberOfNodes = _graph->GetNumberOfNodes(); if(_graph->GetNumberOfNodes()) { + Edge newEdge; 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; - if(0 != oldNodeIDFromNewNodeIDMap.size()) { + if( !oldNodeIDFromNewNodeIDMap.empty() ) { newEdge.source = oldNodeIDFromNewNodeIDMap[node]; newEdge.target = oldNodeIDFromNewNodeIDMap[target]; } else { @@ -477,7 +470,10 @@ public: ); newEdge.data.distance = data.distance; newEdge.data.shortcut = data.shortcut; - if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) { + if( + !data.originalViaNodeID && + !oldNodeIDFromNewNodeIDMap.empty() + ) { newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id]; } else { newEdge.data.id = data.id; @@ -494,31 +490,29 @@ public: } _graph.reset(); std::vector().swap(oldNodeIDFromNewNodeIDMap); + BOOST_ASSERT( 0 == oldNodeIDFromNewNodeIDMap.capacity() ); TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); - //Also get the edges from temporary storage - unsigned numberOfTemporaryEdges = 0; - tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned)); //loads edges of graph before renumbering, no need for further numbering action. NodeID start; NodeID target; - //edges.reserve(edges.size()+numberOfTemporaryEdges); _DynamicGraph::EdgeData data; - for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) { - tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); - tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); - tempStorage.ReadFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); - Edge newEdge; - newEdge.source = start; - newEdge.target = target; - newEdge.data.distance = data.distance; - newEdge.data.shortcut = data.shortcut; - newEdge.data.id = data.id; - newEdge.data.forward = data.forward; - newEdge.data.backward = data.backward; - edges.push_back( newEdge ); + + Edge restored_edge; + for(unsigned i = 0; i < temp_edge_counter; ++i) { + tempStorage.ReadFromSlot(edge_storage_slot, (char*)&start, sizeof(NodeID)); + tempStorage.ReadFromSlot(edge_storage_slot, (char*)&target, sizeof(NodeID)); + tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData)); + restored_edge.source = start; + restored_edge.target = target; + restored_edge.data.distance = data.distance; + restored_edge.data.shortcut = data.shortcut; + restored_edge.data.id = data.id; + restored_edge.data.forward = data.forward; + restored_edge.data.backward = data.backward; + edges.push_back( restored_edge ); } - tempStorage.DeallocateSlot(temporaryStorageSlotID); + tempStorage.DeallocateSlot(edge_storage_slot); } private: @@ -548,7 +542,7 @@ private: //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 ); + const ContractorEdgeData& data = _graph->GetEdgeData( edge ); if ( !data.forward ){ continue; } @@ -594,7 +588,7 @@ private: std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges; for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) { - const _ContractorEdgeData& inData = _graph->GetEdgeData( inEdge ); + const ContractorEdgeData& inData = _graph->GetEdgeData( inEdge ); const NodeID source = _graph->GetTarget( inEdge ); if ( Simulate ) { assert( stats != NULL ); @@ -610,7 +604,7 @@ private: unsigned numTargets = 0; for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { - const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); + const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); if ( !outData.forward ) { continue; } @@ -629,7 +623,7 @@ private: _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 ); + const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); if ( !outData.forward ) { continue; } @@ -645,7 +639,7 @@ private: _ContractorEdge newEdge; newEdge.source = source; newEdge.target = target; - newEdge.data = _ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);; + newEdge.data = ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);; insertedEdges.push_back( newEdge ); std::swap( newEdge.source, newEdge.target ); newEdge.data.forward = false; @@ -784,7 +778,8 @@ private: boost::shared_ptr<_DynamicGraph> _graph; std::vector<_DynamicGraph::InputEdge> contractedEdges; - unsigned temporaryStorageSlotID; + unsigned edge_storage_slot; + uint64_t temp_edge_counter; std::vector oldNodeIDFromNewNodeIDMap; XORFastHash fastHash; }; From 657f7577bf07217275b260afbc651243f10734e6 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 29 Nov 2013 16:37:36 +0100 Subject: [PATCH 23/29] don't use clang specific defines --- prepare.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prepare.cpp b/prepare.cpp index 3374c2722..b91be6fcf 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -332,8 +332,8 @@ int main (int argc, char *argv[]) { std::ofstream hsgr_output_stream(graphOut.c_str(), std::ios::binary); hsgr_output_stream.write((char*)&uuid_orig, sizeof(UUID) ); BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { - BOOST_ASSERT( UINT32_MAX != edge.source ); - BOOST_ASSERT( UINT32_MAX != edge.target ); + BOOST_ASSERT( UINT_MAX != edge.source ); + BOOST_ASSERT( UINT_MAX != edge.target ); if(edge.source > numberOfNodes) { numberOfNodes = edge.source; } From 7a5f45ac94f783ecd7dfe831b354f6ac3865e575 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 29 Nov 2013 18:49:02 +0100 Subject: [PATCH 24/29] add skeleton for geometry compression --- Contractor/EdgeBasedGraphFactory.cpp | 108 ++++++++++++++++++++------- Contractor/EdgeBasedGraphFactory.h | 17 ++++- 2 files changed, 98 insertions(+), 27 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 5ce7434b6..c5f4cf3b5 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -27,6 +27,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "EdgeBasedGraphFactory.h" +//TODO: CompressionWorker +//TODO: EdgeBasedEdgeGenerator + +// template +// inline static void TraverseGraph(NodeBasedDynamicGraph & graph, Work & work) { + +// } + EdgeBasedGraphFactory::EdgeBasedGraphFactory( int number_of_nodes, std::vector & input_edge_list, @@ -35,10 +43,8 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( std::vector & input_restrictions_list, std::vector & m_node_info_list, SpeedProfileProperties speed_profile -) : speed_profile(speed_profile), - m_turn_restrictions_count(0), - m_node_info_list(m_node_info_list) -{ +) : speed_profile(speed_profile), m_node_info_list(m_node_info_list) { + BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) { std::pair restriction_source = std::make_pair(restriction.fromNode, restriction.viaNode); @@ -56,11 +62,11 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( continue; } else if(restriction.flags.isOnly) { //We are going to insert an is_only_*-restriction. There can be only one. - m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size(); + stats.turn_restrictions_count -= m_restriction_bucket_list.at(index).size(); m_restriction_bucket_list.at(index).clear(); } } - ++m_turn_restrictions_count; + ++stats.turn_restrictions_count; m_restriction_bucket_list.at(index).push_back( std::make_pair( restriction.toNode, restriction.flags.isOnly) ); @@ -219,21 +225,73 @@ void EdgeBasedGraphFactory::Run( lua_State *lua_state ) { SimpleLogger().Write() << "Compressing geometry of input graph"; - //TODO: iterate over all turns + Percent p(m_node_based_graph->GetNumberOfNodes()); + // iterate over all turns + for( + NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); + u < end; + ++u + ) { + for( + EdgeIterator e1 = m_node_based_graph->BeginEdges(u), + last_edge_u = m_node_based_graph->EndEdges(u); + e1 < last_edge_u; + ++e1 + ) { + ++stats.node_based_edge_counter; + const NodeIterator v = m_node_based_graph->GetTarget(e1); + const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); + const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); - //TODO: compress geometries + for( + EdgeIterator e2 = m_node_based_graph->BeginEdges(v), + last_edge_v = m_node_based_graph->EndEdges(v); + e2 < last_edge_v; + ++e2 + ) { + const NodeIterator w = m_node_based_graph->GetTarget(e2); + if( + to_node_of_only_restriction != UINT_MAX && + w != to_node_of_only_restriction + ) { + //We are at an only_-restriction but not at the right turn. + ++stats.skipped_turns_counter; + continue; + } - //TODO: update turn restrictions if concerned by compression + if( is_barrier_node && (u != w) ) { + ++stats.skipped_turns_counter; + continue; + } - //TODO: do some compression statistics + if( (u == w) && (1 != m_node_based_graph->GetOutDegree(v)) ) { + continue; + } + + //only add an edge if turn is not a U-turn except when it is + //at the end of a dead-end street + if ( + CheckIfTurnIsRestricted(u, v, w) && + (to_node_of_only_restriction == UINT_MAX) && + (w != to_node_of_only_restriction) + ) { + ++stats.skipped_turns_counter; + continue; + } + + //TODO: compress geometries, edgedata is congruent + + //TODO: update turn restrictions if concerned by compression + + } + } + } + + //TODO: print compression statistics SimpleLogger().Write() << "Identifying components of the road network"; - unsigned skipped_turns_counter = 0; - unsigned node_based_edge_counter = 0; - unsigned original_edges_counter = 0; - std::ofstream edge_data_file( original_edge_data_filename, std::ios::binary @@ -241,7 +299,7 @@ void EdgeBasedGraphFactory::Run( //writes a dummy value that is updated later edge_data_file.write( - (char*)&original_edges_counter, + (char*)&stats.original_edges_counter, sizeof(unsigned) ); @@ -255,7 +313,7 @@ void EdgeBasedGraphFactory::Run( SimpleLogger().Write() << "generating edge-expanded nodes"; - Percent p(m_node_based_graph->GetNumberOfNodes()); + p.reinit(m_node_based_graph->GetNumberOfNodes()); //loop over all edges and generate new set of nodes. for( NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); @@ -320,7 +378,7 @@ void EdgeBasedGraphFactory::Run( e1 < last_edge_u; ++e1 ) { - ++node_based_edge_counter; + ++stats.node_based_edge_counter; const NodeIterator v = m_node_based_graph->GetTarget(e1); const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); @@ -337,12 +395,12 @@ void EdgeBasedGraphFactory::Run( w != to_node_of_only_restriction ) { //We are at an only_-restriction but not at the right turn. - ++skipped_turns_counter; + ++stats.skipped_turns_counter; continue; } if( is_barrier_node && (u != w) ) { - ++skipped_turns_counter; + ++stats.skipped_turns_counter; continue; } @@ -357,7 +415,7 @@ void EdgeBasedGraphFactory::Run( (to_node_of_only_restriction == UINT_MAX) && (w != to_node_of_only_restriction) ) { - ++skipped_turns_counter; + ++stats.skipped_turns_counter; continue; } @@ -396,7 +454,7 @@ void EdgeBasedGraphFactory::Run( turnInstruction ) ); - ++original_edges_counter; + ++stats.original_edges_counter; if(original_edge_data_vector.size() > 100000) { FlushVectorToStream( @@ -422,20 +480,20 @@ void EdgeBasedGraphFactory::Run( FlushVectorToStream( edge_data_file, original_edge_data_vector ); edge_data_file.seekp( std::ios::beg ); - edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); + edge_data_file.write( (char*)&stats.original_edges_counter, sizeof(unsigned) ); edge_data_file.close(); SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes"; SimpleLogger().Write() << - "Node-based graph contains " << node_based_edge_counter << " edges"; + "Node-based graph contains " << stats.node_based_edge_counter << " edges"; SimpleLogger().Write() << "Edge-expanded graph ..."; SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges"; SimpleLogger().Write() << - " skips " << skipped_turns_counter << " turns, " - "defined by " << m_turn_restrictions_count << " restrictions"; + " skips " << stats.skipped_turns_counter << " turns, " + "defined by " << stats.turn_restrictions_count << " restrictions"; } int EdgeBasedGraphFactory::GetTurnPenalty( diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 053a6bfe9..97e18f650 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -101,6 +101,20 @@ public: unsigned GetNumberOfNodes() const; private: + struct EdgeBasedFactorStatistics { + EdgeBasedFactorStatistics() : + turn_restrictions_count(0), + skipped_turns_counter(0), + node_based_edge_counter(0), + original_edges_counter(0) + { } + + unsigned turn_restrictions_count; + unsigned skipped_turns_counter; + unsigned node_based_edge_counter; + unsigned original_edges_counter; + } stats; + struct NodeBasedEdgeData { int distance; unsigned edgeBasedNodeID; @@ -115,8 +129,6 @@ private: bool contraFlow:1; }; - unsigned m_turn_restrictions_count; - typedef DynamicGraph NodeBasedDynamicGraph; typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge; typedef NodeBasedDynamicGraph::NodeIterator NodeIterator; @@ -137,6 +149,7 @@ private: boost::unordered_set m_traffic_lights; RestrictionMap m_restriction_map; + GeometryCompressor m_geometry_compressor; NodeID CheckForEmanatingIsOnlyTurn( const NodeID u, From e32bc5e1868ec53123201b417a3218acc91cadea Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 29 Nov 2013 19:00:00 +0100 Subject: [PATCH 25/29] reverting skeleton, introducing later --- Contractor/EdgeBasedGraphFactory.cpp | 100 +++++++-------------------- Contractor/EdgeBasedGraphFactory.h | 17 +---- 2 files changed, 27 insertions(+), 90 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index c5f4cf3b5..36d94e2b8 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -43,8 +43,10 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( std::vector & input_restrictions_list, std::vector & m_node_info_list, SpeedProfileProperties speed_profile -) : speed_profile(speed_profile), m_node_info_list(m_node_info_list) { - +) : speed_profile(speed_profile), + m_turn_restrictions_count(0), + m_node_info_list(m_node_info_list) +{ BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) { std::pair restriction_source = std::make_pair(restriction.fromNode, restriction.viaNode); @@ -62,11 +64,11 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( continue; } else if(restriction.flags.isOnly) { //We are going to insert an is_only_*-restriction. There can be only one. - stats.turn_restrictions_count -= m_restriction_bucket_list.at(index).size(); + m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size(); m_restriction_bucket_list.at(index).clear(); } } - ++stats.turn_restrictions_count; + ++m_turn_restrictions_count; m_restriction_bucket_list.at(index).push_back( std::make_pair( restriction.toNode, restriction.flags.isOnly) ); @@ -225,73 +227,21 @@ void EdgeBasedGraphFactory::Run( lua_State *lua_state ) { SimpleLogger().Write() << "Compressing geometry of input graph"; - Percent p(m_node_based_graph->GetNumberOfNodes()); - // iterate over all turns - for( - NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); - u < end; - ++u - ) { - for( - EdgeIterator e1 = m_node_based_graph->BeginEdges(u), - last_edge_u = m_node_based_graph->EndEdges(u); - e1 < last_edge_u; - ++e1 - ) { - ++stats.node_based_edge_counter; - const NodeIterator v = m_node_based_graph->GetTarget(e1); - const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); - const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); + //TODO: iterate over all turns - for( - EdgeIterator e2 = m_node_based_graph->BeginEdges(v), - last_edge_v = m_node_based_graph->EndEdges(v); - e2 < last_edge_v; - ++e2 - ) { - const NodeIterator w = m_node_based_graph->GetTarget(e2); - if( - to_node_of_only_restriction != UINT_MAX && - w != to_node_of_only_restriction - ) { - //We are at an only_-restriction but not at the right turn. - ++stats.skipped_turns_counter; - continue; - } + //TODO: compress geometries - if( is_barrier_node && (u != w) ) { - ++stats.skipped_turns_counter; - continue; - } + //TODO: update turn restrictions if concerned by compression - if( (u == w) && (1 != m_node_based_graph->GetOutDegree(v)) ) { - continue; - } - - //only add an edge if turn is not a U-turn except when it is - //at the end of a dead-end street - if ( - CheckIfTurnIsRestricted(u, v, w) && - (to_node_of_only_restriction == UINT_MAX) && - (w != to_node_of_only_restriction) - ) { - ++stats.skipped_turns_counter; - continue; - } - - //TODO: compress geometries, edgedata is congruent - - //TODO: update turn restrictions if concerned by compression - - } - } - } - - //TODO: print compression statistics + //TODO: do some compression statistics SimpleLogger().Write() << "Identifying components of the road network"; + unsigned skipped_turns_counter = 0; + unsigned node_based_edge_counter = 0; + unsigned original_edges_counter = 0; + std::ofstream edge_data_file( original_edge_data_filename, std::ios::binary @@ -299,7 +249,7 @@ void EdgeBasedGraphFactory::Run( //writes a dummy value that is updated later edge_data_file.write( - (char*)&stats.original_edges_counter, + (char*)&original_edges_counter, sizeof(unsigned) ); @@ -313,7 +263,7 @@ void EdgeBasedGraphFactory::Run( SimpleLogger().Write() << "generating edge-expanded nodes"; - p.reinit(m_node_based_graph->GetNumberOfNodes()); + Percent p(m_node_based_graph->GetNumberOfNodes()); //loop over all edges and generate new set of nodes. for( NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); @@ -378,7 +328,7 @@ void EdgeBasedGraphFactory::Run( e1 < last_edge_u; ++e1 ) { - ++stats.node_based_edge_counter; + ++node_based_edge_counter; const NodeIterator v = m_node_based_graph->GetTarget(e1); const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); @@ -395,12 +345,12 @@ void EdgeBasedGraphFactory::Run( w != to_node_of_only_restriction ) { //We are at an only_-restriction but not at the right turn. - ++stats.skipped_turns_counter; + ++skipped_turns_counter; continue; } if( is_barrier_node && (u != w) ) { - ++stats.skipped_turns_counter; + ++skipped_turns_counter; continue; } @@ -415,7 +365,7 @@ void EdgeBasedGraphFactory::Run( (to_node_of_only_restriction == UINT_MAX) && (w != to_node_of_only_restriction) ) { - ++stats.skipped_turns_counter; + ++skipped_turns_counter; continue; } @@ -454,7 +404,7 @@ void EdgeBasedGraphFactory::Run( turnInstruction ) ); - ++stats.original_edges_counter; + ++original_edges_counter; if(original_edge_data_vector.size() > 100000) { FlushVectorToStream( @@ -480,20 +430,20 @@ void EdgeBasedGraphFactory::Run( FlushVectorToStream( edge_data_file, original_edge_data_vector ); edge_data_file.seekp( std::ios::beg ); - edge_data_file.write( (char*)&stats.original_edges_counter, sizeof(unsigned) ); + edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); edge_data_file.close(); SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes"; SimpleLogger().Write() << - "Node-based graph contains " << stats.node_based_edge_counter << " edges"; + "Node-based graph contains " << node_based_edge_counter << " edges"; SimpleLogger().Write() << "Edge-expanded graph ..."; SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges"; SimpleLogger().Write() << - " skips " << stats.skipped_turns_counter << " turns, " - "defined by " << stats.turn_restrictions_count << " restrictions"; + " skips " << skipped_turns_counter << " turns, " + "defined by " << m_turn_restrictions_count << " restrictions"; } int EdgeBasedGraphFactory::GetTurnPenalty( diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 97e18f650..053a6bfe9 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -101,20 +101,6 @@ public: unsigned GetNumberOfNodes() const; private: - struct EdgeBasedFactorStatistics { - EdgeBasedFactorStatistics() : - turn_restrictions_count(0), - skipped_turns_counter(0), - node_based_edge_counter(0), - original_edges_counter(0) - { } - - unsigned turn_restrictions_count; - unsigned skipped_turns_counter; - unsigned node_based_edge_counter; - unsigned original_edges_counter; - } stats; - struct NodeBasedEdgeData { int distance; unsigned edgeBasedNodeID; @@ -129,6 +115,8 @@ private: bool contraFlow:1; }; + unsigned m_turn_restrictions_count; + typedef DynamicGraph NodeBasedDynamicGraph; typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge; typedef NodeBasedDynamicGraph::NodeIterator NodeIterator; @@ -149,7 +137,6 @@ private: boost::unordered_set m_traffic_lights; RestrictionMap m_restriction_map; - GeometryCompressor m_geometry_compressor; NodeID CheckForEmanatingIsOnlyTurn( const NodeID u, From a5c406a4dd1013fe71188b1a3564954dd95d9627 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 6 Dec 2013 10:14:42 +0100 Subject: [PATCH 26/29] cache dependencies on travis ci --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 523e79599..e58e7655f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,11 +12,14 @@ before_script: - mkdir build - cd build - cmake .. $CMAKEOPTIONS -script: make +script: make -j3 branches: only: - master - develop +cache: +- bundler +- apt env: - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" From bde3f95ae930e87b6782e5c4da72f75745d67824 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 6 Dec 2013 12:06:51 +0100 Subject: [PATCH 27/29] fixes #808 --- profiles/car.lua | 4 ++-- profiles/foot.lua | 6 +++--- profiles/testbot.lua | 18 +++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/profiles/car.lua b/profiles/car.lua index f0b6713df..9a959cd20 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -34,8 +34,8 @@ speed_profile = { take_minimum_of_speeds = false obey_oneway = true -obey_bollards = true -use_restrictions = true +obey_bollards = true +use_turn_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 2 u_turn_penalty = 20 diff --git a/profiles/foot.lua b/profiles/foot.lua index 724519046..ae0dd6083 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -114,7 +114,7 @@ function way_function (way) then return 0 end - + -- don't route on ways that are still under construction if highway=='construction' then return 0 @@ -125,7 +125,7 @@ function way_function (way) if access_tag_blacklist[access] then return 0 end - + local name = way.tags:Find("name") local ref = way.tags:Find("ref") local junction = way.tags:Find("junction") @@ -179,7 +179,7 @@ function way_function (way) -- unknown way, but valid access tag way.speed = walking_speed end - + -- oneway if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then way.direction = Way.oneway diff --git a/profiles/testbot.lua b/profiles/testbot.lua index f934fead5..028f8c588 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -6,7 +6,7 @@ -- Secondary road: 18km/h = 18000m/3600s = 100m/20s -- Tertiary road: 12km/h = 12000m/3600s = 100m/30s -speed_profile = { +speed_profile = { ["primary"] = 36, ["secondary"] = 18, ["tertiary"] = 12, @@ -17,8 +17,8 @@ speed_profile = { take_minimum_of_speeds = true obey_oneway = true -obey_bollards = true -use_restrictions = true +obey_barriers = true +use_turn_restrictions = true ignore_areas = true -- future feature traffic_signal_penalty = 7 -- seconds u_turn_penalty = 20 @@ -55,7 +55,7 @@ function way_function (way) local maxspeed = tonumber(way.tags:Find ( "maxspeed")) local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) - + way.name = name if route ~= nil and durationIsValid(duration) then @@ -69,7 +69,7 @@ function way_function (way) speed_forw = temp_speed*1.5 speed_back = temp_speed/1.5 end - + if maxspeed_forward ~= nil and maxspeed_forward > 0 then speed_forw = maxspeed_forward else @@ -77,7 +77,7 @@ function way_function (way) speed_forw = maxspeed end end - + if maxspeed_backward ~= nil and maxspeed_backward > 0 then speed_back = maxspeed_backward else @@ -85,13 +85,13 @@ function way_function (way) speed_back = maxspeed end end - + way.speed = speed_forw if speed_back ~= way_forw then way.backward_speed = speed_back end end - + if oneway == "no" or oneway == "0" or oneway == "false" then way.direction = Way.bidirectional elseif oneway == "-1" then @@ -101,7 +101,7 @@ function way_function (way) else way.direction = Way.bidirectional end - + way.type = 1 return 1 end From f55f8a36296e89f3f09c8cdde666707db04737cd Mon Sep 17 00:00:00 2001 From: Rodolphe Quiedeville Date: Wed, 4 Dec 2013 11:08:21 +0100 Subject: [PATCH 28/29] [options] string is more explicit --- extractor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extractor.cpp b/extractor.cpp index df7864a97..35c590cb7 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -90,7 +90,7 @@ int main (int argc, char *argv[]) { boost::program_options::options_description config_file_options; config_file_options.add(config_options).add(hidden_options); - boost::program_options::options_description visible_options(boost::filesystem::basename(argv[0]) + " []"); + boost::program_options::options_description visible_options(boost::filesystem::basename(argv[0]) + " [options]"); visible_options.add(generic_options).add(config_options); // parse command line options From e70485f1fdc619b4c9ee9ab9c64a7453f6fe351b Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Fri, 6 Dec 2013 15:08:36 +0100 Subject: [PATCH 29/29] workaround for #783 --- Tools/io-benchmark.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Tools/io-benchmark.cpp b/Tools/io-benchmark.cpp index a2aa0f8b6..e235c1208 100644 --- a/Tools/io-benchmark.cpp +++ b/Tools/io-benchmark.cpp @@ -79,6 +79,11 @@ int main (int argc, char * argv[]) { "starting up engines, " << g_GIT_DESCRIPTION << ", " << "compiled at " << __DATE__ << ", " __TIME__; +#ifdef __FreeBSD__ + SimpleLogger().Write() << "Not supported on FreeBSD"; + return 0; +#endif + if( 1 == argc ) { SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device"; @@ -222,6 +227,12 @@ int main (int argc, char * argv[]) { int ret1 = fseek(fd, current_offset, SEEK_SET); int ret2 = read(fileno(fd), (char*)&single_block[0], 4096); #endif + +#ifdef __FreeBSD__ + int ret1 = 0; + int ret2 = 0; +#endif + #ifdef __linux__ int ret1 = lseek(f, current_offset, SEEK_SET); int ret2 = read(f, (char*)single_block, 4096); @@ -281,6 +292,12 @@ int main (int argc, char * argv[]) { int ret1 = fseek(fd, current_offset, SEEK_SET); int ret2 = read(fileno(fd), (char*)&single_block, 4096); #endif + + #ifdef __FreeBSD__ + int ret1 = 0; + int ret2 = 0; + #endif + #ifdef __linux__ int ret1 = lseek(f, current_offset, SEEK_SET);