diff options
author | vng <viktor.govako@gmail.com> | 2012-07-09 01:49:35 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 01:40:44 +0300 |
commit | c4c866b1dea0e1205e9da45a0eb7c7d290dcaffb (patch) | |
tree | 220f707849b0a18c5c9e0829d236656a21feecc9 /indexer | |
parent | 5f04609fff0976ad1e45902beefd8b8bef93beaa (diff) |
Refactoring of maps update after downloading:
- Delay maps deleting and updating if mwm is busy;
- Fix bugs with different mwm maps status;
- Add better function for country bounds;
- Simplify Storage logic;
Diffstat (limited to 'indexer')
-rw-r--r-- | indexer/index.cpp | 83 | ||||
-rw-r--r-- | indexer/index.hpp | 9 | ||||
-rw-r--r-- | indexer/indexer_tests/mwm_set_test.cpp | 28 | ||||
-rw-r--r-- | indexer/mwm_set.cpp | 143 | ||||
-rw-r--r-- | indexer/mwm_set.hpp | 79 |
5 files changed, 238 insertions, 104 deletions
diff --git a/indexer/index.cpp b/indexer/index.cpp index 42536b6d75..69de20d718 100644 --- a/indexer/index.cpp +++ b/indexer/index.cpp @@ -3,6 +3,8 @@ #include "../platform/platform.hpp" +#include "../coding/internal/file_data.hpp" + MwmValue::MwmValue(string const & name) : m_cont(GetPlatform().GetReader(name)), m_name(name) @@ -37,3 +39,84 @@ Index::~Index() { Cleanup(); } + +namespace +{ + void DeleteMapFiles(string const & path, bool deleteReady) + { + (void)my::DeleteFileX(path); + (void)my::DeleteFileX(path + RESUME_FILE_EXTENSION); + (void)my::DeleteFileX(path + DOWNLOADING_FILE_EXTENSION); + + if (deleteReady) + (void)my::DeleteFileX(path + READY_FILE_EXTENSION); + } + + string GetFullPath(string const & fileName) + { + return GetPlatform().WritablePathForFile(fileName); + } + + void ReplaceFileWithReady(string const & fileName) + { + string const path = GetFullPath(fileName); + DeleteMapFiles(path, false); + CHECK ( my::RenameFileX(path + READY_FILE_EXTENSION, path), (path) ); + } +} + +bool Index::DeleteMap(string const & fileName) +{ + threads::MutexGuard mutexGuard(m_lock); + UNUSED_VALUE(mutexGuard); + + if (!RemoveImpl(fileName)) + return false; + + DeleteMapFiles(GetFullPath(fileName), true); + return true; +} + +bool Index::UpdateMap(string const & fileName, m2::RectD & rect) +{ + threads::MutexGuard mutexGuard(m_lock); + UNUSED_VALUE(mutexGuard); + + MwmId const id = GetIdByName(fileName); + if (id != INVALID_MWM_ID) + { + m_info[id].m_status = MwmInfo::STATUS_UPDATE; + return false; + } + + ReplaceFileWithReady(fileName); + + (void)AddImpl(fileName, rect); + return true; +} + +void Index::UpdateMwmInfo(MwmId id) +{ + switch (m_info[id].m_status) + { + case MwmInfo::STATUS_TO_REMOVE: + if (m_info[id].m_lockCount == 0) + { + DeleteMapFiles(m_name[id], true); + + CHECK(RemoveImpl(id), ()); + } + break; + + case MwmInfo::STATUS_UPDATE: + if (m_info[id].m_lockCount == 0) + { + ClearCache(id); + + ReplaceFileWithReady(m_name[id]); + + m_info[id].m_status = MwmInfo::STATUS_ACTIVE; + } + break; + } +} diff --git a/indexer/index.hpp b/indexer/index.hpp index 4efb59116f..90cd3f0d1e 100644 --- a/indexer/index.hpp +++ b/indexer/index.hpp @@ -36,6 +36,7 @@ protected: /// @return mwm format version virtual int GetInfo(string const & name, MwmInfo & info) const; virtual MwmValue * CreateValue(string const & name) const; + virtual void UpdateMwmInfo(MwmId id); public: Index(); @@ -44,7 +45,8 @@ public: class MwmLock : public MwmSet::MwmLock { public: - MwmLock(Index const & index, MwmId mwmId) : MwmSet::MwmLock(index, mwmId) {} + MwmLock(Index const & index, MwmId mwmId) + : MwmSet::MwmLock(const_cast<Index &>(index), mwmId) {} inline MwmValue * GetValue() const { @@ -55,6 +57,9 @@ public: inline feature::DataHeader const & GetHeader() const { return GetValue()->GetHeader(); } }; + bool DeleteMap(string const & fileName); + bool UpdateMap(string const & fileName, m2::RectD & rect); + template <typename F> void ForEachInRect(F & f, m2::RectD const & rect, uint32_t scale) const { @@ -147,7 +152,7 @@ private: { /// @todo It's better to avoid hacks with scale comparison. - if (mwm[id].isCountry()) + if (mwm[id].IsCountry()) { // process countries first ProcessMwm(f, id, cov, scale); diff --git a/indexer/indexer_tests/mwm_set_test.cpp b/indexer/indexer_tests/mwm_set_test.cpp index 1e0df123e4..2f839ac3ab 100644 --- a/indexer/indexer_tests/mwm_set_test.cpp +++ b/indexer/indexer_tests/mwm_set_test.cpp @@ -42,10 +42,10 @@ UNIT_TEST(MwmSetSmokeTest) mwmSet.Remove("1"); mwmSet.GetMwmInfo(info); TEST_EQUAL(info.size(), 3, ()); - TEST(info[0].isValid(), ()); + TEST(info[0].IsActive(), ()); TEST_EQUAL(info[0].m_maxScale, 0, ()); - TEST(!info[1].isValid(), ()); - TEST(info[2].isValid(), ()); + TEST(!info[1].IsActive(), ()); + TEST(info[2].IsActive(), ()); TEST_EQUAL(info[2].m_maxScale, 2, ()); { MwmSet::MwmLock lock0(mwmSet, 0); @@ -57,11 +57,11 @@ UNIT_TEST(MwmSetSmokeTest) mwmSet.Add("3"); mwmSet.GetMwmInfo(info); TEST_EQUAL(info.size(), 3, ()); - TEST(info[0].isValid(), ()); + TEST(info[0].IsActive(), ()); TEST_EQUAL(info[0].m_maxScale, 0, ()); - TEST(info[1].isValid(), ()); + TEST(info[1].IsActive(), ()); TEST_EQUAL(info[1].m_maxScale, 3, ()); - TEST(info[2].isValid(), ()); + TEST(info[2].IsActive(), ()); TEST_EQUAL(info[2].m_maxScale, 2, ()); { @@ -72,23 +72,23 @@ UNIT_TEST(MwmSetSmokeTest) } mwmSet.GetMwmInfo(info); TEST_EQUAL(info.size(), 4, ()); - TEST(info[0].isValid(), ()); + TEST(info[0].IsActive(), ()); TEST_EQUAL(info[0].m_maxScale, 0, ()); - TEST(!info[1].isValid(), ()); - TEST(info[2].isValid(), ()); + TEST(!info[1].IsActive(), ()); + TEST(info[2].IsActive(), ()); TEST_EQUAL(info[2].m_maxScale, 2, ()); - TEST(info[3].isValid(), ()); + TEST(info[3].IsActive(), ()); TEST_EQUAL(info[3].m_maxScale, 4, ()); mwmSet.Add("5"); mwmSet.GetMwmInfo(info); TEST_EQUAL(info.size(), 4, ()); - TEST(info[0].isValid(), ()); + TEST(info[0].IsActive(), ()); TEST_EQUAL(info[0].m_maxScale, 0, ()); - TEST(info[1].isValid(), ()); + TEST(info[1].IsActive(), ()); TEST_EQUAL(info[1].m_maxScale, 5, ()); - TEST(info[2].isValid(), ()); + TEST(info[2].IsActive(), ()); TEST_EQUAL(info[2].m_maxScale, 2, ()); - TEST(info[3].isValid(), ()); + TEST(info[3].IsActive(), ()); TEST_EQUAL(info[3].m_maxScale, 4, ()); } diff --git a/indexer/mwm_set.cpp b/indexer/mwm_set.cpp index 8d763e08a8..dec88bf5df 100644 --- a/indexer/mwm_set.cpp +++ b/indexer/mwm_set.cpp @@ -10,34 +10,19 @@ #include "../std/memcpy.hpp" -namespace -{ - struct MwmIdIsEqualTo - { - MwmSet::MwmId m_id; - explicit MwmIdIsEqualTo(MwmSet::MwmId id) : m_id(id) {} - bool operator() (pair<MwmSet::MwmId, MwmSet::MwmValueBase *> const & p) const - { - return p.first == m_id; - } - }; -} // unnamed namespace - MwmInfo::MwmInfo() : m_lockCount(0), m_status(STATUS_REMOVED) { // Important: STATUS_REMOVED - is the default value. // Apply STATUS_ACTIVE before adding to maps container. } -MwmSet::MwmLock::MwmLock(MwmSet const & mwmSet, MwmId mwmId) +MwmSet::MwmLock::MwmLock(MwmSet & mwmSet, MwmId mwmId) : m_mwmSet(mwmSet), m_id(mwmId), m_pValue(mwmSet.LockValue(mwmId)) { - //LOG(LINFO, ("MwmLock::MwmLock()", m_id)); } MwmSet::MwmLock::~MwmLock() { - //LOG(LINFO, ("MwmLock::~MwmLock()", m_id)); if (m_pValue) m_mwmSet.UnlockValue(m_id, m_pValue); } @@ -46,7 +31,6 @@ MwmSet::MwmLock::~MwmLock() MwmSet::MwmSet(size_t cacheSize) : m_cacheSize(cacheSize) { - //LOG(LINFO, ("MwmSet::MwmSet()")); } MwmSet::~MwmSet() @@ -60,14 +44,12 @@ void MwmSet::Cleanup() threads::MutexGuard mutexGuard(m_lock); UNUSED_VALUE(mutexGuard); - //LOG(LINFO, ("MwmSet::~MwmSet()")); - ClearCacheImpl(m_cache.begin(), m_cache.end()); #ifdef DEBUG - for (size_t i = 0; i < m_info.size(); ++i) + for (MwmId i = 0; i < m_info.size(); ++i) { - if (m_info[i].m_status == MwmInfo::STATUS_ACTIVE) + if (m_info[i].IsActive()) { ASSERT_EQUAL(m_info[i].m_lockCount, 0, (i, m_name[i])); ASSERT_NOT_EQUAL(m_name[i], string(), (i)); @@ -76,15 +58,15 @@ void MwmSet::Cleanup() #endif } -void MwmSet::UpdateMwmInfo(MwmInfo & info) +void MwmSet::UpdateMwmInfo(MwmId id) { - if (info.m_status == MwmInfo::STATUS_TO_REMOVE && info.m_lockCount == 0) - info.m_status = MwmInfo::STATUS_REMOVED; + if (m_info[id].m_status == MwmInfo::STATUS_TO_REMOVE) + (void)RemoveImpl(id); } MwmSet::MwmId MwmSet::GetFreeId() { - MwmId const size = static_cast<MwmId>(m_info.size()); + MwmId const size = m_info.size(); for (MwmId i = 0; i < size; ++i) { if (m_info[i].m_status == MwmInfo::STATUS_REMOVED) @@ -98,11 +80,10 @@ MwmSet::MwmId MwmSet::GetFreeId() MwmSet::MwmId MwmSet::GetIdByName(string const & name) { - MwmId const size = static_cast<MwmId>(m_info.size()); - for (MwmId i = 0; i < size; ++i) + for (MwmId i = 0; i < m_info.size(); ++i) { - UpdateMwmInfo(m_info[i]); - if (m_info[i].m_status == MwmInfo::STATUS_ACTIVE && m_name[i] == name) + UpdateMwmInfo(i); + if (m_name[i] == name) return i; } return INVALID_MWM_ID; @@ -115,19 +96,27 @@ string MwmSet::MwmLock::GetCountryName() const return src.substr(0, src.size() - strlen(DATA_FILE_EXTENSION)); } -int MwmSet::Add(string const & fileName, m2::RectD & r) +int MwmSet::Add(string const & fileName, m2::RectD & rect) { threads::MutexGuard mutexGuard(m_lock); UNUSED_VALUE(mutexGuard); - //LOG(LINFO, ("MwmSet::Add()", fileName)); - - if (GetIdByName(fileName) != INVALID_MWM_ID) + MwmId const id = GetIdByName(fileName); + if (id != INVALID_MWM_ID) { - LOG(LWARNING, ("Trying to add already added map", fileName)); + if (m_info[id].IsExist()) + LOG(LWARNING, ("Trying to add already added map", fileName)); + else + m_info[id].m_status = MwmInfo::STATUS_ACTIVE; + return -1; } + return AddImpl(fileName, rect); +} + +int MwmSet::AddImpl(string const & fileName, m2::RectD & rect) +{ // this function can throw an exception for bad mwm file MwmInfo info; int const version = GetInfo(fileName, info); @@ -138,18 +127,24 @@ int MwmSet::Add(string const & fileName, m2::RectD & r) m_name[id] = fileName; m_info[id] = info; - r = info.m_limitRect; - ASSERT ( r.IsValid(), () ); + rect = info.m_limitRect; + ASSERT ( rect.IsValid(), () ); return version; } -void MwmSet::RemoveImpl(MwmId id) +bool MwmSet::RemoveImpl(MwmId id) { if (m_info[id].m_lockCount == 0) + { + m_name[id].clear(); m_info[id].m_status = MwmInfo::STATUS_REMOVED; + return true; + } else + { m_info[id].m_status = MwmInfo::STATUS_TO_REMOVE; - m_name[id].clear(); + return false; + } } void MwmSet::Remove(string const & fileName) @@ -157,16 +152,22 @@ void MwmSet::Remove(string const & fileName) threads::MutexGuard mutexGuard(m_lock); UNUSED_VALUE(mutexGuard); - //LOG(LINFO, ("MwmSet::Remove()", fileName)); + (void)RemoveImpl(fileName); +} + +bool MwmSet::RemoveImpl(string const & fileName) +{ + bool ret = false; MwmId const id = GetIdByName(fileName); - if (id != INVALID_MWM_ID) + if (id != INVALID_MWM_ID && m_info[id].IsExist()) { - RemoveImpl(id); + ret = RemoveImpl(id); - // Update the cache. - ClearCacheImpl(RemoveIfKeepValid(m_cache.begin(), m_cache.end(), MwmIdIsEqualTo(id)), m_cache.end()); + ClearCache(id); } + + return ret; } void MwmSet::RemoveAllCountries() @@ -176,43 +177,49 @@ void MwmSet::RemoveAllCountries() for (MwmId i = 0; i < m_info.size(); ++i) { - if (m_info[i].isCountry()) - RemoveImpl(i); + if (m_info[i].IsCountry()) + (void)RemoveImpl(i); } // do not call ClearCache - it's under mutex lock ClearCacheImpl(m_cache.begin(), m_cache.end()); } -bool MwmSet::IsLoaded(string const & fName) const +bool MwmSet::IsLoaded(string const & file) const { - return (const_cast<MwmSet *>(this)->GetIdByName(fName + DATA_FILE_EXTENSION) != INVALID_MWM_ID); + MwmSet * p = const_cast<MwmSet *>(this); + + threads::MutexGuard mutexGuard(p->m_lock); + UNUSED_VALUE(mutexGuard); + + MwmId const id = p->GetIdByName(file + DATA_FILE_EXTENSION); + return (id != INVALID_MWM_ID && m_info[id].IsExist()); } void MwmSet::GetMwmInfo(vector<MwmInfo> & info) const { - threads::MutexGuard mutexGuard(m_lock); + MwmSet * p = const_cast<MwmSet *>(this); + + threads::MutexGuard mutexGuard(p->m_lock); UNUSED_VALUE(mutexGuard); - for (vector<MwmInfo>::iterator it = m_info.begin(); it != m_info.end(); ++it) - UpdateMwmInfo(*it); + for (MwmId i = 0; i < m_info.size(); ++i) + p->UpdateMwmInfo(i); info = m_info; } -MwmSet::MwmValueBase * MwmSet::LockValue(MwmId id) const +MwmSet::MwmValueBase * MwmSet::LockValue(MwmId id) { threads::MutexGuard mutexGuard(m_lock); UNUSED_VALUE(mutexGuard); - //LOG(LINFO, ("MwmSet::LockContainer()", id)); - ASSERT_LESS(id, m_info.size(), ()); if (id >= m_info.size()) return NULL; - UpdateMwmInfo(m_info[id]); - if (m_info[id].m_status != MwmInfo::STATUS_ACTIVE) + UpdateMwmInfo(id); + if (!m_info[id].IsActive()) return NULL; ++m_info[id].m_lockCount; @@ -230,13 +237,11 @@ MwmSet::MwmValueBase * MwmSet::LockValue(MwmId id) const return CreateValue(m_name[id]); } -void MwmSet::UnlockValue(MwmId id, MwmValueBase * p) const +void MwmSet::UnlockValue(MwmId id, MwmValueBase * p) { threads::MutexGuard mutexGuard(m_lock); UNUSED_VALUE(mutexGuard); - //LOG(LINFO, ("MwmSet::UnlockContainer()", id)); - ASSERT(p, (id)); ASSERT_LESS(id, m_info.size(), ()); if (id >= m_info.size() || p == 0) @@ -245,9 +250,9 @@ void MwmSet::UnlockValue(MwmId id, MwmValueBase * p) const ASSERT_GREATER(m_info[id].m_lockCount, 0, ()); if (m_info[id].m_lockCount > 0) --m_info[id].m_lockCount; - UpdateMwmInfo(m_info[id]); + UpdateMwmInfo(id); - if (m_info[id].m_status == MwmInfo::STATUS_ACTIVE) + if (m_info[id].IsActive()) { m_cache.push_back(make_pair(id, p)); if (m_cache.size() > m_cacheSize) @@ -275,3 +280,21 @@ void MwmSet::ClearCacheImpl(CacheType::iterator beg, CacheType::iterator end) delete it->second; m_cache.erase(beg, end); } + +namespace +{ + struct MwmIdIsEqualTo + { + MwmSet::MwmId m_id; + explicit MwmIdIsEqualTo(MwmSet::MwmId id) : m_id(id) {} + bool operator() (pair<MwmSet::MwmId, MwmSet::MwmValueBase *> const & p) const + { + return (p.first == m_id); + } + }; +} + +void MwmSet::ClearCache(MwmId id) +{ + ClearCacheImpl(RemoveIfKeepValid(m_cache.begin(), m_cache.end(), MwmIdIsEqualTo(id)), m_cache.end()); +} diff --git a/indexer/mwm_set.hpp b/indexer/mwm_set.hpp index 00235b7604..5bde1d3ae3 100644 --- a/indexer/mwm_set.hpp +++ b/indexer/mwm_set.hpp @@ -19,14 +19,21 @@ public: uint8_t m_minScale; ///< Min zoom level of mwm. uint8_t m_maxScale; ///< Max zoom level of mwm. - // Does this MwmInfo represent a valid Mwm? - inline bool isValid() const { return (m_status == STATUS_ACTIVE); } - inline bool isCountry() const { return (m_minScale > 0); } + inline bool IsExist() const + { + return (m_status == STATUS_ACTIVE || m_status == STATUS_UPDATE); + } + inline bool IsCountry() const { return (m_minScale > 0); } + inline bool IsActive() const { return (m_status == STATUS_ACTIVE); } -private: - friend class MwmSet; + enum Status + { + STATUS_ACTIVE = 0, + STATUS_TO_REMOVE, + STATUS_REMOVED, + STATUS_UPDATE + }; - enum Status { STATUS_ACTIVE = 0, STATUS_TO_REMOVE = 1, STATUS_REMOVED = 2 }; uint8_t m_lockCount; ///< Number of locks. uint8_t m_status; ///< Current country status. }; @@ -49,7 +56,7 @@ public: class MwmLock { public: - MwmLock(MwmSet const & mwmSet, MwmId mwmId); + MwmLock(MwmSet & mwmSet, MwmId mwmId); ~MwmLock(); inline MwmValueBase * GetValue() const { return m_pValue; } @@ -57,26 +64,33 @@ public: inline MwmId GetID() const { return m_id; } private: - MwmSet const & m_mwmSet; + MwmSet & m_mwmSet; MwmId m_id; MwmValueBase * m_pValue; }; /// Add new mwm. Returns false, if mwm with given fileName already exists. /// @param[in] fileName File name (without full path) of country. - /// @param[out] r Limit rect of country. + /// @param[out] rect Limit rect of country. /// @return Map format version or -1 if not added - int Add(string const & fileName, m2::RectD & r); + //@{ +protected: + int AddImpl(string const & fileName, m2::RectD & rect); + +public: + int Add(string const & fileName, m2::RectD & rect); inline bool Add(string const & fileName) { m2::RectD dummy; return (-1 != Add(fileName, dummy)); } + //@} /// @name Remove mwm. //@{ -private: - void RemoveImpl(MwmId id); +protected: + bool RemoveImpl(MwmId id); + bool RemoveImpl(string const & fileName); public: void Remove(string const & fileName); @@ -84,9 +98,11 @@ public: void RemoveAllCountries(); //@} - bool IsLoaded(string const & fName) const; + /// @param[in] file File name without extension. + bool IsLoaded(string const & file) const; - // Get ids of all mwms. Some of them may be marked to remove. + /// Get ids of all mwms. Some of them may be with not active status. + /// In that case, LockValue returns NULL. void GetMwmInfo(vector<MwmInfo> & info) const; // Clear caches. @@ -100,28 +116,35 @@ protected: void Cleanup(); private: - static const MwmId INVALID_MWM_ID = static_cast<MwmId>(-1); - typedef deque<pair<MwmId, MwmValueBase *> > CacheType; - // Update given MwmInfo. - inline static void UpdateMwmInfo(MwmInfo & info); - - MwmValueBase * LockValue(MwmId id) const; - void UnlockValue(MwmId id, MwmValueBase * p) const; + MwmValueBase * LockValue(MwmId id); + void UnlockValue(MwmId id, MwmValueBase * p); // Find first removed mwm or add a new one. MwmId GetFreeId(); - // Find mwm with a given name. - MwmId GetIdByName(string const & name); - // Do the cleaning for [beg, end) without acquiring the mutex. void ClearCacheImpl(CacheType::iterator beg, CacheType::iterator end); - mutable vector<MwmInfo> m_info; // mutable needed for GetMwmInfo - /*mutable*/ vector<string> m_name; - mutable CacheType m_cache; + CacheType m_cache; size_t m_cacheSize; - mutable threads::Mutex m_lock; + +protected: + static const MwmId INVALID_MWM_ID = static_cast<MwmId>(-1); + + /// Find mwm with a given name. + /// @note This function is always called under mutex m_lock. + MwmId GetIdByName(string const & name); + + /// @note This function is always called under mutex m_lock. + void ClearCache(MwmId id); + + /// Update given MwmInfo. + /// @note This function is always called under mutex m_lock. + virtual void UpdateMwmInfo(MwmId id); + + vector<MwmInfo> m_info; + vector<string> m_name; + threads::Mutex m_lock; }; |