copy dummy cache over implement retrievePackedPathFromSearchSpace calculate packed_path_from_source_to_middle debugging the retrievePackedPathFromSearchSpace function implementation adding in packed_path_from_source_to_middle cache is partway working unpack path and get duration that way the computeDurationForEdge method comment out cache clean up the code move vector creation and allocation to outside of loop hack to not return vectors on facade.GetUncompressedForwardDurations and facade.GetUncompressedReverseDurations clean up hack add exclude_index to cache key clearing cache with timestamp rebase against vectors->range pr swapped out unordered_map cache with a boost_lru implementation calculation for cache size cleaned up comment about cache size calculations unit tests cache uses unsigned char for exclude index clean up cache and unit tests
159 lines
5.4 KiB
C++
159 lines
5.4 KiB
C++
#ifndef OSRM_ENGINE_DATAFACADE_FACTORY_HPP
|
|
#define OSRM_ENGINE_DATAFACADE_FACTORY_HPP
|
|
|
|
#include "extractor/class_data.hpp"
|
|
#include "extractor/profile_properties.hpp"
|
|
|
|
#include "engine/algorithm.hpp"
|
|
#include "engine/api/base_parameters.hpp"
|
|
#include "engine/api/tile_parameters.hpp"
|
|
|
|
#include "util/integer_range.hpp"
|
|
|
|
#include "storage/shared_datatype.hpp"
|
|
|
|
#include <array>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
|
|
namespace osrm
|
|
{
|
|
namespace engine
|
|
{
|
|
// This class selects the right facade for
|
|
template <template <typename A> class FacadeT, typename AlgorithmT> class DataFacadeFactory
|
|
{
|
|
static constexpr auto has_exclude_flags = routing_algorithms::HasExcludeFlags<AlgorithmT>{};
|
|
|
|
public:
|
|
using Facade = FacadeT<AlgorithmT>;
|
|
DataFacadeFactory() = default;
|
|
|
|
template <typename AllocatorT>
|
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, unsigned timestamp)
|
|
: DataFacadeFactory(allocator, has_exclude_flags, timestamp)
|
|
{
|
|
BOOST_ASSERT_MSG(facades.size() >= 1, "At least one datafacade is needed");
|
|
}
|
|
|
|
template <typename ParameterT> std::shared_ptr<const Facade> Get(const ParameterT ¶ms) const
|
|
{
|
|
return Get(params, has_exclude_flags);
|
|
}
|
|
|
|
private:
|
|
// Algorithm with exclude flags
|
|
template <typename AllocatorT>
|
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::true_type, unsigned timestamp)
|
|
{
|
|
const auto &index = allocator->GetIndex();
|
|
properties = index.template GetBlockPtr<extractor::ProfileProperties>("/common/properties");
|
|
const auto &metric_name = properties->GetWeightName();
|
|
|
|
std::vector<std::string> exclude_prefixes;
|
|
auto exclude_path = std::string("/") + routing_algorithms::identifier<AlgorithmT>() +
|
|
std::string("/metrics/") + metric_name + "/exclude/";
|
|
index.List(exclude_path, std::back_inserter(exclude_prefixes));
|
|
facades.resize(exclude_prefixes.size());
|
|
|
|
if (facades.empty())
|
|
{
|
|
throw util::exception(std::string("Could not find any metrics for ") +
|
|
routing_algorithms::name<AlgorithmT>() +
|
|
" in the data. Did you load the right dataset?");
|
|
}
|
|
|
|
for (const auto &exclude_prefix : exclude_prefixes)
|
|
{
|
|
auto index_begin = exclude_prefix.find_last_of("/");
|
|
BOOST_ASSERT_MSG(index_begin != std::string::npos,
|
|
"The exclude prefix needs to be a valid data path.");
|
|
std::size_t index =
|
|
std::stoi(exclude_prefix.substr(index_begin + 1, exclude_prefix.size()));
|
|
BOOST_ASSERT(index >= 0 && index < facades.size());
|
|
facades[index] = std::make_shared<const Facade>(allocator, metric_name, index, timestamp);
|
|
}
|
|
|
|
for (const auto index : util::irange<std::size_t>(0, properties->class_names.size()))
|
|
{
|
|
const std::string name = properties->GetClassName(index);
|
|
if (!name.empty())
|
|
{
|
|
name_to_class[name] = extractor::getClassData(index);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Algorithm without exclude flags
|
|
template <typename AllocatorT>
|
|
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::false_type, unsigned timestamp)
|
|
{
|
|
const auto &index = allocator->GetIndex();
|
|
properties = index.template GetBlockPtr<extractor::ProfileProperties>("/common/properties");
|
|
const auto &metric_name = properties->GetWeightName();
|
|
facades.push_back(std::make_shared<const Facade>(allocator, metric_name, 0, timestamp));
|
|
}
|
|
|
|
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::false_type) const
|
|
{
|
|
return facades[0];
|
|
}
|
|
|
|
// Default for non-exclude flags: return only facade
|
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms, std::false_type) const
|
|
{
|
|
if (!params.exclude.empty())
|
|
{
|
|
return {};
|
|
}
|
|
|
|
return facades[0];
|
|
}
|
|
|
|
// TileParameters don't drive from BaseParameters and generally don't have use for exclude flags
|
|
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::true_type) const
|
|
{
|
|
return facades[0];
|
|
}
|
|
|
|
// Selection logic for finding the corresponding datafacade for the given parameters
|
|
std::shared_ptr<const Facade> Get(const api::BaseParameters ¶ms, std::true_type) const
|
|
{
|
|
if (params.exclude.empty())
|
|
return facades[0];
|
|
|
|
extractor::ClassData mask = 0;
|
|
for (const auto &name : params.exclude)
|
|
{
|
|
auto class_mask_iter = name_to_class.find(name);
|
|
if (class_mask_iter == name_to_class.end())
|
|
{
|
|
return {};
|
|
}
|
|
else
|
|
{
|
|
mask |= class_mask_iter->second;
|
|
}
|
|
}
|
|
|
|
auto exclude_iter = std::find(
|
|
properties->excludable_classes.begin(), properties->excludable_classes.end(), mask);
|
|
if (exclude_iter != properties->excludable_classes.end())
|
|
{
|
|
auto exclude_index =
|
|
std::distance(properties->excludable_classes.begin(), exclude_iter);
|
|
return facades[exclude_index];
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::vector<std::shared_ptr<const Facade>> facades;
|
|
std::unordered_map<std::string, extractor::ClassData> name_to_class;
|
|
const extractor::ProfileProperties *properties = nullptr;
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|