Skip to content

Commit

Permalink
Merge tag 'v5.19.0'
Browse files Browse the repository at this point in the history
  - Changes from 5.18.0:
    - Optimizations:
      - CHANGED: Use Grisu2 for serializing floating point numbers. [Project-OSRM#5188](Project-OSRM#5188)
      - ADDED: Node bindings can return pre-rendered JSON buffer. [Project-OSRM#5189](Project-OSRM#5189)
    - Profiles:
      - CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [Project-OSRM#5076
](Project-OSRM#5076)
      - CHANGED: Foot profile now blacklists barriers instead of whitelisting them [Project-OSRM#5077
](Project-OSRM#5077)
      - CHANGED: Support maxlength and maxweight in car profile [Project-OSRM#5101](Project-OSRM#5101]
    - Bugfixes:
      - FIXED: collapsing of ExitRoundabout instructions [Project-OSRM#5114](Project-OSRM#5114)
    - Misc:
      - CHANGED: Support up to 512 named shared memory regions [Project-OSRM#5185](Project-OSRM#5185)
  • Loading branch information
datendelphin committed Nov 19, 2020
2 parents 2f0f085 + 17e1966 commit 0d12ed8
Show file tree
Hide file tree
Showing 31 changed files with 983 additions and 122 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -13,7 +13,7 @@ notifications:
branches:
only:
- master
- "5.18"
- "5.19"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/

Expand Down
16 changes: 16 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,19 @@
# 5.19.0
- Changes from 5.18.0:
- Optimizations:
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
- ADDED: Node bindings can return pre-rendered JSON buffer. [#5189](https://github.com/Project-OSRM/osrm-backend/pull/5189)
- Profiles:
- CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [#5076
](https://github.com/Project-OSRM/osrm-backend/pull/5076/)
- CHANGED: Foot profile now blacklists barriers instead of whitelisting them [#5077
](https://github.com/Project-OSRM/osrm-backend/pull/5077/)
- CHANGED: Support maxlength and maxweight in car profile [#5101](https://github.com/Project-OSRM/osrm-backend/pull/5101]
- Bugfixes:
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
- Misc:
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)

# 5.18.0
- Changes from 5.17.0:
- Features:
Expand Down
23 changes: 23 additions & 0 deletions docs/nodejs/api.md
Expand Up @@ -297,6 +297,29 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.

## Plugin behaviour

All plugins support a second additional object that is available to configure some NodeJS specific behaviours.

- `plugin_config` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `plugin_config.format` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The format of the result object to various API calls. Valid options are `object` (default), which returns a standard Javascript object, as described above, and `json_buffer`, which will return a NodeJS **[Buffer](https://nodejs.org/api/buffer.html)** object, containing a JSON string. The latter has the advantage that it can be immediately serialized to disk/sent over the network, and the generation of the string is performed outside the main NodeJS event loop. This option is ignored by the `tile` plugin.

**Examples**

```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
};
osrm.route(options, { format: "json_buffer" }, function(err, response) {
if (err) throw err;
console.log(response.toString("utf-8"));
});
```

## Responses

Responses
Expand Down
4 changes: 2 additions & 2 deletions docs/profiles.md
Expand Up @@ -138,7 +138,7 @@ Given an OpenStreetMap way, the `process_way` function will either return nothin
Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
node | The input way to process (read-only).
way | The input way to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `way` is a member.

Expand Down Expand Up @@ -199,7 +199,7 @@ source.lon | Read | Float | Co-ordinates of segment start
source.lat | Read | Float | ""
target.lon | Read | Float | Co-ordinates of segment end
target.lat | Read | Float | ""
target.distance | Read | Float | Length of segment
distance | Read | Float | Length of segment
weight | Read/write | Float | Routing weight for this segment
duration | Read/write | Float | Duration for this segment

Expand Down
2 changes: 1 addition & 1 deletion features/bicycle/barrier.feature
Expand Up @@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x |
| wall | |
| fence | |
| some_tag | |
| some_tag | x |
| block | x |

Scenario: Bike - Access tag trumphs barriers
Expand Down
19 changes: 19 additions & 0 deletions features/car/physical_limitation.feature
Expand Up @@ -48,3 +48,22 @@ Feature: Car - Handle physical limitation
| primary | | none | x |
| primary | | no-sign | x |
| primary | | unsigned | x |

Scenario: Car - Limited by length
Then routability should be
| highway | maxlength | bothw |
| primary | | x |
| primary | 1 | |
| primary | 5 | x |
| primary | unsigned | x |

Scenario: Car - Limited by weight
Then routability should be
| highway | maxweight | bothw |
| primary | | x |
| primary | 1 | |
| primary | 3.5 | x |
| primary | 35000 kg | x |
| primary | 8.9t | x |
| primary | 0.1 lbs | |
| primary | unsigned | x |
2 changes: 1 addition & 1 deletion features/foot/barrier.feature
Expand Up @@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x |
| wall | |
| fence | |
| some_tag | |
| some_tag | x |
| block | x |

Scenario: Foot - Access tag trumphs barriers
Expand Down
73 changes: 68 additions & 5 deletions include/nodejs/node_osrm_support.hpp
Expand Up @@ -2,6 +2,7 @@
#define OSRM_BINDINGS_NODE_SUPPORT_HPP

#include "nodejs/json_v8_renderer.hpp"
#include "util/json_renderer.hpp"

#include "osrm/approach.hpp"
#include "osrm/bearing.hpp"
Expand All @@ -24,6 +25,7 @@
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

Expand All @@ -42,18 +44,35 @@ using match_parameters_ptr = std::unique_ptr<osrm::MatchParameters>;
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;

struct PluginParameters
{
bool renderJSONToBuffer = false;
};

using ObjectOrString = typename mapbox::util::variant<osrm::json::Object, std::string>;

template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);

template <> v8::Local<v8::Value> inline render(const std::string &result)
{
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
}

template <> v8::Local<v8::Value> inline render(const osrm::json::Object &result)
template <> v8::Local<v8::Value> inline render(const ObjectOrString &result)
{
v8::Local<v8::Value> value;
renderToV8(value, result);
return value;
if (result.is<osrm::json::Object>())
{
// Convert osrm::json object tree into matching v8 object tree
v8::Local<v8::Value> value;
renderToV8(value, result.get<osrm::json::Object>());
return value;
}
else
{
// Return the string object as a node Buffer
return Nan::CopyBuffer(result.get<std::string>().data(), result.get<std::string>().size())
.ToLocalChecked();
}
}

inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
Expand Down Expand Up @@ -814,6 +833,50 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
return true;
}

inline PluginParameters
argumentsToPluginParameters(const Nan::FunctionCallbackInfo<v8::Value> &args)
{
if (args.Length() < 3 || !args[1]->IsObject())
{
return {};
}
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[1]).ToLocalChecked();
if (obj->Has(Nan::New("format").ToLocalChecked()))
{

v8::Local<v8::Value> format = obj->Get(Nan::New("format").ToLocalChecked());
if (format.IsEmpty())
{
return {};
}

if (!format->IsString())
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}

const Nan::Utf8String format_utf8str(format);
std::string format_str{*format_utf8str, *format_utf8str + format_utf8str.length()};

if (format_str == "object")
{
return {false};
}
else if (format_str == "json_buffer")
{
return {true};
}
else
{
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
return {};
}
}

return {};
}

inline route_parameters_ptr
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
bool requires_multiple_coordinates)
Expand Down Expand Up @@ -1357,6 +1420,6 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
return params;
}

} // ns node_osrm
} // namespace node_osrm

#endif
19 changes: 9 additions & 10 deletions include/storage/shared_datatype.hpp
Expand Up @@ -26,7 +26,7 @@ namespace serialization
inline void read(io::BufferReader &reader, DataLayout &layout);

inline void write(io::BufferWriter &writer, const DataLayout &layout);
}
} // namespace serialization

namespace detail
{
Expand All @@ -52,7 +52,7 @@ inline std::string trimName(const std::string &name_prefix, const std::string &n
return name;
}
}
}
} // namespace detail

class DataLayout
{
Expand Down Expand Up @@ -165,7 +165,7 @@ struct SharedRegion
static constexpr const int MAX_NAME_LENGTH = 254;

SharedRegion() : name{0}, timestamp{0} {}
SharedRegion(const std::string &name_, std::uint64_t timestamp, std::uint8_t shm_key)
SharedRegion(const std::string &name_, std::uint64_t timestamp, std::uint16_t shm_key)
: name{0}, timestamp{timestamp}, shm_key{shm_key}
{
std::copy_n(name_.begin(), std::min<std::size_t>(MAX_NAME_LENGTH, name_.size()), name);
Expand All @@ -175,14 +175,14 @@ struct SharedRegion

char name[MAX_NAME_LENGTH + 1];
std::uint64_t timestamp;
std::uint8_t shm_key;
std::uint16_t shm_key;
};

// Keeps a list of all shared regions in a fixed-sized struct
// for fast access and deserialization.
struct SharedRegionRegister
{
using RegionID = std::uint8_t;
using RegionID = std::uint16_t;
static constexpr const RegionID INVALID_REGION_ID = std::numeric_limits<RegionID>::max();
using ShmKey = decltype(SharedRegion::shm_key);

Expand Down Expand Up @@ -250,20 +250,19 @@ struct SharedRegionRegister

void ReleaseKey(ShmKey key) { shm_key_in_use[key] = false; }

static constexpr const std::uint8_t MAX_SHARED_REGIONS =
std::numeric_limits<RegionID>::max() - 1;
static constexpr const std::size_t MAX_SHARED_REGIONS = 512;
static_assert(MAX_SHARED_REGIONS < std::numeric_limits<RegionID>::max(),
"Number of shared memory regions needs to be less than the region id size.");

static constexpr const std::uint8_t MAX_SHM_KEYS = std::numeric_limits<std::uint8_t>::max() - 1;
static constexpr const std::size_t MAX_SHM_KEYS = MAX_SHARED_REGIONS * 2;

static constexpr const char *name = "osrm-region";

private:
std::array<SharedRegion, MAX_SHARED_REGIONS> regions;
std::array<bool, MAX_SHM_KEYS> shm_key_in_use;
};
}
}
} // namespace storage
} // namespace osrm

#endif /* SHARED_DATA_TYPE_HPP */
19 changes: 10 additions & 9 deletions include/storage/shared_memory.hpp
Expand Up @@ -34,10 +34,10 @@ namespace storage

struct OSRMLockFile
{
boost::filesystem::path operator()()
template <typename IdentifierT> boost::filesystem::path operator()(const IdentifierT &id)
{
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
boost::filesystem::path lock_file = temp_dir / ("osrm-" + std::to_string(id) + ".lock");
return lock_file;
}
};
Expand Down Expand Up @@ -93,7 +93,7 @@ class SharedMemory
try
{
OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
boost::interprocess::xsi_key key(lock_file(id).string().c_str(), id);
result = RegionExists(key);
}
catch (...)
Expand All @@ -106,7 +106,7 @@ class SharedMemory
template <typename IdentifierT> static bool Remove(const IdentifierT id)
{
OSRMLockFile lock_file;
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
boost::interprocess::xsi_key key(lock_file(id).string().c_str(), id);
return Remove(key);
}

Expand Down Expand Up @@ -287,21 +287,22 @@ class SharedMemory
template <typename IdentifierT, typename LockFileT = OSRMLockFile>
std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint64_t size = 0)
{
static_assert(sizeof(id) == sizeof(std::uint16_t), "Key type is not 16 bits");
try
{
LockFileT lock_file;
if (!boost::filesystem::exists(lock_file()))
if (!boost::filesystem::exists(lock_file(id)))
{
if (0 == size)
{
throw util::exception("lock file does not exist, exiting" + SOURCE_REF);
}
else
{
boost::filesystem::ofstream ofs(lock_file());
boost::filesystem::ofstream ofs(lock_file(id));
}
}
return std::make_unique<SharedMemory>(lock_file(), id, size);
return std::make_unique<SharedMemory>(lock_file(id), id, size);
}
catch (const boost::interprocess::interprocess_exception &e)
{
Expand All @@ -310,7 +311,7 @@ std::unique_ptr<SharedMemory> makeSharedMemory(const IdentifierT &id, const uint
throw util::exception(e.what() + SOURCE_REF);
}
}
}
}
} // namespace storage
} // namespace osrm

#endif // SHARED_MEMORY_HPP
10 changes: 6 additions & 4 deletions include/storage/shared_monitor.hpp
Expand Up @@ -33,7 +33,7 @@ template <class Lock> class InvertedLock
InvertedLock(Lock &lock) : lock(lock) { lock.unlock(); }
~InvertedLock() { lock.lock(); }
};
}
} // namespace

// The shared monitor implementation based on a semaphore and mutex
template <typename Data> struct SharedMonitor
Expand Down Expand Up @@ -146,7 +146,9 @@ template <typename Data> struct SharedMonitor
// like two-turnstile reusable barrier or boost/interprocess/sync/spin/condition.hpp
// fail if a waiter is killed.

static constexpr int buffer_size = 256;
// Buffer size needs to be large enough to hold all the semaphores for every
// listener you want to support.
static constexpr int buffer_size = 4096 * 4;

struct InternalData
{
Expand Down Expand Up @@ -232,8 +234,8 @@ template <typename Data> struct SharedMonitor
bi::shared_memory_object shmem;
bi::mapped_region region;
};
}
}
} // namespace storage
} // namespace osrm

#undef USE_BOOST_INTERPROCESS_CONDITION

Expand Down

0 comments on commit 0d12ed8

Please sign in to comment.