Adds a shared/exclusive lock around queries and CheckAndReloadFacade.
Without this, it's possible for CheckAndReloadFacade to start working while a query is still in progress, leading to undefined behaviour.
This commit is contained in:
parent
80b897d8cf
commit
e21eaa4b9e
@ -223,6 +223,8 @@ template <class EdgeDataT> class SharedDataFacade final : public BaseDataFacade<
|
|||||||
public:
|
public:
|
||||||
virtual ~SharedDataFacade() {}
|
virtual ~SharedDataFacade() {}
|
||||||
|
|
||||||
|
boost::shared_mutex data_mutex;
|
||||||
|
|
||||||
SharedDataFacade()
|
SharedDataFacade()
|
||||||
{
|
{
|
||||||
if (!datastore::SharedMemory::RegionExists(CURRENT_REGIONS))
|
if (!datastore::SharedMemory::RegionExists(CURRENT_REGIONS))
|
||||||
@ -243,57 +245,76 @@ template <class EdgeDataT> class SharedDataFacade final : public BaseDataFacade<
|
|||||||
void CheckAndReloadFacade()
|
void CheckAndReloadFacade()
|
||||||
{
|
{
|
||||||
if (CURRENT_LAYOUT != data_timestamp_ptr->layout ||
|
if (CURRENT_LAYOUT != data_timestamp_ptr->layout ||
|
||||||
CURRENT_DATA != data_timestamp_ptr->data)
|
CURRENT_DATA != data_timestamp_ptr->data ||
|
||||||
|
CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp)
|
||||||
{
|
{
|
||||||
// release the previous shared memory segments
|
|
||||||
datastore::SharedMemory::Remove(CURRENT_LAYOUT);
|
|
||||||
datastore::SharedMemory::Remove(CURRENT_DATA);
|
|
||||||
|
|
||||||
CURRENT_LAYOUT = data_timestamp_ptr->layout;
|
// Get exclusive lock
|
||||||
CURRENT_DATA = data_timestamp_ptr->data;
|
util::SimpleLogger().Write(logDEBUG) << "Updates available, getting exclusive lock";
|
||||||
CURRENT_TIMESTAMP = 0; // Force trigger a reload
|
boost::unique_lock<boost::shared_mutex> lock(data_mutex);
|
||||||
}
|
|
||||||
|
|
||||||
if (CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp)
|
if (CURRENT_LAYOUT != data_timestamp_ptr->layout ||
|
||||||
{
|
CURRENT_DATA != data_timestamp_ptr->data)
|
||||||
CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp;
|
|
||||||
m_layout_memory.reset(datastore::SharedMemoryFactory::Get(CURRENT_LAYOUT));
|
|
||||||
|
|
||||||
data_layout = (SharedDataLayout *)(m_layout_memory->Ptr());
|
|
||||||
|
|
||||||
m_large_memory.reset(datastore::SharedMemoryFactory::Get(CURRENT_DATA));
|
|
||||||
shared_memory = (char *)(m_large_memory->Ptr());
|
|
||||||
|
|
||||||
const char *file_index_ptr =
|
|
||||||
data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::FILE_INDEX_PATH);
|
|
||||||
file_index_path = boost::filesystem::path(file_index_ptr);
|
|
||||||
if (!boost::filesystem::exists(file_index_path))
|
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logDEBUG) << "Leaf file name "
|
// release the previous shared memory segments
|
||||||
<< file_index_path.string();
|
datastore::SharedMemory::Remove(CURRENT_LAYOUT);
|
||||||
throw util::exception("Could not load leaf index file. "
|
datastore::SharedMemory::Remove(CURRENT_DATA);
|
||||||
"Is any data loaded into shared memory?");
|
|
||||||
|
CURRENT_LAYOUT = data_timestamp_ptr->layout;
|
||||||
|
CURRENT_DATA = data_timestamp_ptr->data;
|
||||||
|
CURRENT_TIMESTAMP = 0; // Force trigger a reload
|
||||||
|
|
||||||
|
util::SimpleLogger().Write(logDEBUG) << "Current layout was different to new layout, swapping";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write(logDEBUG) << "Current layout was same to new layout, not swapping";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadGraph();
|
if (CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp)
|
||||||
LoadChecksum();
|
|
||||||
LoadNodeAndEdgeInformation();
|
|
||||||
LoadGeometries();
|
|
||||||
LoadTimestamp();
|
|
||||||
LoadViaNodeList();
|
|
||||||
LoadNames();
|
|
||||||
LoadCoreInformation();
|
|
||||||
|
|
||||||
data_layout->PrintInformation();
|
|
||||||
|
|
||||||
util::SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size();
|
|
||||||
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
|
|
||||||
{
|
{
|
||||||
if (!GetCoordinateOfNode(i).IsValid())
|
CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp;
|
||||||
|
|
||||||
|
util::SimpleLogger().Write(logDEBUG) << "Performing data reload";
|
||||||
|
m_layout_memory.reset(datastore::SharedMemoryFactory::Get(CURRENT_LAYOUT));
|
||||||
|
|
||||||
|
data_layout = (SharedDataLayout *) (m_layout_memory->Ptr());
|
||||||
|
|
||||||
|
m_large_memory.reset(datastore::SharedMemoryFactory::Get(CURRENT_DATA));
|
||||||
|
shared_memory = (char *) (m_large_memory->Ptr());
|
||||||
|
|
||||||
|
const char *file_index_ptr =
|
||||||
|
data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::FILE_INDEX_PATH);
|
||||||
|
file_index_path = boost::filesystem::path(file_index_ptr);
|
||||||
|
if (!boost::filesystem::exists(file_index_path)) {
|
||||||
|
util::SimpleLogger().Write(logDEBUG) << "Leaf file name "
|
||||||
|
<< file_index_path.string();
|
||||||
|
throw util::exception("Could not load leaf index file. "
|
||||||
|
"Is any data loaded into shared memory?");
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadGraph();
|
||||||
|
LoadChecksum();
|
||||||
|
LoadNodeAndEdgeInformation();
|
||||||
|
LoadGeometries();
|
||||||
|
LoadTimestamp();
|
||||||
|
LoadViaNodeList();
|
||||||
|
LoadNames();
|
||||||
|
LoadCoreInformation();
|
||||||
|
|
||||||
|
data_layout->PrintInformation();
|
||||||
|
|
||||||
|
util::SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size();
|
||||||
|
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write() << "coordinate " << i << " not valid";
|
if (!GetCoordinateOfNode(i).IsValid())
|
||||||
|
{
|
||||||
|
util::SimpleLogger().Write() << "coordinate " << i << " not valid";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
util::SimpleLogger().Write(logDEBUG) << "Releasing exclusive lock";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,18 @@ int OSRM::OSRM_impl::RunQuery(const RouteParameters &route_parameters,
|
|||||||
return 400;
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osrm::engine::plugins::BasePlugin::Status return_code;
|
||||||
increase_concurrent_query_count();
|
increase_concurrent_query_count();
|
||||||
auto return_code = plugin_iterator->second->HandleRequest(route_parameters, json_result);
|
if (barrier) {
|
||||||
|
// Get a shared data lock so that other threads won't update
|
||||||
|
// things while the query is running
|
||||||
|
boost::shared_lock<boost::shared_mutex> data_lock{
|
||||||
|
(static_cast<datafacade::SharedDataFacade<contractor::QueryEdge::EdgeData> *>(
|
||||||
|
query_data_facade))->data_mutex};
|
||||||
|
return_code = plugin_iterator->second->HandleRequest(route_parameters, json_result);
|
||||||
|
} else {
|
||||||
|
return_code = plugin_iterator->second->HandleRequest(route_parameters, json_result);
|
||||||
|
}
|
||||||
decrease_concurrent_query_count();
|
decrease_concurrent_query_count();
|
||||||
return static_cast<int>(return_code);
|
return static_cast<int>(return_code);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user