diff options
-rw-r--r-- | map/bookmark_manager.cpp | 28 | ||||
-rw-r--r-- | map/bookmark_manager.hpp | 2 | ||||
-rw-r--r-- | map/user_mark_id_storage.cpp | 51 | ||||
-rw-r--r-- | map/user_mark_id_storage.hpp | 13 |
4 files changed, 80 insertions, 14 deletions
diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 575569ed63..431ce1b022 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -1336,11 +1336,10 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection, bool auto & fileData = *data.second; auto & categoryData = fileData.m_categoryData; - if ((categoryData.m_id != kml::kInvalidMarkGroupId) && - (UserMarkIdStorage::Instance().IsJustCreated() || - fileData.m_deviceId != GetPlatform().UniqueClientId())) + if (!UserMarkIdStorage::Instance().CheckIds(fileData) || HasDuplicatedIds(fileData)) { LOG(LINFO, ("Bookmarks ids were reset for file", fileName)); + //TODO: notify subscribers(like search subsystem). This KML could have been indexed. ResetIds(fileData); } @@ -1395,6 +1394,29 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection, bool } } +bool BookmarkManager::HasDuplicatedIds(kml::FileData const & fileData) const +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + if (fileData.m_categoryData.m_id == kml::kInvalidMarkGroupId) + return false; + + if (m_categories.find(fileData.m_categoryData.m_id) != m_categories.cend()) + return true; + + for (auto const & b : fileData.m_bookmarksData) + { + if (m_bookmarks.count(b.m_id) > 0) + return true; + } + + for (auto const & t : fileData.m_tracksData) + { + if (m_tracks.count(t.m_id) > 0) + return true; + } + return false; +} + std::unique_ptr<kml::FileData> BookmarkManager::CollectBmGroupKMLData(BookmarkCategory const * group) const { auto kmlData = std::make_unique<kml::FileData>(); diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 8a69608d1e..f85c9f1af1 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -443,6 +443,8 @@ private: bool CanConvert() const; void FinishConversion(ConversionHandler const & handler, bool result); + bool HasDuplicatedIds(kml::FileData const & fileData) const; + ThreadChecker m_threadChecker; Callbacks m_callbacks; diff --git a/map/user_mark_id_storage.cpp b/map/user_mark_id_storage.cpp index b9ee26b049..62ca1a9654 100644 --- a/map/user_mark_id_storage.cpp +++ b/map/user_mark_id_storage.cpp @@ -14,10 +14,10 @@ std::string const kLastBookmarkCategoryId = "LastBookmarkCategoryId"; } // namespace UserMarkIdStorage::UserMarkIdStorage() - : m_isJustCreated(false) - , m_lastUserMarkId(0) + : m_lastUserMarkId(0) { - m_isJustCreated = !(HasKey(kLastBookmarkCategoryId) && HasKey(kLastBookmarkId) && HasKey(kLastTrackId)); + m_isJustCreated = !(HasKey(kLastBookmarkCategoryId) && HasKey(kLastBookmarkId) && + HasKey(kLastTrackId)); if (m_isJustCreated) { ResetCategoryId(); @@ -30,6 +30,11 @@ UserMarkIdStorage::UserMarkIdStorage() LoadLastTrackId(); LoadLastCategoryId(); } + + m_initialLastBookmarkId = m_lastBookmarkId; + m_initialLastTrackId = m_lastTrackId; + m_initialLastCategoryId = m_lastCategoryId; + LOG(LINFO, ("lastBookmarkId =", m_lastBookmarkId, "lastTrackId =", m_lastTrackId, "lastCategoryId =", m_lastCategoryId)); } @@ -47,11 +52,6 @@ UserMark::Type UserMarkIdStorage::GetMarkType(kml::MarkId id) return static_cast<UserMark::Type>(id >> (sizeof(id) * 8 - kMarkIdTypeBitsCount)); } -bool UserMarkIdStorage::IsJustCreated() const -{ - return m_isJustCreated; -} - void UserMarkIdStorage::ResetBookmarkId() { m_lastBookmarkId = 0; @@ -73,6 +73,41 @@ void UserMarkIdStorage::ResetCategoryId() LOG(LINFO, ("Reset category id")); } +bool UserMarkIdStorage::CheckIds(kml::FileData const & fileData) const +{ + // File has no ids. Check passed. + if (fileData.m_categoryData.m_id == kml::kInvalidMarkGroupId) + return true; + + // Storage is just created. Check failed. + if (m_isJustCreated) + return false; + + // File was created on another device. Check failed. + if (fileData.m_deviceId != GetPlatform().UniqueClientId()) + return false; + + // There are ids of categories, bookmarks or tracks with values + // more than last stored maximums. Check failed. + if (fileData.m_categoryData.m_id > m_initialLastCategoryId) + return false; + + for (auto const & b : fileData.m_bookmarksData) + { + if (b.m_id > m_initialLastBookmarkId) + return false; + } + + for (auto const & t : fileData.m_tracksData) + { + if (t.m_id > m_initialLastTrackId) + return false; + } + + // No one corner case. Check passed. + return true; +} + kml::MarkId UserMarkIdStorage::GetNextUserMarkId(UserMark::Type type) { static_assert(UserMark::Type::USER_MARK_TYPES_COUNT <= (1 << kMarkIdTypeBitsCount), diff --git a/map/user_mark_id_storage.hpp b/map/user_mark_id_storage.hpp index c23457b99f..9d0a00feab 100644 --- a/map/user_mark_id_storage.hpp +++ b/map/user_mark_id_storage.hpp @@ -2,6 +2,8 @@ #include "map/user_mark.hpp" +#include "kml/types.hpp" + #include <atomic> class UserMarkIdStorage @@ -11,12 +13,12 @@ public: static UserMark::Type GetMarkType(kml::MarkId id); - bool IsJustCreated() const; - kml::MarkId GetNextUserMarkId(UserMark::Type type); kml::TrackId GetNextTrackId(); kml::MarkGroupId GetNextCategoryId(); + bool CheckIds(kml::FileData const & fileData) const; + void ResetBookmarkId(); void ResetTrackId(); void ResetCategoryId(); @@ -37,12 +39,17 @@ private: bool HasKey(std::string const & name); - std::atomic<bool> m_isJustCreated; + bool m_isJustCreated; + //TODO: do we really need atomics here? std::atomic<uint64_t> m_lastBookmarkId; std::atomic<uint64_t> m_lastTrackId; std::atomic<uint64_t> m_lastUserMarkId; std::atomic<uint64_t> m_lastCategoryId; + uint64_t m_initialLastBookmarkId; + uint64_t m_initialLastTrackId; + uint64_t m_initialLastCategoryId; + bool m_testModeEnabled = false; }; |