Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6bdf95dfb4 | |||
| 785ae89cd8 | |||
| 16680191de | |||
| 59b70c4d11 | |||
| f96bae40ac | |||
| ba974c73bf | |||
| e498ad3ee7 | |||
| 1de031ed06 | |||
| d6ac924b94 | |||
| ee24473cbb | |||
| c19a3cec1c | |||
| f3694be1a0 | |||
| 306d86ce58 | |||
| 2c001b63a5 | |||
| e162dda836 | |||
| 10c532bd4c | |||
| c8a7bc1d6a | |||
| 9ca3c69b49 | |||
| d1cf8c1fd5 | |||
| 018742f50f | |||
| b82d21f856 | |||
| cfaadf198f | |||
| 6698b5e07e | |||
| 37794a5e8a | |||
| a88fef2937 | |||
| da474a16a9 | |||
| 59bbfeb67f | |||
| 4e9e2ed5bd | |||
| e0593c7ca2 | |||
| 1f69df0d89 | |||
| 05706879a0 | |||
| 7e49b36198 | |||
| 56bcb491d3 | |||
| f4e2bd848d | |||
| 0cf96314a3 | |||
| 91e24cab9e | |||
| 288155ead0 | |||
| 85454857d3 | |||
| fe50f6590a | |||
| 2da5da3f16 | |||
| 446c865415 | |||
| 0072bf0c59 | |||
| 4ec7ca29f1 | |||
| d94017dfae | |||
| dce0ce0e17 | |||
| d61102e255 | |||
| 7f6e0c478b | |||
| 786a3d8919 | |||
| ef3fcdc6e6 | |||
| 90c194fc81 | |||
| 5ed686a17b | |||
| 4e3009260c | |||
| c87ce2dede | |||
| 99a87b4c83 | |||
| 3f5fc1e897 | |||
| 97d1de1beb | |||
| d7e1c9c09c | |||
| 865111bca9 | |||
| 08d62cd5e3 | |||
| 603e2ee7de | |||
| 98948989d0 | |||
| 1aa8cc3b65 | |||
| c487d1307e | |||
| 604f4957f7 | |||
| 7726576bb7 | |||
| cf17a3a4c3 | |||
| 0972ec9115 | |||
| f660ae30dc | |||
| 2766c24b42 | |||
| cab83555e1 | |||
| 48a098a9c7 | |||
| a1fa1c610c | |||
| 905ca69301 | |||
| d66cc125aa | |||
| 3fc0fc65f9 | |||
| 8c64b01d67 | |||
| 2566f64c34 | |||
| 8cd40b9e90 | |||
| 45df8568b6 | |||
| 0da041477b | |||
| 272ea9b92e | |||
| 571681d019 | |||
| 9b614c6057 | |||
| 721f319909 | |||
| a3621f3655 | |||
| 789311abd6 | |||
| 091a495632 | |||
| 16665aeb00 | |||
| d6e56c38d5 | |||
| 87874006c7 | |||
| 703588b684 | |||
| b21ee1b63b | |||
| 427437d49b | |||
| 01deefc3bc | |||
| 157ca9161f | |||
| 266e65e6d2 | |||
| 70b3962c35 |
+120
-13
@@ -16,6 +16,7 @@ notifications:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- "5.7"
|
||||
# enable building tags
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
@@ -132,11 +133,112 @@ matrix:
|
||||
#- packages: ['clang-4.0', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
|
||||
# Node build jobs. These skip running the tests.
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-4-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
||||
nodejs: "4"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-4-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
||||
nodejs: "4"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-6-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
||||
nodejs: "6"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
- os: linux
|
||||
sudo: false
|
||||
compiler: "node-6-mason-linux-release"
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev']
|
||||
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON ENABLE_NODE_BINDINGS=ON PUBLISH_NODE_BINDINGS=On JOBS=4
|
||||
nodejs: "6"
|
||||
install:
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
script:
|
||||
- npm run nodejs-tests
|
||||
after_success:
|
||||
- ./scripts/travis/publish.sh
|
||||
|
||||
before_install:
|
||||
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
export JOBS=$((`nproc` + 1))
|
||||
if [[ -z $JOBS ]]; then
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
export JOBS=$((`nproc` + 1))
|
||||
elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
||||
fi
|
||||
fi
|
||||
- |
|
||||
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
||||
@@ -144,8 +246,10 @@ before_install:
|
||||
fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
export JOBS=$((`sysctl -n hw.ncpu` + 1))
|
||||
sudo mdutil -i off /
|
||||
fi
|
||||
- |
|
||||
if [[ ! -f $(which yarn) ]]; then
|
||||
npm install -g yarn
|
||||
fi
|
||||
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
|
||||
@@ -173,15 +277,17 @@ before_install:
|
||||
fi
|
||||
fi
|
||||
- ccache --max-size=256M # limiting the cache's size to roughly the previous job's object sizes
|
||||
- export OSRM_INSTALL_DIR="$(pwd)/install-osrm"
|
||||
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
|
||||
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
||||
- mkdir ${OSRM_BUILD_DIR}
|
||||
|
||||
install:
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
fi
|
||||
- export OSRM_BUILD_DIR="$(pwd)/build-osrm"
|
||||
- mkdir ${OSRM_BUILD_DIR} && pushd ${OSRM_BUILD_DIR}
|
||||
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
||||
- pushd ${OSRM_BUILD_DIR}
|
||||
- |
|
||||
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
|
||||
@@ -191,7 +297,8 @@ install:
|
||||
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
|
||||
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
|
||||
-DBUILD_TOOLS=ON \
|
||||
-DENABLE_CCACHE=ON
|
||||
-DENABLE_CCACHE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
|
||||
- echo "travis_fold:start:MAKE"
|
||||
- make --jobs=${JOBS}
|
||||
- make tests --jobs=${JOBS}
|
||||
@@ -201,10 +308,11 @@ install:
|
||||
- sudo make install
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
sudo ldconfig
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${OSRM_INSTALL_DIR}/lib
|
||||
fi
|
||||
- popd
|
||||
- mkdir example/build && pushd example/build
|
||||
- export PKG_CONFIG_PATH=${OSRM_INSTALL_DIR}/lib/pkgconfig
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
- make --jobs=${JOBS}
|
||||
- popd
|
||||
@@ -223,6 +331,10 @@ script:
|
||||
- ./unit_tests/util-tests
|
||||
- ./unit_tests/server-tests
|
||||
- ./unit_tests/partition-tests
|
||||
- |
|
||||
if [ -n "${ENABLE_NODE_BINDINGS}" ] && [ -z "${ENABLE_SANITIZER}" ]; then
|
||||
npm run nodejs-tests
|
||||
fi
|
||||
- popd
|
||||
- yarn test
|
||||
|
||||
@@ -231,8 +343,3 @@ after_success:
|
||||
if [ -n "${ENABLE_COVERAGE}" ]; then
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
fi
|
||||
|
||||
- |
|
||||
if [ -n "${ENABLE_NODE_BINDINGS}" ]; then
|
||||
./scripts/travis/publish.sh
|
||||
fi
|
||||
|
||||
+13
-2
@@ -1,17 +1,28 @@
|
||||
- Track preprocessing flag in the map matching plugin.
|
||||
|
||||
# 5.7.0
|
||||
- Changes from 5.6
|
||||
- Algorithm:
|
||||
- OSRM object has new option `algorithm` that allows the selection of a routing algorithm.
|
||||
- New experimental algorithm: Multi-Level Dijkstra with new toolchain:
|
||||
- Allows for fast metric updates in below a minute on continental sized networks (osrm-customize)
|
||||
- Plugins supported: `match` and `route`
|
||||
- Quickstart: `osrm-extract data.osm.pbf`, `osrm-partition data.osrm`, `osrm-customize data.osrm`, `osrm-routed --algorithm=MLD data.osrm`
|
||||
- NodeJs Bindings
|
||||
- Merged https://github.com/Project-OSRM/node-osrm into repository. Build via `cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On -DENABLE_MASON=On`.
|
||||
- `OSRM` object has new option `algorihtm="CH","CoreCH","MLD"`
|
||||
- Internals
|
||||
- Shared memory notification via conditional variables on Linux or semaphore queue on OS X and Windows with a limit of 128 OSRM Engine instances
|
||||
- Files
|
||||
- .osrm.datasource_index file was removed. Data is now part of .osrm.geometries.
|
||||
- .osrm.edge_lookup was removed. The option `--generate-edge-lookup` does nothing now.
|
||||
- `osrm-contract` does not depend on the `.osrm.fileIndex` file anymore
|
||||
- `osrm-extract` creates new file `.osrm.cnbg` and `.cnbg_to_ebg`
|
||||
- `osrm-partition` creates new file `.osrm.partition` and `.osrm.cells`
|
||||
- `osrm-customize` creates new file `.osrm.mldgr`
|
||||
- Profiles
|
||||
- Added `force_split_edges` flag to global properties. True value guarantees that segment_function will be called for all segments, but also could double memory consumption
|
||||
- Map Matching:
|
||||
- new option `gaps=split|ignore` to enable/disbale track splitting
|
||||
- new option `tidy=true|false` to simplify traces automatically
|
||||
|
||||
# 5.6.3
|
||||
- Changes from 5.6.0
|
||||
|
||||
@@ -303,6 +303,8 @@ endif()
|
||||
if (ENABLE_SANITIZER)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -fsanitize=address")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
# Configuring compilers
|
||||
|
||||
@@ -37,27 +37,35 @@ Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
|
||||
|
||||
## Quick Start
|
||||
|
||||
The easiest and quickest way to setup your own routing engine backend is to use Docker images we provide.
|
||||
The easiest and quickest way to setup your own routing engine is to use Docker images we provide.
|
||||
|
||||
### Using Docker
|
||||
|
||||
We base [our Docker images](https://hub.docker.com/r/osrm/osrm-backend/) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
We base our Docker images ([backend](https://hub.docker.com/r/osrm/osrm-backend/), [frontend](https://hub.docker.com/r/osrm/osrm-frontend/)) on Alpine Linux and make sure they are as lightweight as possible.
|
||||
|
||||
```
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
|
||||
Download OpenStreetMap extracts for example from [Geofabrik](http://download.geofabrik.de/)
|
||||
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
|
||||
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
|
||||
|
||||
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
|
||||
```
|
||||
Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000
|
||||
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf
|
||||
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-contract /data/berlin-latest.osrm
|
||||
|
||||
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed /data/berlin-latest.osrm
|
||||
|
||||
Make requests against the HTTP server
|
||||
|
||||
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
|
||||
|
||||
Optionally start a user-friendly frontend on port 9966, and open it up in your browser
|
||||
|
||||
docker run -p 9966:9966 osrm/osrm-frontend
|
||||
xdg-open 'http://127.0.0.1:9966'
|
||||
|
||||
In case Docker complains about not being able to connect to the Docker daemon make sure you are in the `docker` group.
|
||||
|
||||
```
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
After adding yourself to the `docker` group make sure to log out and back in again with your terminal.
|
||||
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
# Vendored NodeJs.cmake to bootstrap our C++ build without
|
||||
# having the user to install Node modules via `npm install`.
|
||||
#
|
||||
# Update via: ../node_modules/.bin/ncmake update
|
||||
|
||||
|
||||
# Defaults for standard Node.js builds
|
||||
set(NODEJS_DEFAULT_URL https://nodejs.org/download/release)
|
||||
set(NODEJS_DEFAULT_VERSION installed)
|
||||
set(NODEJS_VERSION_FALLBACK latest)
|
||||
set(NODEJS_DEFAULT_NAME node)
|
||||
set(NODEJS_DEFAULT_CHECKSUM SHASUMS256.txt)
|
||||
set(NODEJS_DEFAULT_CHECKTYPE SHA256)
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Find a path by walking upward from a base directory until the path is
|
||||
# found. Sets the variable ${PATH} to False if the path can't
|
||||
# be determined
|
||||
function(find_path_parent NAME BASE PATH)
|
||||
set(ROOT ${BASE})
|
||||
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
|
||||
set(DRIVE "^[A-Za-z]?:?/$")
|
||||
while(NOT ROOT MATCHES ${DRIVE} AND NOT EXISTS ${ROOT}/${NAME})
|
||||
get_filename_component(ROOT ${ROOT} DIRECTORY)
|
||||
set(${PATH} ${ROOT}/${NAME} PARENT_SCOPE)
|
||||
endwhile()
|
||||
if(ROOT MATCHES ${DRIVE})
|
||||
set(${PATH} False PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Shortcut for finding standard node module locations
|
||||
macro(find_nodejs_module NAME BASE PATH)
|
||||
find_path_parent(node_modules/${NAME} ${BASE} ${PATH})
|
||||
endmacro()
|
||||
|
||||
# Download with a bit of nice output (without spewing progress)
|
||||
function(download_file URL)
|
||||
message(STATUS "Downloading: ${URL}")
|
||||
file(DOWNLOAD
|
||||
${URL}
|
||||
${ARGN}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Embedded win_delay_load_hook file so that this file can be copied
|
||||
# into projects directly (recommended practice)
|
||||
function(nodejs_generate_delayload_hook OUTPUT)
|
||||
file(WRITE ${OUTPUT} "")
|
||||
file(APPEND ${OUTPUT} "/*\n")
|
||||
file(APPEND ${OUTPUT} " * When this file is linked to a DLL, it sets up a delay-load hook that\n")
|
||||
file(APPEND ${OUTPUT} " * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe'\n")
|
||||
file(APPEND ${OUTPUT} " * dynamically. Instead of trying to locate the .exe file it'll just return\n")
|
||||
file(APPEND ${OUTPUT} " * a handle to the process image.\n")
|
||||
file(APPEND ${OUTPUT} " *\n")
|
||||
file(APPEND ${OUTPUT} " * This allows compiled addons to work when node.exe or iojs.exe is renamed.\n")
|
||||
file(APPEND ${OUTPUT} " */\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifdef _MSC_VER\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifndef DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
|
||||
file(APPEND ${OUTPUT} "#define DELAYIMP_INSECURE_WRITABLE_HOOKS\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#ifndef WIN32_LEAN_AND_MEAN\n")
|
||||
file(APPEND ${OUTPUT} "#define WIN32_LEAN_AND_MEAN\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#include <windows.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <Shlwapi.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <delayimp.h>\n")
|
||||
file(APPEND ${OUTPUT} "#include <string.h>\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) {\n")
|
||||
file(APPEND ${OUTPUT} " if (event != dliNotePreLoadLibrary) return NULL;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " if (_stricmp(info->szDll, \"iojs.exe\") != 0 &&\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.exe\") != 0 &&\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(info->szDll, \"node.dll\") != 0)\n")
|
||||
file(APPEND ${OUTPUT} " return NULL;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get a handle to the current process executable.\n")
|
||||
file(APPEND ${OUTPUT} " HMODULE processModule = GetModuleHandle(NULL);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get the path to the executable.\n")
|
||||
file(APPEND ${OUTPUT} " TCHAR processPath[_MAX_PATH];\n")
|
||||
file(APPEND ${OUTPUT} " GetModuleFileName(processModule, processPath, _MAX_PATH);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Get the name of the current executable.\n")
|
||||
file(APPEND ${OUTPUT} " LPSTR processName = PathFindFileName(processPath);\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // If the current process is node or iojs, then just return the proccess \n")
|
||||
file(APPEND ${OUTPUT} " // module.\n")
|
||||
file(APPEND ${OUTPUT} " if (_stricmp(processName, \"node.exe\") == 0 ||\n")
|
||||
file(APPEND ${OUTPUT} " _stricmp(processName, \"iojs.exe\") == 0) {\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
|
||||
file(APPEND ${OUTPUT} " }\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // If it is another process, attempt to load 'node.dll' from the same \n")
|
||||
file(APPEND ${OUTPUT} " // directory.\n")
|
||||
file(APPEND ${OUTPUT} " PathRemoveFileSpec(processPath);\n")
|
||||
file(APPEND ${OUTPUT} " PathAppend(processPath, \"node.dll\");\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " HMODULE nodeDllModule = GetModuleHandle(processPath);\n")
|
||||
file(APPEND ${OUTPUT} " if(nodeDllModule != NULL) {\n")
|
||||
file(APPEND ${OUTPUT} " // This application has a node.dll in the same directory as the executable,\n")
|
||||
file(APPEND ${OUTPUT} " // use that.\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) nodeDllModule;\n")
|
||||
file(APPEND ${OUTPUT} " }\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} " // Fallback to the current executable, which must statically link to \n")
|
||||
file(APPEND ${OUTPUT} " // node.lib\n")
|
||||
file(APPEND ${OUTPUT} " return (FARPROC) processModule;\n")
|
||||
file(APPEND ${OUTPUT} "}\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "PfnDliHook __pfnDliNotifyHook2 = load_exe_hook;\n")
|
||||
file(APPEND ${OUTPUT} "\n")
|
||||
file(APPEND ${OUTPUT} "#endif\n")
|
||||
endfunction()
|
||||
|
||||
# Sets up a project to build Node.js native modules
|
||||
# - Downloads required dependencies and unpacks them to the build directory.
|
||||
# Internet access is required the first invocation but not after (
|
||||
# provided the download is successful)
|
||||
# - Sets up several variables for building against the downloaded
|
||||
# dependencies
|
||||
# - Guarded to prevent multiple executions, so a single project hierarchy
|
||||
# will only call this once
|
||||
function(nodejs_init)
|
||||
# Prevents this function from executing more than once
|
||||
if(NODEJS_INIT)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Regex patterns used by the init function for component extraction
|
||||
set(HEADERS_MATCH "^([A-Fa-f0-9]+)[ \t]+([^-]+)-(headers|v?[0-9.]+)-(headers|v?[0-9.]+)([.]tar[.]gz)$")
|
||||
set(LIB32_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-x86)?(/)?([^/]*)(.lib)$")
|
||||
set(LIB64_MATCH "(^[0-9A-Fa-f]+)[\t ]+(win-)?(x64/)(.*)(.lib)$")
|
||||
|
||||
# Parse function arguments
|
||||
cmake_parse_arguments(nodejs_init
|
||||
"" "URL;NAME;VERSION;CHECKSUM;CHECKTYPE" "" ${ARGN}
|
||||
)
|
||||
|
||||
# Allow the download URL to be overridden by command line argument
|
||||
# NODEJS_URL
|
||||
if(NODEJS_URL)
|
||||
set(URL ${NODEJS_URL})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(URL ${NODEJS_DEFAULT_URL})
|
||||
if(nodejs_init_URL)
|
||||
set(URL ${nodejs_init_URL})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow name to be overridden by command line argument NODEJS_NAME
|
||||
if(NODEJS_NAME)
|
||||
set(NAME ${NODEJS_NAME})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(NAME ${NODEJS_DEFAULT_NAME})
|
||||
if(nodejs_init_NAME)
|
||||
set(NAME ${nodejs_init_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the checksum file to be overridden by command line argument
|
||||
# NODEJS_CHECKSUM
|
||||
if(NODEJS_CHECKSUM)
|
||||
set(CHECKSUM ${NODEJS_CHECKSUM})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(CHECKSUM ${NODEJS_DEFAULT_CHECKSUM})
|
||||
if(nodejs_init_CHECKSUM)
|
||||
set(CHECKSUM ${nodejs_init_CHECKSUM})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the checksum type to be overriden by the command line argument
|
||||
# NODEJS_CHECKTYPE
|
||||
if(NODEJS_CHECKTYPE)
|
||||
set(CHECKTYPE ${NODEJS_CHECKTYPE})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(CHECKTYPE ${NODEJS_DEFAULT_CHECKTYPE})
|
||||
if(nodejs_init_CHECKTYPE)
|
||||
set(CHECKTYPE ${nodejs_init_CHECKTYPE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Allow the version to be overridden by the command line argument
|
||||
# NODEJS_VERSION
|
||||
if(NODEJS_VERSION)
|
||||
set(VERSION ${NODEJS_VERSION})
|
||||
else()
|
||||
# Use the argument if specified, falling back to the default
|
||||
set(VERSION ${NODEJS_DEFAULT_VERSION})
|
||||
if(nodejs_init_VERSION)
|
||||
set(VERSION ${nodejs_init_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# "installed" is a special version that tries to use the currently
|
||||
# installed version (determined by running node)
|
||||
set(NODEJS_INSTALLED False CACHE BOOL "Node.js install status" FORCE)
|
||||
if(VERSION STREQUAL "installed")
|
||||
if(NOT NAME STREQUAL ${NODEJS_DEFAULT_NAME})
|
||||
message(FATAL_ERROR
|
||||
"'Installed' version identifier can only be used with"
|
||||
"the core Node.js library"
|
||||
)
|
||||
endif()
|
||||
# Fall back to the "latest" version if node isn't installed
|
||||
set(VERSION ${NODEJS_VERSION_FALLBACK})
|
||||
find_program(NODEJS_BINARY NAMES node nodejs)
|
||||
if(NODEJS_BINARY)
|
||||
execute_process(
|
||||
COMMAND ${NODEJS_BINARY} --version
|
||||
RESULT_VARIABLE INSTALLED_VERSION_RESULT
|
||||
OUTPUT_VARIABLE INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(INSTALLED_VERSION_RESULT STREQUAL "0")
|
||||
set(NODEJS_INSTALLED True CACHE BOOL
|
||||
"Node.js install status" FORCE
|
||||
)
|
||||
set(VERSION ${INSTALLED_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create a temporary download directory
|
||||
set(TEMP ${CMAKE_CURRENT_BINARY_DIR}/temp)
|
||||
if(EXISTS ${TEMP})
|
||||
file(REMOVE_RECURSE ${TEMP})
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${TEMP})
|
||||
|
||||
# Unless the target is special version "latest", the parameters
|
||||
# necessary to construct the root path are known
|
||||
if(NOT VERSION STREQUAL "latest")
|
||||
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
|
||||
# Extract checksums from the existing checksum file
|
||||
set(CHECKSUM_TARGET ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# If we're trying to determine the version or we haven't saved the
|
||||
# checksum file for this version, download it from the specified server
|
||||
if(VERSION STREQUAL "latest" OR
|
||||
(DEFINED ROOT AND NOT EXISTS ${ROOT}/CHECKSUM))
|
||||
if(DEFINED ROOT)
|
||||
# Clear away the old checksum in case the new one is different
|
||||
# and/or it fails to download
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
download_file(
|
||||
${URL}/${VERSION}/${CHECKSUM}
|
||||
${TEMP}/CHECKSUM
|
||||
INACTIVITY_TIMEOUT 10
|
||||
STATUS CHECKSUM_STATUS
|
||||
)
|
||||
list(GET CHECKSUM_STATUS 0 CHECKSUM_STATUS)
|
||||
if(CHECKSUM_STATUS GREATER 0)
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download checksum file"
|
||||
)
|
||||
endif()
|
||||
# Extract checksums from the temporary file
|
||||
set(CHECKSUM_TARGET ${TEMP}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# Extract the version, name, header archive and archive checksum
|
||||
# from the file. This first extract is what defines / specifies the
|
||||
# actual version number and name.
|
||||
file(STRINGS
|
||||
${CHECKSUM_TARGET} HEADERS_CHECKSUM
|
||||
REGEX ${HEADERS_MATCH}
|
||||
LIMIT_COUNT 1
|
||||
)
|
||||
if(NOT HEADERS_CHECKSUM)
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
if(DEFINED ROOT)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
message(FATAL_ERROR "Unable to extract header archive checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${HEADERS_MATCH} HEADERS_CHECKSUM ${HEADERS_CHECKSUM})
|
||||
set(HEADERS_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(NAME ${CMAKE_MATCH_2})
|
||||
if(CMAKE_MATCH_3 STREQUAL "headers")
|
||||
set(VERSION ${CMAKE_MATCH_4})
|
||||
else()
|
||||
set(VERSION ${CMAKE_MATCH_3})
|
||||
endif()
|
||||
set(HEADERS_ARCHIVE
|
||||
${CMAKE_MATCH_2}-${CMAKE_MATCH_3}-${CMAKE_MATCH_4}${CMAKE_MATCH_5}
|
||||
)
|
||||
# Make sure that the root directory exists, and that the checksum
|
||||
# file has been moved over from temp
|
||||
if(DEFINED ROOT)
|
||||
set(OLD_ROOT ${ROOT})
|
||||
endif()
|
||||
set(ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}/${VERSION})
|
||||
if(DEFINED OLD_ROOT AND NOT ROOT STREQUAL "${OLD_ROOT}")
|
||||
file(REMOVE ${TEMP}/CHECKSUM)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
message(FATAL_ERROR "Version/Name mismatch")
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${ROOT})
|
||||
if(EXISTS ${TEMP}/CHECKSUM)
|
||||
file(REMOVE ${ROOT}/CHECKSUM)
|
||||
file(RENAME ${TEMP}/CHECKSUM ${ROOT}/CHECKSUM)
|
||||
endif()
|
||||
|
||||
# Now that its fully resolved, report the name and version of Node.js being
|
||||
# used
|
||||
message(STATUS "NodeJS: Using ${NAME}, version ${VERSION}")
|
||||
|
||||
# Download the headers for the version being used
|
||||
# Theoretically, these could be found by searching the installed
|
||||
# system, but in practice, this can be error prone. They're provided
|
||||
# on the download servers, so just use the ones there.
|
||||
if(NOT EXISTS ${ROOT}/include)
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${HEADERS_ARCHIVE}
|
||||
${TEMP}/${HEADERS_ARCHIVE}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${HEADERS_CHECKSUM}
|
||||
STATUS HEADERS_STATUS
|
||||
)
|
||||
list(GET HEADERS_STATUS 0 HEADERS_STATUS)
|
||||
if(HEADER_STATUS GREATER 0)
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
message(FATAL_ERROR "Unable to download Node.js headers")
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xfz ${TEMP}/${HEADERS_ARCHIVE}
|
||||
WORKING_DIRECTORY ${TEMP}
|
||||
)
|
||||
|
||||
# This adapts the header extraction to support a number of different
|
||||
# header archive contents in addition to the one used by the
|
||||
# default Node.js library
|
||||
unset(NODEJS_HEADERS_PATH CACHE)
|
||||
find_path(NODEJS_HEADERS_PATH
|
||||
NAMES src include
|
||||
PATHS
|
||||
${TEMP}/${NAME}-${VERSION}-headers
|
||||
${TEMP}/${NAME}-${VERSION}
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}-headers
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}-${VERSION}
|
||||
${TEMP}/${NODEJS_DEFAULT_NAME}
|
||||
${TEMP}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(NOT NODEJS_HEADERS_PATH)
|
||||
message(FATAL_ERROR "Unable to find extracted headers folder")
|
||||
endif()
|
||||
|
||||
# Move the headers into a standard location with a standard layout
|
||||
file(REMOVE ${TEMP}/${HEADERS_ARCHIVE})
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
if(EXISTS ${NODEJS_HEADERS_PATH}/include/node)
|
||||
file(RENAME ${NODEJS_HEADERS_PATH}/include/node ${ROOT}/include)
|
||||
elseif(EXISTS ${NODEJS_HEADERS_PATH}/src)
|
||||
file(MAKE_DIRECTORY ${ROOT}/include)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/src)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find core headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/src/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/uv/include)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find libuv headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/uv/include/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/v8/include)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find v8 headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/v8/include/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
if(NOT EXISTS ${NODEJS_HEADERS_PATH}/deps/zlib)
|
||||
file(REMOVE_RECURSE ${ROOT}/include)
|
||||
message(FATAL_ERROR "Unable to find zlib headers")
|
||||
endif()
|
||||
file(COPY ${NODEJS_HEADERS_PATH}/deps/zlib/
|
||||
DESTINATION ${ROOT}/include
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${NODEJS_HEADERS_PATH})
|
||||
unset(NODEJS_HEADERS_PATH CACHE)
|
||||
endif()
|
||||
|
||||
# Only download the libraries on windows, since its the only place
|
||||
# its necessary. Note, this requires rerunning CMake if moving
|
||||
# a module from one platform to another (should happen automatically
|
||||
# with most generators)
|
||||
if(WIN32)
|
||||
# Download the win32 library for linking
|
||||
file(STRINGS
|
||||
${ROOT}/CHECKSUM LIB32_CHECKSUM
|
||||
LIMIT_COUNT 1
|
||||
REGEX ${LIB32_MATCH}
|
||||
)
|
||||
if(NOT LIB32_CHECKSUM)
|
||||
message(FATAL_ERROR "Unable to extract x86 library checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${LIB32_MATCH} LIB32_CHECKSUM ${LIB32_CHECKSUM})
|
||||
set(LIB32_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(LIB32_PATH win-x86)
|
||||
set(LIB32_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
|
||||
set(LIB32_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB32_NAME})
|
||||
if(NOT EXISTS ${ROOT}/${LIB32_PATH})
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${LIB32_TARGET}
|
||||
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${LIB32_CHECKSUM}
|
||||
STATUS LIB32_STATUS
|
||||
)
|
||||
list(GET LIB32_STATUS 0 LIB32_STATUS)
|
||||
if(LIB32_STATUS GREATER 0)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download Node.js windows library (32-bit)"
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${ROOT}/${LIB32_PATH})
|
||||
file(MAKE_DIRECTORY ${ROOT}/${LIB32_PATH})
|
||||
file(RENAME
|
||||
${TEMP}/${LIB32_PATH}/${LIB32_NAME}
|
||||
${ROOT}/${LIB32_PATH}/${LIB32_NAME}
|
||||
)
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB32_PATH})
|
||||
endif()
|
||||
|
||||
# Download the win64 library for linking
|
||||
file(STRINGS
|
||||
${ROOT}/CHECKSUM LIB64_CHECKSUM
|
||||
LIMIT_COUNT 1
|
||||
REGEX ${LIB64_MATCH}
|
||||
)
|
||||
if(NOT LIB64_CHECKSUM)
|
||||
message(FATAL_ERROR "Unable to extract x64 library checksum")
|
||||
endif()
|
||||
string(REGEX MATCH ${LIB64_MATCH} LIB64_CHECKSUM ${LIB64_CHECKSUM})
|
||||
set(LIB64_CHECKSUM ${CMAKE_MATCH_1})
|
||||
set(LIB64_PATH win-x64)
|
||||
set(LIB64_NAME ${CMAKE_MATCH_4}${CMAKE_MATCH_5})
|
||||
set(LIB64_TARGET ${CMAKE_MATCH_2}${CMAKE_MATCH_3}${LIB64_NAME})
|
||||
if(NOT EXISTS ${ROOT}/${LIB64_PATH})
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
|
||||
download_file(
|
||||
${URL}/${VERSION}/${LIB64_TARGET}
|
||||
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
|
||||
INACTIVITY_TIMEOUT 10
|
||||
EXPECTED_HASH ${CHECKTYPE}=${LIB64_CHECKSUM}
|
||||
STATUS LIB64_STATUS
|
||||
)
|
||||
list(GET LIB64_STATUS 0 LIB64_STATUS)
|
||||
if(LIB64_STATUS GREATER 0)
|
||||
message(FATAL_ERROR
|
||||
"Unable to download Node.js windows library (64-bit)"
|
||||
)
|
||||
endif()
|
||||
file(REMOVE_RECURSE ${ROOT}/${LIB64_PATH})
|
||||
file(MAKE_DIRECTORY ${ROOT}/${LIB64_PATH})
|
||||
file(RENAME
|
||||
${TEMP}/${LIB64_PATH}/${LIB64_NAME}
|
||||
${ROOT}/${LIB64_PATH}/${LIB64_NAME}
|
||||
)
|
||||
file(REMOVE_RECURSE ${TEMP}/${LIB64_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# The downloaded headers should always be set for inclusion
|
||||
list(APPEND INCLUDE_DIRS ${ROOT}/include)
|
||||
|
||||
# Look for the NAN module, and add it to the includes
|
||||
find_nodejs_module(
|
||||
nan
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
NODEJS_NAN_DIR
|
||||
)
|
||||
if(NODEJS_NAN_DIR)
|
||||
list(APPEND INCLUDE_DIRS ${NODEJS_NAN_DIR})
|
||||
endif()
|
||||
|
||||
# Under windows, we need a bunch of libraries (due to the way
|
||||
# dynamic linking works)
|
||||
if(WIN32)
|
||||
# Generate and use a delay load hook to allow the node binary
|
||||
# name to be changed while still loading native modules
|
||||
set(DELAY_LOAD_HOOK ${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c)
|
||||
nodejs_generate_delayload_hook(${DELAY_LOAD_HOOK})
|
||||
set(SOURCES ${DELAY_LOAD_HOOK})
|
||||
|
||||
# Necessary flags to get delayload working correctly
|
||||
list(APPEND LINK_FLAGS
|
||||
"-IGNORE:4199"
|
||||
"-DELAYLOAD:iojs.exe"
|
||||
"-DELAYLOAD:node.exe"
|
||||
"-DELAYLOAD:node.dll"
|
||||
)
|
||||
|
||||
# Core system libraries used by node
|
||||
list(APPEND LIBRARIES
|
||||
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
|
||||
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
|
||||
odbc32.lib Shlwapi.lib DelayImp.lib
|
||||
)
|
||||
|
||||
# Also link to the node stub itself (downloaded above)
|
||||
if(CMAKE_CL_64)
|
||||
list(APPEND LIBRARIES ${ROOT}/${LIB64_PATH}/${LIB64_NAME})
|
||||
else()
|
||||
list(APPEND LIBRARIES ${ROOT}/${LIB32_PATH}/${LIB32_NAME})
|
||||
endif()
|
||||
else()
|
||||
# Non-windows platforms should use these flags
|
||||
list(APPEND DEFINITIONS _LARGEFILE_SOURCE _FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
||||
# Special handling for OSX / clang to allow undefined symbols
|
||||
# Define is required by node on OSX
|
||||
if(APPLE)
|
||||
list(APPEND LINK_FLAGS "-undefined dynamic_lookup")
|
||||
list(APPEND DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
|
||||
endif()
|
||||
|
||||
# Export all settings for use as arguments in the rest of the build
|
||||
set(NODEJS_VERSION ${VERSION} PARENT_SCOPE)
|
||||
set(NODEJS_SOURCES ${SOURCES} PARENT_SCOPE)
|
||||
set(NODEJS_INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE)
|
||||
set(NODEJS_LIBRARIES ${LIBRARIES} PARENT_SCOPE)
|
||||
set(NODEJS_LINK_FLAGS ${LINK_FLAGS} PARENT_SCOPE)
|
||||
set(NODEJS_DEFINITIONS ${DEFINITIONS} PARENT_SCOPE)
|
||||
|
||||
# Prevents this function from executing more than once
|
||||
set(NODEJS_INIT TRUE PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Helper function for defining a node module
|
||||
# After nodejs_init, all of the settings and dependencies necessary to do
|
||||
# this yourself are defined, but this helps make sure everything is configured
|
||||
# correctly. Feel free to use it as a model to do this by hand (or to
|
||||
# tweak this configuration if you need something custom).
|
||||
function(add_nodejs_module NAME)
|
||||
# Validate name parameter (must be a valid C identifier)
|
||||
string(MAKE_C_IDENTIFIER ${NAME} ${NAME}_SYMBOL_CHECK)
|
||||
if(NOT "${NAME}" STREQUAL "${${NAME}_SYMBOL_CHECK}")
|
||||
message(FATAL_ERROR
|
||||
"Module name must be a valid C identifier. "
|
||||
"Suggested alternative: '${${NAME}_SYMBOL_CHECK}'"
|
||||
)
|
||||
endif()
|
||||
# Make sure node is initialized (variables set) before defining the module
|
||||
if(NOT NODEJS_INIT)
|
||||
message(FATAL_ERROR
|
||||
"Node.js has not been initialized. "
|
||||
"Call nodejs_init before adding any modules"
|
||||
)
|
||||
endif()
|
||||
# In order to match node-gyp, we need to build into type specific folders
|
||||
# ncmake takes care of this, but be sure to set CMAKE_BUILD_TYPE yourself
|
||||
# if invoking CMake directly
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
||||
message(FATAL_ERROR
|
||||
"Configuration type must be specified. "
|
||||
"Set CMAKE_BUILD_TYPE or use a different generator"
|
||||
)
|
||||
endif()
|
||||
|
||||
# A node module is a shared library
|
||||
add_library(${NAME} SHARED ${NODEJS_SOURCES} ${ARGN})
|
||||
# Add compiler defines for the module
|
||||
# Two helpful ones:
|
||||
# MODULE_NAME must match the name of the build library, define that here
|
||||
# ${NAME}_BUILD is for symbol visibility under windows
|
||||
string(TOUPPER "${NAME}_BUILD" ${NAME}_BUILD_DEF)
|
||||
target_compile_definitions(${NAME}
|
||||
PRIVATE MODULE_NAME=${NAME}
|
||||
PRIVATE ${${NAME}_BUILD_DEF}
|
||||
PUBLIC ${NODEJS_DEFINITIONS}
|
||||
)
|
||||
# This properly defines includes for the module
|
||||
target_include_directories(${NAME} PUBLIC ${NODEJS_INCLUDE_DIRS})
|
||||
|
||||
# Add link flags to the module
|
||||
target_link_libraries(${NAME} ${NODEJS_LIBRARIES})
|
||||
|
||||
# Set required properties for the module to build properly
|
||||
# Correct naming, symbol visiblity and C++ standard
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
OUTPUT_NAME ${NAME}
|
||||
PREFIX ""
|
||||
SUFFIX ".node"
|
||||
MACOSX_RPATH ON
|
||||
C_VISIBILITY_PRESET hidden
|
||||
CXX_VISIBILITY_PRESET hidden
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
CMAKE_CXX_STANDARD_REQUIRED TRUE
|
||||
CXX_STANDARD 11
|
||||
LINK_FLAGS "${NODEJS_LINK_FLAGS}"
|
||||
)
|
||||
|
||||
# Make sure we're buiilding in a build specific output directory
|
||||
# Only necessary on single-target generators (Make, Ninja)
|
||||
# Multi-target generators do this automatically
|
||||
# This (luckily) mirrors node-gyp conventions
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(TARGET ${NAME} PROPERTY
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,587 +0,0 @@
|
||||
# Copyright (c) 2015, Colin Taylor
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
# FindNodeJS.cmake CMake module vendored from the node-cmake project (v1.2).
|
||||
|
||||
# This script uses CMake 3.1+ features
|
||||
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0)
|
||||
message(FATAL_ERROR "FindNodeJS.cmake uses CMake 3.1+ features")
|
||||
endif()
|
||||
|
||||
# Force a build type to be set (ignored on config based generators)
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
|
||||
endif()
|
||||
|
||||
# Capture module information
|
||||
set(NodeJS_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
get_filename_component(NodeJS_MODULE_NAME ${NodeJS_MODULE_PATH} NAME)
|
||||
|
||||
# Allow users to specify the installed location of the Node.js package
|
||||
set(NodeJS_ROOT_DIR "" CACHE PATH
|
||||
"The root directory of the node.js installed package")
|
||||
|
||||
# Allow users to specify that downloaded sources should be used
|
||||
option(NodeJS_DOWNLOAD "Download the required source files" Off)
|
||||
|
||||
# Allow users to force downloading of node packages
|
||||
option(NodeJS_FORCE_DOWNLOAD "Download the source files every time" Off)
|
||||
|
||||
# Allow users to force archive extraction
|
||||
option(NodeJS_FORCE_EXTRACT "Extract the archive every time" Off)
|
||||
|
||||
# Make libc++ the default when compiling with clang
|
||||
option(NodeJS_USE_CLANG_STDLIB "Use libc++ when compiling with clang" On)
|
||||
if(APPLE)
|
||||
set(NodeJS_USE_CLANG_STDLIB On CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# Allow users to specify that the executable should be downloaded
|
||||
option(NodeJS_DOWNLOAD_EXECUTABLE
|
||||
"Download matching executable if available" Off
|
||||
)
|
||||
endif()
|
||||
|
||||
# Try to find the node.js executable
|
||||
# The node executable under linux may not be the correct program
|
||||
find_program(NodeJS_EXECUTABLE
|
||||
NAMES node
|
||||
PATHS ${NodeJS_ROOT_DIR}
|
||||
PATH_SUFFIXES nodejs node
|
||||
)
|
||||
set(NodeJS_VALIDATE_EXECUTABLE 1)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} --version
|
||||
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} -p "process.platform"
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_PLATFORM
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} -p "process.arch"
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_ARCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
# If node isn't the node.js binary, try the nodejs binary
|
||||
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
|
||||
find_program(NodeJS_EXECUTABLE
|
||||
NAMES nodejs
|
||||
PATHS ${NodeJS_ROOT_DIR}
|
||||
PATH_SUFFIXES nodejs node
|
||||
)
|
||||
set(NodeJS_VALIDATE_EXECUTABLE 1)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
execute_process(
|
||||
COMMAND ${NodeJS_EXECUTABLE} --version
|
||||
RESULT_VARIABLE NodeJS_VALIDATE_EXECUTABLE
|
||||
OUTPUT_VARIABLE NodeJS_INSTALLED_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_VALIDATE_EXECUTABLE EQUAL 0)
|
||||
message(WARNING "Node.js executable could not be found. \
|
||||
Set NodeJS_ROOT_DIR to the installed location of the executable or \
|
||||
install Node.js to its default location.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Determine if a variant is set in the components
|
||||
list(APPEND NodeJS_OTHER_COMPONENTS
|
||||
X64 IA32 ARM WIN32 LINUX DARWIN
|
||||
)
|
||||
set(NodeJS_COMPONENTS_CONTAINS_VARIANT False)
|
||||
foreach(NodeJS_COMPONENT ${NodeJS_FIND_COMPONENTS})
|
||||
list(FIND NodeJS_OTHER_COMPONENTS ${NodeJS_COMPONENT} NodeJS_OTHER_INDEX)
|
||||
if(NodeJS_OTHER_INDEX EQUAL -1)
|
||||
set(NodeJS_COMPONENTS_CONTAINS_VARIANT True)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Get the targeted version of Node.js (or one of its derivatives)
|
||||
if(NOT NodeJS_VERSION)
|
||||
if(NodeJS_FIND_VERSION)
|
||||
set(NodeJS_VERSION ${NodeJS_FIND_VERSION})
|
||||
elseif(NodeJS_INSTALLED_VERSION AND NOT NodeJS_COMPONENTS_CONTAINS_VARIANT)
|
||||
string(SUBSTRING ${NodeJS_INSTALLED_VERSION} 1 -1 NodeJS_VERSION)
|
||||
else()
|
||||
message(FATAL_ERROR "Node.js version is not set. Set the VERSION \
|
||||
property of the find_package command to the required version of the \
|
||||
Node.js sources")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Determine the target platform for the compiled module
|
||||
# Uses several mechanisms in order:
|
||||
#
|
||||
# 1. CMake cache (allows overriding on the command line)
|
||||
# 2. Node architecture when binary is available
|
||||
# 3. CMake architecture
|
||||
#
|
||||
set(NodeJS_PLATFORM "" CACHE STRING "Target node.js platform for module")
|
||||
if(NOT NodeJS_PLATFORM)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
set(NodeJS_PLATFORM ${NodeJS_INSTALLED_PLATFORM})
|
||||
elseif(WIN32)
|
||||
set(NodeJS_PLATFORM "win32")
|
||||
elseif(UNIX)
|
||||
if(APPLE)
|
||||
set(NodeJS_PLATFORM "darwin")
|
||||
else()
|
||||
set(NodeJS_PLATFORM "linux")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Node.js platform is not set. Add the platform \
|
||||
to the find_package components section or set NodeJS_PLATFORM in the \
|
||||
cache.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Convenience variables for the platform type
|
||||
if(NodeJS_PLATFORM STREQUAL "win32")
|
||||
set(NodeJS_PLATFORM_WIN32 True)
|
||||
set(NodeJS_PLATFORM_LINUX False)
|
||||
set(NodeJS_PLATFORM_DARWIN False)
|
||||
elseif(NodeJS_PLATFORM STREQUAL "linux")
|
||||
set(NodeJS_PLATFORM_WIN32 False)
|
||||
set(NodeJS_PLATFORM_LINUX True)
|
||||
set(NodeJS_PLATFORM_DARWIN False)
|
||||
elseif(NodeJS_PLATFORM STREQUAL "darwin")
|
||||
set(NodeJS_PLATFORM_WIN32 False)
|
||||
set(NodeJS_PLATFORM_LINUX False)
|
||||
set(NodeJS_PLATFORM_DARWIN True)
|
||||
endif()
|
||||
|
||||
# Determine the target architecture for the compiled module
|
||||
# Uses several mechanisms in order:
|
||||
#
|
||||
# 1. CMake cache (allows overriding on the command line)
|
||||
# 2. Node architecture when binary is available
|
||||
# 3. Compiler architecture under MSVC
|
||||
#
|
||||
set(NodeJS_ARCH "" CACHE STRING "Target node.js architecture for module")
|
||||
if(NOT NodeJS_ARCH)
|
||||
if(NodeJS_EXECUTABLE)
|
||||
set(NodeJS_ARCH ${NodeJS_INSTALLED_ARCH})
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(NodeJS_ARCH "x64")
|
||||
else()
|
||||
set(NodeJS_ARCH "ia32")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Node.js architecture is not set. Add the \
|
||||
architecture to the find_package components section or set NodeJS_ARCH \
|
||||
in the cache.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Convenience variables for the architecture
|
||||
if(NodeJS_ARCH STREQUAL "x64")
|
||||
set(NodeJS_ARCH_X64 True)
|
||||
set(NodeJS_ARCH_IA32 False)
|
||||
set(NodeJS_ARCH_ARM False)
|
||||
elseif(NodeJS_ARCH STREQUAL "ia32")
|
||||
set(NodeJS_ARCH_X64 False)
|
||||
set(NodeJS_ARCH_IA32 True)
|
||||
set(NodeJS_ARCH_ARM False)
|
||||
elseif(NodeJS_ARCH STREQUAL "arm")
|
||||
set(NodeJS_ARCH_X64 False)
|
||||
set(NodeJS_ARCH_IA32 False)
|
||||
set(NodeJS_ARCH_ARM True)
|
||||
endif()
|
||||
|
||||
# Include helper functions
|
||||
include(util/NodeJSUtil)
|
||||
|
||||
# Default variant name
|
||||
# Used by the installed header comparison below
|
||||
set(NodeJS_DEFAULT_VARIANT_NAME "node.js")
|
||||
|
||||
# Variables for Node.js artifacts across variants
|
||||
# Specify all of these variables for each new variant
|
||||
set(NodeJS_VARIANT_NAME "") # The printable name of the variant
|
||||
set(NodeJS_VARIANT_BASE "") # A file name safe version of the variant
|
||||
set(NodeJS_URL "") # The URL for the artifacts
|
||||
set(NodeJS_SOURCE_PATH "") # The URL path of the source archive
|
||||
set(NodeJS_CHECKSUM_PATH "") # The URL path of the checksum file
|
||||
set(NodeJS_CHECKSUM_TYPE "") # The checksum type (algorithm)
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "") # The URL path of the windows library
|
||||
set(NodeJS_WIN32_BINARY_PATH "") # The URL path of the windows executable
|
||||
set(NodeJS_WIN32_LIBRARY_NAME "") # The name of the windows library
|
||||
set(NodeJS_WIN32_BINARY_NAME "") # The name of the windows executable
|
||||
|
||||
set(NodeJS_DEFAULT_INCLUDE True) # Enable default include behavior
|
||||
set(NodeJS_DEFAULT_LIBS True) # Include the default libraries
|
||||
set(NodeJS_HAS_WIN32_PREFIX True) # Does the variant use library prefixes
|
||||
set(NodeJS_HAS_WIN32_BINARY True) # Does the variant have win32 executables
|
||||
set(NodeJS_HAS_OPENSSL True) # Does the variant include openssl headers
|
||||
set(NodeJS_HEADER_VERSION 0.12.7) # Version after header-only archives start
|
||||
set(NodeJS_SHA256_VERSION 0.7.0) # Version after sha256 checksums start
|
||||
set(NodeJS_PREFIX_VERSION 0.12.7) # Version after windows prefixing starts
|
||||
set(NodeJS_CXX11R_VERSION 0.12.7) # Version after c++11 is required
|
||||
set(NodeJS_SOURCE_INCLUDE True) # Use the include paths from a source archive
|
||||
set(NodeJS_HEADER_INCLUDE False) # Use the include paths from a header archive
|
||||
set(NodeJS_INCLUDE_PATHS "") # Set of header dirs inside the source archive
|
||||
set(NodeJS_LIBRARIES "") # The set of libraries to link with addon
|
||||
set(NodeJS_WIN32_DELAYLOAD "") # Set of executables to delayload on windows
|
||||
|
||||
# NodeJS variants
|
||||
# Selects download target based on configured component
|
||||
# Include NodeJS last to provide default configurations when omitted
|
||||
file(
|
||||
GLOB NodeJS_SUPPORTED_VARIANTS
|
||||
RELATIVE ${CMAKE_CURRENT_LIST_DIR}/variants
|
||||
${CMAKE_CURRENT_LIST_DIR}/variants/*
|
||||
)
|
||||
foreach(NodeJS_SUPPORTED_VARIANT ${NodeJS_SUPPORTED_VARIANTS})
|
||||
get_filename_component(NodeJS_SUPPORTED_VARIANT_NAME
|
||||
${NodeJS_SUPPORTED_VARIANT} NAME_WE
|
||||
)
|
||||
if(NOT NodeJS_SUPPORTED_VARIANT_NAME STREQUAL "NodeJS")
|
||||
include(variants/${NodeJS_SUPPORTED_VARIANT_NAME})
|
||||
endif()
|
||||
endforeach()
|
||||
include(variants/NodeJS)
|
||||
|
||||
# Populate version variables, including version components
|
||||
set(NodeJS_VERSION_STRING "v${NodeJS_VERSION}")
|
||||
|
||||
# Populate the remaining version variables
|
||||
string(REPLACE "." ";" NodeJS_VERSION_PARTS ${NodeJS_VERSION})
|
||||
list(GET NodeJS_VERSION_PARTS 0 NodeJS_VERSION_MAJOR)
|
||||
list(GET NodeJS_VERSION_PARTS 1 NodeJS_VERSION_MINOR)
|
||||
list(GET NodeJS_VERSION_PARTS 2 NodeJS_VERSION_PATCH)
|
||||
|
||||
# If the version we're looking for is the version that is installed,
|
||||
# try finding the required headers. Don't do this under windows (where
|
||||
# headers are not part of the installed content), when the user has
|
||||
# specified that headers should be downloaded or when using a variant other
|
||||
# than the default
|
||||
if((NOT NodeJS_PLATFORM_WIN32) AND (NOT NodeJS_DOWNLOAD) AND
|
||||
NodeJS_VARIANT_NAME STREQUAL NodeJS_DEFAULT_VARIANT_NAME AND
|
||||
NodeJS_INSTALLED_VERSION STREQUAL NodeJS_VERSION_STRING AND
|
||||
NodeJS_INSTALLED_PLATFORM STREQUAL NodeJS_PLATFORM AND
|
||||
NodeJS_INSTALLED_ARCH STREQUAL NodeJS_ARCH)
|
||||
# node.h is really generic and too easy for cmake to find the wrong
|
||||
# file, so use the directory as a guard, and then just tack it on to
|
||||
# the actual path
|
||||
#
|
||||
# Specifically ran into this under OSX, where python contains a node.h
|
||||
# that gets found instead
|
||||
find_path(NodeJS_INCLUDE_PARENT node/node.h)
|
||||
set(NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_PARENT}/node)
|
||||
|
||||
# Under all systems that support this, there are no libraries required
|
||||
# for linking (symbols are resolved via the main executable at runtime)
|
||||
set(NodeJS_LIBRARIES "")
|
||||
|
||||
# Otherwise, headers and required libraries must be downloaded to the project
|
||||
# to supplement what is installed
|
||||
else()
|
||||
# Create a folder for downloaded artifacts
|
||||
set(NodeJS_DOWNLOAD_PATH
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${NodeJS_VARIANT_BASE}
|
||||
)
|
||||
set(NodeJS_DOWNLOAD_PATH ${NodeJS_DOWNLOAD_PATH}-${NodeJS_VERSION_STRING})
|
||||
file(MAKE_DIRECTORY ${NodeJS_DOWNLOAD_PATH})
|
||||
|
||||
# Download the checksum file for validating all other downloads
|
||||
# Conveniently, if this doesn't download correctly, the setup fails
|
||||
# due to checksum failures
|
||||
set(NodeJS_CHECKSUM_FILE ${NodeJS_DOWNLOAD_PATH}/CHECKSUM)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_CHECKSUM_PATH}
|
||||
${NodeJS_CHECKSUM_FILE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
file(READ ${NodeJS_CHECKSUM_FILE} NodeJS_CHECKSUM_DATA)
|
||||
|
||||
# Download and extract the main source archive
|
||||
set(NodeJS_SOURCE_FILE ${NodeJS_DOWNLOAD_PATH}/headers.tar.gz)
|
||||
nodejs_checksum(
|
||||
${NodeJS_CHECKSUM_DATA} ${NodeJS_SOURCE_PATH} NodeJS_SOURCE_CHECKSUM
|
||||
)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_SOURCE_PATH}
|
||||
${NodeJS_SOURCE_FILE}
|
||||
${NodeJS_SOURCE_CHECKSUM}
|
||||
${NodeJS_CHECKSUM_TYPE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
set(NodeJS_HEADER_PATH ${NodeJS_DOWNLOAD_PATH}/src)
|
||||
nodejs_extract(
|
||||
${NodeJS_SOURCE_FILE}
|
||||
${NodeJS_HEADER_PATH}
|
||||
${NodeJS_FORCE_EXTRACT}
|
||||
)
|
||||
|
||||
# Populate include directories from the extracted source archive
|
||||
foreach(NodeJS_HEADER_BASE ${NodeJS_INCLUDE_PATHS})
|
||||
set(NodeJS_INCLUDE_DIR ${NodeJS_HEADER_PATH}/${NodeJS_HEADER_BASE})
|
||||
if(NOT EXISTS ${NodeJS_INCLUDE_DIR})
|
||||
message(FATAL_ERROR "Include does not exist: ${NodeJS_INCLUDE_DIR}")
|
||||
endif()
|
||||
list(APPEND NodeJS_INCLUDE_DIRS ${NodeJS_INCLUDE_DIR})
|
||||
endforeach()
|
||||
|
||||
# Download required library files when targeting windows
|
||||
if(NodeJS_PLATFORM_WIN32)
|
||||
# Download the windows library
|
||||
set(NodeJS_WIN32_LIBRARY_FILE
|
||||
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
|
||||
)
|
||||
set(NodeJS_WIN32_LIBRARY_FILE
|
||||
${NodeJS_WIN32_LIBRARY_FILE}/${NodeJS_WIN32_LIBRARY_NAME}
|
||||
)
|
||||
nodejs_checksum(
|
||||
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_LIBRARY_PATH}
|
||||
NodeJS_WIN32_LIBRARY_CHECKSUM
|
||||
)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_WIN32_LIBRARY_PATH}
|
||||
${NodeJS_WIN32_LIBRARY_FILE}
|
||||
${NodeJS_WIN32_LIBRARY_CHECKSUM}
|
||||
${NodeJS_CHECKSUM_TYPE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
list(APPEND NodeJS_LIBRARIES ${NodeJS_WIN32_LIBRARY_FILE})
|
||||
|
||||
# If provided, download the windows executable
|
||||
if(NodeJS_WIN32_BINARY_PATH AND
|
||||
NodeJS_DOWNLOAD_EXECUTABLE)
|
||||
set(NodeJS_WIN32_BINARY_FILE
|
||||
${NodeJS_DOWNLOAD_PATH}/lib/${NodeJS_ARCH}
|
||||
)
|
||||
set(NodeJS_WIN32_BINARY_FILE
|
||||
${NodeJS_WIN32_BINARY_FILE}/${NodeJS_WIN32_BINARY_NAME}
|
||||
)
|
||||
nodejs_checksum(
|
||||
${NodeJS_CHECKSUM_DATA} ${NodeJS_WIN32_BINARY_PATH}
|
||||
NodeJS_WIN32_BINARY_CHECKSUM
|
||||
)
|
||||
nodejs_download(
|
||||
${NodeJS_URL}/${NodeJS_WIN32_BINARY_PATH}
|
||||
${NodeJS_WIN32_BINARY_FILE}
|
||||
${NodeJS_WIN32_BINARY_CHECKSUM}
|
||||
${NodeJS_CHECKSUM_TYPE}
|
||||
${NodeJS_FORCE_DOWNLOAD}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Support windows delay loading
|
||||
if(NodeJS_PLATFORM_WIN32)
|
||||
list(APPEND NodeJS_LINK_FLAGS /IGNORE:4199)
|
||||
set(NodeJS_WIN32_DELAYLOAD_CONDITION "")
|
||||
foreach(NodeJS_WIN32_DELAYLOAD_BINARY ${NodeJS_WIN32_DELAYLOAD})
|
||||
list(APPEND NodeJS_LINK_FLAGS
|
||||
/DELAYLOAD:${NodeJS_WIN32_DELAYLOAD_BINARY}
|
||||
)
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD_CONDITION
|
||||
"_stricmp(info->szDll, \"${NodeJS_WIN32_DELAYLOAD_BINARY}\") != 0"
|
||||
)
|
||||
endforeach()
|
||||
string(REPLACE ";" " &&\n "
|
||||
NodeJS_WIN32_DELAYLOAD_CONDITION
|
||||
"${NodeJS_WIN32_DELAYLOAD_CONDITION}"
|
||||
)
|
||||
configure_file(
|
||||
${NodeJS_MODULE_PATH}/src/win_delay_load_hook.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c @ONLY
|
||||
)
|
||||
list(APPEND NodeJS_ADDITIONAL_SOURCES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/win_delay_load_hook.c
|
||||
)
|
||||
endif()
|
||||
|
||||
# Allow undefined symbols on OSX
|
||||
if(NodeJS_PLATFORM_DARWIN)
|
||||
list(APPEND NodeJS_LINK_FLAGS "-undefined dynamic_lookup")
|
||||
endif()
|
||||
|
||||
# Use libc++ when clang is the compiler by default
|
||||
if(NodeJS_USE_CLANG_STDLIB AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*")
|
||||
list(APPEND NodeJS_COMPILE_OPTIONS -stdlib=libc++)
|
||||
endif()
|
||||
|
||||
# Require c++11 support after a specific point, but only if the user hasn't
|
||||
# specified an override
|
||||
if(NOT NodeJS_CXX_STANDARD)
|
||||
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION)
|
||||
set(NodeJS_CXX_STANDARD 11)
|
||||
else()
|
||||
set(NodeJS_CXX_STANDARD 98)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set required definitions
|
||||
list(APPEND NodeJS_DEFINITIONS BUILDING_NODE_EXTENSION)
|
||||
if(NodeJS_PLATFORM_DARWIN)
|
||||
list(APPEND NodeJS_DEFINITIONS _DARWIN_USE_64_BIT_INODE=1)
|
||||
endif()
|
||||
if(NOT NodeJS_PLATFORM_WIN32)
|
||||
list(APPEND NodeJS_DEFINITIONS
|
||||
_LARGEFILE_SOURCE
|
||||
_FILE_OFFSET_BITS=64
|
||||
)
|
||||
endif()
|
||||
|
||||
function(add_nodejs_module NAME)
|
||||
# Build a shared library for the module
|
||||
add_library(${NAME} SHARED ${ARGN} ${NodeJS_ADDITIONAL_SOURCES})
|
||||
|
||||
# Include required headers
|
||||
# Find and include Nan as well (always available as its a
|
||||
# dependency of this module)
|
||||
nodejs_find_module_fallback(nan ${CMAKE_CURRENT_SOURCE_DIR} NAN_PATH)
|
||||
target_include_directories(${NAME}
|
||||
PUBLIC ${NodeJS_INCLUDE_DIRS}
|
||||
PUBLIC ${NAN_PATH}
|
||||
)
|
||||
|
||||
# Set module properties
|
||||
# This ensures proper naming of the module library across all platforms
|
||||
get_target_property(COMPILE_OPTIONS ${NAME} COMPILE_OPTIONS)
|
||||
if(NOT COMPILE_OPTIONS)
|
||||
set(COMPILE_OPTIONS "")
|
||||
endif()
|
||||
set(COMPILE_OPTIONS ${COMPILE_OPTIONS} ${NodeJS_COMPILE_OPTIONS})
|
||||
get_target_property(LINK_FLAGS ${NAME} LINK_FLAGS)
|
||||
if(NOT LINK_FLAGS)
|
||||
set(LINK_FLAGS "")
|
||||
endif()
|
||||
foreach(NodeJS_LINK_FLAG ${NodeJS_LINK_FLAGS})
|
||||
set(LINK_FLAGS "${LINK_FLAGS} ${NodeJS_LINK_FLAG}")
|
||||
endforeach()
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
PREFIX ""
|
||||
SUFFIX ".node"
|
||||
MACOSX_RPATH ON
|
||||
POSITION_INDEPENDENT_CODE TRUE
|
||||
COMPILE_OPTIONS "${COMPILE_OPTIONS}"
|
||||
LINK_FLAGS "${LINK_FLAGS}"
|
||||
CXX_STANDARD_REQUIRED TRUE
|
||||
CXX_STANDARD ${NodeJS_CXX_STANDARD}
|
||||
)
|
||||
|
||||
# Output the module in a per build type directory
|
||||
# This makes builds consistent with visual studio and other generators
|
||||
# that build by configuration
|
||||
if(NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(TARGET ${NAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY
|
||||
${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set any required complier flags
|
||||
# Mostly used under windows
|
||||
target_compile_definitions(${NAME} PRIVATE ${NodeJS_DEFINITIONS})
|
||||
|
||||
# Link against required NodeJS libraries
|
||||
target_link_libraries(${NAME} ${NodeJS_LIBRARIES})
|
||||
endfunction()
|
||||
|
||||
# Write out the configuration for node scripts
|
||||
configure_file(
|
||||
${NodeJS_MODULE_PATH}/build.json.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/build.json @ONLY
|
||||
)
|
||||
|
||||
# Make sure we haven't violated the version-to-standard mapping
|
||||
if(NodeJS_VERSION VERSION_GREATER NodeJS_CXX11R_VERSION AND
|
||||
NodeJS_CXX_STANDARD EQUAL 98)
|
||||
message(FATAL_ERROR "${NodeJS_VARIANT_NAME} ${NodeJS_VERSION} \
|
||||
requires C++11 or newer to build")
|
||||
endif()
|
||||
|
||||
# This is a find_package file, handle the standard invocation
|
||||
include(FindPackageHandleStandardArgs)
|
||||
set(NodeJS_TARGET "${NodeJS_VARIANT_NAME} ${NodeJS_PLATFORM}/${NodeJS_ARCH}")
|
||||
find_package_handle_standard_args(NodeJS
|
||||
FOUND_VAR NodeJS_FOUND
|
||||
REQUIRED_VARS NodeJS_TARGET NodeJS_INCLUDE_DIRS
|
||||
VERSION_VAR NodeJS_VERSION
|
||||
)
|
||||
|
||||
# Mark variables that users shouldn't modify
|
||||
mark_as_advanced(
|
||||
NodeJS_VALIDATE_EXECUTABLE
|
||||
NodeJS_OTHER_COMPONENTS
|
||||
NodeJS_COMPONENTS_CONTAINS_VARIANT
|
||||
NodeJS_COMPONENT
|
||||
NodeJS_OTHER_INDEX
|
||||
NodeJS_VERSION_STRING
|
||||
NodeJS_VERSION_MAJOR
|
||||
NodeJS_VERSION_MINOR
|
||||
NodeJS_VERSION_PATCH
|
||||
NodeJS_VERSION_TWEAK
|
||||
NodeJS_PLATFORM
|
||||
NodeJS_PLATFORM_WIN32
|
||||
NodeJS_PLATFORM_LINUX
|
||||
NodeJS_PLATFORM_DARWIN
|
||||
NodeJS_ARCH
|
||||
NodeJS_ARCH_X64
|
||||
NodeJS_ARCH_IA32
|
||||
NodeJS_ARCH_ARM
|
||||
NodeJS_DEFAULT_VARIANT_NAME
|
||||
NodeJS_VARIANT_BASE
|
||||
NodeJS_VARIANT_NAME
|
||||
NodeJS_URL
|
||||
NodeJS_SOURCE_PATH
|
||||
NodeJS_CHECKSUM_PATH
|
||||
NodeJS_CHECKSUM_TYPE
|
||||
NodeJS_WIN32_LIBRARY_PATH
|
||||
NodeJS_WIN32_BINARY_PATH
|
||||
NodeJS_WIN32_LIBRARY_NAME
|
||||
NodeJS_WIN32_BINARY_NAME
|
||||
NodeJS_DEFAULT_INCLUDE
|
||||
NodeJS_DEFAULT_LIBS
|
||||
NodeJS_HAS_WIN32_BINARY
|
||||
NodeJS_HEADER_VERSION
|
||||
NodeJS_SHA256_VERISON
|
||||
NodeJS_PREFIX_VERSION
|
||||
NodeJS_SOURCE_INCLUDE
|
||||
NodeJS_HEADER_INCLUDE
|
||||
NodeJS_INCLUDE_PATHS
|
||||
NodeJS_WIN32_DELAYLOAD
|
||||
NodeJS_DOWNLOAD_PATH
|
||||
NodeJS_CHECKSUM_FILE
|
||||
NodeJS_CHECKSUM_DATA
|
||||
NodeJS_SOURCE_FILE
|
||||
NodeJS_SOURCE_CHECKSUM
|
||||
NodeJS_HEADER_PATH
|
||||
NodeJS_HEADER_BASE
|
||||
NodeJS_INCLUDE_DIR
|
||||
NodeJS_WIN32_LIBRARY_FILE
|
||||
NodeJS_WIN32_LIBRARY_CHECKSUM
|
||||
NodeJS_WIN32_BINARY_FILE
|
||||
NodeJS_WIN32_BINARY_CHECKSUM
|
||||
NodeJS_NAN_PATH
|
||||
NodeJS_LINK_FLAGS
|
||||
NodeJS_COMPILE_OPTIONS
|
||||
NodeJS_ADDITIONAL_SOURCES
|
||||
NodeJS_WIN32_DELAYLOAD_CONDITION
|
||||
NodeJS_WIN32_DELAYLOAD_BINARY
|
||||
NodeJS_TARGET
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"build_type": "@CMAKE_BUILD_TYPE@",
|
||||
"generator": "@CMAKE_GENERATOR@",
|
||||
"toolset": "@CMAKE_GENERATOR_TOOLSET@",
|
||||
"platform": "@CMAKE_GENERATOR_PLATFORM@",
|
||||
"variant": "@NodeJS_VARIANT_BASE@",
|
||||
"version": "@NodeJS_VERSION@",
|
||||
"download": "@NodeJS_DOWNLOAD@",
|
||||
"standard": "@NodeJS_CXX_STANDARD@"
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
set(GITHUB_API_TOKEN $ENV{GITHUB_API_TOKEN})
|
||||
|
||||
set(GITHUB_AUTH "")
|
||||
if(GITHUB_API_TOKEN)
|
||||
set(GITHUB_AUTH "?access_token=${GITHUB_API_TOKEN}")
|
||||
endif()
|
||||
|
||||
set(GITHUB_API_URL "https://api.github.com")
|
||||
|
||||
function(github_get_rate_limit VAR)
|
||||
set(RATE_LIMIT_FILE ${CMAKE_CURRENT_BINARY_DIR}/GITHUBRATE)
|
||||
set(RATE_LIMIT_URL ${GITHUB_API_URL}/rate_limit${GITHUB_AUTH})
|
||||
nodejs_download(
|
||||
${RATE_LIMIT_URL}
|
||||
${RATE_LIMIT_FILE}
|
||||
ON
|
||||
)
|
||||
file(READ ${RATE_LIMIT_FILE} RATE_LIMIT_DATA)
|
||||
string(REGEX MATCH "\"remaining\": ([0-9]+),"
|
||||
RATE_LIMIT_MATCH ${RATE_LIMIT_DATA})
|
||||
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
mark_as_advanced(
|
||||
GITHUB_AUTH
|
||||
GITHUB_API_TOKEN
|
||||
GITHUB_API_URL
|
||||
)
|
||||
@@ -1,166 +0,0 @@
|
||||
function(nodejs_check_file FILE)
|
||||
set(MESSAGE "File ${FILE} does not exist or is empty")
|
||||
if(ARGC GREATER 1)
|
||||
set(MESSAGE ${ARGV1})
|
||||
endif()
|
||||
|
||||
# Make sure the file has contents
|
||||
file(READ ${FILE} FILE_CONTENT LIMIT 1 HEX)
|
||||
if(NOT FILE_CONTENT)
|
||||
file(REMOVE ${FILE})
|
||||
message(FATAL_ERROR ${MESSAGE})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(nodejs_download URL FILE)
|
||||
# Function optionally takes a checksum and a checksum type, and
|
||||
# a force value
|
||||
# Either can be specified without the other, but checksum must come first
|
||||
if(ARGC GREATER 2)
|
||||
set(CHECKSUM ${ARGV2})
|
||||
if(CHECKSUM STREQUAL "On" OR CHECKSUM STREQUAL "ON" OR
|
||||
CHECKSUM STREQUAL "True" OR CHECKSUM STREQUAL "TRUE" OR
|
||||
CHECKSUM STREQUAL "Off" OR CHECKSUM STREQUAL "OFF" OR
|
||||
CHECKSUM STREQUAL "False" OR CHECKSUM STREQUAL "FALSE")
|
||||
set(FORCE ${CHECKSUM})
|
||||
unset(CHECKSUM)
|
||||
elseif(ARGC GREATER 3)
|
||||
set(TYPE ${ARGV3})
|
||||
else()
|
||||
message(FATAL_ERROR "Checksum type must be specified")
|
||||
endif()
|
||||
elseif(ARGC GREATER 4)
|
||||
set(CHECKSUM ${ARGV2})
|
||||
set(TYPE ${ARGV3})
|
||||
set(FORCE ${ARGV4})
|
||||
endif()
|
||||
|
||||
# If the file exists, no need to download it again unless its being forced
|
||||
if(NOT FORCE AND EXISTS ${FILE})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Download the file
|
||||
message(STATUS "Downloading: ${URL}")
|
||||
file(DOWNLOAD
|
||||
${URL}
|
||||
${FILE}
|
||||
SHOW_PROGRESS
|
||||
)
|
||||
|
||||
# Make sure the file has contents
|
||||
nodejs_check_file(${FILE} "Unable to download ${URL}")
|
||||
|
||||
# If a checksum is provided, validate the downloaded file
|
||||
if(CHECKSUM)
|
||||
message(STATUS "Validating: ${FILE}")
|
||||
file(${TYPE} ${FILE} DOWNLOAD_CHECKSUM)
|
||||
message(STATUS "Checksum: ${CHECKSUM}")
|
||||
message(STATUS "Download: ${DOWNLOAD_CHECKSUM}")
|
||||
if(NOT CHECKSUM STREQUAL DOWNLOAD_CHECKSUM)
|
||||
file(REMOVE ${FILE})
|
||||
message(FATAL_ERROR "Validation failure: ${FILE}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(nodejs_checksum DATA FILE VAR)
|
||||
string(REGEX MATCH "([A-Fa-f0-9]+)[\t ]+${FILE}" CHECKSUM_MATCH ${DATA})
|
||||
if(CMAKE_MATCH_1)
|
||||
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to extract file checksum")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(nodejs_extract FILE DIR)
|
||||
# Function optionally takes a force value
|
||||
if(ARGC GREATER 2)
|
||||
set(FORCE ${ARGV2})
|
||||
endif()
|
||||
|
||||
# If the archvie has been extracted, no need to extract again unless it
|
||||
# is being forced
|
||||
if(NOT FORCE AND EXISTS ${DIR})
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Make a temporary directory for extracting the output
|
||||
set(EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/extract)
|
||||
if(EXISTS ${EXTRACT_DIR})
|
||||
file(REMOVE_RECURSE ${EXTRACT_DIR})
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${EXTRACT_DIR})
|
||||
|
||||
# Extract the archive
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xfz ${FILE}
|
||||
WORKING_DIRECTORY ${EXTRACT_DIR}
|
||||
)
|
||||
|
||||
# If only one element is extracted, the archive contained a nested
|
||||
# folder; use the inner folder as the extracted folder
|
||||
file(GLOB EXTRACT_CHILDREN ${EXTRACT_DIR}/*)
|
||||
list(LENGTH EXTRACT_CHILDREN NUM_CHILDREN)
|
||||
set(TARGET_DIR ${EXTRACT_DIR})
|
||||
if(NUM_CHILDREN EQUAL 1)
|
||||
list(GET EXTRACT_CHILDREN 0 TARGET_DIR)
|
||||
endif()
|
||||
|
||||
# Move the folder to the target path
|
||||
if(EXISTS ${DIR})
|
||||
file(REMOVE_RECURSE ${DIR})
|
||||
endif()
|
||||
file(RENAME ${TARGET_DIR} ${DIR})
|
||||
|
||||
# Make sure to clean up the extraction folder when the inner folder
|
||||
# is used
|
||||
file(REMOVE_RECURSE ${EXTRACT_DIR})
|
||||
endfunction()
|
||||
|
||||
function(nodejs_find_module NAME BASE PATH)
|
||||
# Find a node module using the same search path that require uses
|
||||
# without needing a node binary
|
||||
set(ROOT ${BASE})
|
||||
set(DRIVE "^[A-Za-z]?:?/$")
|
||||
|
||||
# Walk up the directory tree until at the root
|
||||
while(NOT ROOT MATCHES ${DRIVE} AND NOT
|
||||
EXISTS ${ROOT}/node_modules/${NAME})
|
||||
get_filename_component(ROOT ${ROOT} DIRECTORY)
|
||||
endwhile()
|
||||
|
||||
# Operate like the CMake find_* functions, returning NOTFOUND if the
|
||||
# module can't be found
|
||||
if(ROOT MATCHES ${DRIVE})
|
||||
set(${PATH} ${NAME}-NOTFOUND PARENT_SCOPE)
|
||||
else()
|
||||
set(${PATH} ${ROOT}/node_modules/${NAME} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
macro(nodejs_find_module_fallback NAME BASE PATH)
|
||||
# Look in the provided path first
|
||||
# If the module isn't found, try searching from the module
|
||||
nodejs_find_module(${NAME} ${BASE} ${PATH})
|
||||
if(NOT ${PATH})
|
||||
nodejs_find_module(${NAME} ${NodeJS_MODULE_PATH} ${PATH})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function(nodejs_get_version URL VAR)
|
||||
set(NWJS_LATEST_RELEASE_URL
|
||||
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
|
||||
set(VERSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/VERSION)
|
||||
nodejs_download(
|
||||
${URL}
|
||||
${VERSION_FILE}
|
||||
ON
|
||||
)
|
||||
nodejs_check_file(${VERSION_FILE})
|
||||
file(READ ${VERSION_FILE} VERSION_DATA)
|
||||
string(REGEX MATCH "v([0-9]+\.[0-9]+\.[0-9]+)"
|
||||
VERSION_MATCH ${VERSION_DATA}
|
||||
)
|
||||
set(${VAR} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,81 +0,0 @@
|
||||
set(ELECTRON_VARIANT_BASE "electron")
|
||||
set(ELECTRON_WIN32_BINARY_NAME "${ELECTRON_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${ELECTRON_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_FIND_REQUIRED_ELECTRON OR
|
||||
NodeJS_VARIANT STREQUAL ${ELECTRON_VARIANT_BASE})
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
include(util/Github)
|
||||
github_get_rate_limit(GITHUB_RATE_LIMIT)
|
||||
|
||||
# Handle determining the latest release
|
||||
# Very complicated, due to electron not following the "latest"
|
||||
# convention of other variants
|
||||
set(ELECTRON_LATEST_RELEASE_FILE ${CMAKE_CURRENT_BINARY_DIR}/ELECTRON)
|
||||
set(ELECTRON_LATEST_RELEASE_URL
|
||||
${GITHUB_API_URL}/repos/atom/electron/releases/latest${GITHUB_AUTH}
|
||||
)
|
||||
if(GITHUB_RATE_LIMIT GREATER 0)
|
||||
nodejs_download(
|
||||
${ELECTRON_LATEST_RELEASE_URL}
|
||||
${ELECTRON_LATEST_RELEASE_FILE}
|
||||
ON
|
||||
)
|
||||
endif()
|
||||
nodejs_check_file(
|
||||
${ELECTRON_LATEST_RELEASE_FILE}
|
||||
"Releases file could not be downloaded, likely \
|
||||
because github rate limit was exceeded. Wait until the limit \
|
||||
passes or set GITHUB_API_TOKEN in your environment to a valid \
|
||||
github developer token."
|
||||
)
|
||||
file(READ ${ELECTRON_LATEST_RELEASE_FILE} ELECTRON_LATEST_RELEASE_DATA)
|
||||
string(REGEX MATCH "\"tag_name\"\: \"v([0-9]+\.[0-9]+\.[0-9]+)\""
|
||||
ELECTRON_LATEST_RELEASE_MATCH ${ELECTRON_LATEST_RELEASE_DATA})
|
||||
set(NodeJS_VERSION ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
set(NodeJS_VARIANT_NAME "Electron.js")
|
||||
|
||||
# SHASUMS of any kind is inaccessible prior to 0.16.0
|
||||
if(NodeJS_VERSION VERSION_LESS 0.16.0)
|
||||
message(FATAL_ERROR "Electron is only supported for versions >= 0.16.0")
|
||||
endif()
|
||||
|
||||
# Electron switched to IOJS after 0.25.0
|
||||
# Probably needs to be bounded on the upper side if/when they switch
|
||||
# back to node mainline due to iojs-node merge
|
||||
set(NodeJS_VARIANT_BASE "node")
|
||||
if(NodeJS_VERSION VERSION_GREATER 0.25.0)
|
||||
set(NodeJS_VARIANT_BASE "iojs")
|
||||
endif()
|
||||
|
||||
# Url is hard to get, because it will immediately resolve to a CDN
|
||||
# Extracted from the electron website
|
||||
set(NodeJS_URL
|
||||
"https://atom.io/download/atom-shell/v${NodeJS_VERSION}"
|
||||
)
|
||||
|
||||
# Headers become available for IOJS base ONLY!
|
||||
# Variant base switch above handles this
|
||||
set(NodeJS_HEADER_VERSION 0.30.1)
|
||||
|
||||
# Header only archive uses source style paths
|
||||
set(NodeJS_DEFAULT_INCLUDE False)
|
||||
|
||||
# Hard to determine, but versions seem to start at 16, and SHA256 is
|
||||
# available
|
||||
set(NodeJS_SHA256_VERSION 0.15.9)
|
||||
|
||||
# C++11 and Prefixing start after the IOJS switch
|
||||
# Will carry forward after node mainline so no need for upper bound (whew)
|
||||
set(NodeJS_PREFIX_VERSION 0.25.0)
|
||||
set(NodeJS_CXX11R_VERSION 0.25.0)
|
||||
|
||||
# The executable is not provided on the CDN
|
||||
# In theory, I could support a BINARY_URL to get this from github
|
||||
set(NodeJS_HAS_WIN32_BINARY False)
|
||||
|
||||
# OpenSSL isn't included in the headers
|
||||
set(NodeJS_HAS_OPENSSL False)
|
||||
endif()
|
||||
@@ -1,25 +0,0 @@
|
||||
set(IOJS_URL_BASE "https://iojs.org/dist")
|
||||
set(IOJS_VARIANT_BASE "iojs")
|
||||
set(IOJS_WIN32_BINARY_NAME "${IOJS_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${IOJS_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_FIND_REQUIRED_IOJS OR NodeJS_VARIANT STREQUAL ${IOJS_VARIANT_BASE})
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
set(IOJS_LATEST_RELEASE_URL
|
||||
"${IOJS_URL_BASE}/latest/SHASUMS256.txt")
|
||||
nodejs_get_version(${IOJS_LATEST_RELEASE_URL} NodeJS_VERSION)
|
||||
endif()
|
||||
|
||||
set(NodeJS_VARIANT_NAME "io.js")
|
||||
set(NodeJS_VARIANT_BASE ${IOJS_VARIANT_BASE})
|
||||
set(NodeJS_URL "${IOJS_URL_BASE}/v${NodeJS_VERSION}")
|
||||
set(NodeJS_HEADER_VERSION 2.3.1)
|
||||
set(NodeJS_WIN32_BINARY_NAME "${IOJS_WIN32_BINARY_NAME}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
IOJS_URL_BASE
|
||||
IOJS_VARIANT_BASE
|
||||
IOJS_WIN32_BINARY_NAME
|
||||
IOJS_LATEST_RELEASE_URL
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
set(NWJS_URL_BASE "http://dl.nwjs.io")
|
||||
set(NWJS_VARIANT_BASE "nw")
|
||||
set(NWJS_WIN32_BINARY_NAME "${NWJS_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${NWJS_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_FIND_REQUIRED_NWJS OR NodeJS_VARIANT STREQUAL ${NWJS_VARIANT_BASE})
|
||||
set(NodeJS_CHECKSUM_PATH "MD5SUMS")
|
||||
set(NodeJS_CHECKSUM_TYPE "MD5")
|
||||
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
set(NWJS_LATEST_RELEASE_URL
|
||||
"${NWJS_URL_BASE}/latest/${NodeJS_CHECKSUM_PATH}")
|
||||
nodejs_get_version(${NWJS_LATEST_RELEASE_URL} NodeJS_VERSION)
|
||||
endif()
|
||||
|
||||
set(NodeJS_VARIANT_NAME "nw.js")
|
||||
set(NodeJS_VARIANT_BASE ${NWJS_VARIANT_BASE})
|
||||
set(NodeJS_URL "${NWJS_URL_BASE}/v${NodeJS_VERSION}")
|
||||
set(NodeJS_SOURCE_PATH "nw-headers-v${NodeJS_VERSION}.tar.gz")
|
||||
set(NodeJS_DEFAULT_INCLUDE False)
|
||||
set(NodeJS_HAS_WIN32_PREFIX False)
|
||||
set(NodeJS_HAS_WIN32_BINARY False)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
NWJS_URL_BASE
|
||||
NWJS_VARIANT_BASE
|
||||
NWJS_WIN32_BINARY_NAME
|
||||
NWJS_LATEST_RELEASE_URL
|
||||
)
|
||||
@@ -1,131 +0,0 @@
|
||||
set(NodeJS_URL_BASE http://nodejs.org/dist)
|
||||
set(NodeJS_DEFAULT_VARIANT_BASE "node")
|
||||
set(NodeJS_DEFAULT_WIN32_BINARY_NAME "${NodeJS_DEFAULT_VARIANT_BASE}.exe")
|
||||
list(APPEND NodeJS_WIN32_DELAYLOAD ${NodeJS_DEFAULT_WIN32_BINARY_NAME})
|
||||
|
||||
if(NodeJS_VERSION STREQUAL "latest")
|
||||
set(NodeJS_LATEST_RELEASE_URL
|
||||
"${NodeJS_URL_BASE}/latest/SHASUMS256.txt")
|
||||
nodejs_get_version(${NodeJS_LATEST_RELEASE_URL} NodeJS_VERSION)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_VARIANT_NAME)
|
||||
set(NodeJS_VARIANT_NAME ${NodeJS_DEFAULT_VARIANT_NAME})
|
||||
endif()
|
||||
if(NOT NodeJS_VARIANT_BASE)
|
||||
set(NodeJS_VARIANT_BASE ${NodeJS_DEFAULT_VARIANT_BASE})
|
||||
endif()
|
||||
if(NOT NodeJS_URL)
|
||||
set(NodeJS_URL "${NodeJS_URL_BASE}/v${NodeJS_VERSION}")
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_SOURCE_PATH)
|
||||
set(NodeJS_SOURCE_PATH "${NodeJS_VARIANT_BASE}-v${NodeJS_VERSION}")
|
||||
# Use the headers archive when its available
|
||||
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
|
||||
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}-headers")
|
||||
endif()
|
||||
set(NodeJS_SOURCE_PATH "${NodeJS_SOURCE_PATH}.tar.gz")
|
||||
endif()
|
||||
|
||||
if(NodeJS_DEFAULT_INCLUDE AND
|
||||
NodeJS_VERSION VERSION_GREATER ${NodeJS_HEADER_VERSION})
|
||||
set(NodeJS_SOURCE_INCLUDE False)
|
||||
set(NodeJS_HEADER_INCLUDE True)
|
||||
endif()
|
||||
|
||||
if(NodeJS_SOURCE_INCLUDE)
|
||||
list(APPEND NodeJS_INCLUDE_PATHS
|
||||
src
|
||||
deps/uv/include
|
||||
deps/v8/include
|
||||
deps/zlib
|
||||
)
|
||||
# OpenSSL is an optional header
|
||||
if(NodeJS_HAS_OPENSSL)
|
||||
list(APPEND NodeJS_INCLUDE_PATHS
|
||||
deps/openssl/openssl/include
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(NodeJS_HEADER_INCLUDE)
|
||||
set(NodeJS_INCLUDE_PATHS include/node)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_CHECKSUM_TYPE)
|
||||
# Use SHA256 when available
|
||||
if(NodeJS_VERSION VERSION_GREATER ${NodeJS_SHA256_VERSION})
|
||||
set(NodeJS_CHECKSUM_TYPE "SHA256")
|
||||
else()
|
||||
set(NodeJS_CHECKSUM_TYPE "SHA1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_CHECKSUM_PATH)
|
||||
set(NodeJS_CHECKSUM_PATH "SHASUMS")
|
||||
if(NodeJS_CHECKSUM_TYPE STREQUAL "SHA256")
|
||||
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}256")
|
||||
endif()
|
||||
set(NodeJS_CHECKSUM_PATH "${NodeJS_CHECKSUM_PATH}.txt")
|
||||
endif()
|
||||
|
||||
# Library and binary are based on variant base
|
||||
if(NOT NodeJS_WIN32_LIBRARY_NAME)
|
||||
set(NodeJS_WIN32_LIBRARY_NAME ${NodeJS_VARIANT_BASE}.lib)
|
||||
endif()
|
||||
if(NOT NodeJS_WIN32_BINARY_NAME)
|
||||
set(NodeJS_WIN32_BINARY_NAME ${NodeJS_VARIANT_BASE}.exe)
|
||||
endif()
|
||||
|
||||
if(NOT NodeJS_WIN32_LIBRARY_PATH)
|
||||
# The library location is prefixed after a specific version
|
||||
if(NodeJS_HAS_WIN32_PREFIX AND
|
||||
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "win-")
|
||||
if(NodeJS_ARCH_IA32)
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x86/")
|
||||
endif()
|
||||
endif()
|
||||
# 64-bit versions are prefixed
|
||||
if(NodeJS_ARCH_X64)
|
||||
set(NodeJS_WIN32_LIBRARY_PATH "${NodeJS_WIN32_LIBRARY_PATH}x64/")
|
||||
endif()
|
||||
set(NodeJS_WIN32_LIBRARY_PATH
|
||||
"${NodeJS_WIN32_LIBRARY_PATH}${NodeJS_WIN32_LIBRARY_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NodeJS_HAS_WIN32_BINARY AND NOT NodeJS_WIN32_BINARY_PATH)
|
||||
# The executable location is prefixed after a specific version
|
||||
if(NodeJS_HAS_WIN32_PREFIX AND
|
||||
NodeJS_VERSION VERSION_GREATER ${NodeJS_PREFIX_VERSION})
|
||||
set(NodeJS_WIN32_BINARY_PATH "win-")
|
||||
if(NodeJS_ARCH_IA32)
|
||||
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x86/")
|
||||
endif()
|
||||
endif()
|
||||
# 64-bit versions are prefixed
|
||||
if(NodeJS_ARCH_X64)
|
||||
set(NodeJS_WIN32_BINARY_PATH "${NodeJS_WIN32_BINARY_PATH}x64/")
|
||||
endif()
|
||||
set(NodeJS_WIN32_BINARY_PATH
|
||||
"${NodeJS_WIN32_BINARY_PATH}${NodeJS_WIN32_BINARY_NAME}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Specify windows libraries
|
||||
# XXX: This may need to be version/variant specific in the future
|
||||
if(NodeJS_DEFAULT_LIBS AND NodeJS_PLATFORM_WIN32)
|
||||
list(APPEND NodeJS_LIBRARIES
|
||||
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib
|
||||
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib
|
||||
odbc32.lib DelayImp.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
NodeJS_URL_BASE
|
||||
NodeJS_DEFAULT_VARIANT_BASE
|
||||
NodeJS_DEFAULT_WIN32_BINARY_NAME
|
||||
NodeJS_LATEST_RELEASE_URL
|
||||
)
|
||||
+1
-1
@@ -3,5 +3,5 @@ module.exports = {
|
||||
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
||||
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||
all: '--strict --require features/support --require features/step_definitions',
|
||||
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@match --tags ~@alternative --tags ~@matrix --tags ~@trip --tags ~@via --require features/support --require features/step_definitions -f progress'
|
||||
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@alternative --tags ~@matrix --tags ~@trip --require features/support --require features/step_definitions -f progress'
|
||||
}
|
||||
|
||||
@@ -681,3 +681,29 @@ Feature: Basic Roundabout
|
||||
| u,r | ug,ar,ar | depart,roundabout-exit-3,arrive |
|
||||
| u,s | ug,ds,ds | depart,roundabout-exit-4,arrive |
|
||||
| u,t | ug,ft,ft | depart,roundabout-exit-5,arrive |
|
||||
|
||||
|
||||
@3762
|
||||
Scenario: Only Enter
|
||||
Given the node map
|
||||
"""
|
||||
a
|
||||
b
|
||||
i c e ~ ~ ~ f - h
|
||||
j d
|
||||
k g
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes | junction | route |
|
||||
| ab | | |
|
||||
| ef | | ferry |
|
||||
| fh | | |
|
||||
| dg | | |
|
||||
| ic | | |
|
||||
| jk | | |
|
||||
| bcjdeb | roundabout | |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
|
||||
|
||||
@@ -22,9 +22,28 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
|
||||
Scenario: Logging weight with updates over factor of 2, long segment
|
||||
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
|
||||
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
||||
Then stderr should not contain "Speed values were used to update 2 segment(s)"
|
||||
And stderr should contain "Segment: 1,2"
|
||||
And stderr should contain "Segment: 1,3"
|
||||
And I route I should get
|
||||
| from | to | route | speed |
|
||||
| a | b | ab,ab | 100 km/h |
|
||||
| a | c | ac,ac | 100 km/h |
|
||||
|
||||
|
||||
Scenario: Logging using weigts as durations for non-duration profile
|
||||
Given the profile file "testbot" extended with
|
||||
"""
|
||||
properties.weight_name = 'steps'
|
||||
function way_function(way, result)
|
||||
result.forward_mode = mode.driving
|
||||
result.backward_mode = mode.driving
|
||||
result.weight = 1
|
||||
result.duration = 1
|
||||
end
|
||||
"""
|
||||
And the data has been saved to disk
|
||||
|
||||
When I run "osrm-extract --profile {profile_file} {osm_file} --generate-edge-lookup"
|
||||
When I run "osrm-contract --edge-weight-updates-over-factor 2 --segment-speed-file {speeds_file} {processed_file}"
|
||||
Then stderr should contain "Speed values were used to update 2 segments for 'steps' profile"
|
||||
|
||||
@@ -175,8 +175,7 @@ module.exports = function () {
|
||||
|
||||
if (headers.has('matchings')) {
|
||||
if (subMatchings.length != row.matchings.split(',').length) {
|
||||
ok = false;
|
||||
cb(new Error('*** table matchings and api response are not the same'));
|
||||
return cb(new Error('*** table matchings and api response are not the same'));
|
||||
}
|
||||
|
||||
row.matchings.split(',').forEach((sub, si) => {
|
||||
|
||||
@@ -213,7 +213,7 @@ Feature: Basic Map Matching
|
||||
|
||||
And the speed file
|
||||
"""
|
||||
1,2,36
|
||||
1,2,36,10
|
||||
"""
|
||||
|
||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||
@@ -240,7 +240,7 @@ Feature: Basic Map Matching
|
||||
|
||||
And the speed file
|
||||
"""
|
||||
1,2,36
|
||||
1,2,36,10
|
||||
"""
|
||||
|
||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||
|
||||
@@ -30,12 +30,12 @@ Feature: Traffic - speeds
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
"""
|
||||
1,2,0
|
||||
2,1,0
|
||||
2,3,27
|
||||
3,2,27
|
||||
1,4,27
|
||||
4,1,27
|
||||
1,2,0,0
|
||||
2,1,0,0
|
||||
2,3,27,7.5
|
||||
3,2,27,7.5
|
||||
1,4,27,7.5
|
||||
4,1,27,7.5
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
@@ -56,12 +56,12 @@ Feature: Traffic - speeds
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
"""
|
||||
1,2,1,20020.7
|
||||
2,1,1,20020.7
|
||||
2,3,27,741.5
|
||||
3,2,27,741.5
|
||||
1,4,27,1275.7
|
||||
4,1,27,1275.7
|
||||
1,2,1,0.2777777
|
||||
2,1,1
|
||||
2,3,27
|
||||
3,2,27,7.5
|
||||
1,4,27,7.5
|
||||
4,1,27,7.5
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
@@ -89,26 +89,26 @@ Feature: Traffic - speeds
|
||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||
And the speed file
|
||||
"""
|
||||
1,2,1,20020.789
|
||||
2,1,1,20020.123
|
||||
2,3,27,741.56789
|
||||
3,2,27,741.3
|
||||
1,4,1,34445.12
|
||||
4,1,1,34445.3
|
||||
1,2,1,0.27777777
|
||||
2,1,1,0.27777777
|
||||
2,3,27,7.5
|
||||
3,2,27
|
||||
1,4,1
|
||||
4,1,1
|
||||
"""
|
||||
And the query options
|
||||
| annotations | datasources |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | speed | weights | a:datasources |
|
||||
| a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
|
||||
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
|
||||
| b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
|
||||
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
|
||||
| a | b | ab,ab | 1 km/h | 20020.735,0 | 1:0 |
|
||||
| a | c | ab,bc,bc | 2 km/h | 20020.735,741.509,0 | 1:1:0 |
|
||||
| b | c | bc,bc | 27 km/h | 741.509,0 | 1:0 |
|
||||
| a | d | ab,eb,de,de | 2 km/h | 20020.735,378.169,400.415,0 | 1:0:0 |
|
||||
| d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
|
||||
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
|
||||
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
|
||||
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
|
||||
| g | b | ab,ab | 1 km/h | 10010.365,0 | 1:0 |
|
||||
| a | g | ab,ab | 1 km/h | 10010.37,0 | 1 |
|
||||
| g | a | ab,ab | 1 km/h | 10010.37,0 | 1:1 |
|
||||
|
||||
|
||||
Scenario: Speeds that isolate a single node (a)
|
||||
@@ -121,10 +121,10 @@ Feature: Traffic - speeds
|
||||
"""
|
||||
1,2,0
|
||||
2,1,0
|
||||
2,3,27
|
||||
3,2,27
|
||||
1,4,0
|
||||
4,1,0
|
||||
2,3,27,7.5
|
||||
3,2,27,7.5
|
||||
1,4,0,0
|
||||
4,1,0,0
|
||||
"""
|
||||
And the query options
|
||||
| annotations | true |
|
||||
|
||||
@@ -284,8 +284,8 @@ Feature: Weight tests
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | distance | weights | times |
|
||||
| a,d | , | 59.9m | 62,0 | 24s,0s |
|
||||
| a,e | ,, | 60.1m | 68.7,10,0 | 38.5s,11s,0s |
|
||||
| a,d | , | 59.9m | 20.5,0 | 24s,0s |
|
||||
| a,e | ,, | 60.1m | 27.2,10,0 | 38.5s,11s,0s |
|
||||
| d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s |
|
||||
|
||||
@traffic @speed
|
||||
@@ -320,6 +320,6 @@ Feature: Weight tests
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | distance | weights | times |
|
||||
| a,d | abcd,abcd | 59.9m | 6.993,0 | 7s,0s |
|
||||
| a,e | abcd,ce,ce | 60.1m | 6.002,2.002,0 | 6s,2s,0s |
|
||||
| a,d | abcd,abcd | 59.9m | 6.996,0 | 7s,0s |
|
||||
| a,e | abcd,ce,ce | 60.1m | 6.005,2.002,0 | 6s,2s,0s |
|
||||
| d,e | abcd,ce,ce | 39.9m | 1.991,2.002,0 | 2s,2s,0s |
|
||||
|
||||
@@ -68,9 +68,8 @@ class Contractor
|
||||
void WriteCoreNodeMarker(std::vector<bool> &&is_core_node) const;
|
||||
void WriteNodeLevels(std::vector<float> &&node_levels) const;
|
||||
void ReadNodeLevels(std::vector<float> &contraction_order) const;
|
||||
std::size_t
|
||||
WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||
const util::DeallocatingVector<QueryEdge> &contracted_edge_list);
|
||||
void WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||
util::DeallocatingVector<QueryEdge> contracted_edge_list);
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<extractor::EdgeBasedEdge> &edges,
|
||||
std::vector<extractor::EdgeBasedNode> &nodes) const;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef OSRM_CONTRACTOR_FILES_HPP
|
||||
#define OSRM_CONTRACTOR_FILES_HPP
|
||||
|
||||
#include "contractor/query_graph.hpp"
|
||||
|
||||
#include "util/serialization.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace contractor
|
||||
{
|
||||
namespace files
|
||||
{
|
||||
|
||||
// reads .osrm.hsgr file
|
||||
template <typename QueryGraphT>
|
||||
inline void readGraph(const boost::filesystem::path &path, unsigned &checksum, QueryGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
||||
"graph must be of type QueryGraph<>");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.ReadInto(checksum);
|
||||
util::serialization::read(reader, graph);
|
||||
}
|
||||
|
||||
// writes .osrm.hsgr file
|
||||
template <typename QueryGraphT>
|
||||
inline void
|
||||
writeGraph(const boost::filesystem::path &path, unsigned checksum, const QueryGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
|
||||
std::is_same<QueryGraph, QueryGraphT>::value,
|
||||
"graph must be of type QueryGraph<>");
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteOne(checksum);
|
||||
util::serialization::write(writer, graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef OSRM_CONTRACTOR_QUERY_GRAPH_HPP
|
||||
#define OSRM_CONTRACTOR_QUERY_GRAPH_HPP
|
||||
|
||||
#include "contractor/query_edge.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace contractor
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
using QueryGraph = util::StaticGraph<typename QueryEdge::EdgeData, Ownership>;
|
||||
}
|
||||
|
||||
using QueryGraph = detail::QueryGraph<storage::Ownership::Container>;
|
||||
using QueryGraphView = detail::QueryGraph<storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // QUERYEDGE_HPP
|
||||
@@ -5,7 +5,8 @@
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <tbb/enumerable_thread_specific.h>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace osrm
|
||||
@@ -15,12 +16,22 @@ namespace customizer
|
||||
|
||||
class CellCustomizer
|
||||
{
|
||||
private:
|
||||
struct HeapData
|
||||
{
|
||||
bool from_clique;
|
||||
};
|
||||
|
||||
public:
|
||||
using Heap =
|
||||
util::BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::ArrayStorage<NodeID, int>>;
|
||||
using HeapPtr = tbb::enumerable_thread_specific<Heap>;
|
||||
|
||||
CellCustomizer(const partition::MultiLevelPartition &partition) : partition(partition) {}
|
||||
|
||||
template <typename GraphT>
|
||||
void Customize(const GraphT &graph, partition::CellStorage &cells, LevelID level, CellID id)
|
||||
void Customize(
|
||||
const GraphT &graph, Heap &heap, partition::CellStorage &cells, LevelID level, CellID id)
|
||||
{
|
||||
auto cell = cells.GetCell(level, id);
|
||||
auto destinations = cell.GetDestinationNodes();
|
||||
@@ -29,8 +40,8 @@ class CellCustomizer
|
||||
for (auto source : cell.GetSourceNodes())
|
||||
{
|
||||
std::unordered_set<NodeID> destinations_set(destinations.begin(), destinations.end());
|
||||
Heap heap(graph.GetNumberOfNodes());
|
||||
heap.Insert(source, 0, {});
|
||||
heap.Clear();
|
||||
heap.Insert(source, 0, {false});
|
||||
|
||||
// explore search space
|
||||
while (!heap.Empty() && !destinations_set.empty())
|
||||
@@ -60,26 +71,23 @@ class CellCustomizer
|
||||
|
||||
template <typename GraphT> void Customize(const GraphT &graph, partition::CellStorage &cells)
|
||||
{
|
||||
Heap heap_exemplar(graph.GetNumberOfNodes());
|
||||
HeapPtr heaps(heap_exemplar);
|
||||
|
||||
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
|
||||
{
|
||||
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
|
||||
[&](const tbb::blocked_range<std::size_t> &range) {
|
||||
auto &heap = heaps.local();
|
||||
for (auto id = range.begin(), end = range.end(); id != end; ++id)
|
||||
{
|
||||
Customize(graph, cells, level, id);
|
||||
Customize(graph, heap, cells, level, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct HeapData
|
||||
{
|
||||
};
|
||||
using Heap = util::
|
||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||
using HeapPtr = boost::thread_specific_ptr<Heap>;
|
||||
|
||||
template <bool first_level, typename GraphT>
|
||||
void RelaxNode(const GraphT &graph,
|
||||
const partition::CellStorage &cells,
|
||||
@@ -88,29 +96,42 @@ class CellCustomizer
|
||||
NodeID node,
|
||||
EdgeWeight weight) const
|
||||
{
|
||||
BOOST_ASSERT(heap.WasInserted(node));
|
||||
|
||||
if (!first_level)
|
||||
{
|
||||
// Relax sub-cell nodes
|
||||
auto subcell_id = partition.GetCell(level - 1, node);
|
||||
auto subcell = cells.GetCell(level - 1, subcell_id);
|
||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||
// if we reaches this node from a clique arc we don't need to scan
|
||||
// the clique arcs again because of the triangle inequality
|
||||
//
|
||||
// d(parent, node) + d(node, v) >= d(parent, v)
|
||||
//
|
||||
// And if there is a path (parent, node, v) there must also be a
|
||||
// clique arc (parent, v) with d(parent, v).
|
||||
if (!heap.GetData(node).from_clique)
|
||||
{
|
||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||
// Relax sub-cell nodes
|
||||
auto subcell_id = partition.GetCell(level - 1, node);
|
||||
auto subcell = cells.GetCell(level - 1, subcell_id);
|
||||
auto subcell_destination = subcell.GetDestinationNodes().begin();
|
||||
for (auto subcell_weight : subcell.GetOutWeight(node))
|
||||
{
|
||||
const NodeID to = *subcell_destination;
|
||||
const EdgeWeight to_weight = subcell_weight + weight;
|
||||
if (!heap.WasInserted(to))
|
||||
if (subcell_weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
heap.Insert(to, to_weight, {});
|
||||
const NodeID to = *subcell_destination;
|
||||
const EdgeWeight to_weight = subcell_weight + weight;
|
||||
if (!heap.WasInserted(to))
|
||||
{
|
||||
heap.Insert(to, to_weight, {true});
|
||||
}
|
||||
else if (to_weight < heap.GetKey(to))
|
||||
{
|
||||
heap.DecreaseKey(to, to_weight);
|
||||
heap.GetData(to).from_clique = true;
|
||||
}
|
||||
}
|
||||
else if (to_weight < heap.GetKey(to))
|
||||
{
|
||||
heap.DecreaseKey(to, to_weight);
|
||||
}
|
||||
}
|
||||
|
||||
++subcell_destination;
|
||||
++subcell_destination;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,11 +147,12 @@ class CellCustomizer
|
||||
const EdgeWeight to_weight = data.weight + weight;
|
||||
if (!heap.WasInserted(to))
|
||||
{
|
||||
heap.Insert(to, to_weight, {});
|
||||
heap.Insert(to, to_weight, {false});
|
||||
}
|
||||
else if (to_weight < heap.GetKey(to))
|
||||
{
|
||||
heap.DecreaseKey(to, to_weight);
|
||||
heap.GetData(to).from_clique = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace osrm
|
||||
@@ -16,16 +18,17 @@ namespace customizer
|
||||
|
||||
using EdgeBasedGraphEdgeData = partition::EdgeBasedGraphEdgeData;
|
||||
|
||||
struct MultiLevelEdgeBasedGraph : public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>
|
||||
struct MultiLevelEdgeBasedGraph
|
||||
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
|
||||
{
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>;
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
struct MultiLevelEdgeBasedGraphView
|
||||
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, true>
|
||||
: public partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
|
||||
{
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, true>;
|
||||
using Base = partition::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
|
||||
using Base::Base;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef OSRM_CUSTOMIZER_IO_HPP
|
||||
#define OSRM_CUSTOMIZER_IO_HPP
|
||||
|
||||
#include "customizer/edge_based_graph.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace customizer
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -7,30 +7,36 @@ namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
namespace algorithm
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
// Contraction Hiearchy
|
||||
struct CH final
|
||||
namespace ch
|
||||
{
|
||||
struct Algorithm final
|
||||
{
|
||||
};
|
||||
}
|
||||
// Contraction Hiearchy with core
|
||||
struct CoreCH final
|
||||
namespace corech
|
||||
{
|
||||
struct Algorithm final
|
||||
{
|
||||
};
|
||||
}
|
||||
// Multi-Level Dijkstra
|
||||
struct MLD final
|
||||
namespace mld
|
||||
{
|
||||
struct Algorithm final
|
||||
{
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> const char *name();
|
||||
template <> inline const char *name<CH>() { return "CH"; }
|
||||
template <> inline const char *name<CoreCH>() { return "CoreCH"; }
|
||||
template <> inline const char *name<MLD>() { return "MLD"; }
|
||||
}
|
||||
|
||||
namespace algorithm_trais
|
||||
{
|
||||
// Algorithm names
|
||||
template <typename AlgorithmT> const char *name();
|
||||
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
|
||||
template <> inline const char *name<corech::Algorithm>() { return "CoreCH"; }
|
||||
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
|
||||
|
||||
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
|
||||
{
|
||||
@@ -51,62 +57,49 @@ template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct HasAlternativePathSearch<algorithm::CH> final : std::true_type
|
||||
// Algorithms supported by Contraction Hierarchies
|
||||
template <> struct HasAlternativePathSearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasShortestPathSearch<algorithm::CH> final : std::true_type
|
||||
template <> struct HasShortestPathSearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasDirectShortestPathSearch<algorithm::CH> final : std::true_type
|
||||
template <> struct HasDirectShortestPathSearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasMapMatching<algorithm::CH> final : std::true_type
|
||||
template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasManyToManySearch<algorithm::CH> final : std::true_type
|
||||
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasGetTileTurns<algorithm::CH> final : std::true_type
|
||||
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// disbaled because of perfomance reasons
|
||||
template <> struct HasAlternativePathSearch<algorithm::CoreCH> final : std::false_type
|
||||
// Algorithms supported by Contraction Hierarchies with core
|
||||
// the rest is disabled because of performance reasons
|
||||
template <> struct HasShortestPathSearch<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasManyToManySearch<algorithm::CoreCH> final : std::false_type
|
||||
template <> struct HasDirectShortestPathSearch<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasShortestPathSearch<algorithm::CoreCH> final : std::true_type
|
||||
template <> struct HasMapMatching<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasDirectShortestPathSearch<algorithm::CoreCH> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasMapMatching<algorithm::CoreCH> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasGetTileTurns<algorithm::CoreCH> final : std::true_type
|
||||
template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// disbaled because of perfomance reasons
|
||||
template <> struct HasAlternativePathSearch<algorithm::MLD> final : std::false_type
|
||||
// Algorithms supported by Multi-Level Dijkstra
|
||||
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasManyToManySearch<algorithm::MLD> final : std::false_type
|
||||
template <> struct HasShortestPathSearch<mld::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasShortestPathSearch<algorithm::MLD> final : std::false_type
|
||||
{
|
||||
};
|
||||
template <> struct HasDirectShortestPathSearch<algorithm::MLD> final : std::true_type
|
||||
{
|
||||
};
|
||||
template <> struct HasMapMatching<algorithm::MLD> final : std::false_type
|
||||
{
|
||||
};
|
||||
template <> struct HasGetTileTurns<algorithm::MLD> final : std::false_type
|
||||
template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
result.can_be_removed.resize(params.coordinates.size(), false);
|
||||
|
||||
result.tidied_to_original.push_back(0);
|
||||
std::size_t last_good = 0;
|
||||
|
||||
const auto uses_timestamps = !params.timestamps.empty();
|
||||
|
||||
@@ -109,7 +108,6 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
|
||||
if (over_distance && over_duration)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
@@ -122,7 +120,6 @@ inline Result tidy(const MatchParameters ¶ms, Thresholds cfg = {15., 5})
|
||||
{
|
||||
if (over_distance)
|
||||
{
|
||||
last_good = next;
|
||||
result.tidied_to_original.push_back(next);
|
||||
running = {0., 0}; // reset running distance and time
|
||||
}
|
||||
|
||||
@@ -17,11 +17,16 @@ namespace engine
|
||||
namespace datafacade
|
||||
{
|
||||
|
||||
// Namespace local aliases for algorithms
|
||||
using CH = routing_algorithms::ch::Algorithm;
|
||||
using CoreCH = routing_algorithms::corech::Algorithm;
|
||||
using MLD = routing_algorithms::mld::Algorithm;
|
||||
|
||||
using EdgeRange = util::range<EdgeID>;
|
||||
|
||||
template <typename AlgorithmT> class AlgorithmDataFacade;
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::CH>
|
||||
template <> class AlgorithmDataFacade<CH>
|
||||
{
|
||||
public:
|
||||
using EdgeData = contractor::QueryEdge::EdgeData;
|
||||
@@ -56,7 +61,7 @@ template <> class AlgorithmDataFacade<algorithm::CH>
|
||||
const std::function<bool(EdgeData)> filter) const = 0;
|
||||
};
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::CoreCH>
|
||||
template <> class AlgorithmDataFacade<CoreCH>
|
||||
{
|
||||
public:
|
||||
using EdgeData = contractor::QueryEdge::EdgeData;
|
||||
@@ -64,7 +69,7 @@ template <> class AlgorithmDataFacade<algorithm::CoreCH>
|
||||
virtual bool IsCoreNode(const NodeID id) const = 0;
|
||||
};
|
||||
|
||||
template <> class AlgorithmDataFacade<algorithm::MLD>
|
||||
template <> class AlgorithmDataFacade<MLD>
|
||||
{
|
||||
public:
|
||||
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
|
||||
|
||||
@@ -15,11 +15,15 @@
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
|
||||
#include "contractor/query_graph.hpp"
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/shared_datatype.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/exception.hpp"
|
||||
#include "util/exception_utils.hpp"
|
||||
@@ -57,15 +61,14 @@ namespace datafacade
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryAlgorithmDataFacade;
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::CH>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::AlgorithmDataFacade<CH>
|
||||
{
|
||||
private:
|
||||
using QueryGraph = util::StaticGraph<EdgeData, true>;
|
||||
using QueryGraph = contractor::QueryGraphView;
|
||||
using GraphNode = QueryGraph::NodeArrayEntry;
|
||||
using GraphEdge = QueryGraph::EdgeArrayEntry;
|
||||
|
||||
std::unique_ptr<QueryGraph> m_query_graph;
|
||||
QueryGraph m_query_graph;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
@@ -78,11 +81,11 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
|
||||
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
|
||||
|
||||
util::ShM<GraphNode, true>::vector node_list(
|
||||
util::vector_view<GraphNode> node_list(
|
||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
|
||||
util::ShM<GraphEdge, true>::vector edge_list(
|
||||
util::vector_view<GraphEdge> edge_list(
|
||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
|
||||
m_query_graph.reset(new QueryGraph(node_list, edge_list));
|
||||
m_query_graph = QueryGraph(node_list, edge_list);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -99,62 +102,62 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
}
|
||||
|
||||
// search graph access
|
||||
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
|
||||
unsigned GetNumberOfNodes() const override final { return m_query_graph.GetNumberOfNodes(); }
|
||||
|
||||
unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
|
||||
unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); }
|
||||
|
||||
unsigned GetOutDegree(const NodeID n) const override final
|
||||
{
|
||||
return m_query_graph->GetOutDegree(n);
|
||||
return m_query_graph.GetOutDegree(n);
|
||||
}
|
||||
|
||||
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); }
|
||||
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); }
|
||||
|
||||
EdgeData &GetEdgeData(const EdgeID e) const override final
|
||||
const EdgeData &GetEdgeData(const EdgeID e) const override final
|
||||
{
|
||||
return m_query_graph->GetEdgeData(e);
|
||||
return m_query_graph.GetEdgeData(e);
|
||||
}
|
||||
|
||||
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); }
|
||||
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph.BeginEdges(n); }
|
||||
|
||||
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); }
|
||||
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph.EndEdges(n); }
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
|
||||
{
|
||||
return m_query_graph->GetAdjacentEdgeRange(node);
|
||||
return m_query_graph.GetAdjacentEdgeRange(node);
|
||||
}
|
||||
|
||||
// searches for a specific edge
|
||||
EdgeID FindEdge(const NodeID from, const NodeID to) const override final
|
||||
{
|
||||
return m_query_graph->FindEdge(from, to);
|
||||
return m_query_graph.FindEdge(from, to);
|
||||
}
|
||||
|
||||
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final
|
||||
{
|
||||
return m_query_graph->FindEdgeInEitherDirection(from, to);
|
||||
return m_query_graph.FindEdgeInEitherDirection(from, to);
|
||||
}
|
||||
|
||||
EdgeID
|
||||
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final
|
||||
{
|
||||
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
|
||||
return m_query_graph.FindEdgeIndicateIfReverse(from, to, result);
|
||||
}
|
||||
|
||||
EdgeID FindSmallestEdge(const NodeID from,
|
||||
const NodeID to,
|
||||
std::function<bool(EdgeData)> filter) const override final
|
||||
{
|
||||
return m_query_graph->FindSmallestEdge(from, to, filter);
|
||||
return m_query_graph.FindSmallestEdge(from, to, filter);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::CoreCH>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
||||
: public datafacade::AlgorithmDataFacade<CoreCH>
|
||||
{
|
||||
private:
|
||||
util::ShM<bool, true>::vector m_is_core_node;
|
||||
util::vector_view<bool> m_is_core_node;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
@@ -163,7 +166,7 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
{
|
||||
auto core_marker_ptr =
|
||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::CH_CORE_MARKER);
|
||||
util::ShM<bool, true>::vector is_core_node(
|
||||
util::vector_view<bool> is_core_node(
|
||||
core_marker_ptr, data_layout.num_entries[storage::DataLayout::CH_CORE_MARKER]);
|
||||
m_is_core_node = std::move(is_core_node);
|
||||
}
|
||||
@@ -199,10 +202,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
private:
|
||||
using super = BaseDataFacade;
|
||||
using IndexBlock = util::RangeTable<16, true>::BlockT;
|
||||
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
|
||||
using RTreeLeaf = super::RTreeLeaf;
|
||||
using SharedRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
|
||||
using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>;
|
||||
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
|
||||
using RTreeNode = SharedRTree::TreeNode;
|
||||
|
||||
@@ -211,28 +213,20 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
extractor::Datasources *m_datasources;
|
||||
|
||||
unsigned m_check_sum;
|
||||
util::ShM<util::Coordinate, true>::vector m_coordinate_list;
|
||||
util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
|
||||
util::ShM<GeometryID, true>::vector m_via_geometry_list;
|
||||
util::ShM<NameID, true>::vector m_name_ID_list;
|
||||
util::ShM<LaneDataID, true>::vector m_lane_data_id;
|
||||
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
|
||||
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
|
||||
util::ShM<util::guidance::TurnBearing, true>::vector m_pre_turn_bearing;
|
||||
util::ShM<util::guidance::TurnBearing, true>::vector m_post_turn_bearing;
|
||||
util::vector_view<util::Coordinate> m_coordinate_list;
|
||||
util::PackedVectorView<OSMNodeID> m_osmnodeid_list;
|
||||
util::NameTable m_names_table;
|
||||
util::ShM<unsigned, true>::vector m_name_begin_indices;
|
||||
util::ShM<bool, true>::vector m_is_core_node;
|
||||
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
|
||||
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
|
||||
util::ShM<TurnPenalty, true>::vector m_turn_weight_penalties;
|
||||
util::ShM<TurnPenalty, true>::vector m_turn_duration_penalties;
|
||||
util::vector_view<std::uint32_t> m_lane_description_offsets;
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> m_lane_description_masks;
|
||||
util::vector_view<TurnPenalty> m_turn_weight_penalties;
|
||||
util::vector_view<TurnPenalty> m_turn_duration_penalties;
|
||||
extractor::SegmentDataView segment_data;
|
||||
extractor::TurnDataView turn_data;
|
||||
|
||||
util::ShM<char, true>::vector m_datasource_name_data;
|
||||
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
|
||||
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
|
||||
util::ShM<util::guidance::LaneTupleIdPair, true>::vector m_lane_tupel_id_pairs;
|
||||
util::vector_view<char> m_datasource_name_data;
|
||||
util::vector_view<std::size_t> m_datasource_name_offsets;
|
||||
util::vector_view<std::size_t> m_datasource_name_lengths;
|
||||
util::vector_view<util::guidance::LaneTupleIdPair> m_lane_tupel_id_pairs;
|
||||
|
||||
std::unique_ptr<SharedRTree> m_static_rtree;
|
||||
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
|
||||
@@ -240,17 +234,17 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
util::NameTable m_name_table;
|
||||
// bearing classes by node based node
|
||||
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
|
||||
util::vector_view<BearingClassID> m_bearing_class_id_table;
|
||||
// entry class IDs
|
||||
util::ShM<EntryClassID, true>::vector m_entry_class_id_list;
|
||||
util::vector_view<EntryClassID> m_entry_class_id_list;
|
||||
|
||||
// the look-up table for entry classes. An entry class lists the possibility of entry for all
|
||||
// available turns. Such a class id is stored with every edge.
|
||||
util::ShM<util::guidance::EntryClass, true>::vector m_entry_class_table;
|
||||
util::vector_view<util::guidance::EntryClass> m_entry_class_table;
|
||||
// the look-up table for distinct bearing classes. A bearing class lists the available bearings
|
||||
// at an intersection
|
||||
std::shared_ptr<util::RangeTable<16, true>> m_bearing_ranges_table;
|
||||
util::ShM<DiscreteBearing, true>::vector m_bearing_values_table;
|
||||
std::shared_ptr<util::RangeTable<16, storage::Ownership::View>> m_bearing_ranges_table;
|
||||
util::vector_view<DiscreteBearing> m_bearing_values_table;
|
||||
|
||||
// allocator that keeps the allocation data
|
||||
std::shared_ptr<ContiguousBlockAllocator> allocator;
|
||||
@@ -303,8 +297,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
|
||||
}
|
||||
|
||||
void InitializeNodeAndEdgeInformationPointers(storage::DataLayout &data_layout,
|
||||
char *memory_block)
|
||||
void InitializeNodeInformationPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
const auto coordinate_list_ptr = data_layout.GetBlockPtr<util::Coordinate>(
|
||||
memory_block, storage::DataLayout::COORDINATE_LIST);
|
||||
@@ -323,66 +316,59 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
// We (ab)use the number of coordinates here because we know we have the same amount of ids
|
||||
m_osmnodeid_list.set_number_of_entries(
|
||||
data_layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
|
||||
|
||||
const auto travel_mode_list_ptr = data_layout.GetBlockPtr<extractor::TravelMode>(
|
||||
memory_block, storage::DataLayout::TRAVEL_MODE);
|
||||
util::ShM<extractor::TravelMode, true>::vector travel_mode_list(
|
||||
travel_mode_list_ptr, data_layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
|
||||
m_travel_mode_list = std::move(travel_mode_list);
|
||||
|
||||
const auto lane_data_id_ptr =
|
||||
data_layout.GetBlockPtr<LaneDataID>(memory_block, storage::DataLayout::LANE_DATA_ID);
|
||||
util::ShM<LaneDataID, true>::vector lane_data_id(
|
||||
lane_data_id_ptr, data_layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
|
||||
m_lane_data_id = std::move(lane_data_id);
|
||||
|
||||
const auto lane_tupel_id_pair_ptr =
|
||||
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
|
||||
memory_block, storage::DataLayout::TURN_LANE_DATA);
|
||||
util::ShM<util::guidance::LaneTupleIdPair, true>::vector lane_tupel_id_pair(
|
||||
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
|
||||
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
|
||||
|
||||
const auto turn_instruction_list_ptr =
|
||||
data_layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
|
||||
memory_block, storage::DataLayout::TURN_INSTRUCTION);
|
||||
util::ShM<extractor::guidance::TurnInstruction, true>::vector turn_instruction_list(
|
||||
turn_instruction_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
||||
m_turn_instruction_list = std::move(turn_instruction_list);
|
||||
|
||||
const auto name_id_list_ptr =
|
||||
data_layout.GetBlockPtr<NameID>(memory_block, storage::DataLayout::NAME_ID_LIST);
|
||||
util::ShM<NameID, true>::vector name_id_list(
|
||||
name_id_list_ptr, data_layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
|
||||
m_name_ID_list = std::move(name_id_list);
|
||||
|
||||
const auto entry_class_id_list_ptr =
|
||||
data_layout.GetBlockPtr<EntryClassID>(memory_block, storage::DataLayout::ENTRY_CLASSID);
|
||||
typename util::ShM<EntryClassID, true>::vector entry_class_id_list(
|
||||
entry_class_id_list_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||
m_entry_class_id_list = std::move(entry_class_id_list);
|
||||
|
||||
const auto pre_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_block, storage::DataLayout::PRE_TURN_BEARING);
|
||||
typename util::ShM<util::guidance::TurnBearing, true>::vector pre_turn_bearing(
|
||||
pre_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||
m_pre_turn_bearing = std::move(pre_turn_bearing);
|
||||
|
||||
const auto post_turn_bearing_ptr = data_layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_block, storage::DataLayout::POST_TURN_BEARING);
|
||||
typename util::ShM<util::guidance::TurnBearing, true>::vector post_turn_bearing(
|
||||
post_turn_bearing_ptr, data_layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||
m_post_turn_bearing = std::move(post_turn_bearing);
|
||||
}
|
||||
|
||||
void InitializeViaNodeListPointer(storage::DataLayout &data_layout, char *memory_block)
|
||||
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
||||
{
|
||||
auto via_geometry_list_ptr =
|
||||
data_layout.GetBlockPtr<GeometryID>(memory_block, storage::DataLayout::VIA_NODE_LIST);
|
||||
util::ShM<GeometryID, true>::vector via_geometry_list(
|
||||
via_geometry_list_ptr, data_layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
|
||||
m_via_geometry_list = std::move(via_geometry_list);
|
||||
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::VIA_NODE_LIST);
|
||||
util::vector_view<GeometryID> geometry_ids(
|
||||
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::VIA_NODE_LIST]);
|
||||
|
||||
const auto travel_mode_list_ptr =
|
||||
layout.GetBlockPtr<extractor::TravelMode>(memory_ptr, storage::DataLayout::TRAVEL_MODE);
|
||||
util::vector_view<extractor::TravelMode> travel_modes(
|
||||
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE]);
|
||||
|
||||
const auto lane_data_id_ptr =
|
||||
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
|
||||
util::vector_view<LaneDataID> lane_data_ids(
|
||||
lane_data_id_ptr, layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
|
||||
|
||||
const auto turn_instruction_list_ptr =
|
||||
layout.GetBlockPtr<extractor::guidance::TurnInstruction>(
|
||||
memory_ptr, storage::DataLayout::TURN_INSTRUCTION);
|
||||
util::vector_view<extractor::guidance::TurnInstruction> turn_instructions(
|
||||
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
|
||||
|
||||
const auto name_id_list_ptr =
|
||||
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST);
|
||||
util::vector_view<NameID> name_ids(name_id_list_ptr,
|
||||
layout.num_entries[storage::DataLayout::NAME_ID_LIST]);
|
||||
|
||||
const auto entry_class_id_list_ptr =
|
||||
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
|
||||
util::vector_view<EntryClassID> entry_class_ids(
|
||||
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||
|
||||
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
||||
util::vector_view<util::guidance::TurnBearing> pre_turn_bearings(
|
||||
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||
|
||||
const auto post_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
|
||||
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
||||
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
|
||||
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||
|
||||
turn_data = extractor::TurnDataView(std::move(geometry_ids),
|
||||
std::move(name_ids),
|
||||
std::move(turn_instructions),
|
||||
std::move(lane_data_ids),
|
||||
std::move(travel_modes),
|
||||
std::move(entry_class_ids),
|
||||
std::move(pre_turn_bearings),
|
||||
std::move(post_turn_bearings));
|
||||
}
|
||||
|
||||
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
@@ -398,28 +384,35 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto offsets_ptr = data_layout.GetBlockPtr<std::uint32_t>(
|
||||
memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS);
|
||||
util::ShM<std::uint32_t, true>::vector offsets(
|
||||
util::vector_view<std::uint32_t> offsets(
|
||||
offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]);
|
||||
m_lane_description_offsets = std::move(offsets);
|
||||
|
||||
auto masks_ptr = data_layout.GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
|
||||
memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS);
|
||||
|
||||
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector masks(
|
||||
util::vector_view<extractor::guidance::TurnLaneType::Mask> masks(
|
||||
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
|
||||
m_lane_description_masks = std::move(masks);
|
||||
|
||||
const auto lane_tupel_id_pair_ptr =
|
||||
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
|
||||
memory_block, storage::DataLayout::TURN_LANE_DATA);
|
||||
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
|
||||
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
|
||||
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
|
||||
}
|
||||
|
||||
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
auto turn_weight_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
||||
memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES);
|
||||
m_turn_weight_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||
m_turn_weight_penalties = util::vector_view<TurnPenalty>(
|
||||
turn_weight_penalties_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
|
||||
auto turn_duration_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
||||
memory_block, storage::DataLayout::TURN_DURATION_PENALTIES);
|
||||
m_turn_duration_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||
m_turn_duration_penalties = util::vector_view<TurnPenalty>(
|
||||
turn_duration_penalties_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]);
|
||||
}
|
||||
@@ -428,42 +421,42 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto geometries_index_ptr =
|
||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::GEOMETRIES_INDEX);
|
||||
util::ShM<unsigned, true>::vector geometry_begin_indices(
|
||||
util::vector_view<unsigned> geometry_begin_indices(
|
||||
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
|
||||
|
||||
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
|
||||
util::ShM<NodeID, true>::vector geometry_node_list(
|
||||
util::vector_view<NodeID> geometry_node_list(
|
||||
geometries_node_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]);
|
||||
|
||||
auto geometries_fwd_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_fwd_weight_list(
|
||||
util::vector_view<EdgeWeight> geometry_fwd_weight_list(
|
||||
geometries_fwd_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]);
|
||||
|
||||
auto geometries_rev_weight_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_rev_weight_list(
|
||||
util::vector_view<EdgeWeight> geometry_rev_weight_list(
|
||||
geometries_rev_weight_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
|
||||
|
||||
auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_fwd_duration_list(
|
||||
util::vector_view<EdgeWeight> geometry_fwd_duration_list(
|
||||
geometries_fwd_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
|
||||
|
||||
auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
|
||||
util::ShM<EdgeWeight, true>::vector geometry_rev_duration_list(
|
||||
util::vector_view<EdgeWeight> geometry_rev_duration_list(
|
||||
geometries_rev_duration_list_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]);
|
||||
|
||||
auto datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
|
||||
memory_block, storage::DataLayout::DATASOURCES_LIST);
|
||||
util::ShM<DatasourceID, true>::vector datasources_list(
|
||||
util::vector_view<DatasourceID> datasources_list(
|
||||
datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]);
|
||||
|
||||
segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices),
|
||||
@@ -482,13 +475,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
{
|
||||
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
|
||||
memory_block, storage::DataLayout::BEARING_CLASSID);
|
||||
typename util::ShM<BearingClassID, true>::vector bearing_class_id_table(
|
||||
typename util::vector_view<BearingClassID> bearing_class_id_table(
|
||||
bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]);
|
||||
m_bearing_class_id_table = std::move(bearing_class_id_table);
|
||||
|
||||
auto bearing_class_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
|
||||
memory_block, storage::DataLayout::BEARING_VALUES);
|
||||
typename util::ShM<DiscreteBearing, true>::vector bearing_class_table(
|
||||
typename util::vector_view<DiscreteBearing> bearing_class_table(
|
||||
bearing_class_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]);
|
||||
m_bearing_values_table = std::move(bearing_class_table);
|
||||
|
||||
@@ -496,17 +489,17 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
|
||||
auto blocks_ptr =
|
||||
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::BEARING_BLOCKS);
|
||||
util::ShM<unsigned, true>::vector bearing_offsets(
|
||||
util::vector_view<unsigned> bearing_offsets(
|
||||
offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]);
|
||||
util::ShM<IndexBlock, true>::vector bearing_blocks(
|
||||
util::vector_view<IndexBlock> bearing_blocks(
|
||||
blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]);
|
||||
|
||||
m_bearing_ranges_table = std::make_unique<util::RangeTable<16, true>>(
|
||||
m_bearing_ranges_table = std::make_unique<util::RangeTable<16, storage::Ownership::View>>(
|
||||
bearing_offsets, bearing_blocks, static_cast<unsigned>(m_bearing_values_table.size()));
|
||||
|
||||
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
|
||||
memory_block, storage::DataLayout::ENTRY_CLASS);
|
||||
typename util::ShM<util::guidance::EntryClass, true>::vector entry_class_table(
|
||||
typename util::vector_view<util::guidance::EntryClass> entry_class_table(
|
||||
entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]);
|
||||
m_entry_class_table = std::move(entry_class_table);
|
||||
}
|
||||
@@ -514,11 +507,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||
{
|
||||
InitializeChecksumPointer(data_layout, memory_block);
|
||||
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
|
||||
InitializeNodeInformationPointers(data_layout, memory_block);
|
||||
InitializeEdgeInformationPointers(data_layout, memory_block);
|
||||
InitializeTurnPenalties(data_layout, memory_block);
|
||||
InitializeGeometryPointers(data_layout, memory_block);
|
||||
InitializeTimestampPointer(data_layout, memory_block);
|
||||
InitializeViaNodeListPointer(data_layout, memory_block);
|
||||
InitializeNamePointers(data_layout, memory_block);
|
||||
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
|
||||
InitializeProfilePropertiesPointer(data_layout, memory_block);
|
||||
@@ -607,7 +600,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
virtual GeometryID GetGeometryIndexForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_via_geometry_list.at(id);
|
||||
return turn_data.GetGeometryID(id);
|
||||
}
|
||||
|
||||
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
|
||||
@@ -625,12 +618,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
extractor::guidance::TurnInstruction
|
||||
GetTurnInstructionForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_turn_instruction_list.at(id);
|
||||
return turn_data.GetTurnInstruction(id);
|
||||
}
|
||||
|
||||
extractor::TravelMode GetTravelModeForEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_travel_mode_list.at(id);
|
||||
return turn_data.GetTravelMode(id);
|
||||
}
|
||||
|
||||
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||
@@ -752,7 +745,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
NameID GetNameIndexFromEdgeID(const EdgeID id) const override final
|
||||
{
|
||||
return m_name_ID_list.at(id);
|
||||
return turn_data.GetNameID(id);
|
||||
}
|
||||
|
||||
StringView GetNameForID(const NameID id) const override final
|
||||
@@ -824,16 +817,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID eid) const override final
|
||||
{
|
||||
return m_entry_class_id_list.at(eid);
|
||||
return turn_data.GetEntryClassID(eid);
|
||||
}
|
||||
|
||||
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
|
||||
{
|
||||
return m_pre_turn_bearing.at(eid);
|
||||
return turn_data.GetPreTurnBearing(eid);
|
||||
}
|
||||
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
|
||||
{
|
||||
return m_post_turn_bearing.at(eid);
|
||||
return turn_data.GetPostTurnBearing(eid);
|
||||
}
|
||||
|
||||
util::guidance::EntryClass GetEntryClass(const EntryClassID entry_class_id) const override final
|
||||
@@ -841,15 +834,12 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
return m_entry_class_table.at(entry_class_id);
|
||||
}
|
||||
|
||||
bool hasLaneData(const EdgeID id) const override final
|
||||
{
|
||||
return INVALID_LANE_DATAID != m_lane_data_id.at(id);
|
||||
}
|
||||
bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); }
|
||||
|
||||
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
|
||||
{
|
||||
BOOST_ASSERT(hasLaneData(id));
|
||||
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
|
||||
BOOST_ASSERT(HasLaneData(id));
|
||||
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id));
|
||||
}
|
||||
|
||||
extractor::guidance::TurnLaneDescription
|
||||
@@ -868,36 +858,34 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
template <typename AlgorithmT> class ContiguousInternalMemoryDataFacade;
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::CH>
|
||||
class ContiguousInternalMemoryDataFacade<CH>
|
||||
: public ContiguousInternalMemoryDataFacadeBase,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<CH>
|
||||
{
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CH>(allocator)
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::CoreCH> final
|
||||
: public ContiguousInternalMemoryDataFacade<algorithm::CH>,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>
|
||||
class ContiguousInternalMemoryDataFacade<CoreCH> final
|
||||
: public ContiguousInternalMemoryDataFacade<CH>,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>
|
||||
{
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacade<algorithm::CH>(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::CoreCH>(allocator)
|
||||
: ContiguousInternalMemoryDataFacade<CH>(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<CoreCH>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
: public datafacade::AlgorithmDataFacade<algorithm::MLD>
|
||||
template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public AlgorithmDataFacade<MLD>
|
||||
{
|
||||
// MLD data
|
||||
partition::MultiLevelPartitionView mld_partition;
|
||||
@@ -922,22 +910,20 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
|
||||
|
||||
auto level_data =
|
||||
*data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
|
||||
data_layout.GetBlockPtr<partition::MultiLevelPartitionView::LevelData>(
|
||||
memory_block, storage::DataLayout::MLD_LEVEL_DATA);
|
||||
|
||||
auto mld_partition_ptr = data_layout.GetBlockPtr<PartitionID>(
|
||||
memory_block, storage::DataLayout::MLD_PARTITION);
|
||||
auto partition_entries_count =
|
||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION);
|
||||
util::ShM<PartitionID, true>::vector partition(mld_partition_ptr,
|
||||
partition_entries_count);
|
||||
util::vector_view<PartitionID> partition(mld_partition_ptr, partition_entries_count);
|
||||
|
||||
auto mld_chilren_ptr = data_layout.GetBlockPtr<CellID>(
|
||||
memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
auto children_entries_count =
|
||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN);
|
||||
util::ShM<CellID, true>::vector cell_to_children(mld_chilren_ptr,
|
||||
children_entries_count);
|
||||
util::vector_view<CellID> cell_to_children(mld_chilren_ptr, children_entries_count);
|
||||
|
||||
mld_partition =
|
||||
partition::MultiLevelPartitionView{level_data, partition, cell_to_children};
|
||||
@@ -969,15 +955,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
auto cell_level_offsets_entries_count =
|
||||
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
|
||||
|
||||
util::ShM<EdgeWeight, true>::vector weights(mld_cell_weights_ptr, weight_entries_count);
|
||||
util::ShM<NodeID, true>::vector source_boundary(mld_source_boundary_ptr,
|
||||
source_boundary_entries_count);
|
||||
util::ShM<NodeID, true>::vector destination_boundary(
|
||||
mld_destination_boundary_ptr, destination_boundary_entries_count);
|
||||
util::ShM<partition::CellStorageView::CellData, true>::vector cells(
|
||||
mld_cells_ptr, cells_entries_counts);
|
||||
util::ShM<std::uint64_t, true>::vector level_offsets(mld_cell_level_offsets_ptr,
|
||||
cell_level_offsets_entries_count);
|
||||
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
|
||||
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
|
||||
source_boundary_entries_count);
|
||||
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
|
||||
destination_boundary_entries_count);
|
||||
util::vector_view<partition::CellStorageView::CellData> cells(mld_cells_ptr,
|
||||
cells_entries_counts);
|
||||
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
|
||||
cell_level_offsets_entries_count);
|
||||
|
||||
mld_cell_storage = partition::CellStorageView{std::move(weights),
|
||||
std::move(source_boundary),
|
||||
@@ -997,11 +983,11 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
auto graph_node_to_offset_ptr = data_layout.GetBlockPtr<QueryGraph::EdgeOffset>(
|
||||
memory_block, storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET);
|
||||
|
||||
util::ShM<GraphNode, true>::vector node_list(
|
||||
util::vector_view<GraphNode> node_list(
|
||||
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]);
|
||||
util::ShM<GraphEdge, true>::vector edge_list(
|
||||
util::vector_view<GraphEdge> edge_list(
|
||||
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]);
|
||||
util::ShM<QueryGraph::EdgeOffset, true>::vector node_to_offset(
|
||||
util::vector_view<QueryGraph::EdgeOffset> node_to_offset(
|
||||
graph_node_to_offset_ptr,
|
||||
data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]);
|
||||
|
||||
@@ -1066,15 +1052,15 @@ class ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
};
|
||||
|
||||
template <>
|
||||
class ContiguousInternalMemoryDataFacade<algorithm::MLD> final
|
||||
class ContiguousInternalMemoryDataFacade<MLD> final
|
||||
: public ContiguousInternalMemoryDataFacadeBase,
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
|
||||
public ContiguousInternalMemoryAlgorithmDataFacade<MLD>
|
||||
{
|
||||
private:
|
||||
public:
|
||||
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
|
||||
: ContiguousInternalMemoryDataFacadeBase(allocator),
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>(allocator)
|
||||
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class BaseDataFacade
|
||||
const int bearing,
|
||||
const int bearing_range) const = 0;
|
||||
|
||||
virtual bool hasLaneData(const EdgeID id) const = 0;
|
||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||
virtual extractor::guidance::TurnLaneDescription
|
||||
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
|
||||
|
||||
+18
-17
@@ -49,7 +49,7 @@ class EngineInterface
|
||||
virtual Status Tile(const api::TileParameters ¶meters, std::string &result) const = 0;
|
||||
};
|
||||
|
||||
template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
template <typename Algorithm> class Engine final : public EngineInterface
|
||||
{
|
||||
public:
|
||||
explicit Engine(const EngineConfig &config)
|
||||
@@ -64,15 +64,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
if (config.use_shared_memory)
|
||||
{
|
||||
util::Log(logDEBUG) << "Using shared memory with algorithm "
|
||||
<< algorithm::name<AlgorithmT>();
|
||||
facade_provider = std::make_unique<WatchingProvider<AlgorithmT>>();
|
||||
<< routing_algorithms::name<Algorithm>();
|
||||
facade_provider = std::make_unique<WatchingProvider<Algorithm>>();
|
||||
}
|
||||
else
|
||||
{
|
||||
util::Log(logDEBUG) << "Using internal memory with algorithm "
|
||||
<< algorithm::name<AlgorithmT>();
|
||||
facade_provider =
|
||||
std::make_unique<ImmutableProvider<AlgorithmT>>(config.storage_config);
|
||||
<< routing_algorithms::name<Algorithm>();
|
||||
facade_provider = std::make_unique<ImmutableProvider<Algorithm>>(config.storage_config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return route_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
@@ -95,7 +94,7 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return table_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
@@ -103,14 +102,14 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return nearest_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
Status Trip(const api::TripParameters ¶ms, util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return trip_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
@@ -118,22 +117,22 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
util::json::Object &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return match_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
Status Tile(const api::TileParameters ¶ms, std::string &result) const override final
|
||||
{
|
||||
auto facade = facade_provider->Get();
|
||||
auto algorithms = RoutingAlgorithms<AlgorithmT>{heaps, *facade};
|
||||
auto algorithms = RoutingAlgorithms<Algorithm>{heaps, *facade};
|
||||
return tile_plugin.HandleRequest(*facade, algorithms, params, result);
|
||||
}
|
||||
|
||||
static bool CheckCompability(const EngineConfig &config);
|
||||
|
||||
private:
|
||||
std::unique_ptr<DataFacadeProvider<AlgorithmT>> facade_provider;
|
||||
mutable SearchEngineData heaps;
|
||||
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
|
||||
mutable SearchEngineData<Algorithm> heaps;
|
||||
|
||||
const plugins::ViaRoutePlugin route_plugin;
|
||||
const plugins::TablePlugin table_plugin;
|
||||
@@ -143,7 +142,8 @@ template <typename AlgorithmT> class Engine final : public EngineInterface
|
||||
const plugins::TilePlugin tile_plugin;
|
||||
};
|
||||
|
||||
template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &config)
|
||||
template <>
|
||||
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompability(const EngineConfig &config)
|
||||
{
|
||||
if (config.use_shared_memory)
|
||||
{
|
||||
@@ -168,9 +168,10 @@ template <> bool Engine<algorithm::CH>::CheckCompability(const EngineConfig &con
|
||||
}
|
||||
}
|
||||
|
||||
template <> bool Engine<algorithm::CoreCH>::CheckCompability(const EngineConfig &config)
|
||||
template <>
|
||||
bool Engine<routing_algorithms::corech::Algorithm>::CheckCompability(const EngineConfig &config)
|
||||
{
|
||||
if (!Engine<algorithm::CH>::CheckCompability(config))
|
||||
if (!Engine<routing_algorithms::ch::Algorithm>::CheckCompability(config))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -54,11 +54,11 @@ class RoutingAlgorithmsInterface
|
||||
};
|
||||
|
||||
// Short-lived object passed to each plugin in request to wrap routing algorithms
|
||||
template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
|
||||
template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgorithmsInterface
|
||||
{
|
||||
public:
|
||||
RoutingAlgorithms(SearchEngineData &heaps,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade)
|
||||
RoutingAlgorithms(SearchEngineData<Algorithm> &heaps,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade)
|
||||
: heaps(heaps), facade(facade)
|
||||
{
|
||||
}
|
||||
@@ -93,49 +93,50 @@ template <typename AlgorithmT> class RoutingAlgorithms final : public RoutingAlg
|
||||
|
||||
bool HasAlternativePathSearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasAlternativePathSearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasAlternativePathSearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasShortestPathSearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasShortestPathSearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasShortestPathSearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasDirectShortestPathSearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasDirectShortestPathSearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasDirectShortestPathSearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasMapMatching() const final override
|
||||
{
|
||||
return algorithm_trais::HasMapMatching<AlgorithmT>::value;
|
||||
return routing_algorithms::HasMapMatching<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasManyToManySearch() const final override
|
||||
{
|
||||
return algorithm_trais::HasManyToManySearch<AlgorithmT>::value;
|
||||
return routing_algorithms::HasManyToManySearch<Algorithm>::value;
|
||||
}
|
||||
|
||||
bool HasGetTileTurns() const final override
|
||||
{
|
||||
return algorithm_trais::HasGetTileTurns<AlgorithmT>::value;
|
||||
return routing_algorithms::HasGetTileTurns<Algorithm>::value;
|
||||
}
|
||||
|
||||
private:
|
||||
SearchEngineData &heaps;
|
||||
SearchEngineData<Algorithm> &heaps;
|
||||
|
||||
// Owned by shared-ptr passed to the query
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade;
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade;
|
||||
};
|
||||
|
||||
template <typename AlgorithmT>
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<AlgorithmT>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||
{
|
||||
return routing_algorithms::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult RoutingAlgorithms<Algorithm>::ShortestPathSearch(
|
||||
const std::vector<PhantomNodes> &phantom_node_pair,
|
||||
const boost::optional<bool> continue_straight_at_waypoint) const
|
||||
{
|
||||
@@ -143,25 +144,25 @@ InternalRouteResult RoutingAlgorithms<AlgorithmT>::ShortestPathSearch(
|
||||
heaps, facade, phantom_node_pair, continue_straight_at_waypoint);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult
|
||||
RoutingAlgorithms<AlgorithmT>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
|
||||
RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const
|
||||
{
|
||||
return routing_algorithms::directShortestPathSearch(heaps, facade, phantom_nodes);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
std::vector<EdgeWeight> RoutingAlgorithms<AlgorithmT>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const
|
||||
template <typename Algorithm>
|
||||
std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices) const
|
||||
{
|
||||
return routing_algorithms::manyToManySearch(
|
||||
return routing_algorithms::ch::manyToManySearch(
|
||||
heaps, facade, phantom_nodes, source_indices, target_indices);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMatching(
|
||||
template <typename Algorithm>
|
||||
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
|
||||
const routing_algorithms::CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
@@ -177,52 +178,53 @@ inline routing_algorithms::SubMatchingList RoutingAlgorithms<AlgorithmT>::MapMat
|
||||
allow_splitting);
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<AlgorithmT>::GetTileTurns(
|
||||
template <typename Algorithm>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::GetTileTurns(
|
||||
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &edges,
|
||||
const std::vector<std::size_t> &sorted_edge_indexes) const
|
||||
{
|
||||
return routing_algorithms::getTileTurns(facade, edges, sorted_edge_indexes);
|
||||
}
|
||||
|
||||
// CoreCH overrides
|
||||
template <>
|
||||
InternalRouteResult inline RoutingAlgorithms<
|
||||
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
throw util::exception("ManyToManySearch is disabled due to performance reasons");
|
||||
}
|
||||
|
||||
// MLD overrides for not implemented
|
||||
template <>
|
||||
InternalRouteResult inline RoutingAlgorithms<algorithm::MLD>::AlternativePathSearch(
|
||||
const PhantomNodes &) const
|
||||
InternalRouteResult inline RoutingAlgorithms<
|
||||
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||
{
|
||||
throw util::exception("AlternativePathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline InternalRouteResult
|
||||
RoutingAlgorithms<algorithm::MLD>::ShortestPathSearch(const std::vector<PhantomNodes> &,
|
||||
const boost::optional<bool>) const
|
||||
{
|
||||
throw util::exception("ShortestPathSearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<EdgeWeight>
|
||||
RoutingAlgorithms<algorithm::MLD>::ManyToManySearch(const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
|
||||
const std::vector<PhantomNode> &,
|
||||
const std::vector<std::size_t> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
throw util::exception("ManyToManySearch is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline routing_algorithms::SubMatchingList
|
||||
RoutingAlgorithms<algorithm::MLD>::MapMatching(const routing_algorithms::CandidateLists &,
|
||||
const std::vector<util::Coordinate> &,
|
||||
const std::vector<unsigned> &,
|
||||
const std::vector<boost::optional<double>> &,
|
||||
const bool) const
|
||||
{
|
||||
throw util::exception("MapMatching is not implemented");
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<algorithm::MLD>::GetTileTurns(
|
||||
inline std::vector<routing_algorithms::TurnData>
|
||||
RoutingAlgorithms<routing_algorithms::mld::Algorithm>::GetTileTurns(
|
||||
const std::vector<datafacade::BaseDataFacade::RTreeLeaf> &,
|
||||
const std::vector<std::size_t> &) const
|
||||
{
|
||||
|
||||
@@ -15,12 +15,13 @@ namespace engine
|
||||
{
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
namespace ch
|
||||
{
|
||||
InternalRouteResult
|
||||
alternativePathSearch(SearchEngineData &search_engine_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const PhantomNodes &phantom_node_pair);
|
||||
|
||||
} // namespace ch
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -21,11 +21,20 @@ namespace routing_algorithms
|
||||
/// by the previous route.
|
||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||
/// not fully contracted graphs.
|
||||
template <typename AlgorithmT>
|
||||
InternalRouteResult
|
||||
directShortestPathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes);
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -13,16 +13,18 @@ namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
namespace ch
|
||||
{
|
||||
std::vector<EdgeWeight>
|
||||
manyToManySearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices);
|
||||
} // namespace ch
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -22,25 +22,17 @@ static const constexpr double DEFAULT_GPS_PRECISION = 5;
|
||||
|
||||
//[1] "Hidden Markov Map Matching Through Noise and Sparseness";
|
||||
// P. Newson and J. Krumm; 2009; ACM GIS
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
template <typename Algorithm>
|
||||
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* MAP_MATCHING_HPP */
|
||||
|
||||
@@ -37,6 +37,10 @@ static constexpr bool FORWARD_DIRECTION = true;
|
||||
static constexpr bool REVERSE_DIRECTION = false;
|
||||
static constexpr bool DO_NOT_FORCE_LOOPS = false;
|
||||
|
||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
template <bool DIRECTION, typename Heap>
|
||||
void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
||||
{
|
||||
@@ -58,7 +62,8 @@ void insertNodesInHeap(Heap &heap, const PhantomNode &phantom_node)
|
||||
}
|
||||
|
||||
template <bool DIRECTION>
|
||||
void insertNodesInHeap(SearchEngineData::ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
|
||||
void insertNodesInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||
const PhantomNode &phantom_node)
|
||||
{
|
||||
BOOST_ASSERT(phantom_node.IsValid());
|
||||
|
||||
@@ -169,7 +174,7 @@ void annotatePath(const FacadeT &facade,
|
||||
util::guidance::TurnBearing(0)});
|
||||
}
|
||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||
if (facade.hasLaneData(turn_id))
|
||||
if (facade.HasLaneData(turn_id))
|
||||
unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
|
||||
|
||||
unpacked_path.back().entry_classid = facade.GetEntryClassID(turn_id);
|
||||
@@ -305,6 +310,57 @@ void annotatePath(const FacadeT &facade,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Algorithm>
|
||||
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PathData> unpacked_path,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom)
|
||||
{
|
||||
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
|
||||
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
||||
|
||||
double distance = 0;
|
||||
double prev_lat = static_cast<double>(toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
double prev_lon = static_cast<double>(toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
double prev_cos = std::cos(prev_lat);
|
||||
for (const auto &p : unpacked_path)
|
||||
{
|
||||
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
||||
|
||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
distance += EARTH_RADIUS * charv;
|
||||
|
||||
prev_lat = current_lat;
|
||||
prev_lon = current_lon;
|
||||
prev_cos = current_cos;
|
||||
}
|
||||
|
||||
const double current_lat =
|
||||
static_cast<double>(toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
|
||||
const double current_lon =
|
||||
static_cast<double>(toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
|
||||
const double current_cos = std::cos(current_lat);
|
||||
|
||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
||||
|
||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||
distance += EARTH_RADIUS * charv;
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ch
|
||||
|
||||
// Stalling
|
||||
template <bool DIRECTION, typename HeapT>
|
||||
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID node,
|
||||
const EdgeWeight weight,
|
||||
const HeapT &query_heap)
|
||||
@@ -49,10 +49,10 @@ bool stallAtNode(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
}
|
||||
|
||||
template <bool DIRECTION>
|
||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID node,
|
||||
const EdgeWeight weight,
|
||||
SearchEngineData::QueryHeap &heap)
|
||||
SearchEngineData<Algorithm>::QueryHeap &heap)
|
||||
{
|
||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
@@ -113,9 +113,9 @@ we need to add an offset to the termination criterion.
|
||||
static constexpr bool ENABLE_STALLING = true;
|
||||
static constexpr bool DISABLE_STALLING = false;
|
||||
template <bool DIRECTION, bool STALLING = ENABLE_STALLING>
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
NodeID &middle_node_id,
|
||||
EdgeWeight &upper_bound,
|
||||
EdgeWeight min_edge_offset,
|
||||
@@ -186,9 +186,8 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
}
|
||||
|
||||
template <bool UseDuration>
|
||||
EdgeWeight
|
||||
getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
NodeID node)
|
||||
EdgeWeight getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
NodeID node)
|
||||
{
|
||||
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||
@@ -228,7 +227,7 @@ getLoopWeight(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH
|
||||
* original edge found.
|
||||
*/
|
||||
template <typename BidirectionalIterator, typename Callback>
|
||||
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void unpackPath(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
BidirectionalIterator packed_path_begin,
|
||||
BidirectionalIterator packed_path_end,
|
||||
Callback &&callback)
|
||||
@@ -325,17 +324,17 @@ void unpackPath(const FacadeT &facade,
|
||||
* @param to the node the CH edge finishes at
|
||||
* @param unpacked_path the sequence of original NodeIDs that make up the expanded CH edge
|
||||
*/
|
||||
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void unpackEdge(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID from,
|
||||
const NodeID to,
|
||||
std::vector<NodeID> &unpacked_path);
|
||||
|
||||
void retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
|
||||
const SearchEngineData::QueryHeap &reverse_heap,
|
||||
void retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
const SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID> &packed_path);
|
||||
|
||||
void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
|
||||
void retrievePackedPathFromSingleHeap(const SearchEngineData<Algorithm>::QueryHeap &search_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID> &packed_path);
|
||||
|
||||
@@ -351,37 +350,33 @@ void retrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_
|
||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||
// requires
|
||||
// a force loop, if the heaps have been initialized with positive offsets.
|
||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
std::int32_t &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
|
||||
inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &,
|
||||
SearchEngineData::QueryHeap &,
|
||||
std::int32_t &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
search(facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
weight,
|
||||
packed_leg,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
duration_upper_bound);
|
||||
}
|
||||
// Requires the heaps for be empty
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double
|
||||
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
} // namespace ch
|
||||
|
||||
namespace corech
|
||||
{
|
||||
// assumes that heaps are already setup correctly.
|
||||
// A forced loop might be necessary, if source and target are on the same segment.
|
||||
// If this is the case and the offsets of the respective direction are larger for the source
|
||||
@@ -391,66 +386,41 @@ inline void search(const datafacade::ContiguousInternalMemoryDataFacade<algorith
|
||||
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
|
||||
// requires
|
||||
// a force loop, if the heaps have been initialized with positive offsets.
|
||||
void search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &forward_core_heap,
|
||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||
void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
||||
int &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||
|
||||
double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const std::vector<NodeID> &packed_path,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom);
|
||||
|
||||
// Requires the heaps for be empty
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double
|
||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &forward_core_heap,
|
||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<ch::Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
// Requires the heaps for be empty
|
||||
// If heaps should be adjusted to be initialized outside of this function,
|
||||
// the addition of force_loop parameters might be required
|
||||
double
|
||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT);
|
||||
|
||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps
|
||||
inline double
|
||||
getNetworkDistance(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData::QueryHeap &forward_heap,
|
||||
SearchEngineData::QueryHeap &reverse_heap,
|
||||
SearchEngineData::QueryHeap &,
|
||||
SearchEngineData::QueryHeap &,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
int duration_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
template <typename RandomIter, typename FacadeT>
|
||||
void unpackPath(const FacadeT &facade,
|
||||
RandomIter packed_path_begin,
|
||||
RandomIter packed_path_end,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
std::vector<PathData> &unpacked_path)
|
||||
{
|
||||
return getNetworkDistance(
|
||||
facade, forward_heap, reverse_heap, source_phantom, target_phantom, duration_upper_bound);
|
||||
return ch::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
|
||||
}
|
||||
|
||||
} // namespace ch
|
||||
} // namespace corech
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace
|
||||
// Unrestricted search (Args is const PhantomNodes &):
|
||||
// * use partition.GetQueryLevel to find the node query level based on source and target phantoms
|
||||
// * allow to traverse all cells
|
||||
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
|
||||
NodeID node,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
inline LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
|
||||
NodeID node,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
{
|
||||
auto level = [&partition, node](const SegmentID &source, const SegmentID &target) {
|
||||
if (source.enabled && target.enabled)
|
||||
@@ -43,25 +43,31 @@ LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &partition,
|
||||
phantom_nodes.target_phantom.reverse_segment_id)));
|
||||
}
|
||||
|
||||
bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
|
||||
inline bool checkParentCellRestriction(CellID, const PhantomNodes &) { return true; }
|
||||
|
||||
// Restricted search (Args is LevelID, CellID):
|
||||
// * use the fixed level for queries
|
||||
// * check if the node cell is the same as the specified parent onr
|
||||
LevelID getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
|
||||
inline LevelID
|
||||
getNodeQureyLevel(const partition::MultiLevelPartitionView &, NodeID, LevelID level, CellID)
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
bool checkParentCellRestriction(CellID cell, LevelID, CellID parent) { return cell == parent; }
|
||||
inline bool checkParentCellRestriction(CellID cell, LevelID, CellID parent)
|
||||
{
|
||||
return cell == parent;
|
||||
}
|
||||
}
|
||||
|
||||
template <bool DIRECTION, typename... Args>
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
|
||||
void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
NodeID &middle_node,
|
||||
EdgeWeight &path_upper_bound,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
Args... args)
|
||||
{
|
||||
const auto &partition = facade.GetMultiLevelPartition();
|
||||
@@ -79,7 +85,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
{
|
||||
auto reverse_weight = reverse_heap.GetKey(node);
|
||||
auto path_weight = weight + reverse_weight;
|
||||
if (path_weight >= 0 && path_weight < path_upper_bound)
|
||||
|
||||
// if loops are forced, they are so at the source
|
||||
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
|
||||
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
|
||||
(path_weight >= 0) && (path_weight < path_upper_bound))
|
||||
{
|
||||
middle_node = node;
|
||||
path_upper_bound = path_weight;
|
||||
@@ -171,9 +181,13 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
|
||||
|
||||
template <typename... Args>
|
||||
std::tuple<EdgeWeight, NodeID, NodeID, std::vector<EdgeID>>
|
||||
search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &forward_heap,
|
||||
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
|
||||
search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
EdgeWeight weight_upper_bound,
|
||||
Args... args)
|
||||
{
|
||||
|
||||
@@ -184,7 +198,7 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
|
||||
// run two-Target Dijkstra routing step.
|
||||
NodeID middle = SPECIAL_NODEID;
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
EdgeWeight weight = weight_upper_bound;
|
||||
EdgeWeight forward_heap_min = forward_heap.MinKey();
|
||||
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
|
||||
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
||||
@@ -192,22 +206,34 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
{
|
||||
if (!forward_heap.Empty())
|
||||
{
|
||||
routingStep<FORWARD_DIRECTION>(
|
||||
facade, forward_heap, reverse_heap, middle, weight, args...);
|
||||
routingStep<FORWARD_DIRECTION>(facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
middle,
|
||||
weight,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
args...);
|
||||
if (!forward_heap.Empty())
|
||||
forward_heap_min = forward_heap.MinKey();
|
||||
}
|
||||
if (!reverse_heap.Empty())
|
||||
{
|
||||
routingStep<REVERSE_DIRECTION>(
|
||||
facade, reverse_heap, forward_heap, middle, weight, args...);
|
||||
routingStep<REVERSE_DIRECTION>(facade,
|
||||
reverse_heap,
|
||||
forward_heap,
|
||||
middle,
|
||||
weight,
|
||||
force_loop_reverse,
|
||||
force_loop_forward,
|
||||
args...);
|
||||
if (!reverse_heap.Empty())
|
||||
reverse_heap_min = reverse_heap.MinKey();
|
||||
}
|
||||
};
|
||||
|
||||
// No path found for both target nodes?
|
||||
if (weight == INVALID_EDGE_WEIGHT || SPECIAL_NODEID == middle)
|
||||
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
|
||||
{
|
||||
return std::make_tuple(
|
||||
INVALID_EDGE_WEIGHT, SPECIAL_NODEID, SPECIAL_NODEID, std::vector<EdgeID>());
|
||||
@@ -268,7 +294,15 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
NodeID subpath_source, subpath_target;
|
||||
std::vector<EdgeID> subpath;
|
||||
std::tie(subpath_weight, subpath_source, subpath_target, subpath) =
|
||||
search(facade, forward_heap, reverse_heap, sublevel, parent_cell_id);
|
||||
search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
sublevel,
|
||||
parent_cell_id);
|
||||
BOOST_ASSERT(!subpath.empty());
|
||||
BOOST_ASSERT(subpath_source == source);
|
||||
BOOST_ASSERT(subpath_target == target);
|
||||
@@ -279,6 +313,103 @@ search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &fac
|
||||
return std::make_tuple(weight, source_node, target_node, std::move(unpacked_path));
|
||||
}
|
||||
|
||||
// TODO reorder parameters
|
||||
// Alias to be compatible with the overload for CoreCH that needs 4 heaps for shortest path search
|
||||
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
EdgeWeight &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
|
||||
if (weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
packed_leg.push_back(source_node);
|
||||
std::transform(unpacked_edges.begin(),
|
||||
unpacked_edges.end(),
|
||||
std::back_inserter(packed_leg),
|
||||
[&facade](const auto edge) { return facade.GetTarget(edge); });
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RandomIter, typename FacadeT>
|
||||
void unpackPath(const FacadeT &facade,
|
||||
RandomIter packed_path_begin,
|
||||
RandomIter packed_path_end,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
std::vector<PathData> &unpacked_path)
|
||||
{
|
||||
const auto nodes_number = std::distance(packed_path_begin, packed_path_end);
|
||||
BOOST_ASSERT(nodes_number > 0);
|
||||
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
|
||||
auto source_node = *packed_path_begin, target_node = *packed_path_begin;
|
||||
|
||||
if (nodes_number > 1)
|
||||
{
|
||||
target_node = *std::prev(packed_path_end);
|
||||
util::for_each_pair(packed_path_begin,
|
||||
packed_path_end,
|
||||
[&facade, &unpacked_edges](const auto from, const auto to) {
|
||||
unpacked_edges.push_back(facade.FindEdge(from, to));
|
||||
});
|
||||
}
|
||||
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
}
|
||||
|
||||
inline double
|
||||
getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
const PhantomNode &source_phantom,
|
||||
const PhantomNode &target_phantom,
|
||||
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
|
||||
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||
|
||||
EdgeWeight weight;
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
std::tie(weight, source_node, target_node, unpacked_edges) = search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
weight_upper_bound,
|
||||
phantom_nodes);
|
||||
|
||||
if (weight == INVALID_EDGE_WEIGHT)
|
||||
return std::numeric_limits<double>::max();
|
||||
|
||||
std::vector<PathData> unpacked_path;
|
||||
annotatePath(facade, source_node, target_node, unpacked_edges, phantom_nodes, unpacked_path);
|
||||
|
||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
||||
}
|
||||
|
||||
} // namespace mld
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -13,15 +13,10 @@ namespace engine
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
InternalRouteResult
|
||||
shortestPathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
shortestPathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const boost::optional<bool> continue_straight_at_waypoint);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ struct TurnData final
|
||||
using RTreeLeaf = datafacade::BaseDataFacade::RTreeLeaf;
|
||||
|
||||
std::vector<TurnData>
|
||||
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
getTileTurns(const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
const std::vector<RTreeLeaf> &edges,
|
||||
const std::vector<std::size_t> &sorted_edge_indexes);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
#include "engine/algorithm.hpp"
|
||||
#include "util/binary_heap.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -12,6 +12,16 @@ namespace osrm
|
||||
namespace engine
|
||||
{
|
||||
|
||||
// Algorithm-dependent heaps
|
||||
// - CH algorithms use CH heaps
|
||||
// - CoreCH algorithms use CoreCH heaps that can be upcasted to CH heaps when CH algorithms reused
|
||||
// by CoreCH at calling ch::routingStep, ch::retrievePackedPathFromSingleHeap and ch::unpackPath
|
||||
// - MLD algorithms use MLD heaps
|
||||
|
||||
template <typename Algorithm> struct SearchEngineData
|
||||
{
|
||||
};
|
||||
|
||||
struct HeapData
|
||||
{
|
||||
NodeID parent;
|
||||
@@ -24,14 +34,7 @@ struct ManyToManyHeapData : HeapData
|
||||
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
|
||||
};
|
||||
|
||||
struct MultiLayerDijkstraHeapData : HeapData
|
||||
{
|
||||
bool from_clique_arc;
|
||||
MultiLayerDijkstraHeapData(NodeID p) : HeapData(p), from_clique_arc(false) {}
|
||||
MultiLayerDijkstraHeapData(NodeID p, bool from) : HeapData(p), from_clique_arc(from) {}
|
||||
};
|
||||
|
||||
struct SearchEngineData
|
||||
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||
{
|
||||
using QueryHeap = util::
|
||||
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||
@@ -45,14 +48,6 @@ struct SearchEngineData
|
||||
|
||||
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
|
||||
|
||||
using MultiLayerDijkstraHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
MultiLayerDijkstraHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
|
||||
using MultiLayerDijkstraHeapPtr = boost::thread_specific_ptr<MultiLayerDijkstraHeap>;
|
||||
|
||||
static SearchEngineHeapPtr forward_heap_1;
|
||||
static SearchEngineHeapPtr reverse_heap_1;
|
||||
static SearchEngineHeapPtr forward_heap_2;
|
||||
@@ -60,18 +55,44 @@ struct SearchEngineData
|
||||
static SearchEngineHeapPtr forward_heap_3;
|
||||
static SearchEngineHeapPtr reverse_heap_3;
|
||||
static ManyToManyHeapPtr many_to_many_heap;
|
||||
static MultiLayerDijkstraHeapPtr mld_forward_heap;
|
||||
static MultiLayerDijkstraHeapPtr mld_reverse_heap;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearSecondThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearThirdThreadLocalStorage(unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearManyToManyThreadLocalStorage(const unsigned number_of_nodes);
|
||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||
};
|
||||
|
||||
void InitializeOrClearMultiLayerDijkstraThreadLocalStorage(const unsigned number_of_nodes);
|
||||
template <>
|
||||
struct SearchEngineData<routing_algorithms::corech::Algorithm>
|
||||
: public SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||
{
|
||||
};
|
||||
|
||||
struct MultiLayerDijkstraHeapData
|
||||
{
|
||||
NodeID parent;
|
||||
bool from_clique_arc;
|
||||
MultiLayerDijkstraHeapData(NodeID p) : parent(p), from_clique_arc(false) {}
|
||||
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
|
||||
};
|
||||
|
||||
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
||||
{
|
||||
using QueryHeap = util::BinaryHeap<NodeID,
|
||||
NodeID,
|
||||
EdgeWeight,
|
||||
MultiLayerDijkstraHeapData,
|
||||
util::UnorderedMapStorage<NodeID, int>>;
|
||||
|
||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||
|
||||
static SearchEngineHeapPtr forward_heap_1;
|
||||
static SearchEngineHeapPtr reverse_heap_1;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
@@ -72,7 +73,8 @@ class EdgeBasedGraphFactory
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::PackedVector<OSMNodeID> &osm_node_ids,
|
||||
ProfileProperties profile_properties,
|
||||
const util::NameTable &name_table,
|
||||
std::vector<std::uint32_t> &turn_lane_offsets,
|
||||
@@ -128,7 +130,8 @@ class EdgeBasedGraphFactory
|
||||
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||
EdgeID m_max_edge_id;
|
||||
|
||||
const std::vector<QueryNode> &m_node_info_list;
|
||||
const std::vector<util::Coordinate> &m_coordinates;
|
||||
const util::PackedVector<OSMNodeID> &m_osm_node_ids;
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
|
||||
std::shared_ptr<RestrictionMap const> m_restriction_map;
|
||||
|
||||
@@ -156,9 +159,6 @@ class EdgeBasedGraphFactory
|
||||
|
||||
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
||||
|
||||
void FlushVectorToStream(storage::io::FileWriter &edge_data_file,
|
||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||
|
||||
std::size_t restricted_turns_counter;
|
||||
std::size_t skipped_uturns_counter;
|
||||
std::size_t skipped_barrier_turns_counter;
|
||||
|
||||
@@ -58,7 +58,8 @@ class Extractor
|
||||
|
||||
std::pair<std::size_t, EdgeID>
|
||||
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<QueryNode> &internal_to_external_node_map,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids,
|
||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
@@ -66,18 +67,18 @@ class Extractor
|
||||
const std::string &intersection_class_output_file);
|
||||
void WriteProfileProperties(const std::string &output_path,
|
||||
const ProfileProperties &properties) const;
|
||||
void WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map);
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<EdgeBasedEdge> &edges,
|
||||
std::vector<EdgeBasedNode> &nodes) const;
|
||||
void BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
|
||||
std::vector<bool> node_is_startpoint,
|
||||
const std::vector<QueryNode> &internal_to_external_node_map);
|
||||
const std::vector<util::Coordinate> &coordinates);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph>
|
||||
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||
std::unordered_set<NodeID> &traffic_lights,
|
||||
std::vector<QueryNode> &internal_to_external_node_map);
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids);
|
||||
|
||||
void WriteEdgeBasedGraph(const std::string &output_file_filename,
|
||||
const EdgeID max_edge_id,
|
||||
@@ -94,7 +95,7 @@ class Extractor
|
||||
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
|
||||
static void WriteCompressedNodeBasedGraph(const std::string &path,
|
||||
const util::NodeBasedDynamicGraph &graph,
|
||||
const std::vector<QueryNode> &externals);
|
||||
const std::vector<util::Coordinate> &coordiantes);
|
||||
|
||||
// globals persisting during the extraction process and the graph generation process
|
||||
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
#ifndef OSRM_EXTRACTOR_FILES_HPP
|
||||
#define OSRM_EXTRACTOR_FILES_HPP
|
||||
|
||||
#include "extractor/guidance/turn_lane_types.hpp"
|
||||
#include "extractor/serialization.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/serialization.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace files
|
||||
{
|
||||
|
||||
// reads .osrm.nodes
|
||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||
inline void readNodes(const boost::filesystem::path &path,
|
||||
CoordinatesT &coordinates,
|
||||
PackedOSMIDsT &osm_node_ids)
|
||||
{
|
||||
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, coordinates);
|
||||
util::serialization::read(reader, osm_node_ids);
|
||||
}
|
||||
|
||||
// writes .osrm.nodes
|
||||
template <typename CoordinatesT, typename PackedOSMIDsT>
|
||||
inline void writeNodes(const boost::filesystem::path &path,
|
||||
const CoordinatesT &coordinates,
|
||||
const PackedOSMIDsT &osm_node_ids)
|
||||
{
|
||||
static_assert(std::is_same<typename CoordinatesT::value_type, util::Coordinate>::value, "");
|
||||
static_assert(std::is_same<typename PackedOSMIDsT::value_type, OSMNodeID>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, coordinates);
|
||||
util::serialization::write(writer, osm_node_ids);
|
||||
}
|
||||
|
||||
// reads .osrm.cnbg_to_ebg
|
||||
inline void readNBGMapping(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, mapping);
|
||||
}
|
||||
|
||||
// writes .osrm.cnbg_to_ebg
|
||||
inline void writeNBGMapping(const boost::filesystem::path &path,
|
||||
const std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, mapping);
|
||||
}
|
||||
|
||||
// reads .osrm.datasource_names
|
||||
inline void readDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, sources);
|
||||
}
|
||||
|
||||
// writes .osrm.datasource_names
|
||||
inline void writeDatasources(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, sources);
|
||||
}
|
||||
|
||||
// reads .osrm.geometry
|
||||
template <typename SegmentDataT>
|
||||
inline void readSegmentData(const boost::filesystem::path &path, SegmentDataT &segment_data)
|
||||
{
|
||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, segment_data);
|
||||
}
|
||||
|
||||
// writes .osrm.geometry
|
||||
template <typename SegmentDataT>
|
||||
inline void writeSegmentData(const boost::filesystem::path &path, const SegmentDataT &segment_data)
|
||||
{
|
||||
static_assert(std::is_same<SegmentDataContainer, SegmentDataT>::value ||
|
||||
std::is_same<SegmentDataView, SegmentDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, segment_data);
|
||||
}
|
||||
|
||||
// reads .osrm.edges
|
||||
template <typename TurnDataT>
|
||||
inline void readTurnData(const boost::filesystem::path &path, TurnDataT &turn_data)
|
||||
{
|
||||
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
||||
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, turn_data);
|
||||
}
|
||||
|
||||
// writes .osrm.edges
|
||||
template <typename TurnDataT>
|
||||
inline void writeTurnData(const boost::filesystem::path &path, const TurnDataT &turn_data)
|
||||
{
|
||||
static_assert(std::is_same<TurnDataContainer, TurnDataT>::value ||
|
||||
std::is_same<TurnDataView, TurnDataT>::value ||
|
||||
std::is_same<TurnDataExternalContainer, TurnDataT>::value,
|
||||
"");
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, turn_data);
|
||||
}
|
||||
|
||||
// reads .osrm.tls
|
||||
template <typename OffsetsT, typename MaskT>
|
||||
inline void readTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
OffsetsT &turn_offsets,
|
||||
MaskT &turn_masks)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<typename MaskT::value_type, extractor::guidance::TurnLaneType::Mask>::value,
|
||||
"");
|
||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
storage::serialization::read(reader, turn_offsets);
|
||||
storage::serialization::read(reader, turn_masks);
|
||||
}
|
||||
|
||||
// writes .osrm.tls
|
||||
template <typename OffsetsT, typename MaskT>
|
||||
inline void writeTurnLaneDescriptions(const boost::filesystem::path &path,
|
||||
const OffsetsT &turn_offsets,
|
||||
const MaskT &turn_masks)
|
||||
{
|
||||
static_assert(
|
||||
std::is_same<typename MaskT::value_type, extractor::guidance::TurnLaneType::Mask>::value,
|
||||
"");
|
||||
static_assert(std::is_same<typename OffsetsT::value_type, std::uint32_t>::value, "");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
storage::serialization::write(writer, turn_offsets);
|
||||
storage::serialization::write(writer, turn_masks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@ class CoordinateExtractor
|
||||
public:
|
||||
CoordinateExtractor(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const std::vector<extractor::QueryNode> &node_coordinates);
|
||||
const std::vector<util::Coordinate> &node_coordinates);
|
||||
|
||||
/* Find a interpolated coordinate a long the compressed geometries. The desired coordinate
|
||||
* should be in a certain distance. This method is dedicated to find representative coordinates
|
||||
@@ -156,7 +156,7 @@ class CoordinateExtractor
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries;
|
||||
const std::vector<extractor::QueryNode> &node_coordinates;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
|
||||
double ComputeInterpolationFactor(const double desired_distance,
|
||||
const double distance_to_first,
|
||||
|
||||
@@ -40,7 +40,7 @@ class IntersectionGenerator
|
||||
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container);
|
||||
|
||||
// For a source node `a` and a via edge `ab` creates an intersection at target `b`.
|
||||
@@ -112,7 +112,7 @@ class IntersectionGenerator
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const RestrictionMap &restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const std::vector<QueryNode> &node_info_list;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
|
||||
// own state, used to find the correct coordinates along a road
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
|
||||
@@ -34,7 +34,7 @@ class IntersectionHandler
|
||||
{
|
||||
public:
|
||||
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
@@ -51,7 +51,7 @@ class IntersectionHandler
|
||||
|
||||
protected:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const std::vector<QueryNode> &node_info_list;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
const util::NameTable &name_table;
|
||||
const SuffixTable &street_name_suffix_table;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
|
||||
@@ -43,7 +43,7 @@ class IntersectionNormalizer
|
||||
std::vector<IntersectionNormalizationOperation> performed_merges;
|
||||
};
|
||||
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<extractor::QueryNode> &node_coordinates,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
|
||||
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -22,7 +23,6 @@ class NameTable;
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct QueryNode;
|
||||
class SuffixTable;
|
||||
|
||||
namespace guidance
|
||||
@@ -37,7 +37,7 @@ class MergableRoadDetector
|
||||
using MergableRoadData = IntersectionShapeData;
|
||||
|
||||
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_coordinates,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const IntersectionGenerator &intersection_generator,
|
||||
const CoordinateExtractor &coordinate_extractor,
|
||||
const util::NameTable &name_table,
|
||||
@@ -138,7 +138,7 @@ class MergableRoadDetector
|
||||
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
|
||||
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const std::vector<QueryNode> &node_coordinates;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const CoordinateExtractor &coordinate_extractor;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class MotorwayHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
@@ -41,7 +41,7 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
|
||||
@@ -27,7 +27,7 @@ class SliproadHandler final : public IntersectionHandler
|
||||
public:
|
||||
SliproadHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class SuppressModeHandler final : public IntersectionHandler
|
||||
public:
|
||||
SuppressModeHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class TurnAnalysis
|
||||
{
|
||||
public:
|
||||
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
|
||||
@@ -29,7 +29,7 @@ class TurnHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_IO_HPP
|
||||
#define OSRM_EXTRACTOR_IO_HPP
|
||||
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
inline void read(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(mapping);
|
||||
}
|
||||
|
||||
inline void write(const boost::filesystem::path &path, const std::vector<NBGToEBG> &mapping)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter reader{path, fingerprint};
|
||||
|
||||
reader.SerializeVector(mapping);
|
||||
}
|
||||
|
||||
inline void read(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.ReadInto(sources);
|
||||
}
|
||||
|
||||
inline void write(const boost::filesystem::path &path, Datasources &sources)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteFrom(sources);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void read(const boost::filesystem::path &path, SegmentDataContainer &segment_data)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
auto num_indices = reader.ReadElementCount32();
|
||||
segment_data.index.resize(num_indices);
|
||||
reader.ReadInto(segment_data.index.data(), num_indices);
|
||||
|
||||
auto num_entries = reader.ReadElementCount32();
|
||||
segment_data.nodes.resize(num_entries);
|
||||
segment_data.fwd_weights.resize(num_entries);
|
||||
segment_data.rev_weights.resize(num_entries);
|
||||
segment_data.fwd_durations.resize(num_entries);
|
||||
segment_data.rev_durations.resize(num_entries);
|
||||
segment_data.datasources.resize(num_entries);
|
||||
|
||||
reader.ReadInto(segment_data.nodes);
|
||||
reader.ReadInto(segment_data.fwd_weights);
|
||||
reader.ReadInto(segment_data.rev_weights);
|
||||
reader.ReadInto(segment_data.fwd_durations);
|
||||
reader.ReadInto(segment_data.rev_durations);
|
||||
reader.ReadInto(segment_data.datasources);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void write(const boost::filesystem::path &path, const SegmentDataContainer &segment_data)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteElementCount32(segment_data.index.size());
|
||||
writer.WriteFrom(segment_data.index);
|
||||
|
||||
writer.WriteElementCount32(segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.fwd_weights.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.rev_weights.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.fwd_durations.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.rev_durations.size() == segment_data.nodes.size());
|
||||
BOOST_ASSERT(segment_data.datasources.size() == segment_data.nodes.size());
|
||||
writer.WriteFrom(segment_data.nodes);
|
||||
writer.WriteFrom(segment_data.fwd_weights);
|
||||
writer.WriteFrom(segment_data.rev_weights);
|
||||
writer.WriteFrom(segment_data.fwd_durations);
|
||||
writer.WriteFrom(segment_data.rev_durations);
|
||||
writer.WriteFrom(segment_data.datasources);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,11 @@
|
||||
#ifndef OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
|
||||
#define OSRM_EXTRACTOR_SEGMENT_DATA_CONTAINER_HPP_
|
||||
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
@@ -22,24 +25,24 @@ class CompressedEdgeContainer;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class SegmentDataContainerImpl;
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl;
|
||||
}
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
template <bool UseShareMemory>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class SegmentDataContainerImpl
|
||||
template <storage::Ownership Ownership> class SegmentDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
friend CompressedEdgeContainer;
|
||||
|
||||
@@ -189,11 +192,11 @@ template <bool UseShareMemory> class SegmentDataContainerImpl
|
||||
auto GetNumberOfSegments() const { return fwd_weights.size(); }
|
||||
|
||||
friend void
|
||||
io::read<UseShareMemory>(const boost::filesystem::path &path,
|
||||
detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
friend void
|
||||
io::write<UseShareMemory>(const boost::filesystem::path &path,
|
||||
const detail::SegmentDataContainerImpl<UseShareMemory> &segment_data);
|
||||
serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
friend void serialization::write<Ownership>(
|
||||
storage::io::FileWriter &writer,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data);
|
||||
|
||||
private:
|
||||
Vector<std::uint32_t> index;
|
||||
@@ -206,8 +209,8 @@ template <bool UseShareMemory> class SegmentDataContainerImpl
|
||||
};
|
||||
}
|
||||
|
||||
using SegmentDataView = detail::SegmentDataContainerImpl<true>;
|
||||
using SegmentDataContainer = detail::SegmentDataContainerImpl<false>;
|
||||
using SegmentDataView = detail::SegmentDataContainerImpl<storage::Ownership::View>;
|
||||
using SegmentDataContainer = detail::SegmentDataContainerImpl<storage::Ownership::Container>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#ifndef OSRM_EXTRACTOR_IO_HPP
|
||||
#define OSRM_EXTRACTOR_IO_HPP
|
||||
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/segment_data_container.hpp"
|
||||
#include "extractor/turn_data_container.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/serialization.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
inline void read(storage::io::FileReader &reader, Datasources &sources)
|
||||
{
|
||||
reader.ReadInto(sources);
|
||||
}
|
||||
|
||||
inline void write(storage::io::FileWriter &writer, Datasources &sources)
|
||||
{
|
||||
writer.WriteFrom(sources);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::SegmentDataContainerImpl<Ownership> &segment_data)
|
||||
{
|
||||
storage::serialization::read(reader, segment_data.index);
|
||||
storage::serialization::read(reader, segment_data.nodes);
|
||||
storage::serialization::read(reader, segment_data.fwd_weights);
|
||||
storage::serialization::read(reader, segment_data.rev_weights);
|
||||
storage::serialization::read(reader, segment_data.fwd_durations);
|
||||
storage::serialization::read(reader, segment_data.rev_durations);
|
||||
storage::serialization::read(reader, segment_data.datasources);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::SegmentDataContainerImpl<Ownership> &segment_data)
|
||||
{
|
||||
storage::serialization::write(writer, segment_data.index);
|
||||
storage::serialization::write(writer, segment_data.nodes);
|
||||
storage::serialization::write(writer, segment_data.fwd_weights);
|
||||
storage::serialization::write(writer, segment_data.rev_weights);
|
||||
storage::serialization::write(writer, segment_data.fwd_durations);
|
||||
storage::serialization::write(writer, segment_data.rev_durations);
|
||||
storage::serialization::write(writer, segment_data.datasources);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::TurnDataContainerImpl<Ownership> &turn_data_container)
|
||||
{
|
||||
storage::serialization::read(reader, turn_data_container.geometry_ids);
|
||||
storage::serialization::read(reader, turn_data_container.name_ids);
|
||||
storage::serialization::read(reader, turn_data_container.turn_instructions);
|
||||
storage::serialization::read(reader, turn_data_container.lane_data_ids);
|
||||
storage::serialization::read(reader, turn_data_container.travel_modes);
|
||||
storage::serialization::read(reader, turn_data_container.entry_class_ids);
|
||||
storage::serialization::read(reader, turn_data_container.pre_turn_bearings);
|
||||
storage::serialization::read(reader, turn_data_container.post_turn_bearings);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::TurnDataContainerImpl<Ownership> &turn_data_container)
|
||||
{
|
||||
storage::serialization::write(writer, turn_data_container.geometry_ids);
|
||||
storage::serialization::write(writer, turn_data_container.name_ids);
|
||||
storage::serialization::write(writer, turn_data_container.turn_instructions);
|
||||
storage::serialization::write(writer, turn_data_container.lane_data_ids);
|
||||
storage::serialization::write(writer, turn_data_container.travel_modes);
|
||||
storage::serialization::write(writer, turn_data_container.entry_class_ids);
|
||||
storage::serialization::write(writer, turn_data_container.pre_turn_bearings);
|
||||
storage::serialization::write(writer, turn_data_container.post_turn_bearings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
#ifndef OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
|
||||
#define OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
|
||||
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/guidance/turn_bearing.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class TurnDataContainerImpl;
|
||||
}
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <storage::Ownership Ownership>
|
||||
void read(storage::io::FileReader &reader, detail::TurnDataContainerImpl<Ownership> &turn_data);
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
void write(storage::io::FileWriter &writer,
|
||||
const detail::TurnDataContainerImpl<Ownership> &turn_data);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class TurnDataContainerImpl
|
||||
{
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
TurnDataContainerImpl() = default;
|
||||
|
||||
TurnDataContainerImpl(Vector<GeometryID> geometry_ids_,
|
||||
Vector<NameID> name_ids_,
|
||||
Vector<extractor::guidance::TurnInstruction> turn_instructions_,
|
||||
Vector<LaneDataID> lane_data_ids_,
|
||||
Vector<extractor::TravelMode> travel_modes_,
|
||||
Vector<EntryClassID> entry_class_ids_,
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings_,
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings_)
|
||||
: geometry_ids(std::move(geometry_ids_)), name_ids(std::move(name_ids_)),
|
||||
turn_instructions(std::move(turn_instructions_)),
|
||||
lane_data_ids(std::move(lane_data_ids_)), travel_modes(std::move(travel_modes_)),
|
||||
entry_class_ids(std::move(entry_class_ids_)),
|
||||
pre_turn_bearings(std::move(pre_turn_bearings_)),
|
||||
post_turn_bearings(std::move(post_turn_bearings_))
|
||||
{
|
||||
}
|
||||
|
||||
GeometryID GetGeometryID(const EdgeID id) const { return geometry_ids[id]; }
|
||||
|
||||
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
|
||||
|
||||
extractor::TravelMode GetTravelMode(const EdgeID id) const { return travel_modes[id]; }
|
||||
|
||||
util::guidance::TurnBearing GetPreTurnBearing(const EdgeID id) const
|
||||
{
|
||||
return pre_turn_bearings[id];
|
||||
}
|
||||
|
||||
util::guidance::TurnBearing GetPostTurnBearing(const EdgeID id) const
|
||||
{
|
||||
return post_turn_bearings[id];
|
||||
}
|
||||
|
||||
LaneDataID GetLaneDataID(const EdgeID id) const { return lane_data_ids[id]; }
|
||||
|
||||
bool HasLaneData(const EdgeID id) const { return INVALID_LANE_DATAID != lane_data_ids[id]; }
|
||||
|
||||
NameID GetNameID(const EdgeID id) const { return name_ids[id]; }
|
||||
|
||||
extractor::guidance::TurnInstruction GetTurnInstruction(const EdgeID id) const
|
||||
{
|
||||
return turn_instructions[id];
|
||||
}
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void push_back(GeometryID geometry_id,
|
||||
NameID name_id,
|
||||
extractor::guidance::TurnInstruction turn_instruction,
|
||||
LaneDataID lane_data_id,
|
||||
EntryClassID entry_class_id,
|
||||
extractor::TravelMode travel_mode,
|
||||
util::guidance::TurnBearing pre_turn_bearing,
|
||||
util::guidance::TurnBearing post_turn_bearing)
|
||||
{
|
||||
geometry_ids.push_back(geometry_id);
|
||||
name_ids.push_back(name_id);
|
||||
turn_instructions.push_back(turn_instruction);
|
||||
lane_data_ids.push_back(lane_data_id);
|
||||
travel_modes.push_back(travel_mode);
|
||||
entry_class_ids.push_back(entry_class_id);
|
||||
pre_turn_bearings.push_back(pre_turn_bearing);
|
||||
post_turn_bearings.push_back(post_turn_bearing);
|
||||
}
|
||||
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
TurnDataContainerImpl &turn_data_container);
|
||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const TurnDataContainerImpl &turn_data_container);
|
||||
|
||||
private:
|
||||
Vector<GeometryID> geometry_ids;
|
||||
Vector<NameID> name_ids;
|
||||
Vector<extractor::guidance::TurnInstruction> turn_instructions;
|
||||
Vector<LaneDataID> lane_data_ids;
|
||||
Vector<extractor::TravelMode> travel_modes;
|
||||
Vector<EntryClassID> entry_class_ids;
|
||||
Vector<util::guidance::TurnBearing> pre_turn_bearings;
|
||||
Vector<util::guidance::TurnBearing> post_turn_bearings;
|
||||
};
|
||||
}
|
||||
|
||||
using TurnDataExternalContainer = detail::TurnDataContainerImpl<storage::Ownership::External>;
|
||||
using TurnDataContainer = detail::TurnDataContainerImpl<storage::Ownership::Container>;
|
||||
using TurnDataView = detail::TurnDataContainerImpl<storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -6,10 +6,11 @@
|
||||
#include "util/assert.hpp"
|
||||
#include "util/for_each_range.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
@@ -26,24 +27,23 @@ namespace partition
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class CellStorageImpl;
|
||||
template <storage::Ownership Ownership> class CellStorageImpl;
|
||||
}
|
||||
using CellStorage = detail::CellStorageImpl<false>;
|
||||
using CellStorageView = detail::CellStorageImpl<true>;
|
||||
using CellStorage = detail::CellStorageImpl<storage::Ownership::Container>;
|
||||
using CellStorageView = detail::CellStorageImpl<storage::Ownership::View>;
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
template <bool UseShareMemory>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::CellStorageImpl<Ownership> &storage);
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class CellStorageImpl
|
||||
template <storage::Ownership Ownership> class CellStorageImpl
|
||||
{
|
||||
public:
|
||||
using WeightOffset = std::uint32_t;
|
||||
@@ -65,7 +65,7 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
// Implementation of the cell view. We need a template parameter here
|
||||
// because we need to derive a read-only and read-write view from this.
|
||||
@@ -185,7 +185,8 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
|
||||
CellStorageImpl() {}
|
||||
|
||||
template <typename GraphT, typename = std::enable_if<!UseShareMemory>>
|
||||
template <typename GraphT,
|
||||
typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
CellStorageImpl(const partition::MultiLevelPartition &partition, const GraphT &base_graph)
|
||||
{
|
||||
// pre-allocate storge for CellData so we can have random access to it by cell id
|
||||
@@ -314,7 +315,7 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
weights.resize(weight_offset + 1, INVALID_EDGE_WEIGHT);
|
||||
}
|
||||
|
||||
template <typename = std::enable_if<UseShareMemory>>
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::View>>
|
||||
CellStorageImpl(Vector<EdgeWeight> weights_,
|
||||
Vector<NodeID> source_boundary_,
|
||||
Vector<NodeID> destination_boundary_,
|
||||
@@ -339,7 +340,8 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
destination_boundary.empty() ? nullptr : destination_boundary.data()};
|
||||
}
|
||||
|
||||
template <typename = std::enable_if<!UseShareMemory>> Cell GetCell(LevelID level, CellID id)
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
Cell GetCell(LevelID level, CellID id)
|
||||
{
|
||||
const auto level_index = LevelIDToIndex(level);
|
||||
BOOST_ASSERT(level_index < level_to_cell_offset.size());
|
||||
@@ -350,10 +352,10 @@ template <bool UseShareMemory> class CellStorageImpl
|
||||
cells[cell_index], weights.data(), source_boundary.data(), destination_boundary.data()};
|
||||
}
|
||||
|
||||
friend void io::read<UseShareMemory>(const boost::filesystem::path &path,
|
||||
detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
friend void io::write<UseShareMemory>(const boost::filesystem::path &path,
|
||||
const detail::CellStorageImpl<UseShareMemory> &storage);
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
detail::CellStorageImpl<Ownership> &storage);
|
||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const detail::CellStorageImpl<Ownership> &storage);
|
||||
|
||||
private:
|
||||
Vector<EdgeWeight> weights;
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#ifndef OSRM_PARTITION_SERILIZATION_HPP
|
||||
#define OSRM_PARTITION_SERILIZATION_HPP
|
||||
|
||||
#include "customizer/edge_based_graph.hpp"
|
||||
|
||||
#include "partition/serialization.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace files
|
||||
{
|
||||
|
||||
// reads .osrm.mldgr file
|
||||
template <typename MultiLevelGraphT>
|
||||
inline void readGraph(const boost::filesystem::path &path, MultiLevelGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
|
||||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, graph);
|
||||
}
|
||||
|
||||
// writes .osrm.mldgr file
|
||||
template <typename MultiLevelGraphT>
|
||||
inline void writeGraph(const boost::filesystem::path &path, const MultiLevelGraphT &graph)
|
||||
{
|
||||
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
|
||||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, graph);
|
||||
}
|
||||
|
||||
// read .osrm.partition file
|
||||
template <typename MultiLevelPartitionT>
|
||||
inline void readPartition(const boost::filesystem::path &path, MultiLevelPartitionT &mlp)
|
||||
{
|
||||
static_assert(std::is_same<MultiLevelPartitionView, MultiLevelPartitionT>::value ||
|
||||
std::is_same<MultiLevelPartition, MultiLevelPartitionT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, mlp);
|
||||
}
|
||||
|
||||
// writes .osrm.partition file
|
||||
template <typename MultiLevelPartitionT>
|
||||
inline void writePartition(const boost::filesystem::path &path, const MultiLevelPartitionT &mlp)
|
||||
{
|
||||
static_assert(std::is_same<MultiLevelPartitionView, MultiLevelPartitionT>::value ||
|
||||
std::is_same<MultiLevelPartition, MultiLevelPartitionT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, mlp);
|
||||
}
|
||||
|
||||
// reads .osrm.cells file
|
||||
template <typename CellStorageT>
|
||||
inline void readCells(const boost::filesystem::path &path, CellStorageT &storage)
|
||||
{
|
||||
static_assert(std::is_same<CellStorageView, CellStorageT>::value ||
|
||||
std::is_same<CellStorage, CellStorageT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
serialization::read(reader, storage);
|
||||
}
|
||||
|
||||
// writes .osrm.cells file
|
||||
template <typename CellStorageT>
|
||||
inline void writeCells(const boost::filesystem::path &path, CellStorageT &storage)
|
||||
{
|
||||
static_assert(std::is_same<CellStorageView, CellStorageT>::value ||
|
||||
std::is_same<CellStorage, CellStorageT>::value,
|
||||
"");
|
||||
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
serialization::write(writer, storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,89 +0,0 @@
|
||||
#ifndef OSRM_PARTITION_IO_HPP
|
||||
#define OSRM_PARTITION_IO_HPP
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/edge_based_graph.hpp"
|
||||
#include "partition/multi_level_graph.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
inline void read(const boost::filesystem::path &path,
|
||||
MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(graph.node_array);
|
||||
reader.DeserializeVector(graph.edge_array);
|
||||
reader.DeserializeVector(graph.edge_to_level);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
inline void write(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.SerializeVector(graph.node_array);
|
||||
writer.SerializeVector(graph.edge_array);
|
||||
writer.SerializeVector(graph.node_to_edge_offset);
|
||||
}
|
||||
|
||||
template <> inline void read(const boost::filesystem::path &path, MultiLevelPartition &mlp)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.ReadInto<MultiLevelPartition::LevelData>(mlp.level_data);
|
||||
reader.DeserializeVector(mlp.partition);
|
||||
reader.DeserializeVector(mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <> inline void write(const boost::filesystem::path &path, const MultiLevelPartition &mlp)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.WriteOne(mlp.level_data);
|
||||
writer.SerializeVector(mlp.partition);
|
||||
writer.SerializeVector(mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <> inline void read(const boost::filesystem::path &path, CellStorage &storage)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
|
||||
storage::io::FileReader reader{path, fingerprint};
|
||||
|
||||
reader.DeserializeVector(storage.weights);
|
||||
reader.DeserializeVector(storage.source_boundary);
|
||||
reader.DeserializeVector(storage.destination_boundary);
|
||||
reader.DeserializeVector(storage.cells);
|
||||
reader.DeserializeVector(storage.level_to_cell_offset);
|
||||
}
|
||||
|
||||
template <> inline void write(const boost::filesystem::path &path, const CellStorage &storage)
|
||||
{
|
||||
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
|
||||
storage::io::FileWriter writer{path, fingerprint};
|
||||
|
||||
writer.SerializeVector(storage.weights);
|
||||
writer.SerializeVector(storage.source_boundary);
|
||||
writer.SerializeVector(storage.destination_boundary);
|
||||
writer.SerializeVector(storage.cells);
|
||||
writer.SerializeVector(storage.level_to_cell_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
@@ -12,26 +16,26 @@
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
namespace partition
|
||||
{
|
||||
template <typename EdgeDataT, bool UseSharedMemory> class MultiLevelGraph;
|
||||
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void read(storage::io::FileReader &reader, MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void write(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void write(storage::io::FileWriter &writer, const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
|
||||
{
|
||||
private:
|
||||
using SuperT = util::StaticGraph<EdgeDataT, UseSharedMemory>;
|
||||
template <typename T> using Vector = typename util::ShM<T, UseSharedMemory>::vector;
|
||||
using SuperT = util::StaticGraph<EdgeDataT, Ownership>;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
// We limit each node to have 255 edges
|
||||
@@ -190,11 +194,11 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
|
||||
}
|
||||
|
||||
friend void
|
||||
io::read<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
|
||||
MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
serialization::read<EdgeDataT, Ownership>(storage::io::FileReader &reader,
|
||||
MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
friend void
|
||||
io::write<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
|
||||
const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
|
||||
serialization::write<EdgeDataT, Ownership>(storage::io::FileWriter &writer,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
Vector<EdgeOffset> node_to_edge_offset;
|
||||
};
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
#include "util/exception.hpp"
|
||||
#include "util/for_each_pair.hpp"
|
||||
#include "util/msb.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -25,31 +26,29 @@ namespace partition
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <bool UseShareMemory> class MultiLevelPartitionImpl;
|
||||
template <storage::Ownership Ownership> class MultiLevelPartitionImpl;
|
||||
}
|
||||
using MultiLevelPartition = detail::MultiLevelPartitionImpl<false>;
|
||||
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<true>;
|
||||
using MultiLevelPartition = detail::MultiLevelPartitionImpl<storage::Ownership::Container>;
|
||||
using MultiLevelPartitionView = detail::MultiLevelPartitionImpl<storage::Ownership::View>;
|
||||
|
||||
namespace io
|
||||
namespace serialization
|
||||
{
|
||||
template <bool UseShareMemory>
|
||||
void read(const boost::filesystem::path &file,
|
||||
detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
|
||||
template <bool UseShareMemory>
|
||||
void write(const boost::filesystem::path &file,
|
||||
const detail::MultiLevelPartitionImpl<UseShareMemory> &mlp);
|
||||
template <storage::Ownership Ownership>
|
||||
void read(storage::io::FileReader &reader, detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
template <storage::Ownership Ownership>
|
||||
void write(storage::io::FileWriter &writer, const detail::MultiLevelPartitionImpl<Ownership> &mlp);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
|
||||
{
|
||||
// we will support at most 16 levels
|
||||
static const constexpr std::uint8_t MAX_NUM_LEVEL = 16;
|
||||
static const constexpr std::uint8_t NUM_PARTITION_BITS = sizeof(PartitionID) * CHAR_BIT;
|
||||
|
||||
template <typename T> using Vector = typename util::ShM<T, UseShareMemory>::vector;
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
// Contains all data necessary to describe the level hierarchy
|
||||
@@ -62,13 +61,16 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
std::array<LevelID, NUM_PARTITION_BITS> bit_to_level;
|
||||
std::array<std::uint32_t, MAX_NUM_LEVEL - 1> lidx_to_children_offsets;
|
||||
};
|
||||
using LevelDataPtr = typename std::conditional<Ownership == storage::Ownership::View,
|
||||
LevelData *,
|
||||
std::unique_ptr<LevelData>>::type;
|
||||
|
||||
MultiLevelPartitionImpl() = default;
|
||||
MultiLevelPartitionImpl();
|
||||
|
||||
// cell_sizes is index by level (starting at 0, the base graph).
|
||||
// However level 0 always needs to have cell size 1, since it is the
|
||||
// basegraph.
|
||||
template <typename = typename std::enable_if<!UseShareMemory>>
|
||||
template <typename = typename std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
MultiLevelPartitionImpl(const std::vector<std::vector<CellID>> &partitions,
|
||||
const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
: level_data(MakeLevelData(lidx_to_num_cells))
|
||||
@@ -76,8 +78,8 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
InitializePartitionIDs(partitions);
|
||||
}
|
||||
|
||||
template <typename = typename std::enable_if<UseShareMemory>>
|
||||
MultiLevelPartitionImpl(LevelData level_data,
|
||||
template <typename = typename std::enable_if<Ownership == storage::Ownership::View>>
|
||||
MultiLevelPartitionImpl(LevelDataPtr level_data,
|
||||
Vector<PartitionID> partition_,
|
||||
Vector<CellID> cell_to_children_)
|
||||
: level_data(std::move(level_data)), partition(std::move(partition_)),
|
||||
@@ -90,8 +92,8 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
{
|
||||
auto p = partition[node];
|
||||
auto lidx = LevelIDToIndex(l);
|
||||
auto masked = p & level_data.lidx_to_mask[lidx];
|
||||
return masked >> level_data.lidx_to_offset[lidx];
|
||||
auto masked = p & level_data->lidx_to_mask[lidx];
|
||||
return masked >> level_data->lidx_to_offset[lidx];
|
||||
}
|
||||
|
||||
LevelID GetQueryLevel(NodeID start, NodeID target, NodeID node) const
|
||||
@@ -106,10 +108,10 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
return 0;
|
||||
|
||||
auto msb = util::msb(partition[first] ^ partition[second]);
|
||||
return level_data.bit_to_level[msb];
|
||||
return level_data->bit_to_level[msb];
|
||||
}
|
||||
|
||||
std::uint8_t GetNumberOfLevels() const { return level_data.num_level; }
|
||||
std::uint8_t GetNumberOfLevels() const { return level_data->num_level; }
|
||||
|
||||
std::uint32_t GetNumberOfCells(LevelID level) const
|
||||
{
|
||||
@@ -121,7 +123,7 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
{
|
||||
BOOST_ASSERT(level > 1);
|
||||
auto lidx = LevelIDToIndex(level);
|
||||
auto offset = level_data.lidx_to_children_offsets[lidx];
|
||||
auto offset = level_data->lidx_to_children_offsets[lidx];
|
||||
return cell_to_children[offset + cell];
|
||||
}
|
||||
|
||||
@@ -130,14 +132,14 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
{
|
||||
BOOST_ASSERT(level > 1);
|
||||
auto lidx = LevelIDToIndex(level);
|
||||
auto offset = level_data.lidx_to_children_offsets[lidx];
|
||||
auto offset = level_data->lidx_to_children_offsets[lidx];
|
||||
return cell_to_children[offset + cell + 1];
|
||||
}
|
||||
|
||||
friend void io::read<UseShareMemory>(const boost::filesystem::path &file,
|
||||
MultiLevelPartitionImpl &mlp);
|
||||
friend void io::write<UseShareMemory>(const boost::filesystem::path &file,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
MultiLevelPartitionImpl &mlp);
|
||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
||||
const MultiLevelPartitionImpl &mlp);
|
||||
|
||||
private:
|
||||
auto MakeLevelData(const std::vector<std::uint32_t> &lidx_to_num_cells)
|
||||
@@ -146,7 +148,7 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
auto offsets = MakeLevelOffsets(lidx_to_num_cells);
|
||||
auto masks = MakeLevelMasks(offsets, num_level);
|
||||
auto bits = MakeBitToLevel(offsets, num_level);
|
||||
return LevelData{num_level, offsets, masks, bits, {0}};
|
||||
return std::make_unique<LevelData>(LevelData{num_level, offsets, masks, bits, {0}});
|
||||
}
|
||||
|
||||
inline std::size_t LevelIDToIndex(LevelID l) const { return l - 1; }
|
||||
@@ -160,8 +162,8 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
{
|
||||
auto lidx = LevelIDToIndex(l);
|
||||
|
||||
auto shifted_id = cell_id << level_data.lidx_to_offset[lidx];
|
||||
auto cleared_cell = partition[node] & ~level_data.lidx_to_mask[lidx];
|
||||
auto shifted_id = cell_id << level_data->lidx_to_offset[lidx];
|
||||
auto cleared_cell = partition[node] & ~level_data->lidx_to_mask[lidx];
|
||||
partition[node] = cleared_cell | shifted_id;
|
||||
}
|
||||
|
||||
@@ -289,13 +291,13 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
level--;
|
||||
}
|
||||
|
||||
level_data.lidx_to_children_offsets[0] = 0;
|
||||
level_data->lidx_to_children_offsets[0] = 0;
|
||||
|
||||
for (auto level_idx = 0UL; level_idx < partitions.size() - 1; ++level_idx)
|
||||
{
|
||||
const auto &parent_partition = partitions[level_idx + 1];
|
||||
|
||||
level_data.lidx_to_children_offsets[level_idx + 1] = cell_to_children.size();
|
||||
level_data->lidx_to_children_offsets[level_idx + 1] = cell_to_children.size();
|
||||
|
||||
CellID last_parent_id = parent_partition[permutation.front()];
|
||||
cell_to_children.push_back(GetCell(level_idx + 1, permutation.front()));
|
||||
@@ -314,11 +316,22 @@ template <bool UseShareMemory> class MultiLevelPartitionImpl final
|
||||
}
|
||||
}
|
||||
|
||||
//! this is always owned by this class because it is so small
|
||||
LevelData level_data;
|
||||
LevelDataPtr level_data = {};
|
||||
Vector<PartitionID> partition;
|
||||
Vector<CellID> cell_to_children;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline MultiLevelPartitionImpl<storage::Ownership::Container>::MultiLevelPartitionImpl()
|
||||
: level_data(std::make_unique<LevelData>())
|
||||
{
|
||||
}
|
||||
|
||||
template <>
|
||||
inline MultiLevelPartitionImpl<storage::Ownership::View>::MultiLevelPartitionImpl()
|
||||
: level_data(nullptr)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef OSRM_PARTITION_SERIALIZATION_HPP
|
||||
#define OSRM_PARTITION_SERIALIZATION_HPP
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/edge_based_graph.hpp"
|
||||
#include "partition/multi_level_graph.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/serialization.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
storage::serialization::read(reader, graph.node_array);
|
||||
storage::serialization::read(reader, graph.edge_array);
|
||||
storage::serialization::read(reader, graph.node_to_edge_offset);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
storage::serialization::write(writer, graph.node_array);
|
||||
storage::serialization::write(writer, graph.edge_array);
|
||||
storage::serialization::write(writer, graph.node_to_edge_offset);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::MultiLevelPartitionImpl<Ownership> &mlp)
|
||||
{
|
||||
reader.ReadInto(*mlp.level_data);
|
||||
storage::serialization::read(reader, mlp.partition);
|
||||
storage::serialization::read(reader, mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::MultiLevelPartitionImpl<Ownership> &mlp)
|
||||
{
|
||||
writer.WriteOne(*mlp.level_data);
|
||||
storage::serialization::write(writer, mlp.partition);
|
||||
storage::serialization::write(writer, mlp.cell_to_children);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::CellStorageImpl<Ownership> &storage)
|
||||
{
|
||||
storage::serialization::read(reader, storage.weights);
|
||||
storage::serialization::read(reader, storage.source_boundary);
|
||||
storage::serialization::read(reader, storage.destination_boundary);
|
||||
storage::serialization::read(reader, storage.cells);
|
||||
storage::serialization::read(reader, storage.level_to_cell_offset);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::CellStorageImpl<Ownership> &storage)
|
||||
{
|
||||
storage::serialization::write(writer, storage.weights);
|
||||
storage::serialization::write(writer, storage.source_boundary);
|
||||
storage::serialization::write(writer, storage.destination_boundary);
|
||||
storage::serialization::write(writer, storage.cells);
|
||||
storage::serialization::write(writer, storage.level_to_cell_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -128,20 +128,6 @@ class FileReader
|
||||
std::uint32_t ReadElementCount32() { return ReadOne<std::uint32_t>(); }
|
||||
std::uint64_t ReadElementCount64() { return ReadOne<std::uint64_t>(); }
|
||||
|
||||
template <typename T> void DeserializeVector(std::vector<T> &data)
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
data.resize(count);
|
||||
ReadInto(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> std::size_t GetVectorMemorySize()
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
Skip<T>(count);
|
||||
return sizeof(count) + sizeof(T) * count;
|
||||
}
|
||||
|
||||
template <typename T> std::size_t ReadVectorSize()
|
||||
{
|
||||
const auto count = ReadElementCount64();
|
||||
@@ -149,19 +135,6 @@ class FileReader
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename T> void *DeserializeVector(void *begin, const void *end)
|
||||
{
|
||||
auto count = ReadElementCount64();
|
||||
auto required = reinterpret_cast<char *>(begin) + sizeof(count) + sizeof(T) * count;
|
||||
if (required > end)
|
||||
throw util::exception("Not enough memory ");
|
||||
|
||||
*reinterpret_cast<decltype(count) *>(begin) = count;
|
||||
ReadInto(reinterpret_cast<T *>(reinterpret_cast<char *>(begin) + sizeof(decltype(count))),
|
||||
count);
|
||||
return required;
|
||||
}
|
||||
|
||||
bool ReadAndCheckFingerprint()
|
||||
{
|
||||
auto loaded_fingerprint = ReadOne<util::FingerPrint>();
|
||||
@@ -199,42 +172,6 @@ class FileReader
|
||||
input_stream.seekg(current_pos, input_stream.beg);
|
||||
return length;
|
||||
}
|
||||
|
||||
std::vector<std::string> ReadLines()
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::string thisline;
|
||||
try
|
||||
{
|
||||
while (std::getline(input_stream, thisline))
|
||||
{
|
||||
result.push_back(thisline);
|
||||
}
|
||||
}
|
||||
catch (const std::ios_base::failure &)
|
||||
{
|
||||
// EOF is OK here, everything else, re-throw
|
||||
if (!input_stream.eof())
|
||||
throw;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ReadLine()
|
||||
{
|
||||
std::string thisline;
|
||||
try
|
||||
{
|
||||
std::getline(input_stream, thisline);
|
||||
}
|
||||
catch (const std::ios_base::failure & /*e*/)
|
||||
{
|
||||
// EOF is OK here, everything else, re-throw
|
||||
if (!input_stream.eof())
|
||||
throw;
|
||||
}
|
||||
return thisline;
|
||||
}
|
||||
};
|
||||
|
||||
class FileWriter
|
||||
@@ -296,13 +233,6 @@ class FileWriter
|
||||
void WriteElementCount32(const std::uint32_t count) { WriteOne<std::uint32_t>(count); }
|
||||
void WriteElementCount64(const std::uint64_t count) { WriteOne<std::uint64_t>(count); }
|
||||
|
||||
template <typename T> void SerializeVector(const std::vector<T> &data)
|
||||
{
|
||||
const auto count = data.size();
|
||||
WriteElementCount64(count);
|
||||
return WriteFrom(data.data(), count);
|
||||
}
|
||||
|
||||
void WriteFingerprint()
|
||||
{
|
||||
const auto fingerprint = util::FingerPrint::GetValid();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef OSRM_STORAGE_IO_FWD_HPP_
|
||||
#define OSRM_STORAGE_IO_FWD_HPP_
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace storage
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class FileReader;
|
||||
class FileWriter;
|
||||
|
||||
} // ns io
|
||||
} // ns storage
|
||||
} // ns osrm
|
||||
|
||||
#endif
|
||||
@@ -1,23 +1,12 @@
|
||||
#ifndef OSRM_STORAGE_SERIALIZATION_HPP_
|
||||
#define OSRM_STORAGE_SERIALIZATION_HPP_
|
||||
#ifndef OSRM_STORAGE_SERIALIZATION_HPP
|
||||
#define OSRM_STORAGE_SERIALIZATION_HPP
|
||||
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "contractor/query_edge.hpp"
|
||||
#include "extractor/extractor.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "storage/io.hpp"
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/iostreams/seek.hpp>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -25,105 +14,54 @@ namespace storage
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
// To make function calls consistent, this function returns the fixed number of properties
|
||||
inline std::size_t readPropertiesCount() { return 1; }
|
||||
|
||||
struct HSGRHeader
|
||||
template <typename T> inline void read(storage::io::FileReader &reader, stxxl::vector<T> &vec)
|
||||
{
|
||||
std::uint32_t checksum;
|
||||
std::uint64_t number_of_nodes;
|
||||
std::uint64_t number_of_edges;
|
||||
};
|
||||
|
||||
// Reads the checksum, number of nodes and number of edges written in the header file of a `.hsgr`
|
||||
// file and returns them in a HSGRHeader struct
|
||||
inline HSGRHeader readHSGRHeader(io::FileReader &input_file)
|
||||
{
|
||||
|
||||
HSGRHeader header;
|
||||
input_file.ReadInto(header.checksum);
|
||||
input_file.ReadInto(header.number_of_nodes);
|
||||
input_file.ReadInto(header.number_of_edges);
|
||||
|
||||
// If we have edges, then we must have nodes.
|
||||
// However, there can be nodes with no edges (some test cases create this)
|
||||
BOOST_ASSERT_MSG(header.number_of_edges == 0 || header.number_of_nodes > 0,
|
||||
"edges exist, but there are no nodes");
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
// Reads the graph data of a `.hsgr` file into memory
|
||||
// Needs to be called after readHSGRHeader() to get the correct offset in the stream
|
||||
using NodeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::NodeArrayEntry;
|
||||
using EdgeT = typename util::StaticGraph<contractor::QueryEdge::EdgeData>::EdgeArrayEntry;
|
||||
inline void readHSGR(io::FileReader &input_file,
|
||||
NodeT *node_buffer,
|
||||
const std::uint64_t number_of_nodes,
|
||||
EdgeT *edge_buffer,
|
||||
const std::uint64_t number_of_edges)
|
||||
{
|
||||
BOOST_ASSERT(node_buffer);
|
||||
BOOST_ASSERT(edge_buffer);
|
||||
input_file.ReadInto(node_buffer, number_of_nodes);
|
||||
input_file.ReadInto(edge_buffer, number_of_edges);
|
||||
}
|
||||
|
||||
// Loads edge data from .edge files into memory which includes its
|
||||
// geometry, name ID, turn instruction, lane data ID, travel mode, entry class ID
|
||||
// Needs to be called after readElementCount() to get the correct offset in the stream
|
||||
inline void readEdges(io::FileReader &edges_input_file,
|
||||
GeometryID *geometry_list,
|
||||
NameID *name_id_list,
|
||||
extractor::guidance::TurnInstruction *turn_instruction_list,
|
||||
LaneDataID *lane_data_id_list,
|
||||
extractor::TravelMode *travel_mode_list,
|
||||
EntryClassID *entry_class_id_list,
|
||||
util::guidance::TurnBearing *pre_turn_bearing_list,
|
||||
util::guidance::TurnBearing *post_turn_bearing_list,
|
||||
const std::uint64_t number_of_edges)
|
||||
{
|
||||
BOOST_ASSERT(geometry_list);
|
||||
BOOST_ASSERT(name_id_list);
|
||||
BOOST_ASSERT(turn_instruction_list);
|
||||
BOOST_ASSERT(lane_data_id_list);
|
||||
BOOST_ASSERT(travel_mode_list);
|
||||
BOOST_ASSERT(entry_class_id_list);
|
||||
extractor::OriginalEdgeData current_edge_data;
|
||||
for (std::uint64_t i = 0; i < number_of_edges; ++i)
|
||||
auto size = reader.ReadOne<std::uint64_t>();
|
||||
vec.reserve(size);
|
||||
for (auto idx : util::irange<std::size_t>(0, size))
|
||||
{
|
||||
edges_input_file.ReadInto(current_edge_data);
|
||||
|
||||
geometry_list[i] = current_edge_data.via_geometry;
|
||||
name_id_list[i] = current_edge_data.name_id;
|
||||
turn_instruction_list[i] = current_edge_data.turn_instruction;
|
||||
lane_data_id_list[i] = current_edge_data.lane_data_id;
|
||||
travel_mode_list[i] = current_edge_data.travel_mode;
|
||||
entry_class_id_list[i] = current_edge_data.entry_classid;
|
||||
pre_turn_bearing_list[i] = current_edge_data.pre_turn_bearing;
|
||||
post_turn_bearing_list[i] = current_edge_data.post_turn_bearing;
|
||||
(void)idx;
|
||||
vec.push_back(reader.ReadOne<T>());
|
||||
}
|
||||
}
|
||||
|
||||
// Loads coordinates and OSM node IDs from .nodes files into memory
|
||||
// Needs to be called after readElementCount() to get the correct offset in the stream
|
||||
template <typename OSMNodeIDVectorT>
|
||||
void readNodes(io::FileReader &nodes_file,
|
||||
util::Coordinate *coordinate_list,
|
||||
OSMNodeIDVectorT &osmnodeid_list,
|
||||
const std::uint64_t number_of_coordinates)
|
||||
template <typename T>
|
||||
inline void write(storage::io::FileWriter &writer, const stxxl::vector<T> &vec)
|
||||
{
|
||||
BOOST_ASSERT(coordinate_list);
|
||||
extractor::QueryNode current_node;
|
||||
for (std::uint64_t i = 0; i < number_of_coordinates; ++i)
|
||||
writer.WriteOne(vec.size());
|
||||
for (auto idx : util::irange<std::size_t>(0, vec.size()))
|
||||
{
|
||||
nodes_file.ReadInto(current_node);
|
||||
coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat);
|
||||
osmnodeid_list.push_back(current_node.node_id);
|
||||
BOOST_ASSERT(coordinate_list[i].IsValid());
|
||||
writer.WriteOne<T>(vec[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void read(io::FileReader &reader, std::vector<T> &data)
|
||||
{
|
||||
const auto count = reader.ReadElementCount64();
|
||||
data.resize(count);
|
||||
reader.ReadInto(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void write(io::FileWriter &writer, const std::vector<T> &data)
|
||||
{
|
||||
const auto count = data.size();
|
||||
writer.WriteElementCount64(count);
|
||||
return writer.WriteFrom(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void read(io::FileReader &reader, util::vector_view<T> &data)
|
||||
{
|
||||
const auto count = reader.ReadElementCount64();
|
||||
BOOST_ASSERT(data.size() == count);
|
||||
reader.ReadInto(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void write(io::FileWriter &writer, const util::vector_view<T> &data)
|
||||
{
|
||||
const auto count = data.size();
|
||||
writer.WriteElementCount64(count);
|
||||
return writer.WriteFrom(data.data(), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace storage
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef SHARED_MEMORY_OWNERSHIP_HPP
|
||||
#define SHARED_MEMORY_OWNERSHIP_HPP
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace storage
|
||||
{
|
||||
|
||||
enum class Ownership
|
||||
{
|
||||
Container,
|
||||
View,
|
||||
External
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHARED_MEMORY_OWNERSHIP_HPP
|
||||
@@ -49,9 +49,9 @@ struct Segment final
|
||||
|
||||
struct SpeedSource final
|
||||
{
|
||||
SpeedSource() : speed(0), weight(std::numeric_limits<double>::quiet_NaN()) {}
|
||||
SpeedSource() : speed(0), rate(std::numeric_limits<double>::quiet_NaN()) {}
|
||||
unsigned speed;
|
||||
double weight;
|
||||
double rate;
|
||||
std::uint8_t source;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,48 @@ namespace osrm
|
||||
namespace util
|
||||
{
|
||||
|
||||
template <typename NodeID, typename Key> class GenerationArrayStorage
|
||||
{
|
||||
using GenerationCounter = std::uint16_t;
|
||||
|
||||
public:
|
||||
explicit GenerationArrayStorage(std::size_t size)
|
||||
: positions(size, 0), generation(1), generations(size, 0)
|
||||
{
|
||||
}
|
||||
|
||||
Key &operator[](NodeID node)
|
||||
{
|
||||
generation[node] = generation;
|
||||
return positions[node];
|
||||
}
|
||||
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
if (generations[node] < generation)
|
||||
{
|
||||
return std::numeric_limits<Key>::max();
|
||||
}
|
||||
return positions[node];
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
generation++;
|
||||
// if generation overflows we end up at 0 again and need to clear the vector
|
||||
if (generation == 0)
|
||||
{
|
||||
generation = 1;
|
||||
std::fill(generations.begin(), generations.end(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GenerationCounter generation;
|
||||
std::vector<GenerationCounter> generations;
|
||||
std::vector<Key> positions;
|
||||
};
|
||||
|
||||
template <typename NodeID, typename Key> class ArrayStorage
|
||||
{
|
||||
public:
|
||||
@@ -92,10 +134,6 @@ template <typename NodeID,
|
||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||
class BinaryHeap
|
||||
{
|
||||
private:
|
||||
BinaryHeap(const BinaryHeap &right);
|
||||
void operator=(const BinaryHeap &right);
|
||||
|
||||
public:
|
||||
using WeightType = Weight;
|
||||
using DataType = Data;
|
||||
|
||||
@@ -239,6 +239,13 @@ class DeallocatingVector
|
||||
bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||
}
|
||||
|
||||
// copying is not safe since this would only do a shallow copy
|
||||
DeallocatingVector(DeallocatingVector &other) = delete;
|
||||
DeallocatingVector &operator=(DeallocatingVector &other) = delete;
|
||||
// moving is fine
|
||||
DeallocatingVector(DeallocatingVector &&other) = default;
|
||||
DeallocatingVector &operator=(DeallocatingVector &&other) = default;
|
||||
|
||||
~DeallocatingVector() { clear(); }
|
||||
|
||||
friend void swap<>(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &lhs,
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -19,6 +21,16 @@ namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
template <typename EdgeDataT> class DynamicGraph;
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void read(storage::io::FileReader &reader, DynamicGraph<EdgeDataT> &graph);
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory>
|
||||
void write(storage::io::FileWriter &writer, const DynamicGraph<EdgeDataT> &graph);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT> class DynamicGraph
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "util/exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -57,21 +58,23 @@ template <typename BarrierOutIter, typename TrafficSignalsOutIter>
|
||||
NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
|
||||
BarrierOutIter barriers,
|
||||
TrafficSignalsOutIter traffic_signals,
|
||||
std::vector<extractor::QueryNode> &node_array)
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
util::PackedVector<OSMNodeID> &osm_node_ids)
|
||||
{
|
||||
NodeID number_of_nodes = file_reader.ReadElementCount32();
|
||||
Log() << "Importing number_of_nodes new = " << number_of_nodes << " nodes ";
|
||||
|
||||
node_array.resize(number_of_nodes);
|
||||
coordinates.resize(number_of_nodes);
|
||||
osm_node_ids.reserve(number_of_nodes);
|
||||
|
||||
extractor::ExternalMemoryNode current_node;
|
||||
for (NodeID i = 0; i < number_of_nodes; ++i)
|
||||
{
|
||||
file_reader.ReadInto(¤t_node, 1);
|
||||
|
||||
node_array[i].lon = current_node.lon;
|
||||
node_array[i].lat = current_node.lat;
|
||||
node_array[i].node_id = current_node.node_id;
|
||||
coordinates[i].lon = current_node.lon;
|
||||
coordinates[i].lat = current_node.lat;
|
||||
osm_node_ids.push_back(current_node.node_id);
|
||||
|
||||
if (current_node.barrier)
|
||||
{
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#ifndef OSRM_INCLUDE_UTIL_IO_HPP_
|
||||
#define OSRM_INCLUDE_UTIL_IO_HPP_
|
||||
|
||||
#include "util/log.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include <bitset>
|
||||
#include <fstream>
|
||||
#include <stxxl/vector>
|
||||
#include <vector>
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
template <typename simple_type>
|
||||
void deserializeAdjacencyArray(const std::string &filename,
|
||||
std::vector<std::uint32_t> &offsets,
|
||||
std::vector<simple_type> &data)
|
||||
{
|
||||
storage::io::FileReader file(filename, storage::io::FileReader::HasNoFingerprint);
|
||||
|
||||
file.DeserializeVector(offsets);
|
||||
file.DeserializeVector(data);
|
||||
|
||||
// offsets have to match up with the size of the data
|
||||
if (offsets.empty() || (offsets.back() != boost::numeric_cast<std::uint32_t>(data.size())))
|
||||
throw util::exception(
|
||||
"Error in " + filename +
|
||||
(offsets.empty() ? "Offsets are empty" : "Offset and data size do not match") +
|
||||
SOURCE_REF);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_INCLUDE_UTIL_IO_HPP_
|
||||
@@ -2,7 +2,6 @@
|
||||
#define OSRM_UTIL_NAME_TABLE_HPP
|
||||
|
||||
#include "util/indexed_data.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/string_view.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#ifndef PACKED_VECTOR_HPP
|
||||
#define PACKED_VECTOR_HPP
|
||||
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
@@ -11,7 +14,22 @@ namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership> class PackedVector;
|
||||
}
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Ownership> &vec);
|
||||
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const detail::PackedVector<T, Ownership> &vec);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* Since OSM node IDs are (at the time of writing) not quite yet overflowing 32 bits, and
|
||||
* will predictably be containable within 33 bits for a long time, the following packs
|
||||
@@ -20,13 +38,15 @@ namespace util
|
||||
* NOTE: this type is templated for future use, but will require a slight refactor to
|
||||
* configure BITSIZE and ELEMSIZE
|
||||
*/
|
||||
template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
template <typename T, storage::Ownership Ownership> class PackedVector
|
||||
{
|
||||
static const constexpr std::size_t BITSIZE = 33;
|
||||
static const constexpr std::size_t ELEMSIZE = 64;
|
||||
static const constexpr std::size_t PACKSIZE = BITSIZE * ELEMSIZE;
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
/**
|
||||
* Returns the size of the packed vector datastructure with `elements` packed elements (the size
|
||||
* of
|
||||
@@ -77,7 +97,9 @@ template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
num_elements++;
|
||||
}
|
||||
|
||||
T at(const std::size_t &a_index) const
|
||||
T operator[](const std::size_t index) const { return at(index); }
|
||||
|
||||
T at(const std::size_t a_index) const
|
||||
{
|
||||
BOOST_ASSERT(a_index < num_elements);
|
||||
|
||||
@@ -120,20 +142,20 @@ template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
|
||||
std::size_t size() const { return num_elements; }
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void reserve(typename std::enable_if<!enabled, std::size_t>::type capacity)
|
||||
{
|
||||
vec.reserve(elements_to_blocks(capacity));
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void reset(typename std::enable_if<enabled, std::uint64_t>::type *ptr,
|
||||
typename std::enable_if<enabled, std::size_t>::type size)
|
||||
{
|
||||
vec.reset(ptr, size);
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void set_number_of_entries(typename std::enable_if<enabled, std::size_t>::type count)
|
||||
{
|
||||
num_elements = count;
|
||||
@@ -144,51 +166,61 @@ template <typename T, bool UseSharedMemory = false> class PackedVector
|
||||
return std::floor(static_cast<double>(vec.capacity()) * ELEMSIZE / BITSIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
typename util::ShM<std::uint64_t, UseSharedMemory>::vector vec;
|
||||
friend void serialization::read<T, Ownership>(storage::io::FileReader &reader,
|
||||
detail::PackedVector<T, Ownership> &vec);
|
||||
|
||||
std::size_t num_elements = 0;
|
||||
friend void serialization::write<T, Ownership>(storage::io::FileWriter &writer,
|
||||
const detail::PackedVector<T, Ownership> &vec);
|
||||
|
||||
private:
|
||||
util::ViewOrVector<std::uint64_t, Ownership> vec;
|
||||
|
||||
std::uint64_t num_elements = 0;
|
||||
|
||||
signed cursor = -1;
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void replace_last_elem(typename std::enable_if<enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec[cursor] = last_elem;
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void replace_last_elem(typename std::enable_if<!enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec.back() = last_elem;
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void add_last_elem(typename std::enable_if<enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec[cursor + 1] = last_elem;
|
||||
cursor++;
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
void add_last_elem(typename std::enable_if<!enabled, std::uint64_t>::type last_elem)
|
||||
{
|
||||
vec.push_back(last_elem);
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
std::uint64_t vec_back(typename std::enable_if<enabled>::type * = nullptr)
|
||||
{
|
||||
return vec[cursor];
|
||||
}
|
||||
|
||||
template <bool enabled = UseSharedMemory>
|
||||
template <bool enabled = (Ownership == storage::Ownership::View)>
|
||||
std::uint64_t vec_back(typename std::enable_if<!enabled>::type * = nullptr)
|
||||
{
|
||||
return vec.back();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T> using PackedVector = detail::PackedVector<T, storage::Ownership::Container>;
|
||||
template <typename T> using PackedVectorView = detail::PackedVector<T, storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PACKED_VECTOR_HPP */
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
#define RANGE_TABLE_HPP
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
@@ -18,13 +19,14 @@ namespace util
|
||||
* and otherwise the compiler gets confused.
|
||||
*/
|
||||
|
||||
template <unsigned BLOCK_SIZE = 16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||
template <unsigned BLOCK_SIZE = 16, storage::Ownership Ownership = storage::Ownership::Container>
|
||||
class RangeTable;
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, Ownership> &table);
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, Ownership> &table);
|
||||
|
||||
/**
|
||||
* Stores adjacent ranges in a compressed format.
|
||||
@@ -35,12 +37,12 @@ std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEM
|
||||
* But each block consists of an absolute value and BLOCK_SIZE differential values.
|
||||
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
|
||||
*/
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership> class RangeTable
|
||||
{
|
||||
public:
|
||||
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
||||
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
||||
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
||||
using BlockContainerT = util::ViewOrVector<BlockT, Ownership>;
|
||||
using OffsetContainerT = util::ViewOrVector<unsigned, Ownership>;
|
||||
using RangeT = range<unsigned>;
|
||||
|
||||
friend std::ostream &operator<<<>(std::ostream &out, const RangeTable &table);
|
||||
@@ -139,7 +141,7 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
sum_lengths = lengths_prefix_sum;
|
||||
}
|
||||
|
||||
void Write(osrm::storage::io::FileWriter &filewriter)
|
||||
void Write(storage::io::FileWriter &filewriter)
|
||||
{
|
||||
unsigned number_of_blocks = diff_blocks.size();
|
||||
|
||||
@@ -151,7 +153,7 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
filewriter.WriteFrom(diff_blocks.data(), number_of_blocks);
|
||||
}
|
||||
|
||||
void Read(osrm::storage::io::FileReader &filereader)
|
||||
void Read(storage::io::FileReader &filereader)
|
||||
{
|
||||
unsigned number_of_blocks = filereader.ReadElementCount32();
|
||||
// read total length
|
||||
@@ -212,9 +214,8 @@ template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY> class RangeTable
|
||||
unsigned sum_lengths;
|
||||
};
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
const BlockT &block) const
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
unsigned RangeTable<BLOCK_SIZE, Ownership>::PrefixSumAtIndex(int index, const BlockT &block) const
|
||||
{
|
||||
// this loop looks inefficent, but a modern compiler
|
||||
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
|
||||
@@ -227,8 +228,8 @@ unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index,
|
||||
return sum;
|
||||
}
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, Ownership> &table)
|
||||
{
|
||||
// write number of block
|
||||
const unsigned number_of_blocks = table.diff_blocks.size();
|
||||
@@ -243,8 +244,8 @@ std::ostream &operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHA
|
||||
return out;
|
||||
}
|
||||
|
||||
template <unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||
template <unsigned BLOCK_SIZE, storage::Ownership Ownership>
|
||||
std::istream &operator>>(std::istream &in, RangeTable<BLOCK_SIZE, Ownership> &table)
|
||||
{
|
||||
// read number of block
|
||||
unsigned number_of_blocks;
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef OSMR_UTIL_SERIALIZATION_HPP
|
||||
#define OSMR_UTIL_SERIALIZATION_HPP
|
||||
|
||||
#include "util/dynamic_graph.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "storage/serialization.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, detail::PackedVector<T, Ownership> &vec)
|
||||
{
|
||||
vec.num_elements = reader.ReadOne<std::uint64_t>();
|
||||
storage::serialization::read(reader, vec.vec);
|
||||
}
|
||||
|
||||
template <typename T, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const detail::PackedVector<T, Ownership> &vec)
|
||||
{
|
||||
writer.WriteOne(vec.num_elements);
|
||||
storage::serialization::write(writer, vec.vec);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader, StaticGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
storage::serialization::read(reader, graph.node_array);
|
||||
storage::serialization::read(reader, graph.edge_array);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer, const StaticGraph<EdgeDataT, Ownership> &graph)
|
||||
{
|
||||
storage::serialization::write(writer, graph.node_array);
|
||||
storage::serialization::write(writer, graph.edge_array);
|
||||
}
|
||||
|
||||
template <typename EdgeDataT>
|
||||
inline void read(storage::io::FileReader &reader, DynamicGraph<EdgeDataT> &graph)
|
||||
{
|
||||
storage::serialization::read(reader, graph.node_array);
|
||||
auto num_edges = reader.ReadElementCount64();
|
||||
graph.edge_list.resize(num_edges);
|
||||
for (auto index : irange<std::size_t>(0, num_edges))
|
||||
{
|
||||
reader.ReadOne(graph.edge_list[index]);
|
||||
}
|
||||
graph.number_of_nodes = graph.node_array.size();
|
||||
graph.number_of_edges = num_edges;
|
||||
}
|
||||
|
||||
template <typename EdgeDataT>
|
||||
inline void write(storage::io::FileWriter &writer, const DynamicGraph<EdgeDataT> &graph)
|
||||
{
|
||||
storage::serialization::write(writer, graph.node_array);
|
||||
writer.WriteElementCount64(graph.number_of_edges);
|
||||
for (auto index : irange<std::size_t>(0, graph.number_of_edges))
|
||||
{
|
||||
writer.WriteOne(graph.edge_list[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -4,8 +4,11 @@
|
||||
#include "util/graph_traits.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/percent.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
@@ -19,6 +22,16 @@ namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
template <typename EdgeDataT, storage::Ownership Ownership> class StaticGraph;
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void read(storage::io::FileReader &reader, StaticGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
template <typename EdgeDataT, storage::Ownership Ownership>
|
||||
void write(storage::io::FileWriter &writer, const StaticGraph<EdgeDataT, Ownership> &graph);
|
||||
}
|
||||
|
||||
namespace static_graph_details
|
||||
{
|
||||
@@ -97,8 +110,11 @@ EntryT edgeToEntry(const OtherEdge &from, std::false_type)
|
||||
|
||||
} // namespace static_graph_details
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
template <typename EdgeDataT, storage::Ownership Ownership = storage::Ownership::Container>
|
||||
class StaticGraph
|
||||
{
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
using InputEdge = static_graph_details::SortableEdgeWithData<EdgeDataT>;
|
||||
using NodeIterator = static_graph_details::NodeIterator;
|
||||
@@ -114,7 +130,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
|
||||
StaticGraph() {}
|
||||
|
||||
template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &edges)
|
||||
template <typename ContainerT> StaticGraph(const std::uint32_t nodes, const ContainerT &edges)
|
||||
{
|
||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(edges).begin(),
|
||||
const_cast<ContainerT &>(edges).end()));
|
||||
@@ -122,8 +138,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
InitializeFromSortedEdgeRange(nodes, edges.begin(), edges.end());
|
||||
}
|
||||
|
||||
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array_,
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array_)
|
||||
StaticGraph(Vector<NodeArrayEntry> node_array_, Vector<EdgeArrayEntry> edge_array_)
|
||||
: node_array(std::move(node_array_)), edge_array(std::move(edge_array_))
|
||||
{
|
||||
BOOST_ASSERT(!node_array.empty());
|
||||
@@ -226,11 +241,15 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
return current_iterator;
|
||||
}
|
||||
|
||||
const NodeArrayEntry &GetNode(const NodeID nid) const { return node_array[nid]; }
|
||||
const EdgeArrayEntry &GetEdge(const EdgeID eid) const { return edge_array[eid]; }
|
||||
friend void serialization::read<EdgeDataT, Ownership>(storage::io::FileReader &reader,
|
||||
StaticGraph<EdgeDataT, Ownership> &graph);
|
||||
friend void
|
||||
serialization::write<EdgeDataT, Ownership>(storage::io::FileWriter &writer,
|
||||
const StaticGraph<EdgeDataT, Ownership> &graph);
|
||||
|
||||
protected:
|
||||
template <typename IterT>
|
||||
void InitializeFromSortedEdgeRange(const unsigned nodes, IterT begin, IterT end)
|
||||
void InitializeFromSortedEdgeRange(const std::uint32_t nodes, IterT begin, IterT end)
|
||||
{
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = static_cast<EdgeIterator>(std::distance(begin, end));
|
||||
@@ -244,7 +263,9 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
unsigned offset = std::distance(begin, iter);
|
||||
node_array.push_back(NodeArrayEntry{offset});
|
||||
}
|
||||
BOOST_ASSERT(iter == end);
|
||||
BOOST_ASSERT_MSG(
|
||||
iter == end,
|
||||
("Still " + std::to_string(std::distance(iter, end)) + " edges left.").c_str());
|
||||
BOOST_ASSERT(node_array.size() == number_of_nodes + 1);
|
||||
|
||||
edge_array.resize(number_of_edges);
|
||||
@@ -258,8 +279,8 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
NodeIterator number_of_nodes;
|
||||
EdgeIterator number_of_edges;
|
||||
|
||||
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||
Vector<NodeArrayEntry> node_array;
|
||||
Vector<EdgeArrayEntry> edge_array;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
#include "util/hilbert_value.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/rectangle.hpp"
|
||||
#include "util/shared_memory_vector_wrapper.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include "util/vector_view.hpp"
|
||||
#include "util/web_mercator.hpp"
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
@@ -51,16 +53,17 @@ namespace util
|
||||
// All coordinates are pojected first to Web Mercator before the bounding boxes
|
||||
// are computed, this means the internal distance metric doesn not represent meters!
|
||||
template <class EdgeDataT,
|
||||
class CoordinateListT = std::vector<Coordinate>,
|
||||
bool UseSharedMemory = false,
|
||||
storage::Ownership Ownership = storage::Ownership::Container,
|
||||
std::uint32_t BRANCHING_FACTOR = 128,
|
||||
std::uint32_t LEAF_PAGE_SIZE = 4096>
|
||||
class StaticRTree
|
||||
{
|
||||
template <typename T> using Vector = ViewOrVector<T, Ownership>;
|
||||
|
||||
public:
|
||||
using Rectangle = RectangleInt2D;
|
||||
using EdgeData = EdgeDataT;
|
||||
using CoordinateList = CoordinateListT;
|
||||
using CoordinateList = Vector<util::Coordinate>;
|
||||
|
||||
static_assert(LEAF_PAGE_SIZE >= sizeof(uint32_t) + sizeof(EdgeDataT), "page size is too small");
|
||||
static_assert(((LEAF_PAGE_SIZE - 1) & LEAF_PAGE_SIZE) == 0, "page size is not a power of 2");
|
||||
@@ -152,23 +155,22 @@ class StaticRTree
|
||||
Coordinate fixed_projected_coordinate;
|
||||
};
|
||||
|
||||
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||
const CoordinateListT &m_coordinate_list;
|
||||
Vector<TreeNode> m_search_tree;
|
||||
const Vector<Coordinate> &m_coordinate_list;
|
||||
|
||||
boost::iostreams::mapped_file_source m_leaves_region;
|
||||
// read-only view of leaves
|
||||
typename ShM<const LeafNode, true>::vector m_leaves;
|
||||
util::vector_view<const LeafNode> m_leaves;
|
||||
|
||||
public:
|
||||
StaticRTree(const StaticRTree &) = delete;
|
||||
StaticRTree &operator=(const StaticRTree &) = delete;
|
||||
|
||||
template <typename CoordinateT>
|
||||
// Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||
explicit StaticRTree(const std::vector<EdgeDataT> &input_data_vector,
|
||||
const std::string &tree_node_filename,
|
||||
const std::string &leaf_node_filename,
|
||||
const std::vector<CoordinateT> &coordinate_list)
|
||||
const Vector<Coordinate> &coordinate_list)
|
||||
: m_coordinate_list(coordinate_list)
|
||||
{
|
||||
const uint64_t element_count = input_data_vector.size();
|
||||
@@ -345,7 +347,7 @@ class StaticRTree
|
||||
|
||||
explicit StaticRTree(const boost::filesystem::path &node_file,
|
||||
const boost::filesystem::path &leaf_file,
|
||||
const CoordinateListT &coordinate_list)
|
||||
const Vector<Coordinate> &coordinate_list)
|
||||
: m_coordinate_list(coordinate_list)
|
||||
{
|
||||
storage::io::FileReader tree_node_file(node_file,
|
||||
@@ -362,7 +364,7 @@ class StaticRTree
|
||||
explicit StaticRTree(TreeNode *tree_node_ptr,
|
||||
const uint64_t number_of_nodes,
|
||||
const boost::filesystem::path &leaf_file,
|
||||
const CoordinateListT &coordinate_list)
|
||||
const Vector<Coordinate> &coordinate_list)
|
||||
: m_search_tree(tree_node_ptr, number_of_nodes), m_coordinate_list(coordinate_list)
|
||||
{
|
||||
MapLeafNodesFile(leaf_file);
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||
#define SHARED_MEMORY_VECTOR_WRAPPER_HPP
|
||||
#ifndef UTIL_VECTOR_VIEW_HPP
|
||||
#define UTIL_VECTOR_VIEW_HPP
|
||||
|
||||
#include "util/exception.hpp"
|
||||
#include "util/log.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include <stxxl/vector>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
@@ -22,10 +27,13 @@ namespace util
|
||||
{
|
||||
|
||||
template <typename DataT>
|
||||
class ShMemIterator
|
||||
: public boost::iterator_facade<ShMemIterator<DataT>, DataT, boost::random_access_traversal_tag>
|
||||
class VectorViewIterator : public boost::iterator_facade<VectorViewIterator<DataT>,
|
||||
DataT,
|
||||
boost::random_access_traversal_tag>
|
||||
{
|
||||
typedef boost::iterator_facade<ShMemIterator<DataT>, DataT, boost::random_access_traversal_tag>
|
||||
typedef boost::iterator_facade<VectorViewIterator<DataT>,
|
||||
DataT,
|
||||
boost::random_access_traversal_tag>
|
||||
base_t;
|
||||
|
||||
public:
|
||||
@@ -34,16 +42,16 @@ class ShMemIterator
|
||||
typedef typename base_t::reference reference;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
|
||||
explicit ShMemIterator() : m_value(nullptr) {}
|
||||
explicit ShMemIterator(DataT *x) : m_value(x) {}
|
||||
explicit VectorViewIterator() : m_value(nullptr) {}
|
||||
explicit VectorViewIterator(DataT *x) : m_value(x) {}
|
||||
|
||||
private:
|
||||
void increment() { ++m_value; }
|
||||
void decrement() { --m_value; }
|
||||
void advance(difference_type offset) { m_value += offset; }
|
||||
bool equal(const ShMemIterator &other) const { return m_value == other.m_value; }
|
||||
bool equal(const VectorViewIterator &other) const { return m_value == other.m_value; }
|
||||
reference dereference() const { return *m_value; }
|
||||
difference_type distance_to(const ShMemIterator &other) const
|
||||
difference_type distance_to(const VectorViewIterator &other) const
|
||||
{
|
||||
return other.m_value - m_value;
|
||||
}
|
||||
@@ -52,7 +60,7 @@ class ShMemIterator
|
||||
DataT *m_value;
|
||||
};
|
||||
|
||||
template <typename DataT> class SharedMemoryWrapper
|
||||
template <typename DataT> class vector_view
|
||||
{
|
||||
private:
|
||||
DataT *m_ptr;
|
||||
@@ -60,13 +68,13 @@ template <typename DataT> class SharedMemoryWrapper
|
||||
|
||||
public:
|
||||
using value_type = DataT;
|
||||
using iterator = ShMemIterator<DataT>;
|
||||
using const_iterator = ShMemIterator<const DataT>;
|
||||
using iterator = VectorViewIterator<DataT>;
|
||||
using const_iterator = VectorViewIterator<const DataT>;
|
||||
using reverse_iterator = boost::reverse_iterator<iterator>;
|
||||
|
||||
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||
vector_view() : m_ptr(nullptr), m_size(0) {}
|
||||
|
||||
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
vector_view(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
void reset(DataT *ptr, std::size_t size)
|
||||
{
|
||||
@@ -126,20 +134,21 @@ template <typename DataT> class SharedMemoryWrapper
|
||||
|
||||
auto data() const { return m_ptr; }
|
||||
|
||||
template <typename T>
|
||||
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
|
||||
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
|
||||
};
|
||||
|
||||
template <> class SharedMemoryWrapper<bool>
|
||||
template <> class vector_view<bool>
|
||||
{
|
||||
private:
|
||||
unsigned *m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||
using value_type = bool;
|
||||
|
||||
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
vector_view() : m_ptr(nullptr), m_size(0) {}
|
||||
|
||||
vector_view(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||
|
||||
bool at(const std::size_t index) const
|
||||
{
|
||||
@@ -149,11 +158,7 @@ template <> class SharedMemoryWrapper<bool>
|
||||
return m_ptr[bucket] & (1u << offset);
|
||||
}
|
||||
|
||||
void reset(unsigned *ptr, std::size_t size)
|
||||
{
|
||||
m_ptr = ptr;
|
||||
m_size = size;
|
||||
}
|
||||
void reset(unsigned *, std::size_t size) { m_size = size; }
|
||||
|
||||
std::size_t size() const { return m_size; }
|
||||
|
||||
@@ -161,24 +166,26 @@ template <> class SharedMemoryWrapper<bool>
|
||||
|
||||
bool operator[](const unsigned index) const { return at(index); }
|
||||
|
||||
template <typename T>
|
||||
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
|
||||
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
|
||||
};
|
||||
|
||||
// Both SharedMemoryWrapper<T> and the SharedMemoryWrapper<bool> specializations share this impl.
|
||||
template <typename DataT>
|
||||
void swap(SharedMemoryWrapper<DataT> &lhs, SharedMemoryWrapper<DataT> &rhs) noexcept
|
||||
// Both vector_view<T> and the vector_view<bool> specializations share this impl.
|
||||
template <typename DataT> void swap(vector_view<DataT> &lhs, vector_view<DataT> &rhs) noexcept
|
||||
{
|
||||
std::swap(lhs.m_ptr, rhs.m_ptr);
|
||||
std::swap(lhs.m_size, rhs.m_size);
|
||||
}
|
||||
|
||||
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||
{
|
||||
using vector = typename std::conditional<UseSharedMemory,
|
||||
SharedMemoryWrapper<DataT>,
|
||||
std::vector<DataT>>::type;
|
||||
};
|
||||
template <typename DataT, storage::Ownership Ownership>
|
||||
using InternalOrExternalVector =
|
||||
typename std::conditional<Ownership == storage::Ownership::External,
|
||||
stxxl::vector<DataT>,
|
||||
std::vector<DataT>>::type;
|
||||
|
||||
template <typename DataT, storage::Ownership Ownership>
|
||||
using ViewOrVector = typename std::conditional<Ownership == storage::Ownership::View,
|
||||
vector_view<DataT>,
|
||||
InternalOrExternalVector<DataT, Ownership>>::type;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
var OSRM = module.exports = require('./binding/node-osrm.node').OSRM;
|
||||
var OSRM = module.exports = require('./binding/node_osrm.node').OSRM;
|
||||
OSRM.version = require('../package.json').version;
|
||||
|
||||
+7
-5
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "osrm",
|
||||
"version": "5.7.0-latest.2",
|
||||
"version": "5.7.0-rc.1",
|
||||
"private": false,
|
||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||
"dependencies": {
|
||||
"nan": "^2.1.0",
|
||||
"node-cmake": "^1.2.1",
|
||||
"node-cmake": "^2.2.1",
|
||||
"node-pre-gyp": "^0.6.34"
|
||||
},
|
||||
"browserify": {
|
||||
@@ -19,14 +19,15 @@
|
||||
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld",
|
||||
"clean": "rm -rf test/cache",
|
||||
"docs": "./scripts/build_api_docs.sh",
|
||||
"install": "node-pre-gyp install --fallback-to-build=false"
|
||||
"install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh",
|
||||
"nodejs-tests": "make -C test/data && ./lib/binding/osrm-datastore test/data/ch/monaco.osrm && node test/nodejs/index.js | faucet"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Project-OSRM/osrm-backend.git"
|
||||
},
|
||||
"author": "Project OSRM Team",
|
||||
"license": "BSD 2-Clause",
|
||||
"license": "BSD-2-Clause",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Project-OSRM/osrm-backend/issues"
|
||||
},
|
||||
@@ -44,6 +45,7 @@
|
||||
"mkdirp": "^0.5.1",
|
||||
"aws-sdk": "~2.0.31",
|
||||
"tape": "^4.2.2",
|
||||
"faucet": "^0.0.1",
|
||||
"node-timeout": "0.0.4",
|
||||
"polyline": "^0.2.0",
|
||||
"request": "^2.69.0",
|
||||
@@ -55,7 +57,7 @@
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"binary": {
|
||||
"module_name": "node-osrm",
|
||||
"module_name": "node_osrm",
|
||||
"module_path": "./lib/binding/",
|
||||
"host": "https://mapbox-node-binary.s3.amazonaws.com",
|
||||
"remote_path": "./{name}/v{version}/{configuration}/",
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CMAKE_OPTIONS=${CMAKE_OPTIONS:-"-DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=On"}
|
||||
|
||||
if [[ ! -f $(which cmake) ]]; then
|
||||
echo "Needs cmake to build from source"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -d build ]]; then
|
||||
echo "Detected existing build directory, skipping compiling."
|
||||
exit 0
|
||||
else
|
||||
mkdir -p build
|
||||
pushd build
|
||||
cmake .. $CMAKE_OPTIONS
|
||||
cmake --build .
|
||||
popd
|
||||
fi
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
var name = process.argv[2];
|
||||
var cmd = process.argv.slice(3).join(' ');
|
||||
var start = Date.now();
|
||||
exec(cmd, (err) => {
|
||||
if (err) return console.log(err);
|
||||
var stop = +new Date();
|
||||
var time = (stop - start) / 1000.;
|
||||
fs.appendFileSync('/tmp/osrm.timings', `${name}\t${time}`, 'utf-8');
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
TIMINGS_FILE=/tmp/osrm.timings
|
||||
NAME=$1
|
||||
CMD=${@:2}
|
||||
START=$(date "+%s.%N")
|
||||
/bin/bash -c "$CMD"
|
||||
END=$(date "+%s.%N")
|
||||
TIME="$(echo "$END - $START" | bc)s"
|
||||
NEW_ENTRY="$NAME\t$TIME"
|
||||
|
||||
echo -e "$NEW_ENTRY" >> $TIMINGS_FILE
|
||||
@@ -3,20 +3,24 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
echo "node version is:"
|
||||
which node
|
||||
node -v
|
||||
|
||||
if [[ ${PUBLISH} == 'On' ]]; then
|
||||
echo "PUBLISH is set to '${PUBLISH}', publishing!"
|
||||
|
||||
echo "node version is:"
|
||||
which node
|
||||
node -v
|
||||
NPM_FLAGS=''
|
||||
if [[ ${BUILD_TYPE} == "Debug" ]]; then
|
||||
NPM_FLAGS='--debug'
|
||||
fi
|
||||
|
||||
echo "dumping binary meta..."
|
||||
./node_modules/.bin/node-pre-gyp reveal
|
||||
./node_modules/.bin/node-pre-gyp reveal $NPM_FLAGS
|
||||
|
||||
# enforce that binary has proper ORIGIN flags so that
|
||||
# it can portably find libtbb.so in the same directory
|
||||
if [[ $(uname -s) == 'Linux' ]]; then
|
||||
readelf -d ./lib/binding/node-osrm.node > readelf-output.txt
|
||||
readelf -d ./lib/binding/node_osrm.node > readelf-output.txt
|
||||
if grep -q 'Flags: ORIGIN' readelf-output.txt; then
|
||||
echo "Found ORIGIN flag in readelf output"
|
||||
cat readelf-output.txt
|
||||
@@ -27,7 +31,7 @@ if [[ ${PUBLISH} == 'On' ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
./node_modules/.bin/node-pre-gyp package publish info
|
||||
./node_modules/.bin/node-pre-gyp package publish info $NPM_FLAGS
|
||||
else
|
||||
echo "PUBLISH is set to '${PUBLISH}', skipping."
|
||||
fi
|
||||
|
||||
@@ -27,13 +27,12 @@ constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
|
||||
constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
||||
|
||||
using RTreeLeaf = extractor::EdgeBasedNode;
|
||||
using BenchStaticRTree =
|
||||
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, false>::vector, false>;
|
||||
using BenchStaticRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::Container>;
|
||||
|
||||
std::vector<util::Coordinate> loadCoordinates(const boost::filesystem::path &nodes_file)
|
||||
{
|
||||
osrm::storage::io::FileReader nodes_path_file_reader(
|
||||
nodes_file, osrm::storage::io::FileReader::HasNoFingerprint);
|
||||
storage::io::FileReader nodes_path_file_reader(nodes_file,
|
||||
storage::io::FileReader::HasNoFingerprint);
|
||||
|
||||
extractor::QueryNode current_node;
|
||||
unsigned coordinate_count = nodes_path_file_reader.ReadElementCount32();
|
||||
|
||||
+15
-119
@@ -1,5 +1,6 @@
|
||||
#include "contractor/contractor.hpp"
|
||||
#include "contractor/crc32_processor.hpp"
|
||||
#include "contractor/files.hpp"
|
||||
#include "contractor/graph_contractor.hpp"
|
||||
#include "contractor/graph_contractor_adaptors.hpp"
|
||||
|
||||
@@ -15,7 +16,6 @@
|
||||
#include "util/exception_utils.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/io.hpp"
|
||||
#include "util/log.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/string_util.hpp"
|
||||
@@ -47,9 +47,9 @@ int Contractor::Run()
|
||||
util::Log() << "Reading node weights.";
|
||||
std::vector<EdgeWeight> node_weights;
|
||||
{
|
||||
storage::io::FileReader node_file(config.node_file_path,
|
||||
storage::io::FileReader::VerifyFingerprint);
|
||||
node_file.DeserializeVector(node_weights);
|
||||
storage::io::FileReader reader(config.node_file_path,
|
||||
storage::io::FileReader::VerifyFingerprint);
|
||||
storage::serialization::read(reader, node_weights);
|
||||
}
|
||||
util::Log() << "Done reading node weights.";
|
||||
|
||||
@@ -85,7 +85,7 @@ int Contractor::Run()
|
||||
|
||||
util::Log() << "Contraction took " << TIMER_SEC(contraction) << " sec";
|
||||
|
||||
std::size_t number_of_used_edges = WriteContractedGraph(max_edge_id, contracted_edge_list);
|
||||
WriteContractedGraph(max_edge_id, std::move(contracted_edge_list));
|
||||
WriteCoreNodeMarker(std::move(is_core_node));
|
||||
if (!config.use_cached_priority)
|
||||
{
|
||||
@@ -94,14 +94,7 @@ int Contractor::Run()
|
||||
|
||||
TIMER_STOP(preparing);
|
||||
|
||||
const auto nodes_per_second =
|
||||
static_cast<std::uint64_t>((max_edge_id + 1) / TIMER_SEC(contraction));
|
||||
const auto edges_per_second =
|
||||
static_cast<std::uint64_t>(number_of_used_edges / TIMER_SEC(contraction));
|
||||
|
||||
util::Log() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
||||
util::Log() << "Contraction: " << nodes_per_second << " nodes/sec and " << edges_per_second
|
||||
<< " edges/sec";
|
||||
|
||||
util::Log() << "finished preprocessing";
|
||||
|
||||
@@ -122,10 +115,10 @@ void Contractor::WriteNodeLevels(std::vector<float> &&in_node_levels) const
|
||||
{
|
||||
std::vector<float> node_levels(std::move(in_node_levels));
|
||||
|
||||
storage::io::FileWriter node_level_file(config.level_output_path,
|
||||
storage::io::FileWriter::HasNoFingerprint);
|
||||
storage::io::FileWriter writer(config.level_output_path,
|
||||
storage::io::FileWriter::HasNoFingerprint);
|
||||
|
||||
node_level_file.SerializeVector(node_levels);
|
||||
storage::serialization::write(writer, node_levels);
|
||||
}
|
||||
|
||||
void Contractor::WriteCoreNodeMarker(std::vector<bool> &&in_is_core_node) const
|
||||
@@ -145,117 +138,20 @@ void Contractor::WriteCoreNodeMarker(std::vector<bool> &&in_is_core_node) const
|
||||
core_marker_output_file.WriteFrom(unpacked_bool_flags.data(), count);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
Contractor::WriteContractedGraph(unsigned max_node_id,
|
||||
const util::DeallocatingVector<QueryEdge> &contracted_edge_list)
|
||||
void Contractor::WriteContractedGraph(unsigned max_node_id,
|
||||
util::DeallocatingVector<QueryEdge> contracted_edge_list)
|
||||
{
|
||||
// Sorting contracted edges in a way that the static query graph can read some in in-place.
|
||||
tbb::parallel_sort(contracted_edge_list.begin(), contracted_edge_list.end());
|
||||
const std::uint64_t contracted_edge_count = contracted_edge_list.size();
|
||||
util::Log() << "Serializing compacted graph of " << contracted_edge_count << " edges";
|
||||
|
||||
storage::io::FileWriter hsgr_output_file(config.graph_output_path,
|
||||
storage::io::FileWriter::GenerateFingerprint);
|
||||
|
||||
const NodeID max_used_node_id = [&contracted_edge_list] {
|
||||
NodeID tmp_max = 0;
|
||||
for (const QueryEdge &edge : contracted_edge_list)
|
||||
{
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge.source);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge.target);
|
||||
tmp_max = std::max(tmp_max, edge.source);
|
||||
tmp_max = std::max(tmp_max, edge.target);
|
||||
}
|
||||
return tmp_max;
|
||||
}();
|
||||
|
||||
util::Log(logDEBUG) << "input graph has " << (max_node_id + 1) << " nodes";
|
||||
util::Log(logDEBUG) << "contracted graph has " << (max_used_node_id + 1) << " nodes";
|
||||
|
||||
std::vector<util::StaticGraph<EdgeData>::NodeArrayEntry> node_array;
|
||||
// make sure we have at least one sentinel
|
||||
node_array.resize(max_node_id + 2);
|
||||
|
||||
util::Log() << "Building node array";
|
||||
util::StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
||||
util::StaticGraph<EdgeData>::EdgeIterator position = 0;
|
||||
util::StaticGraph<EdgeData>::EdgeIterator last_edge;
|
||||
|
||||
// initializing 'first_edge'-field of nodes:
|
||||
for (const auto node : util::irange(0u, max_used_node_id + 1))
|
||||
{
|
||||
last_edge = edge;
|
||||
while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node))
|
||||
{
|
||||
++edge;
|
||||
}
|
||||
node_array[node].first_edge = position; //=edge
|
||||
position += edge - last_edge; // remove
|
||||
}
|
||||
|
||||
for (const auto sentinel_counter :
|
||||
util::irange<unsigned>(max_used_node_id + 1, node_array.size()))
|
||||
{
|
||||
// sentinel element, guarded against underflow
|
||||
node_array[sentinel_counter].first_edge = contracted_edge_count;
|
||||
}
|
||||
|
||||
util::Log() << "Serializing node array";
|
||||
auto new_end = std::unique(contracted_edge_list.begin(), contracted_edge_list.end());
|
||||
contracted_edge_list.resize(new_end - contracted_edge_list.begin());
|
||||
|
||||
RangebasedCRC32 crc32_calculator;
|
||||
const unsigned edges_crc32 = crc32_calculator(contracted_edge_list);
|
||||
util::Log() << "Writing CRC32: " << edges_crc32;
|
||||
const unsigned checksum = crc32_calculator(contracted_edge_list);
|
||||
|
||||
const std::uint64_t node_array_size = node_array.size();
|
||||
// serialize crc32, aka checksum
|
||||
hsgr_output_file.WriteOne(edges_crc32);
|
||||
// serialize number of nodes
|
||||
hsgr_output_file.WriteOne(node_array_size);
|
||||
// serialize number of edges
|
||||
hsgr_output_file.WriteOne(contracted_edge_count);
|
||||
// serialize all nodes
|
||||
if (node_array_size > 0)
|
||||
{
|
||||
hsgr_output_file.WriteFrom(node_array.data(), node_array_size);
|
||||
}
|
||||
QueryGraph query_graph{max_node_id + 1, contracted_edge_list};
|
||||
|
||||
// serialize all edges
|
||||
util::Log() << "Building edge array";
|
||||
std::size_t number_of_used_edges = 0;
|
||||
|
||||
util::StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
|
||||
for (const auto edge : util::irange<std::size_t>(0UL, contracted_edge_list.size()))
|
||||
{
|
||||
// some self-loops are required for oneway handling. Need to assertthat we only keep these
|
||||
// (TODO)
|
||||
// no eigen loops
|
||||
// BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target ||
|
||||
// node_represents_oneway[contracted_edge_list[edge].source]);
|
||||
current_edge.target = contracted_edge_list[edge].target;
|
||||
current_edge.data = contracted_edge_list[edge].data;
|
||||
|
||||
// every target needs to be valid
|
||||
BOOST_ASSERT(current_edge.target <= max_used_node_id);
|
||||
#ifndef NDEBUG
|
||||
if (current_edge.data.weight <= 0)
|
||||
{
|
||||
util::Log(logWARNING) << "Edge: " << edge
|
||||
<< ",source: " << contracted_edge_list[edge].source
|
||||
<< ", target: " << contracted_edge_list[edge].target
|
||||
<< ", weight: " << current_edge.data.weight;
|
||||
|
||||
util::Log(logWARNING) << "Failed at adjacency list of node "
|
||||
<< contracted_edge_list[edge].source << "/"
|
||||
<< node_array.size() - 1;
|
||||
throw util::exception("Edge weight is <= 0" + SOURCE_REF);
|
||||
}
|
||||
#endif
|
||||
hsgr_output_file.WriteOne(current_edge);
|
||||
|
||||
++number_of_used_edges;
|
||||
}
|
||||
|
||||
return number_of_used_edges;
|
||||
files::writeGraph(config.graph_output_path, checksum, query_graph);
|
||||
}
|
||||
|
||||
} // namespace contractor
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#include "customizer/customizer.hpp"
|
||||
#include "customizer/cell_customizer.hpp"
|
||||
#include "customizer/edge_based_graph.hpp"
|
||||
#include "customizer/io.hpp"
|
||||
|
||||
#include "partition/cell_storage.hpp"
|
||||
#include "partition/edge_based_graph_reader.hpp"
|
||||
#include "partition/io.hpp"
|
||||
#include "partition/files.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
|
||||
#include "storage/shared_memory_ownership.hpp"
|
||||
|
||||
#include "updater/updater.hpp"
|
||||
|
||||
#include "util/log.hpp"
|
||||
@@ -83,8 +84,7 @@ auto LoadAndUpdateEdgeExpandedGraph(const CustomizationConfig &config,
|
||||
auto tidied =
|
||||
partition::prepareEdgesForUsageInGraph<StaticEdgeBasedGraphEdge>(std::move(directed));
|
||||
auto edge_based_graph =
|
||||
std::make_unique<partition::MultiLevelGraph<EdgeBasedGraphEdgeData, false>>(
|
||||
mlp, num_nodes, std::move(tidied));
|
||||
std::make_unique<customizer::MultiLevelEdgeBasedGraph>(mlp, num_nodes, std::move(tidied));
|
||||
|
||||
util::Log() << "Loaded edge based graph for mapping partition ids: "
|
||||
<< edge_based_graph->GetNumberOfEdges() << " edges, "
|
||||
@@ -98,12 +98,12 @@ int Customizer::Run(const CustomizationConfig &config)
|
||||
TIMER_START(loading_data);
|
||||
|
||||
partition::MultiLevelPartition mlp;
|
||||
partition::io::read(config.mld_partition_path, mlp);
|
||||
partition::files::readPartition(config.mld_partition_path, mlp);
|
||||
|
||||
auto edge_based_graph = LoadAndUpdateEdgeExpandedGraph(config, mlp);
|
||||
|
||||
partition::CellStorage storage;
|
||||
partition::io::read(config.mld_storage_path, storage);
|
||||
partition::files::readCells(config.mld_storage_path, storage);
|
||||
TIMER_STOP(loading_data);
|
||||
util::Log() << "Loading partition data took " << TIMER_SEC(loading_data) << " seconds";
|
||||
|
||||
@@ -114,12 +114,12 @@ int Customizer::Run(const CustomizationConfig &config)
|
||||
util::Log() << "Cells customization took " << TIMER_SEC(cell_customize) << " seconds";
|
||||
|
||||
TIMER_START(writing_mld_data);
|
||||
partition::io::write(config.mld_storage_path, storage);
|
||||
partition::files::writeCells(config.mld_storage_path, storage);
|
||||
TIMER_STOP(writing_mld_data);
|
||||
util::Log() << "MLD customization writing took " << TIMER_SEC(writing_mld_data) << " seconds";
|
||||
|
||||
TIMER_START(writing_graph);
|
||||
partition::io::write(config.mld_graph_path, *edge_based_graph);
|
||||
partition::files::writeGraph(config.mld_graph_path, *edge_based_graph);
|
||||
TIMER_STOP(writing_graph);
|
||||
util::Log() << "Graph writing took " << TIMER_SEC(writing_graph) << " seconds";
|
||||
|
||||
|
||||
@@ -118,12 +118,14 @@ bool setUpRoundabout(RouteStep &step)
|
||||
|
||||
void closeOffRoundabout(const bool on_roundabout,
|
||||
std::vector<RouteStep> &steps,
|
||||
const std::size_t step_index)
|
||||
std::size_t step_index)
|
||||
{
|
||||
auto &step = steps[step_index];
|
||||
step.maneuver.exit += 1;
|
||||
if (!on_roundabout)
|
||||
{
|
||||
BOOST_ASSERT(steps.size() >= 2);
|
||||
|
||||
// We reached a special case that requires the addition of a special route step in the
|
||||
// beginning. We started in a roundabout, so to announce the exit, we move use the exit
|
||||
// instruction and move it right to the beginning to make sure to immediately announce the
|
||||
@@ -160,6 +162,23 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
}
|
||||
}
|
||||
|
||||
if (step_index > 1)
|
||||
{
|
||||
auto &exit_step = steps[step_index];
|
||||
auto &prev_step = steps[step_index - 1];
|
||||
// In case the step with the roundabout exit instruction cannot be merged with the
|
||||
// previous step we change the instruction to a normal turn
|
||||
if (!guidance::haveSameMode(exit_step, prev_step))
|
||||
{
|
||||
BOOST_ASSERT(leavesRoundabout(exit_step.maneuver.instruction));
|
||||
prev_step.maneuver.instruction = exit_step.maneuver.instruction;
|
||||
if (!entersRoundabout(prev_step.maneuver.instruction))
|
||||
prev_step.maneuver.exit = exit_step.maneuver.exit;
|
||||
exit_step.maneuver.instruction.type = TurnType::Notification;
|
||||
step_index--;
|
||||
}
|
||||
}
|
||||
|
||||
// Normal exit from the roundabout, or exit from a previously fixed roundabout. Propagate the
|
||||
// index back to the entering location and prepare the current silent set of instructions for
|
||||
// removal.
|
||||
@@ -170,6 +189,7 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
const auto exit_intersection = steps[step_index].intersections.front();
|
||||
const auto exit_bearing = exit_intersection.bearings[exit_intersection.out];
|
||||
const auto destination_copy = step;
|
||||
|
||||
if (step_index > 1)
|
||||
{
|
||||
// The very first route-step is head, so we cannot iterate past that one
|
||||
@@ -177,8 +197,11 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
--propagation_index)
|
||||
{
|
||||
auto &propagation_step = steps[propagation_index];
|
||||
propagation_step.ElongateBy(steps[propagation_index + 1]);
|
||||
propagation_step.maneuver.exit = steps[propagation_index + 1].maneuver.exit;
|
||||
auto &next_step = steps[propagation_index + 1];
|
||||
propagation_step.ElongateBy(next_step);
|
||||
propagation_step.maneuver.exit = next_step.maneuver.exit;
|
||||
next_step.Invalidate();
|
||||
|
||||
if (entersRoundabout(propagation_step.maneuver.instruction))
|
||||
{
|
||||
const auto entry_intersection = propagation_step.intersections.front();
|
||||
@@ -206,13 +229,8 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
}
|
||||
|
||||
propagation_step.AdaptStepSignage(destination_copy);
|
||||
steps[propagation_index + 1].Invalidate();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
steps[propagation_index + 1].Invalidate();
|
||||
}
|
||||
}
|
||||
// remove exit
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace engine
|
||||
{
|
||||
namespace routing_algorithms
|
||||
{
|
||||
namespace ch
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -26,7 +28,7 @@ const double constexpr VIAPATH_ALPHA = 0.10;
|
||||
const double constexpr VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
|
||||
const double constexpr VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
|
||||
|
||||
using QueryHeap = SearchEngineData::QueryHeap;
|
||||
using QueryHeap = SearchEngineData<Algorithm>::QueryHeap;
|
||||
using SearchSpaceEdge = std::pair<NodeID, NodeID>;
|
||||
|
||||
struct RankedCandidateNode
|
||||
@@ -48,15 +50,14 @@ struct RankedCandidateNode
|
||||
|
||||
// todo: reorder parameters
|
||||
template <bool DIRECTION>
|
||||
void alternativeRoutingStep(
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
QueryHeap &heap1,
|
||||
QueryHeap &heap2,
|
||||
NodeID *middle_node,
|
||||
EdgeWeight *upper_bound_to_shortest_path_weight,
|
||||
std::vector<NodeID> &search_space_intersection,
|
||||
std::vector<SearchSpaceEdge> &search_space,
|
||||
const EdgeWeight min_edge_offset)
|
||||
void alternativeRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
QueryHeap &heap1,
|
||||
QueryHeap &heap2,
|
||||
NodeID *middle_node,
|
||||
EdgeWeight *upper_bound_to_shortest_path_weight,
|
||||
std::vector<NodeID> &search_space_intersection,
|
||||
std::vector<SearchSpaceEdge> &search_space,
|
||||
const EdgeWeight min_edge_offset)
|
||||
{
|
||||
QueryHeap &forward_heap = DIRECTION == FORWARD_DIRECTION ? heap1 : heap2;
|
||||
QueryHeap &reverse_heap = DIRECTION == FORWARD_DIRECTION ? heap2 : heap1;
|
||||
@@ -153,8 +154,8 @@ void retrievePackedAlternatePath(const QueryHeap &forward_heap1,
|
||||
// from v and intersecting against queues. only half-searches have to be
|
||||
// done at this stage
|
||||
void computeLengthAndSharingOfViaPath(
|
||||
SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID via_node,
|
||||
int *real_length_of_via_path,
|
||||
int *sharing_of_via_path,
|
||||
@@ -163,10 +164,10 @@ void computeLengthAndSharingOfViaPath(
|
||||
{
|
||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
|
||||
QueryHeap &existing_forward_heap = *engine_working_data.forward_heap_1;
|
||||
QueryHeap &existing_reverse_heap = *engine_working_data.reverse_heap_1;
|
||||
QueryHeap &new_forward_heap = *engine_working_data.forward_heap_2;
|
||||
QueryHeap &new_reverse_heap = *engine_working_data.reverse_heap_2;
|
||||
auto &existing_forward_heap = *engine_working_data.forward_heap_1;
|
||||
auto &existing_reverse_heap = *engine_working_data.reverse_heap_1;
|
||||
auto &new_forward_heap = *engine_working_data.forward_heap_2;
|
||||
auto &new_reverse_heap = *engine_working_data.reverse_heap_2;
|
||||
|
||||
std::vector<NodeID> packed_s_v_path;
|
||||
std::vector<NodeID> packed_v_t_path;
|
||||
@@ -318,8 +319,8 @@ void computeLengthAndSharingOfViaPath(
|
||||
|
||||
// conduct T-Test
|
||||
bool viaNodeCandidatePassesTTest(
|
||||
SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
QueryHeap &existing_forward_heap,
|
||||
QueryHeap &existing_reverse_heap,
|
||||
QueryHeap &new_forward_heap,
|
||||
@@ -562,8 +563,8 @@ bool viaNodeCandidatePassesTTest(
|
||||
}
|
||||
|
||||
InternalRouteResult
|
||||
alternativePathSearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const PhantomNodes &phantom_node_pair)
|
||||
{
|
||||
InternalRouteResult raw_route_data;
|
||||
@@ -578,10 +579,10 @@ alternativePathSearch(SearchEngineData &engine_working_data,
|
||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
engine_working_data.InitializeOrClearThirdThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
|
||||
QueryHeap &forward_heap1 = *(engine_working_data.forward_heap_1);
|
||||
QueryHeap &reverse_heap1 = *(engine_working_data.reverse_heap_1);
|
||||
QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2);
|
||||
QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2);
|
||||
auto &forward_heap1 = *engine_working_data.forward_heap_1;
|
||||
auto &reverse_heap1 = *engine_working_data.reverse_heap_1;
|
||||
auto &forward_heap2 = *engine_working_data.forward_heap_2;
|
||||
auto &reverse_heap2 = *engine_working_data.reverse_heap_2;
|
||||
|
||||
EdgeWeight upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT;
|
||||
NodeID middle_node = SPECIAL_NODEID;
|
||||
@@ -846,6 +847,7 @@ alternativePathSearch(SearchEngineData &engine_working_data,
|
||||
return raw_route_data;
|
||||
}
|
||||
|
||||
} // namespace ch
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm}
|
||||
|
||||
@@ -47,7 +47,7 @@ extractRoute(const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &f
|
||||
return raw_route_data;
|
||||
}
|
||||
|
||||
namespace ch
|
||||
namespace detail
|
||||
{
|
||||
/// This is a striped down version of the general shortest path algorithm.
|
||||
/// The general algorithm always computes two queries for each leg. This is only
|
||||
@@ -55,36 +55,31 @@ namespace ch
|
||||
/// by the previous route.
|
||||
/// This variation is only an optimazation for graphs with slow queries, for example
|
||||
/// not fully contracted graphs.
|
||||
template <typename AlgorithmT>
|
||||
template <typename Algorithm>
|
||||
InternalRouteResult directShortestPathSearchImpl(
|
||||
SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
|
||||
SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
{
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
auto &forward_heap = *(engine_working_data.forward_heap_1);
|
||||
auto &reverse_heap = *(engine_working_data.reverse_heap_1);
|
||||
auto &forward_core_heap = *(engine_working_data.forward_heap_2);
|
||||
auto &reverse_core_heap = *(engine_working_data.reverse_heap_2);
|
||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
forward_core_heap.Clear();
|
||||
reverse_core_heap.Clear();
|
||||
|
||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||
std::vector<NodeID> packed_leg;
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||
|
||||
search(facade,
|
||||
search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
forward_core_heap,
|
||||
reverse_core_heap,
|
||||
weight,
|
||||
packed_leg,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
DO_NOT_FORCE_LOOPS);
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
phantom_nodes);
|
||||
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
auto source_node = SPECIAL_NODEID, target_node = SPECIAL_NODEID;
|
||||
@@ -93,7 +88,7 @@ InternalRouteResult directShortestPathSearchImpl(
|
||||
source_node = packed_leg.front();
|
||||
target_node = packed_leg.back();
|
||||
unpacked_edges.reserve(packed_leg.size());
|
||||
unpackPath(
|
||||
ch::unpackPath(
|
||||
facade,
|
||||
packed_leg.begin(),
|
||||
packed_leg.end(),
|
||||
@@ -106,36 +101,30 @@ InternalRouteResult directShortestPathSearchImpl(
|
||||
|
||||
} // namespace ch
|
||||
|
||||
template <>
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
{
|
||||
return ch::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
|
||||
return detail::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
|
||||
}
|
||||
|
||||
template <>
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
{
|
||||
return ch::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
|
||||
return detail::directShortestPathSearchImpl(engine_working_data, facade, phantom_nodes);
|
||||
}
|
||||
|
||||
template <>
|
||||
InternalRouteResult directShortestPathSearch(
|
||||
SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD> &facade,
|
||||
SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
|
||||
const PhantomNodes &phantom_nodes)
|
||||
{
|
||||
engine_working_data.InitializeOrClearMultiLayerDijkstraThreadLocalStorage(
|
||||
facade.GetNumberOfNodes());
|
||||
auto &forward_heap = *(engine_working_data.mld_forward_heap);
|
||||
auto &reverse_heap = *(engine_working_data.mld_reverse_heap);
|
||||
forward_heap.Clear();
|
||||
reverse_heap.Clear();
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
||||
|
||||
// TODO: when structured bindings will be allowed change to
|
||||
@@ -143,8 +132,14 @@ InternalRouteResult directShortestPathSearch(
|
||||
EdgeWeight weight;
|
||||
NodeID source_node, target_node;
|
||||
std::vector<EdgeID> unpacked_edges;
|
||||
std::tie(weight, source_node, target_node, unpacked_edges) =
|
||||
mld::search(facade, forward_heap, reverse_heap, phantom_nodes);
|
||||
std::tie(weight, source_node, target_node, unpacked_edges) = mld::search(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
DO_NOT_FORCE_LOOPS,
|
||||
INVALID_EDGE_WEIGHT,
|
||||
phantom_nodes);
|
||||
|
||||
return extractRoute(facade, weight, source_node, target_node, unpacked_edges, phantom_nodes);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ namespace engine
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
using ManyToManyQueryHeap = SearchEngineData::ManyToManyQueryHeap;
|
||||
namespace ch
|
||||
{
|
||||
|
||||
using ManyToManyQueryHeap = SearchEngineData<Algorithm>::ManyToManyQueryHeap;
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -34,7 +37,7 @@ struct NodeBucket
|
||||
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
||||
|
||||
template <bool DIRECTION>
|
||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const NodeID node,
|
||||
const EdgeWeight weight,
|
||||
const EdgeWeight duration,
|
||||
@@ -69,7 +72,7 @@ void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<alg
|
||||
}
|
||||
}
|
||||
|
||||
void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const unsigned row_idx,
|
||||
const unsigned number_of_targets,
|
||||
ManyToManyQueryHeap &query_heap,
|
||||
@@ -126,11 +129,10 @@ void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<alg
|
||||
relaxOutgoingEdges<FORWARD_DIRECTION>(facade, node, source_weight, source_duration, query_heap);
|
||||
}
|
||||
|
||||
void backwardRoutingStep(
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
const unsigned column_idx,
|
||||
ManyToManyQueryHeap &query_heap,
|
||||
SearchSpaceWithBuckets &search_space_with_buckets)
|
||||
void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const unsigned column_idx,
|
||||
ManyToManyQueryHeap &query_heap,
|
||||
SearchSpaceWithBuckets &search_space_with_buckets)
|
||||
{
|
||||
const NodeID node = query_heap.DeleteMin();
|
||||
const EdgeWeight target_weight = query_heap.GetKey(node);
|
||||
@@ -149,8 +151,8 @@ void backwardRoutingStep(
|
||||
}
|
||||
|
||||
std::vector<EdgeWeight>
|
||||
manyToManySearch(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const std::vector<PhantomNode> &phantom_nodes,
|
||||
const std::vector<std::size_t> &source_indices,
|
||||
const std::vector<std::size_t> &target_indices)
|
||||
@@ -240,6 +242,7 @@ manyToManySearch(SearchEngineData &engine_working_data,
|
||||
return durations_table;
|
||||
}
|
||||
|
||||
} // namespace ch
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "engine/routing_algorithms/map_matching.hpp"
|
||||
#include "engine/routing_algorithms/routing_base_ch.hpp"
|
||||
#include "engine/routing_algorithms/routing_base_mld.hpp"
|
||||
|
||||
#include "engine/map_matching/hidden_markov_model.hpp"
|
||||
#include "engine/map_matching/matching_confidence.hpp"
|
||||
@@ -47,15 +48,14 @@ unsigned getMedianSampleTime(const std::vector<unsigned> ×tamps)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AlgorithmT>
|
||||
SubMatchingList
|
||||
mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting)
|
||||
template <typename Algorithm>
|
||||
SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting)
|
||||
{
|
||||
map_matching::MatchingConfidence confidence;
|
||||
map_matching::EmissionLogProbability default_emission_log_probability(DEFAULT_GPS_PRECISION);
|
||||
@@ -141,13 +141,11 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
return sub_matchings;
|
||||
}
|
||||
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(facade.GetNumberOfNodes());
|
||||
const auto nodes_number = facade.GetNumberOfNodes();
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number);
|
||||
|
||||
auto &forward_heap = *(engine_working_data.forward_heap_1);
|
||||
auto &reverse_heap = *(engine_working_data.reverse_heap_1);
|
||||
auto &forward_core_heap = *(engine_working_data.forward_heap_2);
|
||||
auto &reverse_core_heap = *(engine_working_data.reverse_heap_2);
|
||||
auto &forward_heap = *engine_working_data.forward_heap_1;
|
||||
auto &reverse_heap = *engine_working_data.reverse_heap_1;
|
||||
|
||||
std::size_t breakage_begin = map_matching::INVALID_STATE;
|
||||
std::vector<std::size_t> split_points;
|
||||
@@ -197,9 +195,9 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
|
||||
const auto haversine_distance = util::coordinate_calculation::haversineDistance(
|
||||
prev_coordinate, current_coordinate);
|
||||
// assumes minumum of 0.1 m/s
|
||||
const int duration_upper_bound =
|
||||
((haversine_distance + max_distance_delta) * 0.25) * 10;
|
||||
// assumes minumum of 4 m/s
|
||||
const EdgeWeight weight_upper_bound =
|
||||
((haversine_distance + max_distance_delta) / 4.) * facade.GetWeightMultiplier();
|
||||
|
||||
// compute d_t for this timestamp and the next one
|
||||
for (const auto s : util::irange<std::size_t>(0UL, prev_viterbi.size()))
|
||||
@@ -219,14 +217,13 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
}
|
||||
|
||||
double network_distance =
|
||||
ch::getNetworkDistance(facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
forward_core_heap,
|
||||
reverse_core_heap,
|
||||
prev_unbroken_timestamps_list[s].phantom_node,
|
||||
current_timestamps_list[s_prime].phantom_node,
|
||||
duration_upper_bound);
|
||||
getNetworkDistance(engine_working_data,
|
||||
facade,
|
||||
forward_heap,
|
||||
reverse_heap,
|
||||
prev_unbroken_timestamps_list[s].phantom_node,
|
||||
current_timestamps_list[s_prime].phantom_node,
|
||||
weight_upper_bound);
|
||||
|
||||
// get distance diff between loc1/2 and locs/s_prime
|
||||
const auto d_t = std::abs(network_distance - haversine_distance);
|
||||
@@ -419,42 +416,32 @@ mapMatchingImpl(SearchEngineData &engine_working_data,
|
||||
return sub_matchings;
|
||||
}
|
||||
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CH> &facade,
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<ch::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool use_tidying)
|
||||
{
|
||||
return mapMatchingImpl(engine_working_data,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision,
|
||||
use_tidying);
|
||||
}
|
||||
const bool allow_splitting);
|
||||
|
||||
SubMatchingList
|
||||
mapMatching(SearchEngineData &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<algorithm::CoreCH> &facade,
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<corech::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<corech::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool use_tidying)
|
||||
{
|
||||
const bool allow_splitting);
|
||||
|
||||
return mapMatchingImpl(engine_working_data,
|
||||
facade,
|
||||
candidates_list,
|
||||
trace_coordinates,
|
||||
trace_timestamps,
|
||||
trace_gps_precision,
|
||||
use_tidying);
|
||||
}
|
||||
template SubMatchingList
|
||||
mapMatching(SearchEngineData<mld::Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
|
||||
const CandidateLists &candidates_list,
|
||||
const std::vector<util::Coordinate> &trace_coordinates,
|
||||
const std::vector<unsigned> &trace_timestamps,
|
||||
const std::vector<boost::optional<double>> &trace_gps_precision,
|
||||
const bool allow_splitting);
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "engine/routing_algorithms/routing_base.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace engine
|
||||
{
|
||||
namespace routing_algorithms
|
||||
{
|
||||
|
||||
bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||
{
|
||||
return source_phantom.forward_segment_id.enabled && target_phantom.forward_segment_id.enabled &&
|
||||
source_phantom.forward_segment_id.id == target_phantom.forward_segment_id.id &&
|
||||
source_phantom.GetForwardWeightPlusOffset() >
|
||||
target_phantom.GetForwardWeightPlusOffset();
|
||||
}
|
||||
|
||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom)
|
||||
{
|
||||
return source_phantom.reverse_segment_id.enabled && target_phantom.reverse_segment_id.enabled &&
|
||||
source_phantom.reverse_segment_id.id == target_phantom.reverse_segment_id.id &&
|
||||
source_phantom.GetReverseWeightPlusOffset() >
|
||||
target_phantom.GetReverseWeightPlusOffset();
|
||||
}
|
||||
|
||||
} // namespace routing_algorithms
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user