Merge branch 'TheMarex-ebgf-refactor' into develop

This commit is contained in:
Dennis Luxen 2014-05-09 11:29:48 +02:00
commit 5579388896
14 changed files with 1626 additions and 1224 deletions

View File

@ -41,7 +41,7 @@ file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources})
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
set(PrepareSources prepare.cpp ${PrepareGlob})
add_executable(osrm-prepare ${PrepareSources})

View File

@ -0,0 +1,145 @@
#ifndef __BFS_COMPONENT_EXPLORER_H__
#define __BFS_COMPONENT_EXPLORER_H__
#include <queue>
#include <boost/unordered_set.hpp>
#include "../typedefs.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/RestrictionMap.h"
/**
* Explores the components of the given graph while respecting turn restrictions
* and barriers.
*/
template <typename GraphT> class BFSComponentExplorer
{
public:
typedef typename GraphT::NodeIterator NodeIterator;
typedef typename GraphT::EdgeIterator EdgeIterator;
BFSComponentExplorer(const GraphT &dynamicGraph,
const RestrictionMap &restrictions,
const boost::unordered_set<NodeID> &barrier_nodes)
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
{
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
}
/*!
* Returns the size of the component that the node belongs to.
*/
inline unsigned int getComponentSize(NodeID node)
{
BOOST_ASSERT(node < m_component_index_list.size());
return m_component_index_size[m_component_index_list[node]];
}
inline unsigned int getNumberOfComponents() { return m_component_index_size.size(); }
/*!
* Computes the component sizes.
*/
void run()
{
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
unsigned current_component = 0;
BOOST_ASSERT(m_component_index_list.empty());
BOOST_ASSERT(m_component_index_size.empty());
unsigned num_nodes = m_graph.GetNumberOfNodes();
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
BOOST_ASSERT(num_nodes > 0);
// put unexplorered node with parent pointer into queue
for (NodeID node = 0; node < num_nodes; ++node)
{
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
{
unsigned size = exploreComponent(bfs_queue, node, current_component);
// push size into vector
m_component_index_size.push_back(size);
++current_component;
}
}
}
private:
/*!
* Explores the current component that starts at node using BFS.
*/
inline unsigned exploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
NodeID node,
unsigned current_component)
{
bfs_queue.push(std::make_pair(node, node));
// mark node as read
m_component_index_list[node] = current_component;
unsigned current_component_size = 1;
while (!bfs_queue.empty())
{
// fetch element from BFS queue
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
bfs_queue.pop();
const NodeID v = current_queue_item.first; // current node
const NodeID u = current_queue_item.second; // parent
// increment size counter of current component
++current_component_size;
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
if (!is_barrier_node)
{
const NodeID to_node_of_only_restriction =
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
for (EdgeIterator e2 = m_graph.BeginEdges(v); e2 < m_graph.EndEdges(v); ++e2)
{
NodeIterator w = m_graph.GetTarget(e2);
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
w != to_node_of_only_restriction)
{
// At an only_-restriction but not at the right turn
continue;
}
if (u != w)
{
// only add an edge if turn is not a U-turn except
// when it is at the end of a dead-end street.
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
{
// only add an edge if turn is not prohibited
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
{
// insert next (node, parent) only if w has
// not yet been explored
// mark node as read
m_component_index_list[w] = current_component;
bfs_queue.push(std::make_pair(w, v));
}
}
}
}
}
}
return current_component_size;
}
std::vector<unsigned> m_component_index_list;
std::vector<NodeID> m_component_index_size;
const GraphT &m_graph;
const RestrictionMap &m_restriction_map;
const boost::unordered_set<NodeID> &m_barrier_nodes;
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -35,20 +35,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/EdgeBasedNode.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/OriginalEdgeData.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/NodeBasedGraph.h"
#include "../DataStructures/RestrictionMap.h"
#include "../Util/LuaUtil.h"
#include "../Util/SimpleLogger.h"
#include "GeometryCompressor.h"
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
@ -57,155 +57,76 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <queue>
#include <vector>
class EdgeBasedGraphFactory : boost::noncopyable {
public:
class EdgeBasedGraphFactory : boost::noncopyable
{
public:
struct SpeedProfileProperties;
explicit EdgeBasedGraphFactory(
int number_of_nodes,
std::vector<ImportEdge> & input_edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties & speed_profile
);
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
std::unique_ptr<RestrictionMap> restricion_map,
std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list,
std::vector<NodeInfo> &m_node_info_list,
SpeedProfileProperties &speed_profile);
void Run(
const std::string & original_edge_data_filename,
const std::string & geometry_filename,
lua_State *myLuaState
);
void Run(const std::string &original_edge_data_filename,
const std::string &geometry_filename,
lua_State *myLuaState);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
TurnInstruction AnalyzeTurn(
const NodeID u,
const NodeID v,
const NodeID w
) const;
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
int GetTurnPenalty(
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *myLuaState
) const;
int GetTurnPenalty(const NodeID u, const NodeID v, const NodeID w, lua_State *myLuaState) const;
unsigned GetNumberOfEdgeBasedNodes() const;
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),
uTurnPenalty(0),
has_turn_penalty_function(false)
{ }
struct SpeedProfileProperties
{
SpeedProfileProperties()
: trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
{
}
int trafficSignalPenalty;
int uTurnPenalty;
bool has_turn_penalty_function;
} speed_profile;
private:
struct NodeBasedEdgeData {
NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), nameID(std::numeric_limits<unsigned>::max()),
type(std::numeric_limits<short>::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false),
roundabout(false), ignore_in_grid(false), contraFlow(false)
{ }
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
short type;
bool isAccessRestricted:1;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignore_in_grid:1;
bool contraFlow:1;
void SwapDirectionFlags() {
bool temp_flag = forward;
forward = backward;
backward = temp_flag;
}
bool IsEqualTo( const NodeBasedEdgeData & other ) const {
return (forward == other.forward) &&
(backward == other.backward) &&
(nameID == other.nameID) &&
(ignore_in_grid == other.ignore_in_grid) &&
(contraFlow == other.contraFlow);
}
};
unsigned m_turn_restrictions_count;
unsigned m_number_of_edge_based_nodes;
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
private:
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
std::vector<NodeInfo> m_node_info_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
unsigned m_number_of_edge_based_nodes;
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_nodes;
boost::unordered_set<NodeID> m_traffic_lights;
std::vector<NodeInfo> m_node_info_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
RestrictionMap m_restriction_map;
GeometryCompressor m_geometry_compressor;
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_nodes;
boost::unordered_set<NodeID> m_traffic_lights;
NodeID CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const;
std::unique_ptr<RestrictionMap> m_restriction_map;
bool CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const;
GeometryCompressor m_geometry_compressor;
void InsertEdgeBasedNode(
NodeBasedDynamicGraph::NodeIterator u,
NodeBasedDynamicGraph::NodeIterator v,
NodeBasedDynamicGraph::EdgeIterator e1,
bool belongsToTinyComponent
);
void CompressGeometry();
void RenumberEdges();
void GenerateEdgeExpandedNodes();
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
lua_State *lua_state);
void BFSCompentExplorer(
std::vector<unsigned> & component_index_list,
std::vector<unsigned> & component_index_size
) const;
void InsertEdgeBasedNode(NodeBasedDynamicGraph::NodeIterator u,
NodeBasedDynamicGraph::NodeIterator v,
NodeBasedDynamicGraph::EdgeIterator e1,
bool belongsToTinyComponent);
void FlushVectorToStream(
std::ofstream & edge_data_file,
std::vector<OriginalEdgeData> & original_edge_data_vector
) const;
void FixupArrivingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
);
void FixupStartingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
);
void FlushVectorToStream(std::ofstream &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
unsigned max_id;
};

View File

@ -70,18 +70,18 @@ unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
void GeometryCompressor::SerializeInternalVector(const std::string &path) const
{
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out);
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries);
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
// write indices array
unsigned prefix_sum_of_list_indices = 0;
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
for (auto &elem : m_compressed_geometries)
{
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
const std::vector<CompressedNode> &current_vector = m_compressed_geometries.at(i);
const std::vector<CompressedNode> &current_vector = elem;
const unsigned unpacked_size = current_vector.size();
BOOST_ASSERT(UINT_MAX != unpacked_size);
prefix_sum_of_list_indices += unpacked_size;
@ -94,9 +94,9 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
unsigned control_sum = 0;
// write compressed geometries
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
for (auto &elem : m_compressed_geometries)
{
const std::vector<CompressedNode> &current_vector = m_compressed_geometries[i];
const std::vector<CompressedNode> &current_vector = elem;
const unsigned unpacked_size = current_vector.size();
control_sum += unpacked_size;
BOOST_ASSERT(UINT_MAX != unpacked_size);
@ -122,8 +122,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1);
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2);
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
// append list of removed edge_id plus via node to surviving edge id:
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
@ -146,7 +146,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
m_free_list.pop_back();
}
const boost::unordered_map<EdgeID, unsigned>::const_iterator iter = m_edge_id_to_list_index_map.find(edge_id_1);
const boost::unordered_map<EdgeID, unsigned>::const_iterator iter =
m_edge_id_to_list_index_map.find(edge_id_1);
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
const unsigned edge_bucket_id1 = iter->second;
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));

View File

@ -56,7 +56,7 @@ class GeometryCompressor
private:
void IncreaseFreeList();
std::vector<std::vector<CompressedNode> > m_compressed_geometries;
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
std::vector<unsigned> m_free_list;
boost::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
};

View File

@ -27,136 +27,154 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() {
temp_directory = boost::filesystem::temp_directory_path();
}
TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
TemporaryStorage & TemporaryStorage::GetInstance(){
TemporaryStorage &TemporaryStorage::GetInstance()
{
static TemporaryStorage static_instance;
return static_instance;
}
TemporaryStorage::~TemporaryStorage() {
RemoveAll();
}
TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
void TemporaryStorage::RemoveAll() {
void TemporaryStorage::RemoveAll()
{
boost::mutex::scoped_lock lock(mutex);
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
{
DeallocateSlot(slot_id);
}
stream_data_list.clear();
}
int TemporaryStorage::AllocateSlot() {
int TemporaryStorage::AllocateSlot()
{
boost::mutex::scoped_lock lock(mutex);
try {
try
{
stream_data_list.push_back(StreamData());
} catch(boost::filesystem::filesystem_error & e) {
}
catch (boost::filesystem::filesystem_error &e)
{
Abort(e);
}
CheckIfTemporaryDeviceFull();
return stream_data_list.size() - 1;
}
void TemporaryStorage::DeallocateSlot(const int slot_id) {
try {
StreamData & data = stream_data_list[slot_id];
void TemporaryStorage::DeallocateSlot(const int slot_id)
{
try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.temp_path)) {
if (!boost::filesystem::exists(data.temp_path))
{
return;
}
if(data.temp_file->is_open()) {
if (data.temp_file->is_open())
{
data.temp_file->close();
}
boost::filesystem::remove(data.temp_path);
} catch(boost::filesystem::filesystem_error & e) {
}
catch (boost::filesystem::filesystem_error &e)
{
Abort(e);
}
}
void TemporaryStorage::WriteToSlot(
const int slot_id,
char * pointer,
const std::size_t size
) {
try {
StreamData & data = stream_data_list[slot_id];
void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
{
try
{
StreamData &data = stream_data_list[slot_id];
BOOST_ASSERT(data.write_mode);
boost::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG(
data.write_mode,
"Writing after first read is not allowed"
);
if( 1073741824 < data.buffer.size() ) {
BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
if (1073741824 < data.buffer.size())
{
data.temp_file->write(&data.buffer[0], data.buffer.size());
// data.temp_file->write(pointer, size);
data.buffer.clear();
CheckIfTemporaryDeviceFull();
}
data.buffer.insert(data.buffer.end(), pointer, pointer+size);
} catch(boost::filesystem::filesystem_error & e) {
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
}
catch (boost::filesystem::filesystem_error &e)
{
Abort(e);
}
}
void TemporaryStorage::ReadFromSlot(
const int slot_id,
char * pointer,
const std::size_t size
) {
try {
StreamData & data = stream_data_list[slot_id];
void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
{
try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if( data.write_mode ) {
if (data.write_mode)
{
data.write_mode = false;
data.temp_file->write(&data.buffer[0], data.buffer.size());
data.buffer.clear();
data.temp_file->seekg( data.temp_file->beg );
BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() );
data.temp_file->seekg(data.temp_file->beg);
BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg());
}
BOOST_ASSERT( !data.write_mode );
BOOST_ASSERT(!data.write_mode);
data.temp_file->read(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
}
catch (boost::filesystem::filesystem_error &e)
{
Abort(e);
}
}
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
{
uint64_t value = -1;
try {
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space( p );
try
{
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space(p);
value = s.free;
} catch(boost::filesystem::filesystem_error & e) {
}
catch (boost::filesystem::filesystem_error &e)
{
Abort(e);
}
return value;
}
void TemporaryStorage::CheckIfTemporaryDeviceFull() {
void TemporaryStorage::CheckIfTemporaryDeviceFull()
{
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space( p );
if( (1024*1024) > s.free ) {
boost::filesystem::space_info s = boost::filesystem::space(p);
if ((1024 * 1024) > s.free)
{
throw OSRMException("temporary device is full");
}
}
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) {
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
{
boost::filesystem::fstream::pos_type position;
try {
StreamData & data = stream_data_list[slot_id];
try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.temp_file->tellp();
} catch(boost::filesystem::filesystem_error & e) {
}
catch (boost::filesystem::filesystem_error &e)
{
Abort(e);
}
return position;
}
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &e)
{
RemoveAll();
throw OSRMException(e.what());
}

View File

@ -36,8 +36,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <cstdint>
@ -56,61 +54,52 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static boost::filesystem::path temp_directory;
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage {
public:
static TemporaryStorage & GetInstance();
class TemporaryStorage
{
public:
static TemporaryStorage &GetInstance();
virtual ~TemporaryStorage();
int AllocateSlot();
void DeallocateSlot(const int slot_id);
void WriteToSlot(const int slot_id, char * pointer, const std::size_t size);
void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size);
//returns the number of free bytes
void WriteToSlot(const int slot_id, char *pointer, const std::size_t size);
void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size);
// returns the number of free bytes
uint64_t GetFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type Tell(const int slot_id);
void RemoveAll();
private:
private:
TemporaryStorage();
TemporaryStorage(TemporaryStorage const &){};
TemporaryStorage(TemporaryStorage const &) {};
TemporaryStorage & operator=(TemporaryStorage const &) {
return *this;
}
TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
void Abort(const boost::filesystem::filesystem_error& e);
void Abort(const boost::filesystem::filesystem_error &e);
void CheckIfTemporaryDeviceFull();
struct StreamData {
struct StreamData
{
bool write_mode;
boost::filesystem::path temp_path;
boost::shared_ptr<boost::filesystem::fstream> temp_file;
boost::shared_ptr<boost::mutex> readWriteMutex;
std::shared_ptr<boost::filesystem::fstream> temp_file;
std::shared_ptr<boost::mutex> readWriteMutex;
std::vector<char> buffer;
StreamData() :
write_mode(true),
temp_path(
boost::filesystem::unique_path(
temp_directory.append(
TemporaryFilePattern.begin(),
TemporaryFilePattern.end()
)
)
),
temp_file(
new boost::filesystem::fstream(
temp_path,
std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary
)
),
readWriteMutex(boost::make_shared<boost::mutex>())
StreamData()
: write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory.append(
TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
temp_file(new boost::filesystem::fstream(
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(std::make_shared<boost::mutex>())
{
if( temp_file->fail() ) {
if (temp_file->fail())
{
throw OSRMException("temporary file could not be created");
}
}
};
//vector of file streams that is used to store temporary data
// vector of file streams that is used to store temporary data
boost::mutex mutex;
std::vector<StreamData> stream_data_list;
};

View File

@ -0,0 +1,110 @@
#ifndef __NODE_BASED_GRAPH_H__
#define __NODE_BASED_GRAPH_H__
#include "DynamicGraph.h"
#include "ImportEdge.h"
struct NodeBasedEdgeData
{
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
roundabout(false), ignore_in_grid(false), contraFlow(false)
{
}
int distance;
unsigned edgeBasedNodeID;
unsigned nameID;
short type;
bool isAccessRestricted : 1;
bool shortcut : 1;
bool forward : 1;
bool backward : 1;
bool roundabout : 1;
bool ignore_in_grid : 1;
bool contraFlow : 1;
void SwapDirectionFlags()
{
bool temp_flag = forward;
forward = backward;
backward = temp_flag;
}
bool IsEqualTo(const NodeBasedEdgeData &other) const
{
return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
(contraFlow == other.contraFlow);
}
};
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
// Factory method to create NodeBasedDynamicGraph from ImportEdges
inline std::shared_ptr<NodeBasedDynamicGraph>
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
{
typedef NodeBasedDynamicGraph::InputEdge DynInputEdge;
std::sort(input_edge_list.begin(), input_edge_list.end());
// TODO: remove duplicate edges
DeallocatingVector<DynInputEdge> edges_list;
DynInputEdge edge;
for (const ImportEdge &import_edge : input_edge_list)
{
if (!import_edge.isForward())
{
edge.source = import_edge.target();
edge.target = import_edge.source();
edge.data.backward = import_edge.isForward();
edge.data.forward = import_edge.isBackward();
}
else
{
edge.source = import_edge.source();
edge.target = import_edge.target();
edge.data.forward = import_edge.isForward();
edge.data.backward = import_edge.isBackward();
}
if (edge.source == edge.target)
{
continue;
}
edge.data.distance = (std::max)((int)import_edge.weight(), 1);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false;
edge.data.roundabout = import_edge.isRoundabout();
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
edge.data.nameID = import_edge.name();
edge.data.type = import_edge.type();
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
edge.data.contraFlow = import_edge.isContraFlow();
edges_list.push_back(edge);
if (!import_edge.IsSplit())
{
using std::swap; // enable ADL
swap(edge.source, edge.target);
edge.data.SwapDirectionFlags();
edges_list.push_back(edge);
}
}
std::sort(edges_list.begin(), edges_list.end());
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
// FIXME probably unneeded since this is the end of scope
DeallocatingVector<DynInputEdge>().swap(edges_list);
BOOST_ASSERT(0 == edges_list.size());
return graph;
}
#endif

View File

@ -0,0 +1,168 @@
#include "RestrictionMap.h"
#include "NodeBasedGraph.h"
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &input_restrictions_list)
: m_count(0), m_graph(graph)
{
// decompose restirction consisting of a start, via and end note into a start-edge
// and all end-nodes
for (auto &restriction : input_restrictions_list)
{
std::pair<NodeID, NodeID> restriction_source =
std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
}
else
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->second)
{
continue;
}
else if (restriction.flags.isOnly)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
}
}
++m_count;
m_restriction_bucket_list.at(index)
.push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
}
}
/**
* Replace end v with w in each turn restriction containing u as via node
*
* Note: We need access to node based graph.
*/
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
// find all possible start edges
// it is more efficent to get a (small) list of potential start edges
// than iterating over all buckets
std::vector<NodeID> predecessors;
for (EdgeID current_edge_id = m_graph->BeginEdges(u); current_edge_id < m_graph->EndEdges(u);
++current_edge_id)
{
const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
const NodeID target = m_graph->GetTarget(current_edge_id);
if (edge_data.backward && (v != target))
{
predecessors.push_back(target);
}
}
for (const NodeID x : predecessors)
{
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x, u);
auto restriction_iterator = m_restriction_map.find(restr_start);
if (restriction_iterator == m_restriction_map.end())
continue;
const unsigned index = restriction_iterator->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (RestrictionTarget &restriction_target : bucket)
{
if (v == restriction_target.first)
{
restriction_target.first = w;
}
}
}
}
/**
* Replaces the start edge (v, w) with (u, w), only start node changes.
*/
void RestrictionMap::FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
const std::pair<NodeID, NodeID> old_start = std::make_pair(v, w);
auto restriction_iterator = m_restriction_map.find(old_start);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
// remove old restriction start (v,w)
m_restriction_map.erase(restriction_iterator);
// insert new restriction start (u,w) (point to index)
const std::pair<NodeID, NodeID> new_start = std::make_pair(u, w);
m_restriction_map.insert(std::make_pair(new_start, index));
}
}
/*
* Check if the edge (u, v) is contained in any turn restriction.
* If so returns id of first target node.
*/
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionSource &restriction_target : bucket)
{
if (restriction_target.second)
{
return restriction_target.first;
}
}
}
return std::numeric_limits<unsigned>::max();
}
/**
* Checks if the turn described by start u, via v and targed w is covert by any turn restriction.
*/
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
{
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
const std::pair<NodeID, NodeID> restriction_source = std::make_pair(u, v);
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if ((w == restriction_target.first) && // target found
(!restriction_target.second) // and not an only_-restr.
)
{
return true;
}
}
}
return false;
}

View File

@ -0,0 +1,71 @@
/*
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 __RESTRICTION_MAP_H__
#define __RESTRICTION_MAP_H__
#include <memory>
#include "../typedefs.h"
#include "DynamicGraph.h"
#include "Restriction.h"
#include "NodeBasedGraph.h"
#include <boost/unordered_map.hpp>
/*!
* Makee it efficent to look up if an edge is the start + via node of a TurnRestriction.
* Is needed by EdgeBasedGraphFactory.
*/
class RestrictionMap
{
public:
RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &input_restrictions_list);
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
unsigned size() { return m_count; }
private:
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
unsigned m_count;
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
//! index -> list of (target, isOnly)
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
//! maps (start, via) -> bucket index
boost::unordered_map<RestrictionSource, unsigned> m_restriction_map;
};
#endif

58
Util/TimingUtil.h Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TIMINGUTIL_H_
#define TIMINGUTIL_H_
#ifdef _WIN32
#include <sys/timeb.h>
#include <sys/types.h>
#include <winsock.h>
void gettimeofday(struct timeval* t,void* timezone) {
struct _timeb timebuffer;
_ftime( &timebuffer );
t->tv_sec=timebuffer.time;
t->tv_usec=1000*timebuffer.millitm;
}
#else
#include <sys/time.h>
#endif
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
static inline double get_timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}
#define TIMER_START(_X) timeval _X##_start, _X##_stop; gettimeofday(&_X##_start, NULL)
#define TIMER_STOP(_X) gettimeofday(&_X##_stop, NULL);
#define TIMER_MSEC(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) * 1000.0 + (_X##_stop.tv_usec - _X##_start.tv_usec) / 1000.0)
#define TIMER_SEC(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) + (_X##_stop.tv_usec - _X##_start.tv_usec) / 1000.0 / 1000.0)
#define TIMER_MIN(_X) ((_X##_stop.tv_sec - _X##_start.tv_sec) / 60.0)
#endif /* TIMINGUTIL_H_ */

View File

@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DataStructures/QueryEdge.h"
#include "DataStructures/StaticGraph.h"
#include "DataStructures/StaticRTree.h"
#include "DataStructures/RestrictionMap.h"
#include "Util/GitDescription.h"
#include "Util/GraphLoader.h"
#include "Util/LuaUtil.h"
@ -48,7 +49,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <luabind/luabind.hpp>
#include <chrono>
#include <string>
#include <vector>
@ -274,12 +274,13 @@ int main(int argc, char *argv[])
*/
SimpleLogger().Write() << "Generating edge-expanded graph representation";
EdgeBasedGraphFactory *edge_based_graph_factor =
new EdgeBasedGraphFactory(number_of_node_based_nodes,
edge_list,
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph = NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
std::unique_ptr<RestrictionMap> restriction_map = std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
EdgeBasedGraphFactory * edge_based_graph_factor =
new EdgeBasedGraphFactory(node_based_graph,
std::move(restriction_map),
barrier_node_list,
traffic_light_list,
restriction_list,
internal_to_external_node_map,
speed_profile);
edge_list.clear();
@ -302,6 +303,9 @@ int main(int argc, char *argv[])
edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list);
delete edge_based_graph_factor;
// TODO actually use scoping: Split this up in subfunctions
node_based_graph.reset();
std::chrono::duration<double> end_of_expansion_time =
std::chrono::steady_clock::now() - startup_time;