diff --git a/.travis.yml b/.travis.yml index d5a186008d8..da116e2aca8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -118,7 +118,7 @@ install: export PATH=${DEPS_DIR}/cmake/bin:${PATH} elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then - brew install cmake boost libzip libstxxl libxml2 lua51 luabind tbb GDAL + brew install cmake boost libzip libstxxl libxml2 lua51 luabind tbb GDAL md5sha1sum fi before_script: @@ -135,8 +135,18 @@ script: - make --jobs=2 - make tests --jobs=2 - make benchmarks + - sudo make install + - | + if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then + sudo ldconfig + fi - ./extractor-tests - ./engine-tests - ./util-tests - cd .. - cucumber -p verify + - make -C test/data + - mkdir example/build && cd example/build + - cmake .. + - make + - ./osrm-example ../../test/data/berlin-latest.osrm diff --git a/CMakeLists.txt b/CMakeLists.txt index 763842cf899..b07b94b536c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ add_custom_target(FingerPrintConfigure ALL ${CMAKE_COMMAND} COMMENT "Configuring revision fingerprint" VERBATIM) -add_custom_target(tests DEPENDS engine-tests extractor-tests util-tests io-tests) +add_custom_target(tests DEPENDS engine-tests extractor-tests util-tests) add_custom_target(benchmarks DEPENDS rtree-bench) set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework) @@ -56,6 +56,7 @@ configure_file( file(GLOB UtilGlob src/util/*.cpp) file(GLOB ExtractorGlob src/extractor/*.cpp) file(GLOB ContractorGlob src/contractor/*.cpp) +file(GLOB StorageGlob src/storage/*.cpp) file(GLOB ServerGlob src/server/*.cpp src/server/**/*.cpp) file(GLOB EngineGlob src/engine/*.cpp src/engine/**/*.cpp) file(GLOB ExtractorTestsGlob unit_tests/extractor/*.cpp) @@ -66,30 +67,29 @@ file(GLOB IOTestsGlob unit_tests/io/*.cpp) add_library(UTIL OBJECT ${UtilGlob}) add_library(EXTRACTOR OBJECT ${ExtractorGlob}) add_library(CONTRACTOR OBJECT ${ContractorGlob}) +add_library(STORAGE OBJECT ${StorageGlob}) add_library(ENGINE OBJECT ${EngineGlob}) add_library(SERVER OBJECT ${ServerGlob}) -add_library(GRAPH OBJECT src/extractor/external_memory_node.cpp) -add_library(PHANTOM OBJECT src/engine/phantom_node.cpp) add_dependencies(UTIL FingerPrintConfigure) set_target_properties(UTIL PROPERTIES LINKER_LANGUAGE CXX) -add_executable(osrm-extract src/tools/extract.cpp $ $) -add_executable(osrm-prepare src/tools/contract.cpp $ $ $) -add_executable(osrm-routed src/tools/routed.cpp $ $ $) -add_executable(osrm-datastore src/tools/datastore.cpp $ $) -add_library(OSRM $ $ $) - -target_link_libraries(osrm-routed OSRM) +add_executable(osrm-extract src/tools/extract.cpp) +add_executable(osrm-prepare src/tools/contract.cpp) +add_executable(osrm-routed src/tools/routed.cpp $ $) +add_executable(osrm-datastore src/tools/store.cpp $) +add_library(osrm src/osrm/osrm.cpp $ $) +add_library(osrm_extract $ $) +add_library(osrm_contract $ $) +add_library(osrm_store $ $) # Unit tests -add_executable(engine-tests EXCLUDE_FROM_ALL unit_tests/engine_tests.cpp ${EngineTestsGlob} $ $ $) +add_executable(engine-tests EXCLUDE_FROM_ALL unit_tests/engine_tests.cpp ${EngineTestsGlob} $ $) add_executable(extractor-tests EXCLUDE_FROM_ALL unit_tests/extractor_tests.cpp ${ExtractorTestsGlob} $ $) -add_executable(util-tests EXCLUDE_FROM_ALL unit_tests/util_tests.cpp ${UtilTestsGlob} $ $) -add_executable(io-tests EXCLUDE_FROM_ALL unit_tests/io_tests.cpp ${IOTestsGlob} $) +add_executable(util-tests EXCLUDE_FROM_ALL unit_tests/util_tests.cpp ${UtilTestsGlob} $) # Benchmarks -add_executable(rtree-bench EXCLUDE_FROM_ALL src/benchmarks/static_rtree.cpp $ $) +add_executable(rtree-bench EXCLUDE_FROM_ALL src/benchmarks/static_rtree.cpp $) # Check the release mode if(NOT CMAKE_BUILD_TYPE MATCHES Debug) @@ -221,10 +221,7 @@ if(APPLE) endif() if(UNIX AND NOT APPLE) - target_link_libraries(osrm-prepare rt) - target_link_libraries(osrm-datastore rt) - target_link_libraries(OSRM rt) - target_link_libraries(engine-tests rt) + set(MAYBE_RT_LIBRARY rt) endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/cmake") @@ -232,8 +229,6 @@ set(OSMIUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/includ find_package(Osmium REQUIRED COMPONENTS io) include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS}) -target_link_libraries(osrm-extract ${OSMIUM_LIBRARIES}) -target_link_libraries(extractor-tests ${OSMIUM_LIBRARIES}) find_package(Boost 1.49.0 COMPONENTS ${BOOST_COMPONENTS} REQUIRED) if(NOT Boost_FOUND) @@ -241,72 +236,29 @@ if(NOT Boost_FOUND) endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) -target_link_libraries(OSRM ${Boost_LIBRARIES}) -target_link_libraries(osrm-extract ${Boost_LIBRARIES}) -target_link_libraries(osrm-prepare ${Boost_LIBRARIES}) -target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM) -target_link_libraries(osrm-datastore ${Boost_LIBRARIES}) -target_link_libraries(engine-tests ${Boost_LIBRARIES}) -target_link_libraries(extractor-tests ${Boost_LIBRARIES}) -target_link_libraries(util-tests ${Boost_LIBRARIES}) -target_link_libraries(rtree-bench ${Boost_LIBRARIES}) -target_link_libraries(io-tests ${Boost_LIBRARIES}) - find_package(Threads REQUIRED) -target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(engine-tests ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(extractor-tests ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(util-tests ${CMAKE_THREAD_LIBS_INIT}) -target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT}) find_package(TBB REQUIRED) +include_directories(SYSTEM ${TBB_INCLUDE_DIR}) if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug) set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES}) endif() -target_link_libraries(osrm-datastore ${TBB_LIBRARIES}) -target_link_libraries(osrm-extract ${TBB_LIBRARIES}) -target_link_libraries(osrm-prepare ${TBB_LIBRARIES}) -target_link_libraries(osrm-routed ${TBB_LIBRARIES}) -target_link_libraries(engine-tests ${TBB_LIBRARIES}) -target_link_libraries(extractor-tests ${TBB_LIBRARIES}) -target_link_libraries(util-tests ${TBB_LIBRARIES}) -target_link_libraries(rtree-bench ${TBB_LIBRARIES}) -include_directories(SYSTEM ${TBB_INCLUDE_DIR}) find_package( Luabind REQUIRED ) include(check_luabind) - include_directories(SYSTEM ${LUABIND_INCLUDE_DIR}) -target_link_libraries(osrm-extract ${LUABIND_LIBRARY}) -target_link_libraries(osrm-prepare ${LUABIND_LIBRARY}) -target_link_libraries(extractor-tests ${LUABIND_LIBRARY}) +set(USED_LUA_LIBRARIES ${LUA_LIBRARY}) if(LUAJIT_FOUND) - target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES}) - target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES}) - target_link_libraries(extractor-tests ${LUAJIT_LIBRARY}) -else() - target_link_libraries(osrm-extract ${LUA_LIBRARY}) - target_link_libraries(osrm-prepare ${LUA_LIBRARY}) - target_link_libraries(extractor-tests ${LUA_LIBRARY}) + set(USED_LUA_LIBRARIES, LUAJIT_LIBRARIES) endif() include_directories(SYSTEM ${LUA_INCLUDE_DIR}) find_package(EXPAT REQUIRED) include_directories(SYSTEM ${EXPAT_INCLUDE_DIRS}) -target_link_libraries(osrm-extract ${EXPAT_LIBRARIES}) -target_link_libraries(extractor-tests ${EXPAT_LIBRARY}) find_package(STXXL REQUIRED) include_directories(SYSTEM ${STXXL_INCLUDE_DIR}) -target_link_libraries(OSRM ${STXXL_LIBRARY}) -target_link_libraries(osrm-extract ${STXXL_LIBRARY}) -target_link_libraries(osrm-prepare ${STXXL_LIBRARY}) -target_link_libraries(extractor-tests ${STXXL_LIBRARY}) -target_link_libraries(util-tests ${STXXL_LIBRARY}) set(OpenMP_FIND_QUIETLY ON) find_package(OpenMP) @@ -317,14 +269,9 @@ endif() find_package(BZip2 REQUIRED) include_directories(SYSTEM ${BZIP_INCLUDE_DIRS}) -target_link_libraries(osrm-extract ${BZIP2_LIBRARIES}) -target_link_libraries(extractor-tests ${BZIP2_LIBRARIES}) find_package(ZLIB REQUIRED) include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS}) -target_link_libraries(osrm-extract ${ZLIB_LIBRARY}) -target_link_libraries(osrm-routed ${ZLIB_LIBRARY}) -target_link_libraries(extractor-tests ${ZLIB_LIBRARY}) if (ENABLE_JSON_LOGGING) message(STATUS "Enabling json logging") @@ -336,21 +283,71 @@ if (DEBUG_GEOMETRY) add_definitions(-DDEBUG_GEOMETRY) endif() + +# Binaries +target_link_libraries(osrm-datastore osrm_store ${Boost_LIBRARIES}) +target_link_libraries(osrm-extract osrm_extract ${Boost_LIBRARIES}) +target_link_libraries(osrm-prepare osrm_contract ${Boost_LIBRARIES}) +target_link_libraries(osrm-routed osrm ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY}) + +set(EXTRACTOR_LIBRARIES + ${BZIP2_LIBRARIES} + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${EXPAT_LIBRARIES} + ${LUABIND_LIBRARY} + ${USED_LUA_LIBRARIES} + ${OSMIUM_LIBRARIES} + ${STXXL_LIBRARY} + ${TBB_LIBRARIES} + ${ZLIB_LIBRARY}) +set(CONTRACTOR_LIBRARIES + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${LUABIND_LIBRARY} + ${USED_LUA_LIBRARIES} + ${STXXL_LIBRARY} + ${TBB_LIBRARIES} + ${MAYBE_RT_LIBRARY}) +set(ENGINE_LIBRARIES + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${STXXL_LIBRARY} + ${TBB_LIBRARIES} + ${MAYBE_RT_LIBRARY}) +set(STORAGE_LIBRARIES + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${TBB_LIBRARIES} + ${MAYBE_RT_LIBRARY}) +set(UTIL_LIBRARIES + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${STXXL_LIBRARY} + ${TBB_LIBRARIES}) +# Libraries +target_link_libraries(osrm ${ENGINE_LIBRARIES}) +target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES}) +target_link_libraries(osrm_extract ${EXTRACTOR_LIBRARIES}) +target_link_libraries(osrm_store ${STORAGE_LIBRARIES}) +# Tests +target_link_libraries(engine-tests ${ENGINE_LIBRARIES}) +target_link_libraries(extractor-tests ${EXTRACTOR_LIBRARIES}) +target_link_libraries(rtree-bench ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${TBB_LIBRARIES}) +target_link_libraries(util-tests ${UTIL_LIBRARIES}) + if(BUILD_TOOLS) message(STATUS "Activating OSRM internal tools") find_package(GDAL) if(GDAL_FOUND) - add_executable(osrm-components src/tools/components.cpp $ $) + add_executable(osrm-components src/tools/components.cpp $) target_link_libraries(osrm-components ${TBB_LIBRARIES}) include_directories(SYSTEM ${GDAL_INCLUDE_DIR}) target_link_libraries(osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES}) install(TARGETS osrm-components DESTINATION bin) else() - message(FATAL_ERROR "libgdal and/or development headers not found") + message(WARNING "libgdal and/or development headers not found") endif() - add_executable(osrm-cli src/tools/simpleclient.cpp) - target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM) - target_link_libraries(osrm-cli ${TBB_LIBRARIES}) add_executable(osrm-io-benchmark src/tools/io-benchmark.cpp $) target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES}) add_executable(osrm-unlock-all src/tools/unlock_all_mutexes.cpp $) @@ -358,21 +355,17 @@ if(BUILD_TOOLS) if(UNIX AND NOT APPLE) target_link_libraries(osrm-unlock-all rt) endif() - add_executable(osrm-check-hsgr src/tools/check-hsgr.cpp $ $) + add_executable(osrm-check-hsgr src/tools/check-hsgr.cpp $) target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES} ${TBB_LIBRARIES}) - add_executable(osrm-springclean src/tools/springclean.cpp $ $) + add_executable(osrm-springclean src/tools/springclean.cpp $) target_link_libraries(osrm-springclean ${Boost_LIBRARIES}) - install(TARGETS osrm-cli DESTINATION bin) install(TARGETS osrm-io-benchmark DESTINATION bin) install(TARGETS osrm-unlock-all DESTINATION bin) install(TARGETS osrm-check-hsgr DESTINATION bin) install(TARGETS osrm-springclean DESTINATION bin) endif() -file(GLOB InstallGlob include/osrm/*.hpp) -file(GLOB VariantGlob third_party/variant/*.hpp) - # Add RPATH info to executables so that when they are run after being installed # (i.e., from /usr/local/bin/) the linker can find library dependencies. For # more info see http://www.cmake.org/Wiki/CMake_RPATH_handling @@ -381,29 +374,35 @@ set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE) set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE) set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE) -install(FILES ${InstallGlob} DESTINATION include/osrm) +file(GLOB VariantGlob third_party/variant/*.hpp) +file(GLOB LibraryGlob include/osrm/*.hpp) +set(EngineHeader include/engine/engine.hpp include/engine/engine_config.hpp include/engine/route_parameters.hpp) +set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp) +set(ExtractorHeader include/extractor/extractor.hpp include/extractor/extractor_config.hpp) +set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp) +#set(StorageHeader include/storage/storage.hpp include/storage/storage_config.hpp) +install(FILES ${EngineHeader} DESTINATION include/osrm/engine) +install(FILES ${UtilHeader} DESTINATION include/osrm/util) +install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor) +install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor) +install(FILES ${LibraryGlob} DESTINATION include/osrm) install(FILES ${VariantGlob} DESTINATION include/variant) install(TARGETS osrm-extract DESTINATION bin) install(TARGETS osrm-prepare DESTINATION bin) install(TARGETS osrm-datastore DESTINATION bin) install(TARGETS osrm-routed DESTINATION bin) -install(TARGETS OSRM DESTINATION lib) - -list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST) -get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH) -set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}") -foreach(lib ${Boost_LIBRARIES}) - get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE) - string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME}) - set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}") -endforeach() -list(GET TBB_LIBRARIES 1 TBB_LIBRARY_FIRST) -get_filename_component(TBB_LIBRARY_LISTING "${TBB_LIBRARY_FIRST}" PATH) -set(TBB_LIBRARY_LISTING "-L${TBB_LIBRARY_LISTING}") -foreach(lib ${TBB_LIBRARIES}) - get_filename_component(TBB_LIBRARY_NAME "${lib}" NAME_WE) - string(REPLACE "lib" "" TBB_LIBRARY_NAME ${TBB_LIBRARY_NAME}) - set(TBB_LIBRARY_LISTING "${TBB_LIBRARY_LISTING} -l${TBB_LIBRARY_NAME}") +install(TARGETS osrm DESTINATION lib) +install(TARGETS osrm_extract DESTINATION lib) +install(TARGETS osrm_contract DESTINATION lib) +install(TARGETS osrm_store DESTINATION lib) + +list(GET ENGINE_LIBRARIES 1 ENGINE_LIBRARY_FIRST) +foreach(lib ${ENGINE_LIBRARIES}) + get_filename_component(ENGINE_LIBRARY_PATH "${ENGINE_LIBRARY_FIRST}" PATH) + get_filename_component(ENGINE_LIBRARY_NAME "${lib}" NAME_WE) + string(REPLACE "lib" "" ENGINE_LIBRARY_NAME ${ENGINE_LIBRARY_NAME}) + string(REPLACE "-l" "" ENGINE_LIBRARY_NAME ${ENGINE_LIBRARY_NAME}) + set(ENGINE_LIBRARY_LISTING "${ENGINE_LIBRARY_LISTING} -L${ENGINE_LIBRARY_PATH} -l${ENGINE_LIBRARY_NAME}") endforeach() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY) diff --git a/cmake/pkgconfig.in b/cmake/pkgconfig.in index 16263bfe0cf..34876c7a590 100644 --- a/cmake/pkgconfig.in +++ b/cmake/pkgconfig.in @@ -6,6 +6,6 @@ Name: libOSRM Description: Project OSRM library Version: v@OSRM_VERSION_MAJOR@.@OSRM_VERSION_MINOR@.@OSRM_VERSION_PATCH@ Requires: -Libs: -L${libdir} -lOSRM -Libs.private: @BOOST_LIBRARY_LISTING@ @TBB_LIBRARY_LISTING@ +Libs: -L${libdir} -losrm +Libs.private: @ENGINE_LIBRARY_LISTING@ Cflags: -I${includedir} diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 00000000000..86a8a7f10b5 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 2.8.8) + +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE) + message(FATAL_ERROR "In-source builds are not allowed. +Please create a directory and run cmake from there, passing the path to this source directory as the last argument. +This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.") +endif() + +project(osrm-example C CXX) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ") + +set(bitness 32) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(bitness 64) + message(STATUS "Building on a 64 bit system") +else() + message(WARNING "Building on a 32 bit system is unsupported") +endif() + +if(WIN32 AND MSVC_VERSION LESS 1800) + message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)") +endif() + +add_executable(osrm-example example.cpp) + +find_package(LibOSRM REQUIRED) +find_package(Boost 1.49.0 COMPONENTS filesystem system thread REQUIRED) + +target_link_libraries(osrm-example ${LibOSRM_LIBRARIES} ${Boost_LIBRARIES}) +include_directories(SYSTEM ${LibOSRM_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) + diff --git a/example/cmake/FindLibOSRM.cmake b/example/cmake/FindLibOSRM.cmake new file mode 100644 index 00000000000..35085b46002 --- /dev/null +++ b/example/cmake/FindLibOSRM.cmake @@ -0,0 +1,65 @@ +# - Try to find LibOSRM +# Once done this will define +# LibOSRM_FOUND - System has LibOSRM +# LibOSRM_INCLUDE_DIRS - The LibOSRM include directories +# LibOSRM_LIBRARIES - The libraries needed to use LibOSRM +# LibOSRM_DEFINITIONS - Compiler switches required for using LibOSRM + +find_package(PkgConfig) +pkg_check_modules(PC_LibOSRM QUIET libosrm) +set(LibOSRM_DEFINITIONS ${PC_LibOSRM_CFLAGS_OTHER}) + +find_path(LibOSRM_INCLUDE_DIR osrm/osrm.hpp + PATH_SUFFIXES osrm include/osrm include + HINTS ${PC_LibOSRM_INCLUDEDIR} ${PC_LibOSRM_INCLUDE_DIRS} + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local + /opt) + +set(LibOSRM_INCLUDE_DIRS ${LibOSRM_INCLUDE_DIR}) + +find_library(TEST_LibOSRM_STATIC_LIBRARY Names osrm.lib libosrm.a + PATH_SUFFIXES osrm lib/osrm lib + HINTS ${PC_LibOSRM_LIBDIR} ${PC_LibOSRM_LIBRARY_DIRS} + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local + /opt) +find_library(TEST_LibOSRM_DYNAMIC_LIBRARY Names osrm.dynlib libosrm.so + PATH_SUFFIXES osrm lib/osrm lib + HINTS ${PC_LibOSRM_LIBDIR} ${PC_LibOSRM_LIBRARY_DIRS} + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /opt/local + /opt) + +if (NOT ("${TEST_LibOSRM_STATIC_LIBRARY}" STREQUAL "TEST_LibOSRM_STATIC_LIBRARY-NOTFOUND")) + if ("${PC_LibOSRM_STATIC_LIBRARIES}" STREQUAL "") + set(LibOSRM_STATIC_LIBRARIES ${TEST_LibOSRM_STATIC_LIBRARY}) + else() + set(LibOSRM_STATIC_LIBRARIES ${PC_LibOSRM_STATIC_LIBRARIES}) + endif() + set(LibOSRM_LIBRARIES ${LibOSRM_STATIC_LIBRARIES}) +endif() + +if (NOT ("${TEST_LibOSRM_DYNAMIC_LIBRARY}" STREQUAL "TEST_LibOSRM_DYNAMIC_LIBRARY-NOTFOUND")) + if ("${PC_LibOSRM_LIBRARIES}" STREQUAL "") + set(LibOSRM_DYNAMIC_LIBRARIES ${TEST_LibOSRM_DYNAMIC_LIBRARY}) + else() + set(LibOSRM_DYNAMIC_LIBRARIES ${PC_LibOSRM_LIBRARIES}) + endif() + set(LibOSRM_LIBRARIES ${LibOSRM_DYNAMIC_LIBRARIES}) +endif() + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBOSRM_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(LibOSRM DEFAULT_MSG + LibOSRM_LIBRARIES LibOSRM_INCLUDE_DIR) diff --git a/example/cmake/FindTBB.cmake b/example/cmake/FindTBB.cmake new file mode 100644 index 00000000000..f9e3e0f57fc --- /dev/null +++ b/example/cmake/FindTBB.cmake @@ -0,0 +1,283 @@ +# Locate Intel Threading Building Blocks include paths and libraries +# FindTBB.cmake can be found at https://code.google.com/p/findtbb/ +# Written by Hannes Hofmann +# Improvements by Gino van den Bergen , +# Florian Uhlig , +# Jiri Marsik + +# The MIT License +# +# Copyright (c) 2011 Hannes Hofmann +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +# GvdB: This module uses the environment variable TBB_ARCH_PLATFORM which defines architecture and compiler. +# e.g. "ia32/vc8" or "em64t/cc4.1.0_libc2.4_kernel2.6.16.21" +# TBB_ARCH_PLATFORM is set by the build script tbbvars[.bat|.sh|.csh], which can be found +# in the TBB installation directory (TBB_INSTALL_DIR). +# +# GvdB: Mac OS X distribution places libraries directly in lib directory. +# +# For backwards compatibility, you may explicitely set the CMake variables TBB_ARCHITECTURE and TBB_COMPILER. +# TBB_ARCHITECTURE [ ia32 | em64t | itanium ] +# which architecture to use +# TBB_COMPILER e.g. vc9 or cc3.2.3_libc2.3.2_kernel2.4.21 or cc4.0.1_os10.4.9 +# which compiler to use (detected automatically on Windows) + +# This module respects +# TBB_INSTALL_DIR or $ENV{TBB21_INSTALL_DIR} or $ENV{TBB_INSTALL_DIR} + +# This module defines +# TBB_INCLUDE_DIRS, where to find task_scheduler_init.h, etc. +# TBB_LIBRARY_DIRS, where to find libtbb, libtbbmalloc +# TBB_DEBUG_LIBRARY_DIRS, where to find libtbb_debug, libtbbmalloc_debug +# TBB_INSTALL_DIR, the base TBB install directory +# TBB_LIBRARIES, the libraries to link against to use TBB. +# TBB_DEBUG_LIBRARIES, the libraries to link against to use TBB with debug symbols. +# TBB_FOUND, If false, don't try to use TBB. +# TBB_INTERFACE_VERSION, as defined in tbb/tbb_stddef.h + + +if (WIN32) + # has em64t/vc8 em64t/vc9 + # has ia32/vc7.1 ia32/vc8 ia32/vc9 + set(_TBB_DEFAULT_INSTALL_DIR "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB") + set(_TBB_LIB_NAME "tbb") + set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") + set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") + set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") + if (MSVC71) + set (_TBB_COMPILER "vc7.1") + endif(MSVC71) + if (MSVC80) + set(_TBB_COMPILER "vc8") + endif(MSVC80) + if (MSVC90) + set(_TBB_COMPILER "vc9") + endif(MSVC90) + if(MSVC10) + set(_TBB_COMPILER "vc10") + endif(MSVC10) + # Todo: add other Windows compilers such as ICL. + set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) +endif (WIN32) + +if (UNIX) + if (APPLE) + # MAC + set(_TBB_DEFAULT_INSTALL_DIR "/Library/Frameworks/Intel_TBB.framework/Versions") + # libs: libtbb.dylib, libtbbmalloc.dylib, *_debug + set(_TBB_LIB_NAME "tbb") + set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") + set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") + set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") + # default flavor on apple: ia32/cc4.0.1_os10.4.9 + # Jiri: There is no reason to presume there is only one flavor and + # that user's setting of variables should be ignored. + if(NOT TBB_COMPILER) + set(_TBB_COMPILER "cc4.0.1_os10.4.9") + elseif (NOT TBB_COMPILER) + set(_TBB_COMPILER ${TBB_COMPILER}) + endif(NOT TBB_COMPILER) + if(NOT TBB_ARCHITECTURE) + set(_TBB_ARCHITECTURE "ia32") + elseif(NOT TBB_ARCHITECTURE) + set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) + endif(NOT TBB_ARCHITECTURE) + else (APPLE) + # LINUX + set(_TBB_DEFAULT_INSTALL_DIR "/opt/intel/tbb" "/usr/local/include" "/usr/include") + set(_TBB_LIB_NAME "tbb") + set(_TBB_LIB_MALLOC_NAME "${_TBB_LIB_NAME}malloc") + set(_TBB_LIB_DEBUG_NAME "${_TBB_LIB_NAME}_debug") + set(_TBB_LIB_MALLOC_DEBUG_NAME "${_TBB_LIB_MALLOC_NAME}_debug") + # has em64t/cc3.2.3_libc2.3.2_kernel2.4.21 em64t/cc3.3.3_libc2.3.3_kernel2.6.5 em64t/cc3.4.3_libc2.3.4_kernel2.6.9 em64t/cc4.1.0_libc2.4_kernel2.6.16.21 + # has ia32/* + # has itanium/* + set(_TBB_COMPILER ${TBB_COMPILER}) + set(_TBB_ARCHITECTURE ${TBB_ARCHITECTURE}) + endif (APPLE) +endif (UNIX) + +if (CMAKE_SYSTEM MATCHES "SunOS.*") +# SUN +# not yet supported +# has em64t/cc3.4.3_kernel5.10 +# has ia32/* +endif (CMAKE_SYSTEM MATCHES "SunOS.*") + + +#-- Clear the public variables +set (TBB_FOUND "NO") + + +#-- Find TBB install dir and set ${_TBB_INSTALL_DIR} and cached ${TBB_INSTALL_DIR} +# first: use CMake variable TBB_INSTALL_DIR +if (TBB_INSTALL_DIR) + set (_TBB_INSTALL_DIR ${TBB_INSTALL_DIR}) +endif (TBB_INSTALL_DIR) +# second: use environment variable +if (NOT _TBB_INSTALL_DIR) + if (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB_INSTALL_DIR}) + endif (NOT "$ENV{TBB_INSTALL_DIR}" STREQUAL "") + # Intel recommends setting TBB21_INSTALL_DIR + if (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB21_INSTALL_DIR}) + endif (NOT "$ENV{TBB21_INSTALL_DIR}" STREQUAL "") + if (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB22_INSTALL_DIR}) + endif (NOT "$ENV{TBB22_INSTALL_DIR}" STREQUAL "") + if (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "") + set (_TBB_INSTALL_DIR $ENV{TBB30_INSTALL_DIR}) + endif (NOT "$ENV{TBB30_INSTALL_DIR}" STREQUAL "") +endif (NOT _TBB_INSTALL_DIR) +# third: try to find path automatically +if (NOT _TBB_INSTALL_DIR) + if (_TBB_DEFAULT_INSTALL_DIR) + set (_TBB_INSTALL_DIR ${_TBB_DEFAULT_INSTALL_DIR}) + endif (_TBB_DEFAULT_INSTALL_DIR) +endif (NOT _TBB_INSTALL_DIR) +# sanity check +if (NOT _TBB_INSTALL_DIR) + message ("ERROR: Unable to find Intel TBB install directory. ${_TBB_INSTALL_DIR}") +else (NOT _TBB_INSTALL_DIR) +# finally: set the cached CMake variable TBB_INSTALL_DIR +if (NOT TBB_INSTALL_DIR) + set (TBB_INSTALL_DIR ${_TBB_INSTALL_DIR} CACHE PATH "Intel TBB install directory") + mark_as_advanced(TBB_INSTALL_DIR) +endif (NOT TBB_INSTALL_DIR) + + +#-- A macro to rewrite the paths of the library. This is necessary, because +# find_library() always found the em64t/vc9 version of the TBB libs +macro(TBB_CORRECT_LIB_DIR var_name) +# if (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t") + string(REPLACE em64t "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}}) +# endif (NOT "${_TBB_ARCHITECTURE}" STREQUAL "em64t") + string(REPLACE ia32 "${_TBB_ARCHITECTURE}" ${var_name} ${${var_name}}) + string(REPLACE vc7.1 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) + string(REPLACE vc8 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) + string(REPLACE vc9 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) + string(REPLACE vc10 "${_TBB_COMPILER}" ${var_name} ${${var_name}}) +endmacro(TBB_CORRECT_LIB_DIR var_content) + + +#-- Look for include directory and set ${TBB_INCLUDE_DIR} +set (TBB_INC_SEARCH_DIR ${_TBB_INSTALL_DIR}/include) +# Jiri: tbbvars now sets the CPATH environment variable to the directory +# containing the headers. +find_path(TBB_INCLUDE_DIR + tbb/task_scheduler_init.h + PATHS ${TBB_INC_SEARCH_DIR} ENV CPATH +) +mark_as_advanced(TBB_INCLUDE_DIR) + + +#-- Look for libraries +# GvdB: $ENV{TBB_ARCH_PLATFORM} is set by the build script tbbvars[.bat|.sh|.csh] +if (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "") + set (_TBB_LIBRARY_DIR + ${_TBB_INSTALL_DIR}/lib/$ENV{TBB_ARCH_PLATFORM} + ${_TBB_INSTALL_DIR}/$ENV{TBB_ARCH_PLATFORM}/lib + ) +endif (NOT $ENV{TBB_ARCH_PLATFORM} STREQUAL "") +# Jiri: This block isn't mutually exclusive with the previous one +# (hence no else), instead I test if the user really specified +# the variables in question. +if ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL "")) + # HH: deprecated + message(STATUS "[Warning] FindTBB.cmake: The use of TBB_ARCHITECTURE and TBB_COMPILER is deprecated and may not be supported in future versions. Please set \$ENV{TBB_ARCH_PLATFORM} (using tbbvars.[bat|csh|sh]).") + # Jiri: It doesn't hurt to look in more places, so I store the hints from + # ENV{TBB_ARCH_PLATFORM} and the TBB_ARCHITECTURE and TBB_COMPILER + # variables and search them both. + set (_TBB_LIBRARY_DIR "${_TBB_INSTALL_DIR}/${_TBB_ARCHITECTURE}/${_TBB_COMPILER}/lib" ${_TBB_LIBRARY_DIR}) +endif ((NOT ${TBB_ARCHITECTURE} STREQUAL "") AND (NOT ${TBB_COMPILER} STREQUAL "")) + +# GvdB: Mac OS X distribution places libraries directly in lib directory. +list(APPEND _TBB_LIBRARY_DIR ${_TBB_INSTALL_DIR}/lib) + +# Jiri: No reason not to check the default paths. From recent versions, +# tbbvars has started exporting the LIBRARY_PATH and LD_LIBRARY_PATH +# variables, which now point to the directories of the lib files. +# It all makes more sense to use the ${_TBB_LIBRARY_DIR} as a HINTS +# argument instead of the implicit PATHS as it isn't hard-coded +# but computed by system introspection. Searching the LIBRARY_PATH +# and LD_LIBRARY_PATH environment variables is now even more important +# that tbbvars doesn't export TBB_ARCH_PLATFORM and it facilitates +# the use of TBB built from sources. +find_library(TBB_LIBRARY ${_TBB_LIB_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) +find_library(TBB_MALLOC_LIBRARY ${_TBB_LIB_MALLOC_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) + +#Extract path from TBB_LIBRARY name +get_filename_component(TBB_LIBRARY_DIR ${TBB_LIBRARY} PATH) + +#TBB_CORRECT_LIB_DIR(TBB_LIBRARY) +#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY) +mark_as_advanced(TBB_LIBRARY TBB_MALLOC_LIBRARY) + +#-- Look for debug libraries +# Jiri: Changed the same way as for the release libraries. +find_library(TBB_LIBRARY_DEBUG ${_TBB_LIB_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) +find_library(TBB_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_MALLOC_DEBUG_NAME} HINTS ${_TBB_LIBRARY_DIR} + PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH) + +# Jiri: Self-built TBB stores the debug libraries in a separate directory. +# Extract path from TBB_LIBRARY_DEBUG name +get_filename_component(TBB_LIBRARY_DEBUG_DIR ${TBB_LIBRARY_DEBUG} PATH) + +#TBB_CORRECT_LIB_DIR(TBB_LIBRARY_DEBUG) +#TBB_CORRECT_LIB_DIR(TBB_MALLOC_LIBRARY_DEBUG) +mark_as_advanced(TBB_LIBRARY_DEBUG TBB_MALLOC_LIBRARY_DEBUG) + + +if (TBB_INCLUDE_DIR) + if (TBB_LIBRARY) + set (TBB_FOUND "YES") + set (TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY} ${TBB_LIBRARIES}) + set (TBB_DEBUG_LIBRARIES ${TBB_LIBRARY_DEBUG} ${TBB_MALLOC_LIBRARY_DEBUG} ${TBB_DEBUG_LIBRARIES}) + set (TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR} CACHE PATH "TBB include directory" FORCE) + set (TBB_LIBRARY_DIRS ${TBB_LIBRARY_DIR} CACHE PATH "TBB library directory" FORCE) + # Jiri: Self-built TBB stores the debug libraries in a separate directory. + set (TBB_DEBUG_LIBRARY_DIRS ${TBB_LIBRARY_DEBUG_DIR} CACHE PATH "TBB debug library directory" FORCE) + mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARY_DIRS TBB_DEBUG_LIBRARY_DIRS TBB_LIBRARIES TBB_DEBUG_LIBRARIES) + message(STATUS "Found Intel TBB") + endif (TBB_LIBRARY) +endif (TBB_INCLUDE_DIR) + +if (NOT TBB_FOUND) + message("ERROR: Intel TBB NOT found!") + message(STATUS "Looked for Threading Building Blocks in ${_TBB_INSTALL_DIR}") + # do only throw fatal, if this pkg is REQUIRED + if (TBB_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find TBB library.") + endif (TBB_FIND_REQUIRED) +endif (NOT TBB_FOUND) + +endif (NOT _TBB_INSTALL_DIR) + +if (TBB_FOUND) + set(TBB_INTERFACE_VERSION 0) + FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS) + STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}") + set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}") +endif (TBB_FOUND) diff --git a/example/example.cpp b/example/example.cpp new file mode 100644 index 00000000000..0442ca6987b --- /dev/null +++ b/example/example.cpp @@ -0,0 +1,63 @@ +#include "osrm/json_container.hpp" +#include "osrm/engine_config.hpp" +#include "osrm/route_parameters.hpp" +#include "osrm/osrm.hpp" + +#include +#include +#include +#include +#include + +int main(int argc, const char *argv[]) try +{ + if (argc < 2) + { + std::cerr << "Error: Not enough arguments." << std::endl + << "Run " << argv[0] << " data.osrm" << std::endl; + return EXIT_FAILURE; + } + + osrm::EngineConfig engine_config; + std::string base_path(argv[1]); + engine_config.server_paths["ramindex"] = base_path + ".ramIndex"; + engine_config.server_paths["fileindex"] = base_path + ".fileIndex"; + engine_config.server_paths["hsgrdata"] = base_path + ".hsgr"; + engine_config.server_paths["nodesdata"] = base_path + ".nodes"; + engine_config.server_paths["edgesdata"] = base_path + ".edges"; + engine_config.server_paths["coredata"] = base_path + ".core"; + engine_config.server_paths["geometries"] = base_path + ".geometry"; + engine_config.server_paths["timestamp"] = base_path + ".timestamp"; + engine_config.server_paths["namesdata"] = base_path + ".names"; + engine_config.use_shared_memory = false; + + osrm::OSRM routing_machine(engine_config); + + osrm::RouteParameters route_parameters; + // route is in Berlin + auto start = std::make_pair(52.519930, 13.438640); + auto target = std::make_pair(52.513191, 13.415852); + route_parameters.service = "viaroute"; + route_parameters.AddCoordinate({start.first, start.second}); + route_parameters.AddCoordinate({target.first, target.second}); + + osrm::json::Object json_result; + const int result_code = routing_machine.RunQuery(route_parameters, json_result); + std::cout << "result code: " << result_code << std::endl; + // 2xx code + if (result_code / 100 == 2) + { + // Extract data out of JSON structure + auto& summary = json_result.values["route_summary"].get(); + auto duration = summary.values["total_time"].get().value; + auto distance = summary.values["total_distance"].get().value; + std::cout << "duration: " << duration << std::endl; + std::cout << "distance: " << distance << std::endl; + } + return EXIT_SUCCESS; +} +catch (const std::exception ¤t_exception) +{ + std::cout << "exception: " << current_exception.what(); + return EXIT_FAILURE; +} diff --git a/include/contractor/contractor.hpp b/include/contractor/contractor.hpp index 6e4f8688b12..64d3c04915e 100644 --- a/include/contractor/contractor.hpp +++ b/include/contractor/contractor.hpp @@ -1,1158 +1,74 @@ -#ifndef CONTRACTOR_HPP -#define CONTRACTOR_HPP +#ifndef CONTRACTOR_CONTRACTOR_HPP +#define CONTRACTOR_CONTRACTOR_HPP -#include "util/binary_heap.hpp" -#include "util/deallocating_vector.hpp" -#include "util/dynamic_graph.hpp" -#include "util/percent.hpp" +#include "extractor/edge_based_edge.hpp" +#include "extractor/node_based_edge.hpp" +#include "contractor/contractor.hpp" +#include "contractor/contractor_config.hpp" #include "contractor/query_edge.hpp" -#include "util/xor_fast_hash.hpp" -#include "util/xor_fast_hash_storage.hpp" -#include "util/integer_range.hpp" -#include "util/simple_logger.hpp" -#include "util/timing_util.hpp" -#include "util/typedefs.hpp" - -#include - -#include +#include "extractor/edge_based_edge.hpp" +#include "util/static_graph.hpp" +#include "util/deallocating_vector.hpp" +#include "util/node_based_graph.hpp" -#include -#include -#include +#include -#include -#include -#include #include +struct lua_State; + namespace osrm { +namespace extractor +{ +struct SpeedProfileProperties; +struct EdgeBasedNode; +struct EdgeBasedEdge; +} namespace contractor { +/// Base class of osrm-contract class Contractor { - - private: - struct ContractorEdgeData - { - ContractorEdgeData() - : distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), - is_original_via_node_ID(false) - { - } - ContractorEdgeData(unsigned distance, - unsigned original_edges, - unsigned id, - bool shortcut, - bool forward, - bool backward) - : distance(distance), id(id), - originalEdges(std::min((unsigned)1 << 28, original_edges)), shortcut(shortcut), - forward(forward), backward(backward), is_original_via_node_ID(false) - { - } - unsigned distance; - unsigned id; - unsigned originalEdges : 28; - bool shortcut : 1; - bool forward : 1; - bool backward : 1; - bool is_original_via_node_ID : 1; - } data; - - struct ContractorHeapData - { - short hop; - bool target; - ContractorHeapData() : hop(0), target(false) {} - ContractorHeapData(short h, bool t) : hop(h), target(t) {} - }; - - using ContractorGraph = util::DynamicGraph; - // using ContractorHeap = util::BinaryHeap - // >; - using ContractorHeap = util::BinaryHeap>; - using ContractorEdge = ContractorGraph::InputEdge; - - struct ContractorThreadData - { - ContractorHeap heap; - std::vector inserted_edges; - std::vector neighbours; - explicit ContractorThreadData(NodeID nodes) : heap(nodes) {} - }; - - struct NodePriorityData - { - int depth; - NodePriorityData() : depth(0) {} - }; - - struct ContractionStats - { - int edges_deleted_count; - int edges_added_count; - int original_edges_deleted_count; - int original_edges_added_count; - ContractionStats() - : edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0), - original_edges_added_count(0) - { - } - }; - - struct RemainingNodeData - { - RemainingNodeData() : id(0), is_independent(false) {} - NodeID id : 31; - bool is_independent : 1; - }; - - struct ThreadDataContainer - { - explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {} - - inline ContractorThreadData *getThreadData() - { - bool exists = false; - auto &ref = data.local(exists); - if (!exists) - { - ref = std::make_shared(number_of_nodes); - } - - return ref.get(); - } - - int number_of_nodes; - using EnumerableThreadData = - tbb::enumerable_thread_specific>; - EnumerableThreadData data; - }; - public: - template - Contractor(int nodes, ContainerT &input_edge_list) - : Contractor(nodes, input_edge_list, {}, {}) - { - } + using EdgeData = QueryEdge::EdgeData; - template - Contractor(int nodes, - ContainerT &input_edge_list, - std::vector &&node_levels_, - std::vector &&node_weights_) - : node_levels(std::move(node_levels_)), node_weights(std::move(node_weights_)) + explicit Contractor(ContractorConfig contractor_config) : config(std::move(contractor_config)) { - std::vector edges; - edges.reserve(input_edge_list.size() * 2); - - const auto dend = input_edge_list.dend(); - for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter) - { - BOOST_ASSERT_MSG(static_cast(std::max(diter->weight, 1)) > 0, - "edge distance < 1"); -#ifndef NDEBUG - if (static_cast(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10) - { - util::SimpleLogger().Write(logWARNING) - << "Edge weight large -> " - << static_cast(std::max(diter->weight, 1)) << " : " - << static_cast(diter->source) << " -> " - << static_cast(diter->target); - } -#endif - edges.emplace_back(diter->source, diter->target, - static_cast(std::max(diter->weight, 1)), 1, - diter->edge_id, false, diter->forward ? true : false, - diter->backward ? true : false); - - edges.emplace_back(diter->target, diter->source, - static_cast(std::max(diter->weight, 1)), 1, - diter->edge_id, false, diter->backward ? true : false, - diter->forward ? true : false); - } - // clear input vector - input_edge_list.clear(); - // FIXME not sure if we need this - edges.shrink_to_fit(); - - tbb::parallel_sort(edges.begin(), edges.end()); - NodeID edge = 0; - for (NodeID i = 0; i < edges.size();) - { - const NodeID source = edges[i].source; - const NodeID target = edges[i].target; - const NodeID id = edges[i].data.id; - // remove eigenloops - if (source == target) - { - ++i; - continue; - } - ContractorEdge forward_edge; - ContractorEdge reverse_edge; - forward_edge.source = reverse_edge.source = source; - forward_edge.target = reverse_edge.target = target; - forward_edge.data.forward = reverse_edge.data.backward = true; - forward_edge.data.backward = reverse_edge.data.forward = false; - forward_edge.data.shortcut = reverse_edge.data.shortcut = false; - forward_edge.data.id = reverse_edge.data.id = id; - forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; - forward_edge.data.distance = reverse_edge.data.distance = INVALID_EDGE_WEIGHT; - // remove parallel edges - while (i < edges.size() && edges[i].source == source && edges[i].target == target) - { - if (edges[i].data.forward) - { - forward_edge.data.distance = - std::min(edges[i].data.distance, forward_edge.data.distance); - } - if (edges[i].data.backward) - { - reverse_edge.data.distance = - std::min(edges[i].data.distance, reverse_edge.data.distance); - } - ++i; - } - // merge edges (s,t) and (t,s) into bidirectional edge - if (forward_edge.data.distance == reverse_edge.data.distance) - { - if ((int)forward_edge.data.distance != INVALID_EDGE_WEIGHT) - { - forward_edge.data.backward = true; - edges[edge++] = forward_edge; - } - } - else - { // insert seperate edges - if (((int)forward_edge.data.distance) != INVALID_EDGE_WEIGHT) - { - edges[edge++] = forward_edge; - } - if ((int)reverse_edge.data.distance != INVALID_EDGE_WEIGHT) - { - edges[edge++] = reverse_edge; - } - } - } - std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() - << std::endl; - edges.resize(edge); - contractor_graph = std::make_shared(nodes, edges); - edges.clear(); - edges.shrink_to_fit(); - - BOOST_ASSERT(0 == edges.capacity()); - // unsigned maxdegree = 0; - // NodeID highestNode = 0; - // - // for(unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i) { - // unsigned degree = contractor_graph->EndEdges(i) - - // contractor_graph->BeginEdges(i); - // if(degree > maxdegree) { - // maxdegree = degree; - // highestNode = i; - // } - // } - // - // util::SimpleLogger().Write() << "edges at node with id " << highestNode << " has - // degree - // " << maxdegree; - // for(unsigned i = contractor_graph->BeginEdges(highestNode); i < - // contractor_graph->EndEdges(highestNode); ++i) { - // util::SimpleLogger().Write() << " ->(" << highestNode << "," << - // contractor_graph->GetTarget(i) - // << "); via: " << contractor_graph->GetEdgeData(i).via; - // } - - std::cout << "contractor finished initalization" << std::endl; - } - - ~Contractor() {} - - void Run(double core_factor = 1.0) - { - // for the preperation we can use a big grain size, which is much faster (probably cache) - constexpr size_t InitGrainSize = 100000; - constexpr size_t PQGrainSize = 100000; - // auto_partitioner will automatically increase the blocksize if we have - // a lot of data. It is *important* for the last loop iterations - // (which have a very small dataset) that it is devisible. - constexpr size_t IndependentGrainSize = 1; - constexpr size_t ContractGrainSize = 1; - constexpr size_t NeighboursGrainSize = 1; - constexpr size_t DeleteGrainSize = 1; - - const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); - util::Percent p(number_of_nodes); - - ThreadDataContainer thread_data_list(number_of_nodes); - - NodeID number_of_contracted_nodes = 0; - std::vector node_data; - std::vector node_priorities; - is_core_node.resize(number_of_nodes, false); - - std::vector remaining_nodes(number_of_nodes); - // initialize priorities in parallel - tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, InitGrainSize), - [this, &remaining_nodes](const tbb::blocked_range &range) - { - for (int x = range.begin(), end = range.end(); x != end; ++x) - { - remaining_nodes[x].id = x; - } - }); - - bool use_cached_node_priorities = !node_levels.empty(); - if (use_cached_node_priorities) - { - std::cout << "using cached node priorities ..." << std::flush; - node_priorities.swap(node_levels); - std::cout << "ok" << std::endl; - } - else - { - node_data.resize(number_of_nodes); - node_priorities.resize(number_of_nodes); - node_levels.resize(number_of_nodes); - - std::cout << "initializing elimination PQ ..." << std::flush; - tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, PQGrainSize), - [this, &node_priorities, &node_data, - &thread_data_list](const tbb::blocked_range &range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - for (int x = range.begin(), end = range.end(); x != end; ++x) - { - node_priorities[x] = - this->EvaluateNodePriority(data, &node_data[x], x); - } - }); - std::cout << "ok" << std::endl; - } - BOOST_ASSERT(node_priorities.size() == number_of_nodes); - - std::cout << "preprocessing " << number_of_nodes << " nodes ..." << std::flush; - - unsigned current_level = 0; - bool flushed_contractor = false; - while (number_of_nodes > 2 && - number_of_contracted_nodes < static_cast(number_of_nodes * core_factor)) - { - if (!flushed_contractor && (number_of_contracted_nodes > - static_cast(number_of_nodes * 0.65 * core_factor))) - { - util::DeallocatingVector - new_edge_set; // this one is not explicitely - // cleared since it goes out of - // scope anywa - std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush; - - // Delete old heap data to free memory that we need for the coming operations - thread_data_list.data.clear(); - - // Create new priority array - std::vector new_node_priority(remaining_nodes.size()); - std::vector new_node_weights(remaining_nodes.size()); - // this map gives the old IDs from the new ones, necessary to get a consistent graph - // at the end of contraction - orig_node_id_from_new_node_id_map.resize(remaining_nodes.size()); - // this map gives the new IDs from the old ones, necessary to remap targets from the - // remaining graph - std::vector new_node_id_from_orig_id_map(number_of_nodes, SPECIAL_NODEID); - - for (const auto new_node_id : util::irange(0, remaining_nodes.size())) - { - auto &node = remaining_nodes[new_node_id]; - BOOST_ASSERT(node_priorities.size() > node.id); - new_node_priority[new_node_id] = node_priorities[node.id]; - BOOST_ASSERT(node_weights.size() > node.id); - new_node_weights[new_node_id] = node_weights[node.id]; - } - - // build forward and backward renumbering map and remap ids in remaining_nodes - for (const auto new_node_id : util::irange(0, remaining_nodes.size())) - { - auto &node = remaining_nodes[new_node_id]; - // create renumbering maps in both directions - orig_node_id_from_new_node_id_map[new_node_id] = node.id; - new_node_id_from_orig_id_map[node.id] = new_node_id; - node.id = new_node_id; - } - // walk over all nodes - for (const auto source : - util::irange(0, contractor_graph->GetNumberOfNodes())) - { - for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source)) - { - ContractorGraph::EdgeData &data = - contractor_graph->GetEdgeData(current_edge); - const NodeID target = contractor_graph->GetTarget(current_edge); - if (SPECIAL_NODEID == new_node_id_from_orig_id_map[source]) - { - external_edge_list.push_back({source, target, data}); - } - else - { - // node is not yet contracted. - // add (renumbered) outgoing edges to new util::DynamicGraph. - ContractorEdge new_edge = {new_node_id_from_orig_id_map[source], - new_node_id_from_orig_id_map[target], data}; - - new_edge.data.is_original_via_node_ID = true; - BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[source], - "new source id not resolveable"); - BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[target], - "new target id not resolveable"); - new_edge_set.push_back(new_edge); - } - } - } - - // Delete map from old NodeIDs to new ones. - new_node_id_from_orig_id_map.clear(); - new_node_id_from_orig_id_map.shrink_to_fit(); - - // Replace old priorities array by new one - node_priorities.swap(new_node_priority); - // Delete old node_priorities vector - // Due to the scope, these should get cleared automatically? @daniel-j-h do you - // agree? - new_node_priority.clear(); - new_node_priority.shrink_to_fit(); - - node_weights.swap(new_node_weights); - // old Graph is removed - contractor_graph.reset(); - - // create new graph - tbb::parallel_sort(new_edge_set.begin(), new_edge_set.end()); - contractor_graph = - std::make_shared(remaining_nodes.size(), new_edge_set); - - new_edge_set.clear(); - flushed_contractor = true; - - // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH! - // reinitialize heaps and ThreadData objects with appropriate size - thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes(); - } - - tbb::parallel_for( - tbb::blocked_range(0, remaining_nodes.size(), IndependentGrainSize), - [this, &node_priorities, &remaining_nodes, - &thread_data_list](const tbb::blocked_range &range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - // determine independent node set - for (auto i = range.begin(), end = range.end(); i != end; ++i) - { - const NodeID node = remaining_nodes[i].id; - remaining_nodes[i].is_independent = - this->IsNodeIndependent(node_priorities, data, node); - } - }); - - // sort all remaining nodes to the beginning of the sequence - const auto begin_independent_nodes = stable_partition( - remaining_nodes.begin(), remaining_nodes.end(), [](RemainingNodeData node_data) - { - return !node_data.is_independent; - }); - auto begin_independent_nodes_idx = - std::distance(remaining_nodes.begin(), begin_independent_nodes); - auto end_independent_nodes_idx = remaining_nodes.size(); - - if (!use_cached_node_priorities) - { - // write out contraction level - tbb::parallel_for( - tbb::blocked_range(begin_independent_nodes_idx, - end_independent_nodes_idx, ContractGrainSize), - [this, remaining_nodes, flushed_contractor, - current_level](const tbb::blocked_range &range) - { - if (flushed_contractor) - { - for (int position = range.begin(), end = range.end(); position != end; - ++position) - { - const NodeID x = remaining_nodes[position].id; - node_levels[orig_node_id_from_new_node_id_map[x]] = current_level; - } - } - else - { - for (int position = range.begin(), end = range.end(); position != end; - ++position) - { - const NodeID x = remaining_nodes[position].id; - node_levels[x] = current_level; - } - } - }); - } - - // contract independent nodes - tbb::parallel_for(tbb::blocked_range(begin_independent_nodes_idx, - end_independent_nodes_idx, - ContractGrainSize), - [this, &remaining_nodes, - &thread_data_list](const tbb::blocked_range &range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - for (int position = range.begin(), end = range.end(); - position != end; ++position) - { - const NodeID x = remaining_nodes[position].id; - this->ContractNode(data, x); - } - }); - - tbb::parallel_for( - tbb::blocked_range(begin_independent_nodes_idx, end_independent_nodes_idx, - DeleteGrainSize), - [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range &range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - for (int position = range.begin(), end = range.end(); position != end; - ++position) - { - const NodeID x = remaining_nodes[position].id; - this->DeleteIncomingEdges(data, x); - } - }); - - // make sure we really sort each block - tbb::parallel_for( - thread_data_list.data.range(), - [&](const ThreadDataContainer::EnumerableThreadData::range_type &range) - { - for (auto &data : range) - tbb::parallel_sort(data->inserted_edges.begin(), - data->inserted_edges.end()); - }); - - // insert new edges - for (auto &data : thread_data_list.data) - { - for (const ContractorEdge &edge : data->inserted_edges) - { - const EdgeID current_edge_ID = - contractor_graph->FindEdge(edge.source, edge.target); - if (current_edge_ID < contractor_graph->EndEdges(edge.source)) - { - ContractorGraph::EdgeData ¤t_data = - contractor_graph->GetEdgeData(current_edge_ID); - if (current_data.shortcut && edge.data.forward == current_data.forward && - edge.data.backward == current_data.backward && - edge.data.distance < current_data.distance) - { - // found a duplicate edge with smaller weight, update it. - current_data = edge.data; - continue; - } - } - contractor_graph->InsertEdge(edge.source, edge.target, edge.data); - } - data->inserted_edges.clear(); - } - - if (!use_cached_node_priorities) - { - tbb::parallel_for( - tbb::blocked_range(begin_independent_nodes_idx, end_independent_nodes_idx, - NeighboursGrainSize), - [this, &node_priorities, &remaining_nodes, &node_data, - &thread_data_list](const tbb::blocked_range &range) - { - ContractorThreadData *data = thread_data_list.getThreadData(); - for (int position = range.begin(), end = range.end(); position != end; - ++position) - { - NodeID x = remaining_nodes[position].id; - this->UpdateNodeNeighbours(node_priorities, node_data, data, x); - } - }); - } - - // remove contracted nodes from the pool - number_of_contracted_nodes += end_independent_nodes_idx - begin_independent_nodes_idx; - remaining_nodes.resize(begin_independent_nodes_idx); - // unsigned maxdegree = 0; - // unsigned avgdegree = 0; - // unsigned mindegree = SPECIAL_NODEID; - // unsigned quaddegree = 0; - // - // for(unsigned i = 0; i < remaining_nodes.size(); ++i) { - // unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].id) - // - - // contractor_graph->BeginEdges(remaining_nodes[i].first); - // if(degree > maxdegree) - // maxdegree = degree; - // if(degree < mindegree) - // mindegree = degree; - // - // avgdegree += degree; - // quaddegree += (degree*degree); - // } - // - // avgdegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() ); - // quaddegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() ); - // - // util::SimpleLogger().Write() << "rest: " << remaining_nodes.size() << ", - // max: " - // << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", - // quad: " << quaddegree; - - p.printStatus(number_of_contracted_nodes); - ++current_level; - } - - if (remaining_nodes.size() > 2) - { - if (orig_node_id_from_new_node_id_map.size() > 0) - { - tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), - [this, &remaining_nodes](const tbb::blocked_range &range) - { - for (int x = range.begin(), end = range.end(); x != end; ++x) - { - const auto orig_id = remaining_nodes[x].id; - is_core_node[orig_node_id_from_new_node_id_map[orig_id]] = - true; - } - }); - } - else - { - tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), - [this, &remaining_nodes](const tbb::blocked_range &range) - { - for (int x = range.begin(), end = range.end(); x != end; ++x) - { - const auto orig_id = remaining_nodes[x].id; - is_core_node[orig_id] = true; - } - }); - } - } - else - { - // in this case we don't need core markers since we fully contracted - // the graph - is_core_node.clear(); - } - - util::SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes " - << contractor_graph->GetNumberOfEdges() << " edges." - << std::endl; - - thread_data_list.data.clear(); - } - - inline void GetCoreMarker(std::vector &out_is_core_node) - { - out_is_core_node.swap(is_core_node); - } - - inline void GetNodeLevels(std::vector &out_node_levels) - { - out_node_levels.swap(node_levels); - } - - template inline void GetEdges(util::DeallocatingVector &edges) - { - util::Percent p(contractor_graph->GetNumberOfNodes()); - util::SimpleLogger().Write() << "Getting edges of minimized graph"; - const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); - if (contractor_graph->GetNumberOfNodes()) - { - Edge new_edge; - for (const auto node : util::irange(0u, number_of_nodes)) - { - p.printStatus(node); - for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) - { - const NodeID target = contractor_graph->GetTarget(edge); - const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge); - if (!orig_node_id_from_new_node_id_map.empty()) - { - new_edge.source = orig_node_id_from_new_node_id_map[node]; - new_edge.target = orig_node_id_from_new_node_id_map[target]; - } - else - { - new_edge.source = node; - new_edge.target = target; - } - BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.source, "Source id invalid"); - BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid"); - new_edge.data.distance = data.distance; - new_edge.data.shortcut = data.shortcut; - if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty()) - { - // tranlate the _node id_ of the shortcutted node - new_edge.data.id = orig_node_id_from_new_node_id_map[data.id]; - } - else - { - new_edge.data.id = data.id; - } - BOOST_ASSERT_MSG(new_edge.data.id != INT_MAX, // 2^31 - "edge id invalid"); - new_edge.data.forward = data.forward; - new_edge.data.backward = data.backward; - edges.push_back(new_edge); - } - } - } - contractor_graph.reset(); - orig_node_id_from_new_node_id_map.clear(); - orig_node_id_from_new_node_id_map.shrink_to_fit(); - - BOOST_ASSERT(0 == orig_node_id_from_new_node_id_map.capacity()); - - edges.append(external_edge_list.begin(), external_edge_list.end()); - external_edge_list.clear(); } + Contractor(const Contractor &) = delete; + Contractor& operator=(const Contractor &) = delete; + + int Run(); + + protected: + void ContractGraph(const unsigned max_edge_id, + util::DeallocatingVector &edge_based_edge_list, + util::DeallocatingVector &contracted_edge_list, + std::vector &&node_weights, + std::vector &is_core_node, + std::vector &inout_node_levels) const; + void WriteCoreNodeMarker(std::vector &&is_core_node) const; + void WriteNodeLevels(std::vector &&node_levels) const; + void ReadNodeLevels(std::vector &contraction_order) const; + std::size_t + WriteContractedGraph(unsigned number_of_edge_based_nodes, + const util::DeallocatingVector &contracted_edge_list); + void FindComponents(unsigned max_edge_id, + const util::DeallocatingVector &edges, + std::vector &nodes) const; private: - inline void RelaxNode(const NodeID node, - const NodeID forbidden_node, - const int distance, - ContractorHeap &heap) - { - const short current_hop = heap.GetData(node).hop + 1; - for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) - { - const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge); - if (!data.forward) - { - continue; - } - const NodeID to = contractor_graph->GetTarget(edge); - if (forbidden_node == to) - { - continue; - } - const int to_distance = distance + data.distance; - - // New Node discovered -> Add to Heap + Node Info Storage - if (!heap.WasInserted(to)) - { - heap.Insert(to, to_distance, ContractorHeapData(current_hop, false)); - } - // Found a shorter Path -> Update distance - else if (to_distance < heap.GetKey(to)) - { - heap.DecreaseKey(to, to_distance); - heap.GetData(to).hop = current_hop; - } - } - } - - inline void Dijkstra(const int max_distance, - const unsigned number_of_targets, - const int maxNodes, - ContractorThreadData &data, - const NodeID middleNode) - { - - ContractorHeap &heap = data.heap; - - int nodes = 0; - unsigned number_of_targets_found = 0; - while (!heap.Empty()) - { - const NodeID node = heap.DeleteMin(); - const auto distance = heap.GetKey(node); - if (++nodes > maxNodes) - { - return; - } - if (distance > max_distance) - { - return; - } - - // Destination settled? - if (heap.GetData(node).target) - { - ++number_of_targets_found; - if (number_of_targets_found >= number_of_targets) - { - return; - } - } - - RelaxNode(node, middleNode, distance, heap); - } - } - - inline float EvaluateNodePriority(ContractorThreadData *const data, - NodePriorityData *const node_data, - const NodeID node) - { - ContractionStats stats; - - // perform simulated contraction - ContractNode(data, node, &stats); - - // Result will contain the priority - float result; - if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count)) - { - result = 1.f * node_data->depth; - } - else - { - result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) + - 4.f * (((float)stats.original_edges_added_count) / - stats.original_edges_deleted_count) + - 1.f * node_data->depth; - } - BOOST_ASSERT(result >= 0); - return result; - } - - template - inline bool - ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr) - { - ContractorHeap &heap = data->heap; - std::size_t inserted_edges_size = data->inserted_edges.size(); - std::vector &inserted_edges = data->inserted_edges; - const constexpr bool SHORTCUT_ARC = true; - const constexpr bool FORWARD_DIRECTION_ENABLED = true; - const constexpr bool FORWARD_DIRECTION_DISABLED = false; - const constexpr bool REVERSE_DIRECTION_ENABLED = true; - const constexpr bool REVERSE_DIRECTION_DISABLED = false; - - for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node)) - { - const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge); - const NodeID source = contractor_graph->GetTarget(in_edge); - if (source == node) - continue; - - if (RUNSIMULATION) - { - BOOST_ASSERT(stats != nullptr); - ++stats->edges_deleted_count; - stats->original_edges_deleted_count += in_data.originalEdges; - } - if (!in_data.backward) - { - continue; - } - - heap.Clear(); - heap.Insert(source, 0, ContractorHeapData()); - int max_distance = 0; - unsigned number_of_targets = 0; - - for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) - { - const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); - if (!out_data.forward) - { - continue; - } - const NodeID target = contractor_graph->GetTarget(out_edge); - if (node == target) - continue; - - const EdgeWeight path_distance = in_data.distance + out_data.distance; - if (target == source) - { - if (path_distance < node_weights[node]) - { - if (RUNSIMULATION) - { - // make sure to prune better, but keep inserting this loop if it should - // still be the best - // CAREFUL: This only works due to the independent node-setting. This - // guarantees that source is not connected to another node that is - // contracted - node_weights[source] = path_distance + 1; - BOOST_ASSERT(stats != nullptr); - stats->edges_added_count += 2; - stats->original_edges_added_count += - 2 * (out_data.originalEdges + in_data.originalEdges); - } - else - { - // CAREFUL: This only works due to the independent node-setting. This - // guarantees that source is not connected to another node that is - // contracted - node_weights[source] = path_distance; // make sure to prune better - inserted_edges.emplace_back( - source, target, path_distance, - out_data.originalEdges + in_data.originalEdges, node, SHORTCUT_ARC, - FORWARD_DIRECTION_ENABLED, REVERSE_DIRECTION_DISABLED); - - inserted_edges.emplace_back( - target, source, path_distance, - out_data.originalEdges + in_data.originalEdges, node, SHORTCUT_ARC, - FORWARD_DIRECTION_DISABLED, REVERSE_DIRECTION_ENABLED); - } - } - continue; - } - max_distance = std::max(max_distance, path_distance); - if (!heap.WasInserted(target)) - { - heap.Insert(target, INVALID_EDGE_WEIGHT, ContractorHeapData(0, true)); - ++number_of_targets; - } - } - - if (RUNSIMULATION) - { - const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000; - Dijkstra(max_distance, number_of_targets, SIMULATION_SEARCH_SPACE_SIZE, *data, - node); - } - else - { - const int constexpr FULL_SEARCH_SPACE_SIZE = 2000; - Dijkstra(max_distance, number_of_targets, FULL_SEARCH_SPACE_SIZE, *data, node); - } - for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) - { - const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); - if (!out_data.forward) - { - continue; - } - const NodeID target = contractor_graph->GetTarget(out_edge); - if (target == node) - continue; - const int path_distance = in_data.distance + out_data.distance; - const int distance = heap.GetKey(target); - if (path_distance < distance) - { - if (RUNSIMULATION) - { - BOOST_ASSERT(stats != nullptr); - stats->edges_added_count += 2; - stats->original_edges_added_count += - 2 * (out_data.originalEdges + in_data.originalEdges); - } - else - { - inserted_edges.emplace_back(source, target, path_distance, - out_data.originalEdges + in_data.originalEdges, - node, SHORTCUT_ARC, FORWARD_DIRECTION_ENABLED, - REVERSE_DIRECTION_DISABLED); - - inserted_edges.emplace_back(target, source, path_distance, - out_data.originalEdges + in_data.originalEdges, - node, SHORTCUT_ARC, FORWARD_DIRECTION_DISABLED, - REVERSE_DIRECTION_ENABLED); - } - } - } - } - // Check For One-Way Streets to decide on the creation of self-loops - - if (!RUNSIMULATION) - { - std::size_t iend = inserted_edges.size(); - for (std::size_t i = inserted_edges_size; i < iend; ++i) - { - bool found = false; - for (std::size_t other = i + 1; other < iend; ++other) - { - if (inserted_edges[other].source != inserted_edges[i].source) - { - continue; - } - if (inserted_edges[other].target != inserted_edges[i].target) - { - continue; - } - if (inserted_edges[other].data.distance != inserted_edges[i].data.distance) - { - continue; - } - if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut) - { - continue; - } - inserted_edges[other].data.forward |= inserted_edges[i].data.forward; - inserted_edges[other].data.backward |= inserted_edges[i].data.backward; - found = true; - break; - } - if (!found) - { - inserted_edges[inserted_edges_size++] = inserted_edges[i]; - } - } - inserted_edges.resize(inserted_edges_size); - } - return true; - } - - inline void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node) - { - std::vector &neighbours = data->neighbours; - neighbours.clear(); - - // find all neighbours - for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) - { - const NodeID u = contractor_graph->GetTarget(e); - if (u != node) - { - neighbours.push_back(u); - } - } - // eliminate duplicate entries ( forward + backward edges ) - std::sort(neighbours.begin(), neighbours.end()); - neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); - - for (const auto i : util::irange(0, neighbours.size())) - { - contractor_graph->DeleteEdgesTo(neighbours[i], node); - } - } - - inline bool UpdateNodeNeighbours(std::vector &priorities, - std::vector &node_data, - ContractorThreadData *const data, - const NodeID node) - { - std::vector &neighbours = data->neighbours; - neighbours.clear(); - - // find all neighbours - for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) - { - const NodeID u = contractor_graph->GetTarget(e); - if (u == node) - { - continue; - } - neighbours.push_back(u); - node_data[u].depth = (std::max)(node_data[node].depth + 1, node_data[u].depth); - } - // eliminate duplicate entries ( forward + backward edges ) - std::sort(neighbours.begin(), neighbours.end()); - neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); - - // re-evaluate priorities of neighboring nodes - for (const NodeID u : neighbours) - { - priorities[u] = EvaluateNodePriority(data, &(node_data)[u], u); - } - return true; - } - - inline bool IsNodeIndependent(const std::vector &priorities, - ContractorThreadData *const data, - NodeID node) const - { - const float priority = priorities[node]; - - std::vector &neighbours = data->neighbours; - neighbours.clear(); - - for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) - { - const NodeID target = contractor_graph->GetTarget(e); - if (node == target) - { - continue; - } - const float target_priority = priorities[target]; - BOOST_ASSERT(target_priority >= 0); - // found a neighbour with lower priority? - if (priority > target_priority) - { - return false; - } - // tie breaking - if (std::abs(priority - target_priority) < std::numeric_limits::epsilon() && - bias(node, target)) - { - return false; - } - neighbours.push_back(target); - } - - std::sort(neighbours.begin(), neighbours.end()); - neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); - - // examine all neighbours that are at most 2 hops away - for (const NodeID u : neighbours) - { - for (auto e : contractor_graph->GetAdjacentEdgeRange(u)) - { - const NodeID target = contractor_graph->GetTarget(e); - if (node == target) - { - continue; - } - const float target_priority = priorities[target]; - BOOST_ASSERT(target_priority >= 0); - // found a neighbour with lower priority? - if (priority > target_priority) - { - return false; - } - // tie breaking - if (std::abs(priority - target_priority) < std::numeric_limits::epsilon() && - bias(node, target)) - { - return false; - } - } - } - return true; - } - - // This bias function takes up 22 assembly instructions in total on X86 - inline bool bias(const NodeID a, const NodeID b) const - { - const unsigned short hasha = fast_hash(a); - const unsigned short hashb = fast_hash(b); - - // The compiler optimizes that to conditional register flags but without branching - // statements! - if (hasha != hashb) - { - return hasha < hashb; - } - return a < b; - } - - std::shared_ptr contractor_graph; - stxxl::vector external_edge_list; - std::vector orig_node_id_from_new_node_id_map; - std::vector node_levels; - - // A list of weights for every node in the graph. - // The weight represents the cost for a u-turn on the segment in the base-graph in addition to - // its traversal. - // During contraction, self-loops are checked against this node weight to ensure that necessary - // self-loops are added. - std::vector node_weights; - std::vector is_core_node; - util::XORFastHash fast_hash; + ContractorConfig config; + std::size_t + LoadEdgeExpandedGraph(const std::string &edge_based_graph_path, + util::DeallocatingVector &edge_based_edge_list, + const std::string &edge_segment_lookup_path, + const std::string &edge_penalty_path, + const std::string &segment_speed_path); }; } } -#endif // CONTRACTOR_HPP +#endif // PROCESSING_CHAIN_HPP diff --git a/include/contractor/contractor_options.hpp b/include/contractor/contractor_config.hpp similarity index 68% rename from include/contractor/contractor_options.hpp rename to include/contractor/contractor_config.hpp index 04316e92539..61c88b0a3f5 100644 --- a/include/contractor/contractor_options.hpp +++ b/include/contractor/contractor_config.hpp @@ -10,17 +10,21 @@ namespace osrm namespace contractor { -enum class return_code : unsigned -{ - ok, - fail, - exit -}; - struct ContractorConfig { ContractorConfig() : requested_num_threads(0) {} + // Infer the output names from the path of the .osrm file + void UseDefaultOutputNames() + { + level_output_path = osrm_input_path.string() + ".level"; + core_output_path = osrm_input_path.string() + ".core"; + graph_output_path = osrm_input_path.string() + ".hsgr"; + edge_based_graph_path = osrm_input_path.string() + ".ebg"; + edge_segment_lookup_path = osrm_input_path.string() + ".edge_segment_lookup"; + edge_penalty_path = osrm_input_path.string() + ".edge_penalties"; + } + boost::filesystem::path config_file_path; boost::filesystem::path osrm_input_path; boost::filesystem::path profile_path; @@ -48,13 +52,6 @@ struct ContractorConfig std::string debug_geometry_path; #endif }; - -struct ContractorOptions -{ - static return_code ParseArguments(int argc, char *argv[], ContractorConfig &extractor_config); - - static void GenerateOutputFilesNames(ContractorConfig &extractor_config); -}; } } diff --git a/include/contractor/graph_contractor.hpp b/include/contractor/graph_contractor.hpp new file mode 100644 index 00000000000..65b31039fd0 --- /dev/null +++ b/include/contractor/graph_contractor.hpp @@ -0,0 +1,1104 @@ +#ifndef GRAPH_CONTRACTOR_HPP +#define GRAPH_CONTRACTOR_HPP + +#include "util/binary_heap.hpp" +#include "util/deallocating_vector.hpp" +#include "util/dynamic_graph.hpp" +#include "util/percent.hpp" +#include "contractor/query_edge.hpp" +#include "util/xor_fast_hash.hpp" +#include "util/xor_fast_hash_storage.hpp" +#include "util/integer_range.hpp" +#include "util/simple_logger.hpp" +#include "util/timing_util.hpp" +#include "util/typedefs.hpp" + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace osrm +{ +namespace contractor +{ + +class GraphContractor +{ + private: + struct ContractorEdgeData + { + ContractorEdgeData() + : distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), + is_original_via_node_ID(false) + { + } + ContractorEdgeData(unsigned distance, + unsigned original_edges, + unsigned id, + bool shortcut, + bool forward, + bool backward) + : distance(distance), id(id), + originalEdges(std::min((unsigned)1 << 28, original_edges)), shortcut(shortcut), + forward(forward), backward(backward), is_original_via_node_ID(false) + { + } + unsigned distance; + unsigned id; + unsigned originalEdges : 28; + bool shortcut : 1; + bool forward : 1; + bool backward : 1; + bool is_original_via_node_ID : 1; + } data; + + struct ContractorHeapData + { + ContractorHeapData() {} + ContractorHeapData(short hop_, bool target_) : hop(hop_), target(target_) {} + + short hop = 0; + bool target = false; + }; + + using ContractorGraph = util::DynamicGraph; + // using ContractorHeap = util::BinaryHeap + // >; + using ContractorHeap = util::BinaryHeap>; + using ContractorEdge = ContractorGraph::InputEdge; + + struct ContractorThreadData + { + ContractorHeap heap; + std::vector inserted_edges; + std::vector neighbours; + explicit ContractorThreadData(NodeID nodes) : heap(nodes) {} + }; + + using NodeDepth = int; + + struct ContractionStats + { + int edges_deleted_count; + int edges_added_count; + int original_edges_deleted_count; + int original_edges_added_count; + ContractionStats() + : edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0), + original_edges_added_count(0) + { + } + }; + + struct RemainingNodeData + { + RemainingNodeData() : id(0), is_independent(false) {} + NodeID id : 31; + bool is_independent : 1; + }; + + struct ThreadDataContainer + { + explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {} + + inline ContractorThreadData *getThreadData() + { + bool exists = false; + auto &ref = data.local(exists); + if (!exists) + { + ref = std::make_shared(number_of_nodes); + } + + return ref.get(); + } + + int number_of_nodes; + using EnumerableThreadData = + tbb::enumerable_thread_specific>; + EnumerableThreadData data; + }; + + public: + template + GraphContractor(int nodes, ContainerT &input_edge_list) + : GraphContractor(nodes, input_edge_list, {}, {}) + { + } + + template + GraphContractor(int nodes, + ContainerT &input_edge_list, + std::vector &&node_levels_, + std::vector &&node_weights_) + : node_levels(std::move(node_levels_)), node_weights(std::move(node_weights_)) + { + std::vector edges; + edges.reserve(input_edge_list.size() * 2); + + const auto dend = input_edge_list.dend(); + for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter) + { + BOOST_ASSERT_MSG(static_cast(std::max(diter->weight, 1)) > 0, + "edge distance < 1"); +#ifndef NDEBUG + if (static_cast(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10) + { + util::SimpleLogger().Write(logWARNING) + << "Edge weight large -> " + << static_cast(std::max(diter->weight, 1)) << " : " + << static_cast(diter->source) << " -> " + << static_cast(diter->target); + } +#endif + edges.emplace_back(diter->source, diter->target, + static_cast(std::max(diter->weight, 1)), 1, + diter->edge_id, false, diter->forward ? true : false, + diter->backward ? true : false); + + edges.emplace_back(diter->target, diter->source, + static_cast(std::max(diter->weight, 1)), 1, + diter->edge_id, false, diter->backward ? true : false, + diter->forward ? true : false); + } + // clear input vector + input_edge_list.clear(); + // FIXME not sure if we need this + edges.shrink_to_fit(); + + tbb::parallel_sort(edges.begin(), edges.end()); + NodeID edge = 0; + for (NodeID i = 0; i < edges.size();) + { + const NodeID source = edges[i].source; + const NodeID target = edges[i].target; + const NodeID id = edges[i].data.id; + // remove eigenloops + if (source == target) + { + ++i; + continue; + } + ContractorEdge forward_edge; + ContractorEdge reverse_edge; + forward_edge.source = reverse_edge.source = source; + forward_edge.target = reverse_edge.target = target; + forward_edge.data.forward = reverse_edge.data.backward = true; + forward_edge.data.backward = reverse_edge.data.forward = false; + forward_edge.data.shortcut = reverse_edge.data.shortcut = false; + forward_edge.data.id = reverse_edge.data.id = id; + forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; + forward_edge.data.distance = reverse_edge.data.distance = INVALID_EDGE_WEIGHT; + // remove parallel edges + while (i < edges.size() && edges[i].source == source && edges[i].target == target) + { + if (edges[i].data.forward) + { + forward_edge.data.distance = + std::min(edges[i].data.distance, forward_edge.data.distance); + } + if (edges[i].data.backward) + { + reverse_edge.data.distance = + std::min(edges[i].data.distance, reverse_edge.data.distance); + } + ++i; + } + // merge edges (s,t) and (t,s) into bidirectional edge + if (forward_edge.data.distance == reverse_edge.data.distance) + { + if ((int)forward_edge.data.distance != INVALID_EDGE_WEIGHT) + { + forward_edge.data.backward = true; + edges[edge++] = forward_edge; + } + } + else + { // insert seperate edges + if (((int)forward_edge.data.distance) != INVALID_EDGE_WEIGHT) + { + edges[edge++] = forward_edge; + } + if ((int)reverse_edge.data.distance != INVALID_EDGE_WEIGHT) + { + edges[edge++] = reverse_edge; + } + } + } + util::SimpleLogger().Write() << "merged " << edges.size() - edge << " edges out of " << edges.size(); + edges.resize(edge); + contractor_graph = std::make_shared(nodes, edges); + edges.clear(); + edges.shrink_to_fit(); + + BOOST_ASSERT(0 == edges.capacity()); + util::SimpleLogger().Write() << "contractor finished initalization"; + } + + void Run(double core_factor = 1.0) + { + // for the preperation we can use a big grain size, which is much faster (probably cache) + const constexpr size_t InitGrainSize = 100000; + const constexpr size_t PQGrainSize = 100000; + // auto_partitioner will automatically increase the blocksize if we have + // a lot of data. It is *important* for the last loop iterations + // (which have a very small dataset) that it is devisible. + const constexpr size_t IndependentGrainSize = 1; + const constexpr size_t ContractGrainSize = 1; + const constexpr size_t NeighboursGrainSize = 1; + const constexpr size_t DeleteGrainSize = 1; + + const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); + util::Percent p(number_of_nodes); + + ThreadDataContainer thread_data_list(number_of_nodes); + + NodeID number_of_contracted_nodes = 0; + std::vector node_depth; + std::vector node_priorities; + is_core_node.resize(number_of_nodes, false); + + std::vector remaining_nodes(number_of_nodes); + // initialize priorities in parallel + tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, InitGrainSize), + [this, &remaining_nodes](const tbb::blocked_range &range) + { + for (int x = range.begin(), end = range.end(); x != end; ++x) + { + remaining_nodes[x].id = x; + } + }); + + bool use_cached_node_priorities = !node_levels.empty(); + if (use_cached_node_priorities) + { + std::cout << "using cached node priorities ..." << std::flush; + node_priorities.swap(node_levels); + std::cout << "ok" << std::endl; + } + else + { + node_depth.resize(number_of_nodes, 0); + node_priorities.resize(number_of_nodes); + node_levels.resize(number_of_nodes); + + std::cout << "initializing elimination PQ ..." << std::flush; + tbb::parallel_for(tbb::blocked_range(0, number_of_nodes, PQGrainSize), + [this, &node_priorities, &node_depth, + &thread_data_list](const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + for (int x = range.begin(), end = range.end(); x != end; ++x) + { + node_priorities[x] = + this->EvaluateNodePriority(data, node_depth[x], x); + } + }); + std::cout << "ok" << std::endl; + } + BOOST_ASSERT(node_priorities.size() == number_of_nodes); + + std::cout << "preprocessing " << number_of_nodes << " nodes ..." << std::flush; + + unsigned current_level = 0; + bool flushed_contractor = false; + while (number_of_nodes > 2 && + number_of_contracted_nodes < static_cast(number_of_nodes * core_factor)) + { + if (!flushed_contractor && (number_of_contracted_nodes > + static_cast(number_of_nodes * 0.65 * core_factor))) + { + util::DeallocatingVector + new_edge_set; // this one is not explicitely + // cleared since it goes out of + // scope anywa + std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush; + + // Delete old heap data to free memory that we need for the coming operations + thread_data_list.data.clear(); + + // Create new priority array + std::vector new_node_priority(remaining_nodes.size()); + std::vector new_node_weights(remaining_nodes.size()); + // this map gives the old IDs from the new ones, necessary to get a consistent graph + // at the end of contraction + orig_node_id_from_new_node_id_map.resize(remaining_nodes.size()); + // this map gives the new IDs from the old ones, necessary to remap targets from the + // remaining graph + std::vector new_node_id_from_orig_id_map(number_of_nodes, SPECIAL_NODEID); + + for (const auto new_node_id : util::irange(0, remaining_nodes.size())) + { + auto &node = remaining_nodes[new_node_id]; + BOOST_ASSERT(node_priorities.size() > node.id); + new_node_priority[new_node_id] = node_priorities[node.id]; + BOOST_ASSERT(node_weights.size() > node.id); + new_node_weights[new_node_id] = node_weights[node.id]; + } + + // build forward and backward renumbering map and remap ids in remaining_nodes + for (const auto new_node_id : util::irange(0, remaining_nodes.size())) + { + auto &node = remaining_nodes[new_node_id]; + // create renumbering maps in both directions + orig_node_id_from_new_node_id_map[new_node_id] = node.id; + new_node_id_from_orig_id_map[node.id] = new_node_id; + node.id = new_node_id; + } + // walk over all nodes + for (const auto source : + util::irange(0, contractor_graph->GetNumberOfNodes())) + { + for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source)) + { + ContractorGraph::EdgeData &data = + contractor_graph->GetEdgeData(current_edge); + const NodeID target = contractor_graph->GetTarget(current_edge); + if (SPECIAL_NODEID == new_node_id_from_orig_id_map[source]) + { + external_edge_list.push_back({source, target, data}); + } + else + { + // node is not yet contracted. + // add (renumbered) outgoing edges to new util::DynamicGraph. + ContractorEdge new_edge = {new_node_id_from_orig_id_map[source], + new_node_id_from_orig_id_map[target], data}; + + new_edge.data.is_original_via_node_ID = true; + BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[source], + "new source id not resolveable"); + BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[target], + "new target id not resolveable"); + new_edge_set.push_back(new_edge); + } + } + } + + // Delete map from old NodeIDs to new ones. + new_node_id_from_orig_id_map.clear(); + new_node_id_from_orig_id_map.shrink_to_fit(); + + // Replace old priorities array by new one + node_priorities.swap(new_node_priority); + // Delete old node_priorities vector + // Due to the scope, these should get cleared automatically? @daniel-j-h do you + // agree? + new_node_priority.clear(); + new_node_priority.shrink_to_fit(); + + node_weights.swap(new_node_weights); + // old Graph is removed + contractor_graph.reset(); + + // create new graph + tbb::parallel_sort(new_edge_set.begin(), new_edge_set.end()); + contractor_graph = + std::make_shared(remaining_nodes.size(), new_edge_set); + + new_edge_set.clear(); + flushed_contractor = true; + + // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH! + // reinitialize heaps and ThreadData objects with appropriate size + thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes(); + } + + tbb::parallel_for( + tbb::blocked_range(0, remaining_nodes.size(), IndependentGrainSize), + [this, &node_priorities, &remaining_nodes, + &thread_data_list](const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + // determine independent node set + for (auto i = range.begin(), end = range.end(); i != end; ++i) + { + const NodeID node = remaining_nodes[i].id; + remaining_nodes[i].is_independent = + this->IsNodeIndependent(node_priorities, data, node); + } + }); + + // sort all remaining nodes to the beginning of the sequence + const auto begin_independent_nodes = stable_partition( + remaining_nodes.begin(), remaining_nodes.end(), [](RemainingNodeData node_data) + { + return !node_data.is_independent; + }); + auto begin_independent_nodes_idx = + std::distance(remaining_nodes.begin(), begin_independent_nodes); + auto end_independent_nodes_idx = remaining_nodes.size(); + + if (!use_cached_node_priorities) + { + // write out contraction level + tbb::parallel_for( + tbb::blocked_range(begin_independent_nodes_idx, + end_independent_nodes_idx, ContractGrainSize), + [this, remaining_nodes, flushed_contractor, + current_level](const tbb::blocked_range &range) + { + if (flushed_contractor) + { + for (int position = range.begin(), end = range.end(); position != end; + ++position) + { + const NodeID x = remaining_nodes[position].id; + node_levels[orig_node_id_from_new_node_id_map[x]] = current_level; + } + } + else + { + for (int position = range.begin(), end = range.end(); position != end; + ++position) + { + const NodeID x = remaining_nodes[position].id; + node_levels[x] = current_level; + } + } + }); + } + + // contract independent nodes + tbb::parallel_for(tbb::blocked_range(begin_independent_nodes_idx, + end_independent_nodes_idx, + ContractGrainSize), + [this, &remaining_nodes, + &thread_data_list](const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + for (int position = range.begin(), end = range.end(); + position != end; ++position) + { + const NodeID x = remaining_nodes[position].id; + this->ContractNode(data, x); + } + }); + + tbb::parallel_for( + tbb::blocked_range(begin_independent_nodes_idx, end_independent_nodes_idx, + DeleteGrainSize), + [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + for (int position = range.begin(), end = range.end(); position != end; + ++position) + { + const NodeID x = remaining_nodes[position].id; + this->DeleteIncomingEdges(data, x); + } + }); + + // make sure we really sort each block + tbb::parallel_for( + thread_data_list.data.range(), + [&](const ThreadDataContainer::EnumerableThreadData::range_type &range) + { + for (auto &data : range) + tbb::parallel_sort(data->inserted_edges.begin(), + data->inserted_edges.end()); + }); + + // insert new edges + for (auto &data : thread_data_list.data) + { + for (const ContractorEdge &edge : data->inserted_edges) + { + const EdgeID current_edge_ID = + contractor_graph->FindEdge(edge.source, edge.target); + if (current_edge_ID < contractor_graph->EndEdges(edge.source)) + { + ContractorGraph::EdgeData ¤t_data = + contractor_graph->GetEdgeData(current_edge_ID); + if (current_data.shortcut && edge.data.forward == current_data.forward && + edge.data.backward == current_data.backward && + edge.data.distance < current_data.distance) + { + // found a duplicate edge with smaller weight, update it. + current_data = edge.data; + continue; + } + } + contractor_graph->InsertEdge(edge.source, edge.target, edge.data); + } + data->inserted_edges.clear(); + } + + if (!use_cached_node_priorities) + { + tbb::parallel_for( + tbb::blocked_range(begin_independent_nodes_idx, end_independent_nodes_idx, + NeighboursGrainSize), + [this, &node_priorities, &remaining_nodes, &node_depth, + &thread_data_list](const tbb::blocked_range &range) + { + ContractorThreadData *data = thread_data_list.getThreadData(); + for (int position = range.begin(), end = range.end(); position != end; + ++position) + { + NodeID x = remaining_nodes[position].id; + this->UpdateNodeNeighbours(node_priorities, node_depth, data, x); + } + }); + } + + // remove contracted nodes from the pool + number_of_contracted_nodes += end_independent_nodes_idx - begin_independent_nodes_idx; + remaining_nodes.resize(begin_independent_nodes_idx); + + p.printStatus(number_of_contracted_nodes); + ++current_level; + } + + if (remaining_nodes.size() > 2) + { + if (orig_node_id_from_new_node_id_map.size() > 0) + { + tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), + [this, &remaining_nodes](const tbb::blocked_range &range) + { + for (int x = range.begin(), end = range.end(); x != end; ++x) + { + const auto orig_id = remaining_nodes[x].id; + is_core_node[orig_node_id_from_new_node_id_map[orig_id]] = + true; + } + }); + } + else + { + tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), + [this, &remaining_nodes](const tbb::blocked_range &range) + { + for (int x = range.begin(), end = range.end(); x != end; ++x) + { + const auto orig_id = remaining_nodes[x].id; + is_core_node[orig_id] = true; + } + }); + } + } + else + { + // in this case we don't need core markers since we fully contracted + // the graph + is_core_node.clear(); + } + + util::SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes " + << contractor_graph->GetNumberOfEdges() << " edges." + << std::endl; + + thread_data_list.data.clear(); + } + + inline void GetCoreMarker(std::vector &out_is_core_node) + { + out_is_core_node.swap(is_core_node); + } + + inline void GetNodeLevels(std::vector &out_node_levels) + { + out_node_levels.swap(node_levels); + } + + template inline void GetEdges(util::DeallocatingVector &edges) + { + util::Percent p(contractor_graph->GetNumberOfNodes()); + util::SimpleLogger().Write() << "Getting edges of minimized graph"; + const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); + if (contractor_graph->GetNumberOfNodes()) + { + Edge new_edge; + for (const auto node : util::irange(0u, number_of_nodes)) + { + p.printStatus(node); + for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) + { + const NodeID target = contractor_graph->GetTarget(edge); + const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge); + if (!orig_node_id_from_new_node_id_map.empty()) + { + new_edge.source = orig_node_id_from_new_node_id_map[node]; + new_edge.target = orig_node_id_from_new_node_id_map[target]; + } + else + { + new_edge.source = node; + new_edge.target = target; + } + BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.source, "Source id invalid"); + BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid"); + new_edge.data.distance = data.distance; + new_edge.data.shortcut = data.shortcut; + if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty()) + { + // tranlate the _node id_ of the shortcutted node + new_edge.data.id = orig_node_id_from_new_node_id_map[data.id]; + } + else + { + new_edge.data.id = data.id; + } + BOOST_ASSERT_MSG(new_edge.data.id != INT_MAX, // 2^31 + "edge id invalid"); + new_edge.data.forward = data.forward; + new_edge.data.backward = data.backward; + edges.push_back(new_edge); + } + } + } + contractor_graph.reset(); + orig_node_id_from_new_node_id_map.clear(); + orig_node_id_from_new_node_id_map.shrink_to_fit(); + + BOOST_ASSERT(0 == orig_node_id_from_new_node_id_map.capacity()); + + edges.append(external_edge_list.begin(), external_edge_list.end()); + external_edge_list.clear(); + } + + private: + inline void RelaxNode(const NodeID node, + const NodeID forbidden_node, + const int distance, + ContractorHeap &heap) + { + const short current_hop = heap.GetData(node).hop + 1; + for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) + { + const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge); + if (!data.forward) + { + continue; + } + const NodeID to = contractor_graph->GetTarget(edge); + if (forbidden_node == to) + { + continue; + } + const int to_distance = distance + data.distance; + + // New Node discovered -> Add to Heap + Node Info Storage + if (!heap.WasInserted(to)) + { + heap.Insert(to, to_distance, ContractorHeapData {current_hop, false}); + } + // Found a shorter Path -> Update distance + else if (to_distance < heap.GetKey(to)) + { + heap.DecreaseKey(to, to_distance); + heap.GetData(to).hop = current_hop; + } + } + } + + inline void Dijkstra(const int max_distance, + const unsigned number_of_targets, + const int maxNodes, + ContractorThreadData &data, + const NodeID middleNode) + { + + ContractorHeap &heap = data.heap; + + int nodes = 0; + unsigned number_of_targets_found = 0; + while (!heap.Empty()) + { + const NodeID node = heap.DeleteMin(); + const auto distance = heap.GetKey(node); + if (++nodes > maxNodes) + { + return; + } + if (distance > max_distance) + { + return; + } + + // Destination settled? + if (heap.GetData(node).target) + { + ++number_of_targets_found; + if (number_of_targets_found >= number_of_targets) + { + return; + } + } + + RelaxNode(node, middleNode, distance, heap); + } + } + + inline float EvaluateNodePriority(ContractorThreadData *const data, + const NodeDepth node_depth, + const NodeID node) + { + ContractionStats stats; + + // perform simulated contraction + ContractNode(data, node, &stats); + + // Result will contain the priority + float result; + if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count)) + { + result = 1.f * node_depth; + } + else + { + result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) + + 4.f * (((float)stats.original_edges_added_count) / + stats.original_edges_deleted_count) + + 1.f * node_depth; + } + BOOST_ASSERT(result >= 0); + return result; + } + + template + inline bool + ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr) + { + ContractorHeap &heap = data->heap; + std::size_t inserted_edges_size = data->inserted_edges.size(); + std::vector &inserted_edges = data->inserted_edges; + const constexpr bool SHORTCUT_ARC = true; + const constexpr bool FORWARD_DIRECTION_ENABLED = true; + const constexpr bool FORWARD_DIRECTION_DISABLED = false; + const constexpr bool REVERSE_DIRECTION_ENABLED = true; + const constexpr bool REVERSE_DIRECTION_DISABLED = false; + + for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node)) + { + const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge); + const NodeID source = contractor_graph->GetTarget(in_edge); + if (source == node) + continue; + + if (RUNSIMULATION) + { + BOOST_ASSERT(stats != nullptr); + ++stats->edges_deleted_count; + stats->original_edges_deleted_count += in_data.originalEdges; + } + if (!in_data.backward) + { + continue; + } + + heap.Clear(); + heap.Insert(source, 0, ContractorHeapData {}); + int max_distance = 0; + unsigned number_of_targets = 0; + + for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) + { + const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); + if (!out_data.forward) + { + continue; + } + const NodeID target = contractor_graph->GetTarget(out_edge); + if (node == target) + continue; + + const EdgeWeight path_distance = in_data.distance + out_data.distance; + if (target == source) + { + if (path_distance < node_weights[node]) + { + if (RUNSIMULATION) + { + // make sure to prune better, but keep inserting this loop if it should + // still be the best + // CAREFUL: This only works due to the independent node-setting. This + // guarantees that source is not connected to another node that is + // contracted + node_weights[source] = path_distance + 1; + BOOST_ASSERT(stats != nullptr); + stats->edges_added_count += 2; + stats->original_edges_added_count += + 2 * (out_data.originalEdges + in_data.originalEdges); + } + else + { + // CAREFUL: This only works due to the independent node-setting. This + // guarantees that source is not connected to another node that is + // contracted + node_weights[source] = path_distance; // make sure to prune better + inserted_edges.emplace_back( + source, target, path_distance, + out_data.originalEdges + in_data.originalEdges, node, SHORTCUT_ARC, + FORWARD_DIRECTION_ENABLED, REVERSE_DIRECTION_DISABLED); + + inserted_edges.emplace_back( + target, source, path_distance, + out_data.originalEdges + in_data.originalEdges, node, SHORTCUT_ARC, + FORWARD_DIRECTION_DISABLED, REVERSE_DIRECTION_ENABLED); + } + } + continue; + } + max_distance = std::max(max_distance, path_distance); + if (!heap.WasInserted(target)) + { + heap.Insert(target, INVALID_EDGE_WEIGHT, ContractorHeapData {0, true}); + ++number_of_targets; + } + } + + if (RUNSIMULATION) + { + const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000; + Dijkstra(max_distance, number_of_targets, SIMULATION_SEARCH_SPACE_SIZE, *data, + node); + } + else + { + const int constexpr FULL_SEARCH_SPACE_SIZE = 2000; + Dijkstra(max_distance, number_of_targets, FULL_SEARCH_SPACE_SIZE, *data, node); + } + for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) + { + const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); + if (!out_data.forward) + { + continue; + } + const NodeID target = contractor_graph->GetTarget(out_edge); + if (target == node) + continue; + const int path_distance = in_data.distance + out_data.distance; + const int distance = heap.GetKey(target); + if (path_distance < distance) + { + if (RUNSIMULATION) + { + BOOST_ASSERT(stats != nullptr); + stats->edges_added_count += 2; + stats->original_edges_added_count += + 2 * (out_data.originalEdges + in_data.originalEdges); + } + else + { + inserted_edges.emplace_back(source, target, path_distance, + out_data.originalEdges + in_data.originalEdges, + node, SHORTCUT_ARC, FORWARD_DIRECTION_ENABLED, + REVERSE_DIRECTION_DISABLED); + + inserted_edges.emplace_back(target, source, path_distance, + out_data.originalEdges + in_data.originalEdges, + node, SHORTCUT_ARC, FORWARD_DIRECTION_DISABLED, + REVERSE_DIRECTION_ENABLED); + } + } + } + } + // Check For One-Way Streets to decide on the creation of self-loops + + if (!RUNSIMULATION) + { + std::size_t iend = inserted_edges.size(); + for (std::size_t i = inserted_edges_size; i < iend; ++i) + { + bool found = false; + for (std::size_t other = i + 1; other < iend; ++other) + { + if (inserted_edges[other].source != inserted_edges[i].source) + { + continue; + } + if (inserted_edges[other].target != inserted_edges[i].target) + { + continue; + } + if (inserted_edges[other].data.distance != inserted_edges[i].data.distance) + { + continue; + } + if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut) + { + continue; + } + inserted_edges[other].data.forward |= inserted_edges[i].data.forward; + inserted_edges[other].data.backward |= inserted_edges[i].data.backward; + found = true; + break; + } + if (!found) + { + inserted_edges[inserted_edges_size++] = inserted_edges[i]; + } + } + inserted_edges.resize(inserted_edges_size); + } + return true; + } + + inline void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node) + { + std::vector &neighbours = data->neighbours; + neighbours.clear(); + + // find all neighbours + for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) + { + const NodeID u = contractor_graph->GetTarget(e); + if (u != node) + { + neighbours.push_back(u); + } + } + // eliminate duplicate entries ( forward + backward edges ) + std::sort(neighbours.begin(), neighbours.end()); + neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); + + for (const auto i : util::irange(0, neighbours.size())) + { + contractor_graph->DeleteEdgesTo(neighbours[i], node); + } + } + + inline bool UpdateNodeNeighbours(std::vector &priorities, + std::vector &node_depth, + ContractorThreadData *const data, + const NodeID node) + { + std::vector &neighbours = data->neighbours; + neighbours.clear(); + + // find all neighbours + for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) + { + const NodeID u = contractor_graph->GetTarget(e); + if (u == node) + { + continue; + } + neighbours.push_back(u); + node_depth[u] = std::max(node_depth[node] + 1, node_depth[u]); + } + // eliminate duplicate entries ( forward + backward edges ) + std::sort(neighbours.begin(), neighbours.end()); + neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); + + // re-evaluate priorities of neighboring nodes + for (const NodeID u : neighbours) + { + priorities[u] = EvaluateNodePriority(data, node_depth[u], u); + } + return true; + } + + inline bool IsNodeIndependent(const std::vector &priorities, + ContractorThreadData *const data, + NodeID node) const + { + const float priority = priorities[node]; + + std::vector &neighbours = data->neighbours; + neighbours.clear(); + + for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) + { + const NodeID target = contractor_graph->GetTarget(e); + if (node == target) + { + continue; + } + const float target_priority = priorities[target]; + BOOST_ASSERT(target_priority >= 0); + // found a neighbour with lower priority? + if (priority > target_priority) + { + return false; + } + // tie breaking + if (std::abs(priority - target_priority) < std::numeric_limits::epsilon() && + bias(node, target)) + { + return false; + } + neighbours.push_back(target); + } + + std::sort(neighbours.begin(), neighbours.end()); + neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); + + // examine all neighbours that are at most 2 hops away + for (const NodeID u : neighbours) + { + for (auto e : contractor_graph->GetAdjacentEdgeRange(u)) + { + const NodeID target = contractor_graph->GetTarget(e); + if (node == target) + { + continue; + } + const float target_priority = priorities[target]; + BOOST_ASSERT(target_priority >= 0); + // found a neighbour with lower priority? + if (priority > target_priority) + { + return false; + } + // tie breaking + if (std::abs(priority - target_priority) < std::numeric_limits::epsilon() && + bias(node, target)) + { + return false; + } + } + } + return true; + } + + // This bias function takes up 22 assembly instructions in total on X86 + inline bool bias(const NodeID a, const NodeID b) const + { + const unsigned short hasha = fast_hash(a); + const unsigned short hashb = fast_hash(b); + + // The compiler optimizes that to conditional register flags but without branching + // statements! + if (hasha != hashb) + { + return hasha < hashb; + } + return a < b; + } + + std::shared_ptr contractor_graph; + stxxl::vector external_edge_list; + std::vector orig_node_id_from_new_node_id_map; + std::vector node_levels; + + // A list of weights for every node in the graph. + // The weight represents the cost for a u-turn on the segment in the base-graph in addition to + // its traversal. + // During contraction, self-loops are checked against this node weight to ensure that necessary + // self-loops are added. + std::vector node_weights; + std::vector is_core_node; + util::XORFastHash fast_hash; +}; +} +} + +#endif // CONTRACTOR_HPP diff --git a/include/contractor/processing_chain.hpp b/include/contractor/processing_chain.hpp deleted file mode 100644 index e75af29e015..00000000000 --- a/include/contractor/processing_chain.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef PROCESSING_CHAIN_HPP -#define PROCESSING_CHAIN_HPP - -#include "contractor/contractor.hpp" -#include "contractor/contractor_options.hpp" -#include "contractor/query_edge.hpp" -#include "extractor/edge_based_edge.hpp" -#include "util/static_graph.hpp" -#include "util/deallocating_vector.hpp" -#include "util/node_based_graph.hpp" - -#include - -#include - -#include - -struct lua_State; - -namespace osrm -{ -namespace extractor -{ -struct SpeedProfileProperties; -struct EdgeBasedNode; -} -namespace contractor -{ - -/** - \brief class of 'prepare' utility. - */ -class Prepare -{ - public: - using EdgeData = QueryEdge::EdgeData; - - explicit Prepare(ContractorConfig contractor_config) : config(std::move(contractor_config)) {} - Prepare(const Prepare &) = delete; - ~Prepare(); - - int Run(); - - protected: - void ContractGraph(const unsigned max_edge_id, - util::DeallocatingVector &edge_based_edge_list, - util::DeallocatingVector &contracted_edge_list, - std::vector &&node_weights, - std::vector &is_core_node, - std::vector &node_levels) const; - void WriteCoreNodeMarker(std::vector &&is_core_node) const; - void WriteNodeLevels(std::vector &&node_levels) const; - void ReadNodeLevels(std::vector &contraction_order) const; - std::size_t - WriteContractedGraph(unsigned number_of_edge_based_nodes, - const util::DeallocatingVector &contracted_edge_list); - void FindComponents(unsigned max_edge_id, - const util::DeallocatingVector &edges, - std::vector &nodes) const; - - private: - ContractorConfig config; - std::size_t - LoadEdgeExpandedGraph(const std::string &edge_based_graph_path, - util::DeallocatingVector &edge_based_edge_list, - const std::string &edge_segment_lookup_path, - const std::string &edge_penalty_path, - const std::string &segment_speed_path); -}; -} -} - -#endif // PROCESSING_CHAIN_HPP diff --git a/include/engine/datafacade/shared_datafacade.hpp b/include/engine/datafacade/shared_datafacade.hpp index 359584682a8..7238bec6c2b 100644 --- a/include/engine/datafacade/shared_datafacade.hpp +++ b/include/engine/datafacade/shared_datafacade.hpp @@ -4,7 +4,8 @@ // implements all data storage when shared memory _IS_ used #include "engine/datafacade/datafacade_base.hpp" -#include "engine/datafacade/shared_datatype.hpp" +#include "storage/shared_datatype.hpp" +#include "storage/shared_memory.hpp" #include "engine/geospatial_query.hpp" #include "util/range_table.hpp" @@ -44,18 +45,18 @@ template class SharedDataFacade final : public BaseDataFacade< using TimeStampedRTreePair = std::pair>; using RTreeNode = typename SharedRTree::TreeNode; - SharedDataLayout *data_layout; + storage::SharedDataLayout *data_layout; char *shared_memory; - SharedDataTimestamp *data_timestamp_ptr; + storage::SharedDataTimestamp *data_timestamp_ptr; - SharedDataType CURRENT_LAYOUT; - SharedDataType CURRENT_DATA; + storage::SharedDataType CURRENT_LAYOUT; + storage::SharedDataType CURRENT_DATA; unsigned CURRENT_TIMESTAMP; unsigned m_check_sum; std::unique_ptr m_query_graph; - std::unique_ptr m_layout_memory; - std::unique_ptr m_large_memory; + std::unique_ptr m_layout_memory; + std::unique_ptr m_large_memory; std::string m_timestamp; std::shared_ptr::vector> m_coordinate_list; @@ -79,17 +80,17 @@ template class SharedDataFacade final : public BaseDataFacade< void LoadChecksum() { m_check_sum = - *data_layout->GetBlockPtr(shared_memory, SharedDataLayout::HSGR_CHECKSUM); + *data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::HSGR_CHECKSUM); util::SimpleLogger().Write() << "set checksum: " << m_check_sum; } void LoadTimestamp() { char *timestamp_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::TIMESTAMP); - m_timestamp.resize(data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP)); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::TIMESTAMP); + m_timestamp.resize(data_layout->GetBlockSize(storage::SharedDataLayout::TIMESTAMP)); std::copy(timestamp_ptr, - timestamp_ptr + data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP), + timestamp_ptr + data_layout->GetBlockSize(storage::SharedDataLayout::TIMESTAMP), m_timestamp.begin()); } @@ -98,11 +99,11 @@ template class SharedDataFacade final : public BaseDataFacade< BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree"); RTreeNode *tree_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::R_SEARCH_TREE); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::R_SEARCH_TREE); m_static_rtree.reset(new TimeStampedRTreePair( CURRENT_TIMESTAMP, util::make_unique( - tree_ptr, data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE], + tree_ptr, data_layout->num_entries[storage::SharedDataLayout::R_SEARCH_TREE], file_index_path, m_coordinate_list))); m_geospatial_query.reset( new SharedGeospatialQuery(*m_static_rtree->second, m_coordinate_list)); @@ -111,15 +112,15 @@ template class SharedDataFacade final : public BaseDataFacade< void LoadGraph() { GraphNode *graph_nodes_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GRAPH_NODE_LIST); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::GRAPH_NODE_LIST); GraphEdge *graph_edges_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GRAPH_EDGE_LIST); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::GRAPH_EDGE_LIST); typename util::ShM::vector node_list( - graph_nodes_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_NODE_LIST]); + graph_nodes_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_NODE_LIST]); typename util::ShM::vector edge_list( - graph_edges_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_EDGE_LIST]); + graph_edges_ptr, data_layout->num_entries[storage::SharedDataLayout::GRAPH_EDGE_LIST]); m_query_graph.reset(new QueryGraph(node_list, edge_list)); } @@ -128,56 +129,56 @@ template class SharedDataFacade final : public BaseDataFacade< util::FixedPointCoordinate *coordinate_list_ptr = data_layout->GetBlockPtr(shared_memory, - SharedDataLayout::COORDINATE_LIST); + storage::SharedDataLayout::COORDINATE_LIST); m_coordinate_list = util::make_unique::vector>( - coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]); + coordinate_list_ptr, data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]); extractor::TravelMode *travel_mode_list_ptr = data_layout->GetBlockPtr(shared_memory, - SharedDataLayout::TRAVEL_MODE); + storage::SharedDataLayout::TRAVEL_MODE); typename util::ShM::vector travel_mode_list( - travel_mode_list_ptr, data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]); + travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]); m_travel_mode_list.swap(travel_mode_list); extractor::TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::TURN_INSTRUCTION); + shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION); typename util::ShM::vector turn_instruction_list( turn_instruction_list_ptr, - data_layout->num_entries[SharedDataLayout::TURN_INSTRUCTION]); + data_layout->num_entries[storage::SharedDataLayout::TURN_INSTRUCTION]); m_turn_instruction_list.swap(turn_instruction_list); unsigned *name_id_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_ID_LIST); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::NAME_ID_LIST); typename util::ShM::vector name_id_list( - name_id_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_ID_LIST]); + name_id_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_ID_LIST]); m_name_ID_list.swap(name_id_list); } void LoadViaNodeList() { NodeID *via_node_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::VIA_NODE_LIST); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::VIA_NODE_LIST); typename util::ShM::vector via_node_list( - via_node_list_ptr, data_layout->num_entries[SharedDataLayout::VIA_NODE_LIST]); + via_node_list_ptr, data_layout->num_entries[storage::SharedDataLayout::VIA_NODE_LIST]); m_via_node_list.swap(via_node_list); } void LoadNames() { unsigned *offsets_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_OFFSETS); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::NAME_OFFSETS); NameIndexBlock *blocks_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_BLOCKS); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::NAME_BLOCKS); typename util::ShM::vector name_offsets( - offsets_ptr, data_layout->num_entries[SharedDataLayout::NAME_OFFSETS]); + offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_OFFSETS]); typename util::ShM::vector name_blocks( - blocks_ptr, data_layout->num_entries[SharedDataLayout::NAME_BLOCKS]); + blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_BLOCKS]); char *names_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::NAME_CHAR_LIST); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::NAME_CHAR_LIST); typename util::ShM::vector names_char_list( - names_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_CHAR_LIST]); + names_list_ptr, data_layout->num_entries[storage::SharedDataLayout::NAME_CHAR_LIST]); m_name_table = util::make_unique>( name_offsets, name_blocks, static_cast(names_char_list.size())); @@ -186,37 +187,37 @@ template class SharedDataFacade final : public BaseDataFacade< void LoadCoreInformation() { - if (data_layout->num_entries[SharedDataLayout::CORE_MARKER] <= 0) + if (data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER] <= 0) { return; } unsigned *core_marker_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::CORE_MARKER); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::CORE_MARKER); typename util::ShM::vector is_core_node( - core_marker_ptr, data_layout->num_entries[SharedDataLayout::CORE_MARKER]); + core_marker_ptr, data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER]); m_is_core_node.swap(is_core_node); } void LoadGeometries() { unsigned *geometries_compressed_ptr = data_layout->GetBlockPtr( - shared_memory, SharedDataLayout::GEOMETRIES_INDICATORS); + shared_memory, storage::SharedDataLayout::GEOMETRIES_INDICATORS); typename util::ShM::vector edge_is_compressed( geometries_compressed_ptr, - data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDICATORS]); + data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_INDICATORS]); m_edge_is_compressed.swap(edge_is_compressed); unsigned *geometries_index_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GEOMETRIES_INDEX); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::GEOMETRIES_INDEX); typename util::ShM::vector geometry_begin_indices( - geometries_index_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDEX]); + geometries_index_ptr, data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_INDEX]); m_geometry_indices.swap(geometry_begin_indices); unsigned *geometries_list_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::GEOMETRIES_LIST); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::GEOMETRIES_LIST); typename util::ShM::vector geometry_list( - geometries_list_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_LIST]); + geometries_list_ptr, data_layout->num_entries[storage::SharedDataLayout::GEOMETRIES_LIST]); m_geometry_list.swap(geometry_list); } @@ -227,15 +228,16 @@ template class SharedDataFacade final : public BaseDataFacade< SharedDataFacade() { - if (!datastore::SharedMemory::RegionExists(CURRENT_REGIONS)) + if (!storage::SharedMemory::RegionExists(storage::CURRENT_REGIONS)) { throw util::exception("No shared memory blocks found, have you forgotten to run osrm-datastore?"); } - data_timestamp_ptr = (SharedDataTimestamp *)datastore::SharedMemoryFactory::Get( - CURRENT_REGIONS, sizeof(SharedDataTimestamp), false, false) - ->Ptr(); - CURRENT_LAYOUT = LAYOUT_NONE; - CURRENT_DATA = DATA_NONE; + data_timestamp_ptr = static_cast( + storage::makeSharedMemory(storage::CURRENT_REGIONS, + sizeof(storage::SharedDataTimestamp), false, false) + ->Ptr()); + CURRENT_LAYOUT = storage::LAYOUT_NONE; + CURRENT_DATA = storage::DATA_NONE; CURRENT_TIMESTAMP = 0; // load data @@ -248,7 +250,6 @@ template class SharedDataFacade final : public BaseDataFacade< CURRENT_DATA != data_timestamp_ptr->data || CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp) { - // Get exclusive lock util::SimpleLogger().Write(logDEBUG) << "Updates available, getting exclusive lock"; boost::unique_lock lock(data_mutex); @@ -257,8 +258,8 @@ template class SharedDataFacade final : public BaseDataFacade< CURRENT_DATA != data_timestamp_ptr->data) { // release the previous shared memory segments - datastore::SharedMemory::Remove(CURRENT_LAYOUT); - datastore::SharedMemory::Remove(CURRENT_DATA); + storage::SharedMemory::Remove(CURRENT_LAYOUT); + storage::SharedMemory::Remove(CURRENT_DATA); CURRENT_LAYOUT = data_timestamp_ptr->layout; CURRENT_DATA = data_timestamp_ptr->data; @@ -277,15 +278,15 @@ template class SharedDataFacade final : public BaseDataFacade< CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp; util::SimpleLogger().Write(logDEBUG) << "Performing data reload"; - m_layout_memory.reset(datastore::SharedMemoryFactory::Get(CURRENT_LAYOUT)); + m_layout_memory.reset(storage::makeSharedMemory(CURRENT_LAYOUT)); - data_layout = (SharedDataLayout *) (m_layout_memory->Ptr()); + data_layout = (storage::SharedDataLayout *) (m_layout_memory->Ptr()); - m_large_memory.reset(datastore::SharedMemoryFactory::Get(CURRENT_DATA)); + m_large_memory.reset(storage::makeSharedMemory(CURRENT_DATA)); shared_memory = (char *) (m_large_memory->Ptr()); const char *file_index_ptr = - data_layout->GetBlockPtr(shared_memory, SharedDataLayout::FILE_INDEX_PATH); + data_layout->GetBlockPtr(shared_memory, storage::SharedDataLayout::FILE_INDEX_PATH); file_index_path = boost::filesystem::path(file_index_ptr); if (!boost::filesystem::exists(file_index_path)) { util::SimpleLogger().Write(logDEBUG) << "Leaf file name " @@ -303,8 +304,6 @@ template class SharedDataFacade final : public BaseDataFacade< LoadNames(); LoadCoreInformation(); - data_layout->PrintInformation(); - util::SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size(); for (unsigned i = 0; i < m_coordinate_list->size(); ++i) { diff --git a/include/engine/osrm_impl.hpp b/include/engine/engine.hpp similarity index 81% rename from include/engine/osrm_impl.hpp rename to include/engine/engine.hpp index c37135102c7..3b23445ba37 100644 --- a/include/engine/osrm_impl.hpp +++ b/include/engine/engine.hpp @@ -1,10 +1,9 @@ -#ifndef OSRM_IMPL_HPP -#define OSRM_IMPL_HPP +#ifndef ENGINE_HPP +#define ENGINE_HPP #include "contractor/query_edge.hpp" #include "osrm/json_container.hpp" -#include "osrm/libosrm_config.hpp" #include "osrm/osrm.hpp" #include @@ -14,6 +13,11 @@ namespace osrm { +namespace storage +{ +struct SharedBarriers; +} + namespace util { namespace json @@ -24,33 +28,32 @@ struct Object; namespace engine { +struct EngineConfig; struct RouteParameters; namespace plugins { class BasePlugin; } - namespace datafacade { -struct SharedBarriers; template class BaseDataFacade; } -class OSRM::OSRM_impl final +class Engine final { private: using PluginMap = std::unordered_map>; public: - OSRM_impl(LibOSRMConfig &lib_config); - OSRM_impl(const OSRM_impl &) = delete; + Engine(EngineConfig &config_); + Engine(const Engine &) = delete; int RunQuery(const RouteParameters &route_parameters, util::json::Object &json_result); private: void RegisterPlugin(plugins::BasePlugin *plugin); PluginMap plugin_map; // will only be initialized if shared memory is used - std::unique_ptr barrier; + std::unique_ptr barrier; // base class pointer to the objects datafacade::BaseDataFacade *query_data_facade; diff --git a/include/osrm/libosrm_config.hpp b/include/engine/engine_config.hpp similarity index 94% rename from include/osrm/libosrm_config.hpp rename to include/engine/engine_config.hpp index 743c682254b..d16f3f4ceec 100644 --- a/include/osrm/libosrm_config.hpp +++ b/include/engine/engine_config.hpp @@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LIBOSRM_CONFIG_HPP -#define LIBOSRM_CONFIG_HPP +#ifndef ENGINE_CONFIG_HPP +#define ENGINE_CONFIG_HPP #include @@ -36,7 +36,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace osrm { -struct LibOSRMConfig +namespace engine +{ + +struct EngineConfig { std::unordered_map server_paths; int max_locations_trip = -1; @@ -45,6 +48,8 @@ struct LibOSRMConfig int max_locations_map_matching = -1; bool use_shared_memory = true; }; + +} } #endif // SERVER_CONFIG_HPP diff --git a/include/engine/phantom_node.hpp b/include/engine/phantom_node.hpp index 1c258b8efdf..ca9b685c28f 100644 --- a/include/engine/phantom_node.hpp +++ b/include/engine/phantom_node.hpp @@ -30,9 +30,63 @@ struct PhantomNode util::FixedPointCoordinate &location, unsigned short fwd_segment_position, extractor::TravelMode forward_travel_mode, - extractor::TravelMode backward_travel_mode); + extractor::TravelMode backward_travel_mode) + : forward_node_id(forward_node_id), reverse_node_id(reverse_node_id), name_id(name_id), + forward_weight(forward_weight), reverse_weight(reverse_weight), + forward_offset(forward_offset), reverse_offset(reverse_offset), + packed_geometry_id(packed_geometry_id), component{component_id, is_tiny_component}, + location(location), fwd_segment_position(fwd_segment_position), + forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode) + { + } + + PhantomNode() + : forward_node_id(SPECIAL_NODEID), reverse_node_id(SPECIAL_NODEID), + name_id(std::numeric_limits::max()), forward_weight(INVALID_EDGE_WEIGHT), + reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0), + packed_geometry_id(SPECIAL_EDGEID), component{INVALID_COMPONENTID, false}, + fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), + backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) + { + } + + int GetForwardWeightPlusOffset() const + { + if (SPECIAL_NODEID == forward_node_id) + { + return 0; + } + return forward_offset + forward_weight; + } + + int GetReverseWeightPlusOffset() const + { + if (SPECIAL_NODEID == reverse_node_id) + { + return 0; + } + return reverse_offset + reverse_weight; + } + + bool IsBidirected() const + { + return (forward_node_id != SPECIAL_NODEID) && (reverse_node_id != SPECIAL_NODEID); + } + + bool IsCompressed() const { return (forward_offset != 0) || (reverse_offset != 0); } - PhantomNode(); + bool IsValid(const unsigned number_of_nodes) const + { + return location.IsValid() && + ((forward_node_id < number_of_nodes) || (reverse_node_id < number_of_nodes)) && + ((forward_weight != INVALID_EDGE_WEIGHT) || + (reverse_weight != INVALID_EDGE_WEIGHT)) && + (component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID); + } + + bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); } + + bool operator==(const PhantomNode &other) const { return location == other.location; } template PhantomNode(const OtherT &other, const util::FixedPointCoordinate &foot_point) @@ -82,20 +136,6 @@ struct PhantomNode // but the saved byte would be padding anyway extractor::TravelMode forward_travel_mode; extractor::TravelMode backward_travel_mode; - - int GetForwardWeightPlusOffset() const; - - int GetReverseWeightPlusOffset() const; - - bool IsBidirected() const; - - bool IsCompressed() const; - - bool is_valid(const unsigned numberOfNodes) const; - - bool IsValid() const; - - bool operator==(const PhantomNode &other) const; }; #ifndef _MSC_VER diff --git a/include/engine/plugins/distance_table.hpp b/include/engine/plugins/distance_table.hpp index 1a37cfd065b..0f607ba57b8 100644 --- a/include/engine/plugins/distance_table.hpp +++ b/include/engine/plugins/distance_table.hpp @@ -96,7 +96,7 @@ template class DistanceTablePlugin final : public BasePlugin { PhantomNode current_phantom_node; ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node); - if (current_phantom_node.is_valid(facade->GetNumberOfNodes())) + if (current_phantom_node.IsValid(facade->GetNumberOfNodes())) { if (route_parameters.is_source[i]) { @@ -130,7 +130,7 @@ template class DistanceTablePlugin final : public BasePlugin facade->NearestPhantomNodeWithAlternativeFromBigComponent( route_parameters.coordinates[i], bearing, range); // we didn't found a fitting node, return error - if (!phantom_node_source_out_iter->first.is_valid(facade->GetNumberOfNodes())) + if (!phantom_node_source_out_iter->first.IsValid(facade->GetNumberOfNodes())) { json_result.values["status_message"] = std::string("Could not find a matching segment for coordinate ") + @@ -153,7 +153,7 @@ template class DistanceTablePlugin final : public BasePlugin facade->NearestPhantomNodeWithAlternativeFromBigComponent( route_parameters.coordinates[i], bearing, range); // we didn't found a fitting node, return error - if (!phantom_node_target_out_iter->first.is_valid(facade->GetNumberOfNodes())) + if (!phantom_node_target_out_iter->first.IsValid(facade->GetNumberOfNodes())) { json_result.values["status_message"] = std::string("Could not find a matching segment for coordinate ") + diff --git a/include/engine/plugins/trip.hpp b/include/engine/plugins/trip.hpp index 45a436dbf21..db84405479c 100644 --- a/include/engine/plugins/trip.hpp +++ b/include/engine/plugins/trip.hpp @@ -66,7 +66,7 @@ template class RoundTripPlugin final : public BasePlugin { PhantomNode current_phantom_node; ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node); - if (current_phantom_node.is_valid(facade->GetNumberOfNodes())) + if (current_phantom_node.IsValid(facade->GetNumberOfNodes())) { phantom_node_list.push_back(std::move(current_phantom_node)); continue; @@ -83,7 +83,7 @@ template class RoundTripPlugin final : public BasePlugin break; } phantom_node_list.push_back(std::move(results.front().phantom_node)); - BOOST_ASSERT(phantom_node_list.back().is_valid(facade->GetNumberOfNodes())); + BOOST_ASSERT(phantom_node_list.back().IsValid(facade->GetNumberOfNodes())); } return phantom_node_list; diff --git a/include/engine/plugins/viaroute.hpp b/include/engine/plugins/viaroute.hpp index 49768df109d..b3d8bb00f1c 100644 --- a/include/engine/plugins/viaroute.hpp +++ b/include/engine/plugins/viaroute.hpp @@ -85,7 +85,7 @@ template class ViaRoutePlugin final : public BasePlugin { ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_pair_list[i].first); - if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) + if (phantom_node_pair_list[i].first.IsValid(facade->GetNumberOfNodes())) { continue; } @@ -97,15 +97,15 @@ template class ViaRoutePlugin final : public BasePlugin phantom_node_pair_list[i] = facade->NearestPhantomNodeWithAlternativeFromBigComponent( route_parameters.coordinates[i], bearing, range); // we didn't found a fitting node, return error - if (!phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())) + if (!phantom_node_pair_list[i].first.IsValid(facade->GetNumberOfNodes())) { json_result.values["status_message"] = std::string("Could not find a matching segment for coordinate ") + std::to_string(i); return Status::NoSegment; } - BOOST_ASSERT(phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes())); - BOOST_ASSERT(phantom_node_pair_list[i].second.is_valid(facade->GetNumberOfNodes())); + BOOST_ASSERT(phantom_node_pair_list[i].first.IsValid(facade->GetNumberOfNodes())); + BOOST_ASSERT(phantom_node_pair_list[i].second.IsValid(facade->GetNumberOfNodes())); } auto snapped_phantoms = snapPhantomNodes(phantom_node_pair_list); diff --git a/include/engine/route_parameters.hpp b/include/engine/route_parameters.hpp new file mode 100644 index 00000000000..e808880ec7a --- /dev/null +++ b/include/engine/route_parameters.hpp @@ -0,0 +1,125 @@ +/* + +Copyright (c) 2016, 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. + +*/ + +#ifndef ROUTE_PARAMETERS_HPP +#define ROUTE_PARAMETERS_HPP + +#include "osrm/coordinate.hpp" + +#include +#include + +#include +#include + +namespace osrm +{ +namespace engine +{ + +struct RouteParameters +{ + RouteParameters(); + + void SetZoomLevel(const short level); + + void SetNumberOfResults(const short number); + + void SetAlternateRouteFlag(const bool flag); + + void SetUTurn(const bool flag); + + void SetAllUTurns(const bool flag); + + void SetClassify(const bool classify); + + void SetMatchingBeta(const double beta); + + void SetGPSPrecision(const double precision); + + void SetDeprecatedAPIFlag(const std::string &); + + void SetChecksum(const unsigned check_sum); + + void SetInstructionFlag(const bool flag); + + void SetService(const std::string &service); + + void SetOutputFormat(const std::string &format); + + void SetJSONpParameter(const std::string ¶meter); + + void AddHint(const std::string &hint); + + void AddTimestamp(const unsigned timestamp); + + void AddBearing(const boost::fusion::vector> &received_bearing, + boost::spirit::qi::unused_type unused, + bool &pass); + + void SetLanguage(const std::string &language); + + void SetGeometryFlag(const bool flag); + + void SetCompressionFlag(const bool flag); + + void AddCoordinate(const boost::fusion::vector &received_coordinates); + + void AddDestination(const boost::fusion::vector &received_coordinates); + + void AddSource(const boost::fusion::vector &received_coordinates); + + void SetCoordinatesFromGeometry(const std::string &geometry_string); + + short zoom_level; + bool print_instructions; + bool alternate_route; + bool geometry; + bool compression; + bool deprecatedAPI; + bool uturn_default; + bool classify; + double matching_beta; + double gps_precision; + unsigned check_sum; + short num_results; + std::string service; + std::string output_format; + std::string jsonp_parameter; + std::string language; + std::vector hints; + std::vector timestamps; + std::vector>> bearings; + std::vector uturns; + std::vector coordinates; + std::vector is_destination; + std::vector is_source; +}; +} +} + +#endif // ROUTE_PARAMETERS_HPP diff --git a/include/extractor/external_memory_node.hpp b/include/extractor/external_memory_node.hpp index a4f9ca94178..6658a7e6e88 100644 --- a/include/extractor/external_memory_node.hpp +++ b/include/extractor/external_memory_node.hpp @@ -12,13 +12,23 @@ namespace extractor struct ExternalMemoryNode : QueryNode { - ExternalMemoryNode(int lat, int lon, OSMNodeID id, bool barrier, bool traffic_light); + ExternalMemoryNode(int lat, int lon, OSMNodeID node_id, bool barrier, bool traffic_lights) + : QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights) + { + } - ExternalMemoryNode(); + ExternalMemoryNode() : barrier(false), traffic_lights(false) {} - static ExternalMemoryNode min_value(); + static ExternalMemoryNode min_value() + { + return ExternalMemoryNode(0, 0, MIN_OSM_NODEID, false, false); + } - static ExternalMemoryNode max_value(); + static ExternalMemoryNode max_value() + { + return ExternalMemoryNode(std::numeric_limits::max(), std::numeric_limits::max(), + MAX_OSM_NODEID, false, false); + } bool barrier; bool traffic_lights; @@ -27,9 +37,12 @@ struct ExternalMemoryNode : QueryNode struct ExternalMemoryNodeSTXXLCompare { using value_type = ExternalMemoryNode; - bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const; - value_type max_value(); - value_type min_value(); + value_type max_value() { return value_type::max_value(); } + value_type min_value() { return value_type::min_value(); } + bool operator()(const value_type &left, const value_type &right) const + { + return left.node_id < right.node_id; + } }; } } diff --git a/include/extractor/extractor.hpp b/include/extractor/extractor.hpp index 72e5be8b746..2255d2b621b 100644 --- a/include/extractor/extractor.hpp +++ b/include/extractor/extractor.hpp @@ -2,7 +2,7 @@ #define EXTRACTOR_HPP #include "extractor/edge_based_edge.hpp" -#include "extractor/extractor_options.hpp" +#include "extractor/extractor_config.hpp" #include "extractor/edge_based_graph_factory.hpp" #include "extractor/graph_compressor.hpp" diff --git a/include/extractor/extractor_config.hpp b/include/extractor/extractor_config.hpp new file mode 100644 index 00000000000..8e44f5e2e02 --- /dev/null +++ b/include/extractor/extractor_config.hpp @@ -0,0 +1,78 @@ +#ifndef EXTRACTOR_CONFIG_HPP +#define EXTRACTOR_CONFIG_HPP + +#include + +#include +#include + +namespace osrm +{ +namespace extractor +{ + +struct ExtractorConfig +{ + ExtractorConfig() noexcept : requested_num_threads(0) {} + void UseDefaultOutputNames() + { + std::string basepath = input_path.string(); + + auto pos = std::string::npos; + std::array known_extensions{ + {".osm.bz2", ".osm.pbf", ".osm.xml", ".pbf", ".osm"}}; + for (auto ext : known_extensions) + { + pos = basepath.find(ext); + if (pos != std::string::npos) + { + basepath.replace(pos, ext.size(), ""); + break; + } + } + + output_file_name = basepath + ".osrm"; + restriction_file_name = basepath + ".osrm.restrictions"; + names_file_name = basepath + ".osrm.names"; + timestamp_file_name = basepath + ".osrm.timestamp"; + geometry_output_path = basepath + ".osrm.geometry"; + node_output_path = basepath + ".osrm.nodes"; + edge_output_path = basepath + ".osrm.edges"; + edge_graph_output_path = basepath + ".osrm.ebg"; + rtree_nodes_output_path = basepath + ".osrm.ramIndex"; + rtree_leafs_output_path = basepath + ".osrm.fileIndex"; + edge_segment_lookup_path = basepath + ".osrm.edge_segment_lookup"; + edge_penalty_path = basepath + ".osrm.edge_penalties"; + edge_based_node_weights_output_path = basepath + ".osrm.enw"; + } + + boost::filesystem::path config_file_path; + boost::filesystem::path input_path; + boost::filesystem::path profile_path; + + std::string output_file_name; + std::string restriction_file_name; + std::string names_file_name; + std::string timestamp_file_name; + std::string geometry_output_path; + std::string edge_output_path; + std::string edge_graph_output_path; + std::string edge_based_node_weights_output_path; + std::string node_output_path; + std::string rtree_nodes_output_path; + std::string rtree_leafs_output_path; + + unsigned requested_num_threads; + unsigned small_component_size; + + bool generate_edge_lookup; + std::string edge_penalty_path; + std::string edge_segment_lookup_path; +#ifdef DEBUG_GEOMETRY + std::string debug_turns_path; +#endif +}; +} +} + +#endif // EXTRACTOR_CONFIG_HPP diff --git a/include/extractor/extractor_options.hpp b/include/extractor/extractor_options.hpp deleted file mode 100644 index 57f79c1eceb..00000000000 --- a/include/extractor/extractor_options.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef EXTRACTOR_OPTIONS_HPP -#define EXTRACTOR_OPTIONS_HPP - -#include - -#include - -namespace osrm -{ -namespace extractor -{ - -enum class return_code : unsigned -{ - ok, - fail, - exit -}; - -struct ExtractorConfig -{ - ExtractorConfig() : requested_num_threads(0) {} - boost::filesystem::path config_file_path; - boost::filesystem::path input_path; - boost::filesystem::path profile_path; - - std::string output_file_name; - std::string restriction_file_name; - std::string names_file_name; - std::string timestamp_file_name; - std::string geometry_output_path; - std::string edge_output_path; - std::string edge_graph_output_path; - std::string node_output_path; - std::string rtree_nodes_output_path; - std::string rtree_leafs_output_path; - - // every edge based node represents a segment in the original graph. During contraciton we need - // to know about this segment length, as we might have to add self-loops in cases of shorter - // parts than the segment represents itself - std::string edge_based_node_weights_output_path; - - unsigned requested_num_threads; - unsigned small_component_size; - - bool generate_edge_lookup; - std::string edge_penalty_path; - std::string edge_segment_lookup_path; -#ifdef DEBUG_GEOMETRY - std::string debug_turns_path; -#endif -}; - -struct ExtractorOptions -{ - static return_code ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config); - - static void GenerateOutputFilesNames(ExtractorConfig &extractor_config); -}; -} -} - -#endif // EXTRACTOR_OPTIONS_HPP diff --git a/include/osrm/coordinate.hpp b/include/osrm/coordinate.hpp index e1c7fef7d3c..34fbb5e260d 100644 --- a/include/osrm/coordinate.hpp +++ b/include/osrm/coordinate.hpp @@ -1,72 +1,11 @@ -/* +#ifndef GLOBAL_COORDINATE_HPP +#define GLOBAL_COORDINATE_HPP -Copyright (c) 2016, 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. - -*/ - -#ifndef COORDINATE_HPP_ -#define COORDINATE_HPP_ - -#include //for std::ostream -#include -#include +#include "util/coordinate.hpp" namespace osrm { - -constexpr static const double COORDINATE_PRECISION = 1000000.0; - -namespace util -{ - -struct FixedPointCoordinate -{ - int lat; - int lon; - - FixedPointCoordinate(); - FixedPointCoordinate(int lat, int lon); - - template - FixedPointCoordinate(const T &coordinate) - : lat(coordinate.lat), lon(coordinate.lon) - { - static_assert(std::is_same::value, - "coordinate types incompatible"); - static_assert(std::is_same::value, - "coordinate types incompatible"); - } - - bool IsValid() const; - bool operator==(const FixedPointCoordinate &other) const; - friend std::ostream &operator<<(std::ostream &out, const FixedPointCoordinate &coordinate); -}; - -std::ostream &operator<<(std::ostream &out, const FixedPointCoordinate &coordinate); -} - -using util::FixedPointCoordinate; + using util::FixedPointCoordinate; } -#endif /* COORDINATE_HPP_ */ +#endif diff --git a/include/osrm/engine_config.hpp b/include/osrm/engine_config.hpp new file mode 100644 index 00000000000..6c10e944199 --- /dev/null +++ b/include/osrm/engine_config.hpp @@ -0,0 +1,12 @@ +#ifndef GLOBAL_ENGINE_CONFIG_HPP +#define GLOBAL_ENGINE_CONFIG_HPP + +#include "engine/engine_config.hpp" + +namespace osrm +{ + using engine::EngineConfig; +} + +#endif + diff --git a/include/osrm/json_container.hpp b/include/osrm/json_container.hpp index 7ab25d5448b..1b0787713bd 100644 --- a/include/osrm/json_container.hpp +++ b/include/osrm/json_container.hpp @@ -1,108 +1,8 @@ -/* - -Copyright (c) 2016, 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. - -*/ - -// based on -// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp - -#ifndef JSON_CONTAINER_HPP -#define JSON_CONTAINER_HPP - -#include - -#include -#include -#include -#include - +#ifndef GLOBAL_JSON_CONTAINER_HPP +#define GLOBAL_JSON_CONTAINER_HPP +#include "util/json_container.hpp" namespace osrm { - -namespace util -{ - -namespace json -{ - -struct Object; -struct Array; - -struct String -{ - String() {} - String(const char *value) : value(value) {} - String(std::string value) : value(std::move(value)) {} - std::string value; -}; - -struct Number -{ - Number() {} - Number(double value) : value(static_cast(value)) {} - double value; -}; - -struct True -{ -}; - -struct False -{ -}; - -struct Null -{ -}; - -using Value = mapbox::util::variant, - mapbox::util::recursive_wrapper, - True, - False, - Null>; - -struct Object -{ - std::unordered_map values; -}; - -struct Array -{ - std::vector values; -}; - -} // namespace JSON -} // namespace util - -namespace json -{ -using namespace osrm::util::json; + namespace json = osrm::util::json; } - -} // namespace osrm - -#endif // JSON_CONTAINER_HPP +#endif diff --git a/include/osrm/osrm.hpp b/include/osrm/osrm.hpp index 3f3e553339a..a1594b90250 100644 --- a/include/osrm/osrm.hpp +++ b/include/osrm/osrm.hpp @@ -45,21 +45,26 @@ struct Object; namespace engine { +class Engine; +struct EngineConfig; struct RouteParameters; +} + +using engine::EngineConfig; +using engine::RouteParameters; +namespace json = util::json; + class OSRM { private: - class OSRM_impl; - std::unique_ptr OSRM_pimpl_; + std::unique_ptr engine_; public: - OSRM(LibOSRMConfig &lib_config); + OSRM(EngineConfig &lib_config); ~OSRM(); // needed because we need to define it with the implementation of OSRM_impl - int RunQuery(const RouteParameters &route_parameters, util::json::Object &json_result); + int RunQuery(const RouteParameters &route_parameters, json::Object &json_result); }; -} -using engine::OSRM; } #endif // OSRM_HPP diff --git a/include/osrm/route_parameters.hpp b/include/osrm/route_parameters.hpp index 53c8629e710..57c884d5f71 100644 --- a/include/osrm/route_parameters.hpp +++ b/include/osrm/route_parameters.hpp @@ -1,127 +1,11 @@ -/* +#ifndef GLOBAL_ROUTE_PARAMETERS_HPP +#define GLOBAL_ROUTE_PARAMETERS_HPP -Copyright (c) 2016, 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. - -*/ - -#ifndef ROUTE_PARAMETERS_HPP -#define ROUTE_PARAMETERS_HPP - -#include "coordinate.hpp" - -#include -#include - -#include -#include +#include "engine/route_parameters.hpp" namespace osrm { -namespace engine -{ - -struct RouteParameters -{ - RouteParameters(); - - void SetZoomLevel(const short level); - - void SetNumberOfResults(const short number); - - void SetAlternateRouteFlag(const bool flag); - - void SetUTurn(const bool flag); - - void SetAllUTurns(const bool flag); - - void SetClassify(const bool classify); - - void SetMatchingBeta(const double beta); - - void SetGPSPrecision(const double precision); - - void SetDeprecatedAPIFlag(const std::string &); - - void SetChecksum(const unsigned check_sum); - - void SetInstructionFlag(const bool flag); - - void SetService(const std::string &service); - - void SetOutputFormat(const std::string &format); - - void SetJSONpParameter(const std::string ¶meter); - - void AddHint(const std::string &hint); - - void AddTimestamp(const unsigned timestamp); - - void AddBearing(const boost::fusion::vector> &received_bearing, - boost::spirit::qi::unused_type unused, - bool &pass); - - void SetLanguage(const std::string &language); - - void SetGeometryFlag(const bool flag); - - void SetCompressionFlag(const bool flag); - - void AddCoordinate(const boost::fusion::vector &received_coordinates); - - void AddDestination(const boost::fusion::vector &received_coordinates); - - void AddSource(const boost::fusion::vector &received_coordinates); - - void SetCoordinatesFromGeometry(const std::string &geometry_string); - - short zoom_level; - bool print_instructions; - bool alternate_route; - bool geometry; - bool compression; - bool deprecatedAPI; - bool uturn_default; - bool classify; - double matching_beta; - double gps_precision; - unsigned check_sum; - short num_results; - std::string service; - std::string output_format; - std::string jsonp_parameter; - std::string language; - std::vector hints; - std::vector timestamps; - std::vector>> bearings; - std::vector uturns; - std::vector coordinates; - std::vector is_destination; - std::vector is_source; -}; -} - -using engine::RouteParameters; + using engine::RouteParameters; } -#endif // ROUTE_PARAMETERS_HPP +#endif diff --git a/include/server/request_handler.hpp b/include/server/request_handler.hpp index 900370a8ac0..eba77eac721 100644 --- a/include/server/request_handler.hpp +++ b/include/server/request_handler.hpp @@ -5,9 +5,9 @@ namespace osrm { +class OSRM; namespace engine { -class OSRM; struct RouteParameters; } namespace server @@ -30,10 +30,10 @@ class RequestHandler RequestHandler(const RequestHandler &) = delete; void handle_request(const http::request ¤t_request, http::reply ¤t_reply); - void RegisterRoutingMachine(engine::OSRM *osrm); + void RegisterRoutingMachine(OSRM *osrm); private: - engine::OSRM *routing_machine; + OSRM *routing_machine; }; } } diff --git a/include/engine/datafacade/shared_barriers.hpp b/include/storage/shared_barriers.hpp similarity index 96% rename from include/engine/datafacade/shared_barriers.hpp rename to include/storage/shared_barriers.hpp index e22e27ea4d2..48d305c79a7 100644 --- a/include/engine/datafacade/shared_barriers.hpp +++ b/include/storage/shared_barriers.hpp @@ -6,11 +6,8 @@ namespace osrm { -namespace engine +namespace storage { -namespace datafacade -{ - struct SharedBarriers { @@ -38,6 +35,5 @@ struct SharedBarriers }; } } -} #endif // SHARED_BARRIERS_HPP diff --git a/include/engine/datafacade/shared_datatype.hpp b/include/storage/shared_datatype.hpp similarity index 53% rename from include/engine/datafacade/shared_datatype.hpp rename to include/storage/shared_datatype.hpp index ab3004df6ed..69e409e42f9 100644 --- a/include/engine/datafacade/shared_datatype.hpp +++ b/include/storage/shared_datatype.hpp @@ -10,9 +10,7 @@ namespace osrm { -namespace engine -{ -namespace datafacade +namespace storage { // Added at the start and end of each block as sanity check @@ -48,46 +46,6 @@ struct SharedDataLayout SharedDataLayout() : num_entries(), entry_size() {} - void PrintInformation() const - { - util::SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " - << ": " << GetBlockSize(NAME_OFFSETS); - util::SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " - << ": " << GetBlockSize(NAME_BLOCKS); - util::SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " - << ": " << GetBlockSize(NAME_CHAR_LIST); - util::SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " - << ": " << GetBlockSize(NAME_ID_LIST); - util::SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " - << ": " << GetBlockSize(VIA_NODE_LIST); - util::SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " - << ": " << GetBlockSize(GRAPH_NODE_LIST); - util::SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " - << ": " << GetBlockSize(GRAPH_EDGE_LIST); - util::SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " - << ": " << GetBlockSize(COORDINATE_LIST); - util::SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " - << ": " << GetBlockSize(TURN_INSTRUCTION); - util::SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " - << ": " << GetBlockSize(TRAVEL_MODE); - util::SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " - << ": " << GetBlockSize(R_SEARCH_TREE); - util::SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " - << ": " << GetBlockSize(GEOMETRIES_INDEX); - util::SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " - << ": " << GetBlockSize(GEOMETRIES_LIST); - util::SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" - << ": " << GetBlockSize(GEOMETRIES_INDICATORS); - util::SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " - << ": " << GetBlockSize(HSGR_CHECKSUM); - util::SimpleLogger().Write(logDEBUG) << "TIMESTAMP " - << ": " << GetBlockSize(TIMESTAMP); - util::SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " - << ": " << GetBlockSize(FILE_INDEX_PATH); - util::SimpleLogger().Write(logDEBUG) << "CORE_MARKER " - << ": " << GetBlockSize(CORE_MARKER); - } - template inline void SetBlockSize(BlockID bid, uint64_t entries) { num_entries[bid] = entries; @@ -170,6 +128,5 @@ struct SharedDataTimestamp }; } } -} #endif /* SHARED_DATA_TYPE_HPP */ diff --git a/include/datastore/shared_memory_factory.hpp b/include/storage/shared_memory.hpp similarity index 85% rename from include/datastore/shared_memory_factory.hpp rename to include/storage/shared_memory.hpp index ae8e11ee538..3b04d2e32a8 100644 --- a/include/datastore/shared_memory_factory.hpp +++ b/include/storage/shared_memory.hpp @@ -1,5 +1,5 @@ -#ifndef SHARED_MEMORY_FACTORY_HPP -#define SHARED_MEMORY_FACTORY_HPP +#ifndef SHARED_MEMORY_HPP +#define SHARED_MEMORY_HPP #include "util/osrm_exception.hpp" #include "util/simple_logger.hpp" @@ -26,7 +26,7 @@ namespace osrm { -namespace datastore +namespace storage { struct OSRMLockFile @@ -322,47 +322,37 @@ class SharedMemory }; #endif -template class SharedMemoryFactory_tmpl +template +SharedMemory *makeSharedMemory(const IdentifierT &id, + const uint64_t size = 0, + bool read_write = false, + bool remove_prev = true) { - public: - template - static SharedMemory *Get(const IdentifierT &id, - const uint64_t size = 0, - bool read_write = false, - bool remove_prev = true) + try + { + LockFileT lock_file; + if (!boost::filesystem::exists(lock_file())) { - try - { - LockFileT lock_file; - if (!boost::filesystem::exists(lock_file())) - { - if (0 == size) - { - throw util::exception("lock file does not exist, exiting"); - } - else - { - boost::filesystem::ofstream ofs(lock_file()); - ofs.close(); - } - } - return new SharedMemory(lock_file(), id, size, read_write, remove_prev); - } - catch (const boost::interprocess::interprocess_exception &e) - { - util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code " - << e.get_error_code(); - throw util::exception(e.what()); - } + if (0 == size) + { + throw util::exception("lock file does not exist, exiting"); + } + else + { + boost::filesystem::ofstream ofs(lock_file()); + } } + return new SharedMemory(lock_file(), id, size, read_write, remove_prev); + } + catch (const boost::interprocess::interprocess_exception &e) + { + util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code " + << e.get_error_code(); + throw util::exception(e.what()); + } +} - SharedMemoryFactory_tmpl() = delete; - SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete; - SharedMemoryFactory_tmpl &operator=(const SharedMemoryFactory_tmpl &) = delete; -}; - -using SharedMemoryFactory = SharedMemoryFactory_tmpl<>; } } -#endif // SHARED_MEMORY_FACTORY_HPP +#endif // SHARED_MEMORY_HPP diff --git a/include/storage/storage.hpp b/include/storage/storage.hpp new file mode 100644 index 00000000000..0b63b32d1e2 --- /dev/null +++ b/include/storage/storage.hpp @@ -0,0 +1,25 @@ +#ifndef STORAGE_HPP +#define STORAGE_HPP + +#include + +#include +#include + +namespace osrm +{ +namespace storage +{ +using DataPaths = std::unordered_map; +class Storage +{ +public: + Storage(const DataPaths& data_paths); + int Run(); +private: + DataPaths paths; +}; +} +} + +#endif diff --git a/include/util/coordinate.hpp b/include/util/coordinate.hpp new file mode 100644 index 00000000000..ca6b26e71c7 --- /dev/null +++ b/include/util/coordinate.hpp @@ -0,0 +1,71 @@ +/* + +Copyright (c) 2016, 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. + +*/ + +#ifndef COORDINATE_HPP_ +#define COORDINATE_HPP_ + +#include //for std::ostream +#include +#include + +namespace osrm +{ + +constexpr const double COORDINATE_PRECISION = 1000000.0; + +namespace util +{ + +struct FixedPointCoordinate +{ + int lat; + int lon; + + FixedPointCoordinate(); + FixedPointCoordinate(int lat, int lon); + + template + FixedPointCoordinate(const T &coordinate) + : lat(coordinate.lat), lon(coordinate.lon) + { + static_assert(std::is_same::value, + "coordinate types incompatible"); + static_assert(std::is_same::value, + "coordinate types incompatible"); + } + + bool IsValid() const; + bool operator==(const FixedPointCoordinate &other) const; + friend std::ostream &operator<<(std::ostream &out, const FixedPointCoordinate &coordinate); +}; + +std::ostream &operator<<(std::ostream &out, const FixedPointCoordinate &coordinate); +} + +} + +#endif /* COORDINATE_HPP_ */ diff --git a/include/util/debug_geometry.hpp b/include/util/debug_geometry.hpp index 41a3ebc8d30..73e8291755d 100644 --- a/include/util/debug_geometry.hpp +++ b/include/util/debug_geometry.hpp @@ -1,7 +1,7 @@ #ifndef DEBUG_GEOMETRY_H #define DEBUG_GEOMETRY_H -#include "contractor/contractor_options.hpp" +#include "contractor/contractor_config.hpp" #include "extractor/query_node.hpp" #ifndef DEBUG_GEOMETRY diff --git a/include/util/fingerprint.hpp b/include/util/fingerprint.hpp index df656cde169..e8238c0acd1 100644 --- a/include/util/fingerprint.hpp +++ b/include/util/fingerprint.hpp @@ -17,7 +17,7 @@ class FingerPrint const boost::uuids::uuid &GetFingerPrint() const; bool IsMagicNumberOK(const FingerPrint &other) const; bool TestGraphUtil(const FingerPrint &other) const; - bool TestPrepare(const FingerPrint &other) const; + bool TestContractor(const FingerPrint &other) const; bool TestRTree(const FingerPrint &other) const; bool TestQueryObjects(const FingerPrint &other) const; diff --git a/include/util/fingerprint_impl.hpp.in b/include/util/fingerprint_impl.hpp.in index f391e4ca22e..1a52269d176 100644 --- a/include/util/fingerprint_impl.hpp.in +++ b/include/util/fingerprint_impl.hpp.in @@ -62,7 +62,7 @@ bool FingerPrint::TestGraphUtil(const FingerPrint &other) const return std::equal(md5_graph, md5_graph + 32, other.md5_graph); } -bool FingerPrint::TestPrepare(const FingerPrint &other) const +bool FingerPrint::TestContractor(const FingerPrint &other) const { if (!IsMagicNumberOK(other)) { diff --git a/include/util/graph_loader.hpp b/include/util/graph_loader.hpp index 91a7f7e77dd..224fb375b14 100644 --- a/include/util/graph_loader.hpp +++ b/include/util/graph_loader.hpp @@ -39,7 +39,7 @@ unsigned loadRestrictionsFromFile(std::istream &input_stream, FingerPrint fingerprint_loaded; unsigned number_of_usable_restrictions = 0; input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint)); - if (!fingerprint_loaded.TestPrepare(fingerprint_valid)) + if (!fingerprint_loaded.TestContractor(fingerprint_valid)) { SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n" "Reprocess to get rid of this warning."; @@ -71,7 +71,7 @@ NodeID loadNodesFromFile(std::istream &input_stream, FingerPrint fingerprint_loaded; input_stream.read(reinterpret_cast(&fingerprint_loaded), sizeof(FingerPrint)); - if (!fingerprint_loaded.TestPrepare(fingerprint_valid)) + if (!fingerprint_loaded.TestContractor(fingerprint_valid)) { SimpleLogger().Write(logWARNING) << ".osrm was prepared with different build.\n" "Reprocess to get rid of this warning."; diff --git a/include/util/io.hpp b/include/util/io.hpp index b7951032cc6..70ab64a1bca 100644 --- a/include/util/io.hpp +++ b/include/util/io.hpp @@ -33,7 +33,7 @@ inline bool readAndCheckFingerprint(std::istream &stream) stream.read(reinterpret_cast(&fingerprint), sizeof(fingerprint)); // compare the compilation state stored in the fingerprint return static_cast(stream) && valid.IsMagicNumberOK(fingerprint) && - valid.TestPrepare(fingerprint) && valid.TestGraphUtil(fingerprint) && + valid.TestContractor(fingerprint) && valid.TestGraphUtil(fingerprint) && valid.TestRTree(fingerprint) && valid.TestQueryObjects(fingerprint); } diff --git a/include/util/json_container.hpp b/include/util/json_container.hpp new file mode 100644 index 00000000000..d3a9ca4a8f5 --- /dev/null +++ b/include/util/json_container.hpp @@ -0,0 +1,102 @@ +/* + +Copyright (c) 2016, 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. + +*/ + +// based on +// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp + +#ifndef JSON_CONTAINER_HPP +#define JSON_CONTAINER_HPP + +#include + +#include +#include +#include +#include + +namespace osrm +{ + +namespace util +{ + +namespace json +{ + +struct Object; +struct Array; + +struct String +{ + String() {} + String(const char *value) : value(value) {} + String(std::string value) : value(std::move(value)) {} + std::string value; +}; + +struct Number +{ + Number() {} + Number(double value) : value(static_cast(value)) {} + double value; +}; + +struct True +{ +}; + +struct False +{ +}; + +struct Null +{ +}; + +using Value = mapbox::util::variant, + mapbox::util::recursive_wrapper, + True, + False, + Null>; + +struct Object +{ + std::unordered_map values; +}; + +struct Array +{ + std::vector values; +}; + +} // namespace JSON +} // namespace util +} // namespace osrm + +#endif // JSON_CONTAINER_HPP diff --git a/include/util/range_table.hpp b/include/util/range_table.hpp index f06df1def1e..e31697b9d7e 100644 --- a/include/util/range_table.hpp +++ b/include/util/range_table.hpp @@ -2,7 +2,6 @@ #define RANGE_TABLE_HPP #include "util/integer_range.hpp" -#include "datastore/shared_memory_factory.hpp" #include "util/shared_memory_vector_wrapper.hpp" #include diff --git a/include/util/static_rtree.hpp b/include/util/static_rtree.hpp index 3a415e3b61f..3aea1794350 100644 --- a/include/util/static_rtree.hpp +++ b/include/util/static_rtree.hpp @@ -4,7 +4,6 @@ #include "util/deallocating_vector.hpp" #include "util/hilbert_value.hpp" #include "util/rectangle.hpp" -#include "datastore/shared_memory_factory.hpp" #include "util/shared_memory_vector_wrapper.hpp" #include "util/bearing.hpp" diff --git a/include/osrm/strong_typedef.hpp b/include/util/strong_typedef.hpp similarity index 69% rename from include/osrm/strong_typedef.hpp rename to include/util/strong_typedef.hpp index f33932a38a6..58e70602fc0 100644 --- a/include/osrm/strong_typedef.hpp +++ b/include/util/strong_typedef.hpp @@ -1,32 +1,5 @@ -#ifndef OSRM_STRONG_TYPEDEF_HPP -#define OSRM_STRONG_TYPEDEF_HPP - -/* - -Copyright (c) 2016, 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. - -*/ +#ifndef STRONG_TYPEDEF_HPP +#define STRONG_TYPEDEF_HPP #include #include diff --git a/include/util/typedefs.hpp b/include/util/typedefs.hpp index 243f04ed65b..614e7ebd615 100644 --- a/include/util/typedefs.hpp +++ b/include/util/typedefs.hpp @@ -1,7 +1,7 @@ #ifndef TYPEDEFS_H #define TYPEDEFS_H -#include "osrm/strong_typedef.hpp" +#include "util/strong_typedef.hpp" #include #include diff --git a/src/contractor/processing_chain.cpp b/src/contractor/contractor.cpp similarity index 94% rename from src/contractor/processing_chain.cpp rename to src/contractor/contractor.cpp index a28f347a1a1..6b01c564a49 100644 --- a/src/contractor/processing_chain.cpp +++ b/src/contractor/contractor.cpp @@ -1,5 +1,5 @@ -#include "contractor/processing_chain.hpp" #include "contractor/contractor.hpp" +#include "contractor/graph_contractor.hpp" #include "extractor/edge_based_edge.hpp" @@ -51,9 +51,7 @@ namespace osrm namespace contractor { -Prepare::~Prepare() {} - -int Prepare::Run() +int Contractor::Run() { #ifdef WIN32 #pragma message("Memory consumption on Windows can be higher due to different bit packing") @@ -95,9 +93,13 @@ int Prepare::Run() std::vector node_weights; std::string node_file_name = config.osrm_input_path.string() + ".enw"; if (util::deserializeVector(node_file_name, node_weights)) + { util::SimpleLogger().Write() << "Done reading node weights."; + } else - util::SimpleLogger().Write() << "Failed reading node weights."; + { + throw util::exception("Failed reading node weights."); + } util::DeallocatingVector contracted_edge_list; ContractGraph(max_edge_id, edge_based_edge_list, contracted_edge_list, std::move(node_weights), @@ -125,7 +127,7 @@ int Prepare::Run() return 0; } -std::size_t Prepare::LoadEdgeExpandedGraph( +std::size_t Contractor::LoadEdgeExpandedGraph( std::string const &edge_based_graph_filename, util::DeallocatingVector &edge_based_edge_list, const std::string &edge_segment_lookup_filename, @@ -154,7 +156,7 @@ std::size_t Prepare::LoadEdgeExpandedGraph( const util::FingerPrint fingerprint_valid = util::FingerPrint::GetValid(); util::FingerPrint fingerprint_loaded; input_stream.read((char *)&fingerprint_loaded, sizeof(util::FingerPrint)); - fingerprint_loaded.TestPrepare(fingerprint_valid); + fingerprint_loaded.TestContractor(fingerprint_valid); // TODO std::size_t can vary on systems. Our files are not transferable, but we might want to // consider using a fixed size type for I/O @@ -260,7 +262,7 @@ std::size_t Prepare::LoadEdgeExpandedGraph( return max_edge_id; } -void Prepare::ReadNodeLevels(std::vector &node_levels) const +void Contractor::ReadNodeLevels(std::vector &node_levels) const { boost::filesystem::ifstream order_input_stream(config.level_output_path, std::ios::binary); @@ -270,7 +272,7 @@ void Prepare::ReadNodeLevels(std::vector &node_levels) const order_input_stream.read((char *)node_levels.data(), sizeof(float) * node_levels.size()); } -void Prepare::WriteNodeLevels(std::vector &&in_node_levels) const +void Contractor::WriteNodeLevels(std::vector &&in_node_levels) const { std::vector node_levels(std::move(in_node_levels)); @@ -281,7 +283,7 @@ void Prepare::WriteNodeLevels(std::vector &&in_node_levels) const order_output_stream.write((char *)node_levels.data(), sizeof(float) * node_levels.size()); } -void Prepare::WriteCoreNodeMarker(std::vector &&in_is_core_node) const +void Contractor::WriteCoreNodeMarker(std::vector &&in_is_core_node) const { std::vector is_core_node(std::move(in_is_core_node)); std::vector unpacked_bool_flags(std::move(is_core_node.size())); @@ -299,7 +301,7 @@ void Prepare::WriteCoreNodeMarker(std::vector &&in_is_core_node) const } std::size_t -Prepare::WriteContractedGraph(unsigned max_node_id, +Contractor::WriteContractedGraph(unsigned max_node_id, const util::DeallocatingVector &contracted_edge_list) { // Sorting contracted edges in a way that the static query graph can read some in in-place. @@ -420,7 +422,7 @@ Prepare::WriteContractedGraph(unsigned max_node_id, /** \brief Build contracted graph. */ -void Prepare::ContractGraph( +void Contractor::ContractGraph( const unsigned max_edge_id, util::DeallocatingVector &edge_based_edge_list, util::DeallocatingVector &contracted_edge_list, @@ -431,15 +433,12 @@ void Prepare::ContractGraph( std::vector node_levels; node_levels.swap(inout_node_levels); - Contractor contractor(max_edge_id + 1, edge_based_edge_list, std::move(node_levels), + GraphContractor graph_contractor(max_edge_id + 1, edge_based_edge_list, std::move(node_levels), std::move(node_weights)); - contractor.Run(config.core_factor); - contractor.GetEdges(contracted_edge_list); - contractor.GetCoreMarker(is_core_node); - contractor.GetNodeLevels(inout_node_levels); - - std::cout << "Levels: " << inout_node_levels.size() << " Core: " << is_core_node.size() - << " MEID: " << max_edge_id << std::endl; + graph_contractor.Run(config.core_factor); + graph_contractor.GetEdges(contracted_edge_list); + graph_contractor.GetCoreMarker(is_core_node); + graph_contractor.GetNodeLevels(inout_node_levels); } } } diff --git a/src/contractor/contractor_options.cpp b/src/contractor/contractor_options.cpp deleted file mode 100644 index 51b8228b70a..00000000000 --- a/src/contractor/contractor_options.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "contractor/contractor_options.hpp" - -#include "util/simple_logger.hpp" -#include "util/version.hpp" - -#include -#include - -#include - -namespace osrm -{ -namespace contractor -{ - -return_code -ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &contractor_config) -{ - // declare a group of options that will be allowed only on command line - boost::program_options::options_description generic_options("Options"); - generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "config,c", - boost::program_options::value(&contractor_config.config_file_path) - ->default_value("contractor.ini"), - "Path to a configuration file."); - - // declare a group of options that will be allowed both on command line and in config file - boost::program_options::options_description config_options("Configuration"); - config_options.add_options()( - "profile,p", - boost::program_options::value(&contractor_config.profile_path) - ->default_value("profile.lua"), - "Path to LUA routing profile")( - "threads,t", - boost::program_options::value(&contractor_config.requested_num_threads) - ->default_value(tbb::task_scheduler_init::default_num_threads()), - "Number of threads to use")( - "core,k", - boost::program_options::value(&contractor_config.core_factor)->default_value(1.0), - "Percentage of the graph (in vertices) to contract [0..1]")( - "segment-speed-file", - boost::program_options::value(&contractor_config.segment_speed_lookup_path), - "Lookup file containing nodeA,nodeB,speed data to adjust edge weights")( - "level-cache,o", boost::program_options::value(&contractor_config.use_cached_priority) - ->default_value(false), - "Use .level file to retain the contaction level for each node from the last run."); - -#ifdef DEBUG_GEOMETRY - config_options.add_options()( - "debug-geometry", - boost::program_options::value(&contractor_config.debug_geometry_path), - "Write out edge-weight debugging geometry data in GeoJSON format to this file"); -#endif - - // hidden options, will be allowed both on command line and in config file, but will not be - // shown to the user - boost::program_options::options_description hidden_options("Hidden options"); - hidden_options.add_options()("input,i", boost::program_options::value( - &contractor_config.osrm_input_path), - "Input file in .osm, .osm.bz2 or .osm.pbf format"); - - // positional option - boost::program_options::positional_options_description positional_options; - positional_options.add("input", 1); - - // combine above options for parsing - boost::program_options::options_description cmdline_options; - cmdline_options.add(generic_options).add(config_options).add(hidden_options); - - boost::program_options::options_description config_file_options; - config_file_options.add(config_options).add(hidden_options); - - boost::program_options::options_description visible_options( - "Usage: " + boost::filesystem::basename(argv[0]) + " [options]"); - visible_options.add(generic_options).add(config_options); - - // parse command line options - boost::program_options::variables_map option_variables; - boost::program_options::store(boost::program_options::command_line_parser(argc, argv) - .options(cmdline_options) - .positional(positional_options) - .run(), - option_variables); - - const auto &temp_config_path = option_variables["config"].as(); - if (boost::filesystem::is_regular_file(temp_config_path)) - { - boost::program_options::store(boost::program_options::parse_config_file( - temp_config_path.string().c_str(), cmdline_options, true), - option_variables); - } - - if (option_variables.count("version")) - { - util::SimpleLogger().Write() << OSRM_VERSION; - return return_code::exit; - } - - if (option_variables.count("help")) - { - util::SimpleLogger().Write() << "\n" << visible_options; - return return_code::exit; - } - - boost::program_options::notify(option_variables); - - if (!option_variables.count("input")) - { - util::SimpleLogger().Write() << "\n" << visible_options; - return return_code::fail; - } - - return return_code::ok; -} - -void ContractorOptions::GenerateOutputFilesNames(ContractorConfig &contractor_config) -{ - contractor_config.level_output_path = contractor_config.osrm_input_path.string() + ".level"; - contractor_config.core_output_path = contractor_config.osrm_input_path.string() + ".core"; - contractor_config.graph_output_path = contractor_config.osrm_input_path.string() + ".hsgr"; - contractor_config.edge_based_graph_path = contractor_config.osrm_input_path.string() + ".ebg"; - contractor_config.edge_segment_lookup_path = - contractor_config.osrm_input_path.string() + ".edge_segment_lookup"; - contractor_config.edge_penalty_path = - contractor_config.osrm_input_path.string() + ".edge_penalties"; -} -} -} diff --git a/src/engine/osrm_impl.cpp b/src/engine/engine.cpp similarity index 75% rename from src/engine/osrm_impl.cpp rename to src/engine/engine.cpp index c059698b487..c9fe44ed145 100644 --- a/src/engine/osrm_impl.cpp +++ b/src/engine/engine.cpp @@ -1,4 +1,6 @@ -#include "engine/osrm_impl.hpp" +#include "engine/engine.hpp" +#include "engine/engine_config.hpp" +#include "engine/route_parameters.hpp" #include "engine/plugins/distance_table.hpp" #include "engine/plugins/hello_world.hpp" @@ -7,10 +9,12 @@ #include "engine/plugins/trip.hpp" #include "engine/plugins/viaroute.hpp" #include "engine/plugins/match.hpp" + #include "engine/datafacade/datafacade_base.hpp" #include "engine/datafacade/internal_datafacade.hpp" -#include "engine/datafacade/shared_barriers.hpp" #include "engine/datafacade/shared_datafacade.hpp" + +#include "storage/shared_barriers.hpp" #include "util/make_unique.hpp" #include "util/routed_options.hpp" #include "util/simple_logger.hpp" @@ -19,10 +23,6 @@ #include #include -#include "osrm/libosrm_config.hpp" -#include "osrm/osrm.hpp" -#include "osrm/route_parameters.hpp" - #include #include #include @@ -33,45 +33,45 @@ namespace osrm namespace engine { -OSRM::OSRM_impl::OSRM_impl(LibOSRMConfig &lib_config) +Engine::Engine(EngineConfig &config) { - if (lib_config.use_shared_memory) + if (config.use_shared_memory) { - barrier = util::make_unique(); + barrier = util::make_unique(); query_data_facade = new datafacade::SharedDataFacade(); } else { // populate base path - util::populate_base_path(lib_config.server_paths); + util::populate_base_path(config.server_paths); query_data_facade = new datafacade::InternalDataFacade( - lib_config.server_paths); + config.server_paths); } using DataFacade = datafacade::BaseDataFacade; // The following plugins handle all requests. RegisterPlugin(new plugins::DistanceTablePlugin( - query_data_facade, lib_config.max_locations_distance_table)); + query_data_facade, config.max_locations_distance_table)); RegisterPlugin(new plugins::HelloWorldPlugin()); RegisterPlugin(new plugins::NearestPlugin(query_data_facade)); RegisterPlugin(new plugins::MapMatchingPlugin( - query_data_facade, lib_config.max_locations_map_matching)); + query_data_facade, config.max_locations_map_matching)); RegisterPlugin(new plugins::TimestampPlugin(query_data_facade)); RegisterPlugin(new plugins::ViaRoutePlugin(query_data_facade, - lib_config.max_locations_viaroute)); + config.max_locations_viaroute)); RegisterPlugin( - new plugins::RoundTripPlugin(query_data_facade, lib_config.max_locations_trip)); + new plugins::RoundTripPlugin(query_data_facade, config.max_locations_trip)); } -void OSRM::OSRM_impl::RegisterPlugin(plugins::BasePlugin *raw_plugin_ptr) +void Engine::RegisterPlugin(plugins::BasePlugin *raw_plugin_ptr) { std::unique_ptr plugin_ptr(raw_plugin_ptr); util::SimpleLogger().Write() << "loaded plugin: " << plugin_ptr->GetDescriptor(); plugin_map[plugin_ptr->GetDescriptor()] = std::move(plugin_ptr); } -int OSRM::OSRM_impl::RunQuery(const RouteParameters &route_parameters, +int Engine::RunQuery(const RouteParameters &route_parameters, util::json::Object &json_result) { const auto &plugin_iterator = plugin_map.find(route_parameters.service); @@ -99,7 +99,7 @@ int OSRM::OSRM_impl::RunQuery(const RouteParameters &route_parameters, } // decrease number of concurrent queries -void OSRM::OSRM_impl::decrease_concurrent_query_count() +void Engine::decrease_concurrent_query_count() { if (!barrier) { @@ -121,7 +121,7 @@ void OSRM::OSRM_impl::decrease_concurrent_query_count() } // increase number of concurrent queries -void OSRM::OSRM_impl::increase_concurrent_query_count() +void Engine::increase_concurrent_query_count() { if (!barrier) { @@ -147,15 +147,5 @@ void OSRM::OSRM_impl::increase_concurrent_query_count() ->CheckAndReloadFacade(); } -// proxy code for compilation firewall -OSRM::OSRM(LibOSRMConfig &lib_config) : OSRM_pimpl_(util::make_unique(lib_config)) {} - -// needed because unique_ptr needs the size of OSRM_impl for delete -OSRM::~OSRM() {} - -int OSRM::RunQuery(const RouteParameters &route_parameters, util::json::Object &json_result) -{ - return OSRM_pimpl_->RunQuery(route_parameters, json_result); -} } } diff --git a/src/engine/phantom_node.cpp b/src/engine/phantom_node.cpp deleted file mode 100644 index e5b5873df99..00000000000 --- a/src/engine/phantom_node.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "engine/phantom_node.hpp" -#include "extractor/travel_mode.hpp" -#include "util/typedefs.hpp" -#include "osrm/coordinate.hpp" - -#include - -namespace osrm -{ -namespace engine -{ - -PhantomNode::PhantomNode(NodeID forward_node_id, - NodeID reverse_node_id, - unsigned name_id, - int forward_weight, - int reverse_weight, - int forward_offset, - int reverse_offset, - unsigned packed_geometry_id, - bool is_tiny_component, - unsigned component_id, - util::FixedPointCoordinate &location, - unsigned short fwd_segment_position, - extractor::TravelMode forward_travel_mode, - extractor::TravelMode backward_travel_mode) - : forward_node_id(forward_node_id), reverse_node_id(reverse_node_id), name_id(name_id), - forward_weight(forward_weight), reverse_weight(reverse_weight), - forward_offset(forward_offset), reverse_offset(reverse_offset), - packed_geometry_id(packed_geometry_id), component{component_id, is_tiny_component}, - location(location), fwd_segment_position(fwd_segment_position), - forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode) -{ -} - -PhantomNode::PhantomNode() - : forward_node_id(SPECIAL_NODEID), reverse_node_id(SPECIAL_NODEID), - name_id(std::numeric_limits::max()), forward_weight(INVALID_EDGE_WEIGHT), - reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0), - packed_geometry_id(SPECIAL_EDGEID), component{INVALID_COMPONENTID, false}, - fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), - backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) -{ -} - -int PhantomNode::GetForwardWeightPlusOffset() const -{ - if (SPECIAL_NODEID == forward_node_id) - { - return 0; - } - return forward_offset + forward_weight; -} - -int PhantomNode::GetReverseWeightPlusOffset() const -{ - if (SPECIAL_NODEID == reverse_node_id) - { - return 0; - } - return reverse_offset + reverse_weight; -} - -bool PhantomNode::IsBidirected() const -{ - return (forward_node_id != SPECIAL_NODEID) && (reverse_node_id != SPECIAL_NODEID); -} - -bool PhantomNode::IsCompressed() const { return (forward_offset != 0) || (reverse_offset != 0); } - -bool PhantomNode::is_valid(const unsigned number_of_nodes) const -{ - return location.IsValid() && - ((forward_node_id < number_of_nodes) || (reverse_node_id < number_of_nodes)) && - ((forward_weight != INVALID_EDGE_WEIGHT) || (reverse_weight != INVALID_EDGE_WEIGHT)) && - (component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID); -} - -bool PhantomNode::IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); } - -bool PhantomNode::operator==(const PhantomNode &other) const { return location == other.location; } -} -} diff --git a/src/engine/route_parameters.cpp b/src/engine/route_parameters.cpp index bbcf40def70..01df5783d4f 100644 --- a/src/engine/route_parameters.cpp +++ b/src/engine/route_parameters.cpp @@ -3,7 +3,8 @@ #include #include -#include "osrm/route_parameters.hpp" +#include "engine/route_parameters.hpp" +#include "util/coordinate.hpp" #include "engine/polyline_compressor.hpp" diff --git a/src/extractor/external_memory_node.cpp b/src/extractor/external_memory_node.cpp deleted file mode 100644 index 249c256066e..00000000000 --- a/src/extractor/external_memory_node.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "extractor/external_memory_node.hpp" -#include "extractor/query_node.hpp" - -#include - -namespace osrm -{ -namespace extractor -{ - -ExternalMemoryNode::ExternalMemoryNode( - int lat, int lon, OSMNodeID node_id, bool barrier, bool traffic_lights) - : QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights) -{ -} - -ExternalMemoryNode::ExternalMemoryNode() : barrier(false), traffic_lights(false) {} - -ExternalMemoryNode ExternalMemoryNode::min_value() -{ - return ExternalMemoryNode(0, 0, MIN_OSM_NODEID, false, false); -} - -ExternalMemoryNode ExternalMemoryNode::max_value() -{ - return ExternalMemoryNode(std::numeric_limits::max(), std::numeric_limits::max(), - MAX_OSM_NODEID, false, false); -} - -bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left, - const ExternalMemoryNode &right) const -{ - return left.node_id < right.node_id; -} - -ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::max_value() -{ - return ExternalMemoryNode::max_value(); -} - -ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::min_value() -{ - return ExternalMemoryNode::min_value(); -} -} -} diff --git a/src/extractor/extractor_options.cpp b/src/extractor/extractor_options.cpp deleted file mode 100644 index 7c985714f7e..00000000000 --- a/src/extractor/extractor_options.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "extractor/extractor_options.hpp" - -#include "util/ini_file.hpp" -#include "util/version.hpp" -#include "util/simple_logger.hpp" - -#include -#include - -#include - -namespace osrm -{ -namespace extractor -{ - -return_code -ExtractorOptions::ParseArguments(int argc, char *argv[], ExtractorConfig &extractor_config) -{ - // declare a group of options that will be allowed only on command line - boost::program_options::options_description generic_options("Options"); - generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - /* - * TODO: re-enable this - "restrictions,r", - boost::program_options::value(&extractor_config.restrictions_path), - "Restrictions file in .osrm.restrictions format")( - */ - "config,c", - boost::program_options::value(&extractor_config.config_file_path) - ->default_value("extractor.ini"), - "Path to a configuration file."); - - // declare a group of options that will be allowed both on command line and in config file - boost::program_options::options_description config_options("Configuration"); - config_options.add_options()( - "profile,p", - boost::program_options::value(&extractor_config.profile_path) - ->default_value("profile.lua"), - "Path to LUA routing profile")( - "threads,t", - boost::program_options::value(&extractor_config.requested_num_threads) - ->default_value(tbb::task_scheduler_init::default_num_threads()), - "Number of threads to use")( - "generate-edge-lookup", - boost::program_options::value(&extractor_config.generate_edge_lookup) - ->implicit_value(true) - ->default_value(false), - "Generate a lookup table for internal edge-expanded-edge IDs to OSM node pairs")( - "small-component-size", - boost::program_options::value(&extractor_config.small_component_size) - ->default_value(1000), - "Number of nodes required before a strongly-connected-componennt is considered big " - "(affects nearest neighbor snapping)"); - -#ifdef DEBUG_GEOMETRY - config_options.add_options()("debug-turns", boost::program_options::value( - &extractor_config.debug_turns_path), - "Write out GeoJSON with turn penalty data"); -#endif // DEBUG_GEOMETRY - - // hidden options, will be allowed both on command line and in config file, but will not be - // shown to the user - boost::program_options::options_description hidden_options("Hidden options"); - hidden_options.add_options()("input,i", boost::program_options::value( - &extractor_config.input_path), - "Input file in .osm, .osm.bz2 or .osm.pbf format"); - - // positional option - boost::program_options::positional_options_description positional_options; - positional_options.add("input", 1); - - // combine above options for parsing - boost::program_options::options_description cmdline_options; - cmdline_options.add(generic_options).add(config_options).add(hidden_options); - - boost::program_options::options_description config_file_options; - config_file_options.add(config_options).add(hidden_options); - - boost::program_options::options_description visible_options( - boost::filesystem::basename(argv[0]) + " [options]"); - visible_options.add(generic_options).add(config_options); - - // parse command line options - try - { - boost::program_options::variables_map option_variables; - boost::program_options::store(boost::program_options::command_line_parser(argc, argv) - .options(cmdline_options) - .positional(positional_options) - .run(), - option_variables); - if (option_variables.count("version")) - { - util::SimpleLogger().Write() << OSRM_VERSION; - return return_code::exit; - } - - if (option_variables.count("help")) - { - util::SimpleLogger().Write() << visible_options; - return return_code::exit; - } - - boost::program_options::notify(option_variables); - - // parse config file - if (boost::filesystem::is_regular_file(extractor_config.config_file_path)) - { - util::SimpleLogger().Write() << "Reading options from: " - << extractor_config.config_file_path.string(); - std::string ini_file_contents = - util::read_file_lower_content(extractor_config.config_file_path); - std::stringstream config_stream(ini_file_contents); - boost::program_options::store(parse_config_file(config_stream, config_file_options), - option_variables); - boost::program_options::notify(option_variables); - } - - if (!option_variables.count("input")) - { - util::SimpleLogger().Write() << visible_options; - return return_code::exit; - } - } - catch (std::exception &e) - { - util::SimpleLogger().Write(logWARNING) << e.what(); - return return_code::fail; - } - - return return_code::ok; -} - -void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_config) -{ - boost::filesystem::path &input_path = extractor_config.input_path; - extractor_config.output_file_name = input_path.string(); - extractor_config.restriction_file_name = input_path.string(); - extractor_config.names_file_name = input_path.string(); - extractor_config.timestamp_file_name = input_path.string(); - extractor_config.geometry_output_path = input_path.string(); - extractor_config.edge_output_path = input_path.string(); - extractor_config.edge_graph_output_path = input_path.string(); - extractor_config.edge_based_node_weights_output_path = input_path.string(); - extractor_config.node_output_path = input_path.string(); - extractor_config.rtree_nodes_output_path = input_path.string(); - extractor_config.rtree_leafs_output_path = input_path.string(); - extractor_config.edge_segment_lookup_path = input_path.string(); - extractor_config.edge_penalty_path = input_path.string(); - std::string::size_type pos = extractor_config.output_file_name.find(".osm.bz2"); - if (pos == std::string::npos) - { - pos = extractor_config.output_file_name.find(".osm.pbf"); - if (pos == std::string::npos) - { - pos = extractor_config.output_file_name.find(".osm.xml"); - } - } - if (pos == std::string::npos) - { - pos = extractor_config.output_file_name.find(".pbf"); - } - if (pos == std::string::npos) - { - pos = extractor_config.output_file_name.find(".osm"); - if (pos == std::string::npos) - { - extractor_config.output_file_name.append(".osrm"); - extractor_config.restriction_file_name.append(".osrm.restrictions"); - extractor_config.names_file_name.append(".osrm.names"); - extractor_config.timestamp_file_name.append(".osrm.timestamp"); - extractor_config.geometry_output_path.append(".osrm.geometry"); - extractor_config.node_output_path.append(".osrm.nodes"); - extractor_config.edge_output_path.append(".osrm.edges"); - extractor_config.edge_graph_output_path.append(".osrm.ebg"); - extractor_config.edge_based_node_weights_output_path.append(".osrm.enw"); - extractor_config.rtree_nodes_output_path.append(".osrm.ramIndex"); - extractor_config.rtree_leafs_output_path.append(".osrm.fileIndex"); - extractor_config.edge_segment_lookup_path.append(".osrm.edge_segment_lookup"); - extractor_config.edge_penalty_path.append(".osrm.edge_penalties"); - } - else - { - extractor_config.output_file_name.replace(pos, 5, ".osrm"); - extractor_config.restriction_file_name.replace(pos, 5, ".osrm.restrictions"); - extractor_config.names_file_name.replace(pos, 5, ".osrm.names"); - extractor_config.timestamp_file_name.replace(pos, 5, ".osrm.timestamp"); - extractor_config.geometry_output_path.replace(pos, 5, ".osrm.geometry"); - extractor_config.node_output_path.replace(pos, 5, ".osrm.nodes"); - extractor_config.edge_output_path.replace(pos, 5, ".osrm.edges"); - extractor_config.edge_graph_output_path.replace(pos, 5, ".osrm.ebg"); - extractor_config.edge_based_node_weights_output_path.replace(pos, 5, ".osrm.enw"); - extractor_config.rtree_nodes_output_path.replace(pos, 5, ".osrm.ramIndex"); - extractor_config.rtree_leafs_output_path.replace(pos, 5, ".osrm.fileIndex"); - extractor_config.edge_segment_lookup_path.replace(pos, 5, ".osrm.edge_segment_lookup"); - extractor_config.edge_penalty_path.replace(pos, 5, ".osrm.edge_penalties"); - } - } - else - { - extractor_config.output_file_name.replace(pos, 8, ".osrm"); - extractor_config.restriction_file_name.replace(pos, 8, ".osrm.restrictions"); - extractor_config.names_file_name.replace(pos, 8, ".osrm.names"); - extractor_config.timestamp_file_name.replace(pos, 8, ".osrm.timestamp"); - extractor_config.geometry_output_path.replace(pos, 8, ".osrm.geometry"); - extractor_config.node_output_path.replace(pos, 8, ".osrm.nodes"); - extractor_config.edge_output_path.replace(pos, 8, ".osrm.edges"); - extractor_config.edge_graph_output_path.replace(pos, 8, ".osrm.ebg"); - extractor_config.edge_based_node_weights_output_path.replace(pos, 8, ".osrm.enw"); - extractor_config.rtree_nodes_output_path.replace(pos, 8, ".osrm.ramIndex"); - extractor_config.rtree_leafs_output_path.replace(pos, 8, ".osrm.fileIndex"); - extractor_config.edge_segment_lookup_path.replace(pos, 8, ".osrm.edge_segment_lookup"); - extractor_config.edge_penalty_path.replace(pos, 8, ".osrm.edge_penalties"); - } -} -} -} diff --git a/src/osrm/osrm.cpp b/src/osrm/osrm.cpp new file mode 100644 index 00000000000..1100b1df985 --- /dev/null +++ b/src/osrm/osrm.cpp @@ -0,0 +1,22 @@ +#include "osrm/osrm.hpp" +#include "engine/engine.hpp" +#include "engine/engine_config.hpp" +#include "engine/plugins/plugin_base.hpp" +#include "storage/shared_barriers.hpp" +#include "util/make_unique.hpp" + +namespace osrm +{ + +// proxy code for compilation firewall +OSRM::OSRM(engine::EngineConfig &config_) : engine_(util::make_unique(config_)) {} + +// needed because unique_ptr needs the size of OSRM_impl for delete +OSRM::~OSRM() {} + +int OSRM::RunQuery(const RouteParameters &route_parameters, util::json::Object &json_result) +{ + return engine_->RunQuery(route_parameters, json_result); +} + +} diff --git a/src/server/request_handler.cpp b/src/server/request_handler.cpp index 4b83c83eeb7..96b94671da1 100644 --- a/src/server/request_handler.cpp +++ b/src/server/request_handler.cpp @@ -10,8 +10,8 @@ #include "util/xml_renderer.hpp" #include "util/typedefs.hpp" -#include "osrm/route_parameters.hpp" -#include "osrm/json_container.hpp" +#include "engine/route_parameters.hpp" +#include "util/json_container.hpp" #include "osrm/osrm.hpp" #include diff --git a/src/tools/datastore.cpp b/src/storage/storage.cpp similarity index 86% rename from src/tools/datastore.cpp rename to src/storage/storage.cpp index c00a9cc63e2..8330613440a 100644 --- a/src/tools/datastore.cpp +++ b/src/storage/storage.cpp @@ -2,16 +2,16 @@ #include "util/range_table.hpp" #include "contractor/query_edge.hpp" #include "extractor/query_node.hpp" -#include "datastore/shared_memory_factory.hpp" #include "util/shared_memory_vector_wrapper.hpp" #include "util/static_graph.hpp" #include "util/static_rtree.hpp" #include "engine/datafacade/datafacade_base.hpp" #include "extractor/travel_mode.hpp" #include "extractor/turn_instructions.hpp" -#include "engine/datafacade/shared_datatype.hpp" -#include "engine/datafacade/shared_barriers.hpp" -#include "util/datastore_options.hpp" +#include "storage/storage.hpp" +#include "storage/shared_datatype.hpp" +#include "storage/shared_barriers.hpp" +#include "storage/shared_memory.hpp" #include "util/fingerprint.hpp" #include "util/osrm_exception.hpp" #include "util/simple_logger.hpp" @@ -32,10 +32,10 @@ #include #include -// FIXME remove after move to datastore -using namespace osrm::engine::datafacade; -using namespace osrm::datastore; -using namespace osrm; +namespace osrm +{ +namespace storage +{ using RTreeLeaf = typename engine::datafacade::BaseDataFacade::RTreeLeaf; @@ -44,11 +44,6 @@ using RTreeNode = util::StaticRTree::TreeNode; using QueryGraph = util::StaticGraph; -namespace osrm -{ -namespace tools -{ - // delete a shared memory region. report warning if it could not be deleted void deleteRegion(const SharedDataType region) { @@ -78,10 +73,10 @@ void deleteRegion(const SharedDataType region) util::SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name; } } -} -} -int main(const int argc, const char *argv[]) try +Storage::Storage(const DataPaths &paths_) : paths(paths_) {} + +int Storage::Run() { util::LogPolicy::GetInstance().Unmute(); SharedBarriers barrier; @@ -91,8 +86,7 @@ int main(const int argc, const char *argv[]) try const bool lock_flags = MCL_CURRENT | MCL_FUTURE; if (-1 == mlockall(lock_flags)) { - util::SimpleLogger().Write(logWARNING) << "Process " << argv[0] - << " could not request RAM lock"; + util::SimpleLogger().Write(logWARNING) << "Could not request RAM lock"; } #endif @@ -107,107 +101,99 @@ int main(const int argc, const char *argv[]) try barrier.pending_update_mutex.unlock(); } - util::SimpleLogger().Write(logDEBUG) << "Checking input parameters"; - - std::unordered_map server_paths; - if (!util::GenerateDataStoreOptions(argc, argv, server_paths)) - { - return EXIT_SUCCESS; - } - - if (server_paths.find("hsgrdata") == server_paths.end()) + if (paths.find("hsgrdata") == paths.end()) { throw util::exception("no hsgr file found"); } - if (server_paths.find("ramindex") == server_paths.end()) + if (paths.find("ramindex") == paths.end()) { throw util::exception("no ram index file found"); } - if (server_paths.find("fileindex") == server_paths.end()) + if (paths.find("fileindex") == paths.end()) { throw util::exception("no leaf index file found"); } - if (server_paths.find("nodesdata") == server_paths.end()) + if (paths.find("nodesdata") == paths.end()) { throw util::exception("no nodes file found"); } - if (server_paths.find("edgesdata") == server_paths.end()) + if (paths.find("edgesdata") == paths.end()) { throw util::exception("no edges file found"); } - if (server_paths.find("namesdata") == server_paths.end()) + if (paths.find("namesdata") == paths.end()) { throw util::exception("no names file found"); } - if (server_paths.find("geometry") == server_paths.end()) + if (paths.find("geometry") == paths.end()) { throw util::exception("no geometry file found"); } - if (server_paths.find("core") == server_paths.end()) + if (paths.find("core") == paths.end()) { throw util::exception("no core file found"); } - auto paths_iterator = server_paths.find("hsgrdata"); - BOOST_ASSERT(server_paths.end() != paths_iterator); + auto paths_iterator = paths.find("hsgrdata"); + BOOST_ASSERT(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); + paths_iterator = paths.find("timestamp"); + BOOST_ASSERT(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); + paths_iterator = paths.find("ramindex"); + BOOST_ASSERT(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); + paths_iterator = paths.find("fileindex"); + BOOST_ASSERT(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); + paths_iterator = paths.find("nodesdata"); + BOOST_ASSERT(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); + paths_iterator = paths.find("edgesdata"); + BOOST_ASSERT(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); + paths_iterator = paths.find("namesdata"); + BOOST_ASSERT(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); + paths_iterator = paths.find("geometry"); + BOOST_ASSERT(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); + paths_iterator = paths.find("core"); + BOOST_ASSERT(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 engine::datafacade::SharedDataType layout_region = [&] + const storage::SharedDataType layout_region = [&] { return segment2_in_use ? LAYOUT_1 : LAYOUT_2; }(); - const engine::datafacade::SharedDataType data_region = [&] + const storage::SharedDataType data_region = [&] { return segment2_in_use ? DATA_1 : DATA_2; }(); - const engine::datafacade::SharedDataType previous_layout_region = [&] + const storage::SharedDataType previous_layout_region = [&] { return segment2_in_use ? LAYOUT_2 : LAYOUT_1; }(); - const engine::datafacade::SharedDataType previous_data_region = [&] + const storage::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 *layout_memory = makeSharedMemory(layout_region, sizeof(SharedDataLayout)); auto shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout(); shared_layout_ptr->SetBlockSize(SharedDataLayout::FILE_INDEX_PATH, @@ -345,8 +331,7 @@ int main(const int argc, const char *argv[]) try // allocate shared memory block util::SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes"; - SharedMemory *shared_memory = - SharedMemoryFactory::Get(data_region, shared_layout_ptr->GetSizeOfLayout()); + auto *shared_memory = makeSharedMemory(data_region, shared_layout_ptr->GetSizeOfLayout()); char *shared_memory_ptr = static_cast(shared_memory->Ptr()); // read actual data into shared memory object // @@ -555,7 +540,7 @@ int main(const int argc, const char *argv[]) try // acquire lock SharedMemory *data_type_memory = - SharedMemoryFactory::Get(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false); + makeSharedMemory(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false); SharedDataTimestamp *data_timestamp_ptr = static_cast(data_type_memory->Ptr()); @@ -571,22 +556,11 @@ int main(const int argc, const char *argv[]) try data_timestamp_ptr->layout = layout_region; data_timestamp_ptr->data = data_region; data_timestamp_ptr->timestamp += 1; - tools::deleteRegion(previous_data_region); - tools::deleteRegion(previous_layout_region); + deleteRegion(previous_data_region); + deleteRegion(previous_layout_region); util::SimpleLogger().Write() << "all data loaded"; - shared_layout_ptr->PrintInformation(); return EXIT_SUCCESS; } -catch (const std::bad_alloc &e) -{ - util::SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); - util::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) -{ - util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what(); } diff --git a/src/tools/check-hsgr.cpp b/src/tools/check-hsgr.cpp index 6f97d32ecdc..54822b1dfd9 100644 --- a/src/tools/check-hsgr.cpp +++ b/src/tools/check-hsgr.cpp @@ -11,6 +11,7 @@ #include #include +#include namespace osrm { @@ -22,72 +23,71 @@ using QueryGraph = util::StaticGraph; } } -int main(int argc, char *argv[]) +int main(int argc, char *argv[]) try { osrm::util::LogPolicy::GetInstance().Unmute(); - try + if (argc != 2) { - if (argc != 2) - { - osrm::util::SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " "; - return 1; - } + osrm::util::SimpleLogger().Write(logWARNING) << "usage: " << argv[0] << " "; + return EXIT_FAILURE; + } - boost::filesystem::path hsgr_path(argv[1]); + boost::filesystem::path hsgr_path(argv[1]); - std::vector node_list; - std::vector edge_list; - osrm::util::SimpleLogger().Write() << "loading graph from " << hsgr_path.string(); + std::vector node_list; + std::vector edge_list; + osrm::util::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); - osrm::util::SimpleLogger().Write() << "expecting " << m_number_of_nodes - << " nodes, checksum: " << m_check_sum; - BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty"); - osrm::util::SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " - << edge_list.size() << " edges"; - auto m_query_graph = std::make_shared(node_list, edge_list); + unsigned m_check_sum = 0; + unsigned m_number_of_nodes = + readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum); + osrm::util::SimpleLogger().Write() << "expecting " << m_number_of_nodes + << " nodes, checksum: " << m_check_sum; + BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty"); + osrm::util::SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " + << edge_list.size() << " edges"; + auto m_query_graph = std::make_shared(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"); + BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed"); + BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed"); - osrm::util::Percent progress(m_query_graph->GetNumberOfNodes()); - for (const auto node_u : osrm::util::irange(0u, m_query_graph->GetNumberOfNodes())) + osrm::util::Percent progress(m_query_graph->GetNumberOfNodes()); + for (const auto node_u : osrm::util::irange(0u, m_query_graph->GetNumberOfNodes())) + { + for (const auto eid : m_query_graph->GetAdjacentEdgeRange(node_u)) { - for (const auto eid : m_query_graph->GetAdjacentEdgeRange(node_u)) + const osrm::tools::EdgeData &data = m_query_graph->GetEdgeData(eid); + if (!data.shortcut) { - const osrm::tools::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::util::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::util::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)); - } + 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::util::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::util::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(); - osrm::util::SimpleLogger().Write() << "Data file " << argv[0] << " appears to be OK"; - } - catch (const std::exception &e) - { - osrm::util::SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); + progress.printStatus(node_u); } - return 0; + m_query_graph.reset(); + osrm::util::SimpleLogger().Write() << "Data file " << argv[0] << " appears to be OK"; + + return EXIT_SUCCESS; +} +catch (const std::exception &e) +{ + osrm::util::SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); + return EXIT_FAILURE; } diff --git a/src/tools/components.cpp b/src/tools/components.cpp index ae6da21262c..69e92cb3c18 100644 --- a/src/tools/components.cpp +++ b/src/tools/components.cpp @@ -98,141 +98,139 @@ std::size_t loadGraph(const char *path, } } -int main(int argc, char *argv[]) +int main(int argc, char *argv[]) try { std::vector coordinate_list; - osrm::util::LogPolicy::GetInstance().Unmute(); - try + + // enable logging + if (argc < 2) { - // enable logging - if (argc < 2) - { - osrm::util::SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " "; - return -1; - } + osrm::util::SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " "; + return EXIT_FAILURE; + } - std::vector graph_edge_list; - auto number_of_nodes = osrm::tools::loadGraph(argv[1], coordinate_list, graph_edge_list); + std::vector graph_edge_list; + auto number_of_nodes = osrm::tools::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(number_of_nodes, graph_edge_list); - graph_edge_list.clear(); - graph_edge_list.shrink_to_fit(); + tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); + const auto graph = + std::make_shared(number_of_nodes, graph_edge_list); + graph_edge_list.clear(); + graph_edge_list.shrink_to_fit(); - osrm::util::SimpleLogger().Write() << "Starting SCC graph traversal"; + osrm::util::SimpleLogger().Write() << "Starting SCC graph traversal"; - auto tarjan = - osrm::util::make_unique>(graph); - tarjan->run(); - osrm::util::SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() - << " many components"; - osrm::util::SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() - << " size 1 SCCs"; + auto tarjan = + osrm::util::make_unique>(graph); + tarjan->run(); + osrm::util::SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() + << " many components"; + osrm::util::SimpleLogger().Write() << "identified " << tarjan->get_size_one_count() + << " size 1 SCCs"; - // output - TIMER_START(SCC_RUN_SETUP); + // output + TIMER_START(SCC_RUN_SETUP); - // remove files from previous run if exist - osrm::tools::deleteFileIfExists("component.dbf"); - osrm::tools::deleteFileIfExists("component.shx"); - osrm::tools::deleteFileIfExists("component.shp"); + // remove files from previous run if exist + osrm::tools::deleteFileIfExists("component.dbf"); + osrm::tools::deleteFileIfExists("component.shx"); + osrm::tools::deleteFileIfExists("component.shp"); - osrm::util::Percent percentage(graph->GetNumberOfNodes()); + osrm::util::Percent percentage(graph->GetNumberOfNodes()); - OGRRegisterAll(); + OGRRegisterAll(); - const char *psz_driver_name = "ESRI Shapefile"; - auto *po_driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(psz_driver_name); - if (nullptr == po_driver) - { - throw osrm::util::exception("ESRI Shapefile driver not available"); - } - auto *po_datasource = po_driver->CreateDataSource("component.shp", nullptr); + const char *psz_driver_name = "ESRI Shapefile"; + auto *po_driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(psz_driver_name); + if (nullptr == po_driver) + { + throw osrm::util::exception("ESRI Shapefile driver not available"); + } + auto *po_datasource = po_driver->CreateDataSource("component.shp", nullptr); - if (nullptr == po_datasource) - { - throw osrm::util::exception("Creation of output file failed"); - } + if (nullptr == po_datasource) + { + throw osrm::util::exception("Creation of output file failed"); + } - auto *po_srs = new OGRSpatialReference(); - po_srs->importFromEPSG(4326); + auto *po_srs = new OGRSpatialReference(); + po_srs->importFromEPSG(4326); - auto *po_layer = po_datasource->CreateLayer("component", po_srs, wkbLineString, nullptr); + auto *po_layer = po_datasource->CreateLayer("component", po_srs, wkbLineString, nullptr); - if (nullptr == po_layer) - { - throw osrm::util::exception("Layer creation failed."); - } - TIMER_STOP(SCC_RUN_SETUP); - osrm::util::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::util::irange(0u, graph->GetNumberOfNodes())) + if (nullptr == po_layer) + { + throw osrm::util::exception("Layer creation failed."); + } + TIMER_STOP(SCC_RUN_SETUP); + osrm::util::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::util::irange(0u, graph->GetNumberOfNodes())) + { + percentage.printIncrement(); + for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) { - percentage.printIncrement(); - for (const auto current_edge : graph->GetAdjacentEdgeRange(source)) - { - const auto target = graph->GetTarget(current_edge); + const auto target = graph->GetTarget(current_edge); - if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source)) - { - total_network_length += - 100 * osrm::util::coordinate_calculation::greatCircleDistance( - coordinate_list[source].lat, coordinate_list[source].lon, - coordinate_list[target].lat, coordinate_list[target].lon); + if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source)) + { + total_network_length += + 100 * osrm::util::coordinate_calculation::greatCircleDistance( + 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); + 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))); + 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) + // edges that end on bollard nodes may actually be in two distinct components + if (size_of_containing_component < 1000) + { + OGRLineString line_string; + line_string.addPoint( + coordinate_list[source].lon / osrm::COORDINATE_PRECISION, + coordinate_list[source].lat / osrm::COORDINATE_PRECISION); + line_string.addPoint( + coordinate_list[target].lon / osrm::COORDINATE_PRECISION, + coordinate_list[target].lat / osrm::COORDINATE_PRECISION); + + OGRFeature *po_feature = + OGRFeature::CreateFeature(po_layer->GetLayerDefn()); + + po_feature->SetGeometry(&line_string); + if (OGRERR_NONE != po_layer->CreateFeature(po_feature)) { - OGRLineString line_string; - line_string.addPoint( - coordinate_list[source].lon / osrm::COORDINATE_PRECISION, - coordinate_list[source].lat / osrm::COORDINATE_PRECISION); - line_string.addPoint( - coordinate_list[target].lon / osrm::COORDINATE_PRECISION, - coordinate_list[target].lat / osrm::COORDINATE_PRECISION); - - OGRFeature *po_feature = - OGRFeature::CreateFeature(po_layer->GetLayerDefn()); - - po_feature->SetGeometry(&line_string); - if (OGRERR_NONE != po_layer->CreateFeature(po_feature)) - { - throw osrm::util::exception("Failed to create feature in shapefile."); - } - OGRFeature::DestroyFeature(po_feature); + throw osrm::util::exception("Failed to create feature in shapefile."); } + OGRFeature::DestroyFeature(po_feature); } } } - OGRSpatialReference::DestroySpatialReference(po_srs); - OGRDataSource::DestroyDataSource(po_datasource); - TIMER_STOP(SCC_OUTPUT); - osrm::util::SimpleLogger().Write() - << "generating output took: " << TIMER_MSEC(SCC_OUTPUT) / 1000. << "s"; - - osrm::util::SimpleLogger().Write() - << "total network distance: " - << static_cast(total_network_length / 100 / 1000.) << " km"; - - osrm::util::SimpleLogger().Write() << "finished component analysis"; } - catch (const std::exception &e) - { - osrm::util::SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); - } - return 0; + OGRSpatialReference::DestroySpatialReference(po_srs); + OGRDataSource::DestroyDataSource(po_datasource); + TIMER_STOP(SCC_OUTPUT); + osrm::util::SimpleLogger().Write() + << "generating output took: " << TIMER_MSEC(SCC_OUTPUT) / 1000. << "s"; + + osrm::util::SimpleLogger().Write() + << "total network distance: " + << static_cast(total_network_length / 100 / 1000.) << " km"; + + osrm::util::SimpleLogger().Write() << "finished component analysis"; + return EXIT_SUCCESS; +} +catch (const std::exception &e) +{ + osrm::util::SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); + return EXIT_FAILURE; } diff --git a/src/tools/contract.cpp b/src/tools/contract.cpp index 508f77bf872..a5253decfd1 100644 --- a/src/tools/contract.cpp +++ b/src/tools/contract.cpp @@ -1,7 +1,10 @@ -#include "contractor/processing_chain.hpp" -#include "contractor/contractor_options.hpp" +#include "contractor/contractor.hpp" +#include "contractor/contractor_config.hpp" #include "util/simple_logger.hpp" +#include "util/version.hpp" +#include +#include #include #include @@ -13,25 +16,131 @@ using namespace osrm; +enum class return_code : unsigned +{ + ok, + fail, + exit +}; + +return_code +parseArguments(int argc, char *argv[], contractor::ContractorConfig &contractor_config) +{ + // declare a group of options that will be allowed only on command line + boost::program_options::options_description generic_options("Options"); + generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( + "config,c", + boost::program_options::value(&contractor_config.config_file_path) + ->default_value("contractor.ini"), + "Path to a configuration file."); + + // declare a group of options that will be allowed both on command line and in config file + boost::program_options::options_description config_options("Configuration"); + config_options.add_options()( + "profile,p", + boost::program_options::value(&contractor_config.profile_path) + ->default_value("profile.lua"), + "Path to LUA routing profile")( + "threads,t", + boost::program_options::value(&contractor_config.requested_num_threads) + ->default_value(tbb::task_scheduler_init::default_num_threads()), + "Number of threads to use")( + "core,k", + boost::program_options::value(&contractor_config.core_factor)->default_value(1.0), + "Percentage of the graph (in vertices) to contract [0..1]")( + "segment-speed-file", + boost::program_options::value(&contractor_config.segment_speed_lookup_path), + "Lookup file containing nodeA,nodeB,speed data to adjust edge weights")( + "level-cache,o", boost::program_options::value(&contractor_config.use_cached_priority) + ->default_value(false), + "Use .level file to retain the contaction level for each node from the last run."); + +#ifdef DEBUG_GEOMETRY + config_options.add_options()( + "debug-geometry", + boost::program_options::value(&contractor_config.debug_geometry_path), + "Write out edge-weight debugging geometry data in GeoJSON format to this file"); +#endif + + // hidden options, will be allowed both on command line and in config file, but will not be + // shown to the user + boost::program_options::options_description hidden_options("Hidden options"); + hidden_options.add_options()("input,i", boost::program_options::value( + &contractor_config.osrm_input_path), + "Input file in .osm, .osm.bz2 or .osm.pbf format"); + + // positional option + boost::program_options::positional_options_description positional_options; + positional_options.add("input", 1); + + // combine above options for parsing + boost::program_options::options_description cmdline_options; + cmdline_options.add(generic_options).add(config_options).add(hidden_options); + + boost::program_options::options_description config_file_options; + config_file_options.add(config_options).add(hidden_options); + + boost::program_options::options_description visible_options( + "Usage: " + boost::filesystem::basename(argv[0]) + " [options]"); + visible_options.add(generic_options).add(config_options); + + // parse command line options + boost::program_options::variables_map option_variables; + boost::program_options::store(boost::program_options::command_line_parser(argc, argv) + .options(cmdline_options) + .positional(positional_options) + .run(), + option_variables); + + const auto &temp_config_path = option_variables["config"].as(); + if (boost::filesystem::is_regular_file(temp_config_path)) + { + boost::program_options::store(boost::program_options::parse_config_file( + temp_config_path.string().c_str(), cmdline_options, true), + option_variables); + } + + if (option_variables.count("version")) + { + util::SimpleLogger().Write() << OSRM_VERSION; + return return_code::exit; + } + + if (option_variables.count("help")) + { + util::SimpleLogger().Write() << "\n" << visible_options; + return return_code::exit; + } + + boost::program_options::notify(option_variables); + + if (!option_variables.count("input")) + { + util::SimpleLogger().Write() << "\n" << visible_options; + return return_code::fail; + } + + return return_code::ok; +} + int main(int argc, char *argv[]) try { util::LogPolicy::GetInstance().Unmute(); contractor::ContractorConfig contractor_config; - const contractor::return_code result = - contractor::ContractorOptions::ParseArguments(argc, argv, contractor_config); + const return_code result = parseArguments(argc, argv, contractor_config); - if (contractor::return_code::fail == result) + if (return_code::fail == result) { return EXIT_FAILURE; } - if (contractor::return_code::exit == result) + if (return_code::exit == result) { return EXIT_SUCCESS; } - contractor::ContractorOptions::GenerateOutputFilesNames(contractor_config); + contractor_config.UseDefaultOutputNames(); if (1 > contractor_config.requested_num_threads) { @@ -70,7 +179,7 @@ int main(int argc, char *argv[]) try tbb::task_scheduler_init init(contractor_config.requested_num_threads); - return contractor::Prepare(contractor_config).Run(); + return contractor::Contractor(contractor_config).Run(); } catch (const std::bad_alloc &e) { diff --git a/src/tools/extract.cpp b/src/tools/extract.cpp index 7f27fbc8d72..9c63bfb4bb1 100644 --- a/src/tools/extract.cpp +++ b/src/tools/extract.cpp @@ -1,8 +1,13 @@ #include "extractor/extractor.hpp" -#include "extractor/extractor_options.hpp" +#include "extractor/extractor_config.hpp" #include "util/simple_logger.hpp" +#include "util/ini_file.hpp" +#include "util/version.hpp" + +#include #include +#include #include #include @@ -10,25 +15,150 @@ using namespace osrm; +enum class return_code : unsigned +{ + ok, + fail, + exit +}; + +return_code +parseArguments(int argc, char *argv[], extractor::ExtractorConfig &extractor_config) +{ + // declare a group of options that will be allowed only on command line + boost::program_options::options_description generic_options("Options"); + generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( + /* + * TODO: re-enable this + "restrictions,r", + boost::program_options::value(&extractor_config.restrictions_path), + "Restrictions file in .osrm.restrictions format")( + */ + "config,c", + boost::program_options::value(&extractor_config.config_file_path) + ->default_value("extractor.ini"), + "Path to a configuration file."); + + // declare a group of options that will be allowed both on command line and in config file + boost::program_options::options_description config_options("Configuration"); + config_options.add_options()( + "profile,p", + boost::program_options::value(&extractor_config.profile_path) + ->default_value("profile.lua"), + "Path to LUA routing profile")( + "threads,t", + boost::program_options::value(&extractor_config.requested_num_threads) + ->default_value(tbb::task_scheduler_init::default_num_threads()), + "Number of threads to use")( + "generate-edge-lookup", + boost::program_options::value(&extractor_config.generate_edge_lookup) + ->implicit_value(true) + ->default_value(false), + "Generate a lookup table for internal edge-expanded-edge IDs to OSM node pairs")( + "small-component-size", + boost::program_options::value(&extractor_config.small_component_size) + ->default_value(1000), + "Number of nodes required before a strongly-connected-componennt is considered big " + "(affects nearest neighbor snapping)"); + +#ifdef DEBUG_GEOMETRY + config_options.add_options()("debug-turns", boost::program_options::value( + &extractor_config.debug_turns_path), + "Write out GeoJSON with turn penalty data"); +#endif // DEBUG_GEOMETRY + + // hidden options, will be allowed both on command line and in config file, but will not be + // shown to the user + boost::program_options::options_description hidden_options("Hidden options"); + hidden_options.add_options()("input,i", boost::program_options::value( + &extractor_config.input_path), + "Input file in .osm, .osm.bz2 or .osm.pbf format"); + + // positional option + boost::program_options::positional_options_description positional_options; + positional_options.add("input", 1); + + // combine above options for parsing + boost::program_options::options_description cmdline_options; + cmdline_options.add(generic_options).add(config_options).add(hidden_options); + + boost::program_options::options_description config_file_options; + config_file_options.add(config_options).add(hidden_options); + + boost::program_options::options_description visible_options( + boost::filesystem::basename(argv[0]) + " [options]"); + visible_options.add(generic_options).add(config_options); + + // parse command line options + try + { + boost::program_options::variables_map option_variables; + boost::program_options::store(boost::program_options::command_line_parser(argc, argv) + .options(cmdline_options) + .positional(positional_options) + .run(), + option_variables); + if (option_variables.count("version")) + { + util::SimpleLogger().Write() << OSRM_VERSION; + return return_code::exit; + } + + if (option_variables.count("help")) + { + util::SimpleLogger().Write() << visible_options; + return return_code::exit; + } + + boost::program_options::notify(option_variables); + + // parse config file + if (boost::filesystem::is_regular_file(extractor_config.config_file_path)) + { + util::SimpleLogger().Write() << "Reading options from: " + << extractor_config.config_file_path.string(); + std::string ini_file_contents = + util::read_file_lower_content(extractor_config.config_file_path); + std::stringstream config_stream(ini_file_contents); + boost::program_options::store(parse_config_file(config_stream, config_file_options), + option_variables); + boost::program_options::notify(option_variables); + } + + if (!option_variables.count("input")) + { + util::SimpleLogger().Write() << visible_options; + return return_code::exit; + } + } + catch (std::exception &e) + { + util::SimpleLogger().Write(logWARNING) << e.what(); + return return_code::fail; + } + + return return_code::ok; +} + + int main(int argc, char *argv[]) try { util::LogPolicy::GetInstance().Unmute(); extractor::ExtractorConfig extractor_config; - const extractor::return_code result = - extractor::ExtractorOptions::ParseArguments(argc, argv, extractor_config); + const auto result = parseArguments(argc, argv, extractor_config); - if (extractor::return_code::fail == result) + if (return_code::fail == result) { return EXIT_FAILURE; } - if (extractor::return_code::exit == result) + if (return_code::exit == result) { return EXIT_SUCCESS; } - extractor::ExtractorOptions::GenerateOutputFilesNames(extractor_config); + extractor_config.UseDefaultOutputNames(); if (1 > extractor_config.requested_num_threads) { diff --git a/src/tools/io-benchmark.cpp b/src/tools/io-benchmark.cpp index edd128d1b76..8c08288a50c 100644 --- a/src/tools/io-benchmark.cpp +++ b/src/tools/io-benchmark.cpp @@ -47,7 +47,9 @@ void runStatistics(std::vector &timings_vector, Statistics &stats) } } -int main(int argc, char *argv[]) +boost::filesystem::path test_path; + +int main(int argc, char *argv[]) try { #ifdef __FreeBSD__ @@ -60,279 +62,275 @@ int main(int argc, char *argv[]) #else osrm::util::LogPolicy::GetInstance().Unmute(); - boost::filesystem::path test_path; - try + if (1 == argc) { - if (1 == argc) - { - osrm::util::SimpleLogger().Write(logWARNING) << "usage: " << argv[0] - << " /path/on/device"; - return -1; - } + osrm::util::SimpleLogger().Write(logWARNING) << "usage: " << argv[0] + << " /path/on/device"; + return -1; + } - test_path = boost::filesystem::path(argv[1]); - test_path /= "osrm.tst"; - osrm::util::SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string(); + test_path = boost::filesystem::path(argv[1]); + test_path /= "osrm.tst"; + osrm::util::SimpleLogger().Write(logDEBUG) << "temporary file: " << test_path.string(); - // create files for testing - if (2 == argc) + // create files for testing + if (2 == argc) + { + // create file to test + if (boost::filesystem::exists(test_path)) { - // create file to test - if (boost::filesystem::exists(test_path)) - { - throw osrm::util::exception("Data file already exists"); - } + throw osrm::util::exception("Data file already exists"); + } - int *random_array = new int[osrm::tools::NUMBER_OF_ELEMENTS]; - std::generate(random_array, random_array + osrm::tools::NUMBER_OF_ELEMENTS, std::rand); + int *random_array = new int[osrm::tools::NUMBER_OF_ELEMENTS]; + std::generate(random_array, random_array + osrm::tools::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, - osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); - TIMER_STOP(write_1gb); - fclose(fd); + 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, + osrm::tools::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::util::exception("Could not open random data file"); - } - TIMER_START(write_1gb); - int ret = - write(file_desc, random_array, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); - if (0 > ret) - { - throw osrm::util::exception("could not write random data file"); - } - TIMER_STOP(write_1gb); - close(file_desc); -#endif - delete[] random_array; - osrm::util::SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " - << TIMER_SEC(write_1gb) << "s"; - osrm::util::SimpleLogger().Write() << "raw write performance: " << std::setprecision(5) - << std::fixed << 1024 * 1024 / TIMER_SEC(write_1gb) - << "MB/sec"; - - osrm::util::SimpleLogger().Write(logDEBUG) - << "finished creation of random data. Flush disk cache now!"; + 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::util::exception("Could not open random data file"); } - else + TIMER_START(write_1gb); + int ret = + write(file_desc, random_array, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); + if (0 > ret) { - // Run Non-Cached I/O benchmarks - if (!boost::filesystem::exists(test_path)) - { - throw osrm::util::exception("data file does not exist"); - } + throw osrm::util::exception("could not write random data file"); + } + TIMER_STOP(write_1gb); + close(file_desc); +#endif + delete[] random_array; + osrm::util::SimpleLogger().Write(logDEBUG) << "writing raw 1GB took " + << TIMER_SEC(write_1gb) << "s"; + osrm::util::SimpleLogger().Write() << "raw write performance: " << std::setprecision(5) + << std::fixed << 1024 * 1024 / TIMER_SEC(write_1gb) + << "MB/sec"; - // volatiles do not get optimized - osrm::tools::Statistics stats; + osrm::util::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::util::exception("data file does not exist"); + } + + // volatiles do not get optimized + osrm::tools::Statistics stats; #ifdef __APPLE__ - volatile unsigned single_block[1024]; - char *raw_array = new char[osrm::tools::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); + volatile unsigned single_block[1024]; + char *raw_array = new char[osrm::tools::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)); + 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) - { - osrm::util::SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno); - return -1; - } - char *raw_array = - (char *)memalign(512, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); + int file_desc = open(test_path.string().c_str(), O_RDONLY | O_DIRECT | O_SYNC); + if (-1 == file_desc) + { + osrm::util::SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno); + return -1; + } + char *raw_array = + (char *)memalign(512, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); #endif - TIMER_START(read_1gb); + TIMER_START(read_1gb); #ifdef __APPLE__ - read(fileno(fd), raw_array, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); - close(fileno(fd)); - fd = fopen(test_path.string().c_str(), "r"); + read(fileno(fd), raw_array, osrm::tools::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, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); - osrm::util::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); - osrm::util::SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno); + int ret = + read(file_desc, raw_array, osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned)); + osrm::util::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); + osrm::util::SimpleLogger().Write(logDEBUG) << "opened, error: " << strerror(errno); #endif - TIMER_STOP(read_1gb); + TIMER_STOP(read_1gb); - osrm::util::SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " - << TIMER_SEC(read_1gb) << "s"; - osrm::util::SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) - << std::fixed << 1024 * 1024 / TIMER_SEC(read_1gb) - << "MB/sec"; + osrm::util::SimpleLogger().Write(logDEBUG) << "reading raw 1GB took " + << TIMER_SEC(read_1gb) << "s"; + osrm::util::SimpleLogger().Write() << "raw read performance: " << std::setprecision(5) + << std::fixed << 1024 * 1024 / TIMER_SEC(read_1gb) + << "MB/sec"; - std::vector timing_results_raw_random; - osrm::util::SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB"; + std::vector timing_results_raw_random; + osrm::util::SimpleLogger().Write(logDEBUG) << "running 1000 random I/Os of 4KB"; #ifdef __APPLE__ - fseek(fd, 0, SEEK_SET); + fseek(fd, 0, SEEK_SET); #endif #ifdef __linux__ - lseek(file_desc, 0, SEEK_SET); + lseek(file_desc, 0, SEEK_SET); #endif - // make 1000 random access, time each I/O seperately - unsigned number_of_blocks = - (osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned) - 1) / 4096; - std::random_device rd; - std::default_random_engine e1(rd()); - std::uniform_int_distribution 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); + // make 1000 random access, time each I/O seperately + unsigned number_of_blocks = + (osrm::tools::NUMBER_OF_ELEMENTS * sizeof(unsigned) - 1) / 4096; + std::random_device rd; + std::default_random_engine e1(rd()); + std::uniform_int_distribution 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); + 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; + 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); + 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) - { - osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; - osrm::util::SimpleLogger().Write(logWARNING) << "seek error " - << strerror(errno); - throw osrm::util::exception("seek error"); - } - if (-1 == ret2) - { - osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; - osrm::util::SimpleLogger().Write(logWARNING) << "read error " - << strerror(errno); - throw osrm::util::exception("read error"); - } - timing_results_raw_random.push_back(TIMER_SEC(random_access)); + TIMER_STOP(random_access); + if (((off_t)-1) == ret1) + { + osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; + osrm::util::SimpleLogger().Write(logWARNING) << "seek error " + << strerror(errno); + throw osrm::util::exception("seek error"); } - - // Do statistics - osrm::util::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) + if (-1 == ret2) { - random_csv << i << ", " << timing_results_raw_random[i] << std::endl; + osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; + osrm::util::SimpleLogger().Write(logWARNING) << "read error " + << strerror(errno); + throw osrm::util::exception("read error"); } - random_csv.close(); - osrm::tools::runStatistics(timing_results_raw_random, stats); + timing_results_raw_random.push_back(TIMER_SEC(random_access)); + } - osrm::util::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"; + // Do statistics + osrm::util::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(); + osrm::tools::runStatistics(timing_results_raw_random, stats); + + osrm::util::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 timing_results_raw_seq; + std::vector timing_results_raw_seq; #ifdef __APPLE__ - fseek(fd, 0, SEEK_SET); + fseek(fd, 0, SEEK_SET); #endif #ifdef __linux__ - lseek(file_desc, 0, SEEK_SET); + 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); + // 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); + 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; + int ret1 = 0; + int ret2 = 0; #endif #ifdef __linux__ - int ret1 = lseek(file_desc, current_offset, SEEK_SET); + int ret1 = lseek(file_desc, current_offset, SEEK_SET); - int ret2 = read(file_desc, (char *)single_block, 4096); + int ret2 = read(file_desc, (char *)single_block, 4096); #endif - TIMER_STOP(read_every_100); - if (((off_t)-1) == ret1) - { - osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; - osrm::util::SimpleLogger().Write(logWARNING) << "seek error " - << strerror(errno); - throw osrm::util::exception("seek error"); - } - if (-1 == ret2) - { - osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; - osrm::util::SimpleLogger().Write(logWARNING) << "read error " - << strerror(errno); - throw osrm::util::exception("read error"); - } - timing_results_raw_seq.push_back(TIMER_SEC(read_every_100)); + TIMER_STOP(read_every_100); + if (((off_t)-1) == ret1) + { + osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; + osrm::util::SimpleLogger().Write(logWARNING) << "seek error " + << strerror(errno); + throw osrm::util::exception("seek error"); + } + if (-1 == ret2) + { + osrm::util::SimpleLogger().Write(logWARNING) << "offset: " << current_offset; + osrm::util::SimpleLogger().Write(logWARNING) << "read error " + << strerror(errno); + throw osrm::util::exception("read error"); } + timing_results_raw_seq.push_back(TIMER_SEC(read_every_100)); + } #ifdef __APPLE__ - fclose(fd); - // free(single_element); - free(raw_array); + fclose(fd); + // free(single_element); + free(raw_array); // free(single_block); #endif #ifdef __linux__ - close(file_desc); + close(file_desc); #endif - // Do statistics - osrm::util::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(); - osrm::tools::runStatistics(timing_results_raw_seq, stats); - osrm::util::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); - osrm::util::SimpleLogger().Write(logDEBUG) << "removing temporary files"; - } + // Do statistics + osrm::util::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; } - } - catch (const std::exception &e) - { - osrm::util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what(); - osrm::util::SimpleLogger().Write(logWARNING) << "cleaning up, and exiting"; + seq_csv.close(); + osrm::tools::runStatistics(timing_results_raw_seq, stats); + osrm::util::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); - osrm::util::SimpleLogger().Write(logWARNING) << "removing temporary files"; + osrm::util::SimpleLogger().Write(logDEBUG) << "removing temporary files"; } - return -1; } - return 0; + return EXIT_SUCCESS; #endif } +catch (const std::exception &e) +{ + osrm::util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what(); + osrm::util::SimpleLogger().Write(logWARNING) << "cleaning up, and exiting"; + if (boost::filesystem::exists(test_path)) + { + boost::filesystem::remove(test_path); + osrm::util::SimpleLogger().Write(logWARNING) << "removing temporary files"; + } + return EXIT_FAILURE; +} diff --git a/src/tools/routed.cpp b/src/tools/routed.cpp index ee00fa38b43..81f8eb6aaea 100644 --- a/src/tools/routed.cpp +++ b/src/tools/routed.cpp @@ -4,7 +4,7 @@ #include "util/simple_logger.hpp" #include "osrm/osrm.hpp" -#include "osrm/libosrm_config.hpp" +#include "osrm/engine_config.hpp" #ifdef __linux__ #include @@ -49,12 +49,12 @@ int main(int argc, const char *argv[]) try std::string ip_address; int ip_port, requested_thread_num; - LibOSRMConfig lib_config; + EngineConfig config; const unsigned init_result = util::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); + argc, argv, config.server_paths, ip_address, ip_port, requested_thread_num, + config.use_shared_memory, trial_run, config.max_locations_trip, + config.max_locations_viaroute, config.max_locations_distance_table, + config.max_locations_map_matching); if (init_result == util::INIT_OK_DO_NOT_START_ENGINE) { return EXIT_SUCCESS; @@ -81,11 +81,11 @@ int main(int argc, const char *argv[]) try (void)munlockall(); } bool should_lock = false, could_lock = true; - } memory_locker(lib_config.use_shared_memory); + } memory_locker(config.use_shared_memory); #endif util::SimpleLogger().Write() << "starting up engines, " << OSRM_VERSION; - if (lib_config.use_shared_memory) + if (config.use_shared_memory) { util::SimpleLogger().Write(logDEBUG) << "Loading from shared memory"; } @@ -102,7 +102,7 @@ int main(int argc, const char *argv[]) try pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); #endif - OSRM osrm_lib(lib_config); + OSRM osrm_lib(config); auto routing_server = server::Server::CreateServer(ip_address, ip_port, requested_thread_num); routing_server->GetRequestHandlerPtr().RegisterRoutingMachine(&osrm_lib); diff --git a/src/tools/simpleclient.cpp b/src/tools/simpleclient.cpp deleted file mode 100644 index f00b302d697..00000000000 --- a/src/tools/simpleclient.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#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 - -int main(int argc, const char *argv[]) -{ - osrm::util::LogPolicy::GetInstance().Unmute(); - try - { - std::string ip_address; - int ip_port, requested_thread_num; - bool trial_run = false; - osrm::LibOSRMConfig lib_config; - const unsigned init_result = osrm::util::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 == osrm::util::INIT_OK_DO_NOT_START_ENGINE) - { - return 0; - } - if (init_result == osrm::util::INIT_FAILED) - { - return 1; - } - - osrm::OSRM routing_machine(lib_config); - - osrm::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 * osrm::COORDINATE_PRECISION, - 13.438640 * osrm::COORDINATE_PRECISION); - // target_coordinate - route_parameters.coordinates.emplace_back(52.513191 * osrm::COORDINATE_PRECISION, - 13.415852 * osrm::COORDINATE_PRECISION); - osrm::json::Object json_result; - const int result_code = routing_machine.RunQuery(route_parameters, json_result); - osrm::util::SimpleLogger().Write() << "http code: " << result_code; - osrm::json::render(osrm::util::SimpleLogger().Write(), json_result); - } - catch (std::exception ¤t_exception) - { - osrm::util::SimpleLogger().Write(logWARNING) << "caught exception: " - << current_exception.what(); - return -1; - } - return 0; -} diff --git a/src/tools/springclean.cpp b/src/tools/springclean.cpp index 7408e7d2c30..440dda2f709 100644 --- a/src/tools/springclean.cpp +++ b/src/tools/springclean.cpp @@ -1,7 +1,7 @@ #include -#include "datastore/shared_memory_factory.hpp" -#include "engine/datafacade/shared_datatype.hpp" +#include "storage/shared_memory.hpp" +#include "storage/shared_datatype.hpp" #include "util/simple_logger.hpp" namespace osrm @@ -10,8 +10,7 @@ namespace tools { // FIXME remove after folding back into datastore -using namespace datastore; -using namespace engine::datafacade; +using namespace storage; void deleteRegion(const SharedDataType region) { @@ -55,33 +54,31 @@ void springclean() } } -int main() +int main() try { osrm::util::LogPolicy::GetInstance().Unmute(); - try - { - osrm::util::SimpleLogger().Write() << "Releasing all locks"; - osrm::util::SimpleLogger().Write() << "ATTENTION! BE CAREFUL!"; - osrm::util::SimpleLogger().Write() << "----------------------"; - osrm::util::SimpleLogger().Write() - << "This tool may put osrm-routed into an undefined state!"; - osrm::util::SimpleLogger().Write() - << "Type 'Y' to acknowledge that you know what your are doing."; - osrm::util::SimpleLogger().Write() - << "\n\nDo you want to purge all shared memory allocated " - << "by osrm-datastore? [type 'Y' to confirm]"; + osrm::util::SimpleLogger().Write() << "Releasing all locks"; + osrm::util::SimpleLogger().Write() << "ATTENTION! BE CAREFUL!"; + osrm::util::SimpleLogger().Write() << "----------------------"; + osrm::util::SimpleLogger().Write() + << "This tool may put osrm-routed into an undefined state!"; + osrm::util::SimpleLogger().Write() + << "Type 'Y' to acknowledge that you know what your are doing."; + osrm::util::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') - { - osrm::util::SimpleLogger().Write() << "aborted."; - return 0; - } - osrm::tools::springclean(); - } - catch (const std::exception &e) + const auto letter = getchar(); + if (letter != 'Y') { - osrm::util::SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what(); + osrm::util::SimpleLogger().Write() << "aborted."; + return EXIT_SUCCESS; } - return 0; + osrm::tools::springclean(); + return EXIT_SUCCESS; +} +catch (const std::exception &e) +{ + osrm::util::SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what(); + return EXIT_FAILURE; } diff --git a/include/util/datastore_options.hpp b/src/tools/store.cpp similarity index 80% rename from include/util/datastore_options.hpp rename to src/tools/store.cpp index bd090250696..7065cbb1037 100644 --- a/include/util/datastore_options.hpp +++ b/src/tools/store.cpp @@ -1,27 +1,19 @@ -#ifndef DATASTORE_OPTIONS_HPP -#define DATASTORE_OPTIONS_HPP - -#include "util/version.hpp" -#include "util/ini_file.hpp" +#include "storage/storage.hpp" #include "util/osrm_exception.hpp" #include "util/simple_logger.hpp" +#include "util/typedefs.hpp" +#include "util/ini_file.hpp" +#include "util/version.hpp" -#include -#include +#include #include -#include -#include - -namespace osrm -{ -namespace util -{ +using namespace osrm; // generate boost::program_options object for the routing part -bool GenerateDataStoreOptions(const int argc, +bool generateDataStoreOptions(const int argc, const char *argv[], - std::unordered_map &paths) + storage::DataPaths &paths) { // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); @@ -76,6 +68,13 @@ bool GenerateDataStoreOptions(const int argc, boost::filesystem::basename(argv[0]) + " [] "); visible_options.add(generic_options).add(config_options); + // print help options if no infile is specified + if (argc < 2) + { + util::SimpleLogger().Write() << visible_options; + return false; + } + // parse command line options boost::program_options::variables_map option_variables; boost::program_options::store(boost::program_options::command_line_parser(argc, argv) @@ -86,13 +85,13 @@ bool GenerateDataStoreOptions(const int argc, if (option_variables.count("version")) { - SimpleLogger().Write() << OSRM_VERSION; + util::SimpleLogger().Write() << OSRM_VERSION; return false; } if (option_variables.count("help")) { - SimpleLogger().Write() << visible_options; + util::SimpleLogger().Write() << visible_options; return false; } @@ -121,8 +120,8 @@ bool GenerateDataStoreOptions(const int argc, boost::filesystem::is_regular_file(paths.find("config")->second)) || option_variables.count("base")) { - SimpleLogger().Write(logWARNING) << "conflicting parameters"; - SimpleLogger().Write() << visible_options; + util::SimpleLogger().Write(logWARNING) << "conflicting parameters"; + util::SimpleLogger().Write() << visible_options; return false; } } @@ -132,8 +131,8 @@ bool GenerateDataStoreOptions(const int argc, if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) && !option_variables.count("base")) { - SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); - std::string ini_file_contents = read_file_lower_content(path_iterator->second); + util::SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string(); + std::string ini_file_contents = util::read_file_lower_content(path_iterator->second); std::stringstream config_stream(ini_file_contents); boost::program_options::store(parse_config_file(config_stream, config_file_options), option_variables); @@ -204,61 +203,84 @@ bool GenerateDataStoreOptions(const int argc, if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .hsgr file must be specified"); + throw util::exception("valid .hsgr file must be specified"); } path_iterator = paths.find("nodesdata"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .nodes file must be specified"); + throw util::exception("valid .nodes file must be specified"); } path_iterator = paths.find("edgesdata"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .edges file must be specified"); + throw util::exception("valid .edges file must be specified"); } path_iterator = paths.find("geometry"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .geometry file must be specified"); + throw util::exception("valid .geometry file must be specified"); } path_iterator = paths.find("ramindex"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .ramindex file must be specified"); + throw util::exception("valid .ramindex file must be specified"); } path_iterator = paths.find("fileindex"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .fileindex file must be specified"); + throw util::exception("valid .fileindex file must be specified"); } path_iterator = paths.find("namesdata"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .names file must be specified"); + throw util::exception("valid .names file must be specified"); } path_iterator = paths.find("timestamp"); if (path_iterator == paths.end() || path_iterator->second.string().empty() || !boost::filesystem::is_regular_file(path_iterator->second)) { - throw exception("valid .timestamp file must be specified"); + throw util::exception("valid .timestamp file must be specified"); } return true; } + +int main(const int argc, const char *argv[]) try +{ + util::LogPolicy::GetInstance().Unmute(); + + storage::DataPaths paths; + if (!generateDataStoreOptions(argc, argv, paths)) + { + return EXIT_SUCCESS; + } + + storage::Storage storage(paths); + return storage.Run(); } +catch (const std::bad_alloc &e) +{ + util::SimpleLogger().Write(logWARNING) << "[exception] " << e.what(); + util::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) +{ + util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what(); + return EXIT_FAILURE; } - -#endif /* DATASTORE_OPTIONS_HPP */ diff --git a/src/tools/unlock_all_mutexes.cpp b/src/tools/unlock_all_mutexes.cpp index f59bf77218e..2af8477ab54 100644 --- a/src/tools/unlock_all_mutexes.cpp +++ b/src/tools/unlock_all_mutexes.cpp @@ -1,22 +1,20 @@ #include "util/simple_logger.hpp" -#include "engine/datafacade/shared_barriers.hpp" +#include "storage/shared_barriers.hpp" #include -int main() +int main() try { osrm::util::LogPolicy::GetInstance().Unmute(); - try - { - osrm::util::SimpleLogger().Write() << "Releasing all locks"; - osrm::engine::datafacade::SharedBarriers barrier; - barrier.pending_update_mutex.unlock(); - barrier.query_mutex.unlock(); - barrier.update_mutex.unlock(); - } - catch (const std::exception &e) - { - osrm::util::SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what(); - } + osrm::util::SimpleLogger().Write() << "Releasing all locks"; + osrm::storage::SharedBarriers barrier; + barrier.pending_update_mutex.unlock(); + barrier.query_mutex.unlock(); + barrier.update_mutex.unlock(); return 0; } +catch (const std::exception &e) +{ + osrm::util::SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what(); + return EXIT_FAILURE; +} diff --git a/test/data/Makefile b/test/data/Makefile new file mode 100755 index 00000000000..a21afa7f53d --- /dev/null +++ b/test/data/Makefile @@ -0,0 +1,29 @@ +BERLIN_URL:=https://s3.amazonaws.com/mapbox/node-osrm/testing/berlin-latest.osm.pbf +TOOL_ROOT:=../../build +PROFILE_ROOT:=../../profiles +OSRM_EXTRACT:=$(TOOL_ROOT)/osrm-extract +OSRM_PREPARE:=$(TOOL_ROOT)/osrm-prepare +PROFILE:=$(PROFILE_ROOT)/car.lua + +all: berlin-latest.osrm.hsgr + +clean: + rm berlin-latest.* + +berlin-latest.osm.pbf: + wget $(BERLIN_URL) -O berlin-latest.osm.pbf + +berlin-latest.osrm: berlin-latest.osm.pbf $(PROFILE) $(OSRM_EXTRACT) + @echo "Verifiyng data file integrity..." + md5sum -c data.md5sum + @echo "Running osrm-extract..." + $(OSRM_EXTRACT) berlin-latest.osm.pbf -p $(PROFILE) + +berlin-latest.osrm.hsgr: berlin-latest.osrm $(PROFILE) $(OSRM_PREPARE) + @echo "Running osrm-prepare..." + $(OSRM_PREPARE) berlin-latest.osrm -p $(PROFILE) + +checksum: + md5sum berlin-latest.osm.pbf > data.md5sum + +.PHONY: clean checksum diff --git a/test/data/data.md5sum b/test/data/data.md5sum new file mode 100644 index 00000000000..008701a4669 --- /dev/null +++ b/test/data/data.md5sum @@ -0,0 +1 @@ +045af81d07eb9f22e5718db13cf337e4 berlin-latest.osm.pbf diff --git a/unit_tests/io_tests.cpp b/unit_tests/io_tests.cpp deleted file mode 100644 index 4b0d83b567e..00000000000 --- a/unit_tests/io_tests.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#define BOOST_TEST_MODULE io tests - -#include - -/* - * This file will contain an automatically generated main function. - */ diff --git a/unit_tests/io/io.cpp b/unit_tests/util/io.cpp similarity index 100% rename from unit_tests/io/io.cpp rename to unit_tests/util/io.cpp