Move files in src/ include/
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/osrm-component
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "../data_structures/percent.hpp"
|
||||
#include "../data_structures/query_edge.hpp"
|
||||
#include "../data_structures/static_graph.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/graph_loader.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using EdgeData = QueryEdge::EdgeData;
|
||||
using QueryGraph = StaticGraph<EdgeData>;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " <file.hsgr>";
|
||||
return 1;
|
||||
}
|
||||
|
||||
boost::filesystem::path hsgr_path(argv[1]);
|
||||
|
||||
std::vector<QueryGraph::NodeArrayEntry> node_list;
|
||||
std::vector<QueryGraph::EdgeArrayEntry> edge_list;
|
||||
SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
|
||||
|
||||
unsigned m_check_sum = 0;
|
||||
unsigned m_number_of_nodes =
|
||||
readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum);
|
||||
SimpleLogger().Write() << "expecting " << m_number_of_nodes
|
||||
<< " nodes, checksum: " << m_check_sum;
|
||||
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
|
||||
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size()
|
||||
<< " edges";
|
||||
auto m_query_graph = std::make_shared<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");
|
||||
|
||||
Percent progress(m_query_graph->GetNumberOfNodes());
|
||||
for (const auto node_u : osrm::irange(0u, m_query_graph->GetNumberOfNodes()))
|
||||
{
|
||||
for (const auto eid : m_query_graph->GetAdjacentEdgeRange(node_u))
|
||||
{
|
||||
const EdgeData &data = m_query_graph->GetEdgeData(eid);
|
||||
if (!data.shortcut)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const unsigned node_v = m_query_graph->GetTarget(eid);
|
||||
const EdgeID edge_id_1 = m_query_graph->FindEdgeInEitherDirection(node_u, data.id);
|
||||
if (SPECIAL_EDGEID == edge_id_1)
|
||||
{
|
||||
throw osrm::exception("cannot find first segment of edge (" +
|
||||
std::to_string(node_u) + "," + std::to_string(data.id) +
|
||||
"," + std::to_string(node_v) + "), eid: " +
|
||||
std::to_string(eid));
|
||||
}
|
||||
const EdgeID edge_id_2 = m_query_graph->FindEdgeInEitherDirection(data.id, node_v);
|
||||
if (SPECIAL_EDGEID == edge_id_2)
|
||||
{
|
||||
throw osrm::exception("cannot find second segment of edge (" +
|
||||
std::to_string(node_u) + "," + std::to_string(data.id) +
|
||||
"," + std::to_string(node_v) + "), eid: " +
|
||||
std::to_string(eid));
|
||||
}
|
||||
}
|
||||
progress.printStatus(node_u);
|
||||
}
|
||||
m_query_graph.reset();
|
||||
SimpleLogger().Write() << "Data file " << argv[0] << " appears to be OK";
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "../typedefs.h"
|
||||
#include "../algorithms/tarjan_scc.hpp"
|
||||
#include "../algorithms/coordinate_calculation.hpp"
|
||||
#include "../data_structures/dynamic_graph.hpp"
|
||||
#include "../data_structures/static_graph.hpp"
|
||||
#include "../util/fingerprint.hpp"
|
||||
#include "../util/graph_loader.hpp"
|
||||
#include "../util/make_unique.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
#include <gdal.h>
|
||||
#include <ogrsf_frmts.h>
|
||||
#else
|
||||
#include <gdal/gdal.h>
|
||||
#include <gdal/ogrsf_frmts.h>
|
||||
#endif
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct TarjanEdgeData
|
||||
{
|
||||
TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
|
||||
TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {}
|
||||
unsigned distance;
|
||||
unsigned name_id;
|
||||
};
|
||||
|
||||
using TarjanGraph = StaticGraph<TarjanEdgeData>;
|
||||
using TarjanEdge = TarjanGraph::InputEdge;
|
||||
|
||||
void DeleteFileIfExists(const std::string &file_name)
|
||||
{
|
||||
if (boost::filesystem::exists(file_name))
|
||||
{
|
||||
boost::filesystem::remove(file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t LoadGraph(const char *path,
|
||||
std::vector<QueryNode> &coordinate_list,
|
||||
std::vector<TarjanEdge> &graph_edge_list)
|
||||
{
|
||||
std::ifstream input_stream(path, std::ifstream::in | std::ifstream::binary);
|
||||
if (!input_stream.is_open())
|
||||
{
|
||||
throw osrm::exception("Cannot open osrm file");
|
||||
}
|
||||
|
||||
// load graph data
|
||||
std::vector<NodeBasedEdge> edge_list;
|
||||
std::vector<NodeID> traffic_light_node_list;
|
||||
std::vector<NodeID> barrier_node_list;
|
||||
|
||||
auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list,
|
||||
traffic_light_node_list, coordinate_list);
|
||||
|
||||
loadEdgesFromFile(input_stream, edge_list);
|
||||
|
||||
traffic_light_node_list.clear();
|
||||
traffic_light_node_list.shrink_to_fit();
|
||||
|
||||
// Building an node-based graph
|
||||
for (const auto &input_edge : edge_list)
|
||||
{
|
||||
if (input_edge.source == input_edge.target)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (input_edge.forward)
|
||||
{
|
||||
graph_edge_list.emplace_back(input_edge.source, input_edge.target,
|
||||
(std::max)(input_edge.weight, 1), input_edge.name_id);
|
||||
}
|
||||
if (input_edge.backward)
|
||||
{
|
||||
graph_edge_list.emplace_back(input_edge.target, input_edge.source,
|
||||
(std::max)(input_edge.weight, 1), input_edge.name_id);
|
||||
}
|
||||
}
|
||||
|
||||
return number_of_nodes;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::vector<QueryNode> coordinate_list;
|
||||
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try
|
||||
{
|
||||
// enable logging
|
||||
if (argc < 2)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm>";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<TarjanEdge> graph_edge_list;
|
||||
auto number_of_nodes = LoadGraph(argv[1], coordinate_list, graph_edge_list);
|
||||
|
||||
tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end());
|
||||
const auto graph = std::make_shared<TarjanGraph>(number_of_nodes, graph_edge_list);
|
||||
graph_edge_list.clear();
|
||||
graph_edge_list.shrink_to_fit();
|
||||
|
||||
SimpleLogger().Write() << "Starting SCC graph traversal";
|
||||
|
||||
auto tarjan = osrm::make_unique<TarjanSCC<TarjanGraph>>(graph);
|
||||
tarjan->run();
|
||||
SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components()
|
||||
<< " many components";
|
||||
SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() << " size 1 SCCs";
|
||||
|
||||
// output
|
||||
TIMER_START(SCC_RUN_SETUP);
|
||||
|
||||
// remove files from previous run if exist
|
||||
DeleteFileIfExists("component.dbf");
|
||||
DeleteFileIfExists("component.shx");
|
||||
DeleteFileIfExists("component.shp");
|
||||
|
||||
Percent percentage(graph->GetNumberOfNodes());
|
||||
|
||||
OGRRegisterAll();
|
||||
|
||||
const char *pszDriverName = "ESRI Shapefile";
|
||||
OGRSFDriver *poDriver =
|
||||
OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
|
||||
if (nullptr == poDriver)
|
||||
{
|
||||
throw osrm::exception("ESRI Shapefile driver not available");
|
||||
}
|
||||
OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
|
||||
|
||||
if (nullptr == poDS)
|
||||
{
|
||||
throw osrm::exception("Creation of output file failed");
|
||||
}
|
||||
|
||||
OGRSpatialReference *poSRS = new OGRSpatialReference();
|
||||
poSRS->importFromEPSG(4326);
|
||||
|
||||
OGRLayer *poLayer = poDS->CreateLayer("component", poSRS, wkbLineString, nullptr);
|
||||
|
||||
if (nullptr == poLayer)
|
||||
{
|
||||
throw osrm::exception("Layer creation failed.");
|
||||
}
|
||||
TIMER_STOP(SCC_RUN_SETUP);
|
||||
SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP) / 1000.
|
||||
<< "s";
|
||||
|
||||
uint64_t total_network_length = 0;
|
||||
percentage.reinit(graph->GetNumberOfNodes());
|
||||
TIMER_START(SCC_OUTPUT);
|
||||
for (const NodeID source : osrm::irange(0u, graph->GetNumberOfNodes()))
|
||||
{
|
||||
percentage.printIncrement();
|
||||
for (const auto current_edge : graph->GetAdjacentEdgeRange(source))
|
||||
{
|
||||
const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge);
|
||||
|
||||
if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source))
|
||||
{
|
||||
total_network_length +=
|
||||
100 * coordinate_calculation::great_circle_distance(
|
||||
coordinate_list[source].lat, coordinate_list[source].lon,
|
||||
coordinate_list[target].lat, coordinate_list[target].lon);
|
||||
|
||||
BOOST_ASSERT(current_edge != SPECIAL_EDGEID);
|
||||
BOOST_ASSERT(source != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(target != SPECIAL_NODEID);
|
||||
|
||||
const unsigned size_of_containing_component =
|
||||
std::min(tarjan->get_component_size(tarjan->get_component_id(source)),
|
||||
tarjan->get_component_size(tarjan->get_component_id(target)));
|
||||
|
||||
// edges that end on bollard nodes may actually be in two distinct components
|
||||
if (size_of_containing_component < 1000)
|
||||
{
|
||||
OGRLineString lineString;
|
||||
lineString.addPoint(coordinate_list[source].lon / COORDINATE_PRECISION,
|
||||
coordinate_list[source].lat / COORDINATE_PRECISION);
|
||||
lineString.addPoint(coordinate_list[target].lon / COORDINATE_PRECISION,
|
||||
coordinate_list[target].lat / COORDINATE_PRECISION);
|
||||
|
||||
OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
|
||||
|
||||
poFeature->SetGeometry(&lineString);
|
||||
if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
|
||||
{
|
||||
throw osrm::exception("Failed to create feature in shapefile.");
|
||||
}
|
||||
OGRFeature::DestroyFeature(poFeature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OGRSpatialReference::DestroySpatialReference(poSRS);
|
||||
OGRDataSource::DestroyDataSource(poDS);
|
||||
TIMER_STOP(SCC_OUTPUT);
|
||||
SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT) / 1000.
|
||||
<< "s";
|
||||
|
||||
SimpleLogger().Write() << "total network distance: "
|
||||
<< static_cast<uint64_t>(total_network_length / 100 / 1000.)
|
||||
<< " km";
|
||||
|
||||
SimpleLogger().Write() << "finished component analysis";
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 "contractor/processing_chain.hpp"
|
||||
#include "contractor/contractor_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
#include <boost/program_options/errors.hpp>
|
||||
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <ostream>
|
||||
#include <new>
|
||||
|
||||
int main(int argc, char *argv[]) try
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
ContractorConfig contractor_config;
|
||||
|
||||
const return_code result = ContractorOptions::ParseArguments(argc, argv, contractor_config);
|
||||
|
||||
if (return_code::fail == result)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (return_code::exit == result)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
ContractorOptions::GenerateOutputFilesNames(contractor_config);
|
||||
|
||||
if (1 > contractor_config.requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
|
||||
|
||||
if (recommended_num_threads != contractor_config.requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
|
||||
<< recommended_num_threads
|
||||
<< "! This setting may have performance side-effects.";
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(contractor_config.osrm_input_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Input file " << contractor_config.osrm_input_path.string() << " not found!";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(contractor_config.profile_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << contractor_config.profile_path.string()
|
||||
<< " not found!";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Input file: "
|
||||
<< contractor_config.osrm_input_path.filename().string();
|
||||
SimpleLogger().Write() << "Profile: " << contractor_config.profile_path.filename().string();
|
||||
SimpleLogger().Write() << "Threads: " << contractor_config.requested_num_threads;
|
||||
|
||||
tbb::task_scheduler_init init(contractor_config.requested_num_threads);
|
||||
|
||||
return Prepare(contractor_config).Run();
|
||||
}
|
||||
catch (const std::bad_alloc &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Please provide more memory or consider using a larger swapfile";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "data_structures/original_edge_data.hpp"
|
||||
#include "data_structures/range_table.hpp"
|
||||
#include "data_structures/query_edge.hpp"
|
||||
#include "data_structures/query_node.hpp"
|
||||
#include "data_structures/shared_memory_factory.hpp"
|
||||
#include "data_structures/shared_memory_vector_wrapper.hpp"
|
||||
#include "data_structures/static_graph.hpp"
|
||||
#include "data_structures/static_rtree.hpp"
|
||||
#include "data_structures/travel_mode.hpp"
|
||||
#include "data_structures/turn_instructions.hpp"
|
||||
#include "server/data_structures/datafacade_base.hpp"
|
||||
#include "server/data_structures/shared_datatype.hpp"
|
||||
#include "server/data_structures/shared_barriers.hpp"
|
||||
#include "util/datastore_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/osrm_exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
using RTreeLeaf = BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf;
|
||||
using RTreeNode = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode;
|
||||
using QueryGraph = StaticGraph<QueryEdge::EdgeData>;
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/iostreams/seek.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <new>
|
||||
|
||||
// delete a shared memory region. report warning if it could not be deleted
|
||||
void delete_region(const SharedDataType region)
|
||||
{
|
||||
if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
|
||||
{
|
||||
const std::string name = [&]
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case CURRENT_REGIONS:
|
||||
return "CURRENT_REGIONS";
|
||||
case LAYOUT_1:
|
||||
return "LAYOUT_1";
|
||||
case DATA_1:
|
||||
return "DATA_1";
|
||||
case LAYOUT_2:
|
||||
return "LAYOUT_2";
|
||||
case DATA_2:
|
||||
return "DATA_2";
|
||||
case LAYOUT_NONE:
|
||||
return "LAYOUT_NONE";
|
||||
default: // DATA_NONE:
|
||||
return "DATA_NONE";
|
||||
}
|
||||
}();
|
||||
|
||||
SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name;
|
||||
}
|
||||
}
|
||||
|
||||
int main(const int argc, const char *argv[]) try
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
SharedBarriers barrier;
|
||||
|
||||
#ifdef __linux__
|
||||
// try to disable swapping on Linux
|
||||
const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
|
||||
if (-1 == mlockall(lock_flags))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Process " << argv[0] << " could not request RAM lock";
|
||||
}
|
||||
#endif
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
|
||||
|
||||
std::unordered_map<std::string, boost::filesystem::path> server_paths;
|
||||
if (!GenerateDataStoreOptions(argc, argv, server_paths))
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (server_paths.find("hsgrdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no hsgr file found");
|
||||
}
|
||||
if (server_paths.find("ramindex") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no ram index file found");
|
||||
}
|
||||
if (server_paths.find("fileindex") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no leaf index file found");
|
||||
}
|
||||
if (server_paths.find("nodesdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no nodes file found");
|
||||
}
|
||||
if (server_paths.find("edgesdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no edges file found");
|
||||
}
|
||||
if (server_paths.find("namesdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no names file found");
|
||||
}
|
||||
if (server_paths.find("geometry") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no geometry file found");
|
||||
}
|
||||
if (server_paths.find("core") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no core file found");
|
||||
}
|
||||
|
||||
auto 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 ×tamp_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 boost::filesystem::path index_file_path_absolute =
|
||||
boost::filesystem::canonical(paths_iterator->second);
|
||||
const std::string &file_index_path = index_file_path_absolute.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;
|
||||
paths_iterator = server_paths.find("geometry");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &geometries_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("core");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &core_marker_path = paths_iterator->second;
|
||||
|
||||
// determine segment to use
|
||||
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
|
||||
const SharedDataType layout_region = [&]
|
||||
{
|
||||
return segment2_in_use ? LAYOUT_1 : LAYOUT_2;
|
||||
}();
|
||||
const SharedDataType data_region = [&]
|
||||
{
|
||||
return segment2_in_use ? DATA_1 : DATA_2;
|
||||
}();
|
||||
const SharedDataType previous_layout_region = [&]
|
||||
{
|
||||
return segment2_in_use ? LAYOUT_2 : LAYOUT_1;
|
||||
}();
|
||||
const SharedDataType previous_data_region = [&]
|
||||
{
|
||||
return segment2_in_use ? DATA_2 : DATA_1;
|
||||
}();
|
||||
|
||||
// Allocate a memory layout in shared memory, deallocate previous
|
||||
auto *layout_memory = SharedMemoryFactory::Get(layout_region, sizeof(SharedDataLayout));
|
||||
auto *shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout();
|
||||
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::FILE_INDEX_PATH,
|
||||
file_index_path.length() + 1);
|
||||
|
||||
// collect number of elements to store in shared memory object
|
||||
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_blocks = 0;
|
||||
name_stream.read((char *)&name_blocks, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
|
||||
shared_layout_ptr->SetBlockSize<typename RangeTable<16, true>::BlockT>(
|
||||
SharedDataLayout::NAME_BLOCKS, name_blocks);
|
||||
SimpleLogger().Write() << "name offsets size: " << name_blocks;
|
||||
BOOST_ASSERT_MSG(0 != name_blocks, "name file broken");
|
||||
|
||||
unsigned number_of_chars = 0;
|
||||
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
|
||||
|
||||
// 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));
|
||||
|
||||
// note: settings this all to the same size is correct, we extract them from the same struct
|
||||
shared_layout_ptr->SetBlockSize<NodeID>(SharedDataLayout::VIA_NODE_LIST,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_ID_LIST,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<TravelMode>(SharedDataLayout::TRAVEL_MODE,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<TurnInstruction>(SharedDataLayout::TURN_INSTRUCTION,
|
||||
number_of_original_edges);
|
||||
// note: there are 32 geometry indicators in one unsigned block
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDICATORS,
|
||||
number_of_original_edges);
|
||||
|
||||
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
|
||||
|
||||
FingerPrint fingerprint_valid = FingerPrint::GetValid();
|
||||
FingerPrint fingerprint_loaded;
|
||||
hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||
if (fingerprint_loaded.TestGraphUtil(fingerprint_valid))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Fingerprint checked out ok";
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
// load checksum
|
||||
unsigned checksum = 0;
|
||||
hsgr_input_stream.read((char *)&checksum, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::HSGR_CHECKSUM, 1);
|
||||
// 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->SetBlockSize<QueryGraph::NodeArrayEntry>(SharedDataLayout::GRAPH_NODE_LIST,
|
||||
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->SetBlockSize<QueryGraph::EdgeArrayEntry>(SharedDataLayout::GRAPH_EDGE_LIST,
|
||||
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->SetBlockSize<RTreeNode>(SharedDataLayout::R_SEARCH_TREE, tree_size);
|
||||
|
||||
// load timestamp size
|
||||
std::string m_timestamp;
|
||||
if (boost::filesystem::exists(timestamp_path))
|
||||
{
|
||||
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
||||
if (!timestamp_stream)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << timestamp_path << " not found. setting to default";
|
||||
}
|
||||
else
|
||||
{
|
||||
getline(timestamp_stream, m_timestamp);
|
||||
timestamp_stream.close();
|
||||
}
|
||||
}
|
||||
if (m_timestamp.empty())
|
||||
{
|
||||
m_timestamp = "n/a";
|
||||
}
|
||||
if (25 < m_timestamp.length())
|
||||
{
|
||||
m_timestamp.resize(25);
|
||||
}
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
|
||||
|
||||
// load core marker size
|
||||
boost::filesystem::ifstream core_marker_file(core_marker_path, std::ios::binary);
|
||||
|
||||
uint32_t number_of_core_markers = 0;
|
||||
core_marker_file.read((char *)&number_of_core_markers, sizeof(uint32_t));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::CORE_MARKER,
|
||||
number_of_core_markers);
|
||||
|
||||
// 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->SetBlockSize<FixedPointCoordinate>(SharedDataLayout::COORDINATE_LIST,
|
||||
coordinate_list_size);
|
||||
|
||||
// load geometries sizes
|
||||
std::ifstream geometry_input_stream(geometries_data_path.string().c_str(), std::ios::binary);
|
||||
unsigned number_of_geometries_indices = 0;
|
||||
unsigned number_of_compressed_geometries = 0;
|
||||
|
||||
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDEX,
|
||||
number_of_geometries_indices);
|
||||
boost::iostreams::seek(geometry_input_stream, number_of_geometries_indices * sizeof(unsigned),
|
||||
BOOST_IOS::cur);
|
||||
geometry_input_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_LIST,
|
||||
number_of_compressed_geometries);
|
||||
// allocate shared memory block
|
||||
SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout()
|
||||
<< " bytes";
|
||||
SharedMemory *shared_memory =
|
||||
SharedMemoryFactory::Get(data_region, shared_layout_ptr->GetSizeOfLayout());
|
||||
char *shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
|
||||
|
||||
// read actual data into shared memory object //
|
||||
|
||||
// hsgr checksum
|
||||
unsigned *checksum_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::HSGR_CHECKSUM);
|
||||
*checksum_ptr = checksum;
|
||||
|
||||
// ram index file name
|
||||
char *file_index_path_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::FILE_INDEX_PATH);
|
||||
// make sure we have 0 ending
|
||||
std::fill(file_index_path_ptr,
|
||||
file_index_path_ptr +
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
|
||||
0);
|
||||
std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
|
||||
|
||||
// Loading street names
|
||||
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_OFFSETS);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS) > 0)
|
||||
{
|
||||
name_stream.read((char *)name_offsets_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS));
|
||||
}
|
||||
|
||||
unsigned *name_blocks_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_BLOCKS);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS) > 0)
|
||||
{
|
||||
name_stream.read((char *)name_blocks_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS));
|
||||
}
|
||||
|
||||
char *name_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_CHAR_LIST);
|
||||
unsigned temp_length;
|
||||
name_stream.read((char *)&temp_length, sizeof(unsigned));
|
||||
|
||||
BOOST_ASSERT_MSG(temp_length ==
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST),
|
||||
"Name file corrupted!");
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST) > 0)
|
||||
{
|
||||
name_stream.read(name_char_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
|
||||
}
|
||||
|
||||
name_stream.close();
|
||||
|
||||
// load original edge information
|
||||
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
|
||||
shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
|
||||
|
||||
unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_ID_LIST);
|
||||
|
||||
TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr<TravelMode, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
|
||||
|
||||
TurnInstruction *turn_instructions_ptr = shared_layout_ptr->GetBlockPtr<TurnInstruction, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
|
||||
|
||||
unsigned *geometries_indicator_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDICATORS);
|
||||
|
||||
OriginalEdgeData current_edge_data;
|
||||
for (unsigned i = 0; i < number_of_original_edges; ++i)
|
||||
{
|
||||
edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
|
||||
via_node_ptr[i] = current_edge_data.via_node;
|
||||
name_id_ptr[i] = current_edge_data.name_id;
|
||||
travel_mode_ptr[i] = current_edge_data.travel_mode;
|
||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||
|
||||
const unsigned bucket = i / 32;
|
||||
const unsigned offset = i % 32;
|
||||
const unsigned value = [&]
|
||||
{
|
||||
unsigned return_value = 0;
|
||||
if (0 != offset)
|
||||
{
|
||||
return_value = geometries_indicator_ptr[bucket];
|
||||
}
|
||||
return return_value;
|
||||
}();
|
||||
if (current_edge_data.compressed_geometry)
|
||||
{
|
||||
geometries_indicator_ptr[bucket] = (value | (1 << offset));
|
||||
}
|
||||
}
|
||||
edges_input_stream.close();
|
||||
|
||||
// load compressed geometry
|
||||
unsigned temporary_value;
|
||||
unsigned *geometries_index_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDEX);
|
||||
geometry_input_stream.seekg(0, geometry_input_stream.beg);
|
||||
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||
BOOST_ASSERT(temporary_value ==
|
||||
shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_INDEX]);
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX) > 0)
|
||||
{
|
||||
geometry_input_stream.read(
|
||||
(char *)geometries_index_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX));
|
||||
}
|
||||
unsigned *geometries_list_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GEOMETRIES_LIST);
|
||||
|
||||
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||
BOOST_ASSERT(temporary_value ==
|
||||
shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_LIST]);
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST) > 0)
|
||||
{
|
||||
geometry_input_stream.read(
|
||||
(char *)geometries_list_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST));
|
||||
}
|
||||
|
||||
// Loading list of coordinates
|
||||
FixedPointCoordinate *coordinates_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<FixedPointCoordinate, true>(
|
||||
shared_memory_ptr, SharedDataLayout::COORDINATE_LIST);
|
||||
|
||||
QueryNode current_node;
|
||||
for (unsigned i = 0; i < coordinate_list_size; ++i)
|
||||
{
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||
coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||
}
|
||||
nodes_input_stream.close();
|
||||
|
||||
// store timestamp
|
||||
char *timestamp_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<char, true>(shared_memory_ptr, SharedDataLayout::TIMESTAMP);
|
||||
std::copy(m_timestamp.c_str(), m_timestamp.c_str() + m_timestamp.length(), timestamp_ptr);
|
||||
|
||||
// store search tree portion of rtree
|
||||
char *rtree_ptr = shared_layout_ptr->GetBlockPtr<char, true>(shared_memory_ptr,
|
||||
SharedDataLayout::R_SEARCH_TREE);
|
||||
|
||||
if (tree_size > 0)
|
||||
{
|
||||
tree_node_file.read(rtree_ptr, sizeof(RTreeNode) * tree_size);
|
||||
}
|
||||
tree_node_file.close();
|
||||
|
||||
// load core markers
|
||||
std::vector<char> unpacked_core_markers(number_of_core_markers);
|
||||
core_marker_file.read((char *)unpacked_core_markers.data(),
|
||||
sizeof(char) * number_of_core_markers);
|
||||
|
||||
unsigned *core_marker_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::CORE_MARKER);
|
||||
|
||||
for (auto i = 0u; i < number_of_core_markers; ++i)
|
||||
{
|
||||
BOOST_ASSERT(unpacked_core_markers[i] == 0 || unpacked_core_markers[i] == 1);
|
||||
|
||||
if (unpacked_core_markers[i] == 1)
|
||||
{
|
||||
const unsigned bucket = i / 32;
|
||||
const unsigned offset = i % 32;
|
||||
const unsigned value = [&]
|
||||
{
|
||||
unsigned return_value = 0;
|
||||
if (0 != offset)
|
||||
{
|
||||
return_value = core_marker_ptr[bucket];
|
||||
}
|
||||
return return_value;
|
||||
}();
|
||||
|
||||
core_marker_ptr[bucket] = (value | (1 << offset));
|
||||
}
|
||||
}
|
||||
|
||||
// load the nodes of the search graph
|
||||
QueryGraph::NodeArrayEntry *graph_node_list_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<QueryGraph::NodeArrayEntry, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GRAPH_NODE_LIST);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST) > 0)
|
||||
{
|
||||
hsgr_input_stream.read((char *)graph_node_list_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST));
|
||||
}
|
||||
|
||||
// load the edges of the search graph
|
||||
QueryGraph::EdgeArrayEntry *graph_edge_list_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<QueryGraph::EdgeArrayEntry, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GRAPH_EDGE_LIST);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST) > 0)
|
||||
{
|
||||
hsgr_input_stream.read((char *)graph_edge_list_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST));
|
||||
}
|
||||
hsgr_input_stream.close();
|
||||
|
||||
// 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_region;
|
||||
data_timestamp_ptr->data = data_region;
|
||||
data_timestamp_ptr->timestamp += 1;
|
||||
delete_region(previous_data_region);
|
||||
delete_region(previous_layout_region);
|
||||
SimpleLogger().Write() << "all data loaded";
|
||||
|
||||
shared_layout_ptr->PrintInformation();
|
||||
}
|
||||
catch (const std::bad_alloc &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
SimpleLogger().Write(logWARNING) << "Please provide more memory or disable locking the virtual "
|
||||
"address space (note: this makes OSRM swap, i.e. slow)";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "extractor/extractor.hpp"
|
||||
#include "extractor/extractor_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <new>
|
||||
|
||||
int main(int argc, char *argv[]) try
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
ExtractorConfig extractor_config;
|
||||
|
||||
const return_code result = ExtractorOptions::ParseArguments(argc, argv, extractor_config);
|
||||
|
||||
if (return_code::fail == result)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (return_code::exit == result)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
ExtractorOptions::GenerateOutputFilesNames(extractor_config);
|
||||
|
||||
if (1 > extractor_config.requested_num_threads)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.input_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Input file " << extractor_config.input_path.string()
|
||||
<< " not found!";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!boost::filesystem::is_regular_file(extractor_config.profile_path))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Profile " << extractor_config.profile_path.string()
|
||||
<< " not found!";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return extractor(extractor_config).run();
|
||||
}
|
||||
catch (const std::bad_alloc &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Please provide more memory or consider using a larger swapfile";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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/version.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <fcntl.h>
|
||||
#ifdef __linux__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
const unsigned number_of_elements = 268435456;
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
double min, max, med, mean, dev;
|
||||
};
|
||||
|
||||
void RunStatistics(std::vector<double> &timings_vector, Statistics &stats)
|
||||
{
|
||||
std::sort(timings_vector.begin(), timings_vector.end());
|
||||
stats.min = timings_vector.front();
|
||||
stats.max = timings_vector.back();
|
||||
stats.med = timings_vector[timings_vector.size() / 2];
|
||||
double primary_sum = std::accumulate(timings_vector.begin(), timings_vector.end(), 0.0);
|
||||
stats.mean = primary_sum / timings_vector.size();
|
||||
|
||||
double primary_sq_sum = std::inner_product(timings_vector.begin(), timings_vector.end(),
|
||||
timings_vector.begin(), 0.0);
|
||||
stats.dev = std::sqrt(primary_sq_sum / timings_vector.size() - (stats.mean * stats.mean));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
SimpleLogger().Write() << "Not supported on FreeBSD";
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
SimpleLogger().Write() << "Not supported on Windows";
|
||||
return 0;
|
||||
#else
|
||||
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
boost::filesystem::path test_path;
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION;
|
||||
|
||||
if (1 == argc)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " /path/on/device";
|
||||
return -1;
|
||||
}
|
||||
|
||||
test_path = boost::filesystem::path(argv[1]);
|
||||
test_path /= "osrm.tst";
|
||||
SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string();
|
||||
|
||||
// create files for testing
|
||||
if (2 == argc)
|
||||
{
|
||||
// create file to test
|
||||
if (boost::filesystem::exists(test_path))
|
||||
{
|
||||
throw osrm::exception("Data file already exists");
|
||||
}
|
||||
|
||||
int *random_array = new int[number_of_elements];
|
||||
std::generate(random_array, random_array + number_of_elements, std::rand);
|
||||
#ifdef __APPLE__
|
||||
FILE *fd = fopen(test_path.string().c_str(), "w");
|
||||
fcntl(fileno(fd), F_NOCACHE, 1);
|
||||
fcntl(fileno(fd), F_RDAHEAD, 0);
|
||||
TIMER_START(write_1gb);
|
||||
write(fileno(fd), (char *)random_array, number_of_elements * sizeof(unsigned));
|
||||
TIMER_STOP(write_1gb);
|
||||
fclose(fd);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
int file_desc =
|
||||
open(test_path.string().c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
|
||||
if (-1 == file_desc)
|
||||
{
|
||||
throw osrm::exception("Could not open random data file");
|
||||
}
|
||||
TIMER_START(write_1gb);
|
||||
int ret = write(file_desc, random_array, number_of_elements * sizeof(unsigned));
|
||||
if (0 > ret)
|
||||
{
|
||||
throw osrm::exception("could not write random data file");
|
||||
}
|
||||
TIMER_STOP(write_1gb);
|
||||
close(file_desc);
|
||||
#endif
|
||||
delete[] random_array;
|
||||
SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " << TIMER_SEC(write_1gb)
|
||||
<< "s";
|
||||
SimpleLogger().Write() << "raw write performance: " << std::setprecision(5)
|
||||
<< std::fixed << 1024 * 1024 / TIMER_SEC(write_1gb) << "MB/sec";
|
||||
|
||||
SimpleLogger().Write(logDEBUG)
|
||||
<< "finished creation of random data. Flush disk cache now!";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Run Non-Cached I/O benchmarks
|
||||
if (!boost::filesystem::exists(test_path))
|
||||
{
|
||||
throw osrm::exception("data file does not exist");
|
||||
}
|
||||
|
||||
// volatiles do not get optimized
|
||||
Statistics stats;
|
||||
|
||||
#ifdef __APPLE__
|
||||
volatile unsigned single_block[1024];
|
||||
char *raw_array = new char[number_of_elements * sizeof(unsigned)];
|
||||
FILE *fd = fopen(test_path.string().c_str(), "r");
|
||||
fcntl(fileno(fd), F_NOCACHE, 1);
|
||||
fcntl(fileno(fd), F_RDAHEAD, 0);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
char *single_block = (char *)memalign(512, 1024 * sizeof(unsigned));
|
||||
|
||||
int file_desc = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
|
||||
if (-1 == file_desc)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
|
||||
return -1;
|
||||
}
|
||||
char *raw_array = (char *)memalign(512, number_of_elements * sizeof(unsigned));
|
||||
#endif
|
||||
TIMER_START(read_1gb);
|
||||
#ifdef __APPLE__
|
||||
read(fileno(fd), raw_array, number_of_elements * sizeof(unsigned));
|
||||
close(fileno(fd));
|
||||
fd = fopen(test_path.string().c_str(), "r");
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
int ret = read(file_desc, raw_array, number_of_elements * sizeof(unsigned));
|
||||
SimpleLogger().Write(logDEBUG) << "read " << ret
|
||||
<< " bytes, error: " << strerror(errno);
|
||||
close(file_desc);
|
||||
file_desc = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC);
|
||||
SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno);
|
||||
#endif
|
||||
TIMER_STOP(read_1gb);
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " << TIMER_SEC(read_1gb) << "s";
|
||||
SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) << std::fixed
|
||||
<< 1024 * 1024 / TIMER_SEC(read_1gb) << "MB/sec";
|
||||
|
||||
std::vector<double> timing_results_raw_random;
|
||||
SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB";
|
||||
|
||||
#ifdef __APPLE__
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
lseek(file_desc, 0, SEEK_SET);
|
||||
#endif
|
||||
// make 1000 random access, time each I/O seperately
|
||||
unsigned number_of_blocks = (number_of_elements * sizeof(unsigned) - 1) / 4096;
|
||||
std::random_device rd;
|
||||
std::default_random_engine e1(rd());
|
||||
std::uniform_int_distribution<unsigned> uniform_dist(0, number_of_blocks - 1);
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
unsigned block_to_read = uniform_dist(e1);
|
||||
off_t current_offset = block_to_read * 4096;
|
||||
TIMER_START(random_access);
|
||||
#ifdef __APPLE__
|
||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||
int ret2 = read(fileno(fd), (char *)&single_block[0], 4096);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int ret1 = lseek(file_desc, current_offset, SEEK_SET);
|
||||
int ret2 = read(file_desc, (char *)single_block, 4096);
|
||||
#endif
|
||||
TIMER_STOP(random_access);
|
||||
if (((off_t)-1) == ret1)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
|
||||
throw osrm::exception("seek error");
|
||||
}
|
||||
if (-1 == ret2)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
|
||||
throw osrm::exception("read error");
|
||||
}
|
||||
timing_results_raw_random.push_back(TIMER_SEC(random_access));
|
||||
}
|
||||
|
||||
// Do statistics
|
||||
SimpleLogger().Write(logDEBUG) << "running raw random I/O statistics";
|
||||
std::ofstream random_csv("random.csv", std::ios::trunc);
|
||||
for (unsigned i = 0; i < timing_results_raw_random.size(); ++i)
|
||||
{
|
||||
random_csv << i << ", " << timing_results_raw_random[i] << std::endl;
|
||||
}
|
||||
random_csv.close();
|
||||
RunStatistics(timing_results_raw_random, stats);
|
||||
|
||||
SimpleLogger().Write() << "raw random I/O: " << std::setprecision(5) << std::fixed
|
||||
<< "min: " << stats.min << "ms, "
|
||||
<< "mean: " << stats.mean << "ms, "
|
||||
<< "med: " << stats.med << "ms, "
|
||||
<< "max: " << stats.max << "ms, "
|
||||
<< "dev: " << stats.dev << "ms";
|
||||
|
||||
std::vector<double> timing_results_raw_seq;
|
||||
#ifdef __APPLE__
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
lseek(file_desc, 0, SEEK_SET);
|
||||
#endif
|
||||
|
||||
// read every 100th block
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
off_t current_offset = i * 4096;
|
||||
TIMER_START(read_every_100);
|
||||
#ifdef __APPLE__
|
||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||
int ret2 = read(fileno(fd), (char *)&single_block, 4096);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int ret1 = lseek(file_desc, current_offset, SEEK_SET);
|
||||
|
||||
int ret2 = read(file_desc, (char *)single_block, 4096);
|
||||
#endif
|
||||
TIMER_STOP(read_every_100);
|
||||
if (((off_t)-1) == ret1)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "seek error " << strerror(errno);
|
||||
throw osrm::exception("seek error");
|
||||
}
|
||||
if (-1 == ret2)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "offset: " << current_offset;
|
||||
SimpleLogger().Write(logWARNING) << "read error " << strerror(errno);
|
||||
throw osrm::exception("read error");
|
||||
}
|
||||
timing_results_raw_seq.push_back(TIMER_SEC(read_every_100));
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
fclose(fd);
|
||||
// free(single_element);
|
||||
free(raw_array);
|
||||
// free(single_block);
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
close(file_desc);
|
||||
#endif
|
||||
// Do statistics
|
||||
SimpleLogger().Write(logDEBUG) << "running sequential I/O statistics";
|
||||
// print simple statistics: min, max, median, variance
|
||||
std::ofstream seq_csv("sequential.csv", std::ios::trunc);
|
||||
for (unsigned i = 0; i < timing_results_raw_seq.size(); ++i)
|
||||
{
|
||||
seq_csv << i << ", " << timing_results_raw_seq[i] << std::endl;
|
||||
}
|
||||
seq_csv.close();
|
||||
RunStatistics(timing_results_raw_seq, stats);
|
||||
SimpleLogger().Write() << "raw sequential I/O: " << std::setprecision(5) << std::fixed
|
||||
<< "min: " << stats.min << "ms, "
|
||||
<< "mean: " << stats.mean << "ms, "
|
||||
<< "med: " << stats.med << "ms, "
|
||||
<< "max: " << stats.max << "ms, "
|
||||
<< "dev: " << stats.dev << "ms";
|
||||
|
||||
if (boost::filesystem::exists(test_path))
|
||||
{
|
||||
boost::filesystem::remove(test_path);
|
||||
SimpleLogger().Write(logDEBUG) << "removing temporary files";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||
SimpleLogger().Write(logWARNING) << "cleaning up, and exiting";
|
||||
if (boost::filesystem::exists(test_path))
|
||||
{
|
||||
boost::filesystem::remove(test_path);
|
||||
SimpleLogger().Write(logWARNING) << "removing temporary files";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "server/server.hpp"
|
||||
#include "util/version.hpp"
|
||||
#include "util/routed_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/osrm.hpp>
|
||||
#include <osrm/libosrm_config.hpp>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <new>
|
||||
|
||||
#ifdef _WIN32
|
||||
boost::function0<void> console_ctrl_function;
|
||||
|
||||
BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
|
||||
{
|
||||
switch (ctrl_type)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
console_ctrl_function();
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, const char *argv[]) try
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
|
||||
bool trial_run = false;
|
||||
std::string ip_address;
|
||||
int ip_port, requested_thread_num;
|
||||
|
||||
LibOSRMConfig lib_config;
|
||||
const unsigned init_result = GenerateServerProgramOptions(
|
||||
argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num,
|
||||
lib_config.use_shared_memory, trial_run, lib_config.max_locations_trip, lib_config.max_locations_viaroute,
|
||||
lib_config.max_locations_distance_table,
|
||||
lib_config.max_locations_map_matching);
|
||||
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (init_result == INIT_FAILED)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
struct MemoryLocker final
|
||||
{
|
||||
explicit MemoryLocker(bool shouldLock_) : shouldLock(shouldLock_)
|
||||
{
|
||||
if (shouldLock && -1 == mlockall(MCL_CURRENT | MCL_FUTURE))
|
||||
{
|
||||
couldLock = false;
|
||||
SimpleLogger().Write(logWARNING) << "memory could not be locked to RAM";
|
||||
}
|
||||
}
|
||||
~MemoryLocker()
|
||||
{
|
||||
if (shouldLock && couldLock)
|
||||
(void)munlockall();
|
||||
}
|
||||
bool shouldLock = false, couldLock = true;
|
||||
} memoryLocker(lib_config.use_shared_memory);
|
||||
#endif
|
||||
SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION;
|
||||
|
||||
if (lib_config.use_shared_memory)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Loading from shared memory";
|
||||
}
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "Threads:\t" << requested_thread_num;
|
||||
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;
|
||||
sigset_t old_mask;
|
||||
sigfillset(&new_mask);
|
||||
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||
#endif
|
||||
|
||||
OSRM osrm_lib(lib_config);
|
||||
auto routing_server = Server::CreateServer(ip_address, ip_port, requested_thread_num);
|
||||
|
||||
routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib);
|
||||
|
||||
if (trial_run)
|
||||
{
|
||||
SimpleLogger().Write() << "trial run, quitting after successful initialization";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::packaged_task<int()> server_task([&]() -> int
|
||||
{
|
||||
routing_server->Run();
|
||||
return 0;
|
||||
});
|
||||
auto future = server_task.get_future();
|
||||
std::thread server_thread(std::move(server_task));
|
||||
|
||||
#ifndef _WIN32
|
||||
sigset_t wait_mask;
|
||||
pthread_sigmask(SIG_SETMASK, &old_mask, nullptr);
|
||||
sigemptyset(&wait_mask);
|
||||
sigaddset(&wait_mask, SIGINT);
|
||||
sigaddset(&wait_mask, SIGQUIT);
|
||||
sigaddset(&wait_mask, SIGTERM);
|
||||
pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr);
|
||||
SimpleLogger().Write() << "running and waiting for requests";
|
||||
sigwait(&wait_mask, &sig);
|
||||
#else
|
||||
// Set console control handler to allow server to be stopped.
|
||||
console_ctrl_function = std::bind(&Server::Stop, routing_server);
|
||||
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
|
||||
SimpleLogger().Write() << "running and waiting for requests";
|
||||
routing_server->Run();
|
||||
#endif
|
||||
SimpleLogger().Write() << "initiating shutdown";
|
||||
routing_server->Stop();
|
||||
SimpleLogger().Write() << "stopping threads";
|
||||
|
||||
auto status = future.wait_for(std::chrono::seconds(2));
|
||||
|
||||
if (status == std::future_status::ready)
|
||||
{
|
||||
server_thread.join();
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Didn't exit within 2 seconds. Hard abort!";
|
||||
server_task.reset(); // just kill it
|
||||
}
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "freeing objects";
|
||||
routing_server.reset();
|
||||
SimpleLogger().Write() << "shutdown completed";
|
||||
}
|
||||
catch (const std::bad_alloc &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
SimpleLogger().Write(logWARNING)
|
||||
<< "Please provide more memory or consider using a larger swapfile";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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/version.hpp"
|
||||
#include "../util/json_renderer.hpp"
|
||||
#include "../util/routed_options.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
#include <osrm/libosrm_config.hpp>
|
||||
#include <osrm/route_parameters.hpp>
|
||||
#include <osrm/osrm.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try
|
||||
{
|
||||
std::string ip_address;
|
||||
int ip_port, requested_thread_num;
|
||||
bool trial_run = false;
|
||||
LibOSRMConfig lib_config;
|
||||
const unsigned init_result = GenerateServerProgramOptions(
|
||||
argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num,
|
||||
lib_config.use_shared_memory, trial_run, lib_config.max_locations_trip,
|
||||
lib_config.max_locations_viaroute, lib_config.max_locations_distance_table,
|
||||
lib_config.max_locations_map_matching);
|
||||
|
||||
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (init_result == INIT_FAILED)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION;
|
||||
|
||||
OSRM routing_machine(lib_config);
|
||||
|
||||
RouteParameters route_parameters;
|
||||
route_parameters.zoom_level = 18; // no generalization
|
||||
route_parameters.print_instructions = true; // turn by turn instructions
|
||||
route_parameters.alternate_route = true; // get an alternate route, too
|
||||
route_parameters.geometry = true; // retrieve geometry of route
|
||||
route_parameters.compression = true; // polyline encoding
|
||||
route_parameters.check_sum = -1; // see wiki
|
||||
route_parameters.service = "viaroute"; // that's routing
|
||||
route_parameters.output_format = "json";
|
||||
route_parameters.jsonp_parameter = ""; // set for jsonp wrapping
|
||||
route_parameters.language = ""; // unused atm
|
||||
// route_parameters.hints.push_back(); // see wiki, saves I/O if done properly
|
||||
|
||||
// start_coordinate
|
||||
route_parameters.coordinates.emplace_back(52.519930 * COORDINATE_PRECISION,
|
||||
13.438640 * COORDINATE_PRECISION);
|
||||
// target_coordinate
|
||||
route_parameters.coordinates.emplace_back(52.513191 * COORDINATE_PRECISION,
|
||||
13.415852 * COORDINATE_PRECISION);
|
||||
osrm::json::Object json_result;
|
||||
const int result_code = routing_machine.RunQuery(route_parameters, json_result);
|
||||
SimpleLogger().Write() << "http code: " << result_code;
|
||||
osrm::json::render(SimpleLogger().Write(), json_result);
|
||||
}
|
||||
catch (std::exception ¤t_exception)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << current_exception.what();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 <cstdio>
|
||||
|
||||
#include "../data_structures/shared_memory_factory.hpp"
|
||||
#include "../server/data_structures/shared_datatype.hpp"
|
||||
#include "util/version.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
void delete_region(const SharedDataType region)
|
||||
{
|
||||
if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
|
||||
{
|
||||
const std::string name = [&]
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case CURRENT_REGIONS:
|
||||
return "CURRENT_REGIONS";
|
||||
case LAYOUT_1:
|
||||
return "LAYOUT_1";
|
||||
case DATA_1:
|
||||
return "DATA_1";
|
||||
case LAYOUT_2:
|
||||
return "LAYOUT_2";
|
||||
case DATA_2:
|
||||
return "DATA_2";
|
||||
case LAYOUT_NONE:
|
||||
return "LAYOUT_NONE";
|
||||
default: // DATA_NONE:
|
||||
return "DATA_NONE";
|
||||
}
|
||||
}();
|
||||
|
||||
SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name;
|
||||
}
|
||||
}
|
||||
|
||||
// find all existing shmem regions and remove them.
|
||||
void springclean()
|
||||
{
|
||||
SimpleLogger().Write() << "spring-cleaning all shared memory regions";
|
||||
delete_region(DATA_1);
|
||||
delete_region(LAYOUT_1);
|
||||
delete_region(DATA_2);
|
||||
delete_region(LAYOUT_2);
|
||||
delete_region(CURRENT_REGIONS);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION << "\n\n";
|
||||
SimpleLogger().Write() << "Releasing all locks";
|
||||
SimpleLogger().Write() << "ATTENTION! BE CAREFUL!";
|
||||
SimpleLogger().Write() << "----------------------";
|
||||
SimpleLogger().Write() << "This tool may put osrm-routed into an undefined state!";
|
||||
SimpleLogger().Write() << "Type 'Y' to acknowledge that you know what your are doing.";
|
||||
SimpleLogger().Write() << "\n\nDo you want to purge all shared memory allocated "
|
||||
<< "by osrm-datastore? [type 'Y' to confirm]";
|
||||
|
||||
const auto letter = getchar();
|
||||
if (letter != 'Y')
|
||||
{
|
||||
SimpleLogger().Write() << "aborted.";
|
||||
return 0;
|
||||
}
|
||||
springclean();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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/version.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../server/data_structures/shared_barriers.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION;
|
||||
SimpleLogger().Write() << "Releasing all locks";
|
||||
SharedBarriers barrier;
|
||||
barrier.pending_update_mutex.unlock();
|
||||
barrier.query_mutex.unlock();
|
||||
barrier.update_mutex.unlock();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user