From b376c97db80249feac8ea8ba50b62b7333059d70 Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Fri, 23 Dec 2016 00:18:57 +0100 Subject: [PATCH] Join LAYOUT and DATA shared memory blocks into REGION --- include/engine/data_watchdog.hpp | 29 +++--- .../datafacade/shared_memory_datafacade.hpp | 29 ++---- include/storage/shared_barriers.hpp | 20 ++-- include/storage/shared_datatype.hpp | 36 +++---- src/storage/storage.cpp | 98 ++++++++----------- src/tools/springclean.cpp | 28 ++---- src/tools/store.cpp | 2 +- src/tools/unlock_all_mutexes.cpp | 6 +- 8 files changed, 99 insertions(+), 149 deletions(-) diff --git a/include/engine/data_watchdog.hpp b/include/engine/data_watchdog.hpp index d8e090422..497602fcc 100644 --- a/include/engine/data_watchdog.hpp +++ b/include/engine/data_watchdog.hpp @@ -32,15 +32,15 @@ class DataWatchdog public: DataWatchdog() : shared_barriers{std::make_shared()}, - shared_regions(storage::makeSharedMemory(storage::CURRENT_REGIONS)), - current_timestamp{storage::LAYOUT_NONE, storage::DATA_NONE, 0} + shared_regions(storage::makeSharedMemory(storage::CURRENT_REGION)), + current_timestamp{storage::REGION_NONE, 0} { } // Tries to connect to the shared memory containing the regions table static bool TryConnect() { - return storage::SharedMemory::RegionExists(storage::CURRENT_REGIONS); + return storage::SharedMemory::RegionExists(storage::CURRENT_REGION); } using RegionsLock = @@ -52,22 +52,20 @@ class DataWatchdog LockAndFacade GetDataFacade() { const boost::interprocess::sharable_lock lock( - shared_barriers->current_regions_mutex); + shared_barriers->current_region_mutex); const auto shared_timestamp = static_cast(shared_regions->Ptr()); const auto get_locked_facade = [this, shared_timestamp]() { - if (current_timestamp.data == storage::DATA_1) + if (current_timestamp.region == storage::REGION_1) { - BOOST_ASSERT(current_timestamp.layout == storage::LAYOUT_1); - return std::make_pair(RegionsLock(shared_barriers->regions_1_mutex), facade); + return std::make_pair(RegionsLock(shared_barriers->region_1_mutex), facade); } else { - BOOST_ASSERT(current_timestamp.layout == storage::LAYOUT_2); - BOOST_ASSERT(current_timestamp.data == storage::DATA_2); - return std::make_pair(RegionsLock(shared_barriers->regions_2_mutex), facade); + BOOST_ASSERT(current_timestamp.region == storage::REGION_2); + return std::make_pair(RegionsLock(shared_barriers->region_2_mutex), facade); } }; @@ -78,8 +76,7 @@ class DataWatchdog if (shared_timestamp->timestamp == current_timestamp.timestamp) { - BOOST_ASSERT(shared_timestamp->layout == current_timestamp.layout); - BOOST_ASSERT(shared_timestamp->data == current_timestamp.data); + BOOST_ASSERT(shared_timestamp->region == current_timestamp.region); return get_locked_facade(); } } @@ -89,11 +86,10 @@ class DataWatchdog boost::upgrade_lock facade_lock(facade_mutex); // we might get overtaken before we actually do the writing - // in that case we don't modify anthing + // in that case we don't modify anything if (shared_timestamp->timestamp == current_timestamp.timestamp) { - BOOST_ASSERT(shared_timestamp->layout == current_timestamp.layout); - BOOST_ASSERT(shared_timestamp->data == current_timestamp.data); + BOOST_ASSERT(shared_timestamp->region == current_timestamp.region); return get_locked_facade(); } @@ -103,8 +99,7 @@ class DataWatchdog current_timestamp = *shared_timestamp; facade = std::make_shared(shared_barriers, - current_timestamp.layout, - current_timestamp.data, + current_timestamp.region, current_timestamp.timestamp); return get_locked_facade(); diff --git a/include/engine/datafacade/shared_memory_datafacade.hpp b/include/engine/datafacade/shared_memory_datafacade.hpp index c6fb0bbf9..6908af81a 100644 --- a/include/engine/datafacade/shared_memory_datafacade.hpp +++ b/include/engine/datafacade/shared_memory_datafacade.hpp @@ -24,10 +24,8 @@ class SharedMemoryDataFacade : public ContiguousInternalMemoryDataFacadeBase { protected: - std::unique_ptr m_layout_memory; std::unique_ptr m_large_memory; std::shared_ptr shared_barriers; - storage::SharedDataType layout_region; storage::SharedDataType data_region; unsigned shared_timestamp; @@ -40,12 +38,12 @@ class SharedMemoryDataFacade : public ContiguousInternalMemoryDataFacadeBase { // Now check if this is still the newest dataset boost::interprocess::sharable_lock - current_regions_lock(shared_barriers->current_regions_mutex, + current_regions_lock(shared_barriers->current_region_mutex, boost::interprocess::defer_lock); boost::interprocess::scoped_lock exclusive_lock( - data_region == storage::DATA_1 ? shared_barriers->regions_1_mutex - : shared_barriers->regions_2_mutex, + data_region == storage::REGION_1 ? shared_barriers->region_1_mutex + : shared_barriers->region_2_mutex, boost::interprocess::defer_lock); // if this returns false this is still in use @@ -53,45 +51,36 @@ class SharedMemoryDataFacade : public ContiguousInternalMemoryDataFacadeBase { if (storage::SharedMemory::RegionExists(data_region)) { - BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region)); - - auto shared_regions = storage::makeSharedMemory(storage::CURRENT_REGIONS); + auto shared_region = storage::makeSharedMemory(storage::CURRENT_REGION); const auto current_timestamp = - static_cast(shared_regions->Ptr()); + static_cast(shared_region->Ptr()); // check if the memory region referenced by this facade needs cleanup - if (current_timestamp->data == data_region) + if (current_timestamp->region == data_region) { - BOOST_ASSERT(current_timestamp->layout == layout_region); util::Log(logDEBUG) << "Retaining data with shared timestamp " << shared_timestamp; } else { storage::SharedMemory::Remove(data_region); - storage::SharedMemory::Remove(layout_region); } } } } SharedMemoryDataFacade(const std::shared_ptr &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_) + : shared_barriers(shared_barriers_), data_region(data_region_), shared_timestamp(shared_timestamp_) { util::Log(logDEBUG) << "Loading new data with shared timestamp " << shared_timestamp; - BOOST_ASSERT(storage::SharedMemory::RegionExists(layout_region)); - m_layout_memory = storage::makeSharedMemory(layout_region); - BOOST_ASSERT(storage::SharedMemory::RegionExists(data_region)); m_large_memory = storage::makeSharedMemory(data_region); - InitializeInternalPointers(*reinterpret_cast(m_layout_memory->Ptr()), - reinterpret_cast(m_large_memory->Ptr())); + InitializeInternalPointers(*reinterpret_cast(m_large_memory->Ptr()), + reinterpret_cast(m_large_memory->Ptr()) + sizeof(storage::DataLayout)); } }; } diff --git a/include/storage/shared_barriers.hpp b/include/storage/shared_barriers.hpp index 574bdfaf5..db48cead9 100644 --- a/include/storage/shared_barriers.hpp +++ b/include/storage/shared_barriers.hpp @@ -13,22 +13,22 @@ struct SharedBarriers { SharedBarriers() - : current_regions_mutex(boost::interprocess::open_or_create, "current_regions"), - regions_1_mutex(boost::interprocess::open_or_create, "regions_1"), - regions_2_mutex(boost::interprocess::open_or_create, "regions_2") + : current_region_mutex(boost::interprocess::open_or_create, "current_region"), + region_1_mutex(boost::interprocess::open_or_create, "region_1"), + region_2_mutex(boost::interprocess::open_or_create, "region_2") { } - static void resetCurrentRegions() + static void resetCurrentRegion() { - boost::interprocess::named_sharable_mutex::remove("current_regions"); + boost::interprocess::named_sharable_mutex::remove("current_region"); } - static void resetRegions1() { boost::interprocess::named_sharable_mutex::remove("regions_1"); } - static void resetRegions2() { boost::interprocess::named_sharable_mutex::remove("regions_2"); } + static void resetRegion1() { boost::interprocess::named_sharable_mutex::remove("region_1"); } + static void resetRegion2() { boost::interprocess::named_sharable_mutex::remove("region_2"); } - boost::interprocess::named_upgradable_mutex current_regions_mutex; - boost::interprocess::named_sharable_mutex regions_1_mutex; - boost::interprocess::named_sharable_mutex regions_2_mutex; + boost::interprocess::named_upgradable_mutex current_region_mutex; + boost::interprocess::named_sharable_mutex region_1_mutex; + boost::interprocess::named_sharable_mutex region_2_mutex; }; } } diff --git a/include/storage/shared_datatype.hpp b/include/storage/shared_datatype.hpp index e55937ff3..f38799fda 100644 --- a/include/storage/shared_datatype.hpp +++ b/include/storage/shared_datatype.hpp @@ -192,19 +192,15 @@ struct DataLayout enum SharedDataType { - CURRENT_REGIONS, - LAYOUT_1, - DATA_1, - LAYOUT_2, - DATA_2, - LAYOUT_NONE, - DATA_NONE + CURRENT_REGION, + REGION_1, + REGION_2, + REGION_NONE }; struct SharedDataTimestamp { - SharedDataType layout; - SharedDataType data; + SharedDataType region; unsigned timestamp; }; @@ -212,20 +208,14 @@ inline std::string regionToString(const SharedDataType region) { switch (region) { - case CURRENT_REGIONS: - 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"; - case DATA_NONE: - return "DATA_NONE"; + case CURRENT_REGION: + return "CURRENT_REGION"; + case REGION_1: + return "REGION_1"; + case REGION_2: + return "REGION_2"; + case REGION_NONE: + return "REGION_NONE"; default: return "INVALID_REGION"; } diff --git a/src/storage/storage.cpp b/src/storage/storage.cpp index 47c00fda8..777c6371f 100644 --- a/src/storage/storage.cpp +++ b/src/storage/storage.cpp @@ -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 ¤t_regions_mutex; - SharedDataType old_layout_region; + boost::interprocess::named_sharable_mutex ¤t_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(shared_regions->Ptr()); - if (shared_timestamp->data == DATA_1) + static_cast(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 - 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 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(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(data_type_memory->Ptr()); { boost::interprocess::scoped_lock - 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( - 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( - 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."; diff --git a/src/tools/springclean.cpp b/src/tools/springclean.cpp index 2ae1ec62a..d05ff35a5 100644 --- a/src/tools/springclean.cpp +++ b/src/tools/springclean.cpp @@ -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); } } } diff --git a/src/tools/store.cpp b/src/tools/store.cpp index 8d1782af1..6729b35db 100644 --- a/src/tools/store.cpp +++ b/src/tools/store.cpp @@ -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); } diff --git a/src/tools/unlock_all_mutexes.cpp b/src/tools/unlock_all_mutexes.cpp index bdda90d3b..4c3a534e6 100644 --- a/src/tools/unlock_all_mutexes.cpp +++ b/src/tools/unlock_all_mutexes.cpp @@ -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; }