Join LAYOUT and DATA shared memory blocks into REGION

This commit is contained in:
Michael Krasnyk
2016-12-23 00:18:57 +01:00
committed by Patrick Niklaus
parent 7b11cd3a11
commit b376c97db8
8 changed files with 99 additions and 149 deletions
+41 -57
View File
@@ -58,38 +58,31 @@ Storage::Storage(StorageConfig config_) : config(std::move(config_)) {}
struct RegionsLayout
{
SharedDataType current_layout_region;
SharedDataType current_data_region;
boost::interprocess::named_sharable_mutex &current_regions_mutex;
SharedDataType old_layout_region;
boost::interprocess::named_sharable_mutex &current_region_mutex;
SharedDataType old_data_region;
boost::interprocess::named_sharable_mutex &old_regions_mutex;
boost::interprocess::named_sharable_mutex &old_region_mutex;
};
RegionsLayout getRegionsLayout(SharedBarriers &barriers)
{
if (SharedMemory::RegionExists(CURRENT_REGIONS))
if (SharedMemory::RegionExists(CURRENT_REGION))
{
auto shared_regions = makeSharedMemory(CURRENT_REGIONS);
auto shared_region = makeSharedMemory(CURRENT_REGION);
const auto shared_timestamp =
static_cast<const SharedDataTimestamp *>(shared_regions->Ptr());
if (shared_timestamp->data == DATA_1)
static_cast<const SharedDataTimestamp *>(shared_region->Ptr());
if (shared_timestamp->region == REGION_1)
{
BOOST_ASSERT(shared_timestamp->layout == LAYOUT_1);
return RegionsLayout{LAYOUT_1,
DATA_1,
barriers.regions_1_mutex,
LAYOUT_2,
DATA_2,
barriers.regions_2_mutex};
return RegionsLayout{REGION_1,
barriers.region_1_mutex,
REGION_2,
barriers.region_2_mutex};
}
BOOST_ASSERT(shared_timestamp->data == DATA_2);
BOOST_ASSERT(shared_timestamp->layout == LAYOUT_2);
BOOST_ASSERT(shared_timestamp->region == REGION_2);
}
return RegionsLayout{
LAYOUT_2, DATA_2, barriers.regions_2_mutex, LAYOUT_1, DATA_1, barriers.regions_1_mutex};
return RegionsLayout{REGION_2, barriers.region_2_mutex, REGION_1, barriers.region_1_mutex};
}
Storage::ReturnCode Storage::Run(int max_wait)
@@ -101,10 +94,10 @@ Storage::ReturnCode Storage::Run(int max_wait)
SharedBarriers barriers;
boost::interprocess::upgradable_lock<boost::interprocess::named_upgradable_mutex>
current_regions_lock(barriers.current_regions_mutex, boost::interprocess::defer_lock);
current_region_lock(barriers.current_region_mutex, boost::interprocess::defer_lock);
try
{
if (!current_regions_lock.try_lock())
if (!current_region_lock.try_lock())
{
util::Log(logWARNING) << "A data update is in progress";
return ReturnCode::Error;
@@ -113,7 +106,7 @@ Storage::ReturnCode Storage::Run(int max_wait)
// hard unlock in case of any exception.
catch (boost::interprocess::lock_exception &ex)
{
barriers.current_regions_mutex.unlock_upgradable();
barriers.current_region_mutex.unlock_upgradable();
// make sure we exit here because this is bad
throw;
}
@@ -128,7 +121,6 @@ Storage::ReturnCode Storage::Run(int max_wait)
#endif
auto regions_layout = getRegionsLayout(barriers);
const SharedDataType layout_region = regions_layout.old_layout_region;
const SharedDataType data_region = regions_layout.old_data_region;
if (max_wait > 0)
@@ -142,7 +134,7 @@ Storage::ReturnCode Storage::Run(int max_wait)
}
boost::interprocess::scoped_lock<boost::interprocess::named_sharable_mutex> regions_lock(
regions_layout.old_regions_mutex, boost::interprocess::defer_lock);
regions_layout.old_region_mutex, boost::interprocess::defer_lock);
if (max_wait > 0)
{
@@ -152,16 +144,14 @@ Storage::ReturnCode Storage::Run(int max_wait)
util::Log(logWARNING) << "Queries did not finish in " << max_wait
<< " seconds. Claiming the lock by force.";
// WARNING: if queries are still using the old dataset they might crash
if (regions_layout.old_layout_region == LAYOUT_1)
if (regions_layout.old_data_region == REGION_1)
{
BOOST_ASSERT(regions_layout.old_data_region == DATA_1);
barriers.resetRegions1();
barriers.resetRegion1();
}
else
{
BOOST_ASSERT(regions_layout.old_layout_region == LAYOUT_2);
BOOST_ASSERT(regions_layout.old_data_region == DATA_2);
barriers.resetRegions2();
BOOST_ASSERT(regions_layout.old_data_region == REGION_2);
barriers.resetRegion2();
}
return ReturnCode::Retry;
@@ -174,70 +164,64 @@ Storage::ReturnCode Storage::Run(int max_wait)
util::Log() << "Ok.";
// since we can't change the size of a shared memory regions we delete and reallocate
if (SharedMemory::RegionExists(layout_region) && !SharedMemory::Remove(layout_region))
{
throw util::exception("Could not remove shared memory region " +
regionToString(layout_region) + SOURCE_REF);
}
if (SharedMemory::RegionExists(data_region) && !SharedMemory::Remove(data_region))
{
throw util::exception("Could not remove shared memory region " +
regionToString(data_region) + SOURCE_REF);
}
// Allocate a memory layout in shared memory
auto layout_memory = makeSharedMemory(layout_region, sizeof(DataLayout), true);
auto shared_layout_ptr = new (layout_memory->Ptr()) DataLayout();
// Populate a memory layout into stack memory
DataLayout layout;
PopulateLayout(layout);
PopulateLayout(*shared_layout_ptr);
// Allocate shared memory block
auto regions_size = sizeof(layout) + layout.GetSizeOfLayout();
util::Log() << "allocating shared memory of " << regions_size << " bytes";
auto shared_memory = makeSharedMemory(data_region, regions_size, true);
// allocate shared memory block
util::Log() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout()
<< " bytes";
auto shared_memory = makeSharedMemory(data_region, shared_layout_ptr->GetSizeOfLayout(), true);
// Copy memory layout to shared memory and populate data
char *shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
memcpy(shared_memory_ptr, &layout, sizeof(layout));
PopulateData(layout, shared_memory_ptr + sizeof(layout));
PopulateData(*shared_layout_ptr, shared_memory_ptr);
auto data_type_memory = makeSharedMemory(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true);
auto data_type_memory = makeSharedMemory(CURRENT_REGION, sizeof(SharedDataTimestamp), true);
SharedDataTimestamp *data_timestamp_ptr =
static_cast<SharedDataTimestamp *>(data_type_memory->Ptr());
{
boost::interprocess::scoped_lock<boost::interprocess::named_upgradable_mutex>
current_regions_exclusive_lock;
current_region_exclusive_lock;
if (max_wait > 0)
{
util::Log() << "Waiting for " << max_wait << " seconds to write new dataset timestamp";
auto end_time = boost::posix_time::microsec_clock::universal_time() +
boost::posix_time::seconds(max_wait);
current_regions_exclusive_lock =
current_region_exclusive_lock =
boost::interprocess::scoped_lock<boost::interprocess::named_upgradable_mutex>(
std::move(current_regions_lock), end_time);
std::move(current_region_lock), end_time);
if (!current_regions_exclusive_lock.owns())
if (!current_region_exclusive_lock.owns())
{
util::Log(logWARNING) << "Aquiring the lock timed out after " << max_wait
<< " seconds. Claiming the lock by force.";
current_regions_lock.unlock();
current_regions_lock.release();
storage::SharedBarriers::resetCurrentRegions();
current_region_lock.unlock();
current_region_lock.release();
storage::SharedBarriers::resetCurrentRegion();
return ReturnCode::Retry;
}
}
else
{
util::Log() << "Waiting to write new dataset timestamp";
current_regions_exclusive_lock =
current_region_exclusive_lock =
boost::interprocess::scoped_lock<boost::interprocess::named_upgradable_mutex>(
std::move(current_regions_lock));
std::move(current_region_lock));
}
util::Log() << "Ok.";
data_timestamp_ptr->layout = layout_region;
data_timestamp_ptr->data = data_region;
data_timestamp_ptr->region = data_region;
data_timestamp_ptr->timestamp += 1;
}
util::Log() << "All data loaded.";
+10 -18
View File
@@ -19,20 +19,14 @@ void deleteRegion(const SharedDataType region)
const std::string name = [&] {
switch (region)
{
case CURRENT_REGIONS:
case CURRENT_REGION:
return "CURRENT_REGIONS";
case LAYOUT_1:
return "LAYOUT_1";
case DATA_1:
return "DATA_1";
case LAYOUT_2:
return "LAYOUT_2";
case DATA_2:
return "DATA_2";
case LAYOUT_NONE:
return "LAYOUT_NONE";
default: // DATA_NONE:
return "DATA_NONE";
case REGION_1:
return "REGION_1";
case REGION_2:
return "REGION_2";
default: // REGION_NONE:
return "REGION_NONE";
}
}();
@@ -44,11 +38,9 @@ void deleteRegion(const SharedDataType region)
void springclean()
{
util::Log() << "spring-cleaning all shared memory regions";
deleteRegion(DATA_1);
deleteRegion(LAYOUT_1);
deleteRegion(DATA_2);
deleteRegion(LAYOUT_2);
deleteRegion(CURRENT_REGIONS);
deleteRegion(REGION_1);
deleteRegion(REGION_2);
deleteRegion(CURRENT_REGION);
}
}
}
+1 -1
View File
@@ -93,7 +93,7 @@ bool generateDataStoreOptions(const int argc,
[[ noreturn ]] void CleanupSharedBarriers(int signum)
{ // Here the lock state of named mutexes is unknown, make a hard cleanup
osrm::storage::SharedBarriers::resetCurrentRegions();
osrm::storage::SharedBarriers::resetCurrentRegion();
std::_Exit(128 + signum);
}
+3 -3
View File
@@ -8,9 +8,9 @@ int main()
osrm::util::LogPolicy::GetInstance().Unmute();
osrm::util::Log() << "Releasing all locks";
osrm::storage::SharedBarriers::resetCurrentRegions();
osrm::storage::SharedBarriers::resetRegions1();
osrm::storage::SharedBarriers::resetRegions2();
osrm::storage::SharedBarriers::resetCurrentRegion();
osrm::storage::SharedBarriers::resetRegion1();
osrm::storage::SharedBarriers::resetRegion2();
return 0;
}