Merge branch 'develop' into dep-liblua

This commit is contained in:
Dirk L 2013-11-08 15:20:56 +01:00
commit 8f5d9c4816
58 changed files with 3844 additions and 1503 deletions

3
.gitignore vendored
View File

@ -72,7 +72,10 @@ stxxl.errlog
/win/bin/
/win/bin-debug/
/osrm-extract
/osrm-io-benchmark
/osrm-components
/osrm-routed
/osrm-datastore
/osrm-prepare
/osrm-cli
/nohup.out

View File

@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 2.6)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(OSRM)
include(FindPackageHandleStandardArgs)
set(HUGO "${CMAKE_CURRENT_SOURCE_DIR}")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription)
@ -34,25 +33,27 @@ set(BOOST_COMPONENTS filesystem program_options regex system thread)
configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp)
file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob} Util/GitDescription.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources} )
file(GLOB PrepareGlob Contractor/*.cpp)
set(PrepareSources createHierarchy.cpp ${PrepareGlob} Util/GitDescription.cpp)
add_executable(osrm-prepare ${PrepareSources} )
file( GLOB PrepareGlob Contractor/*.cpp)
set( PrepareSources prepare.cpp ${PrepareGlob} )
add_executable( osrm-prepare ${PrepareSources} )
add_executable(osrm-routed routed.cpp Util/GitDescription.cpp)
add_executable(osrm-routed routed.cpp)
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
add_executable(osrm-datastore datastore.cpp)
file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB DatastructureGlob DataStructures/*.cpp)
file(GLOB LibOSRMGlob Library/*.cpp)
file(GLOB SearchEngineSource DataStructures/SearchEngine*.cpp)
file(GLOB ServerStructureGlob Server/DataStructures/*.cpp)
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${SearchEngineSource} ${ServerStructureGlob})
add_library(OSRM SHARED ${OSRMSources})
add_library(UUID STATIC Util/UUID.cpp)
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob})
add_library( OSRM SHARED ${OSRMSources} )
add_library( UUID STATIC Util/UUID.cpp )
add_library( GITDESCRIPTION STATIC Util/GitDescription.cpp )
add_dependencies( UUID UUIDConfigure )
add_dependencies( GITDESCRIPTION GIT_DESCRIPTION )
# Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
@ -65,7 +66,14 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
endif(CMAKE_BUILD_TYPE MATCHES Release)
#Configuring compilers
# set compile switches
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# not using Visual Studio C++
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
endif()
# Configuring compilers
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
@ -80,11 +88,23 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
endif()
# Configuring other platform dependencies
if(APPLE)
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
message("Set Architecture to x64 on OS X")
message(STATUS "Set Architecture to x64 on OS X")
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
IF (DARWIN_VERSION GREATER 12)
MESSAGE(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ENDIF (DARWIN_VERSION GREATER 12)
endif()
if(UNIX AND NOT APPLE)
target_link_libraries( osrm-datastore rt )
target_link_libraries( OSRM rt )
endif(UNIX AND NOT APPLE)
#Check Boost
set(BOOST_MIN_VERSION "1.44.0")
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
@ -98,9 +118,10 @@ IF( APPLE )
ELSE( APPLE )
target_link_libraries( OSRM ${Boost_LIBRARIES} )
ENDIF( APPLE )
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID )
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID )
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID )
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION )
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION )
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
target_link_libraries( osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION )
find_package ( BZip2 REQUIRED )
include_directories(${BZIP_INCLUDE_DIRS})
@ -155,17 +176,22 @@ target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
if(WITH_TOOLS)
message("-- Activating OSRM internal tools")
message(STATUS "Activating OSRM internal tools")
find_package( GDAL )
if(GDAL_FOUND)
add_executable(osrm-components Tools/componentAnalysis.cpp)
include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries(
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION
)
endif(GDAL_FOUND)
add_executable ( osrm-cli Tools/simpleclient.cpp Util/GitDescription.cpp)
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID )
add_executable ( osrm-cli Tools/simpleclient.cpp)
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
add_executable ( osrm-io-benchmark Tools/io-benchmark.cpp )
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} )
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
add_executable ( osrm-unlock-all Tools/unlock_all_mutexes.cpp )
target_link_libraries( osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
if(UNIX AND NOT APPLE)
target_link_libraries( osrm-unlock-all rt )
endif(UNIX AND NOT APPLE)
endif(WITH_TOOLS)

View File

@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/EdgeBasedNode.h"
#include "../Extractor/ExtractorStructs.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h"
@ -56,51 +57,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class EdgeBasedGraphFactory : boost::noncopyable {
public:
struct EdgeBasedNode {
EdgeBasedNode() :
id(INT_MAX),
lat1(INT_MAX),
lat2(INT_MAX),
lon1(INT_MAX),
lon2(INT_MAX >> 1),
belongsToTinyComponent(false),
nameID(UINT_MAX),
weight(UINT_MAX >> 1),
ignoreInGrid(false)
{ }
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
return centroid;
}
inline bool isIgnored() const {
return ignoreInGrid;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),

View File

@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/unordered_map.hpp>
#include <cassert>
#include <boost/assert.hpp>
#include <algorithm>
#include <limits>
@ -132,6 +132,10 @@ public:
return static_cast<Key>( heap.size() - 1 );
}
bool Empty() const {
return 0 == Size();
}
void Insert( NodeID node, Weight weight, const Data &data ) {
HeapElement element;
element.index = static_cast<NodeID>(insertedNodes.size());
@ -155,7 +159,7 @@ public:
}
bool WasRemoved( const NodeID node ) {
assert( WasInserted( node ) );
BOOST_ASSERT( WasInserted( node ) );
const Key index = nodeIndex[node];
return insertedNodes[index].key == 0;
}
@ -168,12 +172,12 @@ public:
}
NodeID Min() const {
assert( heap.size() > 1 );
BOOST_ASSERT( heap.size() > 1 );
return insertedNodes[heap[1].index].node;
}
NodeID DeleteMin() {
assert( heap.size() > 1 );
BOOST_ASSERT( heap.size() > 1 );
const Key removedIndex = heap[1].index;
heap[1] = heap[heap.size()-1];
heap.pop_back();
@ -192,10 +196,10 @@ public:
}
void DecreaseKey( NodeID node, Weight weight ) {
assert( UINT_MAX != node );
BOOST_ASSERT( UINT_MAX != node );
const Key & index = nodeIndex[node];
Key & key = insertedNodes[index].key;
assert ( key >= 0 );
BOOST_ASSERT ( key >= 0 );
insertedNodes[index].weight = weight;
heap[key].weight = weight;
@ -253,7 +257,7 @@ private:
const Weight weight = heap[key].weight;
Key nextKey = key >> 1;
while ( heap[nextKey].weight > weight ) {
assert( nextKey != 0 );
BOOST_ASSERT( nextKey != 0 );
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
@ -267,7 +271,7 @@ private:
void CheckHeap() {
#ifndef NDEBUG
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
assert( heap[i].weight >= heap[i >> 1].weight );
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight );
}
#endif
}

View File

@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/MercatorUtil.h"
#include "../Util/StringUtil.h"
#include <cassert>
#include <boost/assert.hpp>
#include <cmath>
#include <climits>
@ -74,10 +74,10 @@ inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate
}
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
assert(lat1 != INT_MIN);
assert(lon1 != INT_MIN);
assert(lat2 != INT_MIN);
assert(lon2 != INT_MIN);
BOOST_ASSERT(lat1 != INT_MIN);
BOOST_ASSERT(lon1 != INT_MIN);
BOOST_ASSERT(lat2 != INT_MIN);
BOOST_ASSERT(lon2 != INT_MIN);
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/COORDINATE_PRECISION;
double ln1 = lon1/COORDINATE_PRECISION;
@ -106,10 +106,10 @@ inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPoi
}
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
assert(c1.lat != INT_MIN);
assert(c1.lon != INT_MIN);
assert(c2.lat != INT_MIN);
assert(c2.lon != INT_MIN);
BOOST_ASSERT(c1.lat != INT_MIN);
BOOST_ASSERT(c1.lon != INT_MIN);
BOOST_ASSERT(c2.lat != INT_MIN);
BOOST_ASSERT(c2.lon != INT_MIN);
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;

View File

@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include <cassert>
#include <boost/assert.hpp>
#include <cstring>
#include <vector>
@ -48,45 +48,32 @@ protected:
//make constructors explicit, so we do not mix random access and deallocation iterators.
DeallocatingVectorIteratorState();
public:
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
setPointerForIndex();
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
}
ElementT * mData;
std::size_t mIndex;
std::vector<ElementT *> & mBucketList;
inline void setPointerForIndex() {
if(bucketSizeC*mBucketList.size() <= mIndex) {
mData = DEALLOCATION_VECTOR_NULL_PTR;
return;
}
std::size_t _bucket = mIndex/bucketSizeC;
std::size_t _index = mIndex%bucketSizeC;
mData = &(mBucketList[_bucket][_index]);
if(DeallocateC) {
//if we hopped over the border of the previous bucket, then delete that bucket.
if(0 == _index && _bucket) {
delete[] mBucketList[_bucket-1];
mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
}
}
}
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
return mIndex != other.mIndex;
}
inline bool operator==(const DeallocatingVectorIteratorState &other) {
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
return mIndex == other.mIndex;
}
inline bool operator<(const DeallocatingVectorIteratorState &other) {
bool operator<(const DeallocatingVectorIteratorState &other) const {
return mIndex < other.mIndex;
}
bool operator>(const DeallocatingVectorIteratorState &other) const {
return mIndex > other.mIndex;
}
bool operator>=(const DeallocatingVectorIteratorState &other) const {
return mIndex >= other.mIndex;
}
//This is a hack to make assignment operator possible with reference member
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
if (this != &a) {
@ -112,66 +99,69 @@ public:
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
//DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
template<typename T2>
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
if(DeallocateC) assert(false);
if(DeallocateC) BOOST_ASSERT(false);
mState = r.mState; return *this;
}
inline DeallocatingVectorIterator& operator++() { //prefix
// if(DeallocateC) assert(false);
++mState.mIndex; mState.setPointerForIndex(); return *this;
++mState.mIndex;
return *this;
}
inline DeallocatingVectorIterator& operator--() { //prefix
if(DeallocateC) assert(false);
--mState.mIndex; mState.setPointerForIndex(); return *this;
if(DeallocateC) BOOST_ASSERT(false);
--mState.mIndex;
return *this;
}
inline DeallocatingVectorIterator operator++(int) { //postfix
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex++; mState.setPointerForIndex();
mState.mIndex++;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator --(int) { //postfix
if(DeallocateC) assert(false);
inline DeallocatingVectorIterator operator--(int) { //postfix
if(DeallocateC) BOOST_ASSERT(false);
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex--; mState.setPointerForIndex();
mState.mIndex--;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex+=n; _myState.setPointerForIndex();
_myState.mIndex+=n;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
mState.mIndex+=n; return *this;
}
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
if(DeallocateC) assert(false);
if(DeallocateC) BOOST_ASSERT(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex-=n; _myState.setPointerForIndex();
_myState.mIndex-=n;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
if(DeallocateC) assert(false);
if(DeallocateC) BOOST_ASSERT(false);
mState.mIndex-=n; return *this;
}
inline reference operator*() const { return *mState.mData; }
inline pointer operator->() const { return mState.mData; }
inline reference operator[](const difference_type &n) const {
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex += n;
_myState.setPointerForIndex;
return _myState.mData;
inline reference operator*() const {
std::size_t _bucket = mState.mIndex/bucketSizeC;
std::size_t _index = mState.mIndex%bucketSizeC;
return (mState.mBucketList[_bucket][_index]);
}
inline pointer operator->() const {
std::size_t _bucket = mState.mIndex/bucketSizeC;
std::size_t _index = mState.mIndex%bucketSizeC;
return &(mState.mBucketList[_bucket][_index]);
}
inline bool operator!=(const DeallocatingVectorIterator & other) {
@ -182,12 +172,20 @@ public:
return mState == other.mState;
}
bool operator<(const DeallocatingVectorIterator & other) {
inline bool operator<(const DeallocatingVectorIterator & other) const {
return mState < other.mState;
}
inline bool operator>(const DeallocatingVectorIterator & other) const {
return mState > other.mState;
}
inline bool operator>=(const DeallocatingVectorIterator & other) const {
return mState >= other.mState;
}
difference_type operator-(const DeallocatingVectorIterator & other) {
if(DeallocateC) assert(false);
if(DeallocateC) BOOST_ASSERT(false);
return mState.mIndex-other.mState.mIndex;
}
};

View File

@ -0,0 +1,51 @@
#ifndef EDGE_BASED_NODE_H
#define EDGE_BASED_NODE_H
#include "Coordinate.h"
struct EdgeBasedNode {
EdgeBasedNode() :
id(INT_MAX),
lat1(INT_MAX),
lat2(INT_MAX),
lon1(INT_MAX),
lon2(INT_MAX >> 1),
belongsToTinyComponent(false),
nameID(UINT_MAX),
weight(UINT_MAX >> 1),
ignoreInGrid(false)
{ }
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
return centroid;
}
inline bool isIgnored() const {
return ignoreInGrid;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
#endif //EDGE_BASED_NODE_H

View File

@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
inline double y2lat(double a) {
return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
return 180./M_PI * (2. * atan(exp(a*M_PI/180.)) - M_PI/2.);
}
inline double lat2y(double a) {
return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
return 180./M_PI * log(tan(M_PI/4.+a*(M_PI/180.)/2.));
}
#endif /* MERCATORUTIL_H_ */

View File

@ -1,218 +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.
*/
#ifndef NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_
#include "QueryNode.h"
#include "PhantomNodes.h"
#include "StaticRTree.h"
#include "../Contractor/EdgeBasedGraphFactory.h"
#include "../Util/OSRMException.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/noncopyable.hpp>
#include <iostream>
#include <string>
#include <vector>
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
class NodeInformationHelpDesk : boost::noncopyable {
public:
NodeInformationHelpDesk(
const std::string & ram_index_filename,
const std::string & mem_index_filename,
const std::string & nodes_filename,
const std::string & edges_filename,
const unsigned m_number_of_nodes,
const unsigned m_check_sum
) :
m_number_of_nodes(m_number_of_nodes),
m_check_sum(m_check_sum)
{
if ( ram_index_filename.empty() ) {
throw OSRMException("no ram index file name in server ini");
}
if ( mem_index_filename.empty() ) {
throw OSRMException("no mem index file name in server ini");
}
if ( nodes_filename.empty() ) {
throw OSRMException("no nodes file name in server ini");
}
if ( edges_filename.empty() ) {
throw OSRMException("no edges file name in server ini");
}
m_ro_rtree_ptr = new StaticRTree<RTreeLeaf>(
ram_index_filename,
mem_index_filename
);
BOOST_ASSERT_MSG(
0 == m_coordinate_list.size(),
"Coordinate vector not empty"
);
LoadNodesAndEdges(nodes_filename, edges_filename);
}
~NodeInformationHelpDesk() {
delete m_ro_rtree_ptr;
}
inline FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const {
const NodeID node = m_via_node_list.at(id);
return m_coordinate_list.at(node);
}
inline unsigned GetNameIndexFromEdgeID(const unsigned id) const {
return m_name_ID_list.at(id);
}
inline TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const {
return m_turn_instruction_list.at(id);
}
inline NodeID GetNumberOfNodes() const {
return m_number_of_nodes;
}
inline bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
bool found_node = m_ro_rtree_ptr->LocateClosestEndPointForCoordinate(
input_coordinate,
result, zoom_level
);
return found_node;
}
inline bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return m_ro_rtree_ptr->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
}
inline unsigned GetCheckSum() const {
return m_check_sum;
}
private:
void LoadNodesAndEdges(
const std::string & nodes_filename,
const std::string & edges_filename
) {
boost::filesystem::path nodes_file(nodes_filename);
if ( !boost::filesystem::exists( nodes_file ) ) {
throw OSRMException("nodes file does not exist");
}
if ( 0 == boost::filesystem::file_size( nodes_file ) ) {
throw OSRMException("nodes file is empty");
}
boost::filesystem::path edges_file(edges_filename);
if ( !boost::filesystem::exists( edges_file ) ) {
throw OSRMException("edges file does not exist");
}
if ( 0 == boost::filesystem::file_size( edges_file ) ) {
throw OSRMException("edges file is empty");
}
boost::filesystem::ifstream nodes_input_stream(
nodes_file,
std::ios::binary
);
boost::filesystem::ifstream edges_input_stream(
edges_file, std::ios::binary
);
SimpleLogger().Write(logDEBUG)
<< "Loading node data";
NodeInfo current_node;
while(!nodes_input_stream.eof()) {
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
m_coordinate_list.push_back(
FixedPointCoordinate(
current_node.lat,
current_node.lon
)
);
}
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
nodes_input_stream.close();
SimpleLogger().Write(logDEBUG)
<< "Loading edge data";
unsigned number_of_edges = 0;
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_edges; ++i) {
edges_input_stream.read(
(char*)&(current_edge_data),
sizeof(OriginalEdgeData)
);
m_via_node_list[i] = current_edge_data.viaNode;
m_name_ID_list[i] = current_edge_data.nameID;
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
}
edges_input_stream.close();
SimpleLogger().Write(logDEBUG)
<< "Loaded " << number_of_edges << " orig edges";
SimpleLogger().Write(logDEBUG)
<< "Opening NN indices";
}
std::vector<FixedPointCoordinate> m_coordinate_list;
std::vector<NodeID> m_via_node_list;
std::vector<unsigned> m_name_ID_list;
std::vector<TurnInstruction> m_turn_instruction_list;
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * m_ro_rtree_ptr;
const unsigned m_number_of_nodes;
const unsigned m_check_sum;
};
#endif /*NODEINFORMATIONHELPDESK_H_*/

View File

@ -1,91 +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 "SearchEngine.h"
SearchEngine::SearchEngine( QueryObjectsStorage * query_objects ) :
_queryData(query_objects),
shortestPath(_queryData),
alternativePaths(_queryData)
{}
SearchEngine::~SearchEngine() {}
void SearchEngine::GetCoordinatesForNodeID(
NodeID id,
FixedPointCoordinate& result
) const {
result = _queryData.nodeHelpDesk->GetCoordinateOfNode(id);
}
void SearchEngine::FindPhantomNodeForCoordinate(
const FixedPointCoordinate & location,
PhantomNode & result,
const unsigned zoomLevel
) const {
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
location,
result, zoomLevel
);
}
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
const NodeID s,
const NodeID t
) const {
if(s == t) {
return 0;
}
EdgeID e = _queryData.graph->FindEdge(s, t);
if(e == UINT_MAX) {
e = _queryData.graph->FindEdge( t, s );
}
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
return ed.id;
}
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
std::string result;
_queryData.query_objects->GetName(nameID, result);
return HTMLEntitize(result);
}
SearchEngineHeapPtr SearchEngineData::forwardHeap;
SearchEngineHeapPtr SearchEngineData::backwardHeap;
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineHeapPtr SearchEngineData::backwardHeap3;

View File

@ -12,6 +12,7 @@ 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.
<<<<<<< HEAD
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
@ -25,48 +26,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SEARCHENGINE_H_
#define SEARCHENGINE_H_
#ifndef SEARCHENGINE_H
#define SEARCHENGINE_H
#include "Coordinate.h"
#include "NodeInformationHelpDesk.h"
#include "SearchEngineData.h"
#include "PhantomNodes.h"
#include "QueryEdge.h"
#include "SearchEngineData.h"
#include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <climits>
#include <string>
#include <vector>
template<class DataFacadeT>
class SearchEngine {
private:
SearchEngineData _queryData;
DataFacadeT * facade;
SearchEngineData engine_working_data;
public:
ShortestPathRouting<SearchEngineData> shortestPath;
AlternativeRouting<SearchEngineData> alternativePaths;
ShortestPathRouting<DataFacadeT> shortest_path;
AlternativeRouting <DataFacadeT> alternative_path;
SearchEngine( QueryObjectsStorage * query_objects );
~SearchEngine();
SearchEngine( DataFacadeT * facade )
:
facade (facade),
shortest_path (facade, engine_working_data),
alternative_path (facade, engine_working_data)
{}
void GetCoordinatesForNodeID(NodeID id, FixedPointCoordinate& result) const;
~SearchEngine() {}
void FindPhantomNodeForCoordinate(
const FixedPointCoordinate & location,
PhantomNode & result,
unsigned zoomLevel
) const;
NodeID GetNameIDForOriginDestinationNodeID(
const NodeID s, const NodeID t) const;
std::string GetEscapedNameForNameID(const unsigned nameID) const;
};
#endif /* SEARCHENGINE_H_ */
#endif // SEARCHENGINE_H

View File

@ -27,40 +27,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SearchEngineData.h"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) {
if(!forwardHeap.get()) {
forwardHeap.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
forwardHeap.reset(new QueryHeap(number_of_nodes));
} else {
forwardHeap->Clear();
}
if(!backwardHeap.get()) {
backwardHeap.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
backwardHeap.reset(new QueryHeap(number_of_nodes));
} else {
backwardHeap->Clear();
}
}
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) {
if(!forwardHeap2.get()) {
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
forwardHeap2.reset(new QueryHeap(number_of_nodes));
} else {
forwardHeap2->Clear();
}
if(!backwardHeap2.get()) {
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
backwardHeap2.reset(new QueryHeap(number_of_nodes));
} else {
backwardHeap2->Clear();
}
}
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) {
if(!forwardHeap3.get()) {
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
forwardHeap3.reset(new QueryHeap(number_of_nodes));
} else {
forwardHeap3->Clear();
}
if(!backwardHeap3.get()) {
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
backwardHeap3.reset(new QueryHeap(number_of_nodes));
} else {
backwardHeap3->Clear();
}

View File

@ -25,10 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SEARCH_ENGINE_DATA_H
#define SEARCH_ENGINE_DATA_H
#include "BinaryHeap.h"
#include "QueryEdge.h"
#include "StaticGraph.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../typedefs.h"
@ -41,23 +43,12 @@ struct _HeapData {
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
struct SearchEngineData {
typedef QueryGraph Graph;
typedef QueryHeapType QueryHeap;
SearchEngineData(QueryObjectsStorage * query_objects)
:
query_objects(query_objects),
graph(query_objects->graph),
nodeHelpDesk(query_objects->nodeHelpDesk)
{}
const QueryObjectsStorage * query_objects;
const QueryGraph * graph;
const NodeInformationHelpDesk * nodeHelpDesk;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
static SearchEngineHeapPtr forwardHeap;
static SearchEngineHeapPtr backwardHeap;
@ -66,9 +57,11 @@ struct SearchEngineData {
static SearchEngineHeapPtr forwardHeap3;
static SearchEngineHeapPtr backwardHeap3;
void InitializeOrClearFirstThreadLocalStorage();
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearSecondThreadLocalStorage();
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
void InitializeOrClearThirdThreadLocalStorage();
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
};
#endif // SEARCH_ENGINE_DATA_H

View File

@ -0,0 +1,233 @@
/*
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.
*/
#ifndef SHARED_MEMORY_FACTORY_H
#define SHARED_MEMORY_FACTORY_H
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include <boost/noncopyable.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/xsi_shared_memory.hpp>
#include <algorithm>
#include <exception>
struct OSRMLockFile {
boost::filesystem::path operator()() {
boost::filesystem::path temp_dir =
boost::filesystem::temp_directory_path();
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
return lock_file;
}
};
class SharedMemory : boost::noncopyable {
//Remove shared memory on destruction
class shm_remove : boost::noncopyable {
private:
int m_shmid;
bool m_initialized;
public:
void SetID(int shmid) {
m_shmid = shmid;
m_initialized = true;
}
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
~shm_remove(){
if(m_initialized) {
SimpleLogger().Write(logDEBUG) <<
"automatic memory deallocation";
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) {
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
}
}
}
};
public:
void * Ptr() const {
return region.get_address();
}
template<typename IdentifierT >
SharedMemory(
const boost::filesystem::path & lock_file,
const IdentifierT id,
const unsigned size = 0,
bool read_write = false,
bool remove_prev = true
) : key(
lock_file.string().c_str(),
id
) {
if( 0 == size ){ //read_only
shm = boost::interprocess::xsi_shared_memory (
boost::interprocess::open_only,
key
);
region = boost::interprocess::mapped_region (
shm,
(
read_write ?
boost::interprocess::read_write :
boost::interprocess::read_only
)
);
} else { //writeable pointer
//remove previously allocated mem
if( remove_prev ) {
Remove(key);
}
shm = boost::interprocess::xsi_shared_memory (
boost::interprocess::open_or_create,
key,
size
);
region = boost::interprocess::mapped_region (
shm,
boost::interprocess::read_write
);
remover.SetID( shm.get_shmid() );
SimpleLogger().Write(logDEBUG) <<
"writeable memory allocated " << size << " bytes";
}
}
template<typename IdentifierT >
static bool RegionExists(
const IdentifierT id
) {
bool result = true;
try {
OSRMLockFile lock_file;
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
result = RegionExists(key);
} catch(...) {
result = false;
}
return result;
}
template<typename IdentifierT >
static bool Remove(
const IdentifierT id
) {
OSRMLockFile lock_file;
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
return Remove(key);
}
private:
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
bool result = true;
try {
boost::interprocess::xsi_shared_memory shm(
boost::interprocess::open_only,
key
);
} catch(...) {
result = false;
}
return result;
}
static bool Remove(
const boost::interprocess::xsi_key &key
) {
bool ret = false;
try{
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
boost::interprocess::xsi_shared_memory xsi(
boost::interprocess::open_only,
key
);
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
} catch(const boost::interprocess::interprocess_exception &e){
if(e.get_error_code() != boost::interprocess::not_found_error) {
throw;
}
}
return ret;
}
boost::interprocess::xsi_key key;
boost::interprocess::xsi_shared_memory shm;
boost::interprocess::mapped_region region;
shm_remove remover;
};
template<class LockFileT = OSRMLockFile>
class SharedMemoryFactory_tmpl : boost::noncopyable {
public:
template<typename IdentifierT >
static SharedMemory * Get(
const IdentifierT & id,
const unsigned size = 0,
bool read_write = false,
bool remove_prev = true
) {
try {
LockFileT lock_file;
if(!boost::filesystem::exists(lock_file()) ) {
if( 0 == size ) {
throw OSRMException("lock file does not exist, exiting");
} else {
boost::filesystem::ofstream ofs(lock_file());
ofs.close();
}
}
return new SharedMemory(
lock_file(),
id,
size,
read_write,
remove_prev
);
} catch(const boost::interprocess::interprocess_exception &e){
SimpleLogger().Write(logWARNING) <<
"caught exception: " << e.what() <<
", code " << e.get_error_code();
throw OSRMException(e.what());
}
}
private:
SharedMemoryFactory_tmpl() {}
};
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */

View File

@ -0,0 +1,139 @@
/*
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.
*/
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
#define SHARED_MEMORY_VECTOR_WRAPPER_H
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/type_traits.hpp>
#include <algorithm>
#include <iterator>
#include <vector>
template<typename DataT>
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
DataT * p;
public:
ShMemIterator(DataT * x) : p(x) {}
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
ShMemIterator& operator++() {
++p;
return *this;
}
ShMemIterator operator++(int) {
ShMemIterator tmp(*this);
operator++();
return tmp;
}
ShMemIterator operator+(std::ptrdiff_t diff) {
ShMemIterator tmp(p+diff);
return tmp;
}
bool operator==(const ShMemIterator& rhs) {
return p==rhs.p;
}
bool operator!=(const ShMemIterator& rhs) {
return p!=rhs.p;
}
DataT& operator*() {
return *p;
}
};
template<typename DataT>
class SharedMemoryWrapper {
private:
DataT * m_ptr;
std::size_t m_size;
public:
SharedMemoryWrapper() :
m_ptr(NULL),
m_size(0)
{ }
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
m_ptr(ptr),
m_size(size)
{ }
void swap( SharedMemoryWrapper<DataT> & other ) {
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
std::swap( m_size, other.m_size);
std::swap( m_ptr , other.m_ptr );
}
// void SetData(const DataT * ptr, const std::size_t size) {
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
// m_ptr.reset(ptr);
// m_size = size;
// }
DataT & at(const std::size_t index) {
return m_ptr[index];
}
const DataT & at(const std::size_t index) const {
return m_ptr[index];
}
ShMemIterator<DataT> begin() const {
return ShMemIterator<DataT>(m_ptr);
}
ShMemIterator<DataT> end() const {
return ShMemIterator<DataT>(m_ptr+m_size);
}
std::size_t size() const { return m_size; }
DataT & operator[](const unsigned index) {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index];
}
const DataT & operator[](const unsigned index) const {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index];
}
};
template<typename DataT, bool UseSharedMemory>
struct ShM {
typedef typename boost::conditional<
UseSharedMemory,
SharedMemoryWrapper<DataT>,
std::vector<DataT>
>::type vector;
};
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H

View File

@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SIMPLESTACK_H_
#define SIMPLESTACK_H_
#include <cassert>
#include <boost/assert.hpp>
#include <vector>
template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
@ -61,7 +61,7 @@ public:
}
inline StackItemT top() {
assert (last >= 0);
BOOST_ASSERT (last >= 0);
return arr[last];
}

View File

@ -29,13 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define STATICGRAPH_H_INCLUDED
#include "../DataStructures/Percent.h"
#include "../DataStructures/SharedMemoryVectorWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <algorithm>
#include <vector>
template< typename EdgeDataT>
template< typename EdgeDataT, bool UseSharedMemory = false>
class StaticGraph {
public:
typedef NodeID NodeIterator;
@ -47,8 +48,9 @@ public:
NodeIterator source;
NodeIterator target;
bool operator<( const InputEdge& right ) const {
if ( source != right.source )
if ( source != right.source ) {
return source < right.source;
}
return target < right.target;
}
};
@ -89,16 +91,16 @@ public:
}
}
StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
_numNodes = nodes.size();
StaticGraph(
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
) {
_numNodes = nodes.size()-1;
_numEdges = edges.size();
_nodes.swap(nodes);
_edges.swap(edges);
//Add dummy node to end of _nodes array;
_nodes.push_back(_nodes.back());
#ifndef NDEBUG
Percent p(GetNumberOfNodes());
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
@ -136,32 +138,32 @@ public:
return _numEdges;
}
unsigned GetOutDegree( const NodeIterator &n ) const {
unsigned GetOutDegree( const NodeIterator n ) const {
return BeginEdges(n)-EndEdges(n) - 1;
}
inline NodeIterator GetTarget( const EdgeIterator &e ) const {
inline NodeIterator GetTarget( const EdgeIterator e ) const {
return NodeIterator( _edges[e].target );
}
inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
return _edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
return _edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator &n ) const {
EdgeIterator BeginEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator &n ) const {
EdgeIterator EndEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes[n+1].firstEdge );
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
EdgeIterator smallestEdge = SPECIAL_EDGEID;
EdgeWeight smallestWeight = UINT_MAX;
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
@ -174,17 +176,18 @@ public:
return smallestEdge;
}
EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
EdgeIterator tmp = FindEdge( from, to );
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
}
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
EdgeIterator tmp = FindEdge( from, to );
if(UINT_MAX == tmp) {
tmp = FindEdge( to, from );
if(UINT_MAX != tmp)
if(UINT_MAX != tmp) {
result = true;
}
}
return tmp;
}
@ -194,8 +197,8 @@ private:
NodeIterator _numNodes;
EdgeIterator _numEdges;
std::vector< _StrNode > _nodes;
std::vector< _StrEdge > _edges;
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
};
#endif // STATICGRAPH_H_INCLUDED

View File

@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STATICKDTREE_H_INCLUDED
#define STATICKDTREE_H_INCLUDED
#include <cassert>
#include <boost/assert.hpp>
#include <vector>
#include <algorithm>
#include <stack>
@ -100,8 +100,8 @@ public:
};
StaticKDTree( std::vector< InputPoint > * points ){
assert( k > 0 );
assert ( points->size() > 0 );
BOOST_ASSERT( k > 0 );
BOOST_ASSERT ( points->size() > 0 );
size = points->size();
kdtree = new InputPoint[size];
for ( Iterator i = 0; i != size; ++i ) {
@ -209,11 +209,11 @@ private:
public:
Less( unsigned d ) {
dimension = d;
assert( dimension < k );
BOOST_ASSERT( dimension < k );
}
bool operator() ( const InputPoint& left, const InputPoint& right ) {
assert( dimension < k );
BOOST_ASSERT( dimension < k );
return left.coordinates[dimension] < right.coordinates[dimension];
}
private:

View File

@ -28,11 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STATICRTREE_H_
#define STATICRTREE_H_
#include "MercatorUtil.h"
#include "Coordinate.h"
#include "PhantomNodes.h"
#include "DeallocatingVector.h"
#include "HilbertValue.h"
#include "MercatorUtil.h"
#include "PhantomNodes.h"
#include "SharedMemoryFactory.h"
#include "SharedMemoryVectorWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
@ -48,6 +51,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <boost/type_traits.hpp>
#include <algorithm>
#include <limits>
@ -63,9 +67,9 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
template<class DataT>
template<class DataT, bool UseSharedMemory = false>
class StaticRTree : boost::noncopyable {
private:
public:
struct RectangleInt2D {
RectangleInt2D() :
min_lon(INT_MAX),
@ -237,6 +241,16 @@ private:
typedef RectangleInt2D RectangleT;
struct TreeNode {
TreeNode() : child_count(0), child_is_on_disk(false) {}
RectangleT minimum_bounding_rectangle;
uint32_t child_count:31;
bool child_is_on_disk:1;
uint32_t children[RTREE_BRANCHING_FACTOR];
};
private:
struct WrappedInputElement {
explicit WrappedInputElement(
const uint32_t _array_index,
@ -259,14 +273,6 @@ private:
DataT objects[RTREE_LEAF_NODE_SIZE];
};
struct TreeNode {
TreeNode() : child_count(0), child_is_on_disk(false) {}
RectangleT minimum_bounding_rectangle;
uint32_t child_count:31;
bool child_is_on_disk:1;
uint32_t children[RTREE_BRANCHING_FACTOR];
};
struct QueryCandidate {
explicit QueryCandidate(
const uint32_t n_id,
@ -280,7 +286,7 @@ private:
}
};
std::vector<TreeNode> m_search_tree;
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
uint64_t m_element_count;
const std::string m_leaf_node_filename;
@ -414,11 +420,10 @@ public:
//Read-only operation for queries
explicit StaticRTree(
const std::string & node_filename,
const std::string & leaf_filename
) : m_leaf_node_filename(leaf_filename) {
const boost::filesystem::path & node_file,
const boost::filesystem::path & leaf_file
) : m_leaf_node_filename(leaf_file.string()) {
//open tree node file and load into RAM.
boost::filesystem::path node_file(node_filename);
if ( !boost::filesystem::exists( node_file ) ) {
throw OSRMException("ram index file does not exist");
@ -434,9 +439,7 @@ public:
m_search_tree.resize(tree_size);
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
tree_node_file.close();
//open leaf node file and store thread specific pointer
boost::filesystem::path leaf_file(leaf_filename);
if ( !boost::filesystem::exists( leaf_file ) ) {
throw OSRMException("mem index file does not exist");
}
@ -451,6 +454,34 @@ public:
//SimpleLogger().Write() << tree_size << " nodes in search tree";
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
explicit StaticRTree(
TreeNode * tree_node_ptr,
const uint32_t number_of_nodes,
const boost::filesystem::path & leaf_file
) : m_search_tree(tree_node_ptr, number_of_nodes),
m_leaf_node_filename(leaf_file.string())
{
//open leaf node file and store thread specific pointer
if ( !boost::filesystem::exists( leaf_file ) ) {
throw OSRMException("mem index file does not exist");
}
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
throw OSRMException("mem index file is empty");
}
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
leaf_node_file.close();
if( thread_local_rtree_stream.get() ) {
thread_local_rtree_stream->close();
}
//SimpleLogger().Write() << tree_size << " nodes in search tree";
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
//Read-only operation for queries
/*
inline void FindKNearestPhantomNodesForCoordinate(
const FixedPointCoordinate & location,

View File

@ -31,33 +31,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/HashTable.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngine.h"
#include "../Server/BasicDatastructures.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <cassert>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
struct _DescriptorConfig {
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
struct DescriptorConfig {
DescriptorConfig() :
instructions(true),
geometry(true),
encode_geometry(true),
zoom_level(18)
{ }
bool instructions;
bool geometry;
bool encodeGeometry;
unsigned short z;
bool encode_geometry;
unsigned short zoom_level;
};
template<class DataFacadeT>
class BaseDescriptor {
public:
BaseDescriptor() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { }
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
virtual void Run(
http::Reply & reply,
const RawRouteData &rawRoute,
PhantomNodes &phantomNodes,
const DataFacadeT * facade
) = 0;
virtual void SetConfig(const DescriptorConfig & config) = 0;
};
#endif /* BASE_DESCRIPTOR_H_ */

View File

@ -92,126 +92,126 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
// void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
if(0 == pathDescription.size())
return;
// if(0 == pathDescription.size())
// return;
// unsigned entireLength = 0;
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
}
// // unsigned entireLength = 0;
// /** starts at index 1 */
// pathDescription[0].length = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
// pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
// }
double lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
// double lengthOfSegment = 0;
// unsigned durationOfSegment = 0;
// unsigned indexOfSegmentBegin = 0;
std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
std::string string1;
// std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
// std::string string1;
/*Simplify turn instructions
Input :
10. Turn left on B 36 for 20 km
11. Continue on B 35; B 36 for 2 km
12. Continue on B 36 for 13 km
// /*Simplify turn instructions
// Input :
// 10. Turn left on B 36 for 20 km
// 11. Continue on B 35; B 36 for 2 km
// 12. Continue on B 36 for 13 km
becomes:
10. Turn left on B 36 for 35 km
*/
//TODO: rework to check only end and start of string.
// stl string is way to expensive
// becomes:
// 10. Turn left on B 36 for 35 km
// */
// //TODO: rework to check only end and start of string.
// // stl string is way to expensive
// unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
// if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1)
// ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// } else if(std::string::npos != string1.find(string0+";")
// || std::string::npos != string1.find(";"+string0)
// || std::string::npos != string1.find(string0+" ;")
// || std::string::npos != string1.find("; "+string0)
// ){
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// pathDescription[i].nameID = pathDescription[i-1].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// }
// }
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
// lastTurn = i;
// }
// string0 = string1;
// }
// // unsigned lastTurn = 0;
// // for(unsigned i = 1; i < pathDescription.size(); ++i) {
// // string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
// // if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
// // if(std::string::npos != string0.find(string1+";")
// // || std::string::npos != string0.find(";"+string1)
// // || std::string::npos != string0.find(string1+" ;")
// // || std::string::npos != string0.find("; "+string1)
// // ){
// // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// // for(; lastTurn != i; ++lastTurn)
// // pathDescription[lastTurn].nameID = pathDescription[i].nameID;
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// // } else if(std::string::npos != string1.find(string0+";")
// // || std::string::npos != string1.find(";"+string0)
// // || std::string::npos != string1.find(string0+" ;")
// // || std::string::npos != string1.find("; "+string0)
// // ){
// // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// // pathDescription[i].nameID = pathDescription[i-1].nameID;
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// // }
// // }
// // if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
// // lastTurn = i;
// // }
// // string0 = string1;
// // }
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
lengthOfSegment += pathDescription[i].length;
durationOfSegment += pathDescription[i].duration;
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
// entireLength += pathDescription[i].length;
// lengthOfSegment += pathDescription[i].length;
// durationOfSegment += pathDescription[i].duration;
// pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
// pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
}
}
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
// if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
// //SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
// assert(pathDescription[i].necessary);
// lengthOfSegment = 0;
// durationOfSegment = 0;
// indexOfSegmentBegin = i;
// }
// }
// // SimpleLogger().Write() << "#segs: " << pathDescription.size();
//Post-processing to remove empty or nearly empty path segments
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
// SimpleLogger().Write() << "Deleting last turn instruction";
}
} else {
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
}
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
//TODO: this is never called actually?
if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin());
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
pathDescription[0].necessary = true;
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
}
} else {
pathDescription[0].duration *= startPhantom.ratio;
}
// //Post-processing to remove empty or nearly empty path segments
// if(FLT_EPSILON > pathDescription.back().length) {
// // SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
// if(pathDescription.size() > 2){
// pathDescription.pop_back();
// pathDescription.back().necessary = true;
// pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
// targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
// // SimpleLogger().Write() << "Deleting last turn instruction";
// }
// } else {
// pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
// }
// if(FLT_EPSILON > pathDescription[0].length) {
// //TODO: this is never called actually?
// if(pathDescription.size() > 2) {
// pathDescription.erase(pathDescription.begin());
// pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
// pathDescription[0].necessary = true;
// startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
// // SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
// }
// } else {
// pathDescription[0].duration *= startPhantom.ratio;
// }
//Generalize poly line
dp.Run(pathDescription, zoomLevel);
// //Generalize poly line
// dp.Run(pathDescription, zoomLevel);
//fix what needs to be fixed else
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
if(pathDescription[i].necessary) {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
pathDescription[i].bearing = angle;
}
}
// //fix what needs to be fixed else
// for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
// if(pathDescription[i].necessary) {
// double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
// pathDescription[i].bearing = angle;
// }
// }
// BuildRouteSummary(entireLength, duration);
return;
}
// // BuildRouteSummary(entireLength, duration);
// return;
// }
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
summary.startName = startPhantom.nodeBasedEdgeNameID;

View File

@ -31,7 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/SearchEngine.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
@ -51,12 +52,18 @@ class DescriptionFactory {
double DegreeToRadian(const double degree) const;
double RadianToDegree(const double degree) const;
public:
struct _RouteSummary {
struct RouteSummary {
std::string lengthString;
std::string durationString;
unsigned startName;
unsigned destName;
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
RouteSummary() :
lengthString("0"),
durationString("0"),
startName(0),
destName(0)
{}
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
//compute distance/duration for route summary
intToString(round(distance), lengthString);
@ -79,7 +86,129 @@ public:
void SetStartSegment(const PhantomNode & startPhantom);
void SetEndSegment(const PhantomNode & startPhantom);
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
template<class DataFacadeT>
void Run(const DataFacadeT * facade, const unsigned zoomLevel) {
if( pathDescription.empty() ) {
return;
}
// unsigned entireLength = 0;
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
}
double lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].nameID);
// std::string string1;
/*Simplify turn instructions
Input :
10. Turn left on B 36 for 20 km
11. Continue on B 35; B 36 for 2 km
12. Continue on B 36 for 13 km
becomes:
10. Turn left on B 36 for 35 km
*/
//TODO: rework to check only end and start of string.
// stl string is way to expensive
// unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
// if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1)
// ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// } else if(std::string::npos != string1.find(string0+";")
// || std::string::npos != string1.find(";"+string0)
// || std::string::npos != string1.find(string0+" ;")
// || std::string::npos != string1.find("; "+string0)
// ){
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// pathDescription[i].nameID = pathDescription[i-1].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// }
// }
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
// lastTurn = i;
// }
// string0 = string1;
// }
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
lengthOfSegment += pathDescription[i].length;
durationOfSegment += pathDescription[i].duration;
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << pathDescription[i].nameID;
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
}
}
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
//Post-processing to remove empty or nearly empty path segments
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
// SimpleLogger().Write() << "Deleting last turn instruction";
}
} else {
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
}
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
//TODO: this is never called actually?
if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin());
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
pathDescription[0].necessary = true;
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
}
} else {
pathDescription[0].duration *= startPhantom.ratio;
}
//Generalize poly line
dp.Run(pathDescription, zoomLevel);
//fix what needs to be fixed else
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
if(pathDescription[i].necessary) {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
pathDescription[i].bearing = angle;
}
}
// BuildRouteSummary(entireLength, duration);
return;
}
};
#endif /* DESCRIPTIONFACTORY_H_ */

View File

@ -32,42 +32,72 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/foreach.hpp>
class GPXDescriptor : public BaseDescriptor{
template<class DataFacadeT>
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
private:
_DescriptorConfig config;
DescriptorConfig config;
FixedPointCoordinate current;
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
void SetConfig(const DescriptorConfig & c) { config = c; }
//TODO: reorder parameters
void Run(
http::Reply & reply,
const RawRouteData &rawRoute,
PhantomNodes &phantomNodes,
const DataFacadeT * facade
) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
reply.content +=
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
"\">";
reply.content += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
reply.content +=
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>";
reply.content += "<rte>";
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) &&
(rawRoute.computedShortestPath.size() );
if( found_route ) {
convertInternalLatLonToString(
phantomNodes.startPhantom.location.lat,
tmp
);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
convertInternalLatLonToString(
phantomNodes.startPhantom.location.lon,
tmp
);
reply.content += "lon=\"" + tmp + "\"></rtept>";
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
BOOST_FOREACH(
const _PathData & pathData,
rawRoute.computedShortestPath
) {
current = facade->GetCoordinateOfNode(pathData.node);
convertInternalLatLonToString(current.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(current.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
convertInternalLatLonToString(
phantomNodes.targetPhantom.location.lat,
tmp
);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
convertInternalLatLonToString(
phantomNodes.targetPhantom.location.lon,
tmp
);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
reply.content += "</rte></gpx>";
}
};
#endif /* GPX_DESCRIPTOR_H_ */
#endif // GPX_DESCRIPTOR_H_

View File

@ -41,32 +41,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
class JSONDescriptor : public BaseDescriptor{
template<class DataFacadeT>
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
private:
_DescriptorConfig config;
DescriptionFactory descriptionFactory;
DescriptorConfig config;
DescriptionFactory description_factory;
DescriptionFactory alternateDescriptionFactory;
FixedPointCoordinate current;
unsigned numberOfEnteredRestrictedAreas;
unsigned entered_restricted_area_count;
struct RoundAbout{
RoundAbout() :
startIndex(INT_MAX),
nameID(INT_MAX),
leaveAtExit(INT_MAX)
start_index(INT_MAX),
name_id(INT_MAX),
leave_at_exit(INT_MAX)
{}
int startIndex;
int nameID;
int leaveAtExit;
int start_index;
int name_id;
int leave_at_exit;
} roundAbout;
struct Segment {
Segment() : nameID(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
int nameID;
Segment() : name_id(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
int name_id;
int length;
int position;
};
std::vector<Segment> shortestSegments, alternativeSegments;
std::vector<Segment> shortest_path_segments, alternative_path_segments;
struct RouteNames {
std::string shortestPathName1;
@ -76,109 +77,143 @@ private:
};
public:
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
JSONDescriptor() : entered_restricted_area_count(0) {}
void SetConfig(const DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
//TODO: reorder parameters
void Run(
http::Reply & reply,
const RawRouteData & raw_route_information,
PhantomNodes & phantom_nodes,
const DataFacadeT * facade
) {
WriteHeaderToOutput(reply.content);
if(rawRoute.lengthOfShortestPath != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
if(raw_route_information.lengthOfShortestPath != INT_MAX) {
description_factory.SetStartSegment(phantom_nodes.startPhantom);
reply.content += "0,"
"\"status_message\": \"Found route between points\",";
//Get all the coordinates for the computed route
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData );
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedShortestPath) {
current = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current, path_data );
}
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
} else {
//We do not need to do much, if there is no route ;-)
reply.content += "207,"
"\"status_message\": \"Cannot find route between points\",";
}
descriptionFactory.Run(sEngine, config.z);
description_factory.Run(facade, config.zoom_level);
reply.content += "\"route_geometry\": ";
if(config.geometry) {
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
description_factory.AppendEncodedPolylineString(
reply.content,
config.encode_geometry
);
} else {
reply.content += "[]";
}
reply.content += ","
"\"route_instructions\": [";
numberOfEnteredRestrictedAreas = 0;
entered_restricted_area_count = 0;
if(config.instructions) {
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
BuildTextualDescription(
description_factory,
reply,
raw_route_information.lengthOfShortestPath,
facade,
shortest_path_segments
);
} else {
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
BOOST_FOREACH(
const SegmentInformation & segment,
description_factory.pathDescription
) {
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
}
}
reply.content += "],";
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
description_factory.BuildRouteSummary(
description_factory.entireLength,
raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty)
);
reply.content += "\"route_summary\":";
reply.content += "{";
reply.content += "\"total_distance\":";
reply.content += descriptionFactory.summary.lengthString;
reply.content += description_factory.summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += descriptionFactory.summary.durationString;
reply.content += description_factory.summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += facade->GetEscapedNameForNameID(
description_factory.summary.startName
);
reply.content += "\","
"\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += facade->GetEscapedNameForNameID(
description_factory.summary.destName
);
reply.content += "\"";
reply.content += "}";
reply.content +=",";
//only one alternative route is computed at this time, so this is hardcoded
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
if(raw_route_information.lengthOfAlternativePath != INT_MAX) {
alternateDescriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
//Get all the coordinates for the computed route
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
alternateDescriptionFactory.AppendSegment(current, pathData );
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedAlternativePath) {
current = facade->GetCoordinateOfNode(path_data.node);
alternateDescriptionFactory.AppendSegment(current, path_data );
}
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
alternateDescriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
}
alternateDescriptionFactory.Run(sEngine, config.z);
alternateDescriptionFactory.Run(facade, config.zoom_level);
//give an array of alternative routes
reply.content += "\"alternative_geometries\": [";
if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
if(config.geometry && INT_MAX != raw_route_information.lengthOfAlternativePath) {
//Generate the linestrings for each alternative
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
alternateDescriptionFactory.AppendEncodedPolylineString(
reply.content,
config.encode_geometry
);
}
reply.content += "],";
reply.content += "\"alternative_instructions\":[";
numberOfEnteredRestrictedAreas = 0;
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
entered_restricted_area_count = 0;
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
reply.content += "[";
//Generate instructions for each alternative
if(config.instructions) {
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
BuildTextualDescription(
alternateDescriptionFactory,
reply,
raw_route_information.lengthOfAlternativePath,
facade,
alternative_path_segments
);
} else {
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
}
}
reply.content += "]";
}
reply.content += "],";
reply.content += "\"alternative_summaries\":[";
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
//Generate route summary (length, duration) for each alternative
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, raw_route_information.lengthOfAlternativePath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty));
reply.content += "{";
reply.content += "\"total_distance\":";
reply.content += alternateDescriptionFactory.summary.lengthString;
@ -187,10 +222,10 @@ public:
reply.content += alternateDescriptionFactory.summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += facade->GetEscapedNameForNameID(description_factory.summary.startName);
reply.content += "\","
"\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += facade->GetEscapedNameForNameID(description_factory.summary.destName);
reply.content += "\"";
reply.content += "}";
}
@ -198,7 +233,7 @@ public:
//Get Names for both routes
RouteNames routeNames;
GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
reply.content += "\"route_name\":[\"";
reply.content += routeNames.shortestPathName1;
@ -215,40 +250,40 @@ public:
//list all viapoints so that the client may display it
reply.content += "\"via_points\":[";
std::string tmp;
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
if(config.geometry && INT_MAX != raw_route_information.lengthOfShortestPath) {
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
reply.content += "[";
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
if(raw_route_information.segmentEndCoordinates[i].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates[i].startPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates[i], tmp);
reply.content += tmp;
reply.content += "],";
}
reply.content += "[";
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet())
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp);
reply.content += tmp;
reply.content += "]";
}
reply.content += "],";
reply.content += "\"hint_data\": {";
reply.content += "\"checksum\":";
intToString(rawRoute.checkSum, tmp);
intToString(raw_route_information.checkSum, tmp);
reply.content += tmp;
reply.content += ", \"locations\": [";
std::string hint;
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
reply.content += "\"";
EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates[i].startPhantom, hint);
reply.content += hint;
reply.content += "\", ";
}
EncodeObjectToBase64(rawRoute.segmentEndCoordinates.back().targetPhantom, hint);
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates.back().targetPhantom, hint);
reply.content += "\"";
reply.content += hint;
reply.content += "\"]";
@ -257,26 +292,31 @@ public:
reply.content += "}";
}
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
/*** extract names for both alternatives ***/
// construct routes names
void GetRouteNames(
std::vector<Segment> & shortest_path_segments,
std::vector<Segment> & alternative_path_segments,
const DataFacadeT * facade,
RouteNames & routeNames
) {
Segment shortestSegment1, shortestSegment2;
Segment alternativeSegment1, alternativeSegment2;
if(0 < shortestSegments.size()) {
sort(shortestSegments.begin(), shortestSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
shortestSegment1 = shortestSegments[0];
if(0 < alternativeSegments.size()) {
sort(alternativeSegments.begin(), alternativeSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
alternativeSegment1 = alternativeSegments[0];
if(0 < shortest_path_segments.size()) {
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
shortestSegment1 = shortest_path_segments[0];
if(0 < alternative_path_segments.size()) {
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
alternativeSegment1 = alternative_path_segments[0];
}
std::vector<Segment> shortestDifference(shortestSegments.size());
std::vector<Segment> alternativeDifference(alternativeSegments.size());
std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
std::vector<Segment> shortestDifference(shortest_path_segments.size());
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), alternative_path_segments.begin(), alternative_path_segments.end(), shortestDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
int size_of_difference = shortestDifference.size();
if(0 < size_of_difference ) {
int i = 0;
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) {
++i;
}
if(i < size_of_difference ) {
@ -284,11 +324,11 @@ public:
}
}
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
size_of_difference = alternativeDifference.size();
if(0 < size_of_difference ) {
int i = 0;
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) {
++i;
}
if(i < size_of_difference ) {
@ -301,11 +341,19 @@ public:
if(alternativeSegment1.position > alternativeSegment2.position)
std::swap(alternativeSegment1, alternativeSegment2);
routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
shortestSegment1.name_id
);
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
shortestSegment2.name_id
);
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
alternativeSegment1.name_id
);
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
alternativeSegment2.name_id
);
}
}
@ -315,43 +363,49 @@ public:
"\"status\":";
}
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
//TODO: reorder parameters
inline void BuildTextualDescription(
DescriptionFactory & description_factory,
http::Reply & reply,
const int route_length,
const DataFacadeT * facade,
std::vector<Segment> & route_segments_list
) {
//Segment information has following format:
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0;
roundAbout.leave_at_exit = 0;
roundAbout.name_id = 0;
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
if(TurnInstructions.EnterRoundAbout == current_instruction) {
roundAbout.name_id = segment.nameID;
roundAbout.start_index = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments){
reply.content += ",";
}
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
reply.content += tmpInstruction;
reply.content += "-";
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
reply.content += tmpInstruction;
roundAbout.leaveAtExit = 0;
roundAbout.leave_at_exit = 0;
} else {
intToString(currentInstruction, tmpInstruction);
intToString(current_instruction, tmpInstruction);
reply.content += tmpInstruction;
}
reply.content += "\",\"";
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
reply.content += facade->GetEscapedNameForNameID(segment.nameID);
reply.content += "\",";
intToString(segment.length, tmpDist);
reply.content += tmpDist;
@ -371,15 +425,21 @@ public:
reply.content += tmpBearing;
reply.content += "]";
segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() ));
route_segments_list.push_back(
Segment(
segment.nameID,
segment.length,
route_segments_list.size()
)
);
}
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
++roundAbout.leaveAtExit;
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
++roundAbout.leave_at_exit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
}
if(INT_MAX != lengthOfRoute) {
if(INT_MAX != route_length) {
reply.content += ",[\"";
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
reply.content += tmpInstruction;

View File

@ -297,8 +297,21 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
std::ios::binary
);
const unsigned number_of_ways = name_list.size()+1;
name_file_stream.write((char *)&(number_of_ways), sizeof(unsigned));
//write number of names
const unsigned number_of_names = name_list.size()+1;
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
//compute total number of chars
unsigned total_number_of_chars = 0;
BOOST_FOREACH(const std::string & str, name_list) {
total_number_of_chars += strlen(str.c_str());
}
//write total number of chars
name_file_stream.write(
(char *)&(total_number_of_chars),
sizeof(unsigned)
);
//write prefixe sums
unsigned name_lengths_prefix_sum = 0;
BOOST_FOREACH(const std::string & str, name_list) {
name_file_stream.write(
@ -307,12 +320,13 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
);
name_lengths_prefix_sum += strlen(str.c_str());
}
//duplicate on purpose!
name_file_stream.write(
(char *)&(name_lengths_prefix_sum),
sizeof(unsigned)
);
//duplicate on purpose!
name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
//write all chars consecutively
BOOST_FOREACH(const std::string & str, name_list) {
const unsigned lengthOfRawString = strlen(str.c_str());
name_file_stream.write(str.c_str(), lengthOfRawString);

View File

@ -66,7 +66,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readwrite("id", &ImportNode::id)
.def_readonly("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)
@ -75,6 +75,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
luabind::module(myLuaState) [
luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
@ -94,9 +95,11 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
]
];
// fails on c++11/OS X 10.9
luabind::module(myLuaState) [
luabind::class_<std::vector<std::string> >("vector")
.def("Add", &std::vector<std::string>::push_back)
luabind::class_<std::vector<std::string> >("vector")
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back)
)
];
if(0 != luaL_dofile(myLuaState, fileName) ) {

View File

@ -26,38 +26,105 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "OSRM.h"
#include <boost/foreach.hpp>
OSRM::OSRM( const ServerPaths & server_paths, const bool use_shared_memory )
:
use_shared_memory(use_shared_memory)
{
if( !use_shared_memory ) {
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
server_paths
);
} else {
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
}
OSRM::OSRM(boost::unordered_map<const std::string,boost::filesystem::path>& paths) {
objects = new QueryObjectsStorage( paths );
RegisterPlugin(new HelloWorldPlugin());
RegisterPlugin(new LocatePlugin(objects));
RegisterPlugin(new NearestPlugin(objects));
RegisterPlugin(new TimestampPlugin(objects));
RegisterPlugin(new ViaRoutePlugin(objects));
//The following plugins handle all requests.
RegisterPlugin(
new HelloWorldPlugin()
);
RegisterPlugin(
new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
RegisterPlugin(
new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
RegisterPlugin(
new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
RegisterPlugin(
new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
}
OSRM::~OSRM() {
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, pluginMap) {
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
delete plugin_pointer.second;
}
delete objects;
}
void OSRM::RegisterPlugin(BasePlugin * plugin) {
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if( pluginMap.find(plugin->GetDescriptor()) != pluginMap.end() ) {
delete pluginMap.find(plugin->GetDescriptor())->second;
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
delete plugin_map.find(plugin->GetDescriptor())->second;
}
pluginMap.emplace(plugin->GetDescriptor(), plugin);
plugin_map.emplace(plugin->GetDescriptor(), plugin);
}
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
const PluginMap::const_iterator & iter = pluginMap.find(route_parameters.service);
if(pluginMap.end() != iter) {
const PluginMap::const_iterator & iter = plugin_map.find(
route_parameters.service
);
if(plugin_map.end() != iter) {
reply.status = http::Reply::ok;
if( use_shared_memory ) {
// lock update pending
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> pending_lock(barrier.pending_update_mutex);
// lock query
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> query_lock(barrier.query_mutex);
// unlock update pending
pending_lock.unlock();
// increment query count
++(barrier.number_of_queries);
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
}
iter->second->HandleRequest(route_parameters, reply );
if( use_shared_memory ) {
// lock query
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> query_lock(barrier.query_mutex);
// decrement query count
--(barrier.number_of_queries);
BOOST_ASSERT_MSG(
0 <= barrier.number_of_queries,
"invalid number of queries"
);
// notify all processes that were waiting for this condition
if (0 == barrier.number_of_queries) {
barrier.no_running_queries_condition.notify_all();
}
}
} else {
reply = http::Reply::stockReply(http::Reply::badRequest);
}

View File

@ -36,6 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h"
#include "../Server/DataStructures/BaseDataFacade.h"
#include "../Server/DataStructures/InternalDataFacade.h"
#include "../Server/DataStructures/SharedBarriers.h"
#include "../Server/DataStructures/SharedDataFacade.h"
#include "../Server/DataStructures/RouteParameters.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
@ -45,21 +49,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <vector>
class OSRM : boost::noncopyable {
private:
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
QueryObjectsStorage * objects;
public:
OSRM(boost::unordered_map<const std::string,boost::filesystem::path>& paths);
OSRM(
const ServerPaths & paths,
const bool use_shared_memory = false
);
~OSRM();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
private:
void RegisterPlugin(BasePlugin * plugin);
PluginMap pluginMap;
PluginMap plugin_map;
bool use_shared_memory;
SharedBarriers barrier;
//base class pointer to the objects
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
};
#endif //OSRM_H

View File

@ -29,20 +29,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define LOCATEPLUGIN_H_
#include "BasePlugin.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/StringUtil.h"
/*
* This Plugin locates the nearest node in the road network for a given coordinate.
*/
//locates the nearest node in the road network for a given coordinate.
template<class DataFacadeT>
class LocatePlugin : public BasePlugin {
public:
LocatePlugin(QueryObjectsStorage * objects) : descriptor_string("locate") {
nodeHelpDesk = objects->nodeHelpDesk;
}
LocatePlugin(DataFacadeT * facade)
:
descriptor_string("locate"),
facade(facade)
{ }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply& reply
) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
reply = http::Reply::stockReply(http::Reply::badRequest);
@ -58,15 +62,19 @@ public:
std::string tmp;
//json
// JSONParameter = routeParameters.options.Find("jsonp");
if("" != routeParameters.jsonpParameter) {
if(!routeParameters.jsonpParameter.empty()) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
if(!nodeHelpDesk->LocateClosestEndPointForCoordinate(routeParameters.coordinates[0], result)) {
if(
!facade->LocateClosestEndPointForCoordinate(
routeParameters.coordinates[0],
result
)
) {
reply.content += ("\"status\":207,");
reply.content += ("\"mapped_coordinate\":[]");
} else {
@ -85,7 +93,7 @@ public:
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
if(!routeParameters.jsonpParameter.empty()) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
@ -104,8 +112,8 @@ public:
}
private:
NodeInformationHelpDesk * nodeHelpDesk;
std::string descriptor_string;
DataFacadeT * facade;
};
#endif /* LOCATEPLUGIN_H_ */

View File

@ -29,19 +29,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define NearestPlugin_H_
#include "BasePlugin.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../DataStructures/PhantomNodes.h"
#include "../Util/StringUtil.h"
/*
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/
template<class DataFacadeT>
class NearestPlugin : public BasePlugin {
public:
NearestPlugin(QueryObjectsStorage * objects )
NearestPlugin(DataFacadeT * facade )
:
m_query_objects(objects),
facade(facade),
descriptor_string("nearest")
{
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
@ -54,14 +54,13 @@ public:
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
if(false == checkCoord(routeParameters.coordinates[0])) {
if( !checkCoord(routeParameters.coordinates[0]) ) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
NodeInformationHelpDesk * nodeHelpDesk = m_query_objects->nodeHelpDesk;
//query to helpdesk
PhantomNode result;
nodeHelpDesk->FindPhantomNodeForCoordinate(
facade->FindPhantomNodeForCoordinate(
routeParameters.coordinates[0],
result,
routeParameters.zoomLevel
@ -96,14 +95,14 @@ public:
reply.content += "],";
reply.content += "\"name\":\"";
if(UINT_MAX != result.edgeBasedNode) {
m_query_objects->GetName(result.nodeBasedEdgeNameID, temp_string);
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
reply.content += temp_string;
}
reply.content += "\"";
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
if( !routeParameters.jsonpParameter.empty() ) {
reply.content += ")";
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
@ -121,7 +120,7 @@ public:
}
private:
QueryObjectsStorage * m_query_objects;
DataFacadeT * facade;
HashTable<std::string, unsigned> descriptorTable;
std::string descriptor_string;
};

View File

@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BasePlugin.h"
template<class DataFacadeT>
class TimestampPlugin : public BasePlugin {
public:
TimestampPlugin(QueryObjectsStorage * o)
: objects(o), descriptor_string("timestamp")
TimestampPlugin(const DataFacadeT * facade)
: facade(facade), descriptor_string("timestamp")
{ }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
@ -51,7 +52,7 @@ public:
reply.content += ("\"status\":");
reply.content += "0,";
reply.content += ("\"timestamp\":\"");
reply.content += objects->timestamp;
reply.content += facade->GetTimestamp();
reply.content += "\"";
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
reply.content += ("}");
@ -73,7 +74,7 @@ public:
reply.headers[0].value = tmp;
}
private:
QueryObjectsStorage * objects;
const DataFacadeT * facade;
std::string descriptor_string;
};

View File

@ -32,12 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/StaticGraph.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
@ -48,36 +46,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>
template<class DataFacadeT>
class ViaRoutePlugin : public BasePlugin {
private:
NodeInformationHelpDesk * nodeHelpDesk;
StaticGraph<QueryEdge::EdgeData> * graph;
HashTable<std::string, unsigned> descriptorTable;
SearchEngine * searchEnginePtr;
boost::unordered_map<std::string, unsigned> descriptorTable;
SearchEngine<DataFacadeT> * search_engine_ptr;
public:
ViaRoutePlugin(QueryObjectsStorage * objects)
ViaRoutePlugin(DataFacadeT * facade)
:
// objects(objects),
descriptor_string("viaroute")
descriptor_string("viaroute"),
facade(facade)
{
nodeHelpDesk = objects->nodeHelpDesk;
graph = objects->graph;
//TODO: set up an engine for each thread!!
search_engine_ptr = new SearchEngine<DataFacadeT>(facade);
searchEnginePtr = new SearchEngine(objects);
// descriptorTable.emplace("" , 0);
descriptorTable.emplace("json", 0);
descriptorTable.emplace("gpx" , 1);
}
virtual ~ViaRoutePlugin() {
delete searchEnginePtr;
delete search_engine_ptr;
}
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply& reply
) {
//check number of parameters
if( 2 > routeParameters.coordinates.size() ) {
reply = http::Reply::stockReply(http::Reply::badRequest);
@ -85,11 +82,11 @@ public:
}
RawRouteData rawRoute;
rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
rawRoute.checkSum = facade->GetCheckSum();
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
std::vector<std::string> textCoord;
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
if(false == checkCoord(routeParameters.coordinates[i])) {
if( !checkCoord(routeParameters.coordinates[i]) ) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
@ -100,13 +97,17 @@ public:
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
if(phantomNodeVector[i].isValid(nodeHelpDesk->GetNumberOfNodes())) {
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
continue;
}
}
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
facade->FindPhantomNodeForCoordinate(
rawRoute.rawViaNodeCoordinates[i],
phantomNodeVector[i],
routeParameters.zoomLevel
);
}
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
@ -115,49 +116,56 @@ public:
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
}
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
// SimpleLogger().Write() << "Checking for alternative paths";
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
if(
( routeParameters.alternateRoute ) &&
(1 == rawRoute.segmentEndCoordinates.size())
) {
search_engine_ptr->alternative_path(
rawRoute.segmentEndCoordinates[0],
rawRoute
);
} else {
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
search_engine_ptr->shortest_path(
rawRoute.segmentEndCoordinates,
rawRoute
);
}
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
SimpleLogger().Write(logDEBUG) <<
"Error occurred, single path not found";
}
reply.status = http::Reply::ok;
//TODO: Move to member as smart pointer
BaseDescriptor * desc;
BaseDescriptor<DataFacadeT> * desc;
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
_DescriptorConfig descriptorConfig;
DescriptorConfig descriptorConfig;
unsigned descriptorType = 0;
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
}
descriptorConfig.z = routeParameters.zoomLevel;
descriptorConfig.zoom_level = routeParameters.zoomLevel;
descriptorConfig.instructions = routeParameters.printInstructions;
descriptorConfig.geometry = routeParameters.geometry;
descriptorConfig.encodeGeometry = routeParameters.compression;
descriptorConfig.encode_geometry = routeParameters.compression;
switch(descriptorType){
case 0:
desc = new JSONDescriptor();
desc = new JSONDescriptor<DataFacadeT>();
break;
case 1:
desc = new GPXDescriptor();
desc = new GPXDescriptor<DataFacadeT>();
break;
default:
desc = new JSONDescriptor();
desc = new JSONDescriptor<DataFacadeT>();
break;
}
@ -170,7 +178,7 @@ public:
// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size();
desc->SetConfig(descriptorConfig);
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
desc->Run(reply, rawRoute, phantomNodes, facade);
if("" != routeParameters.jsonpParameter) {
reply.content += ")\n";
}
@ -181,7 +189,7 @@ public:
reply.headers[0].value = tmp;
switch(descriptorType){
case 0:
if("" != routeParameters.jsonpParameter){
if( !routeParameters.jsonpParameter.empty() ){
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
@ -202,7 +210,7 @@ public:
break;
default:
if("" != routeParameters.jsonpParameter){
if( !routeParameters.jsonpParameter.empty() ){
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
@ -221,6 +229,7 @@ public:
}
private:
std::string descriptor_string;
DataFacadeT * facade;
};

View File

@ -6,7 +6,7 @@ require 'sys/proctable'
BUILD_FOLDER = 'build'
DATA_FOLDER = 'sandbox'
PROFILE = 'bicycle'
PROFILE = 'examples/postgis'
OSRM_PORT = 5000
PROFILES_FOLDER = '../profiles'

View File

@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ALTERNATIVEROUTES_H_
#include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h"
#include <boost/unordered_map.hpp>
#include <cmath>
#include <vector>
@ -37,15 +39,20 @@ const double VIAPATH_ALPHA = 0.15;
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
template<class QueryDataT>
class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::Graph SearchGraph;
typedef typename QueryDataT::QueryHeap QueryHeap;
template<class DataFacadeT>
class AlternativeRouting : private BasicRoutingInterface<DataFacadeT> {
typedef BasicRoutingInterface<DataFacadeT> super;
typedef typename DataFacadeT::EdgeData EdgeData;
typedef SearchEngineData::QueryHeap QueryHeap;
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
struct RankedCandidateNode {
RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {}
RankedCandidateNode(const NodeID n, const int l, const int s) :
node(n),
length(l),
sharing(s)
{ }
NodeID node;
int length;
int sharing;
@ -53,66 +60,129 @@ class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
return (2*length + sharing) < (2*other.length + other.sharing);
}
};
const SearchGraph * search_graph;
DataFacadeT * facade;
SearchEngineData & engine_working_data;
public:
AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
AlternativeRouting(
DataFacadeT * facade,
SearchEngineData & engine_working_data
) :
super(facade),
facade(facade),
engine_working_data(engine_working_data)
{ }
~AlternativeRouting() {}
void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
void operator()(
const PhantomNodes & phantom_node_pair,
RawRouteData & raw_route_data) {
if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) ||
phantom_node_pair.PhantomNodesHaveEqualLocation()
) {
raw_route_data.lengthOfShortestPath = INT_MAX;
raw_route_data.lengthOfAlternativePath = INT_MAX;
return;
}
std::vector<NodeID> alternativePath;
std::vector<NodeID> viaNodeCandidates;
std::vector<NodeID> alternative_path;
std::vector<NodeID> via_node_candidate_list;
std::vector<SearchSpaceEdge> forward_search_space;
std::vector<SearchSpaceEdge> reverse_search_space;
//Initialize Queues, semi-expensive because access to TSS invokes a system call
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
//Init queues, semi-expensive because access to TSS invokes a sys-call
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
int upper_bound_to_shortest_path_distance = INT_MAX;
NodeID middle_node = UINT_MAX;
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
if(phantomNodePair.startPhantom.isBidirected() ) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
}
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
if(phantomNodePair.targetPhantom.isBidirected() ) {
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode,
-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode
);
if(phantom_node_pair.startPhantom.isBidirected() ) {
forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1,
-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1
);
}
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
reverse_heap1.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode,
phantom_node_pair.targetPhantom.weight1,
phantom_node_pair.targetPhantom.edgeBasedNode
);
if(phantom_node_pair.targetPhantom.isBidirected() ) {
reverse_heap1.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode+1,
phantom_node_pair.targetPhantom.weight2,
phantom_node_pair.targetPhantom.edgeBasedNode+1
);
}
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
const int forward_offset = super::ComputeEdgeOffset(
phantom_node_pair.startPhantom
);
const int reverse_offset = super::ComputeEdgeOffset(
phantom_node_pair.targetPhantom
);
//search from s and t till new_min/(1+epsilon) > length_of_shortest_path
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
if(0 < forward_heap1.Size()){
AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
AlternativeRoutingStep<true>(
forward_heap1,
reverse_heap1,
&middle_node,
&upper_bound_to_shortest_path_distance,
via_node_candidate_list,
forward_search_space,
forward_offset
);
}
if(0 < reverse_heap1.Size()){
AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
AlternativeRoutingStep<false>(
reverse_heap1,
forward_heap1,
&middle_node,
&upper_bound_to_shortest_path_distance,
via_node_candidate_list,
reverse_search_space,
reverse_offset
);
}
}
sort_unique_resize(viaNodeCandidates);
sort_unique_resize(via_node_candidate_list);
std::vector<NodeID> packed_forward_path;
std::vector<NodeID> packed_reverse_path;
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
super::RetrievePackedPathFromSingleHeap(
forward_heap1,
middle_node,
packed_forward_path
);
super::RetrievePackedPathFromSingleHeap(
reverse_heap1,
middle_node,
packed_reverse_path
);
boost::unordered_map<NodeID, int> approximated_forward_sharing;
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
@ -146,7 +216,7 @@ public:
}
}
std::vector<NodeID> nodes_that_passed_preselection;
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
BOOST_FOREACH(const NodeID node, via_node_candidate_list) {
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
@ -187,17 +257,17 @@ public:
//Unpack shortest path and alternative, if they exist
if(INT_MAX != upper_bound_to_shortest_path_distance) {
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
super::UnpackPath(packedShortestPath, raw_route_data.computedShortestPath);
raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
} else {
rawRouteData.lengthOfShortestPath = INT_MAX;
raw_route_data.lengthOfShortestPath = INT_MAX;
}
if(selectedViaNode != UINT_MAX) {
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, raw_route_data.computedAlternativePath);
raw_route_data.lengthOfAlternativePath = lengthOfViaPath;
} else {
rawRouteData.lengthOfAlternativePath = INT_MAX;
raw_route_data.lengthOfAlternativePath = INT_MAX;
}
}
@ -219,12 +289,14 @@ private:
const int offset, const std::vector<NodeID> & packed_shortest_path) {
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
//only half-searches have to be done at this stage
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2;
QueryHeap & existingForwardHeap = *engine_working_data.forwardHeap;
QueryHeap & existingBackwardHeap = *engine_working_data.backwardHeap;
QueryHeap & newForwardHeap = *engine_working_data.forwardHeap2;
QueryHeap & newBackwardHeap = *engine_working_data.backwardHeap2;
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
@ -258,8 +330,8 @@ private:
//First partially unpack s-->v until paths deviate, note length of common path.
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
} else {
if (packed_s_v_path[i] == packed_shortest_path[i]) {
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
@ -270,8 +342,8 @@ private:
}
//traverse partially unpacked edge and note common prefix
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
}
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
@ -279,8 +351,8 @@ private:
int shortestPathIndex = packed_shortest_path.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
} else {
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
@ -294,8 +366,8 @@ private:
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
} else {
break;
}
@ -315,8 +387,8 @@ private:
//compute forward sharing
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += facade->GetEdgeData(edgeID).distance;
++aindex;
}
@ -324,8 +396,8 @@ private:
int bindex = packedShortestPath.size()-1;
//compute backward sharing
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += facade->GetEdgeData(edgeID).distance;
--aindex; --bindex;
}
return sharing;
@ -363,12 +435,12 @@ private:
}
}
for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
for ( EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); edge++ ) {
const EdgeData & data = facade->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = search_graph->GetTarget(edge);
const NodeID to = facade->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
@ -438,8 +510,8 @@ private:
std::stack<SearchSpaceEdge> unpackStack;
//Traverse path s-->v
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
} else {
@ -451,15 +523,15 @@ private:
while (!unpackStack.empty()) {
const SearchSpaceEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath);
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
EdgeID edgeIDOfSecondSegment = facade->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = facade->GetEdgeData(edgeIDOfSecondSegment).distance;
//attention: !unpacking in reverse!
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
@ -479,8 +551,8 @@ private:
unpackedUntilDistance = 0;
//Traverse path s-->v
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
} else {
@ -492,15 +564,15 @@ private:
while (!unpackStack.empty()) {
const SearchSpaceEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath);
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance;
EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = facade->GetEdgeData( edgeIDOfFirstSegment).distance;
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
@ -517,10 +589,12 @@ private:
lengthOfPathT_Test_Path += unpackedUntilDistance;
//Run actual T-Test query and compare if distances equal.
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
QueryHeap& forward_heap3 = *engine_working_data.forwardHeap3;
QueryHeap& backward_heap3 = *engine_working_data.backwardHeap3;
int _upperBound = INT_MAX;
NodeID middle = UINT_MAX;
forward_heap3.Insert(s_P, 0, s_P);

View File

@ -29,135 +29,180 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define BASICROUTINGINTERFACE_H_
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngineData.h"
#include "../Util/ContainerUtils.h"
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/noncopyable.hpp>
#include <cassert>
#include <climits>
#include <stack>
template<class QueryDataT>
class BasicRoutingInterface : boost::noncopyable{
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
template<class DataFacadeT>
class BasicRoutingInterface : boost::noncopyable {
private:
typedef typename DataFacadeT::EdgeData EdgeData;
protected:
QueryDataT & _queryData;
DataFacadeT * facade;
public:
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
virtual ~BasicRoutingInterface(){ };
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
const NodeID node = _forwardHeap.DeleteMin();
const int distance = _forwardHeap.GetKey(node);
//SimpleLogger().Write() << "Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance;
if(_backwardHeap.WasInserted(node) ){
const int newDistance = _backwardHeap.GetKey(node) + distance;
if(newDistance < *_upperbound ){
if(newDistance>=0 ) {
*middle = node;
*_upperbound = newDistance;
} else {
inline void RoutingStep(
SearchEngineData::QueryHeap & forward_heap,
SearchEngineData::QueryHeap & reverse_heap,
NodeID * middle_node_id,
int * upper_bound,
const int edge_expansion_offset,
const bool forward_direction
) const {
const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node);
//SimpleLogger().Write() << "Settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
if(reverse_heap.WasInserted(node) ){
const int new_distance = reverse_heap.GetKey(node) + distance;
if(new_distance < *upper_bound ){
if( new_distance >= 0 ) {
*middle_node_id = node;
*upper_bound = new_distance;
}
}
}
if(distance-edgeBasedOffset > *_upperbound){
_forwardHeap.DeleteAll();
if( (distance-edge_expansion_offset) > *upper_bound ){
forward_heap.DeleteAll();
return;
}
//Stalling
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) {
const NodeID to = _queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
for(
EdgeID edge = facade->BeginEdges( node );
edge < facade->EndEdges(node);
++edge
) {
const EdgeData & data = facade->GetEdgeData(edge);
const bool reverse_flag = (!forward_direction) ? data.forward : data.backward;
if( reverse_flag ) {
const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance;
assert( edgeWeight > 0 );
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
if(_forwardHeap.WasInserted( to )) {
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
if(forward_heap.WasInserted( to )) {
if(forward_heap.GetKey( to ) + edge_weight < distance) {
return;
}
}
}
}
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
for(
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
edge < end_edge;
++edge
) {
const EdgeData & data = facade->GetEdgeData(edge);
bool forward_directionFlag = (forward_direction ? data.forward : data.backward );
if( forward_directionFlag ) {
const NodeID to = _queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
const int to_distance = distance + edge_weight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap.WasInserted( to ) ) {
_forwardHeap.Insert( to, toDistance, node );
if ( !forward_heap.WasInserted( to ) ) {
forward_heap.Insert( to, to_distance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap.GetKey( to ) ) {
_forwardHeap.GetData( to ).parent = node;
_forwardHeap.DecreaseKey( to, toDistance );
else if ( to_distance < forward_heap.GetKey( to ) ) {
forward_heap.GetData( to ).parent = node;
forward_heap.DecreaseKey( to, to_distance );
//new parent
}
}
}
}
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const unsigned sizeOfPackedPath = packedPath.size();
std::stack<std::pair<NodeID, NodeID> > recursionStack;
inline void UnpackPath(
const std::vector<NodeID> & packed_path,
std::vector<_PathData> & unpacked_path
) const {
const unsigned packed_path_size = packed_path.size();
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
//We have to push the path in reverse order onto the stack because it's LIFO.
for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
for(unsigned i = packed_path_size-1; i > 0; --i){
recursion_stack.push(
std::make_pair(packed_path[i-1], packed_path[i])
);
}
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
while(!recursion_stack.empty()) {
edge = recursion_stack.top();
recursion_stack.pop();
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX;
for(
EdgeID edge_id = facade->BeginEdges(edge.first);
edge_id < facade->EndEdges(edge.first);
++edge_id
){
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.second) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).forward
){
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
if( SPECIAL_EDGEID == smaller_edge_id ){
for(
EdgeID edge_id = facade->BeginEdges(edge.second);
edge_id < facade->EndEdges(edge.second);
++edge_id
){
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.first) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).backward
){
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge id invalid");
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
if( ed.shortcut ) {//unpack
const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
} else {
assert(!ed.shortcut);
unpackedPath.push_back(
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
unpacked_path.push_back(
_PathData(
ed.id,
_queryData.nodeHelpDesk->GetNameIndexFromEdgeID(ed.id),
_queryData.nodeHelpDesk->GetTurnInstructionForEdgeID(ed.id),
facade->GetNameIndexFromEdgeID(ed.id),
facade->GetTurnInstructionForEdgeID(ed.id),
ed.distance
)
);
@ -165,74 +210,112 @@ public:
}
}
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
std::stack<std::pair<NodeID, NodeID> > recursionStack;
recursionStack.push(std::make_pair(s,t));
inline void UnpackEdge(
const NodeID s,
const NodeID t,
std::vector<NodeID> & unpacked_path
) const {
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
recursion_stack.push(std::make_pair(s,t));
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
while(!recursion_stack.empty()) {
edge = recursion_stack.top();
recursion_stack.pop();
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX;
for(
EdgeID edge_id = facade->BeginEdges(edge.first);
edge_id < facade->EndEdges(edge.first);
++edge_id
){
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.second) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).forward
){
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
if( SPECIAL_EDGEID == smaller_edge_id ){
for(
EdgeID edge_id = facade->BeginEdges(edge.second);
edge_id < facade->EndEdges(edge.second);
++edge_id
){
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.first) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).backward
){
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
recursion_stack.push(
std::make_pair(middle_node_id, edge.second)
);
recursion_stack.push(
std::make_pair(edge.first, middle_node_id)
);
} else {
assert(!ed.shortcut);
unpackedPath.push_back(edge.first );
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
unpacked_path.push_back(edge.first );
}
}
unpackedPath.push_back(t);
unpacked_path.push_back(t);
}
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
NodeID pathNode = middle;
while(pathNode != _fHeap.GetData(pathNode).parent) {
pathNode = _fHeap.GetData(pathNode).parent;
packedPath.push_back(pathNode);
inline void RetrievePackedPathFromHeap(
SearchEngineData::QueryHeap & forward_heap,
SearchEngineData::QueryHeap & reverse_heap,
const NodeID middle_node_id,
std::vector<NodeID> & packed_path
) const {
NodeID current_node_id = middle_node_id;
while(current_node_id != forward_heap.GetData(current_node_id).parent) {
current_node_id = forward_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id);
}
std::reverse(packedPath.begin(), packedPath.end());
packedPath.push_back(middle);
pathNode = middle;
while (pathNode != _bHeap.GetData(pathNode).parent){
pathNode = _bHeap.GetData(pathNode).parent;
packedPath.push_back(pathNode);
std::reverse(packed_path.begin(), packed_path.end());
packed_path.push_back(middle_node_id);
current_node_id = middle_node_id;
while (current_node_id != reverse_heap.GetData(current_node_id).parent){
current_node_id = reverse_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id);
}
}
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
NodeID pathNode = middle;
while(pathNode != search_heap.GetData(pathNode).parent) {
pathNode = search_heap.GetData(pathNode).parent;
packed_path.push_back(pathNode);
//TODO: reorder parameters
inline void RetrievePackedPathFromSingleHeap(
SearchEngineData::QueryHeap & search_heap,
const NodeID middle_node_id,
std::vector<NodeID>& packed_path
) const {
NodeID current_node_id = middle_node_id;
while(current_node_id != search_heap.GetData(current_node_id).parent) {
current_node_id = search_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id);
}
}
int ComputeEdgeOffset(const PhantomNode & phantom) const {
return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0);
}
};
#endif /* BASICROUTINGINTERFACE_H_ */

View File

@ -28,176 +28,314 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SHORTESTPATHROUTING_H_
#define SHORTESTPATHROUTING_H_
#include "BasicRoutingInterface.h"
#include <boost/assert.hpp>
#include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h"
template<class DataFacadeT>
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
typedef BasicRoutingInterface<DataFacadeT> super;
typedef SearchEngineData::QueryHeap QueryHeap;
SearchEngineData & engine_working_data;
template<class QueryDataT>
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super;
typedef typename QueryDataT::QueryHeap QueryHeap;
public:
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
ShortestPathRouting(
DataFacadeT * facade,
SearchEngineData & engine_working_data
) :
super(facade),
engine_working_data(engine_working_data)
{}
~ShortestPathRouting() {}
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
void operator()(
std::vector<PhantomNodes> & phantom_nodes_vector,
RawRouteData & raw_route_data
) const {
BOOST_FOREACH(
const PhantomNodes & phantom_node_pair,
phantom_nodes_vector
){
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
raw_route_data.lengthOfShortestPath = INT_MAX;
raw_route_data.lengthOfAlternativePath = INT_MAX;
return;
}
}
int distance1 = 0;
int distance2 = 0;
bool searchFrom1stStartNode = true;
bool searchFrom2ndStartNode = true;
bool search_from_1st_node = true;
bool search_from_2nd_node = true;
NodeID middle1 = UINT_MAX;
NodeID middle2 = UINT_MAX;
std::vector<NodeID> packedPath1;
std::vector<NodeID> packedPath2;
std::vector<NodeID> packed_path1;
std::vector<NodeID> packed_path2;
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
//Get distance to next pair of target nodes.
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
BOOST_FOREACH(
const PhantomNodes & phantom_node_pair,
phantom_nodes_vector
){
forward_heap1.Clear(); forward_heap2.Clear();
reverse_heap1.Clear(); reverse_heap2.Clear();
int _localUpperbound1 = INT_MAX;
int _localUpperbound2 = INT_MAX;
int local_upper_bound1 = INT_MAX;
int local_upper_bound2 = INT_MAX;
middle1 = UINT_MAX;
middle2 = UINT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances.
if(searchFrom1stStartNode) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
if(search_from_1st_node) {
forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode,
distance1-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode
);
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
forward_heap2.Insert(
phantom_node_pair.startPhantom.edgeBasedNode,
distance1-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode
);
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
}
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1,
distance2-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1
);
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
forward_heap2.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1,
distance2-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1
);
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
}
//insert new backward nodes into backward heap, unadjusted.
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
if(phantomNodePair.targetPhantom.isBidirected() ) {
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
// INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
reverse_heap1.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode,
phantom_node_pair.targetPhantom.weight1,
phantom_node_pair.targetPhantom.edgeBasedNode
);
// INFO("rv1: " << phantom_node_pair.targetPhantom.edgeBasedNode << ", w;" << phantom_node_pair.targetPhantom.weight1 );
if(phantom_node_pair.targetPhantom.isBidirected() ) {
reverse_heap2.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode+1,
phantom_node_pair.targetPhantom.weight2,
phantom_node_pair.targetPhantom.edgeBasedNode+1
);
// INFO("rv2: " << phantom_node_pair.targetPhantom.edgeBasedNode+1 << ", w;" << phantom_node_pair.targetPhantom.weight2 );
}
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
const int forward_offset = super::ComputeEdgeOffset(
phantom_node_pair.startPhantom
);
const int reverse_offset = super::ComputeEdgeOffset(
phantom_node_pair.targetPhantom
);
//run two-Target Dijkstra routing step.
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
if(0 < forward_heap1.Size()){
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
if( !forward_heap1.Empty()){
super::RoutingStep(
forward_heap1,
reverse_heap1,
&middle1,
&local_upper_bound1,
forward_offset,
true
);
}
if(0 < reverse_heap1.Size() ){
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
if( !reverse_heap1.Empty() ){
super::RoutingStep(
reverse_heap1,
forward_heap1,
&middle1,
&local_upper_bound1,
reverse_offset,
false
);
}
}
if(0 < reverse_heap2.Size()) {
if( !reverse_heap2.Empty() ) {
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
if(0 < forward_heap2.Size()){
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
if( !forward_heap2.Empty() ){
super::RoutingStep(
forward_heap2,
reverse_heap2,
&middle2,
&local_upper_bound2,
forward_offset,
true
);
}
if(0 < reverse_heap2.Size()){
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
if( !reverse_heap2.Empty() ){
super::RoutingStep(
reverse_heap2,
forward_heap2,
&middle2,
&local_upper_bound2,
reverse_offset,
false
);
}
}
}
//No path found for both target nodes?
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
if(
(INT_MAX == local_upper_bound1) &&
(INT_MAX == local_upper_bound2)
) {
raw_route_data.lengthOfShortestPath = INT_MAX;
raw_route_data.lengthOfAlternativePath = INT_MAX;
return;
}
if(UINT_MAX == middle1) {
searchFrom1stStartNode = false;
search_from_1st_node = false;
}
if(UINT_MAX == middle2) {
searchFrom2ndStartNode = false;
search_from_2nd_node = false;
}
//Was at most one of the two paths not found?
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
BOOST_ASSERT_MSG(
(INT_MAX != distance1 || INT_MAX != distance2),
"no path found"
);
//Unpack paths if they exist
std::vector<NodeID> temporaryPackedPath1;
std::vector<NodeID> temporaryPackedPath2;
if(INT_MAX != _localUpperbound1) {
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
std::vector<NodeID> temporary_packed_path1;
std::vector<NodeID> temporary_packed_path2;
if(INT_MAX != local_upper_bound1) {
super::RetrievePackedPathFromHeap(
forward_heap1,
reverse_heap1,
middle1,
temporary_packed_path1
);
}
if(INT_MAX != _localUpperbound2) {
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
if(INT_MAX != local_upper_bound2) {
super::RetrievePackedPathFromHeap(
forward_heap2,
reverse_heap2,
middle2,
temporary_packed_path2
);
}
//if one of the paths was not found, replace it with the other one.
if(0 == temporaryPackedPath1.size()) {
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
_localUpperbound1 = _localUpperbound2;
if( temporary_packed_path1.empty() ) {
temporary_packed_path1.insert(
temporary_packed_path1.end(),
temporary_packed_path2.begin(),
temporary_packed_path2.end()
);
local_upper_bound1 = local_upper_bound2;
}
if(0 == temporaryPackedPath2.size()) {
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
_localUpperbound2 = _localUpperbound1;
if( temporary_packed_path2.empty() ) {
temporary_packed_path2.insert(
temporary_packed_path2.end(),
temporary_packed_path1.begin(),
temporary_packed_path1.end()
);
local_upper_bound2 = local_upper_bound1;
}
assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
BOOST_ASSERT_MSG(
!temporary_packed_path1.empty() ||
!temporary_packed_path2.empty(),
"tempory packed paths empty"
);
//Plug paths together, s.t. end of packed path is begin of temporary packed path
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
//both new route segments start with the same node, thus one of the packedPath must go.
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
packedPath2.clear();
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
if( !packed_path1.empty() && !packed_path2.empty() ) {
if(
temporary_packed_path1.front() ==
temporary_packed_path2.front()
) {
//both new route segments start with the same node
//thus, one of the packedPath must go.
BOOST_ASSERT_MSG(
(packed_path1.size() == packed_path2.size() ) ||
(packed_path1.back() != packed_path2.back() ),
"packed paths must be different"
);
if( packed_path1.back() == temporary_packed_path1.front()) {
packed_path2.clear();
packed_path2.insert(
packed_path2.end(),
packed_path1.begin(),
packed_path1.end()
);
} else {
packedPath1.clear();
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
packed_path1.clear();
packed_path1.insert(
packed_path1.end(),
packed_path2.begin(),
packed_path2.end()
);
}
} else {
//packed paths 1 and 2 may need to switch.
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
packedPath1.swap(packedPath2);
if( packed_path1.back() != temporary_packed_path1.front()) {
packed_path1.swap(packed_path2);
std::swap(distance1, distance2);
}
}
}
packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
packed_path1.insert(
packed_path1.end(),
temporary_packed_path1.begin(),
temporary_packed_path1.end()
);
packed_path2.insert(
packed_path2.end(),
temporary_packed_path2.begin(),
temporary_packed_path2.end()
);
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
NodeID lastNodeID = packedPath2.back();
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
if(
(packed_path1.back() == packed_path2.back()) &&
phantom_node_pair.targetPhantom.isBidirected()
) {
const NodeID last_node_id = packed_path2.back();
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
}
distance1 = _localUpperbound1;
distance2 = _localUpperbound2;
distance1 = local_upper_bound1;
distance2 = local_upper_bound2;
}
if(distance1 > distance2){
std::swap(packedPath1, packedPath2);
if( distance1 > distance2 ) {
std::swap( packed_path1, packed_path2 );
}
remove_consecutive_duplicates_from_vector(packedPath1);
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
return;
remove_consecutive_duplicates_from_vector(packed_path1);
super::UnpackPath(packed_path1, raw_route_data.computedShortestPath);
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
}
};

View File

@ -0,0 +1,122 @@
/*
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.
*/
#ifndef QUERY_DATA_FACADE_H
#define QUERY_DATA_FACADE_H
//Exposes all data access interfaces to the algorithms via base class ptr
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/EdgeBasedNode.h"
#include "../../DataStructures/ImportNode.h"
#include "../../DataStructures/PhantomNodes.h"
#include "../../DataStructures/TurnInstructions.h"
#include "../../Util/OSRMException.h"
#include "../../Util/StringUtil.h"
#include "../../typedefs.h"
#include <string>
template<class EdgeDataT>
class BaseDataFacade {
public:
typedef EdgeBasedNode RTreeLeaf;
typedef EdgeDataT EdgeData;
BaseDataFacade( ) { }
virtual ~BaseDataFacade() { }
//search graph access
virtual unsigned GetNumberOfNodes() const = 0;
virtual unsigned GetNumberOfEdges() const = 0;
virtual unsigned GetOutDegree( const NodeID n ) const = 0;
virtual NodeID GetTarget( const EdgeID e ) const = 0;
virtual EdgeDataT &GetEdgeData( const EdgeID e ) = 0;
// virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0;
virtual EdgeID BeginEdges( const NodeID n ) const = 0;
virtual EdgeID EndEdges( const NodeID n ) const = 0;
//searches for a specific edge
virtual EdgeID FindEdge( const NodeID from, const NodeID to ) const = 0;
virtual EdgeID FindEdgeInEitherDirection(
const NodeID from,
const NodeID to
) const = 0;
virtual EdgeID FindEdgeIndicateIfReverse(
const NodeID from,
const NodeID to,
bool & result
) const = 0;
//node and edge information access
virtual FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const = 0;
virtual TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const = 0;
virtual bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const = 0;
virtual bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const = 0;
virtual unsigned GetCheckSum() const = 0;
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
virtual void GetName(
const unsigned name_id,
std::string & result
) const = 0;
std::string GetEscapedNameForNameID(const unsigned name_id) const {
std::string temporary_string;
GetName(name_id, temporary_string);
return HTMLEntitize(temporary_string);
}
virtual std::string GetTimestamp() const = 0;
};
#endif // QUERY_DATA_FACADE_H

View File

@ -0,0 +1,396 @@
/*
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.
*/
#ifndef INTERNAL_DATA_FACADE
#define INTERNAL_DATA_FACADE
//implements all data storage when shared memory is _NOT_ used
#include "BaseDataFacade.h"
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/QueryNode.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/SharedMemoryVectorWrapper.h"
#include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h"
#include "../../Util/BoostFileSystemFix.h"
#include "../../Util/GraphLoader.h"
#include "../../Util/IniFile.h"
#include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h"
template<class EdgeDataT>
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
private:
typedef BaseDataFacade<EdgeDataT> super;
typedef StaticGraph<typename super::EdgeData> QueryGraph;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
InternalDataFacade() { }
unsigned m_check_sum;
unsigned m_number_of_nodes;
QueryGraph * m_query_graph;
std::string m_timestamp;
ShM<FixedPointCoordinate, false>::vector m_coordinate_list;
ShM<NodeID, false>::vector m_via_node_list;
ShM<unsigned, false>::vector m_name_ID_list;
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
ShM<char, false>::vector m_names_char_list;
ShM<unsigned, false>::vector m_name_begin_indices;
StaticRTree<RTreeLeaf, false> * m_static_rtree;
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
if( boost::filesystem::exists(timestamp_path) ) {
SimpleLogger().Write() << "Loading Timestamp";
boost::filesystem::ifstream timestampInStream( timestamp_path );
if(!timestampInStream) {
SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
}
getline(timestampInStream, m_timestamp);
timestampInStream.close();
}
if(m_timestamp.empty()) {
m_timestamp = "n/a";
}
if(25 < m_timestamp.length()) {
m_timestamp.resize(25);
}
}
void LoadGraph(const boost::filesystem::path & hsgr_path) {
typename ShM<typename QueryGraph::_StrNode, false>::vector node_list;
typename ShM<typename QueryGraph::_StrEdge, false>::vector edge_list;
SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
m_number_of_nodes = readHSGRFromStream(
hsgr_path,
node_list,
edge_list,
&m_check_sum
);
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
m_query_graph = new QueryGraph(node_list, edge_list);
BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed");
SimpleLogger().Write() << "Data checksum is " << m_check_sum;
}
void LoadNodeAndEdgeInformation(
const boost::filesystem::path nodes_file,
const boost::filesystem::path edges_file
) {
boost::filesystem::ifstream nodes_input_stream(
nodes_file,
std::ios::binary
);
SimpleLogger().Write(logDEBUG) << "Loading node data";
NodeInfo current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read(
(char *)&number_of_coordinates,
sizeof(unsigned)
);
m_coordinate_list.resize(number_of_coordinates);
for(unsigned i = 0; i < number_of_coordinates; ++i) {
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
m_coordinate_list[i] = FixedPointCoordinate(
current_node.lat,
current_node.lon
);
}
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
nodes_input_stream.close();
SimpleLogger().Write(logDEBUG) << "Loading edge data";
boost::filesystem::ifstream edges_input_stream(
edges_file,
std::ios::binary
);
unsigned number_of_edges = 0;
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_edges; ++i) {
edges_input_stream.read(
(char*)&(current_edge_data),
sizeof(OriginalEdgeData)
);
m_via_node_list[i] = current_edge_data.viaNode;
m_name_ID_list[i] = current_edge_data.nameID;
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
}
edges_input_stream.close();
}
void LoadRTree(
const boost::filesystem::path & ram_index_path,
const boost::filesystem::path & file_index_path
) {
m_static_rtree = new StaticRTree<RTreeLeaf>(
ram_index_path,
file_index_path
);
}
void LoadStreetNames(
const boost::filesystem::path & names_file
) {
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
unsigned number_of_names = 0;
unsigned number_of_chars = 0;
name_stream.read((char *)&number_of_names, sizeof(unsigned));
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != number_of_names, "name file broken");
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
m_name_begin_indices.resize(number_of_names);
name_stream.read(
(char*)&m_name_begin_indices[0],
number_of_names*sizeof(unsigned)
);
m_names_char_list.resize(number_of_chars+1); //+1 gives sentinel element
name_stream.read(
(char *)&m_names_char_list[0],
number_of_chars*sizeof(char)
);
BOOST_ASSERT_MSG(
0 != m_names_char_list.size(),
"could not load any names"
);
name_stream.close();
}
public:
~InternalDataFacade() {
delete m_query_graph;
delete m_static_rtree;
}
InternalDataFacade( const ServerPaths & server_paths ) {
//generate paths of data files
if( server_paths.find("hsgrdata") == server_paths.end() ) {
throw OSRMException("no hsgr file given in ini file");
}
if( server_paths.find("ramindex") == server_paths.end() ) {
throw OSRMException("no ram index file given in ini file");
}
if( server_paths.find("fileindex") == server_paths.end() ) {
throw OSRMException("no leaf index file given in ini file");
}
if( server_paths.find("nodesdata") == server_paths.end() ) {
throw OSRMException("no nodes file given in ini file");
}
if( server_paths.find("edgesdata") == server_paths.end() ) {
throw OSRMException("no edges file given in ini file");
}
if( server_paths.find("namesdata") == server_paths.end() ) {
throw OSRMException("no names file given in ini file");
}
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & hsgr_path = paths_iterator->second;
paths_iterator = server_paths.find("timestamp");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & timestamp_path = paths_iterator->second;
paths_iterator = server_paths.find("ramindex");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & ram_index_path = paths_iterator->second;
paths_iterator = server_paths.find("fileindex");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & file_index_path = paths_iterator->second;
paths_iterator = server_paths.find("nodesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & nodes_data_path = paths_iterator->second;
paths_iterator = server_paths.find("edgesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & edges_data_path = paths_iterator->second;
paths_iterator = server_paths.find("namesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & names_data_path = paths_iterator->second;
//load data
SimpleLogger().Write() << "loading graph data";
LoadGraph(hsgr_path);
SimpleLogger().Write() << "loading egde information";
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
SimpleLogger().Write() << "loading r-tree";
LoadRTree(ram_index_path, file_index_path);
SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(timestamp_path);
SimpleLogger().Write() << "loading street names";
LoadStreetNames(names_data_path);
}
//search graph access
unsigned GetNumberOfNodes() const {
return m_query_graph->GetNumberOfNodes();
}
unsigned GetNumberOfEdges() const {
return m_query_graph->GetNumberOfEdges();
}
unsigned GetOutDegree( const NodeID n ) const {
return m_query_graph->GetOutDegree(n);
}
NodeID GetTarget( const EdgeID e ) const {
return m_query_graph->GetTarget(e); }
EdgeDataT &GetEdgeData( const EdgeID e ) {
return m_query_graph->GetEdgeData(e);
}
const EdgeDataT &GetEdgeData( const EdgeID e ) const {
return m_query_graph->GetEdgeData(e);
}
EdgeID BeginEdges( const NodeID n ) const {
return m_query_graph->BeginEdges(n);
}
EdgeID EndEdges( const NodeID n ) const {
return m_query_graph->EndEdges(n);
}
//searches for a specific edge
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
return m_query_graph->FindEdge(from, to);
}
EdgeID FindEdgeInEitherDirection(
const NodeID from,
const NodeID to
) const {
return m_query_graph->FindEdgeInEitherDirection(from, to);
}
EdgeID FindEdgeIndicateIfReverse(
const NodeID from,
const NodeID to,
bool & result
) const {
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
}
//node and edge information access
FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const {
const NodeID node = m_via_node_list.at(id);
return m_coordinate_list.at(node);
};
TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const {
return m_turn_instruction_list.at(id);
}
bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
return m_static_rtree->LocateClosestEndPointForCoordinate(
input_coordinate,
result,
zoom_level
);
}
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
}
unsigned GetCheckSum() const { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
return m_name_ID_list.at(id);
};
void GetName( const unsigned name_id, std::string & result ) const {
if(UINT_MAX == name_id) {
result = "";
return;
}
BOOST_ASSERT_MSG(
name_id < m_name_begin_indices.size(),
"name id too high"
);
unsigned begin_index = m_name_begin_indices[name_id];
unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG(
begin_index < m_names_char_list.size(),
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index < m_names_char_list.size(),
"end index of name too high"
);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear();
result.resize(end_index - begin_index);
std::copy(
m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + end_index,
result.begin()
);
}
std::string GetTimestamp() const {
return m_timestamp;
}
};
#endif // INTERNAL_DATA_FACADE

View File

@ -1,183 +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 "QueryObjectsStorage.h"
QueryObjectsStorage::QueryObjectsStorage( const ServerPaths & paths ) {
if( paths.find("hsgrdata") == paths.end() ) {
throw OSRMException("no hsgr file given in ini file");
}
if( paths.find("ramindex") == paths.end() ) {
throw OSRMException("no ram index file given in ini file");
}
if( paths.find("fileindex") == paths.end() ) {
throw OSRMException("no mem index file given in ini file");
}
if( paths.find("nodesdata") == paths.end() ) {
throw OSRMException("no nodes file given in ini file");
}
if( paths.find("edgesdata") == paths.end() ) {
throw OSRMException("no edges file given in ini file");
}
if( paths.find("namesdata") == paths.end() ) {
throw OSRMException("no names file given in ini file");
}
SimpleLogger().Write() << "loading graph data";
//Deserialize road network graph
ServerPaths::const_iterator paths_iterator = paths.find("hsgrdata");
BOOST_ASSERT(paths.end() != paths_iterator);
const std::string & hsgr_data_string = paths_iterator->second.string();
std::vector< QueryGraph::_StrNode> node_list;
std::vector< QueryGraph::_StrEdge> edge_list;
const int number_of_nodes = readHSGRFromStream(
hsgr_data_string,
node_list,
edge_list,
&check_sum
);
SimpleLogger().Write() << "Data checksum is " << check_sum;
graph = new QueryGraph(node_list, edge_list);
BOOST_ASSERT(0 == node_list.size());
BOOST_ASSERT(0 == edge_list.size());
paths_iterator = paths.find("timestamp");
if(paths.end() != paths_iterator) {
SimpleLogger().Write() << "Loading Timestamp";
const std::string & timestamp_string = paths_iterator->second.string();
boost::filesystem::ifstream time_stamp_instream(timestamp_string);
if( !time_stamp_instream.good() ) {
SimpleLogger().Write(logWARNING) << timestamp_string << " not found";
}
getline(time_stamp_instream, timestamp);
time_stamp_instream.close();
}
if(!timestamp.length()) {
timestamp = "n/a";
}
if(25 < timestamp.length()) {
timestamp.resize(25);
}
SimpleLogger().Write() << "Loading auxiliary information";
paths_iterator = paths.find("ramindex");
BOOST_ASSERT(paths.end() != paths_iterator);
const std::string & ram_index_string = paths_iterator->second.string();
paths_iterator = paths.find("fileindex");
BOOST_ASSERT(paths.end() != paths_iterator);
const std::string & file_index_string = paths_iterator->second.string();
paths_iterator = paths.find("nodesdata");
BOOST_ASSERT(paths.end() != paths_iterator);
const std::string & nodes_data_string = paths_iterator->second.string();
paths_iterator = paths.find("edgesdata");
BOOST_ASSERT(paths.end() != paths_iterator);
const std::string & edges_data_string = paths_iterator->second.string();
//Init nearest neighbor data structure
nodeHelpDesk = new NodeInformationHelpDesk(
ram_index_string,
file_index_string,
nodes_data_string,
edges_data_string,
number_of_nodes,
check_sum
);
//deserialize street name list
SimpleLogger().Write() << "Loading names index";
paths_iterator = paths.find("namesdata");
BOOST_ASSERT(paths.end() != paths_iterator);
const std::string & names_data_string = paths_iterator->second.string();
if ( !boost::filesystem::exists( paths_iterator->second ) ) {
throw OSRMException("names file does not exist");
}
if ( 0 == boost::filesystem::file_size( paths_iterator->second ) ) {
throw OSRMException("names file is empty");
}
boost::filesystem::ifstream name_stream(names_data_string, std::ios::binary);
unsigned size = 0;
name_stream.read((char *)&size, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != size, "name file broken");
m_name_begin_indices.resize(size);
name_stream.read((char*)&m_name_begin_indices[0], size*sizeof(unsigned));
name_stream.read((char *)&size, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != size, "name file broken");
m_names_char_list.resize(size+1); //+1 is sentinel/dummy element
name_stream.read((char *)&m_names_char_list[0], size*sizeof(char));
BOOST_ASSERT_MSG(0 != m_names_char_list.size(), "could not load any names");
name_stream.close();
SimpleLogger().Write() << "All query data structures loaded";
}
void QueryObjectsStorage::GetName(
const unsigned name_id,
std::string & result
) const {
if(UINT_MAX == name_id) {
result = "";
return;
}
BOOST_ASSERT_MSG(
name_id < m_name_begin_indices.size(),
"name id too high"
);
unsigned begin_index = m_name_begin_indices[name_id];
unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG(
begin_index < m_names_char_list.size(),
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index < m_names_char_list.size(),
"end index of name too high"
);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear();
result.resize(end_index - begin_index);
std::copy(
m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + end_index,
result.begin()
);
}
QueryObjectsStorage::~QueryObjectsStorage() {
delete graph;
delete nodeHelpDesk;
}

View File

@ -0,0 +1,40 @@
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
struct SharedBarriers {
SharedBarriers ()
:
pending_update_mutex(
boost::interprocess::open_or_create,
"pending_update"
),
update_mutex(
boost::interprocess::open_or_create,
"update"
),
query_mutex(
boost::interprocess::open_or_create,
"query"
),
no_running_queries_condition(
boost::interprocess::open_or_create,
"no_running_queries"
),
update_ongoing(false),
number_of_queries(0)
{ }
// Mutex to protect access to the boolean variable
boost::interprocess::named_mutex pending_update_mutex;
boost::interprocess::named_mutex update_mutex;
boost::interprocess::named_mutex query_mutex;
// Condition that no update is running
boost::interprocess::named_condition no_running_queries_condition;
// Is there an ongoing update?
bool update_ongoing;
// Is there any query?
int number_of_queries;
};

View File

@ -0,0 +1,385 @@
/*
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.
*/
#ifndef SHARED_DATA_FACADE_H
#define SHARED_DATA_FACADE_H
//implements all data storage when shared memory is _NOT_ used
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include "BaseDataFacade.h"
#include "SharedDataType.h"
#include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h"
#include "../../Util/BoostFileSystemFix.h"
#include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h"
#include <algorithm>
template<class EdgeDataT>
class SharedDataFacade : public BaseDataFacade<EdgeDataT> {
private:
typedef EdgeDataT EdgeData;
typedef BaseDataFacade<EdgeData> super;
typedef StaticGraph<EdgeData, true> QueryGraph;
typedef typename StaticGraph<EdgeData, true>::_StrNode GraphNode;
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
typedef typename StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
SharedDataLayout * data_layout;
char * shared_memory;
SharedDataTimestamp * data_timestamp_ptr;
SharedDataType CURRENT_LAYOUT;
SharedDataType CURRENT_DATA;
unsigned CURRENT_TIMESTAMP;
unsigned m_check_sum;
unsigned m_number_of_nodes;
boost::shared_ptr<QueryGraph> m_query_graph;
boost::shared_ptr<SharedMemory> m_layout_memory;
boost::shared_ptr<SharedMemory> m_large_memory;
std::string m_timestamp;
ShM<FixedPointCoordinate, true>::vector m_coordinate_list;
ShM<NodeID, true>::vector m_via_node_list;
ShM<unsigned, true>::vector m_name_ID_list;
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
ShM<char, true>::vector m_names_char_list;
ShM<unsigned, true>::vector m_name_begin_indices;
boost::shared_ptr<StaticRTree<RTreeLeaf, true> > m_static_rtree;
// SharedDataFacade() { }
void LoadTimestamp() {
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
m_timestamp.resize(data_layout->timestamp_length);
std::copy(
timestamp_ptr,
timestamp_ptr+data_layout->timestamp_length,
m_timestamp.begin()
);
}
void LoadRTree(
const boost::filesystem::path & file_index_path
) {
RTreeNode * tree_ptr = (RTreeNode *)(
shared_memory + data_layout->GetRSearchTreeOffset()
);
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, true> >(
tree_ptr,
data_layout->r_search_tree_size,
file_index_path
);
}
void LoadGraph() {
m_number_of_nodes = data_layout->graph_node_list_size;
GraphNode * graph_nodes_ptr = (GraphNode *)(
shared_memory + data_layout->GetGraphNodeListOffset()
);
GraphEdge * graph_edges_ptr = (GraphEdge *)(
shared_memory + data_layout->GetGraphEdgeListOffsett()
);
typename ShM<GraphNode, true>::vector node_list(
graph_nodes_ptr,
data_layout->graph_node_list_size
);
typename ShM<GraphEdge, true>::vector edge_list(
graph_edges_ptr,
data_layout->graph_edge_list_size
);
m_query_graph.reset(
new QueryGraph(node_list, edge_list)
);
}
void LoadNodeAndEdgeInformation() {
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
shared_memory + data_layout->GetCoordinateListOffset()
);
typename ShM<FixedPointCoordinate, true>::vector coordinate_list(
coordinate_list_ptr,
data_layout->coordinate_list_size
);
m_coordinate_list.swap( coordinate_list );
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
shared_memory + data_layout->GetTurnInstructionListOffset()
);
typename ShM<TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr,
data_layout->turn_instruction_list_size
);
m_turn_instruction_list.swap(turn_instruction_list);
unsigned * name_id_list_ptr = (unsigned *)(
shared_memory + data_layout->GetNameIDListOffset()
);
typename ShM<unsigned, true>::vector name_id_list(
name_id_list_ptr,
data_layout->name_id_list_size
);
m_name_ID_list.swap(name_id_list);
}
void LoadViaNodeList() {
NodeID * via_node_list_ptr = (NodeID *)(
shared_memory + data_layout->GetViaNodeListOffset()
);
typename ShM<NodeID, true>::vector via_node_list(
via_node_list_ptr,
data_layout->via_node_list_size
);
m_via_node_list.swap(via_node_list);
}
void LoadNames() {
unsigned * street_names_index_ptr = (unsigned *)(
shared_memory + data_layout->GetNameIndexOffset()
);
typename ShM<unsigned, true>::vector name_begin_indices(
street_names_index_ptr,
data_layout->name_index_list_size
);
m_name_begin_indices.swap(name_begin_indices);
char * names_list_ptr = (char *)(
shared_memory + data_layout->GetNameListOffset()
);
typename ShM<char, true>::vector names_char_list(
names_list_ptr,
data_layout->name_char_list_size
);
m_names_char_list.swap(names_char_list);
}
public:
SharedDataFacade( ) {
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
CURRENT_REGIONS,
sizeof(SharedDataTimestamp),
false,
false
)->Ptr();
CURRENT_LAYOUT = LAYOUT_NONE;
CURRENT_DATA = DATA_NONE;
CURRENT_TIMESTAMP = 0;
//load data
CheckAndReloadFacade();
}
void CheckAndReloadFacade() {
if(
CURRENT_LAYOUT != data_timestamp_ptr->layout ||
CURRENT_DATA != data_timestamp_ptr->data ||
CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp
) {
// release the previous shared memory segments
SharedMemory::Remove(CURRENT_LAYOUT);
SharedMemory::Remove(CURRENT_DATA);
CURRENT_LAYOUT = data_timestamp_ptr->layout;
CURRENT_DATA = data_timestamp_ptr->data;
CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp;
m_layout_memory.reset( SharedMemoryFactory::Get(CURRENT_LAYOUT) );
data_layout = (SharedDataLayout *)(
m_layout_memory->Ptr()
);
boost::filesystem::path ram_index_path(data_layout->ram_index_file_name);
if( !boost::filesystem::exists(ram_index_path) ) {
throw OSRMException(
"no leaf index file given. "
"Is any data loaded into shared memory?"
);
}
m_large_memory.reset( SharedMemoryFactory::Get(CURRENT_DATA) );
shared_memory = (char *)(
m_large_memory->Ptr()
);
LoadGraph();
LoadNodeAndEdgeInformation();
LoadRTree(ram_index_path);
LoadTimestamp();
LoadViaNodeList();
LoadNames();
data_layout->PrintInformation();
}
}
//search graph access
unsigned GetNumberOfNodes() const {
return m_query_graph->GetNumberOfNodes();
}
unsigned GetNumberOfEdges() const {
return m_query_graph->GetNumberOfEdges();
}
unsigned GetOutDegree( const NodeID n ) const {
return m_query_graph->GetOutDegree(n);
}
NodeID GetTarget( const EdgeID e ) const {
return m_query_graph->GetTarget(e); }
EdgeDataT &GetEdgeData( const EdgeID e ) {
return m_query_graph->GetEdgeData(e);
}
// const EdgeDataT &GetEdgeData( const EdgeID e ) const {
// return m_query_graph->GetEdgeData(e);
// }
EdgeID BeginEdges( const NodeID n ) const {
return m_query_graph->BeginEdges(n);
}
EdgeID EndEdges( const NodeID n ) const {
return m_query_graph->EndEdges(n);
}
//searches for a specific edge
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
return m_query_graph->FindEdge(from, to);
}
EdgeID FindEdgeInEitherDirection(
const NodeID from,
const NodeID to
) const {
return m_query_graph->FindEdgeInEitherDirection(from, to);
}
EdgeID FindEdgeIndicateIfReverse(
const NodeID from,
const NodeID to,
bool & result
) const {
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
}
//node and edge information access
FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const {
const NodeID node = m_via_node_list.at(id);
return m_coordinate_list.at(node);
};
TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const {
return m_turn_instruction_list.at(id);
}
bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
return m_static_rtree->LocateClosestEndPointForCoordinate(
input_coordinate,
result,
zoom_level
);
}
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
return m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
}
unsigned GetCheckSum() const { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
return m_name_ID_list.at(id);
};
void GetName( const unsigned name_id, std::string & result ) const {
if(UINT_MAX == name_id) {
result = "";
return;
}
BOOST_ASSERT_MSG(
name_id < m_name_begin_indices.size(),
"name id too high"
);
unsigned begin_index = m_name_begin_indices[name_id];
unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG(
begin_index < m_names_char_list.size(),
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index < m_names_char_list.size(),
"end index of name too high"
);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear();
result.resize(end_index - begin_index);
std::copy(
m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + end_index,
result.begin()
);
}
std::string GetTimestamp() const {
return m_timestamp;
}
};
#endif // SHARED_DATA_FACADE_H

View File

@ -0,0 +1,229 @@
/*
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.
*/
#ifndef SHARED_DATA_TYPE_H_
#define SHARED_DATA_TYPE_H_
#include "BaseDataFacade.h"
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h"
#include "../../DataStructures/TurnInstructions.h"
#include "../../typedefs.h"
#include <boost/integer.hpp>
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
typedef StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
struct SharedDataLayout {
uint64_t name_index_list_size;
uint64_t name_char_list_size;
uint64_t name_id_list_size;
uint64_t via_node_list_size;
uint64_t graph_node_list_size;
uint64_t graph_edge_list_size;
uint64_t coordinate_list_size;
uint64_t turn_instruction_list_size;
uint64_t r_search_tree_size;
unsigned checksum;
unsigned timestamp_length;
char ram_index_file_name[1024];
SharedDataLayout() :
name_index_list_size(0),
name_char_list_size(0),
name_id_list_size(0),
via_node_list_size(0),
graph_node_list_size(0),
graph_edge_list_size(0),
coordinate_list_size(0),
turn_instruction_list_size(0),
r_search_tree_size(0),
checksum(0),
timestamp_length(0)
{
ram_index_file_name[0] = '\0';
}
void PrintInformation() const {
SimpleLogger().Write(logDEBUG) << "-";
SimpleLogger().Write(logDEBUG) << "name_index_list_size: " << name_index_list_size;
SimpleLogger().Write(logDEBUG) << "name_char_list_size: " << name_char_list_size;
SimpleLogger().Write(logDEBUG) << "name_id_list_size: " << name_id_list_size;
SimpleLogger().Write(logDEBUG) << "via_node_list_size: " << via_node_list_size;
SimpleLogger().Write(logDEBUG) << "graph_node_list_size: " << graph_node_list_size;
SimpleLogger().Write(logDEBUG) << "graph_edge_list_size: " << graph_edge_list_size;
SimpleLogger().Write(logDEBUG) << "timestamp_length: " << timestamp_length;
SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << coordinate_list_size;
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_list_size;
SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << r_search_tree_size;
SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << sizeof(checksum);
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
}
uint64_t GetSizeOfLayout() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
(r_search_tree_size * sizeof(RTreeNode) ) +
sizeof(checksum) +
1024*sizeof(char);
return result;
}
uint64_t GetNameIndexOffset() const {
return 0;
}
uint64_t GetNameListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) );
return result;
}
uint64_t GetNameIDListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) );
return result;
}
uint64_t GetViaNodeListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) );
return result;
}
uint64_t GetGraphNodeListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) );
return result;
}
uint64_t GetGraphEdgeListOffsett() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
return result;
}
uint64_t GetTimeStampOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge));
return result;
}
uint64_t GetCoordinateListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) );
return result;
}
uint64_t GetTurnInstructionListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate));
return result;
}
uint64_t GetRSearchTreeOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
(turn_instruction_list_size * sizeof(TurnInstructions) );
return result;
}
uint64_t GetChecksumOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
(r_search_tree_size * sizeof(RTreeNode) );
return result;
}
};
enum SharedDataType {
CURRENT_REGIONS,
LAYOUT_1,
DATA_1,
LAYOUT_2,
DATA_2,
LAYOUT_NONE,
DATA_NONE
};
struct SharedDataTimestamp {
SharedDataType layout;
SharedDataType data;
unsigned timestamp;
};
#endif /* SHARED_DATA_TYPE_H_ */

View File

@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../Util/GitDescription.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
@ -74,8 +75,9 @@ void RunStatistics(std::vector<double> & timings_vector, Statistics & stats) {
int main (int argc, char * argv[]) {
LogPolicy::GetInstance().Unmute();
SimpleLogger().Write(logDEBUG) << "starting up engines, compiled at " <<
__DATE__ << ", " __TIME__;
SimpleLogger().Write() <<
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
"compiled at " << __DATE__ << ", " __TIME__;
if( 1 == argc ) {
SimpleLogger().Write(logWARNING) <<

View File

@ -55,7 +55,7 @@ int main (int argc, const char * argv[]) {
try {
std::string ip_address;
int ip_port, requested_num_threads;
bool use_shared_memory = false;
ServerPaths server_paths;
if( !GenerateServerProgramOptions(
argc,
@ -63,7 +63,8 @@ int main (int argc, const char * argv[]) {
server_paths,
ip_address,
ip_port,
requested_num_threads
requested_num_threads,
use_shared_memory
)
) {
return 0;
@ -73,7 +74,7 @@ int main (int argc, const char * argv[]) {
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
"compiled at " << __DATE__ << ", " __TIME__;
OSRM routing_machine(server_paths);
OSRM routing_machine( server_paths, use_shared_memory );
RouteParameters route_parameters;
route_parameters.zoomLevel = 18; //no generalization

View File

@ -0,0 +1,45 @@
/*
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/GitDescription.h"
#include "../Util/SimpleLogger.h"
#include "../Server/DataStructures/SharedBarriers.h"
#include <iostream>
int main() {
LogPolicy::GetInstance().Unmute();
SimpleLogger().Write() <<
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
"compiled at " << __DATE__ << ", " __TIME__;
SimpleLogger().Write() << "Releasing all locks";
SharedBarriers barrier;
barrier.pending_update_mutex.unlock();
barrier.query_mutex.unlock();
barrier.update_mutex.unlock();
return 0;
}

View File

@ -25,40 +25,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef QUERYOBJECTSSTORAGE_H_
#define QUERYOBJECTSSTORAGE_H_
#ifndef BOOST_FILE_SYSTEM_FIX_H
#define BOOST_FILE_SYSTEM_FIX_H
#include "../../Util/GraphLoader.h"
#include "../../Util/OSRMException.h"
#include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h"
#include "../../DataStructures/NodeInformationHelpDesk.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h"
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <vector>
#include <string>
//This is one big workaround for latest boost renaming woes.
#if BOOST_FILESYSTEM_VERSION < 3
#warning Boost Installation with Filesystem3 missing, activating workaround
#include <cstdio>
namespace boost {
namespace filesystem {
inline path temp_directory_path() {
char * buffer;
buffer = tmpnam (NULL);
struct QueryObjectsStorage {
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
return path(buffer);
}
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<char> m_names_char_list;
std::vector<unsigned> m_name_begin_indices;
QueryGraph * graph;
std::string timestamp;
unsigned check_sum;
inline path unique_path(const path&) {
return temp_directory_path();
}
void GetName( const unsigned name_id, std::string & result ) const;
}
}
QueryObjectsStorage( const ServerPaths & paths );
~QueryObjectsStorage();
};
#endif
#endif /* QUERYOBJECTSSTORAGE_H_ */
#ifndef BOOST_FILESYSTEM_VERSION
#define BOOST_FILESYSTEM_VERSION 3
#endif
#endif /* BOOST_FILE_SYSTEM_FIX_H */

View File

@ -42,7 +42,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/filesystem/fstream.hpp>
#include <boost/unordered_map.hpp>
#include <cassert>
#include <cmath>
#include <algorithm>
@ -158,7 +157,7 @@ NodeID readBinaryOSRMGraphFromStream(
if (1 == dir) { backward = false; }
if (2 == dir) { forward = false; }
assert(type >= 0);
BOOST_ASSERT(type >= 0);
// translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(source);
@ -308,12 +307,12 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
if(speedType == 13) {
weight = length;
}
assert(length > 0);
assert(weight > 0);
BOOST_ASSERT(length > 0);
BOOST_ASSERT(weight > 0);
if(dir <0 || dir > 2) {
SimpleLogger().Write(logWARNING) << "direction bogus: " << dir;
}
assert(0<=dir && dir<=2);
BOOST_ASSERT(0<=dir && dir<=2);
bool forward = true;
bool backward = true;
@ -373,11 +372,11 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
EdgeWeight weight;
in >> source >> target >> weight >> dir;
assert(weight > 0);
BOOST_ASSERT(weight > 0);
if(dir <0 || dir > 3) {
throw OSRMException( "[error] direction bogus");
}
assert(0<=dir && dir<=3);
BOOST_ASSERT(0<=dir && dir<=3);
bool forward = true;
bool backward = true;
@ -410,12 +409,11 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
template<typename NodeT, typename EdgeT>
unsigned readHSGRFromStream(
const std::string & hsgr_filename,
const boost::filesystem::path & hsgr_file,
std::vector<NodeT> & node_list,
std::vector<EdgeT> & edge_list,
unsigned * check_sum
) {
boost::filesystem::path hsgr_file(hsgr_filename);
if ( !boost::filesystem::exists( hsgr_file ) ) {
throw OSRMException("hsgr file does not exist");
}
@ -434,20 +432,17 @@ unsigned readHSGRFromStream(
}
unsigned number_of_nodes = 0;
hsgr_input_stream.read((char*) check_sum, sizeof(unsigned));
hsgr_input_stream.read((char*) & number_of_nodes, sizeof(unsigned));
unsigned number_of_edges = 0;
hsgr_input_stream.read( (char*) check_sum, sizeof(unsigned) );
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
node_list.resize(number_of_nodes + 1);
hsgr_input_stream.read(
(char*) &(node_list[0]),
number_of_nodes*sizeof(NodeT)
);
unsigned number_of_edges = 0;
hsgr_input_stream.read(
(char*) &number_of_edges,
sizeof(unsigned)
);
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
edge_list.resize(number_of_edges);
hsgr_input_stream.read(

View File

@ -71,6 +71,10 @@ public:
return parameters.Find(key);
}
std::string GetParameter(const std::string & key) const {
return parameters.Find(key);
}
bool Holds(const std::string & key) const {
return parameters.Holds(key);
}

View File

@ -52,7 +52,7 @@ namespace boost {
// Validator for boost::filesystem::path, that verifies that the file
// exists. The validate() function must be defined in the same namespace
// as the target type, (boost::filesystem::path in this case), otherwise
// it is not be called
// it is not called
inline void validate(
boost::any & v,
const std::vector<std::string> & values,
@ -65,20 +65,18 @@ namespace boost {
if(boost::filesystem::is_regular_file(input_string)) {
v = boost::any(boost::filesystem::path(input_string));
} else {
throw OSRMException(input_string);
throw OSRMException(input_string + " not found");
}
}
}
}
// support old capitalized option names by downcasing them with a regex replace
// read from file and store in a stringstream that can be passed to
// boost::program_options
// support old capitalized option names by down-casing them with a regex replace
inline void PrepareConfigFile(
const boost::filesystem::path& path,
std::string& output
) {
std::ifstream config_stream(path.string().c_str());
std::ifstream config_stream( path.string().c_str() );
std::string input_str(
(std::istreambuf_iterator<char>(config_stream)),
std::istreambuf_iterator<char>()
@ -96,7 +94,8 @@ inline bool GenerateServerProgramOptions(
ServerPaths & paths,
std::string & ip_address,
int & ip_port,
int & requested_num_threads
int & requested_num_threads,
bool & use_shared_memory
) {
// declare a group of options that will be allowed only on command line
@ -160,6 +159,11 @@ inline bool GenerateServerProgramOptions(
"threads,t",
boost::program_options::value<int>(&requested_num_threads)->default_value(8),
"Number of threads to use"
)
(
"sharedmemory,s",
boost::program_options::value<bool>(&use_shared_memory)->default_value(false),
"Load data from shared memory"
);
// hidden options, will be allowed both on command line and in config
@ -209,8 +213,11 @@ inline bool GenerateServerProgramOptions(
// parse config file
ServerPaths::const_iterator path_iterator = paths.find("config");
if( path_iterator != paths.end() &&
boost::filesystem::is_regular_file(path_iterator->second)) {
if(
path_iterator != paths.end() &&
boost::filesystem::is_regular_file(path_iterator->second) &&
!option_variables.count("base")
) {
SimpleLogger().Write() <<
"Reading options from: " << path_iterator->second.string();
std::string config_str;
@ -223,56 +230,66 @@ inline bool GenerateServerProgramOptions(
boost::program_options::notify(option_variables);
}
if(!option_variables.count("hsgrdata")) {
if(!option_variables.count("base")) {
throw OSRMException("hsgrdata (or base) must be specified");
if( !use_shared_memory && option_variables.count("base") ) {
std::string base_string = paths["base"].string();
path_iterator = paths.find("hsgrdata");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["hsgrdata"] = base_string + ".hsgr";
}
path_iterator = paths.find("nodesdata");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["nodesdata"] = base_string + ".nodes";
}
path_iterator = paths.find("edgesdata");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["edgesdata"] = base_string + ".edges";
}
path_iterator = paths.find("ramindex");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["ramindex"] = base_string + ".ramIndex";
}
path_iterator = paths.find("fileindex");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["fileindex"] = base_string + ".fileIndex";
}
path_iterator = paths.find("namesdata");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["namesdata"] = base_string + ".names";
}
path_iterator = paths.find("timestamp");
if(
path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second)
) {
paths["timestamp"] = (paths["base"].string() + ".timestamp");
}
paths["hsgrdata"] = std::string( paths["base"].string()) + ".hsgr";
}
if(!option_variables.count("nodesdata")) {
if(!option_variables.count("base")) {
throw OSRMException("nodesdata (or base) must be specified");
}
paths["nodesdata"] = std::string( paths["base"].c_str()) + ".nodes";
}
if(!option_variables.count("edgesdata")) {
if(!option_variables.count("base")) {
throw OSRMException("edgesdata (or base) must be specified");
}
paths["edgesdata"] = std::string( paths["base"].c_str()) + ".edges";
}
if(!option_variables.count("ramindex")) {
if(!option_variables.count("base")) {
throw OSRMException("ramindex (or base) must be specified");
}
paths["ramindex"] = std::string( paths["base"].c_str()) + ".ramIndex";
}
if(!option_variables.count("fileindex")) {
if(!option_variables.count("base")) {
throw OSRMException("fileindex (or base) must be specified");
}
paths["fileindex"] = std::string( paths["base"].c_str()) + ".fileIndex";
}
if(!option_variables.count("namesdata")) {
if(!option_variables.count("base")) {
throw OSRMException("namesdata (or base) must be specified");
}
paths["namesdata"] = std::string( paths["base"].c_str()) + ".names";
}
if(!option_variables.count("timestamp")) {
if(!option_variables.count("base")) {
throw OSRMException("timestamp (or base) must be specified");
}
paths["timestamp"] = std::string( paths["base"].c_str()) + ".timestamp";
}
if(1 > requested_num_threads) {
if( 1 > requested_num_threads ) {
throw OSRMException("Number of threads must be a positive number");
}
return true;

View File

@ -132,7 +132,10 @@ static inline void doubleToString(const double value, std::string & output){
boost::spirit::karma::generate(sink, boost::spirit::karma::double_, value);
}
static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string & output){
static inline void doubleToStringWithTwoDigitsBehindComma(
const double value,
std::string & output
){
// The largest 32-bit integer is 4294967295, that is 10 chars
// On the safe side, add 1 for sign, and 1 for trailing zero
char buffer[12] ;
@ -140,11 +143,19 @@ static inline void doubleToStringWithTwoDigitsBehindComma(const double value, st
output = buffer ;
}
inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) {
inline void replaceAll(
std::string & s,
const std::string & sub,
const std::string & other
) {
boost::replace_all(s, sub, other);
}
inline void stringSplit(const std::string &s, const char delim, std::vector<std::string>& result) {
inline void stringSplit(
const std::string &s,
const char delim,
std::vector<std::string>& result
) {
boost::split(result, s, boost::is_any_of(std::string(&delim)));
}
@ -166,7 +177,10 @@ inline std::string HTMLDeEntitize( std::string & result) {
return result;
}
inline bool StringStartsWith(const std::string & input, const std::string & prefix) {
inline bool StringStartsWith(
const std::string & input,
const std::string & prefix
) {
return boost::starts_with(input, prefix);
}

View File

@ -30,13 +30,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#cmakedefine01 HAS64BITS
#cmakedefine MD5PREPARE "${MD5PREPARE}"
#cmakedefine MD5RTREE "${MD5RTREE}"
#cmakedefine MD5NODEINFO "${MD5NODEINFO}"
#cmakedefine MD5GRAPH "${MD5GRAPH}"
#cmakedefine MD5OBJECTS "${MD5OBJECTS}"
UUID::UUID() : magic_number(1297240911) {
md5_prepare[32] = md5_tree[32] = md5_nodeinfo[32] = md5_graph[32] =
md5_objects[32] = '\0';
md5_prepare[32] =
md5_tree[32] =
md5_graph[32] =
md5_objects[32] = '\0';
boost::uuids::name_generator gen(named_uuid);
std::string temp_string(__DATE__);
@ -46,8 +47,6 @@ UUID::UUID() : magic_number(1297240911) {
temp_string += md5_prepare;
std::copy(MD5RTREE, MD5RTREE+32, md5_tree);
temp_string += md5_tree;
std::copy(MD5NODEINFO, MD5NODEINFO+32, md5_nodeinfo);
temp_string += md5_nodeinfo;
std::copy(MD5GRAPH, MD5GRAPH+32, md5_graph);
temp_string += md5_graph;
std::copy(MD5OBJECTS, MD5OBJECTS+32, md5_objects);
@ -90,13 +89,6 @@ bool UUID::TestRTree(const UUID & other) const {
return std::equal(md5_tree, md5_tree+32, other.md5_tree);
}
bool UUID::TestNodeInfo(const UUID & other) const {
if(!other.IsMagicNumberOK()) {
throw OSRMException("nodes file misses magic number. Check or reprocess the file");
}
return std::equal(md5_nodeinfo, md5_nodeinfo+32, other.md5_nodeinfo);
}
bool UUID::TestQueryObjects(const UUID & other) const {
if(!other.IsMagicNumberOK()) {
throw OSRMException("missing magic number. Check or reprocess the file");

View File

@ -58,7 +58,6 @@ private:
const unsigned magic_number;
char md5_prepare[33];
char md5_tree[33];
char md5_nodeinfo[33];
char md5_graph[33];
char md5_objects[33];

View File

@ -2,10 +2,9 @@ set(OLDFILE ${SOURCE_DIR}/Util/UUID.cpp)
if (EXISTS ${OLDFILE})
file(REMOVE_RECURSE ${OLDFILE})
endif()
file(MD5 ${SOURCE_DIR}/createHierarchy.cpp MD5PREPARE)
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
file(MD5 ${SOURCE_DIR}/DataStructures/StaticRTree.h MD5RTREE)
file(MD5 ${SOURCE_DIR}/DataStructures/NodeInformationHelpDesk.h MD5NODEINFO)
file(MD5 ${SOURCE_DIR}/Util/GraphLoader.h MD5GRAPH)
file(MD5 ${SOURCE_DIR}/Server/DataStructures/QueryObjectsStorage.cpp MD5OBJECTS)
file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS)
CONFIGURE_FILE( ${SOURCE_DIR}/Util/UUID.cpp.in ${SOURCE_DIR}/Util/UUID.cpp )

418
datastore.cpp Normal file
View File

@ -0,0 +1,418 @@
/*
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 "DataStructures/QueryEdge.h"
#include "DataStructures/SharedMemoryFactory.h"
#include "DataStructures/SharedMemoryVectorWrapper.h"
#include "DataStructures/StaticGraph.h"
#include "DataStructures/StaticRTree.h"
#include "Server/DataStructures/BaseDataFacade.h"
#include "Server/DataStructures/SharedDataType.h"
#include "Server/DataStructures/SharedBarriers.h"
#include "Util/BoostFileSystemFix.h"
#include "Util/ProgramOptions.h"
#include "Util/SimpleLogger.h"
#include "Util/UUID.h"
#include "typedefs.h"
#include <boost/integer.hpp>
#include <boost/filesystem/fstream.hpp>
#include <string>
#include <vector>
int main( const int argc, const char * argv[] ) {
SharedBarriers barrier;
try {
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> pending_lock(barrier.pending_update_mutex);
} catch(...) {
// hard unlock in case of any exception.
barrier.pending_update_mutex.unlock();
}
try {
LogPolicy::GetInstance().Unmute();
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
bool use_shared_memory = false;
std::string ip_address;
int ip_port, requested_num_threads;
ServerPaths server_paths;
if(
!GenerateServerProgramOptions(
argc,
argv,
server_paths,
ip_address,
ip_port,
requested_num_threads,
use_shared_memory
)
) {
return 0;
}
if( server_paths.find("hsgrdata") == server_paths.end() ) {
throw OSRMException("no hsgr file given in ini file");
}
if( server_paths.find("ramindex") == server_paths.end() ) {
throw OSRMException("no ram index file given in ini file");
}
if( server_paths.find("fileindex") == server_paths.end() ) {
throw OSRMException("no leaf index file given in ini file");
}
if( server_paths.find("nodesdata") == server_paths.end() ) {
throw OSRMException("no nodes file given in ini file");
}
if( server_paths.find("edgesdata") == server_paths.end() ) {
throw OSRMException("no edges file given in ini file");
}
if( server_paths.find("namesdata") == server_paths.end() ) {
throw OSRMException("no names file given in ini file");
}
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & hsgr_path = paths_iterator->second;
paths_iterator = server_paths.find("timestamp");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & timestamp_path = paths_iterator->second;
paths_iterator = server_paths.find("ramindex");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & ram_index_path = paths_iterator->second;
paths_iterator = server_paths.find("fileindex");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const std::string & file_index_file_name = paths_iterator->second.string();
paths_iterator = server_paths.find("nodesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & nodes_data_path = paths_iterator->second;
paths_iterator = server_paths.find("edgesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & edges_data_path = paths_iterator->second;
paths_iterator = server_paths.find("namesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty());
const boost::filesystem::path & names_data_path = paths_iterator->second;
// get the shared memory segment to use
bool use_first_segment = SharedMemory::RegionExists( LAYOUT_2 );
SharedDataType LAYOUT = ( use_first_segment ? LAYOUT_1 : LAYOUT_2 );
SharedDataType DATA = ( use_first_segment ? DATA_1 : DATA_2 );
// Allocate a memory layout in shared memory, deallocate previous
SharedMemory * layout_memory = SharedMemoryFactory::Get(
LAYOUT,
sizeof(SharedDataLayout)
);
SharedDataLayout * shared_layout_ptr = static_cast<SharedDataLayout *>(
layout_memory->Ptr()
);
shared_layout_ptr = new(layout_memory->Ptr()) SharedDataLayout();
std::copy(
file_index_file_name.begin(),
(file_index_file_name.length() <= 1024 ? file_index_file_name.end() : file_index_file_name.begin()+1023),
shared_layout_ptr->ram_index_file_name
);
// add zero termination
unsigned end_of_string_index = std::min(1023ul, 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
SimpleLogger().Write(logDEBUG) << "Collecting files sizes";
SimpleLogger().Write() << "load names from: " << names_data_path;
// number of entries in name index
boost::filesystem::ifstream name_stream(
names_data_path, std::ios::binary
);
unsigned name_index_size = 0;
name_stream.read((char *)&name_index_size, sizeof(unsigned));
shared_layout_ptr->name_index_list_size = name_index_size;
SimpleLogger().Write() << "size: " << name_index_size;
// SimpleLogger().Write() << "name index size: " << shared_layout_ptr->name_index_list_size;
BOOST_ASSERT_MSG(0 != shared_layout_ptr->name_index_list_size, "name file broken");
unsigned number_of_chars = 0;
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
shared_layout_ptr->name_char_list_size = number_of_chars;
// SimpleLogger().Write() << "name char size: " << shared_layout_ptr->name_char_list_size;
//Loading information for original edges
boost::filesystem::ifstream edges_input_stream(
edges_data_path,
std::ios::binary
);
unsigned number_of_original_edges = 0;
edges_input_stream.read((char*)&number_of_original_edges, sizeof(unsigned));
shared_layout_ptr->via_node_list_size = number_of_original_edges;
shared_layout_ptr->name_id_list_size = number_of_original_edges;
shared_layout_ptr->turn_instruction_list_size = number_of_original_edges;
boost::filesystem::ifstream hsgr_input_stream(
hsgr_path,
std::ios::binary
);
UUID uuid_loaded, uuid_orig;
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
SimpleLogger().Write(logWARNING) <<
".hsgr was prepared with different build. "
"Reprocess to get rid of this warning.";
} else {
SimpleLogger().Write(logDEBUG) << "UUID checked out ok";
}
// load checksum
unsigned checksum = 0;
hsgr_input_stream.read((char*)&checksum, sizeof(unsigned) );
shared_layout_ptr->checksum = checksum;
// load graph node size
unsigned number_of_graph_nodes = 0;
hsgr_input_stream.read(
(char*) &number_of_graph_nodes,
sizeof(unsigned)
);
BOOST_ASSERT_MSG(
(0 != number_of_graph_nodes),
"number of nodes is zero"
);
shared_layout_ptr->graph_node_list_size = number_of_graph_nodes;
// load graph edge size
unsigned number_of_graph_edges = 0;
hsgr_input_stream.read( (char*) &number_of_graph_edges, sizeof(unsigned) );
BOOST_ASSERT_MSG(
0 != number_of_graph_edges,
"number of graph edges is zero"
);
shared_layout_ptr->graph_edge_list_size = number_of_graph_edges;
// load rsearch tree size
boost::filesystem::ifstream tree_node_file(
ram_index_path,
std::ios::binary
);
uint32_t tree_size = 0;
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
shared_layout_ptr->r_search_tree_size = tree_size;
//load timestamp size
std::string m_timestamp;
if( boost::filesystem::exists(timestamp_path) ) {
boost::filesystem::ifstream timestampInStream( timestamp_path );
if(!timestampInStream) {
SimpleLogger().Write(logWARNING) <<
timestamp_path << " not found. setting to default";
} else {
getline(timestampInStream, m_timestamp);
timestampInStream.close();
}
}
if(m_timestamp.empty()) {
m_timestamp = "n/a";
}
if(25 < m_timestamp.length()) {
m_timestamp.resize(25);
}
shared_layout_ptr->timestamp_length = m_timestamp.length();
//load coordinate size
boost::filesystem::ifstream nodes_input_stream(
nodes_data_path,
std::ios::binary
);
unsigned coordinate_list_size = 0;
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
shared_layout_ptr->coordinate_list_size = coordinate_list_size;
// allocate shared memory block
SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
SharedMemory * shared_memory = SharedMemoryFactory::Get(
DATA,
shared_layout_ptr->GetSizeOfLayout()
);
char * shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
// read actual data into shared memory object //
// Loading street names
// SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
unsigned * name_index_ptr = (unsigned*)(
shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
);
// SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);
name_stream.read(
(char*)name_index_ptr,
shared_layout_ptr->name_index_list_size*sizeof(unsigned)
);
char * name_char_ptr = shared_memory_ptr + shared_layout_ptr->GetNameListOffset();
name_stream.read(
name_char_ptr,
shared_layout_ptr->name_char_list_size*sizeof(char)
);
name_stream.close();
//load original edge information
NodeID * via_node_ptr = (NodeID *)(
shared_memory_ptr + shared_layout_ptr->GetViaNodeListOffset()
);
unsigned * name_id_ptr = (unsigned *)(
shared_memory_ptr + shared_layout_ptr->GetNameIDListOffset()
);
TurnInstruction * turn_instructions_ptr = (TurnInstruction *)(
shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
);
OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_original_edges; ++i) {
// SimpleLogger().Write() << i << "/" << number_of_edges;
edges_input_stream.read(
(char*)&(current_edge_data),
sizeof(OriginalEdgeData)
);
via_node_ptr[i] = current_edge_data.viaNode;
name_id_ptr[i] = current_edge_data.nameID;
turn_instructions_ptr[i] = current_edge_data.turnInstruction;
}
edges_input_stream.close();
// Loading list of coordinates
FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
);
NodeInfo current_node;
for(unsigned i = 0; i < coordinate_list_size; ++i) {
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
}
nodes_input_stream.close();
//store timestamp
char * timestamp_ptr = static_cast<char *>(
shared_memory_ptr + shared_layout_ptr->GetTimeStampOffset()
);
std::copy(
m_timestamp.c_str(),
m_timestamp.c_str()+m_timestamp.length(),
timestamp_ptr
);
// store search tree portion of rtree
char * rtree_ptr = static_cast<char *>(
shared_memory_ptr + shared_layout_ptr->GetRSearchTreeOffset()
);
tree_node_file.read(rtree_ptr, sizeof(RTreeNode)*tree_size);
tree_node_file.close();
// load the nodes of the search graph
QueryGraph::_StrNode * graph_node_list_ptr = (QueryGraph::_StrNode*)(
shared_memory_ptr + shared_layout_ptr->GetGraphNodeListOffset()
);
hsgr_input_stream.read(
(char*) graph_node_list_ptr,
shared_layout_ptr->graph_node_list_size*sizeof(QueryGraph::_StrNode)
);
// load the edges of the search graph
QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett()
);
hsgr_input_stream.read(
(char*) graph_edge_list_ptr,
shared_layout_ptr->graph_edge_list_size*sizeof(QueryGraph::_StrEdge)
);
hsgr_input_stream.close();
//TODO acquire lock
SharedMemory * data_type_memory = SharedMemoryFactory::Get(
CURRENT_REGIONS,
sizeof(SharedDataTimestamp),
true,
false
);
SharedDataTimestamp * data_timestamp_ptr = static_cast<SharedDataTimestamp*>(
data_type_memory->Ptr()
);
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> query_lock(barrier.query_mutex);
// notify all processes that were waiting for this condition
if (0 < barrier.number_of_queries) {
barrier.no_running_queries_condition.wait(query_lock);
}
data_timestamp_ptr->layout = LAYOUT;
data_timestamp_ptr->data = DATA;
data_timestamp_ptr->timestamp +=1;
if(use_first_segment) {
BOOST_ASSERT( DATA == DATA_1 );
BOOST_ASSERT( LAYOUT == LAYOUT_1 );
if( !SharedMemory::Remove(DATA_2) ) {
SimpleLogger().Write(logWARNING) << "could not delete DATA_2";
}
if( !SharedMemory::Remove(LAYOUT_2) ) {
SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_2";
}
} else {
BOOST_ASSERT( DATA == DATA_2 );
BOOST_ASSERT( LAYOUT == LAYOUT_2 );
if( !SharedMemory::Remove(DATA_1) ) {
SimpleLogger().Write(logWARNING) << "could not delete DATA_1";
}
if( !SharedMemory::Remove(LAYOUT_1) ) {
SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_1";
}
}
SimpleLogger().Write() << "all data loaded";
} catch(const std::exception & e) {
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
}
return 0;
}

View File

@ -265,7 +265,7 @@ int main (int argc, char *argv[]) {
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
std::vector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
std::vector<EdgeBasedNode> nodeBasedEdgeList;
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
delete edgeBasedGraphFactory;
@ -275,7 +275,12 @@ int main (int argc, char *argv[]) {
SimpleLogger().Write() << "writing node map ...";
std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
const unsigned size_of_mapping = internalToExternalNodeMapping.size();
mapOutFile.write((char *)&size_of_mapping, sizeof(unsigned));
mapOutFile.write(
(char *)&(internalToExternalNodeMapping[0]),
size_of_mapping*sizeof(NodeInfo)
);
mapOutFile.close();
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
@ -286,14 +291,14 @@ int main (int argc, char *argv[]) {
*/
SimpleLogger().Write() << "building r-tree ...";
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * rtree =
new StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode>(
StaticRTree<EdgeBasedNode> * rtree =
new StaticRTree<EdgeBasedNode>(
nodeBasedEdgeList,
rtree_nodes_path.c_str(),
rtree_leafs_path.c_str()
);
delete rtree;
IteratorbasedCRC32<std::vector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
IteratorbasedCRC32<std::vector<EdgeBasedNode> > crc32;
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
nodeBasedEdgeList.clear();
SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList;
@ -346,20 +351,31 @@ int main (int argc, char *argv[]) {
StaticGraph<EdgeData>::EdgeIterator edge = 0;
StaticGraph<EdgeData>::EdgeIterator position = 0;
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
++edge;
_nodes[node].firstEdge = position; //=edge
position += edge - lastEdge; //remove
}
_nodes.back().firstEdge = numberOfEdges; //sentinel element
++numberOfNodes;
//Serialize numberOfNodes, nodes
BOOST_ASSERT_MSG(
_nodes.size() == numberOfNodes,
"no. of nodes dont match"
);
//serialize crc32, aka checksum
hsgr_output_stream.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
//serialize number f nodes
hsgr_output_stream.write((char*) &numberOfNodes, sizeof(unsigned));
hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
//Serialize number of Edges
//serialize number of edges
hsgr_output_stream.write((char*) &position, sizeof(unsigned));
//serialize all nodes
hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
//serialize all edges
--numberOfNodes;
edge = 0;
int usedEdgeCounter = 0;

View File

@ -3,7 +3,7 @@ require("lib/access")
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 }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true }
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
access_tags = { "motorcar", "motor_vehicle", "vehicle" }
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }

View File

@ -0,0 +1,82 @@
-- This example shows how to query external data stored in PostGIS when processing ways.
-- This profile assumes that OSM data has been imported to PostGIS using imposm to a db
-- with the name 'imposm', the default user and no password. It assumes areas with
-- landusage=* was imported to the table osm_landusages, containting the columns type and area.
-- Seee http://imposm.org/ for more info on imposm.
-- Other tools for importing OSM data to PostGIS include osm2pgsql and osmosis.
-- It uses the PostGIS function ST_DWithin() to find areas tagged with landuse=industrial
-- that are within 100 meters of the way.
-- It then slows down the routing depending on the number and size of the industrial area.
-- The end result is that routes will tend to avoid industrial area. Passing through
-- industrial areas is still possible, it's just slower, and thus avoided if a reasonable
-- alternative is found.
-- We use the osm id as the key when querying PostGIS. Be sure to add an index to the colunn
-- containing the osm id (osm_id in this case), otherwise you will suffer form very
-- bad performance. You should also have spatial indexes on the relevant gemoetry columns.
-- More info about using SQL form LUA can be found at http://www.keplerproject.org/luasql/
-- Happy routing!
-- Open PostGIS connection
lua_sql = require "luasql.postgres" -- we will connect to a postgresql database
sql_env = assert( lua_sql.postgres() )
sql_con = assert( sql_env:connect("imposm") ) -- you can add db user/password here if needed
print("PostGIS connection opened")
-- these settings are read directly by osrm
take_minimum_of_speeds = true
obey_oneway = true
obey_bollards = true
use_restrictions = true
ignore_areas = true -- future feature
traffic_signal_penalty = 7 -- seconds
u_turn_penalty = 20
-- nodes processing, called from OSRM
function node_function(node)
return 1
end
-- ways processing, called from OSRM
function way_function (way)
-- only route on ways with highway=*
local highway = way.tags:Find("highway")
if (not highway or highway=='') then
return 0
end
-- Query PostGIS for industrial areas close to the way, then group by way and sum the areas.
-- We take the square root of the area to get a estimate of the length of the side of the area,
-- and thus a rough guess of how far we might be travelling along the area.
local sql_query = " " ..
"SELECT SUM(SQRT(area.area)) AS val " ..
"FROM osm_ways way " ..
"LEFT JOIN osm_landusages area ON ST_DWithin(way.geometry, area.geometry, 100) " ..
"WHERE area.type IN ('industrial') AND way.osm_id=" .. way.id .. " " ..
"GROUP BY way.id"
local cursor = assert( sql_con:execute(sql_query) ) -- execute querty
local row = cursor:fetch( {}, "a" ) -- fetch first (and only) row
way.speed = 20.0 -- default speed
if row then
local val = tonumber(row.val) -- read 'val' from row
if val > 10 then
way.speed = way.speed / math.log10( val ) -- reduce speed by amount of industry close by
end
end
cursor:close() -- done with this query
-- set other required info for this way
way.name = way.tags:Find("name")
way.direction = Way.bidirectional
way.type = 1
return 1
end

View File

@ -72,12 +72,13 @@ int main (int argc, const char * argv[]) {
try {
LogPolicy::GetInstance().Unmute();
#ifdef __linux__
if(!mlockall(MCL_CURRENT | MCL_FUTURE)) {
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
SimpleLogger().Write(logWARNING) <<
"Process " << argv[0] << "could not be locked to RAM";
"Process " << argv[0] << " could not be locked to RAM";
}
installCrashHandler(argv[0]);
#endif
bool use_shared_memory = false;
std::string ip_address;
int ip_port, requested_num_threads;
@ -88,7 +89,8 @@ int main (int argc, const char * argv[]) {
server_paths,
ip_address,
ip_port,
requested_num_threads
requested_num_threads,
use_shared_memory
)
) {
return 0;
@ -98,27 +100,30 @@ int main (int argc, const char * argv[]) {
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
"compiled at " << __DATE__ << ", " __TIME__;
SimpleLogger().Write() <<
"HSGR file:\t" << server_paths["hsgrdata"];
SimpleLogger().Write() <<
"Nodes file:\t" << server_paths["nodesdata"];
SimpleLogger().Write() <<
"Edges file:\t" << server_paths["edgesdata"];
SimpleLogger().Write() <<
"RAM file:\t" << server_paths["ramindex"];
SimpleLogger().Write() <<
"Index file:\t" << server_paths["fileindex"];
SimpleLogger().Write() <<
"Names file:\t" << server_paths["namesdata"];
SimpleLogger().Write() <<
"Timestamp file:\t" << server_paths["timestamp"];
SimpleLogger().Write() <<
"Threads:\t" << requested_num_threads;
SimpleLogger().Write() <<
"IP address:\t" << ip_address;
SimpleLogger().Write() <<
"IP port:\t" << ip_port;
if( use_shared_memory ) {
SimpleLogger().Write(logDEBUG) << "Loading from shared memory";
} else {
SimpleLogger().Write() <<
"HSGR file:\t" << server_paths["hsgrdata"];
SimpleLogger().Write(logDEBUG) <<
"Nodes file:\t" << server_paths["nodesdata"];
SimpleLogger().Write(logDEBUG) <<
"Edges file:\t" << server_paths["edgesdata"];
SimpleLogger().Write(logDEBUG) <<
"RAM file:\t" << server_paths["ramindex"];
SimpleLogger().Write(logDEBUG) <<
"Index file:\t" << server_paths["fileindex"];
SimpleLogger().Write(logDEBUG) <<
"Names file:\t" << server_paths["namesdata"];
SimpleLogger().Write(logDEBUG) <<
"Timestamp file:\t" << server_paths["timestamp"];
SimpleLogger().Write(logDEBUG) <<
"Threads:\t" << requested_num_threads;
SimpleLogger().Write(logDEBUG) <<
"IP address:\t" << ip_address;
SimpleLogger().Write(logDEBUG) <<
"IP port:\t" << ip_port;
}
#ifndef _WIN32
int sig = 0;
sigset_t new_mask;
@ -127,12 +132,13 @@ int main (int argc, const char * argv[]) {
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
#endif
OSRM routing_machine(server_paths);
OSRM routing_machine(server_paths, use_shared_memory);
Server * s = ServerFactory::CreateServer(
ip_address,
ip_port,
requested_num_threads
);
s->GetRequestHandlerPtr().RegisterRoutingMachine(&routing_machine);
boost::thread t(boost::bind(&Server::Run, s));
@ -159,7 +165,8 @@ int main (int argc, const char * argv[]) {
std::cout << "[server] stopping threads" << std::endl;
if(!t.timed_join(boost::posix_time::seconds(2))) {
SimpleLogger().Write(logDEBUG) << "Threads did not finish within 2 seconds. Hard abort!";
SimpleLogger().Write(logDEBUG) <<
"Threads did not finish within 2 seconds. Hard abort!";
}
std::cout << "[server] freeing objects" << std::endl;