Don't block all requests to switch data

This switchtes the data even if there are requests still running on the
old data. osrm-datastore then waits until all of these old requests have
finished before freeing the old regions.

This also means that osrm-datastore will return with an error if there
is a data update currenlty in progress.
This commit is contained in:
Patrick Niklaus
2016-10-08 01:52:47 +02:00
committed by Patrick Niklaus
parent 1557ff81bc
commit c69545c47a
6 changed files with 150 additions and 85 deletions
+21 -8
View File
@@ -6,6 +6,8 @@
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include <boost/interprocess/sync/named_upgradable_mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/shared_mutex.hpp>
@@ -28,7 +30,8 @@ class DataWatchdog
{
public:
DataWatchdog()
: shared_regions(storage::makeSharedMemoryView(storage::CURRENT_REGIONS)),
: shared_barriers{std::make_shared<storage::SharedBarriers>()},
shared_regions(storage::makeSharedMemoryView(storage::CURRENT_REGIONS)),
current_timestamp{storage::LAYOUT_NONE, storage::DATA_NONE, 0}
{
}
@@ -42,7 +45,8 @@ class DataWatchdog
// Check if it might be worth to try to aquire a exclusive lock
bool HasNewRegion() const
{
const boost::shared_lock<boost::shared_mutex> lock(current_timestamp_mutex);
const boost::interprocess::sharable_lock<boost::interprocess::named_upgradable_mutex> lock(
shared_barriers->current_regions_mutex);
const auto shared_timestamp =
static_cast<const storage::SharedDataTimestamp *>(shared_regions->Ptr());
@@ -59,11 +63,14 @@ class DataWatchdog
// if the update was already done by another thread
void MaybeLoadNewRegion(std::shared_ptr<datafacade::BaseDataFacade> &facade)
{
const boost::lock_guard<boost::shared_mutex> lock(current_timestamp_mutex);
const boost::interprocess::sharable_lock<boost::interprocess::named_upgradable_mutex> lock(
shared_barriers->current_regions_mutex);
const auto shared_timestamp =
static_cast<const storage::SharedDataTimestamp *>(shared_regions->Ptr());
boost::upgrade_lock<boost::shared_mutex> facade_lock(facade_mutex);
// if more then one request tried to aquire the write lock
// we might get overtaken before we actually do the writing
// in that case we don't modify anthing
@@ -75,23 +82,29 @@ class DataWatchdog
// this thread has won and can update the data
else
{
boost::upgrade_to_unique_lock<boost::upgrade_mutex> unique_facade_lock(facade_lock);
current_timestamp = *shared_timestamp;
// TODO remove once we allow for more then one SharedMemoryFacade at the same time
// at this point no other query is allowed to reference this facade!
// the old facade will die exactly here
BOOST_ASSERT(!facade || facade.use_count() == 1);
facade = std::make_shared<datafacade::SharedDataFacade>(
current_timestamp.layout, current_timestamp.data, current_timestamp.timestamp);
facade = std::make_shared<datafacade::SharedDataFacade>(shared_barriers,
current_timestamp.layout,
current_timestamp.data,
current_timestamp.timestamp);
}
}
private:
// mutexes should be mutable even on const objects: This enables
// marking functions as logical const and thread-safe.
std::shared_ptr<storage::SharedBarriers> shared_barriers;
// shared memory table containing pointers to all shared regions
std::unique_ptr<storage::SharedMemory> shared_regions;
// mutexes should be mutable even on const objects: This enables
// marking functions as logical const and thread-safe.
mutable boost::shared_mutex current_timestamp_mutex;
mutable boost::shared_mutex facade_mutex;
storage::SharedDataTimestamp current_timestamp;
};
}
+22 -12
View File
@@ -3,6 +3,7 @@
// implements all data storage when shared memory _IS_ used
#include "storage/shared_barriers.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include "engine/datafacade/datafacade_base.hpp"
@@ -24,8 +25,12 @@
#include "util/static_rtree.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/thread/tss.hpp>
#include <boost/interprocess/sync/named_sharable_mutex.hpp>
#include <boost/interprocess/sync/sharable_lock.hpp>
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <limits>
@@ -34,10 +39,6 @@
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/tss.hpp>
namespace osrm
{
@@ -65,9 +66,11 @@ class SharedDataFacade final : public BaseDataFacade
storage::SharedDataLayout *data_layout;
char *shared_memory;
std::shared_ptr<storage::SharedBarriers> shared_barriers;
storage::SharedDataType layout_region;
storage::SharedDataType data_region;
unsigned shared_timestamp;
boost::interprocess::sharable_lock<boost::interprocess::named_sharable_mutex> regions_lock;
unsigned m_check_sum;
std::unique_ptr<QueryGraph> m_query_graph;
@@ -147,8 +150,7 @@ class SharedDataFacade final : public BaseDataFacade
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();
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?");
}
@@ -382,18 +384,26 @@ class SharedDataFacade final : public BaseDataFacade
public:
virtual ~SharedDataFacade() {}
SharedDataFacade(storage::SharedDataType layout_region_, storage::SharedDataType data_region_, unsigned shared_timestamp_)
: layout_region(layout_region_), data_region(data_region_), shared_timestamp(shared_timestamp_)
SharedDataFacade(const std::shared_ptr<storage::SharedBarriers> &shared_barriers_,
storage::SharedDataType layout_region_,
storage::SharedDataType data_region_,
unsigned shared_timestamp_)
: shared_barriers(shared_barriers_),
layout_region(layout_region_), data_region(data_region_),
shared_timestamp(shared_timestamp_),
regions_lock(layout_region == storage::LAYOUT_1 ? shared_barriers->regions_1_mutex
: shared_barriers->regions_2_mutex)
{
util::SimpleLogger().Write(logDEBUG) << "Loading new data with shared timestamp " << shared_timestamp;
util::SimpleLogger().Write(logDEBUG) << "Loading new data with shared timestamp "
<< shared_timestamp;
BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region));
m_layout_memory = storage::makeOwnedSharedMemoryView(layout_region);
m_layout_memory = storage::makeSharedMemoryView(layout_region);
data_layout = static_cast<storage::SharedDataLayout *>(m_layout_memory->Ptr());
BOOST_ASSERT(storage::SharedMemory::RegionExists(data_region));
m_large_memory = storage::makeOwnedSharedMemoryView(data_region);
m_large_memory = storage::makeSharedMemoryView(data_region);
shared_memory = (char *)(m_large_memory->Ptr());
LoadGraph();