Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgorshenin <y.gorshenin@corp.mail.ru>2015-07-01 16:48:58 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:53:27 +0300
commita7bcdb5ae8b8e75c1a3806b00b19f3b80c72c5b3 (patch)
treee24caedef110b579fcedc15d29c62cc43e3f6d9c
parente0470160313b3ed0bc396ffec72b16fded6b8520 (diff)
Revert "[storage, framework, index] Storage redesign. Plain strings are replaced to CountryFile and LocalCountryFile."
-rw-r--r--android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp11
-rw-r--r--android/jni/com/mapswithme/maps/Framework.cpp46
-rw-r--r--drape_head/drape_surface.cpp12
-rw-r--r--generator/generator_tests/check_mwms.cpp16
-rw-r--r--generator/routing_generator.cpp17
-rw-r--r--generator/update_generator.cpp12
-rw-r--r--indexer/index.cpp142
-rw-r--r--indexer/index.hpp83
-rw-r--r--indexer/indexer_tests/index_builder_test.cpp2
-rw-r--r--indexer/indexer_tests/index_test.cpp141
-rw-r--r--indexer/indexer_tests/mwm_set_test.cpp67
-rw-r--r--indexer/mwm_set.cpp130
-rw-r--r--indexer/mwm_set.hpp86
-rw-r--r--integration_tests/osrm_test_tools.cpp58
-rw-r--r--integration_tests/osrm_test_tools.hpp4
-rw-r--r--iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm2
-rw-r--r--map/active_maps_layout.cpp12
-rw-r--r--map/active_maps_layout.hpp5
-rw-r--r--map/benchmark_engine.cpp7
-rw-r--r--map/benchmark_tool/features_loading.cpp18
-rw-r--r--map/country_tree.cpp2
-rw-r--r--map/country_tree.hpp4
-rw-r--r--map/feature_vec_model.cpp67
-rw-r--r--map/feature_vec_model.hpp60
-rw-r--r--map/framework.cpp240
-rw-r--r--map/framework.hpp18
-rw-r--r--map/map_tests/bookmarks_test.cpp2
-rw-r--r--map/mwm_tests/multithread_mwm_test.cpp2
-rw-r--r--map/mwm_tests/mwm_foreach_test.cpp14
-rw-r--r--map/mwm_tests/mwm_index_test.cpp13
-rw-r--r--map/routing_session.cpp17
-rw-r--r--map/routing_session.hpp36
-rw-r--r--pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp33
-rw-r--r--platform/country_defines.cpp22
-rw-r--r--platform/country_defines.hpp8
-rw-r--r--platform/country_file.cpp2
-rw-r--r--platform/local_country_file.cpp13
-rw-r--r--platform/local_country_file.hpp6
-rw-r--r--platform/local_country_file_utils.cpp31
-rw-r--r--platform/platform.cpp8
-rw-r--r--platform/platform.hpp11
-rw-r--r--platform/platform_android.cpp22
-rw-r--r--platform/platform_ios.mm2
-rw-r--r--platform/platform_tests/local_country_file_tests.cpp214
-rw-r--r--routing/osrm_router.cpp8
-rw-r--r--routing/osrm_router.hpp7
-rw-r--r--routing/road_graph_router.cpp3
-rw-r--r--routing/routing_mapping.cpp52
-rw-r--r--routing/routing_mapping.h29
-rw-r--r--search/search_query.cpp23
-rw-r--r--search/search_tests/house_detector_tests.cpp14
-rw-r--r--search/search_tests/locality_finder_test.cpp7
-rw-r--r--std/algorithm.hpp1
-rw-r--r--storage/country.cpp250
-rw-r--r--storage/country.hpp127
-rw-r--r--storage/map_files_downloader.hpp1
-rw-r--r--storage/queued_country.cpp52
-rw-r--r--storage/queued_country.hpp31
-rw-r--r--storage/storage.cpp1193
-rw-r--r--storage/storage.hpp302
-rw-r--r--storage/storage.pro2
-rw-r--r--storage/storage_defines.hpp2
-rw-r--r--storage/storage_tests/fake_map_files_downloader.hpp1
-rw-r--r--storage/storage_tests/queued_country_tests.cpp106
-rw-r--r--storage/storage_tests/storage_tests.cpp506
-rw-r--r--storage/storage_tests/storage_tests.pro2
66 files changed, 1923 insertions, 2514 deletions
diff --git a/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp b/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp
index bd6993716b..1b6b3c9067 100644
--- a/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp
+++ b/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp
@@ -3,10 +3,9 @@
#include "defines.hpp"
-#include "coding/file_name_utils.hpp"
-#include "coding/internal/file_data.hpp"
-#include "coding/reader_streambuf.hpp"
#include "coding/url_encode.hpp"
+#include "coding/reader_streambuf.hpp"
+#include "coding/internal/file_data.hpp"
#include "platform/platform.hpp"
#include "platform/http_request.hpp"
@@ -213,11 +212,7 @@ extern "C"
storage::Storage const & storage = g_framework->Storage();
for (size_t i = 0; i < curFile.m_urls.size(); ++i)
{
- string baseName = curFile.m_fileName;
- my::GetNameWithoutExt(baseName);
- storage::TIndex const index = storage.FindIndexByFile(baseName);
-
- curFile.m_urls[i] = storage.GetFileDownloadUrl(curFile.m_urls[i], index, TMapOptions::EMap);
+ curFile.m_urls[i] = storage.GetFileDownloadUrl(curFile.m_urls[i], curFile.m_fileName);
LOG(LDEBUG, (curFile.m_urls[i]));
}
diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp
index 6e9f751f5d..957e150873 100644
--- a/android/jni/com/mapswithme/maps/Framework.cpp
+++ b/android/jni/com/mapswithme/maps/Framework.cpp
@@ -23,11 +23,8 @@
#include "geometry/angles.hpp"
-#include "platform/country_file.hpp"
-#include "platform/local_country_file.hpp"
-#include "platform/local_country_file_utils.hpp"
-#include "platform/location.hpp"
#include "platform/measurement_utils.hpp"
+#include "platform/location.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"
@@ -48,8 +45,6 @@ const double DOUBLE_TOUCH_S = SHORT_TOUCH_MS / 1000.0;
android::Framework * g_framework = 0;
using namespace storage;
-using platform::CountryFile;
-using platform::LocalCountryFile;
namespace
{
@@ -558,32 +553,33 @@ namespace android
void Framework::GetMapsWithoutSearch(vector<string> & out) const
{
- ASSERT(out.empty(), ());
+ ASSERT ( out.empty(), () );
::Platform const & pl = GetPlatform();
- vector<LocalCountryFile> localFiles;
- platform::FindAllLocalMaps(localFiles);
+ vector<string> v;
+ m_work.GetMaps(v);
- for (LocalCountryFile const & localFile : localFiles)
+ for (size_t i = 0; i < v.size(); ++i)
{
- CountryFile const countryFile = localFile.GetCountryFile();
// skip World and WorldCoast
- if (countryFile.GetNameWithoutExt() == WORLD_FILE_NAME ||
- countryFile.GetNameWithoutExt() == WORLD_COASTS_FILE_NAME)
- {
- continue;
- }
- try
- {
- FilesContainerR cont(pl.GetCountryReader(localFile, TMapOptions::EMap));
- if (!cont.IsExist(SEARCH_INDEX_FILE_TAG))
- out.push_back(countryFile.GetNameWithoutExt());
- }
- catch (RootException const & ex)
+ if (v[i].find(WORLD_FILE_NAME) == string::npos &&
+ v[i].find(WORLD_COASTS_FILE_NAME) == string::npos)
{
- // sdcard can contain dummy _*.mwm files. Suppress these errors.
- LOG(LWARNING, ("Bad mwm file:", countryFile.GetNameWithoutExt(), "Error:", ex.Msg()));
+ try
+ {
+ FilesContainerR cont(pl.GetReader(v[i]));
+ if (!cont.IsExist(SEARCH_INDEX_FILE_TAG))
+ {
+ my::GetNameWithoutExt(v[i]);
+ out.push_back(v[i]);
+ }
+ }
+ catch (RootException const & ex)
+ {
+ // sdcard can contain dummy _*.mwm files. Supress this errors.
+ LOG(LWARNING, ("Bad mwm file:", v[i], "Error:", ex.Msg()));
+ }
}
}
}
diff --git a/drape_head/drape_surface.cpp b/drape_head/drape_surface.cpp
index c1c431ebfa..76df4004da 100644
--- a/drape_head/drape_surface.cpp
+++ b/drape_head/drape_surface.cpp
@@ -28,13 +28,13 @@ DrapeSurface::DrapeSurface()
///{ Temporary initialization
m_model.InitClassificator();
- // Platform::FilesList maps;
- // Platform & pl = GetPlatform();
- // pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, maps);
+ Platform::FilesList maps;
+ Platform & pl = GetPlatform();
+ pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, maps);
- // for_each(maps.begin(), maps.end(), bind(&model::FeaturesFetcher::RegisterMap, &m_model, _1));
- // ///}
- // ///
+ for_each(maps.begin(), maps.end(), bind(&model::FeaturesFetcher::RegisterMap, &m_model, _1));
+ ///}
+ ///
}
DrapeSurface::~DrapeSurface()
diff --git a/generator/generator_tests/check_mwms.cpp b/generator/generator_tests/check_mwms.cpp
index 1ce869d62c..b4771110ba 100644
--- a/generator/generator_tests/check_mwms.cpp
+++ b/generator/generator_tests/check_mwms.cpp
@@ -5,8 +5,6 @@
#include "indexer/data_header.hpp"
#include "indexer/interval_index.hpp"
-#include "platform/local_country_file.hpp"
-#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "base/logging.hpp"
@@ -14,25 +12,25 @@
UNIT_TEST(CheckMWM_LoadAll)
{
- Platform & platform = GetPlatform();
- vector<platform::LocalCountryFile> localFiles;
- platform::FindAllLocalMapsInDirectory(platform.WritableDir(), 0 /* version */, localFiles);
+ Platform & pl = GetPlatform();
+
+ Platform::FilesList maps;
+ pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, maps);
model::FeaturesFetcher m;
m.InitClassificator();
- for (platform::LocalCountryFile const & localFile : localFiles)
+ for (string const & s : maps)
{
- LOG(LINFO, ("Found mwm:", localFile));
try
{
- pair<MwmSet::MwmLock, bool> const p = m.RegisterMap(localFile);
+ pair<MwmSet::MwmLock, bool> const p = m.RegisterMap(s);
TEST(p.first.IsLocked(), ());
TEST(p.second, ());
}
catch (RootException const & ex)
{
- TEST(false, ("Bad mwm file:", localFile));
+ TEST(false, ("Bad mwm file:", s));
}
}
}
diff --git a/generator/routing_generator.cpp b/generator/routing_generator.cpp
index 2f37a187a3..5827019b9b 100644
--- a/generator/routing_generator.cpp
+++ b/generator/routing_generator.cpp
@@ -30,9 +30,6 @@
#include "3party/osrm/osrm-backend/data_structures/query_edge.hpp"
#include "3party/osrm/osrm-backend/data_structures/internal_route_result.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
-
namespace routing
{
@@ -226,13 +223,9 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin
{
classificator::Load();
- CountryFile countryFile(countryName);
-
- // Correct mwm version doesn't matter here - we just need access to mwm files via Index.
- LocalCountryFile localFile(baseDir, countryFile, 0 /* version */);
- localFile.SyncWithDisk();
+ string const mwmFile = baseDir + countryName + DATA_FILE_EXTENSION;
Index index;
- pair<MwmSet::MwmLock, bool> const p = index.Register(localFile);
+ pair<MwmSet::MwmLock, bool> const p = index.Register(mwmFile);
if (!p.second)
{
LOG(LCRITICAL, ("MWM file not found"));
@@ -242,7 +235,7 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin
osrm::NodeDataVectorT nodeData;
gen::OsmID2FeatureID osm2ft;
- if (!LoadIndexes(localFile.GetPath(TMapOptions::EMap), osrmFile, nodeData, osm2ft))
+ if (!LoadIndexes(mwmFile, osrmFile, nodeData, osm2ft))
return;
OsrmFtSegMappingBuilder mapping;
@@ -373,13 +366,13 @@ void BuildRoutingIndex(string const & baseDir, string const & countryName, strin
"Multiple:", multiple, "Equal:", equal));
LOG(LINFO, ("Collect all data into one file..."));
- string const fPath = localFile.GetPath(TMapOptions::ECarRouting);
+ string const fPath = mwmFile + ROUTING_FILE_EXTENSION;
FilesContainerW routingCont(fPath /*, FileWriter::OP_APPEND*/);
{
// Write version for routing file that is equal to correspondent mwm file.
- FilesContainerR mwmCont(localFile.GetPath(TMapOptions::EMap));
+ FilesContainerR mwmCont(mwmFile);
FileWriter w = routingCont.GetWriter(VERSION_FILE_TAG);
ReaderSource<ModelReaderPtr> src(mwmCont.GetReader(VERSION_FILE_TAG));
diff --git a/generator/update_generator.cpp b/generator/update_generator.cpp
index 2653e281ad..9d8cda8d45 100644
--- a/generator/update_generator.cpp
+++ b/generator/update_generator.cpp
@@ -43,10 +43,10 @@ namespace update
string m_dataDir;
Platform::FilesList & m_files;
- uint64_t GetFileSize(platform::CountryFile const & cnt, TMapOptions opt) const
+ uint64_t GetFileSize(CountryFile const & cnt, TMapOptions opt) const
{
uint64_t sz = 0;
- string const fName = cnt.GetNameWithExt(opt);
+ string const fName = cnt.GetFileWithExt(opt);
if (!GetPlatform().GetFileSizeByFullPath(m_dataDir + fName, sz))
{
LOG(opt == TMapOptions::EMap ? LCRITICAL : LWARNING, ("File was not found:", fName));
@@ -74,14 +74,14 @@ namespace update
{
for (size_t i = 0; i < c.Value().m_files.size(); ++i)
{
- platform::CountryFile & cnt = c.Value().m_files[i];
+ CountryFile & cnt = c.Value().m_files[i];
++m_processedFiles;
- cnt.SetRemoteSizes(GetFileSize(cnt, TMapOptions::EMap),
- GetFileSize(cnt, TMapOptions::ECarRouting));
+ cnt.AssignSizes(GetFileSize(cnt, TMapOptions::EMap),
+ GetFileSize(cnt, TMapOptions::ECarRouting));
- string const fName = cnt.GetNameWithExt(TMapOptions::EMap);
+ string const fName = cnt.GetFileWithoutExt() + DATA_FILE_EXTENSION;
auto found = find(m_files.begin(), m_files.end(), fName);
if (found != m_files.end())
m_files.erase(found);
diff --git a/indexer/index.cpp b/indexer/index.cpp
index 12d0a02fe7..e27814dc74 100644
--- a/indexer/index.cpp
+++ b/indexer/index.cpp
@@ -6,27 +6,32 @@
#include "coding/file_name_utils.hpp"
#include "coding/internal/file_data.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
//////////////////////////////////////////////////////////////////////////////////
// MwmValue implementation
//////////////////////////////////////////////////////////////////////////////////
-MwmValue::MwmValue(LocalCountryFile const & localFile)
- : m_cont(GetPlatform().GetCountryReader(localFile, TMapOptions::EMap)),
- m_countryFile(localFile.GetCountryFile())
+MwmValue::MwmValue(string const & name)
+ : m_cont(GetPlatform().GetReader(name))
{
m_factory.Load(m_cont);
}
+string MwmValue::GetFileName() const
+{
+ string s = m_cont.GetFileName();
+ my::GetNameFromFullPath(s);
+ my::GetNameWithoutExt(s);
+ return s;
+}
+
//////////////////////////////////////////////////////////////////////////////////
// Index implementation
//////////////////////////////////////////////////////////////////////////////////
-bool Index::GetVersion(LocalCountryFile const & localFile, MwmInfo & info) const
+bool Index::GetVersion(string const & name, MwmInfo & info) const
{
- MwmValue value(localFile);
+ MwmValue value(name);
feature::DataHeader const & h = value.GetHeader();
if (!h.IsMWMSuitable())
@@ -42,9 +47,9 @@ bool Index::GetVersion(LocalCountryFile const & localFile, MwmInfo & info) const
return true;
}
-MwmSet::TMwmValueBasePtr Index::CreateValue(LocalCountryFile const & localFile) const
+MwmSet::TMwmValueBasePtr Index::CreateValue(string const & name) const
{
- TMwmValueBasePtr p(new MwmValue(localFile));
+ TMwmValueBasePtr p(new MwmValue(name));
ASSERT(static_cast<MwmValue &>(*p.get()).GetHeader().IsMWMSuitable(), ());
return p;
}
@@ -58,23 +63,124 @@ Index::~Index()
Cleanup();
}
-pair<MwmSet::MwmLock, bool> Index::RegisterMap(LocalCountryFile const & localFile)
+namespace
{
- pair<MwmSet::MwmLock, bool> result = Register(localFile);
- if (result.first.IsLocked() && result.second)
- m_observers.ForEach(&Observer::OnMapRegistered, localFile);
+ // Deletes map file denoted by @path and all temporary files related
+ // to it.
+ 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);
+ }
+
+ // Deletes all files related to @fileName and renames
+ // @fileName.READY_FILE_EXTENSION to @fileName.
+ void ReplaceFileWithReady(string const & fileName)
+ {
+ string const path = GetFullPath(fileName);
+ DeleteMapFiles(path, false /* deleteReady */);
+ CHECK(my::RenameFileX(path + READY_FILE_EXTENSION, path), (path));
+ }
+}
+
+pair<MwmSet::MwmLock, bool> Index::RegisterMap(string const & fileName)
+{
+ if (GetPlatform().IsFileExistsByFullPath(GetFullPath(fileName + READY_FILE_EXTENSION)))
+ {
+ pair<MwmSet::MwmLock, UpdateStatus> updateResult = UpdateMap(fileName);
+ switch (updateResult.second)
+ {
+ case UPDATE_STATUS_OK:
+ return make_pair(move(updateResult.first), true);
+ case UPDATE_STATUS_BAD_FILE:
+ return make_pair(move(updateResult.first), false);
+ case UPDATE_STATUS_UPDATE_DELAYED:
+ // Not dangerous, but it's strange when adding existing maps.
+ ASSERT(false, ());
+ return make_pair(move(updateResult.first), true);
+ }
+ }
+
+ pair<MwmSet::MwmLock, bool> result = Register(fileName);
+ if (result.second)
+ m_observers.ForEach(&Observer::OnMapRegistered, fileName);
return result;
}
-bool Index::DeregisterMap(CountryFile const & countryFile) { return Deregister(countryFile); }
+bool Index::DeleteMap(string const & fileName)
+{
+ {
+ lock_guard<mutex> lock(m_lock);
+
+ if (!DeregisterImpl(fileName))
+ return false;
+
+ DeleteMapFiles(GetFullPath(fileName), true /* deleteReady */);
+ }
+ m_observers.ForEach(&Observer::OnMapDeleted, fileName);
+ return true;
+}
bool Index::AddObserver(Observer & observer) { return m_observers.Add(observer); }
bool Index::RemoveObserver(Observer const & observer) { return m_observers.Remove(observer); }
-void Index::OnMwmDeregistered(LocalCountryFile const & localFile)
+pair<MwmSet::MwmLock, Index::UpdateStatus> Index::UpdateMap(string const & fileName)
+{
+ pair<MwmSet::MwmLock, UpdateStatus> result;
+ result.second = UPDATE_STATUS_BAD_FILE;
+
+ {
+ lock_guard<mutex> lock(m_lock);
+
+ MwmId const id = GetMwmIdByFileNameImpl(fileName);
+ shared_ptr<MwmInfo> info = id.GetInfo();
+ if (id.IsAlive() && info->m_lockCount > 0)
+ {
+ info->SetStatus(MwmInfo::STATUS_PENDING_UPDATE);
+ result.first = GetLock(id);
+ result.second = UPDATE_STATUS_UPDATE_DELAYED;
+ }
+ else
+ {
+ ReplaceFileWithReady(fileName);
+ pair<MwmSet::MwmLock, bool> registerResult = RegisterImpl(fileName);
+ if (registerResult.second)
+ {
+ result.first = move(registerResult.first);
+ result.second = UPDATE_STATUS_OK;
+ }
+ }
+ }
+ if (result.second != UPDATE_STATUS_BAD_FILE)
+ m_observers.ForEach(&Observer::OnMapUpdateIsReady, fileName);
+ if (result.second == UPDATE_STATUS_OK)
+ m_observers.ForEach(&Observer::OnMapUpdated, fileName);
+ return result;
+}
+
+void Index::OnMwmDeleted(shared_ptr<MwmInfo> const & info)
+{
+ string const & fileName = info->m_fileName;
+ DeleteMapFiles(fileName, true /* deleteReady */);
+ m_observers.ForEach(&Observer::OnMapDeleted, fileName);
+}
+
+void Index::OnMwmReadyForUpdate(shared_ptr<MwmInfo> const & info)
{
- m_observers.ForEach(&Observer::OnMapDeregistered, localFile);
+ ClearCache(MwmId(info));
+ ReplaceFileWithReady(info->m_fileName);
+ info->SetStatus(MwmInfo::STATUS_UP_TO_DATE);
+ m_observers.ForEach(&Observer::OnMapUpdated, info->m_fileName);
}
//////////////////////////////////////////////////////////////////////////////////
@@ -88,11 +194,11 @@ Index::FeaturesLoaderGuard::FeaturesLoaderGuard(Index const & parent, MwmId id)
{
}
-string Index::FeaturesLoaderGuard::GetCountryFileName() const
+string Index::FeaturesLoaderGuard::GetFileName() const
{
if (!m_lock.IsLocked())
return string();
- return m_lock.GetValue<MwmValue>()->GetCountryFile().GetNameWithoutExt();
+ return m_lock.GetValue<MwmValue>()->GetFileName();
}
bool Index::FeaturesLoaderGuard::IsWorld() const
diff --git a/indexer/index.hpp b/indexer/index.hpp
index 20d9d75c5d..c058a0f11b 100644
--- a/indexer/index.hpp
+++ b/indexer/index.hpp
@@ -24,25 +24,33 @@ class MwmValue : public MwmSet::MwmValueBase
public:
FilesContainerR m_cont;
IndexFactory m_factory;
- platform::CountryFile const m_countryFile;
- explicit MwmValue(platform::LocalCountryFile const & localFile);
+ explicit MwmValue(string const & name);
inline feature::DataHeader const & GetHeader() const { return m_factory.GetHeader(); }
inline version::MwmVersion const & GetMwmVersion() const { return m_factory.GetMwmVersion(); }
- inline platform::CountryFile const & GetCountryFile() const { return m_countryFile; }
+ /// @return MWM file name without extension.
+ string GetFileName() const;
};
class Index : public MwmSet
{
protected:
// MwmSet overrides:
- bool GetVersion(platform::LocalCountryFile const & localFile, MwmInfo & info) const override;
- TMwmValueBasePtr CreateValue(platform::LocalCountryFile const & localFile) const override;
- void OnMwmDeregistered(platform::LocalCountryFile const & localFile) override;
+ bool GetVersion(string const & name, MwmInfo & info) const override;
+ TMwmValueBasePtr CreateValue(string const & name) const override;
+ void OnMwmDeleted(shared_ptr<MwmInfo> const & info) override;
+ void OnMwmReadyForUpdate(shared_ptr<MwmInfo> const & info) override;
public:
+ enum UpdateStatus
+ {
+ UPDATE_STATUS_OK,
+ UPDATE_STATUS_BAD_FILE,
+ UPDATE_STATUS_UPDATE_DELAYED
+ };
+
/// An Observer interface to MwmSet. Note that these functions can
/// be called from *ANY* thread because most signals are sent when
/// some thread releases its MwmLock, so overrides must be as fast
@@ -50,14 +58,19 @@ public:
class Observer
{
public:
- virtual ~Observer() = default;
+ virtual ~Observer() {}
+
+ /// Called when a map is registered for a first time.
+ virtual void OnMapRegistered(string const & file) {}
- /// Called when a map is registered for a first time and can be
- /// used.
- virtual void OnMapRegistered(platform::LocalCountryFile const & localFile) {}
+ /// Called when an update for a map is downloaded.
+ virtual void OnMapUpdateIsReady(string const & file) {}
- /// Called when a map is deregistered and can not be used.
- virtual void OnMapDeregistered(platform::LocalCountryFile const & localFile) {}
+ /// Called when an update for a map is applied.
+ virtual void OnMapUpdated(string const & file) {}
+
+ /// Called when a map is deleted.
+ virtual void OnMapDeleted(string const & file) {}
};
Index();
@@ -65,21 +78,37 @@ public:
/// Registers a new map.
///
- /// \return A pair of an MwmLock and a flag. There are three cases:
- /// * the map is newer than the newest registered - returns
- /// active lock and set flag
- /// * the map is older than the newest registered - returns inactive lock and
- /// unset flag.
- /// * the version of the map equals to the version of the newest registered -
- /// returns active lock and unset flag.
- WARN_UNUSED_RESULT pair<MwmLock, bool> RegisterMap(platform::LocalCountryFile const & localFile);
-
- /// Deregisters a map from internal records.
+ /// \return A pair of an MwmLock and a flag. MwmLock is locked iff the
+ /// map with fileName was created or already exists. Flag
+ /// is set when the map was registered for a first
+ /// time. Thus, there are three main cases:
+ ///
+ /// * the map already exists - returns active lock and unset flag
+ /// * the map was already registered - returns active lock and set flag
+ /// * the map can't be registered - returns inactive lock and unset flag
+ WARN_UNUSED_RESULT pair<MwmLock, bool> RegisterMap(string const & fileName);
+
+ /// Replaces a map file corresponding to fileName with a new one, when
+ /// it's possible - no clients of the map file. Otherwise, update
+ /// will be delayed.
+ ///
+ /// \return * the map file have been updated - returns active lock and
+ /// UPDATE_STATUS_OK
+ /// * update is delayed because the map is busy - returns active lock and
+ /// UPDATE_STATUS_UPDATE_DELAYED
+ /// * the file isn't suitable for update - returns inactive lock and
+ /// UPDATE_STATUS_BAD_FILE
+ WARN_UNUSED_RESULT pair<MwmLock, UpdateStatus> UpdateMap(string const & fileName);
+
+ /// Deletes a map both from the file system and internal tables, also,
+ /// deletes all files related to the map. If the map was successfully
+ /// deleted, notifies observers.
///
- /// \param countryFile A countryFile denoting a map to be deregistered.
- /// \return True if the map was successfully deregistered. If map is locked
- /// now, returns false.
- bool DeregisterMap(platform::CountryFile const & countryFile);
+ /// \param fileName A fileName denoting the map to be deleted, may
+ /// be a full path or a short path relative to
+ /// executable's directories.
+ //// \return True if the map was successfully deleted.
+ bool DeleteMap(string const & fileName);
bool AddObserver(Observer & observer);
@@ -251,7 +280,7 @@ public:
FeaturesLoaderGuard(Index const & parent, MwmId id);
inline MwmSet::MwmId GetId() const { return m_lock.GetId(); }
- string GetCountryFileName() const;
+ string GetFileName() const;
bool IsWorld() const;
void GetFeature(uint32_t offset, FeatureType & ft);
diff --git a/indexer/indexer_tests/index_builder_test.cpp b/indexer/indexer_tests/index_builder_test.cpp
index 1ebfe9c068..7efeb27fb6 100644
--- a/indexer/indexer_tests/index_builder_test.cpp
+++ b/indexer/indexer_tests/index_builder_test.cpp
@@ -56,7 +56,7 @@ UNIT_TEST(BuildIndexTest)
{
// Check that index actually works.
Index index;
- UNUSED_VALUE(index.Register(platform::LocalCountryFile::MakeForTesting("build_index_test")));
+ UNUSED_VALUE(index.Register(fileName));
// Make sure that index is actually parsed.
NoopFunctor fn;
diff --git a/indexer/indexer_tests/index_test.cpp b/indexer/indexer_tests/index_test.cpp
index 1e24aa5365..dfea961b07 100644
--- a/indexer/indexer_tests/index_test.cpp
+++ b/indexer/indexer_tests/index_test.cpp
@@ -6,8 +6,6 @@
#include "coding/file_name_utils.hpp"
#include "coding/internal/file_data.hpp"
-#include "platform/country_file.hpp"
-#include "platform/local_country_file.hpp"
#include "platform/platform.hpp"
#include "base/logging.hpp"
@@ -18,11 +16,6 @@
#include "std/bind.hpp"
#include "std/string.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
-
-namespace
-{
void CheckedDeleteFile(string const & file)
{
if (Platform::IsFileExistsByFullPath(file))
@@ -32,60 +25,57 @@ void CheckedDeleteFile(string const & file)
class Observer : public Index::Observer
{
public:
- Observer() : m_numRegisteredCalls(0), m_numDeregisteredCalls(0) {}
-
- ~Observer() { CheckExpectations(); }
-
- void ExpectRegisteredMap(platform::LocalCountryFile const & localFile)
+ Observer(string const & file)
+ : m_file(file),
+ m_map_registered_calls(0),
+ m_map_update_is_ready_calls(0),
+ m_map_updated_calls(0),
+ m_map_deleted_calls(0)
{
- m_expectedRegisteredMaps.push_back(localFile);
}
- void ExpectDeregisteredMap(platform::LocalCountryFile const & localFile)
+ // Index::Observer overrides:
+ void OnMapRegistered(string const & file) override
{
- m_expectedDeregisteredMaps.push_back(localFile);
+ CHECK_EQUAL(m_file, file, ());
+ ++m_map_registered_calls;
}
- void CheckExpectations()
+ void OnMapUpdateIsReady(string const & file) override
{
- CHECK_EQUAL(m_numRegisteredCalls, m_expectedRegisteredMaps.size(), ());
- CHECK_EQUAL(m_numDeregisteredCalls, m_expectedDeregisteredMaps.size(), ());
+ CHECK_EQUAL(m_file, file, ());
+ ++m_map_update_is_ready_calls;
}
- // Index::Observer overrides:
- void OnMapRegistered(platform::LocalCountryFile const & localFile) override
+ void OnMapUpdated(string const & file) override
{
- CHECK_LESS(m_numRegisteredCalls, m_expectedRegisteredMaps.size(),
- ("Unexpected OnMapRegistered() call (", m_numRegisteredCalls, "): ", localFile));
- CHECK_EQUAL(m_expectedRegisteredMaps[m_numRegisteredCalls], localFile, (m_numRegisteredCalls));
- ++m_numRegisteredCalls;
+ CHECK_EQUAL(m_file, file, ());
+ ++m_map_updated_calls;
}
- void OnMapDeregistered(platform::LocalCountryFile const & localFile) override
+ void OnMapDeleted(string const & file) override
{
- CHECK_LESS(m_numDeregisteredCalls, m_expectedDeregisteredMaps.size(),
- ("Unexpected OnMapDeregistered() call (", m_numDeregisteredCalls, "): ", localFile));
- CHECK_EQUAL(m_expectedDeregisteredMaps[m_numDeregisteredCalls], localFile,
- (m_numDeregisteredCalls));
- ++m_numDeregisteredCalls;
+ CHECK_EQUAL(m_file, file, ());
+ ++m_map_deleted_calls;
}
- inline size_t MapRegisteredCalls() const { return m_numRegisteredCalls; }
- inline size_t MapDeregisteredCalls() const { return m_numDeregisteredCalls; }
+ int map_registered_calls() const { return m_map_registered_calls; }
+ int map_update_is_ready_calls() const { return m_map_update_is_ready_calls; }
+ int map_updated_calls() const { return m_map_updated_calls; }
+ int map_deleted_calls() const { return m_map_deleted_calls; }
private:
- size_t m_numRegisteredCalls;
- size_t m_numDeregisteredCalls;
-
- vector<LocalCountryFile> m_expectedRegisteredMaps;
- vector<LocalCountryFile> m_expectedDeregisteredMaps;
+ string const m_file;
+ int m_map_registered_calls;
+ int m_map_update_is_ready_calls;
+ int m_map_updated_calls;
+ int m_map_deleted_calls;
};
-} // namespace
UNIT_TEST(Index_Parse)
{
Index index;
- UNUSED_VALUE(index.RegisterMap(platform::LocalCountryFile::MakeForTesting("minsk-pass")));
+ UNUSED_VALUE(index.RegisterMap("minsk-pass" DATA_FILE_EXTENSION));
// Make sure that index is actually parsed.
NoopFunctor fn;
@@ -94,68 +84,65 @@ UNIT_TEST(Index_Parse)
UNIT_TEST(Index_MwmStatusNotifications)
{
- Platform & platform = GetPlatform();
- string const mapsDir = GetPlatform().WritableDir();
- CountryFile const countryFile("minsk-pass");
+ string const resourcesDir = GetPlatform().ResourcesDir();
+ string const sourceMapName = "minsk-pass" DATA_FILE_EXTENSION;
+ string const sourceMapPath = my::JoinFoldersToPath(resourcesDir, sourceMapName);
+ string const testMapName = "minsk-pass-copy" DATA_FILE_EXTENSION;
+ string const testMapPath = my::JoinFoldersToPath(resourcesDir, testMapName);
+ string const testMapUpdatePath = testMapPath + READY_FILE_EXTENSION;
- // These two classes point to the same file, but will be considered
- // by Index as distinct files because versions are artificially set
- // to different numbers.
- LocalCountryFile const localFileV1(mapsDir, countryFile, 1 /* version */);
- LocalCountryFile const localFileV2(mapsDir, countryFile, 2 /* version */);
+ TEST(my::CopyFileX(sourceMapPath, testMapPath), ());
+ MY_SCOPE_GUARD(testMapGuard, bind(&CheckedDeleteFile, testMapPath));
Index index;
- Observer observer;
+ Observer observer(testMapName);
index.AddObserver(observer);
- TEST_EQUAL(0, observer.MapRegisteredCalls(), ());
-
- MwmSet::MwmId localFileV1Id;
+ TEST_EQUAL(0, observer.map_registered_calls(), ());
// Checks that observers are triggered after map registration.
{
- observer.ExpectRegisteredMap(localFileV1);
- pair<MwmSet::MwmLock, bool> const p = index.RegisterMap(localFileV1);
+ pair<MwmSet::MwmLock, bool> const p = index.RegisterMap(testMapName);
TEST(p.first.IsLocked(), ());
TEST(p.second, ());
- observer.CheckExpectations();
- localFileV1Id = p.first.GetId();
+ TEST_EQUAL(1, observer.map_registered_calls(), ());
}
- // Checks that map can't registered twice.
+ // Checks that map can't registered twice and observers aren't
+ // triggered.
{
- pair<MwmSet::MwmLock, bool> const p = index.RegisterMap(localFileV1);
+ pair<MwmSet::MwmLock, bool> const p = index.RegisterMap(testMapName);
TEST(p.first.IsLocked(), ());
TEST(!p.second, ());
- observer.CheckExpectations();
- TEST_EQUAL(localFileV1Id, p.first.GetId(), ());
+ TEST_EQUAL(1, observer.map_registered_calls(), ());
}
- // Checks that observers are notified when map is updated.
- MwmSet::MwmId localFileV2Id;
+ TEST(my::CopyFileX(testMapPath, testMapUpdatePath), ());
+ MY_SCOPE_GUARD(testMapUpdateGuard, bind(&CheckedDeleteFile, testMapUpdatePath));
+
+ // Checks that observers are notified when map is deleted.
{
- observer.ExpectRegisteredMap(localFileV2);
- observer.ExpectDeregisteredMap(localFileV1);
- pair<MwmSet::MwmLock, bool> const p = index.RegisterMap(localFileV2);
+ TEST_EQUAL(0, observer.map_update_is_ready_calls(), ());
+ TEST_EQUAL(0, observer.map_updated_calls(), ());
+ pair<MwmSet::MwmLock, Index::UpdateStatus> const p = index.UpdateMap(testMapName);
TEST(p.first.IsLocked(), ());
- TEST(p.second, ());
- observer.CheckExpectations();
- localFileV2Id = p.first.GetId();
- TEST_NOT_EQUAL(localFileV1Id, localFileV2Id, ());
+ TEST_EQUAL(Index::UPDATE_STATUS_OK, p.second, ());
+ TEST_EQUAL(1, observer.map_update_is_ready_calls(), ());
+ TEST_EQUAL(1, observer.map_updated_calls(), ());
}
- // Tries to deregister a map in presence of an active lock. Map
- // should be marked "to be removed" but can't be deregistered. After
- // leaving the inner block the map should be deregistered.
+ // Tries to delete map in presence of active lock. Map should be
+ // marked "to be removed" but can't be deleted.
{
- MwmSet::MwmLock const lock = index.GetMwmLockByCountryFile(countryFile);
+ MwmSet::MwmLock const lock = index.GetMwmLockByFileName(testMapName);
TEST(lock.IsLocked(), ());
- TEST(!index.DeregisterMap(countryFile), ());
- observer.CheckExpectations();
-
- observer.ExpectDeregisteredMap(localFileV2);
+ TEST(!index.DeleteMap(testMapName), ());
+ TEST_EQUAL(0, observer.map_deleted_calls(), ());
}
- observer.CheckExpectations();
+
+ // Checks that observers are notified when all locks are destroyed.
+ TEST_EQUAL(1, observer.map_deleted_calls(), ());
+
index.RemoveObserver(observer);
}
diff --git a/indexer/indexer_tests/mwm_set_test.cpp b/indexer/indexer_tests/mwm_set_test.cpp
index 30b9adebe5..27fd148f6b 100644
--- a/indexer/indexer_tests/mwm_set_test.cpp
+++ b/indexer/indexer_tests/mwm_set_test.cpp
@@ -7,11 +7,6 @@
#include "std/initializer_list.hpp"
#include "std/unordered_map.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
-
-using TMwmsInfo = unordered_map<string, shared_ptr<MwmInfo>>;
-
namespace
{
class MwmValue : public MwmSet::MwmValueBase
@@ -21,17 +16,16 @@ class MwmValue : public MwmSet::MwmValueBase
class TestMwmSet : public MwmSet
{
protected:
- // MwmSet overrides:
- bool GetVersion(LocalCountryFile const & localFile, MwmInfo & info) const override
+ bool GetVersion(string const & path, MwmInfo & info) const override
{
- int const n = localFile.GetCountryFile().GetNameWithoutExt()[0] - '0';
+ int const n = path[0] - '0';
info.m_maxScale = n;
info.m_limitRect = m2::RectD(0, 0, 1, 1);
info.m_version.format = version::lastFormat;
return true;
}
- TMwmValueBasePtr CreateValue(LocalCountryFile const &) const override
+ TMwmValueBasePtr CreateValue(string const &) const override
{
return TMwmValueBasePtr(new MwmValue());
}
@@ -40,21 +34,23 @@ public:
~TestMwmSet() { Cleanup(); }
};
-void GetMwmsInfo(MwmSet const & mwmSet, TMwmsInfo & mwmsInfo)
+void GetMwmsInfo(MwmSet const & mwmSet,
+ unordered_map<MwmSet::TMwmFileName, shared_ptr<MwmInfo>> & mwmsInfo)
{
vector<shared_ptr<MwmInfo>> mwmsInfoList;
mwmSet.GetMwmsInfo(mwmsInfoList);
mwmsInfo.clear();
for (shared_ptr<MwmInfo> const & info : mwmsInfoList)
- mwmsInfo[info->GetCountryName()] = info;
+ mwmsInfo[info->GetFileName()] = info;
}
-void TestFilesPresence(TMwmsInfo const & mwmsInfo, initializer_list<string> const & expectedNames)
+void TestFilesPresence(unordered_map<MwmSet::TMwmFileName, shared_ptr<MwmInfo>> const & mwmsInfo,
+ initializer_list<MwmSet::TMwmFileName> const & expectedNames)
{
TEST_EQUAL(expectedNames.size(), mwmsInfo.size(), ());
- for (string const & countryFileName : expectedNames)
- TEST_EQUAL(1, mwmsInfo.count(countryFileName), (countryFileName));
+ for (MwmSet::TMwmFileName const & fileName : expectedNames)
+ TEST_EQUAL(1, mwmsInfo.count(fileName), (fileName));
}
} // namespace
@@ -62,12 +58,12 @@ void TestFilesPresence(TMwmsInfo const & mwmsInfo, initializer_list<string> cons
UNIT_TEST(MwmSetSmokeTest)
{
TestMwmSet mwmSet;
- TMwmsInfo mwmsInfo;
+ unordered_map<MwmSet::TMwmFileName, shared_ptr<MwmInfo>> mwmsInfo;
- UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("0")));
- UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("1")));
- UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("2")));
- mwmSet.Deregister(CountryFile("1"));
+ UNUSED_VALUE(mwmSet.Register("0"));
+ UNUSED_VALUE(mwmSet.Register("1"));
+ UNUSED_VALUE(mwmSet.Register("2"));
+ mwmSet.Deregister("1");
GetMwmsInfo(mwmSet, mwmsInfo);
TestFilesPresence(mwmsInfo, {"0", "2"});
@@ -76,13 +72,13 @@ UNIT_TEST(MwmSetSmokeTest)
TEST_EQUAL(mwmsInfo["0"]->m_maxScale, 0, ());
TEST(mwmsInfo["2"]->IsUpToDate(), ());
{
- MwmSet::MwmLock const lock0 = mwmSet.GetMwmLockByCountryFile(CountryFile("0"));
- MwmSet::MwmLock const lock1 = mwmSet.GetMwmLockByCountryFile(CountryFile("1"));
+ MwmSet::MwmLock const lock0 = mwmSet.GetMwmLockByFileName("0");
+ MwmSet::MwmLock const lock1 = mwmSet.GetMwmLockByFileName("1");
TEST(lock0.IsLocked(), ());
TEST(!lock1.IsLocked(), ());
}
- UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("3")));
+ UNUSED_VALUE(mwmSet.Register("3"));
GetMwmsInfo(mwmSet, mwmsInfo);
TestFilesPresence(mwmsInfo, {"0", "2", "3"});
@@ -95,10 +91,10 @@ UNIT_TEST(MwmSetSmokeTest)
TEST_EQUAL(mwmsInfo["3"]->m_maxScale, 3, ());
{
- MwmSet::MwmLock const lock1 = mwmSet.GetMwmLockByCountryFile(CountryFile("1"));
+ MwmSet::MwmLock const lock1 = mwmSet.GetMwmLockByFileName("1");
TEST(!lock1.IsLocked(), ());
- mwmSet.Deregister(CountryFile("3"));
- UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("4")));
+ mwmSet.Deregister("3");
+ UNUSED_VALUE(mwmSet.Register("4"));
}
GetMwmsInfo(mwmSet, mwmsInfo);
@@ -111,7 +107,7 @@ UNIT_TEST(MwmSetSmokeTest)
TEST(mwmsInfo["4"]->IsUpToDate(), ());
TEST_EQUAL(mwmsInfo["4"]->m_maxScale, 4, ());
- UNUSED_VALUE(mwmSet.Register(LocalCountryFile::MakeForTesting("5")));
+ UNUSED_VALUE(mwmSet.Register("5"));
GetMwmsInfo(mwmSet, mwmsInfo);
TestFilesPresence(mwmsInfo, {"0", "2", "4", "5"});
@@ -130,17 +126,17 @@ UNIT_TEST(MwmSetSmokeTest)
UNIT_TEST(MwmSetIdTest)
{
TestMwmSet mwmSet;
- TEST(mwmSet.Register(LocalCountryFile::MakeForTesting("3")).second, ());
+ TEST(mwmSet.Register("3").second, ());
- MwmSet::MwmId const id0 = mwmSet.GetMwmLockByCountryFile(CountryFile("3")).GetId();
- MwmSet::MwmId const id1 = mwmSet.GetMwmLockByCountryFile(CountryFile("3")).GetId();
+ MwmSet::MwmId const id0 = mwmSet.GetMwmLockByFileName("3").GetId();
+ MwmSet::MwmId const id1 = mwmSet.GetMwmLockByFileName("3").GetId();
TEST(id0.IsAlive(), ());
TEST(id1.IsAlive(), ());
TEST_EQUAL(id0.GetInfo().get(), id1.GetInfo().get(), ());
- TEST_EQUAL(MwmInfo::STATUS_REGISTERED, id0.GetInfo()->GetStatus(), ());
+ TEST_EQUAL(MwmInfo::STATUS_UP_TO_DATE, id0.GetInfo()->GetStatus(), ());
- TEST(mwmSet.Deregister(CountryFile("3")), ());
+ TEST(mwmSet.Deregister("3"), ());
// Test that both id's are sour now.
TEST(!id0.IsAlive(), ());
@@ -155,15 +151,14 @@ UNIT_TEST(MwmSetLockAndIdTest)
MwmSet::MwmId id;
{
- pair<MwmSet::MwmLock, bool> const lockFlag =
- mwmSet.Register(LocalCountryFile::MakeForTesting("4"));
+ pair<MwmSet::MwmLock, bool> const lockFlag = mwmSet.Register("4");
MwmSet::MwmLock const & lock = lockFlag.first;
bool const success = lockFlag.second;
TEST(lock.IsLocked(), ());
TEST(success, ("Can't register test mwm 4"));
- TEST_EQUAL(MwmInfo::STATUS_REGISTERED, lock.GetInfo()->GetStatus(), ());
+ TEST_EQUAL(MwmInfo::STATUS_UP_TO_DATE, lock.GetInfo()->GetStatus(), ());
- TEST(!mwmSet.Deregister(CountryFile("4")), ()); // It's not possible to remove mwm 4 right now.
+ TEST(!mwmSet.Deregister("4"), ()); // It's not possible to remove mwm 4 right now.
TEST(lock.IsLocked(), ());
TEST_EQUAL(MwmInfo::STATUS_MARKED_TO_DEREGISTER, lock.GetInfo()->GetStatus(), ());
id = lock.GetId();
@@ -177,7 +172,7 @@ UNIT_TEST(MwmSetLockAndIdTest)
// It is not possible to lock mwm 4 because it is already deleted,
// and it is not possible to get to it's info from mwmSet.
- MwmSet::MwmLock lock = mwmSet.GetMwmLockByCountryFile(CountryFile("4"));
+ MwmSet::MwmLock lock = mwmSet.GetMwmLockByFileName("4");
TEST(!lock.IsLocked(), ());
TEST(!lock.GetId().IsAlive(), ());
TEST(!lock.GetId().GetInfo().get(), ());
diff --git a/indexer/mwm_set.cpp b/indexer/mwm_set.cpp
index d6961ebdd0..c9005078ce 100644
--- a/indexer/mwm_set.cpp
+++ b/indexer/mwm_set.cpp
@@ -9,9 +9,6 @@
#include "std/algorithm.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
-
MwmInfo::MwmInfo() : m_minScale(0), m_maxScale(0), m_status(STATUS_DEREGISTERED), m_lockCount(0) {}
MwmInfo::MwmTypeT MwmInfo::GetType() const
@@ -77,64 +74,57 @@ MwmSet::~MwmSet()
void MwmSet::Cleanup()
{
lock_guard<mutex> lock(m_lock);
+
ClearCacheImpl(m_cache.begin(), m_cache.end());
+
+#ifdef DEBUG
+ for (auto const & p : m_info)
+ {
+ MwmInfo const & info = *p.second;
+ if (info.IsUpToDate())
+ {
+ ASSERT_EQUAL(info.m_lockCount, 0, (info.m_fileName));
+ ASSERT(!info.m_fileName.empty(), ());
+ }
+ }
+#endif
}
-MwmSet::MwmId MwmSet::GetMwmIdByCountryFileImpl(CountryFile const & countryFile) const
+MwmSet::MwmId MwmSet::GetMwmIdByFileNameImpl(TMwmFileName const & name) const
{
- string const name = countryFile.GetNameWithoutExt();
ASSERT(!name.empty(), ());
auto const it = m_info.find(name);
- if (it == m_info.cend() || it->second.empty())
+ if (it == m_info.cend())
return MwmId();
- return MwmId(it->second.back());
+ return MwmId(it->second);
}
-pair<MwmSet::MwmLock, bool> MwmSet::Register(LocalCountryFile const & localFile)
+pair<MwmSet::MwmLock, bool> MwmSet::Register(TMwmFileName const & fileName)
{
lock_guard<mutex> lock(m_lock);
- CountryFile const & countryFile = localFile.GetCountryFile();
- MwmId const id = GetMwmIdByCountryFileImpl(countryFile);
+ MwmId const id = GetMwmIdByFileNameImpl(fileName);
if (!id.IsAlive())
- return RegisterImpl(localFile);
-
+ return RegisterImpl(fileName);
shared_ptr<MwmInfo> info = id.GetInfo();
-
- // Deregister old mwm for the country.
- if (info->GetVersion() < localFile.GetVersion())
- {
- DeregisterImpl(id);
- return RegisterImpl(localFile);
- }
-
- string const name = countryFile.GetNameWithoutExt();
- // Update the status of the mwm with the same version.
- if (info->GetVersion() == localFile.GetVersion())
- {
- LOG(LWARNING, ("Trying to add already registered mwm:", name));
- info->SetStatus(MwmInfo::STATUS_REGISTERED);
- return make_pair(GetLock(id), false);
- }
-
- LOG(LWARNING, ("Trying to add too old (", localFile.GetVersion(), ") mwm (", name,
- "), current version:", info->GetVersion()));
- return make_pair(MwmLock(), false);
+ if (info->IsRegistered())
+ LOG(LWARNING, ("Trying to add already registered mwm:", fileName));
+ else
+ info->SetStatus(MwmInfo::STATUS_UP_TO_DATE);
+ return make_pair(GetLock(id), false);
}
-pair<MwmSet::MwmLock, bool> MwmSet::RegisterImpl(LocalCountryFile const & localFile)
+pair<MwmSet::MwmLock, bool> MwmSet::RegisterImpl(TMwmFileName const & fileName)
{
shared_ptr<MwmInfo> info(new MwmInfo());
// This function can throw an exception for a bad mwm file.
- if (!GetVersion(localFile, *info))
+ if (!GetVersion(fileName, *info))
return make_pair(MwmLock(), false);
- info->SetStatus(MwmInfo::STATUS_REGISTERED);
- info->m_file = localFile;
- string const name = localFile.GetCountryFile().GetNameWithoutExt();
+ info->SetStatus(MwmInfo::STATUS_UP_TO_DATE);
+ info->m_fileName = fileName;
+ m_info[fileName] = info;
- vector<shared_ptr<MwmInfo>> & infos = m_info[name];
- infos.push_back(info);
return make_pair(GetLock(MwmId(info)), true);
}
@@ -143,28 +133,26 @@ bool MwmSet::DeregisterImpl(MwmId const & id)
if (!id.IsAlive())
return false;
shared_ptr<MwmInfo> const & info = id.GetInfo();
-
if (info->m_lockCount == 0)
{
info->SetStatus(MwmInfo::STATUS_DEREGISTERED);
- vector<shared_ptr<MwmInfo>> & infos = m_info[info->GetCountryName()];
- infos.erase(remove(infos.begin(), infos.end(), info), infos.end());
- OnMwmDeregistered(info->GetLocalFile());
+ m_info.erase(info->m_fileName);
+ OnMwmDeleted(info);
return true;
}
info->SetStatus(MwmInfo::STATUS_MARKED_TO_DEREGISTER);
return false;
}
-bool MwmSet::Deregister(CountryFile const & countryFile)
+bool MwmSet::Deregister(TMwmFileName const & fileName)
{
lock_guard<mutex> lock(m_lock);
- return DeregisterImpl(countryFile);
+ return DeregisterImpl(fileName);
}
-bool MwmSet::DeregisterImpl(CountryFile const & countryFile)
+bool MwmSet::DeregisterImpl(TMwmFileName const & fileName)
{
- MwmId const id = GetMwmIdByCountryFileImpl(countryFile);
+ MwmId const id = GetMwmIdByFileNameImpl(fileName);
if (!id.IsAlive())
return false;
bool const deregistered = DeregisterImpl(id);
@@ -176,24 +164,21 @@ void MwmSet::DeregisterAll()
{
lock_guard<mutex> lock(m_lock);
- for (auto const & p : m_info)
+ for (auto it = m_info.begin(); it != m_info.end();)
{
- // Vector of shared pointers is copied here because an original
- // vector will be modified by the body of the cycle.
- vector<shared_ptr<MwmInfo>> infos = p.second;
- for (shared_ptr<MwmInfo> info : infos)
- DeregisterImpl(MwmId(info));
+ auto cur = it++;
+ DeregisterImpl(MwmId(cur->second));
}
// Do not call ClearCache - it's under mutex lock.
ClearCacheImpl(m_cache.begin(), m_cache.end());
}
-bool MwmSet::IsLoaded(CountryFile const & countryFile) const
+bool MwmSet::IsLoaded(TMwmFileName const & fileName) const
{
lock_guard<mutex> lock(m_lock);
- MwmId const id = GetMwmIdByCountryFileImpl(countryFile);
+ MwmId const id = GetMwmIdByFileNameImpl(fileName + DATA_FILE_EXTENSION);
return id.IsAlive() && id.GetInfo()->IsRegistered();
}
@@ -203,10 +188,7 @@ void MwmSet::GetMwmsInfo(vector<shared_ptr<MwmInfo>> & info) const
info.clear();
info.reserve(m_info.size());
for (auto const & p : m_info)
- {
- if (!p.second.empty())
- info.push_back(p.second.back());
- }
+ info.push_back(p.second);
}
MwmSet::TMwmValueBasePtr MwmSet::LockValue(MwmId const & id)
@@ -234,7 +216,7 @@ MwmSet::TMwmValueBasePtr MwmSet::LockValueImpl(MwmId const & id)
return result;
}
}
- return CreateValue(info->GetLocalFile());
+ return CreateValue(info->m_fileName);
}
void MwmSet::UnlockValue(MwmId const & id, TMwmValueBasePtr p)
@@ -251,10 +233,22 @@ void MwmSet::UnlockValueImpl(MwmId const & id, TMwmValueBasePtr p)
return;
shared_ptr<MwmInfo> const & info = id.GetInfo();
- ASSERT_GREATER(info->m_lockCount, 0, ());
+ CHECK_GREATER(info->m_lockCount, 0, ());
--info->m_lockCount;
- if (info->m_lockCount == 0 && info->GetStatus() == MwmInfo::STATUS_MARKED_TO_DEREGISTER)
- VERIFY(DeregisterImpl(id), ());
+ if (info->m_lockCount == 0)
+ {
+ switch (info->GetStatus())
+ {
+ case MwmInfo::STATUS_MARKED_TO_DEREGISTER:
+ CHECK(DeregisterImpl(id), ());
+ break;
+ case MwmInfo::STATUS_PENDING_UPDATE:
+ OnMwmReadyForUpdate(info);
+ break;
+ default:
+ break;
+ }
+ }
if (info->IsUpToDate())
{
@@ -273,20 +267,20 @@ void MwmSet::ClearCache()
ClearCacheImpl(m_cache.begin(), m_cache.end());
}
-MwmSet::MwmId MwmSet::GetMwmIdByCountryFile(CountryFile const & countryFile) const
+MwmSet::MwmId MwmSet::GetMwmIdByFileName(TMwmFileName const & fileName) const
{
lock_guard<mutex> lock(m_lock);
- MwmId const id = GetMwmIdByCountryFileImpl(countryFile);
- ASSERT(id.IsAlive(), ("Can't get an mwm's (", countryFile.GetNameWithoutExt(), ") identifier."));
+ MwmId const id = GetMwmIdByFileNameImpl(fileName);
+ ASSERT(id.IsAlive(), ("Can't get an mwm's (", fileName, ") identifier."));
return id;
}
-MwmSet::MwmLock MwmSet::GetMwmLockByCountryFile(CountryFile const & countryFile)
+MwmSet::MwmLock MwmSet::GetMwmLockByFileName(TMwmFileName const & fileName)
{
lock_guard<mutex> lock(m_lock);
- MwmId const id = GetMwmIdByCountryFileImpl(countryFile);
+ MwmId const id = GetMwmIdByFileNameImpl(fileName);
TMwmValueBasePtr value(nullptr);
if (id.IsAlive())
value = LockValueImpl(id);
diff --git a/indexer/mwm_set.hpp b/indexer/mwm_set.hpp
index dfc225f4c4..25682c16b0 100644
--- a/indexer/mwm_set.hpp
+++ b/indexer/mwm_set.hpp
@@ -2,9 +2,6 @@
#include "indexer/mwm_version.hpp"
-#include "platform/country_file.hpp"
-#include "platform/local_country_file.hpp"
-
#include "geometry/rect2d.hpp"
#include "base/macros.hpp"
@@ -34,9 +31,10 @@ public:
enum Status
{
- STATUS_REGISTERED, ///< Mwm is registered and up to date.
- STATUS_MARKED_TO_DEREGISTER, ///< Mwm is marked to be deregistered as soon as possible.
- STATUS_DEREGISTERED, ///< Mwm is deregistered.
+ STATUS_UP_TO_DATE, ///< Mwm is registered and up-to-date
+ STATUS_MARKED_TO_DEREGISTER, ///< Mwm is marked to be deregistered as soon as possible
+ STATUS_DEREGISTERED, ///< Mwm is deregistered
+ STATUS_PENDING_UPDATE ///< Mwm is registered but there're a pending update to it
};
MwmInfo();
@@ -48,32 +46,31 @@ public:
inline Status GetStatus() const { return m_status; }
- inline bool IsUpToDate() const { return IsRegistered(); }
-
inline bool IsRegistered() const
{
- return m_status == STATUS_REGISTERED;
+ return m_status == STATUS_UP_TO_DATE || m_status == STATUS_PENDING_UPDATE;
}
- inline platform::LocalCountryFile const & GetLocalFile() const { return m_file; }
-
- inline string GetCountryName() const { return m_file.GetCountryFile().GetNameWithoutExt(); }
+ inline bool IsUpToDate() const { return m_status == STATUS_UP_TO_DATE; }
- inline int64_t GetVersion() const { return m_file.GetVersion(); }
+ inline string const & GetFileName() const { return m_fileName; }
MwmTypeT GetType() const;
private:
inline void SetStatus(Status status) { m_status = status; }
- platform::LocalCountryFile m_file; ///< Path to the mwm file.
- Status m_status; ///< Current country status.
- uint8_t m_lockCount; ///< Number of locks.
+ string m_fileName; ///< Path to the mwm file.
+ Status m_status; ///< Current country status.
+ uint8_t m_lockCount; ///< Number of locks.
};
class MwmSet
{
public:
+ using TMwmFileName = string;
+ using TMwmInfoTable = map<TMwmFileName, shared_ptr<MwmInfo>>;
+
struct MwmId
{
public:
@@ -97,9 +94,9 @@ public:
friend ostream & operator<<(ostream & os, MwmId const & id)
{
if (id.m_info.get())
- os << "MwmId [" << id.m_info->GetCountryName() << "]";
+ os << "MwmId[" << id.m_info->GetFileName() << "]";
else
- os << "MwmId [invalid]";
+ os << "MwmId[invalid]";
return os;
}
@@ -155,43 +152,41 @@ public:
/// Registers a new map.
///
- /// \return A pair of an MwmLock and a flag. There are three cases:
- /// * the map is newer than the newest registered - returns
- /// active lock and set flag.
- /// * the map is older than the newest registered - returns inactive lock and
- /// unset flag.
- /// * the version of the map equals to the version of the newest registered -
- /// returns active lock and unset flag.
+ /// \return A pair of an MwmLock and a flag. MwmLock is locked iff the
+ /// map with fileName was created or already exists. Flag
+ /// is set when the map was registered for a first
+ /// time. Thus, there are three main cases:
///
- /// *NOTE* When a new version for the same country is registered,
- /// all previous versions will be automatically deregistered.
+ /// * the map already exists - returns active lock and unset flag
+ /// * the map was already registered - returns active lock and set flag
+ /// * the map can't be registered - returns inactive lock and unset flag
+ //@{
protected:
- WARN_UNUSED_RESULT pair<MwmLock, bool> RegisterImpl(platform::LocalCountryFile const & localFile);
+ WARN_UNUSED_RESULT pair<MwmLock, bool> RegisterImpl(TMwmFileName const & fileName);
public:
- WARN_UNUSED_RESULT pair<MwmLock, bool> Register(platform::LocalCountryFile const & localFile);
+ WARN_UNUSED_RESULT pair<MwmLock, bool> Register(TMwmFileName const & fileName);
//@}
/// @name Remove mwm.
//@{
protected:
- /// Deregisters a map from internal records.
+ /// Deregisters a map from the set when it's possible. Note that an
+ /// underlying file is not deleted.
///
- /// \param countryFile A countryFile denoting a map to be deregistered.
- /// \return True if the map was successfully deregistered. If map is locked
- /// now, returns false.
+ /// @return true when the map was deregistered.
//@{
bool DeregisterImpl(MwmId const & id);
- bool DeregisterImpl(platform::CountryFile const & countryFile);
+ bool DeregisterImpl(TMwmFileName const & ofileName);
//@}
public:
- bool Deregister(platform::CountryFile const & countryFile);
+ bool Deregister(TMwmFileName const & fileName);
void DeregisterAll();
//@}
- /// Returns true when country is registered and can be used.
- bool IsLoaded(platform::CountryFile const & countryFile) const;
+ /// @param[in] file File name without extension.
+ bool IsLoaded(TMwmFileName const & fileName) const;
/// Get ids of all mwms. Some of them may be with not active status.
/// In that case, LockValue returns NULL.
@@ -199,14 +194,14 @@ public:
void ClearCache();
- MwmId GetMwmIdByCountryFile(platform::CountryFile const & countryFile) const;
+ MwmId GetMwmIdByFileName(TMwmFileName const & fileName) const;
- MwmLock GetMwmLockByCountryFile(platform::CountryFile const & countryFile);
+ MwmLock GetMwmLockByFileName(TMwmFileName const & fileName);
protected:
/// @return True when file format version was successfully read to MwmInfo.
- virtual bool GetVersion(platform::LocalCountryFile const & localFile, MwmInfo & info) const = 0;
- virtual TMwmValueBasePtr CreateValue(platform::LocalCountryFile const & localFile) const = 0;
+ virtual bool GetVersion(TMwmFileName const & fileName, MwmInfo & info) const = 0;
+ virtual TMwmValueBasePtr CreateValue(string const & name) const = 0;
void Cleanup();
@@ -231,7 +226,7 @@ protected:
/// Find mwm with a given name.
/// @precondition This function is always called under mutex m_lock.
- MwmId GetMwmIdByCountryFileImpl(platform::CountryFile const & countryFile) const;
+ MwmId GetMwmIdByFileNameImpl(TMwmFileName const & fileName) const;
/// @precondition This function is always called under mutex m_lock.
WARN_UNUSED_RESULT inline MwmLock GetLock(MwmId const & id)
@@ -241,9 +236,12 @@ protected:
// This method is called under m_lock when mwm is removed from a
// registry.
- virtual void OnMwmDeregistered(platform::LocalCountryFile const & localFile) {}
+ virtual void OnMwmDeleted(shared_ptr<MwmInfo> const & info) {}
+
+ // This method is called under m_lock when mwm is ready for update.
+ virtual void OnMwmReadyForUpdate(shared_ptr<MwmInfo> const & info) {}
- map<string, vector<shared_ptr<MwmInfo>>> m_info;
+ TMwmInfoTable m_info;
mutable mutex m_lock;
};
diff --git a/integration_tests/osrm_test_tools.cpp b/integration_tests/osrm_test_tools.cpp
index 4bf6cd94b8..90f9dbeaa9 100644
--- a/integration_tests/osrm_test_tools.cpp
+++ b/integration_tests/osrm_test_tools.cpp
@@ -11,8 +11,6 @@
#include "map/feature_vec_model.hpp"
-#include "platform/local_country_file.hpp"
-#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/preferred_languages.hpp"
@@ -22,7 +20,6 @@
using namespace routing;
-using platform::LocalCountryFile;
namespace
{
@@ -37,19 +34,19 @@ namespace
namespace integration
{
- shared_ptr<model::FeaturesFetcher> CreateFeaturesFetcher(vector<LocalCountryFile> const & localFiles)
+ shared_ptr<model::FeaturesFetcher> CreateFeaturesFetcher(vector<string> const & mapNames)
{
size_t const maxOpenFileNumber = 1024;
ChangeMaxNumberOfOpenFiles(maxOpenFileNumber);
shared_ptr<model::FeaturesFetcher> featuresFetcher(new model::FeaturesFetcher);
featuresFetcher->InitClassificator();
- for (LocalCountryFile const & localFile : localFiles)
+ for (auto const mapName : mapNames)
{
- pair<MwmSet::MwmLock, bool> result = featuresFetcher->RegisterMap(localFile);
+ pair<MwmSet::MwmLock, bool> result = featuresFetcher->RegisterMap(mapName);
if (!result.second)
{
- ASSERT(false, ("Can't register", localFile));
+ ASSERT(false, ());
return nullptr;
}
}
@@ -85,27 +82,21 @@ namespace integration
ASSERT(featuresFetcher, ());
ASSERT(searchEngine, ());
- shared_ptr<OsrmRouter> osrmRouter(new OsrmRouter(
- &featuresFetcher->GetIndex(), [searchEngine](m2::PointD const & pt)
- {
- return searchEngine->GetCountryFile(pt);
- },
- [](string const & countryFileName)
- {
- return make_shared<LocalCountryFile>(LocalCountryFile::MakeForTesting(countryFileName));
- }));
+ shared_ptr<OsrmRouter> osrmRouter(new OsrmRouter(&featuresFetcher->GetIndex(),
+ [searchEngine](m2::PointD const & pt)
+ {
+ return searchEngine->GetCountryFile(pt);
+ }));
return osrmRouter;
}
class OsrmRouterComponents
{
public:
- OsrmRouterComponents(vector<LocalCountryFile> const & localFiles)
- : m_featuresFetcher(CreateFeaturesFetcher(localFiles)),
- m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
- m_osrmRouter(CreateOsrmRouter(m_featuresFetcher, m_searchEngine))
- {
- }
+ OsrmRouterComponents(vector<string> const & mapNames)
+ : m_featuresFetcher(CreateFeaturesFetcher(mapNames)),
+ m_searchEngine(CreateSearchEngine(m_featuresFetcher)),
+ m_osrmRouter(CreateOsrmRouter(m_featuresFetcher, m_searchEngine)) {}
OsrmRouter * GetOsrmRouter() const { return m_osrmRouter.get(); }
search::Engine * GetSearchEngine() const { return m_searchEngine.get(); }
@@ -115,17 +106,28 @@ namespace integration
shared_ptr<OsrmRouter> m_osrmRouter;
};
- shared_ptr<OsrmRouterComponents> LoadMaps(vector<LocalCountryFile> const & localFiles)
+ void GetMapNames(vector<string> & maps)
+ {
+ Platform const & pl = GetPlatform();
+
+ pl.GetFilesByExt(pl.ResourcesDir(), DATA_FILE_EXTENSION, maps);
+ pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, maps);
+
+ sort(maps.begin(), maps.end());
+ maps.erase(unique(maps.begin(), maps.end()), maps.end());
+ }
+
+ shared_ptr<OsrmRouterComponents> LoadMaps(vector<string> const & mapNames)
{
- return shared_ptr<OsrmRouterComponents>(new OsrmRouterComponents(localFiles));
+ return shared_ptr<OsrmRouterComponents>(new OsrmRouterComponents(mapNames));
}
shared_ptr<OsrmRouterComponents> LoadAllMaps()
{
- vector<LocalCountryFile> localFiles;
- platform::FindAllLocalMaps(localFiles);
- ASSERT(!localFiles.empty(), ());
- return LoadMaps(localFiles);
+ vector<string> maps;
+ GetMapNames(maps);
+ ASSERT(!maps.empty(), ());
+ return LoadMaps(maps);
}
OsrmRouterComponents & GetAllMaps()
diff --git a/integration_tests/osrm_test_tools.hpp b/integration_tests/osrm_test_tools.hpp
index b6d23146d7..8bc5608e7a 100644
--- a/integration_tests/osrm_test_tools.hpp
+++ b/integration_tests/osrm_test_tools.hpp
@@ -8,8 +8,6 @@
#include "routing/osrm_router.hpp"
-#include "platform/local_country_file.hpp"
-
/*
* These tests are developed to simplify routing integration tests writing.
* You can use the interface bellow however you want but there are some hints.
@@ -48,7 +46,7 @@ namespace integration
OsrmRouterComponents & routerComponents);
OsrmRouterComponents & GetAllMaps();
- shared_ptr<OsrmRouterComponents> LoadMaps(vector<platform::LocalCountryFile> const & localFiles);
+ shared_ptr<OsrmRouterComponents> LoadMaps(vector<string> const & mapNames);
TRouteResult CalculateRoute(OsrmRouterComponents const & routerComponents,
m2::PointD const & startPoint, m2::PointD const & startDirection,
m2::PointD const & finalPoint);
diff --git a/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm b/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm
index c1ff8c6a9c..567183be8d 100644
--- a/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm
+++ b/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm
@@ -100,4 +100,4 @@ extern UIColor * const kActiveDownloaderViewColor;
self.downloadButton.minY = self.notNowButton.frame.origin.y;
}
-@end
+@end \ No newline at end of file
diff --git a/map/active_maps_layout.cpp b/map/active_maps_layout.cpp
index 090cef36b5..8dc200ded3 100644
--- a/map/active_maps_layout.cpp
+++ b/map/active_maps_layout.cpp
@@ -36,14 +36,14 @@ ActiveMapsLayout::~ActiveMapsLayout()
#endif
}
-void ActiveMapsLayout::Init(vector<platform::CountryFile> const & files)
+void ActiveMapsLayout::Init(vector<string> const & maps)
{
Clear();
Storage & storage = GetStorage();
- for (auto const & file : files)
+ for (auto const & file : maps)
{
- vector<TIndex> arr = storage.FindAllIndexesByFile(file.GetNameWithoutExt());
+ vector<TIndex> arr = storage.FindAllIndexesByFile(Storage::MapWithoutExt(file));
if (!arr.empty())
{
TStatus status;
@@ -53,9 +53,7 @@ void ActiveMapsLayout::Init(vector<platform::CountryFile> const & files)
m_items.push_back({ arr, status, options, options });
}
else
- {
LOG(LWARNING, ("Can't find map index for", file));
- }
}
auto const comparatorFn = [&storage] (Item const & lhs, Item const & rhs)
@@ -239,7 +237,7 @@ LocalAndRemoteSizeT const ActiveMapsLayout::GetRemoteCountrySizes(TGroup const &
LocalAndRemoteSizeT const ActiveMapsLayout::GetRemoteCountrySizes(TIndex const & index) const
{
- platform::CountryFile const & c = GetStorage().CountryByIndex(index).GetFile();
+ CountryFile const & c = GetStorage().CountryByIndex(index).GetFile();
size_t const mapSize = c.GetRemoteSize(TMapOptions::EMap);
return { mapSize, c.GetRemoteSize(TMapOptions::ECarRouting) };
}
@@ -267,7 +265,7 @@ void ActiveMapsLayout::DownloadMap(TIndex const & index, TMapOptions const & opt
else
{
Storage const & s = GetStorage();
- vector<TIndex> arr = s.FindAllIndexesByFile(s.GetCountryFile(index).GetNameWithoutExt());
+ vector<TIndex> arr = s.FindAllIndexesByFile(s.CountryFileNameWithoutExt(index));
int position = InsertInGroup(TGroup::ENewMap, { arr, TStatus::ENotDownloaded, validOptions, validOptions });
NotifyInsertion(TGroup::ENewMap, position);
}
diff --git a/map/active_maps_layout.hpp b/map/active_maps_layout.hpp
index 331d17296b..27c1e101e4 100644
--- a/map/active_maps_layout.hpp
+++ b/map/active_maps_layout.hpp
@@ -1,10 +1,9 @@
#pragma once
-#include "storage/index.hpp"
#include "storage/storage_defines.hpp"
+#include "storage/index.hpp"
#include "platform/country_defines.hpp"
-#include "platform/country_file.hpp"
#include "base/buffer_vector.hpp"
@@ -96,7 +95,7 @@ private:
Storage const & GetStorage() const;
Storage & GetStorage();
- void Init(vector<platform::CountryFile> const & files);
+ void Init(vector<string> const & maps);
void Clear();
void ShowMap(TIndex const & index);
diff --git a/map/benchmark_engine.cpp b/map/benchmark_engine.cpp
index 208cd1bb94..3c99a0b9f9 100644
--- a/map/benchmark_engine.cpp
+++ b/map/benchmark_engine.cpp
@@ -133,11 +133,8 @@ void BenchmarkEngine::PrepareMaps()
// add only maps needed for benchmarks
MapsCollector collector;
ForEachBenchmarkRecord(collector);
- for (string const & map : collector.m_maps)
- {
- LOG(LINFO, ("Looking for:", map));
- m_framework->RegisterMap(platform::LocalCountryFile::MakeForTesting(map));
- }
+ for_each(collector.m_maps.begin(), collector.m_maps.end(),
+ bind(&Framework::RegisterMap, m_framework, _1));
}
BenchmarkEngine::BenchmarkEngine(Framework * fw)
diff --git a/map/benchmark_tool/features_loading.cpp b/map/benchmark_tool/features_loading.cpp
index a316188916..c9fd84ab7d 100644
--- a/map/benchmark_tool/features_loading.cpp
+++ b/map/benchmark_tool/features_loading.cpp
@@ -9,8 +9,6 @@
#include "platform/platform.hpp"
-#include "coding/file_name_utils.hpp"
-
#include "base/macros.hpp"
#include "base/timer.hpp"
@@ -99,20 +97,8 @@ namespace
void RunFeaturesLoadingBenchmark(string const & file, pair<int, int> scaleR, AllResult & res)
{
- string baseName = file;
- my::GetNameFromFullPath(baseName);
-
- // Check that file is relative to maps dir.
- ASSERT_EQUAL(file, baseName, ());
-
- string countryFileName = baseName;
- my::GetNameWithoutExt(countryFileName);
-
- platform::LocalCountryFile localFile =
- platform::LocalCountryFile::MakeForTesting(countryFileName);
-
feature::DataHeader header;
- LoadMapHeader(GetPlatform().GetCountryReader(localFile, TMapOptions::EMap), header);
+ LoadMapHeader(GetPlatform().GetReader(file), header);
pair<int, int> const r = header.GetScaleRange();
if (r.first > scaleR.first)
@@ -124,7 +110,7 @@ void RunFeaturesLoadingBenchmark(string const & file, pair<int, int> scaleR, All
return;
model::FeaturesFetcher src;
- UNUSED_VALUE(src.RegisterMap(platform::LocalCountryFile::MakeForTesting(countryFileName)));
+ UNUSED_VALUE(src.RegisterMap(file));
RunBenchmark(src, header.GetBounds(), scaleR, res);
}
diff --git a/map/country_tree.cpp b/map/country_tree.cpp
index 4d62070703..e0c53bccd2 100644
--- a/map/country_tree.cpp
+++ b/map/country_tree.cpp
@@ -65,7 +65,7 @@ CountryTree & CountryTree::operator=(CountryTree const & other)
return *this;
}
-void CountryTree::Init(vector<platform::CountryFile> const & maps)
+void CountryTree::Init(vector<string> const & maps)
{
ASSERT(IsValid(), ());
m_layout->Init(maps);
diff --git a/map/country_tree.hpp b/map/country_tree.hpp
index 2a28dce7a3..ab8e88838a 100644
--- a/map/country_tree.hpp
+++ b/map/country_tree.hpp
@@ -5,8 +5,6 @@
#include "storage/index.hpp"
#include "storage/storage_defines.hpp"
-#include "platform/country_file.hpp"
-
#include "base/buffer_vector.hpp"
#include "std/string.hpp"
@@ -38,7 +36,7 @@ public:
CountryTree & operator=(CountryTree const & other);
/// @param[in] Sorted vector of current .mwm files.
- void Init(vector<platform::CountryFile> const & maps);
+ void Init(vector<string> const & maps);
void Clear();
ActiveMapsLayout & GetActiveMapLayout();
diff --git a/map/feature_vec_model.cpp b/map/feature_vec_model.cpp
index ca5f1f4ba0..ec7b701f25 100644
--- a/map/feature_vec_model.cpp
+++ b/map/feature_vec_model.cpp
@@ -13,20 +13,9 @@
#include "std/bind.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
namespace model
{
-FeaturesFetcher::FeaturesFetcher()
-{
- m_multiIndex.AddObserver(*this);
-}
-
-FeaturesFetcher::~FeaturesFetcher()
-{
- m_multiIndex.RemoveObserver(*this);
-}
// While reading any files (classificator or mwm), there are 2 types of possible exceptions:
// Reader::Exception, FileAbsentException.
@@ -44,47 +33,71 @@ void FeaturesFetcher::InitClassificator()
}
}
-pair<MwmSet::MwmLock, bool> FeaturesFetcher::RegisterMap(LocalCountryFile const & localFile)
+pair<MwmSet::MwmLock, bool> FeaturesFetcher::RegisterMap(string const & file)
{
- string const countryFileName = localFile.GetCountryFile().GetNameWithoutExt();
try
{
- pair<MwmSet::MwmLock, bool> result = m_multiIndex.RegisterMap(localFile);
- if (!result.second)
+ pair<MwmSet::MwmLock, bool> p = m_multiIndex.RegisterMap(file);
+ if (!p.second)
{
- LOG(LWARNING, ("Can't add map", countryFileName,
- "Probably it's already added or has newer data version."));
- return result;
+ LOG(LWARNING,
+ ("Can't add map", file, "Probably it's already added or has newer data version."));
+ return p;
}
- MwmSet::MwmLock & lock = result.first;
+ MwmSet::MwmLock & lock = p.first;
ASSERT(lock.IsLocked(), ("Mwm lock invariant violation."));
m_rect.Add(lock.GetInfo()->m_limitRect);
- return result;
+ return p;
}
catch (RootException const & e)
{
- LOG(LERROR, ("IO error while adding ", countryFileName, " map. ", e.what()));
+ LOG(LERROR, ("IO error while adding ", file, " map. ", e.what()));
return make_pair(MwmSet::MwmLock(), false);
}
}
-bool FeaturesFetcher::DeregisterMap(CountryFile const & countryFile)
+void FeaturesFetcher::DeregisterMap(string const & file) { m_multiIndex.Deregister(file); }
+
+void FeaturesFetcher::DeregisterAllMaps() { m_multiIndex.DeregisterAll(); }
+
+bool FeaturesFetcher::DeleteMap(string const & file)
+{
+ return m_multiIndex.DeleteMap(file);
+}
+
+pair<MwmSet::MwmLock, Index::UpdateStatus> FeaturesFetcher::UpdateMap(string const & file)
{
- return m_multiIndex.Deregister(countryFile);
+ return m_multiIndex.UpdateMap(file);
}
-void FeaturesFetcher::DeregisterAllMaps() { m_multiIndex.DeregisterAll(); }
+//void FeaturesFetcher::Clean()
+//{
+// m_rect.MakeEmpty();
+// // TODO: m_multiIndex.Clear(); - is it needed?
+//}
void FeaturesFetcher::ClearCaches()
{
m_multiIndex.ClearCache();
}
-void FeaturesFetcher::OnMapDeregistered(platform::LocalCountryFile const & localFile)
+/*
+bool FeaturesFetcher::IsLoaded(m2::PointD const & pt) const
{
- if (m_onMapDeregistered)
- m_onMapDeregistered(localFile);
+ vector<MwmInfo> info;
+ m_multiIndex.GetMwmInfo(info);
+
+ for (size_t i = 0; i < info.size(); ++i)
+ if (info[i].IsExist() &&
+ info[i].GetType() == MwmInfo::COUNTRY &&
+ info[i].m_limitRect.IsPointInside(pt))
+ {
+ return true;
+ }
+
+ return false;
}
+*/
m2::RectD FeaturesFetcher::GetWorldRect() const
{
diff --git a/map/feature_vec_model.hpp b/map/feature_vec_model.hpp
index 9698d5a745..b671ba0721 100644
--- a/map/feature_vec_model.hpp
+++ b/map/feature_vec_model.hpp
@@ -15,7 +15,7 @@ namespace model
{
//#define USE_BUFFER_READER
-class FeaturesFetcher : public Index::Observer
+ class FeaturesFetcher
{
public:
#ifdef USE_BUFFER_READER
@@ -24,56 +24,58 @@ class FeaturesFetcher : public Index::Observer
typedef ModelReaderPtr ReaderT;
#endif
- typedef function<void(platform::LocalCountryFile const &)> TMapDeregisteredCallback;
-
private:
m2::RectD m_rect;
Index m_multiIndex;
- TMapDeregisteredCallback m_onMapDeregistered;
-
public:
- FeaturesFetcher();
-
- virtual ~FeaturesFetcher();
-
void InitClassificator();
- inline void SetOnMapDeregisteredCallback(TMapDeregisteredCallback const & callback)
- {
- m_onMapDeregistered = callback;
- }
-
/// Registers a new map.
///
- /// \return A pair of an MwmLock and a flag. There are three cases:
- /// * the map is newer than the newest registered - returns
- /// active lock and set flag
- /// * the map is older than the newest registered - returns inactive lock and
- /// unset flag.
- /// * the version of the map equals to the version of the newest registered -
- /// returns active lock and unset flag.
- WARN_UNUSED_RESULT pair<MwmSet::MwmLock, bool> RegisterMap(
- platform::LocalCountryFile const & localFile);
+ /// \return A pair of an MwmLock and a flag. MwmLock is locked iff the
+ /// map with fileName was created or already exists. Flag
+ /// is set when the map was registered for a first
+ /// time. Thus, there are three main cases:
+ ///
+ /// * the map already exists - returns active lock and unset flag
+ /// * the map was already registered - returns active lock and set flag
+ /// * the map can't be registered - returns inactive lock and unset flag
+ WARN_UNUSED_RESULT pair<MwmSet::MwmLock, bool> RegisterMap(string const & file);
/// Deregisters a map denoted by file from internal records.
- bool DeregisterMap(platform::CountryFile const & countryFile);
+ void DeregisterMap(string const & file);
/// Deregisters all registered maps.
void DeregisterAllMaps();
+ /// Deletes all files related to map denoted by file.
+ ///
+ /// \return True if a map was successfully deleted.
+ bool DeleteMap(string const & file);
+
+ /// Replaces a map file corresponding to fileName with a new one, when
+ /// it's possible - no clients of the map file. Otherwise, update
+ /// will be delayed.
+ ///
+ /// \return * the map file have been updated - returns active lock and
+ /// UPDATE_STATUS_OK
+ /// * update is delayed because the map is busy - returns active lock and
+ /// UPDATE_STATUS_UPDATE_DELAYED
+ /// * the file isn't suitable for update - returns inactive lock and
+ /// UPDATE_STATUS_BAD_FILE
+ WARN_UNUSED_RESULT pair<MwmSet::MwmLock, Index::UpdateStatus> UpdateMap(string const & file);
+ //@}
+
//void Clean();
void ClearCaches();
- inline bool IsLoaded(string const & countryFileName) const
+ inline bool IsLoaded(string const & fName) const
{
- return m_multiIndex.IsLoaded(platform::CountryFile(countryFileName));
+ return m_multiIndex.IsLoaded(fName);
}
- // Index::Observer overrides:
- void OnMapDeregistered(platform::LocalCountryFile const & localFile) override;
-
//bool IsLoaded(m2::PointD const & pt) const;
/// @name Features enumeration.
diff --git a/map/framework.cpp b/map/framework.cpp
index e4083f8004..9265215902 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -44,11 +44,10 @@
#include "gui/controller.hpp"
-#include "platform/local_country_file_utils.hpp"
#include "platform/measurement_utils.hpp"
-#include "platform/platform.hpp"
-#include "platform/preferred_languages.hpp"
#include "platform/settings.hpp"
+#include "platform/preferred_languages.hpp"
+#include "platform/platform.hpp"
#include "coding/internal/file_data.hpp"
#include "coding/zip_reader.hpp"
@@ -82,8 +81,6 @@ using namespace storage;
using namespace routing;
using namespace location;
-using platform::CountryFile;
-using platform::LocalCountryFile;
#ifdef FIXED_LOCATION
Framework::FixedPosition::FixedPosition()
@@ -98,20 +95,38 @@ namespace
static const int BM_TOUCH_PIXEL_INCREASE = 20;
}
-pair<MwmSet::MwmLock, bool> Framework::RegisterMap(LocalCountryFile const & localFile)
+pair<MwmSet::MwmLock, bool> Framework::RegisterMap(string const & file)
{
- string const countryFileName = localFile.GetCountryFile().GetNameWithoutExt();
- LOG(LINFO, ("Loading map:", countryFileName));
- return m_model.RegisterMap(localFile);
+ LOG(LINFO, ("Loading map:", file));
+
+ pair<MwmSet::MwmLock, bool> p = m_model.RegisterMap(file);
+ if (!p.second)
+ return p;
+ MwmSet::MwmLock const & lock = p.first;
+ ASSERT(lock.IsLocked(), ());
+
+ shared_ptr<MwmInfo> info = lock.GetInfo();
+ ASSERT(info, ());
+
+ if (info->m_version.format == version::v1)
+ {
+ // Now we do force delete of old (April 2011) maps.
+ LOG(LINFO, ("Deleting old map:", file));
+
+ DeregisterMap(file);
+ VERIFY(my::DeleteFileX(GetPlatform().WritablePathForFile(file)), ());
+ return make_pair(MwmSet::MwmLock(), false);
+ }
+
+ return p;
}
-void Framework::DeregisterMap(CountryFile const & countryFile)
+void Framework::DeregisterMap(string const & file) { m_model.DeregisterMap(file); }
+
+void Framework::OnLocationError(TLocationError /*error*/)
{
- m_model.DeregisterMap(countryFile);
}
-void Framework::OnLocationError(TLocationError /*error*/) {}
-
void Framework::OnLocationUpdate(GpsInfo const & info)
{
#ifdef FIXED_LOCATION
@@ -183,6 +198,32 @@ m2::PointD Framework::GetWidgetSize(InformationDisplay::WidgetType widget) const
return m_informationDisplay.GetWidgetSize(widget);
}
+void Framework::GetMaps(vector<string> & maps) const
+{
+ Platform & pl = GetPlatform();
+
+ pl.GetFilesByExt(pl.ResourcesDir(), DATA_FILE_EXTENSION, maps);
+ pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, maps);
+
+ // Remove duplicate maps if they're both present in Resources and in Writable dirs.
+ sort(maps.begin(), maps.end());
+ maps.erase(unique(maps.begin(), maps.end()), maps.end());
+
+#ifdef OMIM_OS_ANDROID
+ // On Android World and WorldCoasts can be stored in alternative /Android/obb/ path.
+ char const * arrCheck[] = { WORLD_FILE_NAME DATA_FILE_EXTENSION,
+ WORLD_COASTS_FILE_NAME DATA_FILE_EXTENSION };
+
+ for (size_t i = 0; i < ARRAY_SIZE(arrCheck); ++i)
+ {
+ auto const it = lower_bound(maps.begin(), maps.end(), arrCheck[i]);
+ if (it == maps.end() || *it != arrCheck[i])
+ maps.insert(it, arrCheck[i]);
+ }
+#endif
+}
+
+
Framework::Framework()
: m_navigator(m_scales),
m_animator(this),
@@ -239,7 +280,6 @@ Framework::Framework()
#endif
m_model.InitClassificator();
- m_model.SetOnMapDeregisteredCallback(bind(&Framework::OnMapDeregistered, this, _1));
LOG(LDEBUG, ("Classificator initialized"));
// To avoid possible races - init search engine once in constructor.
@@ -252,7 +292,7 @@ Framework::Framework()
LOG(LDEBUG, ("Maps initialized"));
// Init storage with needed callback.
- m_storage.Init(bind(&Framework::UpdateAfterDownload, this, _1));
+ m_storage.Init(bind(&Framework::UpdateAfterDownload, this, _1, _2));
LOG(LDEBUG, ("Storage initialized"));
#ifdef USE_PEDESTRIAN_ROUTER
@@ -268,7 +308,6 @@ Framework::Framework()
Framework::~Framework()
{
delete m_benchmarkEngine;
- m_model.SetOnMapDeregisteredCallback(nullptr);
}
void Framework::DrawSingleFrame(m2::PointD const & center, int zoomModifier,
@@ -356,34 +395,44 @@ double Framework::GetVisualScale() const
return m_scales.GetVisualScale();
}
-void Framework::DeleteCountry(storage::TIndex const & index, TMapOptions opt)
+void Framework::DeleteCountry(TIndex const & index, TMapOptions opt)
{
- switch (opt)
+ if (HasOptions(opt, TMapOptions::EMap))
+ opt = TMapOptions::EMapWithCarRouting;
+
+ if (!m_storage.DeleteFromDownloader(index))
{
- case TMapOptions::ENothing:
- return;
- case TMapOptions::EMap: // fall through
- case TMapOptions::EMapWithCarRouting:
+ CountryFile const & file = m_storage.CountryByIndex(index).GetFile();
+
+ if (HasOptions(opt, TMapOptions::EMap))
{
- CountryFile const & countryFile = m_storage.GetCountryFile(index);
- // m_model will notify us when latest map file will be deleted via
- // OnMapDeregistered call.
- if (m_model.DeregisterMap(countryFile))
- {
- InvalidateRect(GetCountryBounds(countryFile.GetNameWithoutExt()), true /* doForceUpdate */);
- }
- // TODO (@ldragunov, @gorshenin): rewrite routing session to use MwmLocks. Thus,
- // it won' be needed to reset it after maps update.
- m_routingSession.Reset();
- return;
+ if (m_model.DeleteMap(file.GetFileWithExt(TMapOptions::EMap)))
+ InvalidateRect(GetCountryBounds(file.GetFileWithoutExt()), true);
}
- case TMapOptions::ECarRouting:
- m_routingSession.Reset();
- m_storage.DeleteCountry(index, opt);
- return;
+
+ if (HasOptions(opt, TMapOptions::ECarRouting))
+ m_routingSession.DeleteIndexFile(file.GetFileWithExt(TMapOptions::ECarRouting));
+
+ m_storage.NotifyStatusChanged(index);
+
+ DeleteCountryIndexes(m_storage.CountryFileNameWithoutExt(index));
}
}
+void Framework::DeleteCountryIndexes(string const & mwmName)
+{
+ m_routingSession.Reset();
+
+ Platform::FilesList files;
+ Platform const & pl = GetPlatform();
+ string const path = pl.WritablePathForCountryIndexes(mwmName);
+
+ /// @todo We need correct regexp for any file (not including "." and "..").
+ pl.GetFilesByRegExp(path, mwmName + "\\..*", files);
+ for (auto const & file : files)
+ (void) my::DeleteFileX(path + file);
+}
+
void Framework::DownloadCountry(TIndex const & index, TMapOptions opt)
{
m_storage.DownloadCountry(index, opt);
@@ -410,8 +459,7 @@ m2::RectD Framework::GetCountryBounds(string const & file) const
m2::RectD Framework::GetCountryBounds(TIndex const & index) const
{
- CountryFile const & file = m_storage.GetCountryFile(index);
- return GetCountryBounds(file.GetNameWithoutExt());
+ return GetCountryBounds(m_storage.CountryFileNameWithoutExt(index));
}
void Framework::ShowCountry(TIndex const & index)
@@ -421,57 +469,72 @@ void Framework::ShowCountry(TIndex const & index)
ShowRectEx(GetCountryBounds(index));
}
-void Framework::UpdateAfterDownload(LocalCountryFile const & localFile)
+void Framework::UpdateAfterDownload(string const & fileName, TMapOptions opt)
{
- // TODO (@ldragunov, @gorshenin): rewrite routing session to use MwmLocks. Thus,
- // it won' be needed to reset it after maps update.
- m_routingSession.Reset();
+ if (HasOptions(opt, TMapOptions::EMap))
+ {
+ // Delete old (splitted) map files, if any.
+ char const * arr[] = { "Japan", "Brazil" };
+ for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
+ if (fileName.find(arr[i]) == 0)
+ {
+ if (m_model.DeleteMap(string(arr[i]) + DATA_FILE_EXTENSION))
+ Invalidate(true);
- if (!HasOptions(localFile.GetFiles(), TMapOptions::EMap))
- return;
+ // Routing index doesn't exist for this map files.
+ }
- // Add downloaded map.
- pair<MwmSet::MwmLock, bool> const result = m_model.RegisterMap(localFile);
- MwmSet::MwmLock const & lock = result.first;
- if (lock.IsLocked())
- InvalidateRect(lock.GetInfo()->m_limitRect, true /* doForceUpdate */);
- GetSearchEngine()->ClearViewportsCache();
-}
+ // Add downloaded map.
+ pair<MwmSet::MwmLock, Index::UpdateStatus> const p = m_model.UpdateMap(fileName);
+ if (p.second == Index::UPDATE_STATUS_OK)
+ {
+ MwmSet::MwmLock const & lock = p.first;
+ ASSERT(lock.IsLocked(), ());
+ InvalidateRect(lock.GetInfo()->m_limitRect, true);
+ }
-void Framework::OnMapDeregistered(platform::LocalCountryFile const & localFile)
-{
- m_storage.DeleteCustomCountryVersion(localFile);
+ GetSearchEngine()->ClearViewportsCache();
+ }
+
+ // Replace routing file.
+ if (HasOptions(opt, TMapOptions::ECarRouting))
+ {
+ string routingName = fileName + ROUTING_FILE_EXTENSION;
+ m_routingSession.DeleteIndexFile(routingName);
+
+ routingName = GetPlatform().WritableDir() + routingName;
+ VERIFY(my::RenameFileX(routingName + READY_FILE_EXTENSION, routingName), ());
+ }
+
+ string countryName(fileName);
+ my::GetNameWithoutExt(countryName);
+ DeleteCountryIndexes(countryName);
}
void Framework::RegisterAllMaps()
{
- ASSERT(!m_storage.IsDownloadInProgress(),
- ("Registering maps while map downloading leads to removing downloading maps from "
- "ActiveMapsListener::m_items."));
-
- platform::CleanupMapsDirectory();
- m_storage.RegisterAllLocalMaps();
+ ASSERT(!Storage().IsDownloadInProgress(),
+ ("Registering maps while map downloading leads to removing downloading maps from ActiveMapsListener::m_items."));
+ //ASSERT(m_model.IsEmpty(), ());
- int minFormat = numeric_limits<int>::max();
- vector<CountryFile> maps;
- m_storage.GetLocalMaps(maps);
+ int minVersion = numeric_limits<int>::max();
- for (CountryFile const & countryFile : maps)
+ vector<string> maps;
+ GetMaps(maps);
+ for_each(maps.begin(), maps.end(), [&](string const & file)
{
- shared_ptr<LocalCountryFile> localFile = m_storage.GetLatestLocalFile(countryFile);
- if (!localFile)
- continue;
- pair<MwmSet::MwmLock, bool> const p = RegisterMap(*localFile);
- if (!p.second)
- continue;
- MwmSet::MwmLock const & lock = p.first;
- ASSERT(lock.IsLocked(), ());
- minFormat = min(minFormat, static_cast<int>(lock.GetInfo()->m_version.format));
- }
+ pair<MwmSet::MwmLock, bool> const p = RegisterMap(file);
+ if (p.second)
+ {
+ MwmSet::MwmLock const & lock = p.first;
+ ASSERT(lock.IsLocked(), ());
+ minVersion = min(minVersion, static_cast<int>(lock.GetInfo()->m_version.format));
+ }
+ });
m_countryTree.Init(maps);
- GetSearchEngine()->SupportOldFormat(minFormat < version::v3);
+ GetSearchEngine()->SupportOldFormat(minVersion < version::v3);
}
void Framework::DeregisterAllMaps()
@@ -2149,27 +2212,22 @@ void Framework::SetRouter(RouterType type)
alohalytics::LogEvent("Routing_CalculatingRoute", statistics);
};
- auto countryFileGetter = [this](m2::PointD const & p) -> string
- {
- // TODO (@gorshenin): fix search engine to return CountryFile
- // instances instead of plain strings.
- return GetSearchEngine()->GetCountryFile(p);
- };
- auto localFileGetter = [this](string const & countryFile) -> shared_ptr<LocalCountryFile>
- {
- return m_storage.GetLatestLocalFile(CountryFile(countryFile));
- };
-
unique_ptr<IRouter> router;
if (type == RouterType::Pedestrian)
{
- router = CreatePedestrianAStarBidirectionalRouter(m_model.GetIndex(), countryFileGetter,
- routingVisualizerFn);
+ auto const countryFileFn = [this](m2::PointD const & pt)
+ {
+ return GetSearchEngine()->GetCountryFile(pt) + DATA_FILE_EXTENSION;
+ };
+ router = CreatePedestrianAStarBidirectionalRouter(m_model.GetIndex(), countryFileFn, routingVisualizerFn);
}
else
{
- router.reset(new OsrmRouter(&m_model.GetIndex(), countryFileGetter, localFileGetter,
- routingVisualizerFn));
+ auto const countryFileFn = [this](m2::PointD const & pt)
+ {
+ return GetSearchEngine()->GetCountryFile(pt);
+ };
+ router.reset(new OsrmRouter(&m_model.GetIndex(), countryFileFn, routingVisualizerFn));
}
m_routingSession.SetRouter(move(router), routingStatisticsFn);
diff --git a/map/framework.hpp b/map/framework.hpp
index 89f0541bda..d0e6a723b2 100644
--- a/map/framework.hpp
+++ b/map/framework.hpp
@@ -135,10 +135,8 @@ protected:
static const int TOUCH_PIXEL_RADIUS = 20;
/// This function is called by m_storage to notify that country downloading is finished.
- void UpdateAfterDownload(platform::LocalCountryFile const & localFile);
-
- /// This function is called by m_model when the map file is deregistered.
- void OnMapDeregistered(platform::LocalCountryFile const & localFile);
+ /// @param[in] file Country file name (without extensions).
+ void UpdateAfterDownload(string const & file, TMapOptions opt);
//my::Timer m_timer;
inline double ElapsedSeconds() const
@@ -157,7 +155,10 @@ protected:
void ClearAllCaches();
- void DeregisterMap(platform::CountryFile const & countryFile);
+ void DeregisterMap(string const & file);
+
+ /// Deletes user calculated indexes on country updates
+ void DeleteCountryIndexes(string const & mwmName);
public:
Framework();
@@ -188,6 +189,11 @@ public:
void ReleaseSingleFrameRenderer();
bool IsSingleFrameRendererInited() const;
+ /// @name Process storage connecting/disconnecting.
+ //@{
+ /// @param[out] maps File names without path.
+ void GetMaps(vector<string> & maps) const;
+
/// Registers all local map files in internal indexes.
void RegisterAllMaps();
@@ -198,7 +204,7 @@ public:
///
/// @return True and inner mwm data version from header in version
/// or false in case of errors.
- pair<MwmSet::MwmLock, bool> RegisterMap(platform::LocalCountryFile const & localFile);
+ pair<MwmSet::MwmLock, bool> RegisterMap(string const & file);
//@}
/// Deletes all disk files corresponding to country.
diff --git a/map/map_tests/bookmarks_test.cpp b/map/map_tests/bookmarks_test.cpp
index 51cc6e854b..8edd6d69f6 100644
--- a/map/map_tests/bookmarks_test.cpp
+++ b/map/map_tests/bookmarks_test.cpp
@@ -400,7 +400,7 @@ UNIT_TEST(Bookmarks_AddressInfo)
// Maps added in constructor (we need minsk-pass.mwm only)
Framework fm;
fm.DeregisterAllMaps();
- fm.RegisterMap(platform::LocalCountryFile::MakeForTesting("minsk-pass"));
+ fm.RegisterMap("minsk-pass.mwm");
fm.OnSize(800, 600);
// assume that developers have English or Russian system language :)
diff --git a/map/mwm_tests/multithread_mwm_test.cpp b/map/mwm_tests/multithread_mwm_test.cpp
index 974cb436a4..22529e5752 100644
--- a/map/mwm_tests/multithread_mwm_test.cpp
+++ b/map/mwm_tests/multithread_mwm_test.cpp
@@ -63,7 +63,7 @@ namespace
SourceT src;
src.InitClassificator();
- UNUSED_VALUE(src.RegisterMap(platform::LocalCountryFile::MakeForTesting(file)));
+ UNUSED_VALUE(src.RegisterMap(file + DATA_FILE_EXTENSION));
// Check that country rect is valid and not infinity.
m2::RectD const r = src.GetWorldRect();
diff --git a/map/mwm_tests/mwm_foreach_test.cpp b/map/mwm_tests/mwm_foreach_test.cpp
index ce23dc7eea..6036885f89 100644
--- a/map/mwm_tests/mwm_foreach_test.cpp
+++ b/map/mwm_tests/mwm_foreach_test.cpp
@@ -247,18 +247,17 @@ public:
}
};
-void RunTest(string const & countryFileName)
+void RunTest(string const & file)
{
model::FeaturesFetcher src1;
src1.InitClassificator();
- platform::LocalCountryFile localFile(platform::LocalCountryFile::MakeForTesting(countryFileName));
- UNUSED_VALUE(src1.RegisterMap(localFile));
+ UNUSED_VALUE(src1.RegisterMap(file));
vector<m2::RectD> rects;
rects.push_back(src1.GetWorldRect());
- ModelReaderPtr reader = GetPlatform().GetCountryReader(localFile, TMapOptions::EMap);
+ ModelReaderPtr reader = GetPlatform().GetReader(file);
while (!rects.empty())
{
@@ -302,10 +301,15 @@ void RunTest(string const & countryFileName)
}
}
+void RunTestForChoice(string const & fName)
+{
+ RunTest(fName + DATA_FILE_EXTENSION);
+}
+
}
UNIT_TEST(ForEach_QueryResults)
{
- RunTest("minsk-pass");
+ RunTestForChoice("minsk-pass");
//RunTestForChoice("london-center");
}
diff --git a/map/mwm_tests/mwm_index_test.cpp b/map/mwm_tests/mwm_index_test.cpp
index 700d1ddf12..5f3b3e509e 100644
--- a/map/mwm_tests/mwm_index_test.cpp
+++ b/map/mwm_tests/mwm_index_test.cpp
@@ -36,11 +36,10 @@ public:
}
};
-bool RunTest(string const & countryFileName, int lowS, int highS)
+bool RunTest(string const & fileName, int lowS, int highS)
{
model::FeaturesFetcher src;
- pair<MwmSet::MwmLock, bool> const p =
- src.RegisterMap(platform::LocalCountryFile::MakeForTesting(countryFileName));
+ pair<MwmSet::MwmLock, bool> const p = src.RegisterMap(fileName);
if (!p.second)
return false;
MwmSet::MwmLock const & lock = p.first;
@@ -67,8 +66,8 @@ UNIT_TEST(ForEachFeatureID_Test)
classificator::Load();
/// @todo Uncomment World* checking after next map data update.
- // TEST(RunTest("World", 0, scales::GetUpperWorldScale()), ());
- // TEST(RunTest("WorldCoasts.mwm", 0, scales::GetUpperWorldScale()), ());
- // TEST(RunTest("Belarus", scales::GetUpperWorldScale() + 1, scales::GetUpperStyleScale()), ());
- TEST(RunTest("minsk-pass", scales::GetUpperWorldScale() + 1, scales::GetUpperStyleScale()), ());
+ //TEST(RunTest("World.mwm", 0, scales::GetUpperWorldScale()), ());
+ //TEST(RunTest("WorldCoasts.mwm", 0, scales::GetUpperWorldScale()), ());
+ //TEST(RunTest("Belarus.mwm", scales::GetUpperWorldScale() + 1, scales::GetUpperStyleScale()), ());
+ TEST(RunTest("minsk-pass.mwm", scales::GetUpperWorldScale() + 1, scales::GetUpperStyleScale()), ());
}
diff --git a/map/routing_session.cpp b/map/routing_session.cpp
index 431f13ee00..64aa286261 100644
--- a/map/routing_session.cpp
+++ b/map/routing_session.cpp
@@ -8,10 +8,12 @@
#include "coding/internal/file_data.hpp"
+
using namespace location;
namespace routing
{
+
static int const ON_ROUTE_MISSED_COUNT = 5;
RoutingSession::RoutingSession()
@@ -44,7 +46,7 @@ void RoutingSession::RebuildRoute(m2::PointD const & startPoint, TReadyCallbackF
DoReadyCallback(*this, callback, m_routeSessionMutex));
}
-void RoutingSession::DoReadyCallback::operator()(Route & route, IRouter::ResultCode e)
+void RoutingSession::DoReadyCallback::operator() (Route & route, IRouter::ResultCode e)
{
threads::MutexGuard guard(m_routeSessionMutexInner);
UNUSED_VALUE(guard);
@@ -65,8 +67,6 @@ void RoutingSession::Reset()
threads::MutexGuard guard(m_routeSessionMutex);
UNUSED_VALUE(guard);
Route(string()).Swap(m_route);
-
- m_router->ClearState();
}
RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const & position,
@@ -196,8 +196,14 @@ void RoutingSession::SetRouter(unique_ptr<IRouter> && router, TRoutingStatistics
m_router.reset(new AsyncRouter(move(router), routingStatisticsFn));
}
-void RoutingSession::MatchLocationToRoute(location::GpsInfo & location,
- location::RouteMatchingInfo & routeMatchingInfo) const
+void RoutingSession::DeleteIndexFile(string const & fileName)
+{
+ Reset();
+ m_router->ClearState();
+ (void) my::DeleteFileX(GetPlatform().WritablePathForFile(fileName));
+}
+
+void RoutingSession::MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const
{
if (m_state != State::OnRoute)
return;
@@ -206,4 +212,5 @@ void RoutingSession::MatchLocationToRoute(location::GpsInfo & location,
UNUSED_VALUE(guard);
m_route.MatchLocationToRoute(location, routeMatchingInfo);
}
+
}
diff --git a/map/routing_session.hpp b/map/routing_session.hpp
index 98a7606ae3..fd1abdb910 100644
--- a/map/routing_session.hpp
+++ b/map/routing_session.hpp
@@ -13,25 +13,24 @@
#include "base/mutex.hpp"
-namespace location
-{
-class RouteMatchingInfo;
-}
+
+namespace location { class RouteMatchingInfo;}
namespace routing
{
+
class RoutingSession
{
public:
enum State
{
RoutingNotActive,
- RouteBuilding, // we requested a route and wait when it will be builded
- RouteNotReady, // routing was not build
- RouteNotStarted, // route is builded but the user isn't on it
- OnRoute, // user follows the route
- RouteNeedRebuild, // user left the route
- RouteFinished // destination point is reached but the session isn't closed
+ RouteBuilding, // we requested a route and wait when it will be builded
+ RouteNotReady, // routing was not build
+ RouteNotStarted, // route is builded but the user isn't on it
+ OnRoute, // user follows the route
+ RouteNeedRebuild, // user left the route
+ RouteFinished // destination point is reached but the session isn't closed
};
/*
@@ -48,7 +47,7 @@ public:
typedef function<void(map<string, string> const &)> TRoutingStatisticsCallback;
- typedef function<void(Route const &, IRouter::ResultCode)> TReadyCallbackFn;
+ typedef function<void (Route const &, IRouter::ResultCode)> TReadyCallbackFn;
RoutingSession();
@@ -56,8 +55,7 @@ public:
TRoutingStatisticsCallback const & routingStatisticsFn);
/// @param[in] startPoint and endPoint in mercator
- void BuildRoute(m2::PointD const & startPoint, m2::PointD const & endPoint,
- TReadyCallbackFn const & callback);
+ void BuildRoute(m2::PointD const & startPoint, m2::PointD const & endPoint, TReadyCallbackFn const & callback);
void RebuildRoute(m2::PointD const & startPoint, TReadyCallbackFn const & callback);
m2::PointD GetEndPoint() const { return m_endPoint; }
@@ -70,8 +68,8 @@ public:
State OnLocationPositionChanged(m2::PointD const & position, location::GpsInfo const & info);
void GetRouteFollowingInfo(location::FollowingInfo & info) const;
- void MatchLocationToRoute(location::GpsInfo & location,
- location::RouteMatchingInfo & routeMatchingInfo) const;
+ void DeleteIndexFile(string const & fileName);
+ void MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const;
// TODO (Dragunov) Make activation of the pedestrian routing
void ActivateAdditionalFeatures() {}
@@ -83,13 +81,12 @@ private:
TReadyCallbackFn m_callback;
threads::Mutex & m_routeSessionMutexInner;
- DoReadyCallback(RoutingSession & rs, TReadyCallbackFn const & cb,
- threads::Mutex & routeSessionMutex)
- : m_rs(rs), m_callback(cb), m_routeSessionMutexInner(routeSessionMutex)
+ DoReadyCallback(RoutingSession & rs, TReadyCallbackFn const & cb, threads::Mutex & routeSessionMutex)
+ : m_rs(rs), m_callback(cb), m_routeSessionMutexInner(routeSessionMutex)
{
}
- void operator()(Route & route, IRouter::ResultCode e);
+ void operator() (Route & route, IRouter::ResultCode e);
};
void AssignRoute(Route & route);
@@ -106,4 +103,5 @@ private:
int m_moveAwayCounter;
m2::PointD m_lastGoodPosition;
};
+
}
diff --git a/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp b/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp
index fe9e956d73..3cffe31eaa 100644
--- a/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp
+++ b/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp
@@ -17,13 +17,11 @@
#include "std/utility.hpp"
#include "std/vector.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
-
namespace
{
string const MAP_NAME = "UK_England";
+string const MAP_FILE = MAP_NAME + DATA_FILE_EXTENSION;
// Since for test purposes we compare routes lengths to check algorithms consistency,
// we should use simplified pedestrian model, where all available edges have max speed
@@ -71,7 +69,7 @@ m2::PointD GetPointOnEdge(routing::Edge & e, double posAlong)
void GetNearestPedestrianEdges(Index & index, m2::PointD const & pt, vector<pair<routing::Edge, m2::PointD>> & edges)
{
- MwmSet::MwmId const id = index.GetMwmIdByCountryFile(CountryFile(MAP_NAME));
+ MwmSet::MwmId const id = index.GetMwmIdByFileName(MAP_FILE);
TEST(id.IsAlive(), ());
routing::PedestrianModel const vehicleModel;
@@ -109,7 +107,7 @@ void TestRouter(routing::IRouter & router, m2::PointD const & startPos, m2::Poin
void TestRouters(Index const & index, m2::PointD const & startPos, m2::PointD const & finalPos)
{
- auto const countryFileFn = [](m2::PointD const & /* point */) { return MAP_NAME; };
+ auto const countryFileFn = [](m2::PointD const & /* point */){ return MAP_FILE; };
// find route by A*-bidirectional algorithm
routing::Route routeFoundByAstarBidirectional("");
@@ -129,14 +127,9 @@ void TestTwoPointsOnFeature(m2::PointD const & startPos, m2::PointD const & fina
{
classificator::Load();
- CountryFile countryFile(MAP_NAME);
- LocalCountryFile localFile = LocalCountryFile::MakeForTesting(MAP_NAME);
-
Index index;
- UNUSED_VALUE(index.RegisterMap(localFile));
- TEST(index.IsLoaded(countryFile), ());
- MwmSet::MwmId const id = index.GetMwmIdByCountryFile(countryFile);
- TEST(id.IsAlive(), ());
+ UNUSED_VALUE(index.RegisterMap(MAP_FILE));
+ TEST(index.IsLoaded(MAP_NAME), ());
vector<pair<routing::Edge, m2::PointD>> startEdges;
GetNearestPedestrianEdges(index, startPos, startEdges);
@@ -146,10 +139,8 @@ void TestTwoPointsOnFeature(m2::PointD const & startPos, m2::PointD const & fina
GetNearestPedestrianEdges(index, finalPos, finalEdges);
TEST(!finalEdges.empty(), ());
- m2::PointD const startPosOnFeature =
- GetPointOnEdge(startEdges.front().first, 0.0 /* the start point of the feature */);
- m2::PointD const finalPosOnFeature =
- GetPointOnEdge(finalEdges.front().first, 1.0 /* the end point of the feature */);
+ m2::PointD const startPosOnFeature = GetPointOnEdge(startEdges.front().first, 0.0 /* the start point of the feature */ );
+ m2::PointD const finalPosOnFeature = GetPointOnEdge(finalEdges.front().first, 1.0 /* the end point of the feature */ );
TestRouters(index, startPosOnFeature, finalPosOnFeature);
}
@@ -158,13 +149,11 @@ void TestTwoPoints(m2::PointD const & startPos, m2::PointD const & finalPos)
{
classificator::Load();
- CountryFile countryFile(MAP_NAME);
- LocalCountryFile localFile = LocalCountryFile::MakeForTesting(MAP_NAME);
-
Index index;
- UNUSED_VALUE(index.RegisterMap(localFile));
- TEST(index.IsLoaded(countryFile), ());
- MwmSet::MwmId const id = index.GetMwmIdByCountryFile(countryFile);
+ UNUSED_VALUE(index.RegisterMap(MAP_FILE));
+ TEST(index.IsLoaded(MAP_NAME), ());
+
+ MwmSet::MwmId const id = index.GetMwmIdByFileName(MAP_FILE);
TEST(id.IsAlive(), ());
TestRouters(index, startPos, finalPos);
diff --git a/platform/country_defines.cpp b/platform/country_defines.cpp
index 927f883709..5a3ab9e8f5 100644
--- a/platform/country_defines.cpp
+++ b/platform/country_defines.cpp
@@ -2,25 +2,14 @@
#include "base/assert.hpp"
-bool HasOptions(TMapOptions mask, TMapOptions options)
+bool HasOptions(TMapOptions options, TMapOptions bits)
{
- return (static_cast<uint8_t>(mask) & static_cast<uint8_t>(options)) ==
- static_cast<uint8_t>(options);
+ return (static_cast<uint8_t>(options) & static_cast<uint8_t>(bits)) == static_cast<uint8_t>(bits);
}
-TMapOptions SetOptions(TMapOptions mask, TMapOptions options)
+TMapOptions SetOptions(TMapOptions options, TMapOptions bits)
{
- return static_cast<TMapOptions>(static_cast<uint8_t>(mask) | static_cast<uint8_t>(options));
-}
-
-TMapOptions UnsetOptions(TMapOptions mask, TMapOptions options)
-{
- return static_cast<TMapOptions>(static_cast<uint8_t>(mask) & ~static_cast<uint8_t>(options));
-}
-
-TMapOptions LeastSignificantOption(TMapOptions mask)
-{
- return static_cast<TMapOptions>(static_cast<uint8_t>(mask) & -static_cast<uint8_t>(mask));
+ return static_cast<TMapOptions>(static_cast<uint8_t>(options) | static_cast<uint8_t>(bits));
}
string DebugPrint(TMapOptions options)
@@ -35,5 +24,8 @@ string DebugPrint(TMapOptions options)
return "CarRouting";
case TMapOptions::EMapWithCarRouting:
return "MapWithCarRouting";
+ default:
+ ASSERT(false, ("Unknown TMapOptions (", static_cast<uint8_t>(options), ")"));
+ return string();
}
}
diff --git a/platform/country_defines.hpp b/platform/country_defines.hpp
index 5c010cbd13..11e6f97842 100644
--- a/platform/country_defines.hpp
+++ b/platform/country_defines.hpp
@@ -10,12 +10,8 @@ enum class TMapOptions : uint8_t
EMapWithCarRouting = 0x3
};
-bool HasOptions(TMapOptions mask, TMapOptions options);
+bool HasOptions(TMapOptions options, TMapOptions bits);
-TMapOptions SetOptions(TMapOptions mask, TMapOptions options);
-
-TMapOptions UnsetOptions(TMapOptions mask, TMapOptions options);
-
-TMapOptions LeastSignificantOption(TMapOptions mask);
+TMapOptions SetOptions(TMapOptions options, TMapOptions bits);
string DebugPrint(TMapOptions options);
diff --git a/platform/country_file.cpp b/platform/country_file.cpp
index b7f4210e8b..8fffb2a52d 100644
--- a/platform/country_file.cpp
+++ b/platform/country_file.cpp
@@ -22,8 +22,8 @@ string CountryFile::GetNameWithExt(TMapOptions file) const
return m_name + DATA_FILE_EXTENSION + ROUTING_FILE_EXTENSION;
default:
ASSERT(false, ("Can't get name for:", file));
- return string();
}
+ return string();
}
void CountryFile::SetRemoteSizes(uint32_t mapSize, uint32_t routingSize)
diff --git a/platform/local_country_file.cpp b/platform/local_country_file.cpp
index 2ccf776392..b730395ad5 100644
--- a/platform/local_country_file.cpp
+++ b/platform/local_country_file.cpp
@@ -34,23 +34,20 @@ void LocalCountryFile::SyncWithDisk()
Platform & platform = GetPlatform();
- if (platform.GetFileSizeByFullPath(GetPath(TMapOptions::EMap), m_mapSize))
+ if (platform.GetFileSizeByName(GetPath(TMapOptions::EMap), m_mapSize))
m_files = SetOptions(m_files, TMapOptions::EMap);
string const routingPath = GetPath(TMapOptions::ECarRouting);
- if (platform.GetFileSizeByFullPath(routingPath, m_routingSize))
+ if (platform.GetFileSizeByName(routingPath, m_routingSize))
m_files = SetOptions(m_files, TMapOptions::ECarRouting);
}
-void LocalCountryFile::DeleteFromDisk(TMapOptions files) const
+void LocalCountryFile::DeleteFromDisk()
{
for (TMapOptions file : {TMapOptions::EMap, TMapOptions::ECarRouting})
{
- if (OnDisk(file) && HasOptions(files, file))
- {
- if (!my::DeleteFileX(GetPath(file)))
- LOG(LERROR, (file, "from", *this, "wasn't deleted from disk."));
- }
+ if (OnDisk(file))
+ VERIFY(my::DeleteFileX(GetPath(file)), (file, "from", *this, "wasn't deleted from disk."));
}
}
diff --git a/platform/local_country_file.hpp b/platform/local_country_file.hpp
index 1a2afa0180..c73975f772 100644
--- a/platform/local_country_file.hpp
+++ b/platform/local_country_file.hpp
@@ -25,9 +25,8 @@ public:
// their sizes etc. with disk.
void SyncWithDisk();
- // Removes specified files from disk if they're known for LocalCountryFile, i.e.
- // were found by previous SyncWithDisk() call.
- void DeleteFromDisk(TMapOptions files) const;
+ // Removes known country files from disk.
+ void DeleteFromDisk();
// Returns path to a file. Return value may be empty until
// SyncWithDisk() is called.
@@ -48,7 +47,6 @@ public:
return (static_cast<unsigned>(m_files) & static_cast<unsigned>(filesMask)) ==
static_cast<unsigned>(filesMask);
}
-
inline string const & GetDirectory() const { return m_directory; }
inline int64_t GetVersion() const { return m_version; }
inline CountryFile const & GetCountryFile() const { return m_countryFile; }
diff --git a/platform/local_country_file_utils.cpp b/platform/local_country_file_utils.cpp
index b5ded8a11c..87e76142d3 100644
--- a/platform/local_country_file_utils.cpp
+++ b/platform/local_country_file_utils.cpp
@@ -1,16 +1,12 @@
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
-
#include "coding/file_name_utils.hpp"
#include "coding/file_writer.hpp"
-
#include "base/string_utils.hpp"
#include "base/logging.hpp"
-
#include "std/algorithm.hpp"
#include "std/cctype.hpp"
-#include "std/sstream.hpp"
namespace platform
{
@@ -30,11 +26,10 @@ void CleanupMapsDirectory()
// Remove partially downloaded maps.
{
Platform::FilesList files;
- // .(downloading|resume|ready)[0-9]?$
- string const regexp = "\\.(downloading|resume|ready)[0-9]?$";
+ string const regexp = "\\" DATA_FILE_EXTENSION "\\.(downloading2?$|resume2?$)";
platform.GetFilesByRegExp(mapsDir, regexp, files);
for (string const & file : files)
- FileWriter::DeleteFileX(my::JoinFoldersToPath(mapsDir, file));
+ FileWriter::DeleteFileX(file);
}
// Find and remove Brazil and Japan maps.
@@ -46,7 +41,7 @@ void CleanupMapsDirectory()
if (countryFile.GetNameWithoutExt() == "Japan" || countryFile.GetNameWithoutExt() == "Brazil")
{
localFile.SyncWithDisk();
- localFile.DeleteFromDisk(TMapOptions::EMapWithCarRouting);
+ localFile.DeleteFromDisk();
}
}
@@ -109,10 +104,9 @@ void FindAllLocalMaps(vector<LocalCountryFile> & localFiles)
{
int64_t version;
if (ParseVersion(subdir, version))
- FindAllLocalMapsInDirectory(my::JoinFoldersToPath(directory, subdir), version, localFiles);
+ FindAllLocalMapsInDirectory(my::JoinFoldersToPath(directory, subdir), version, allFiles);
}
}
-
#if defined(OMIM_OS_ANDROID)
// On Android World and WorldCoasts can be stored in alternative /Android/obb/ path.
for (string const & file : {WORLD_FILE_NAME, WORLD_COASTS_FILE_NAME})
@@ -141,6 +135,7 @@ void FindAllLocalMaps(vector<LocalCountryFile> & localFiles)
}
}
#endif // defined(OMIM_OS_ANDROID)
+
localFiles.insert(localFiles.end(), allFiles.begin(), allFiles.end());
}
@@ -148,7 +143,6 @@ bool ParseVersion(string const & s, int64_t & version)
{
if (s.empty() || s.size() > kMaxTimestampLength)
return false;
-
int64_t v = 0;
for (char const c : s)
{
@@ -168,29 +162,22 @@ shared_ptr<LocalCountryFile> PreparePlaceForCountryFiles(CountryFile const & cou
return make_shared<LocalCountryFile>(platform.WritableDir(), countryFile, version);
string const directory =
my::JoinFoldersToPath(platform.WritableDir(), strings::to_string(version));
- Platform::EError ret = platform.MkDir(directory);
- switch (ret)
+ switch (platform.MkDir(directory))
{
case Platform::ERR_OK:
return make_shared<LocalCountryFile>(directory, countryFile, version);
case Platform::ERR_FILE_ALREADY_EXISTS:
{
Platform::EFileType type;
- if (Platform::GetFileType(directory, type) != Platform::ERR_OK)
+ if (Platform::GetFileType(directory, type) != Platform::ERR_OK ||
+ type != Platform::FILE_TYPE_DIRECTORY)
{
- LOG(LERROR, ("Can't determine file type for:", directory));
- return shared_ptr<LocalCountryFile>();
- }
- if (type != Platform::FILE_TYPE_DIRECTORY)
- {
- LOG(LERROR, (directory, "exists, but not a directory:", type));
return shared_ptr<LocalCountryFile>();
}
return make_shared<LocalCountryFile>(directory, countryFile, version);
}
default:
- LOG(LERROR, ("Can't prepare place for", countryFile, "(", version, ") :", ret));
return shared_ptr<LocalCountryFile>();
- }
+ };
}
} // namespace platform
diff --git a/platform/platform.cpp b/platform/platform.cpp
index bfffb65a7c..a5b0f720a5 100644
--- a/platform/platform.cpp
+++ b/platform/platform.cpp
@@ -1,7 +1,5 @@
#include "platform/platform.hpp"
-#include "platform/local_country_file.hpp"
-
#include "coding/sha2.hpp"
#include "coding/base64.hpp"
#include "coding/file_name_utils.hpp"
@@ -149,9 +147,3 @@ string Platform::GetIndexFileName(string const & mwmName, string const & extensi
{
return GetPlatform().WritablePathForCountryIndexes(mwmName) + mwmName + extension;
}
-
-ModelReader * Platform::GetCountryReader(platform::LocalCountryFile const & file,
- TMapOptions options) const
-{
- return GetReader(file.GetPath(options), "f");
-}
diff --git a/platform/platform.hpp b/platform/platform.hpp
index 7effb78d90..91f86740d7 100644
--- a/platform/platform.hpp
+++ b/platform/platform.hpp
@@ -1,7 +1,5 @@
#pragma once
-#include "platform/country_defines.hpp"
-
#include "coding/reader.hpp"
#include "base/exception.hpp"
@@ -14,14 +12,10 @@
#include "defines.hpp"
+
DECLARE_EXCEPTION(FileAbsentException, RootException);
DECLARE_EXCEPTION(NotImplementedException, RootException);
-namespace platform
-{
-class LocalCountryFile;
-}
-
class Platform
{
public:
@@ -115,9 +109,6 @@ public:
/// @return full path to file in the settings directory
string SettingsPathForFile(string const & file) const { return SettingsDir() + file; }
- ModelReader * GetCountryReader(platform::LocalCountryFile const & file,
- TMapOptions options) const;
-
/// @return reader for file decriptor.
/// @throws FileAbsentException
/// @param[in] file name or full path which we want to read, don't forget to free memory or wrap it to ReaderPtr
diff --git a/platform/platform_android.cpp b/platform/platform_android.cpp
index 225547015e..92e6fde61c 100644
--- a/platform/platform_android.cpp
+++ b/platform/platform_android.cpp
@@ -20,15 +20,8 @@ Platform::Platform()
namespace
{
-enum SourceT
-{
- EXTERNAL_RESOURCE,
- RESOURCE,
- WRITABLE_PATH,
- SETTINGS_PATH,
- FULL_PATH,
- SOURCE_COUNT
-};
+
+enum SourceT { EXTERNAL_RESOURCE, RESOURCE, WRITABLE_PATH, SETTINGS_PATH, FULL_PATH };
bool IsResource(string const & file, string const & ext)
{
@@ -47,8 +40,7 @@ bool IsResource(string const & file, string const & ext)
return true;
}
-size_t GetSearchSources(string const & file, string const & searchScope,
- SourceT (&arr)[SOURCE_COUNT])
+size_t GetSearchSources(string const & file, string const & searchScope, SourceT (&arr)[4])
{
size_t ret = 0;
@@ -96,7 +88,7 @@ ModelReader * Platform::GetReader(string const & file, string const & searchScop
uint32_t const logPageSize = (ext == DATA_FILE_EXTENSION) ? READER_CHUNK_LOG_SIZE : 10;
uint32_t const logPageCount = (ext == DATA_FILE_EXTENSION) ? READER_CHUNK_LOG_COUNT : 4;
- SourceT sources[SOURCE_COUNT];
+ SourceT sources[4];
size_t n = 0;
if (searchScope.empty())
@@ -180,7 +172,6 @@ ModelReader * Platform::GetReader(string const & file, string const & searchScop
}
}
- LOG(LERROR, ("Can't get reader for:", file));
MYTHROW(FileAbsentException, ("File not found", file));
return 0;
}
@@ -247,9 +238,8 @@ bool Platform::GetFileSizeByName(string const & fileName, uint64_t & size) const
size = ReaderPtr<Reader>(GetReader(fileName)).Size();
return true;
}
- catch (RootException const & ex)
+ catch (RootException const &)
{
- LOG(LWARNING, ("Can't get file size for:", fileName));
return false;
}
}
@@ -259,7 +249,7 @@ Platform::EError Platform::MkDir(string const & dirName) const
if (mkdir(dirName.c_str(), 0755))
{
LOG(LWARNING, ("Can't create directory: ", dirName));
- return ErrnoToError();
+ return Platform::ERR_UNKNOWN;
}
return Platform::ERR_OK;
}
diff --git a/platform/platform_ios.mm b/platform/platform_ios.mm
index cb14de0171..5fd1310059 100644
--- a/platform/platform_ios.mm
+++ b/platform/platform_ios.mm
@@ -37,7 +37,7 @@ Platform::Platform()
Platform::EError Platform::MkDir(string const & dirName) const
{
if (::mkdir(dirName.c_str(), 0755))
- return ErrnoToError();
+ return Platform::ERR_UNKNOWN;
return Platform::ERR_OK;
}
diff --git a/platform/platform_tests/local_country_file_tests.cpp b/platform/platform_tests/local_country_file_tests.cpp
index 46981142f6..5594a4e63f 100644
--- a/platform/platform_tests/local_country_file_tests.cpp
+++ b/platform/platform_tests/local_country_file_tests.cpp
@@ -7,7 +7,6 @@
#include "coding/file_name_utils.hpp"
#include "coding/file_writer.hpp"
-#include "coding/internal/file_data.hpp"
#include "base/scope_guard.hpp"
@@ -27,30 +26,24 @@ bool Contains(vector<T> const & v, T const & t)
return find(v.begin(), v.end(), t) != v.end();
}
-// Scoped test directory in a writable dir.
class ScopedTestDir
{
public:
- /// Creates test dir in a writable directory.
- /// @param path Path for a testing directory, should be relative to writable-dir.
- ScopedTestDir(string const & relativePath)
- : m_fullPath(my::JoinFoldersToPath(GetPlatform().WritableDir(), relativePath)),
- m_relativePath(relativePath),
- m_reset(false)
+ ScopedTestDir(string const & path) : m_path(path), m_reset(false)
{
Platform & platform = GetPlatform();
- Platform::EError ret = platform.MkDir(GetFullPath());
+ Platform::EError ret = platform.MkDir(m_path);
switch (ret)
{
case Platform::ERR_OK:
break;
case Platform::ERR_FILE_ALREADY_EXISTS:
Platform::EFileType type;
- TEST_EQUAL(Platform::ERR_OK, Platform::GetFileType(GetFullPath(), type), ());
+ TEST_EQUAL(Platform::ERR_OK, Platform::GetFileType(m_path, type), ());
TEST_EQUAL(Platform::FILE_TYPE_DIRECTORY, type, ());
break;
default:
- CHECK(false, ("Can't create directory:", GetFullPath(), "error:", ret));
+ CHECK(false, ("Can't create directory:", m_path, "error:", ret));
break;
}
}
@@ -60,100 +53,43 @@ public:
if (m_reset)
return;
- string const fullPath = GetFullPath();
- Platform::EError ret = Platform::RmDir(fullPath);
+ Platform::EError ret = Platform::RmDir(m_path);
switch (ret)
{
case Platform::ERR_OK:
break;
case Platform::ERR_FILE_DOES_NOT_EXIST:
- LOG(LWARNING, (fullPath, "was deleted before destruction of ScopedTestDir."));
+ LOG(LWARNING, (m_path, "was deleted before destruction of ScopedTestDir."));
break;
case Platform::ERR_DIRECTORY_NOT_EMPTY:
- LOG(LWARNING, ("There are files in", fullPath));
+ LOG(LWARNING, ("There are files in", m_path));
break;
default:
- LOG(LWARNING, ("Platform::RmDir() error for", fullPath, ":", ret));
+ LOG(LWARNING, ("Platform::RmDir() error:", ret));
break;
}
}
inline void Reset() { m_reset = true; }
- inline string const & GetFullPath() const { return m_fullPath; }
-
- inline string const & GetRelativePath() const { return m_relativePath; }
-
- bool Exists() const { return GetPlatform().IsFileExistsByFullPath(GetFullPath()); }
+ inline string const GetPath() const { return m_path; }
private:
- string const m_fullPath;
- string const m_relativePath;
+ string const m_path;
bool m_reset;
DISALLOW_COPY_AND_MOVE(ScopedTestDir);
};
-class ScopedTestFile
+void CreateTestFile(string const & testFile, string const & contents)
{
-public:
- ScopedTestFile(string const & relativePath, string const & contents)
- : m_fullPath(my::JoinFoldersToPath(GetPlatform().WritableDir(), relativePath)), m_reset(false)
- {
- {
- FileWriter writer(GetFullPath());
- writer.Write(contents.data(), contents.size());
- }
- TEST(Exists(), ("Can't create test file", GetFullPath()));
- }
-
- ScopedTestFile(ScopedTestDir const & dir, CountryFile const & countryFile, TMapOptions file,
- string const & contents)
- : ScopedTestFile(
- my::JoinFoldersToPath(dir.GetRelativePath(), countryFile.GetNameWithExt(file)),
- contents)
{
+ FileWriter writer(testFile);
+ writer.Write(contents.data(), contents.size());
}
-
- ~ScopedTestFile()
- {
- if (m_reset)
- return;
- if (!Exists())
- {
- LOG(LWARNING, ("File", GetFullPath(), "was deleted before dtor of ScopedTestFile."));
- return;
- }
- if (!my::DeleteFileX(GetFullPath()))
- LOG(LWARNING, ("Can't remove test file:", GetFullPath()));
- }
-
- inline string const & GetFullPath() const { return m_fullPath; }
-
- inline void Reset() { m_reset = true; }
-
- bool Exists() const { return GetPlatform().IsFileExistsByFullPath(GetFullPath()); }
-
-private:
- string const m_fullPath;
- bool m_reset;
-
- DISALLOW_COPY_AND_MOVE(ScopedTestFile);
-};
-
-string DebugPrint(ScopedTestDir const & dir)
-{
- ostringstream os;
- os << "ScopedTestDir [" << dir.GetFullPath() << "]";
- return os.str();
+ TEST(Platform::IsFileExistsByFullPath(testFile), ("Can't create test file", testFile));
}
-string DebugPrint(ScopedTestFile const & file)
-{
- ostringstream os;
- os << "ScopedTestFile [" << file.GetFullPath() << "]";
- return os.str();
-}
} // namespace
// Checks that all unsigned numbers less than 10 ^ 18 can be parsed as
@@ -224,12 +160,17 @@ UNIT_TEST(LocalCountryFile_DiskFiles)
CountryFile countryFile("TestCountry");
countryFile.SetRemoteSizes(1 /* mapSize */, 2 /* routingSize */);
+ string const testMapFile =
+ my::JoinFoldersToPath(platform.WritableDir(), countryFile.GetNameWithExt(TMapOptions::EMap));
+ string const testRoutingFile = my::JoinFoldersToPath(
+ platform.WritableDir(), countryFile.GetNameWithExt(TMapOptions::ECarRouting));
+
LocalCountryFile localFile(platform.WritableDir(), countryFile, 0 /* version */);
TEST(!localFile.OnDisk(TMapOptions::EMap), ());
TEST(!localFile.OnDisk(TMapOptions::ECarRouting), ());
TEST(!localFile.OnDisk(TMapOptions::EMapWithCarRouting), ());
- ScopedTestFile testMapFile(countryFile.GetNameWithExt(TMapOptions::EMap), "map");
+ CreateTestFile(testMapFile, "map");
localFile.SyncWithDisk();
TEST(localFile.OnDisk(TMapOptions::EMap), ());
@@ -237,7 +178,7 @@ UNIT_TEST(LocalCountryFile_DiskFiles)
TEST(!localFile.OnDisk(TMapOptions::EMapWithCarRouting), ());
TEST_EQUAL(3, localFile.GetSize(TMapOptions::EMap), ());
- ScopedTestFile testRoutingFile(countryFile.GetNameWithExt(TMapOptions::ECarRouting), "routing");
+ CreateTestFile(testRoutingFile, "routing");
localFile.SyncWithDisk();
TEST(localFile.OnDisk(TMapOptions::EMap), ());
@@ -247,15 +188,14 @@ UNIT_TEST(LocalCountryFile_DiskFiles)
TEST_EQUAL(7, localFile.GetSize(TMapOptions::ECarRouting), ());
TEST_EQUAL(10, localFile.GetSize(TMapOptions::EMapWithCarRouting), ());
- localFile.DeleteFromDisk(TMapOptions::EMapWithCarRouting);
- TEST(!testMapFile.Exists(), (testMapFile, "wasn't deleted by LocalCountryFile."));
- testMapFile.Reset();
-
- TEST(!testRoutingFile.Exists(), (testRoutingFile, "wasn't deleted by LocalCountryFile."));
- testRoutingFile.Reset();
+ localFile.DeleteFromDisk();
+ TEST(!platform.IsFileExistsByFullPath(testMapFile),
+ ("Map file", testMapFile, "wasn't deleted by LocalCountryFile."));
+ TEST(!platform.IsFileExistsByFullPath(testRoutingFile),
+ ("Routing file", testRoutingFile, "wasn't deleted by LocalCountryFile."));
}
-UNIT_TEST(LocalCountryFile_CleanupMapFiles)
+UNIT_TEST(LocalCountryFile_DirectoryCleanup)
{
Platform & platform = GetPlatform();
string const mapsDir = platform.WritableDir();
@@ -264,19 +204,19 @@ UNIT_TEST(LocalCountryFile_CleanupMapFiles)
CountryFile brazilFile("Brazil");
CountryFile irelandFile("Ireland");
- ScopedTestDir testDir1("1");
- LocalCountryFile japanLocalFile(testDir1.GetFullPath(), japanFile, 1 /* version */);
- ScopedTestFile japanMapFile(testDir1, japanFile, TMapOptions::EMap, "Japan");
+ ScopedTestDir testDir1(my::JoinFoldersToPath(mapsDir, "1"));
+ LocalCountryFile japanLocalFile(testDir1.GetPath(), japanFile, 1 /* version */);
+ CreateTestFile(japanLocalFile.GetPath(TMapOptions::EMap), "Japan");
+
+ ScopedTestDir testDir2(my::JoinFoldersToPath(mapsDir, "2"));
+ LocalCountryFile brazilLocalFile(testDir2.GetPath(), brazilFile, 2 /* version */);
+ CreateTestFile(brazilLocalFile.GetPath(TMapOptions::EMap), "Brazil");
- ScopedTestDir testDir2("2");
- LocalCountryFile brazilLocalFile(testDir2.GetFullPath(), brazilFile, 2 /* version */);
- ScopedTestFile brazilMapFile(testDir2, brazilFile, TMapOptions::EMap, "Brazil");
- LocalCountryFile irelandLocalFile(testDir2.GetFullPath(), irelandFile, 2 /* version */);
- ScopedTestFile irelandMapFile(testDir2, irelandFile, TMapOptions::EMap, "Ireland");
+ ScopedTestDir testDir3(my::JoinFoldersToPath(mapsDir, "3"));
- ScopedTestDir testDir3("3");
+ LocalCountryFile irelandLocalFile(testDir2.GetPath(), irelandFile, 2 /* version */);
+ CreateTestFile(irelandLocalFile.GetPath(TMapOptions::EMap), "Ireland");
- // Check that FindAllLocalMaps()
vector<LocalCountryFile> localFiles;
FindAllLocalMaps(localFiles);
TEST(Contains(localFiles, japanLocalFile), (japanLocalFile));
@@ -287,47 +227,20 @@ UNIT_TEST(LocalCountryFile_CleanupMapFiles)
japanLocalFile.SyncWithDisk();
TEST_EQUAL(TMapOptions::ENothing, japanLocalFile.GetFiles(), ());
- TEST(!testDir1.Exists(), ("Empty directory", testDir1, "wasn't removed."));
+ TEST(!Platform::IsFileExistsByFullPath(testDir1.GetPath()), ("Empty directory wasn't removed."));
testDir1.Reset();
- TEST(!japanMapFile.Exists(), (japanMapFile));
- japanMapFile.Reset();
brazilLocalFile.SyncWithDisk();
TEST_EQUAL(TMapOptions::ENothing, brazilLocalFile.GetFiles(), ());
- TEST(!brazilMapFile.Exists(), (brazilMapFile));
- brazilMapFile.Reset();
irelandLocalFile.SyncWithDisk();
TEST_EQUAL(TMapOptions::EMap, irelandLocalFile.GetFiles(), ());
- irelandLocalFile.DeleteFromDisk(TMapOptions::EMap);
- TEST(!irelandMapFile.Exists(), (irelandMapFile));
- irelandMapFile.Reset();
+ irelandLocalFile.DeleteFromDisk();
- TEST(!testDir3.Exists(), ("Empty directory", testDir3, "wasn't removed."));
+ TEST(!Platform::IsFileExistsByFullPath(testDir3.GetPath()), ("Empty directory wasn't removed."));
testDir3.Reset();
}
-UNIT_TEST(LocalCountryFile_CleanupPartiallyDownloadedFiles)
-{
- ScopedTestFile toBeDeleted[] = {{"Ireland.mwm.ready", "Ireland"},
- {"Netherlands.mwm.routing.downloading2", "Netherlands"},
- {"Germany.mwm.ready3", "Germany"},
- {"UK_England.mwm.resume4", "UK"}};
- ScopedTestFile toBeKept[] = {
- {"Italy.mwm", "Italy"}, {"Spain.mwm", "Spain map"}, {"Spain.mwm.routing", "Spain routing"}};
-
- CleanupMapsDirectory();
-
- for (ScopedTestFile & file : toBeDeleted)
- {
- TEST(!file.Exists(), (file));
- file.Reset();
- }
-
- for (ScopedTestFile & file : toBeKept)
- TEST(file.Exists(), (file));
-}
-
// Creates test-dir and following files:
// * test-dir/Ireland.mwm
// * test-dir/Netherlands.mwm
@@ -340,24 +253,37 @@ UNIT_TEST(LocalCountryFile_DirectoryLookup)
CountryFile const irelandFile("Ireland");
CountryFile const netherlandsFile("Netherlands");
- ScopedTestDir testDir("test-dir");
+ Platform & platform = GetPlatform();
+
+ ScopedTestDir testDir(my::JoinFoldersToPath(platform.WritableDir(), "test-dir"));
+
+ string const testIrelandMapFile =
+ my::JoinFoldersToPath(testDir.GetPath(), irelandFile.GetNameWithExt(TMapOptions::EMap));
+ CreateTestFile(testIrelandMapFile, "Ireland-map");
+ MY_SCOPE_GUARD(removeTestIrelandMapFile, bind(&FileWriter::DeleteFileX, testIrelandMapFile));
- ScopedTestFile testIrelandMapFile(testDir, irelandFile, TMapOptions::EMap, "Ireland-map");
- ScopedTestFile testNetherlandsMapFile(testDir, netherlandsFile, TMapOptions::EMap,
- "Netherlands-map");
- ScopedTestFile testNetherlandsRoutingFile(testDir, netherlandsFile, TMapOptions::ECarRouting,
- "Netherlands-routing");
+ string const testNetherlandsMapFile =
+ my::JoinFoldersToPath(testDir.GetPath(), netherlandsFile.GetNameWithExt(TMapOptions::EMap));
+ CreateTestFile(testNetherlandsMapFile, "Netherlands-map");
+ MY_SCOPE_GUARD(removeTestNetherlandsMapFile,
+ bind(&FileWriter::DeleteFileX, testNetherlandsMapFile));
+
+ string const testNetherlandsRoutingFile = my::JoinFoldersToPath(
+ testDir.GetPath(), netherlandsFile.GetNameWithExt(TMapOptions::ECarRouting));
+ CreateTestFile(testNetherlandsRoutingFile, "Netherlands-routing");
+ MY_SCOPE_GUARD(removeTestNetherlandsRoutingFile,
+ bind(&FileWriter::DeleteFileX, testNetherlandsRoutingFile));
vector<LocalCountryFile> localFiles;
- FindAllLocalMapsInDirectory(testDir.GetFullPath(), 150309, localFiles);
+ FindAllLocalMapsInDirectory(testDir.GetPath(), 150309, localFiles);
sort(localFiles.begin(), localFiles.end());
for (LocalCountryFile & localFile : localFiles)
localFile.SyncWithDisk();
- LocalCountryFile expectedIrelandFile(testDir.GetFullPath(), irelandFile, 150309);
+ LocalCountryFile expectedIrelandFile(testDir.GetPath(), irelandFile, 150309);
expectedIrelandFile.m_files = TMapOptions::EMap;
- LocalCountryFile expectedNetherlandsFile(testDir.GetFullPath(), netherlandsFile, 150309);
+ LocalCountryFile expectedNetherlandsFile(testDir.GetPath(), netherlandsFile, 150309);
expectedNetherlandsFile.m_files = TMapOptions::EMapWithCarRouting;
vector<LocalCountryFile> expectedLocalFiles = {expectedIrelandFile, expectedNetherlandsFile};
@@ -375,8 +301,12 @@ UNIT_TEST(LocalCountryFile_AllLocalFilesLookup)
Platform & platform = GetPlatform();
- ScopedTestDir testDir("010101");
- ScopedTestFile testItalyMapFile(testDir, italyFile, TMapOptions::EMap, "Italy-map");
+ ScopedTestDir testDir(my::JoinFoldersToPath(platform.WritableDir(), "010101"));
+
+ string const testItalyMapFile =
+ my::JoinFoldersToPath(testDir.GetPath(), italyFile.GetNameWithExt(TMapOptions::EMap));
+ CreateTestFile(testItalyMapFile, "Italy-map");
+ MY_SCOPE_GUARD(remoteTestItalyMapFile, bind(&FileWriter::DeleteFileX, testItalyMapFile));
vector<LocalCountryFile> localFiles;
FindAllLocalMaps(localFiles);
@@ -390,7 +320,7 @@ UNIT_TEST(LocalCountryFile_AllLocalFilesLookup)
CountryFile(WORLD_COASTS_FILE_NAME), 0 /* version */);
TEST_EQUAL(1, localFilesSet.count(expectedWorldCoastsFile), ());
- LocalCountryFile expectedItalyFile(testDir.GetFullPath(), italyFile, 10101);
+ LocalCountryFile expectedItalyFile(testDir.GetPath(), italyFile, 10101);
TEST_EQUAL(1, localFilesSet.count(expectedItalyFile), ());
}
@@ -405,17 +335,17 @@ UNIT_TEST(LocalCountryFile_PreparePlaceForCountryFiles)
TEST(italyLocalFile.get(), ());
TEST_EQUAL(expectedItalyFile, *italyLocalFile, ());
- ScopedTestDir directoryForV1("1");
+ ScopedTestDir directoryForV1(my::JoinFoldersToPath(platform.WritableDir(), "1"));
CountryFile germanyFile("Germany");
- LocalCountryFile expectedGermanyFile(directoryForV1.GetFullPath(), germanyFile, 1 /* version */);
+ LocalCountryFile expectedGermanyFile(directoryForV1.GetPath(), germanyFile, 1 /* version */);
shared_ptr<LocalCountryFile> germanyLocalFile =
PreparePlaceForCountryFiles(germanyFile, 1 /* version */);
TEST(germanyLocalFile.get(), ());
TEST_EQUAL(expectedGermanyFile, *germanyLocalFile, ());
CountryFile franceFile("France");
- LocalCountryFile expectedFranceFile(directoryForV1.GetFullPath(), franceFile, 1 /* version */);
+ LocalCountryFile expectedFranceFile(directoryForV1.GetPath(), franceFile, 1 /* version */);
shared_ptr<LocalCountryFile> franceLocalFile =
PreparePlaceForCountryFiles(franceFile, 1 /* version */);
TEST(franceLocalFile.get(), ());
diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp
index e52a2bc6c8..1fb3840e50 100644
--- a/routing/osrm_router.cpp
+++ b/routing/osrm_router.cpp
@@ -4,7 +4,6 @@
#include "turns_generator.hpp"
#include "vehicle_model.hpp"
-#include "platform/country_file.hpp"
#include "platform/platform.hpp"
#include "geometry/angles.hpp"
@@ -350,12 +349,9 @@ public:
};
} // namespace
-OsrmRouter::OsrmRouter(Index const * index, TCountryFileFn const & countryFileFn,
- TCountryLocalFileFn const & countryLocalFileFn,
+OsrmRouter::OsrmRouter(Index const * index, TCountryFileFn const & fn,
TRoutingVisualizerFn routingVisualization)
- : m_pIndex(index),
- m_indexManager(countryFileFn, countryLocalFileFn, index),
- m_routingVisualization(routingVisualization)
+ : m_pIndex(index), m_indexManager(fn, index), m_routingVisualization(routingVisualization)
{
}
diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp
index 813fffd1cd..3eac5e9483 100644
--- a/routing/osrm_router.hpp
+++ b/routing/osrm_router.hpp
@@ -28,17 +28,18 @@ namespace routing
struct RoutePathCross;
using TCheckedPath = vector<RoutePathCross>;
+typedef OsrmDataFacade<QueryEdge::EdgeData> TDataFacade;
+
/// All edges available for start route while routing
typedef vector<FeatureGraphNode> TFeatureGraphNodeVec;
+
class OsrmRouter : public IRouter
{
public:
typedef vector<double> GeomTurnCandidateT;
- OsrmRouter(Index const * index, TCountryFileFn const & countryFileFn,
- TCountryLocalFileFn const & countryLocalFileFn,
- TRoutingVisualizerFn routingVisualization = nullptr);
+ OsrmRouter(Index const * index, TCountryFileFn const & fn, TRoutingVisualizerFn routingVisualization = nullptr);
virtual string GetName() const;
diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp
index 3f1a1b67cc..7224e73d34 100644
--- a/routing/road_graph_router.cpp
+++ b/routing/road_graph_router.cpp
@@ -92,8 +92,7 @@ IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoin
if (m_countryFileFn(startPoint) != mwmName)
return PointsInDifferentMWM;
- platform::CountryFile countryFile(mwmName);
- MwmSet::MwmLock const mwmLock = const_cast<Index &>(m_index).GetMwmLockByCountryFile(countryFile);
+ MwmSet::MwmLock const mwmLock = const_cast<Index&>(m_index).GetMwmLockByFileName(mwmName);
if (!mwmLock.IsLocked())
return RouteFileNotExist;
diff --git a/routing/routing_mapping.cpp b/routing/routing_mapping.cpp
index a7c6f3bf97..1d2001c578 100644
--- a/routing/routing_mapping.cpp
+++ b/routing/routing_mapping.cpp
@@ -10,49 +10,34 @@
#include "indexer/mwm_version.hpp"
-#include "platform/country_file.hpp"
-#include "platform/local_country_file.hpp"
#include "platform/platform.hpp"
-using platform::CountryFile;
-using platform::LocalCountryFile;
-
namespace routing
{
-RoutingMapping::RoutingMapping(CountryFile const & countryFile)
+RoutingMapping::RoutingMapping(string const & fName, Index const * pIndex)
: m_mapCounter(0),
m_facadeCounter(0),
m_crossContextLoaded(0),
- m_countryFileName(countryFile.GetNameWithoutExt()),
- m_isValid(false),
- m_error(IRouter::ResultCode::RouteFileNotExist)
-{
-}
-
-RoutingMapping::RoutingMapping(LocalCountryFile const & localFile, Index const * pIndex)
- : m_mapCounter(0),
- m_facadeCounter(0),
- m_crossContextLoaded(0),
- m_countryFileName(localFile.GetCountryFile().GetNameWithoutExt()),
+ m_baseName(fName),
m_isValid(true),
m_error(IRouter::ResultCode::NoError)
{
Platform & pl = GetPlatform();
- if (!HasOptions(localFile.GetFiles(), TMapOptions::EMapWithCarRouting))
+ string const mwmName = m_baseName + DATA_FILE_EXTENSION;
+ string const fPath = pl.WritablePathForFile(mwmName + ROUTING_FILE_EXTENSION);
+ if (!pl.IsFileExistsByFullPath(fPath))
{
m_isValid = false;
m_error = IRouter::ResultCode::RouteFileNotExist;
return;
}
- string const routingFilePath = localFile.GetPath(TMapOptions::ECarRouting);
// Open new container and check that mwm and routing have equal timestamp.
- LOG(LDEBUG, ("Load routing index for file:", routingFilePath));
- m_container.Open(routingFilePath);
+ LOG(LDEBUG, ("Load routing index for file:", fPath));
+ m_container.Open(fPath);
{
FileReader r1 = m_container.GetReader(VERSION_FILE_TAG);
ReaderSrc src1(r1);
- ModelReaderPtr r2 = FilesContainerR(pl.GetCountryReader(localFile, TMapOptions::EMap))
- .GetReader(VERSION_FILE_TAG);
+ ModelReaderPtr r2 = FilesContainerR(pl.GetReader(mwmName)).GetReader(VERSION_FILE_TAG);
ReaderSrc src2(r2.GetPtr());
version::MwmVersion version1;
@@ -70,7 +55,7 @@ RoutingMapping::RoutingMapping(LocalCountryFile const & localFile, Index const *
}
}
- m_mwmId = pIndex->GetMwmIdByCountryFile(localFile.GetCountryFile());
+ m_mwmId = pIndex->GetMwmIdByFileName(mwmName);
}
RoutingMapping::~RoutingMapping()
@@ -128,33 +113,22 @@ void RoutingMapping::FreeCrossContext()
m_crossContext = CrossRoutingContextReader();
}
-// static
-shared_ptr<RoutingMapping> RoutingMapping::MakeInvalid(platform::CountryFile const & countryFile)
-{
- return shared_ptr<RoutingMapping>(new RoutingMapping(countryFile));
-}
-
TRoutingMappingPtr RoutingIndexManager::GetMappingByPoint(m2::PointD const & point)
{
- return GetMappingByName(m_countryFileFn(point));
+ return GetMappingByName(m_countryFn(point));
}
TRoutingMappingPtr RoutingIndexManager::GetMappingByName(string const & mapName)
{
- shared_ptr<platform::LocalCountryFile> localFile = m_countryLocalFileFn(mapName);
- // Return invalid mapping when file does not exist.
- if (!localFile)
- return RoutingMapping::MakeInvalid(platform::CountryFile(mapName));
-
// Check if we have already loaded this file.
auto mapIter = m_mapping.find(mapName);
if (mapIter != m_mapping.end())
return mapIter->second;
// Or load and check file.
- TRoutingMappingPtr newMapping = make_shared<RoutingMapping>(*localFile, m_index);
- m_mapping.insert(make_pair(mapName, newMapping));
- return newMapping;
+ TRoutingMappingPtr new_mapping = make_shared<RoutingMapping>(mapName, m_index);
+ m_mapping.insert(make_pair(mapName, new_mapping));
+ return new_mapping;
}
} // namespace routing
diff --git a/routing/routing_mapping.h b/routing/routing_mapping.h
index 41d0b0da50..e791599f30 100644
--- a/routing/routing_mapping.h
+++ b/routing/routing_mapping.h
@@ -11,17 +11,10 @@
#include "std/algorithm.hpp"
#include "std/unordered_map.hpp"
-namespace platform
-{
-class CountryFile;
-class LocalCountryFile;
-}
-
namespace routing
{
using TDataFacade = OsrmDataFacade<QueryEdge::EdgeData>;
using TCountryFileFn = function<string(m2::PointD const &)>;
-using TCountryLocalFileFn = function<shared_ptr<platform::LocalCountryFile>(string const &)>;
/// Datamapping and facade for single MWM and MWM.routing file
struct RoutingMapping
@@ -31,7 +24,7 @@ struct RoutingMapping
CrossRoutingContextReader m_crossContext;
///@param fName: mwm file path
- RoutingMapping(platform::LocalCountryFile const & localFile, Index const * pIndex);
+ RoutingMapping(string const & fName, Index const * pIndex);
~RoutingMapping();
@@ -51,21 +44,15 @@ struct RoutingMapping
IRouter::ResultCode GetError() const {return m_error;}
- string const & GetName() const { return m_countryFileName; }
+ string const & GetName() const { return m_baseName; }
Index::MwmId const & GetMwmId() const { return m_mwmId; }
- // static
- static shared_ptr<RoutingMapping> MakeInvalid(platform::CountryFile const & countryFile);
-
private:
- // Ctor for invalid mappings.
- RoutingMapping(platform::CountryFile const & countryFile);
-
size_t m_mapCounter;
size_t m_facadeCounter;
bool m_crossContextLoaded;
- string m_countryFileName;
+ string m_baseName;
FilesMappingContainer m_container;
Index::MwmId m_mwmId;
bool m_isValid;
@@ -99,9 +86,8 @@ public:
class RoutingIndexManager
{
public:
- RoutingIndexManager(TCountryFileFn const & countryFileFn,
- TCountryLocalFileFn const & countryLocalFileFn, Index const * index)
- : m_countryFileFn(countryFileFn), m_countryLocalFileFn(countryLocalFileFn), m_index(index)
+ RoutingIndexManager(TCountryFileFn const & fn, Index const * index)
+ : m_countryFn(fn), m_index(index)
{
ASSERT(index, ());
}
@@ -119,10 +105,9 @@ public:
void Clear() { m_mapping.clear(); }
private:
- TCountryFileFn m_countryFileFn;
- TCountryLocalFileFn m_countryLocalFileFn;
- unordered_map<string, TRoutingMappingPtr> m_mapping;
+ TCountryFileFn m_countryFn;
Index const * m_index;
+ unordered_map<string, TRoutingMappingPtr> m_mapping;
};
} // namespace routing
diff --git a/search/search_query.cpp b/search/search_query.cpp
index 12741b473b..0a5eab18d3 100644
--- a/search/search_query.cpp
+++ b/search/search_query.cpp
@@ -600,7 +600,7 @@ namespace impl
if (m_pFV->IsWorld())
country.clear();
else
- country = m_pFV->GetCountryFileName();
+ country = m_pFV->GetFileName();
}
public:
@@ -1659,14 +1659,11 @@ void Query::SearchAddress(Results & res)
{
MwmSet::MwmId id(info);
Index::MwmLock const mwmLock(const_cast<Index &>(*m_pIndex), id);
+ string fileName;
if (mwmLock.IsLocked())
- {
- platform::CountryFile const & countryFile =
- mwmLock.GetValue<MwmValue>()->GetCountryFile();
- string const countryFileName = countryFile.GetNameWithoutExt();
- if (m_pInfoGetter->IsBelongToRegion(countryFileName, region.m_ids))
- SearchInMWM(mwmLock, params);
- }
+ fileName = mwmLock.GetValue<MwmValue>()->GetFileName();
+ if (m_pInfoGetter->IsBelongToRegion(fileName, region.m_ids))
+ SearchInMWM(mwmLock, params);
}
}
}
@@ -2111,8 +2108,9 @@ void Query::SearchInMWM(Index::MwmLock const & mwmLock, Params const & params,
TrieRootPrefix(*pLangRoot, edge),
filter, categoriesHolder, emitter);
- LOG(LDEBUG, ("Country", pMwm->GetCountryFile().GetNameWithoutExt(), "Lang",
- StringUtf8Multilang::GetLangByCode(lang), "Matched", emitter.GetCount()));
+ LOG(LDEBUG, ("Country", pMwm->GetFileName(),
+ "Lang", StringUtf8Multilang::GetLangByCode(lang),
+ "Matched", emitter.GetCount()));
emitter.Reset();
}
@@ -2195,11 +2193,8 @@ void Query::SearchAdditional(Results & res, size_t resCount)
for (shared_ptr<MwmInfo> const & info : mwmsInfo)
{
Index::MwmLock const mwmLock(const_cast<Index &>(*m_pIndex), MwmSet::MwmId(info));
- if (mwmLock.IsLocked() &&
- mwmLock.GetValue<MwmValue>()->GetCountryFile().GetNameWithoutExt() == fileName)
- {
+ if (mwmLock.IsLocked() && mwmLock.GetValue<MwmValue>()->GetFileName() == fileName)
SearchInMWM(mwmLock, params);
- }
}
FlushResults(res, true, resCount);
diff --git a/search/search_tests/house_detector_tests.cpp b/search/search_tests/house_detector_tests.cpp
index eae291fb9a..1f03cb824d 100644
--- a/search/search_tests/house_detector_tests.cpp
+++ b/search/search_tests/house_detector_tests.cpp
@@ -17,7 +17,6 @@
#include "std/iostream.hpp"
#include "std/fstream.hpp"
-using platform::LocalCountryFile;
class StreetIDsByName
{
@@ -184,8 +183,7 @@ UNIT_TEST(HS_StreetsMerge)
classificator::Load();
Index index;
- pair<MwmSet::MwmLock, bool> const p =
- index.Register(LocalCountryFile::MakeForTesting("minsk-pass"));
+ pair<MwmSet::MwmLock, bool> const p = index.Register("minsk-pass.mwm");
TEST(p.first.IsLocked(), ());
TEST(p.second, ());
@@ -274,8 +272,7 @@ UNIT_TEST(HS_FindHouseSmoke)
classificator::Load();
Index index;
- pair<MwmSet::MwmLock, bool> const p =
- index.Register(LocalCountryFile::MakeForTesting("minsk-pass"));
+ pair<MwmSet::MwmLock, bool> const p = index.Register("minsk-pass.mwm");
TEST(p.first.IsLocked(), ());
TEST(p.second, ());
@@ -348,7 +345,10 @@ struct Address
string m_house;
double m_lat, m_lon;
- bool operator<(Address const & rhs) const { return (m_streetKey < rhs.m_streetKey); }
+ bool operator<(Address const & rhs) const
+ {
+ return (m_streetKey < rhs.m_streetKey);
+ }
};
void swap(Address & a1, Address & a2)
@@ -375,7 +375,7 @@ UNIT_TEST(HS_MWMSearch)
}
Index index;
- pair<MwmSet::MwmLock, bool> const p = index.Register(LocalCountryFile::MakeForTesting(country));
+ pair<MwmSet::MwmLock, bool> const p = index.Register(country + ".mwm");
if (!p.second)
{
LOG(LWARNING, ("MWM file not found"));
diff --git a/search/search_tests/locality_finder_test.cpp b/search/search_tests/locality_finder_test.cpp
index 62efda0f5e..30182f7267 100644
--- a/search/search_tests/locality_finder_test.cpp
+++ b/search/search_tests/locality_finder_test.cpp
@@ -5,10 +5,6 @@
#include "search/locality_finder.hpp"
-#include "platform/country_file.hpp"
-#include "platform/local_country_file.hpp"
-#include "platform/platform.hpp"
-
namespace
{
@@ -38,8 +34,7 @@ void doTests2(search::LocalityFinder & finder, vector<m2::PointD> const & input,
UNIT_TEST(LocalityFinder)
{
Index index;
- pair<MwmSet::MwmLock, bool> const p =
- index.Register(platform::LocalCountryFile::MakeForTesting("World"));
+ pair<MwmSet::MwmLock, bool> const p = index.Register("World.mwm");
TEST(p.second, ());
MwmSet::MwmLock const & lock = p.first;
TEST(lock.IsLocked(), ());
diff --git a/std/algorithm.hpp b/std/algorithm.hpp
index 913e1c0482..426296336b 100644
--- a/std/algorithm.hpp
+++ b/std/algorithm.hpp
@@ -6,7 +6,6 @@
#include <algorithm>
-using std::all_of;
using std::binary_search;
using std::equal;
using std::find;
diff --git a/storage/country.cpp b/storage/country.cpp
index d2be152219..3e39eb674a 100644
--- a/storage/country.cpp
+++ b/storage/country.cpp
@@ -6,19 +6,96 @@
#include "3party/jansson/myjansson.hpp"
-using platform::CountryFile;
namespace storage
{
-uint64_t Country::Size(TMapOptions opt) const
+
+string CountryFile::GetFileWithExt(TMapOptions opt) const
+{
+ switch (opt)
+ {
+ case TMapOptions::EMap: return m_fileName + DATA_FILE_EXTENSION;
+ case TMapOptions::ECarRouting: return m_fileName + DATA_FILE_EXTENSION + ROUTING_FILE_EXTENSION;
+
+ case TMapOptions::EMapWithCarRouting:
+ default:
+ ASSERT(false, ());
+ }
+ return string();
+}
+
+uint32_t CountryFile::GetFileSize(TMapOptions opt) const
{
uint64_t size = 0;
- for (CountryFile const & file : m_files)
- size += file.GetRemoteSize(opt);
- return size;
+ if (GetPlatform().GetFileSizeByName(GetFileWithExt(opt), size))
+ {
+ uint32_t const ret = static_cast<uint32_t>(size);
+ ASSERT_EQUAL ( ret, size, () );
+ return ret;
+ }
+ else
+ return 0;
+}
+
+uint32_t CountryFile::GetRemoteSize(TMapOptions opt) const
+{
+ switch (opt)
+ {
+ case TMapOptions::ENothing:
+ return 0;
+ case TMapOptions::EMap:
+ return m_mapSize;
+ case TMapOptions::ECarRouting:
+ return m_routingSize;
+ case TMapOptions::EMapWithCarRouting:
+ return m_mapSize + m_routingSize;
+ }
+}
+
+/*
+class CountryBoundsCalculator
+{
+ m2::RectD & m_bounds;
+ Platform & m_platform;
+
+public:
+ CountryBoundsCalculator(m2::RectD & bounds)
+ : m_bounds(bounds), m_platform(GetPlatform())
+ {
+ }
+
+ void operator()(CountryFile const & file)
+ {
+ feature::DataHeader h;
+ LoadMapHeader(m_platform.GetReader(file.GetFileWithExt()), h);
+ m_bounds.Add(h.GetBounds());
+ }
+};
+
+m2::RectD Country::Bounds() const
+{
+ m2::RectD bounds;
+ std::for_each(m_files.begin(), m_files.end(), CountryBoundsCalculator(bounds));
+ return bounds;
+}
+*/
+
+LocalAndRemoteSizeT Country::Size(TMapOptions opt) const
+{
+ uint64_t localSize = 0, remoteSize = 0;
+ for (CountryFile const & f : m_files)
+ {
+ localSize += f.GetFileSize(opt);
+ remoteSize += f.GetRemoteSize(opt);
+ }
+ return LocalAndRemoteSizeT(localSize, remoteSize);
+}
+
+void Country::AddFile(CountryFile const & file)
+{
+ m_files.push_back(file);
}
-void Country::AddFile(CountryFile const & file) { m_files.push_back(file); }
////////////////////////////////////////////////////////////////////////
@@ -41,9 +118,10 @@ void LoadGroupImpl(int depth, json_t * group, ToDo & toDo)
char const * flag = json_string_value(json_object_get(j, "c"));
toDo(name, file, flag ? flag : "",
- // We expect what mwm and routing files should be less 2Gb
+ // We expect what mwm and routing files should be less 2Gb
static_cast<uint32_t>(json_integer_value(json_object_get(j, "s"))),
- static_cast<uint32_t>(json_integer_value(json_object_get(j, "rs"))), depth);
+ static_cast<uint32_t>(json_integer_value(json_object_get(j, "rs"))),
+ depth);
json_t * children = json_object_get(j, "g");
if (children)
@@ -52,133 +130,120 @@ void LoadGroupImpl(int depth, json_t * group, ToDo & toDo)
}
template <class ToDo>
-bool LoadCountriesImpl(string const & jsonBuffer, ToDo & toDo)
+int64_t LoadCountriesImpl(string const & jsonBuffer, ToDo & toDo)
{
+ int64_t version = -1;
+
try
{
my::Json root(jsonBuffer.c_str());
+ version = json_integer_value(json_object_get(root.get(), "v"));
json_t * children = json_object_get(root.get(), "g");
if (!children)
MYTHROW(my::Json::Exception, ("Root country doesn't have any groups"));
LoadGroupImpl(0, children, toDo);
- return true;
}
- catch (my::Json::Exception const & e)
+ catch (my::Json::Exception const & ex)
{
- LOG(LERROR, (e.Msg()));
- return false;
+ LOG(LERROR, (ex.Msg()));
+ return -1;
}
+
+ return version;
}
namespace
{
-class DoStoreCountries
-{
- CountriesContainerT & m_cont;
-
-public:
- DoStoreCountries(CountriesContainerT & cont) : m_cont(cont) {}
-
- void operator()(string const & name, string const & file, string const & flag, uint32_t mapSize,
- uint32_t routingSize, int depth)
+ class DoStoreCountries
{
- Country country(name, flag);
- if (mapSize)
+ CountriesContainerT & m_cont;
+ public:
+ DoStoreCountries(CountriesContainerT & cont) : m_cont(cont) {}
+
+ void operator() (string const & name, string const & file, string const & flag,
+ uint32_t mapSize, uint32_t routingSize, int depth)
{
- CountryFile countryFile(file);
- countryFile.SetRemoteSizes(mapSize, routingSize);
- country.AddFile(countryFile);
+ Country country(name, flag);
+ if (mapSize)
+ country.AddFile(CountryFile(file, mapSize, routingSize));
+ m_cont.AddAtDepth(depth, country);
}
- m_cont.AddAtDepth(depth, country);
- }
-};
+ };
-class DoStoreFile2Info
-{
- map<string, CountryInfo> & m_file2info;
- string m_lastFlag;
-
-public:
- DoStoreFile2Info(map<string, CountryInfo> & file2info) : m_file2info(file2info) {}
-
- void operator()(string name, string file, string const & flag, uint32_t mapSize, uint32_t, int)
+ class DoStoreFile2Info
{
- if (!flag.empty())
- m_lastFlag = flag;
+ map<string, CountryInfo> & m_file2info;
+ string m_lastFlag;
- if (mapSize)
+ public:
+ DoStoreFile2Info(map<string, CountryInfo> & file2info) : m_file2info(file2info) {}
+
+ void operator() (string name, string file, string const & flag,
+ uint32_t mapSize, uint32_t, int)
{
- CountryInfo info;
+ if (!flag.empty())
+ m_lastFlag = flag;
- // if 'file' is empty - it's equal to 'name'
- if (!file.empty())
+ if (mapSize)
{
- // make compound name: country_region
- size_t const i = file.find_first_of('_');
- if (i != string::npos)
- name = file.substr(0, i) + '_' + name;
-
- // fill 'name' only when it differs with 'file'
- if (name != file)
- info.m_name.swap(name);
- }
- else
- file.swap(name);
+ CountryInfo info;
- // Do not use 'name' here! It was swapped!
+ // if 'file' is empty - it's equal to 'name'
+ if (!file.empty())
+ {
+ // make compound name: country_region
+ size_t const i = file.find_first_of('_');
+ if (i != string::npos)
+ name = file.substr(0, i) + '_' + name;
- ASSERT(!m_lastFlag.empty(), ());
- info.m_flag = m_lastFlag;
+ // fill 'name' only when it differs with 'file'
+ if (name != file)
+ info.m_name.swap(name);
+ }
+ else
+ file.swap(name);
- m_file2info[file] = info;
- }
- }
-};
+ // Do not use 'name' here! It was swapped!
-class DoStoreCode2File
-{
- multimap<string, string> & m_code2file;
+ ASSERT ( !m_lastFlag.empty(), () );
+ info.m_flag = m_lastFlag;
-public:
- DoStoreCode2File(multimap<string, string> & code2file) : m_code2file(code2file) {}
+ m_file2info[file] = info;
+ }
+ }
+ };
- void operator()(string const &, string const & file, string const & flag, uint32_t, uint32_t, int)
+ class DoStoreCode2File
{
- m_code2file.insert(make_pair(flag, file));
- }
-};
+ multimap<string, string> & m_code2file;
+ public:
+ DoStoreCode2File(multimap<string, string> & code2file) : m_code2file(code2file) {}
+
+ void operator() (string const &, string const & file, string const & flag,
+ uint32_t, uint32_t, int)
+ {
+ m_code2file.insert(make_pair(flag, file));
+ }
+ };
}
int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries)
{
countries.Clear();
-
- int64_t version = -1;
- try
- {
- my::Json root(jsonBuffer.c_str());
- version = json_integer_value(json_object_get(root.get(), "v"));
- DoStoreCountries doStore(countries);
- if (!LoadCountriesImpl(jsonBuffer, doStore))
- return -1;
- }
- catch (my::Json::Exception const & e)
- {
- LOG(LERROR, (e.Msg()));
- }
- return version;
+ DoStoreCountries doStore(countries);
+ return LoadCountriesImpl(jsonBuffer, doStore);
}
void LoadCountryFile2CountryInfo(string const & jsonBuffer, map<string, CountryInfo> & id2info)
{
- ASSERT(id2info.empty(), ());
+ ASSERT ( id2info.empty(), () );
DoStoreFile2Info doStore(id2info);
LoadCountriesImpl(jsonBuffer, doStore);
}
void LoadCountryCode2File(string const & jsonBuffer, multimap<string, string> & code2file)
{
- ASSERT(code2file.empty(), ());
+ ASSERT ( code2file.empty(), () );
DoStoreCode2File doStore(code2file);
LoadCountriesImpl(jsonBuffer, doStore);
}
@@ -208,12 +273,11 @@ void SaveImpl(T const & v, json_t * jParent)
if (countriesCount > 0)
{
CountryFile const & file = v[i].Value().GetFile();
- string const & strFile = file.GetNameWithoutExt();
+ string const & strFile = file.GetFileWithoutExt();
if (strFile != strName)
json_object_set_new(jCountry.get(), "f", json_string(strFile.c_str()));
json_object_set_new(jCountry.get(), "s", json_integer(file.GetRemoteSize(TMapOptions::EMap)));
- json_object_set_new(jCountry.get(), "rs",
- json_integer(file.GetRemoteSize(TMapOptions::ECarRouting)));
+ json_object_set_new(jCountry.get(), "rs", json_integer(file.GetRemoteSize(TMapOptions::ECarRouting)));
}
if (v[i].SiblingsCount())
@@ -240,4 +304,4 @@ bool SaveCountries(int64_t version, CountriesContainerT const & countries, strin
return true;
}
-} // namespace storage
+} // namespace storage
diff --git a/storage/country.hpp b/storage/country.hpp
index a51997be9d..0140722634 100644
--- a/storage/country.hpp
+++ b/storage/country.hpp
@@ -1,10 +1,8 @@
#pragma once
-#include "storage/country_decl.hpp"
-#include "storage/simple_tree.hpp"
#include "storage/storage_defines.hpp"
-
-#include "platform/local_country_file.hpp"
+#include "storage/simple_tree.hpp"
+#include "storage/country_decl.hpp"
#include "platform/country_defines.hpp"
@@ -17,56 +15,91 @@
#include "std/string.hpp"
#include "std/vector.hpp"
-namespace update
-{
-class SizeUpdater;
-}
+
+namespace update { class SizeUpdater; }
namespace storage
{
-/// Serves as a proxy between GUI and downloaded files
-class Country
-{
- friend class update::SizeUpdater;
- /// Name in the country node tree
- string m_name;
- /// Flag to display
- string m_flag;
- /// stores squares with world pieces which are part of the country
- buffer_vector<platform::CountryFile, 1> m_files;
-
-public:
- Country() {}
- Country(string const & name, string const & flag = "") : m_name(name), m_flag(flag) {}
-
- bool operator<(Country const & other) const { return Name() < other.Name(); }
-
- void AddFile(platform::CountryFile const & file);
-
- size_t GetFilesCount() const { return m_files.size(); }
-
- /// This function valid for current logic - one file for one country (region).
- /// If the logic will be changed, replace GetFile with ForEachFile.
- platform::CountryFile const & GetFile() const
+ /// Information about each file for a country
+ class CountryFile
{
- ASSERT_EQUAL(m_files.size(), 1, (m_name));
- return m_files.front();
- }
-
- string const & Name() const { return m_name; }
- string const & Flag() const { return m_flag; }
+ string m_fileName; /// Same as id of country\region.
+ uint32_t m_mapSize, m_routingSize;
- uint64_t Size(TMapOptions opt) const;
-};
+ public:
+ CountryFile() : m_mapSize(0), m_routingSize(0) {}
+ CountryFile(string const & fName, uint32_t mapSize, uint32_t routingSize)
+ : m_fileName(fName), m_mapSize(mapSize), m_routingSize(routingSize)
+ {
+ }
-typedef SimpleTree<Country> CountriesContainerT;
+ void AssignSizes(uint32_t mapSize, uint32_t routingSize)
+ {
+ m_mapSize = mapSize;
+ m_routingSize = routingSize;
+ }
-/// @return version of country file or -1 if error was encountered
-int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries);
+ string GetFileWithExt(TMapOptions opt) const;
+ string const & GetFileWithoutExt() const { return m_fileName; }
-void LoadCountryFile2CountryInfo(string const & jsonBuffer, map<string, CountryInfo> & id2info);
+ uint32_t GetFileSize(TMapOptions opt) const;
+ uint32_t GetRemoteSize(TMapOptions opt) const;
+ };
-void LoadCountryCode2File(string const & jsonBuffer, multimap<string, string> & code2file);
+ typedef buffer_vector<CountryFile, 1> FilesContainerT;
-bool SaveCountries(int64_t version, CountriesContainerT const & countries, string & jsonBuffer);
-} // namespace storage
+ /// Serves as a proxy between GUI and downloaded files
+ class Country
+ {
+ friend class update::SizeUpdater;
+ /// Name in the country node tree
+ string m_name;
+ /// Flag to display
+ string m_flag;
+ /// stores squares with world pieces which are part of the country
+ FilesContainerT m_files;
+
+ public:
+ Country() {}
+ Country(string const & name, string const & flag = "")
+ : m_name(name), m_flag(flag) {}
+
+ bool operator<(Country const & other) const { return Name() < other.Name(); }
+
+ void AddFile(CountryFile const & file);
+
+ size_t GetFilesCount() const { return m_files.size(); }
+
+ /*
+ template <class ToDo> void ForEachFile(ToDo toDo) const
+ {
+ for (FilesContainerT::const_iterator i = m_files.begin(); i != m_files.end(); ++i)
+ toDo(i->GetFileWithExt());
+ }
+ */
+
+ /// This function valid for current logic - one file for one country (region).
+ /// If the logic will be changed, replace GetFile with ForEachFile.
+ CountryFile const & GetFile() const
+ {
+ ASSERT_EQUAL ( m_files.size(), 1, (m_name) );
+ return m_files.front();
+ }
+
+ string const & Name() const { return m_name; }
+ string const & Flag() const { return m_flag; }
+
+ /// @return bounds for downloaded parts of the country or empty rect
+ //m2::RectD Bounds() const;
+ LocalAndRemoteSizeT Size(TMapOptions opt) const;
+ };
+
+ typedef SimpleTree<Country> CountriesContainerT;
+
+ /// @return version of country file or -1 if error was encountered
+ int64_t LoadCountries(string const & jsonBuffer, CountriesContainerT & countries);
+ void LoadCountryFile2CountryInfo(string const & jsonBuffer, map<string, CountryInfo> & id2info);
+ void LoadCountryCode2File(string const & jsonBuffer, multimap<string, string> & code2file);
+
+ bool SaveCountries(int64_t version, CountriesContainerT const & countries, string & jsonBuffer);
+}
diff --git a/storage/map_files_downloader.hpp b/storage/map_files_downloader.hpp
index ad9224b426..ce0cf2fc1f 100644
--- a/storage/map_files_downloader.hpp
+++ b/storage/map_files_downloader.hpp
@@ -2,7 +2,6 @@
#include "std/function.hpp"
#include "std/string.hpp"
-
#include "std/utility.hpp"
#include "std/vector.hpp"
diff --git a/storage/queued_country.cpp b/storage/queued_country.cpp
deleted file mode 100644
index 9034370e77..0000000000
--- a/storage/queued_country.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "storage/queued_country.hpp"
-
-#include "base/assert.hpp"
-
-namespace storage
-{
-QueuedCountry::QueuedCountry(TIndex const & index, TMapOptions opt)
- : m_index(index), m_init(opt), m_left(opt), m_current(TMapOptions::ENothing)
-{
- ASSERT(GetIndex().IsValid(), ("Only valid countries may be downloaded."));
- ASSERT(m_left != TMapOptions::ENothing, ("Empty file set was requested for downloading."));
- SwitchToNextFile();
-}
-
-void QueuedCountry::AddOptions(TMapOptions opt)
-{
- for (TMapOptions file : {TMapOptions::EMap, TMapOptions::ECarRouting})
- {
- if (HasOptions(opt, file) && !HasOptions(m_init, file))
- {
- m_init = SetOptions(m_init, file);
- m_left = SetOptions(m_left, file);
- }
- }
-}
-
-void QueuedCountry::RemoveOptions(TMapOptions opt)
-{
- for (TMapOptions file : {TMapOptions::EMap, TMapOptions::ECarRouting})
- {
- if (HasOptions(opt, file) && HasOptions(m_init, file))
- {
- m_init = UnsetOptions(m_init, file);
- m_left = UnsetOptions(m_left, file);
- }
- }
- if (HasOptions(opt, m_current))
- m_current = LeastSignificantOption(m_left);
-}
-
-bool QueuedCountry::SwitchToNextFile()
-{
- // static_casts are needed here because TMapOptions values are
- // actually enum flags (see 3party/enum_flags.hpp) and bitwise
- // operators are overloaded for them.
- ASSERT(HasOptions(m_left, m_current),
- ("Current file (", m_current, ") is not specified in left files (", m_left, ")."));
- m_left = UnsetOptions(m_left, m_current);
- m_current = LeastSignificantOption(m_left);
- return m_current != TMapOptions::ENothing;
-}
-} // namespace storage
diff --git a/storage/queued_country.hpp b/storage/queued_country.hpp
deleted file mode 100644
index de0f070273..0000000000
--- a/storage/queued_country.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include "storage/index.hpp"
-#include "platform/country_defines.hpp"
-
-namespace storage
-{
-/// Country queued for downloading.
-class QueuedCountry
-{
-public:
- QueuedCountry(TIndex const & index, TMapOptions opt);
-
- void AddOptions(TMapOptions opt);
- void RemoveOptions(TMapOptions opt);
- bool SwitchToNextFile();
-
- inline TIndex const & GetIndex() const { return m_index; }
- inline TMapOptions GetInitOptions() const { return m_init; }
- inline TMapOptions GetCurrentFile() const { return m_current; }
- inline TMapOptions GetDownloadedFiles() const { return UnsetOptions(m_init, m_left); }
-
- inline bool operator==(TIndex const & index) const { return m_index == index; }
-
-private:
- TIndex m_index;
- TMapOptions m_init;
- TMapOptions m_left;
- TMapOptions m_current;
-};
-} // namespace storage
diff --git a/storage/storage.cpp b/storage/storage.cpp
index b9f7e75f58..bad306c873 100644
--- a/storage/storage.cpp
+++ b/storage/storage.cpp
@@ -4,22 +4,17 @@
#include "defines.hpp"
-#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/servers_list.hpp"
#include "platform/settings.hpp"
-#include "coding/file_container.hpp"
-#include "coding/file_name_utils.hpp"
-#include "coding/file_reader.hpp"
#include "coding/file_writer.hpp"
-#include "coding/internal/file_data.hpp"
+#include "coding/file_reader.hpp"
+#include "coding/file_container.hpp"
#include "coding/url_encode.hpp"
-
-#include "platform/local_country_file_utils.hpp"
+#include "coding/file_name_utils.hpp"
#include "base/logging.hpp"
-#include "base/scope_guard.hpp"
#include "base/string_utils.hpp"
#include "std/algorithm.hpp"
@@ -30,844 +25,688 @@
#include "3party/Alohalytics/src/alohalytics.h"
using namespace downloader;
-using namespace platform;
namespace storage
{
-namespace
-{
-template <typename T>
-void RemoveIf(vector<T> & v, function<bool(T const & t)> const & p)
-{
- v.erase(remove_if(v.begin(), v.end(), p), v.end());
-}
+ /*
+ static string ErrorString(DownloadResultT res)
+ {
+ switch (res)
+ {
+ case EHttpDownloadCantCreateFile:
+ return "File can't be created. Probably, you have no disk space available or "
+ "using read-only file system.";
+ case EHttpDownloadFailed:
+ return "Download failed due to missing or poor connection. "
+ "Please, try again later.";
+ case EHttpDownloadFileIsLocked:
+ return "Download can't be finished because file is locked. "
+ "Please, try again after restarting application.";
+ case EHttpDownloadFileNotFound:
+ return "Requested file is absent on the server.";
+ case EHttpDownloadNoConnectionAvailable:
+ return "No network connection is available.";
+ case EHttpDownloadOk:
+ return "Download finished successfully.";
+ }
+ return "Unknown error";
+ }
+ */
-uint64_t GetLocalSize(shared_ptr<LocalCountryFile> file, TMapOptions opt)
-{
- if (file.get() == nullptr)
- return 0;
- uint64_t size = 0;
- for (TMapOptions bit : {TMapOptions::EMap, TMapOptions::ECarRouting})
+ Storage::QueuedCountry::QueuedCountry(Storage const & storage, TIndex const & index,
+ TMapOptions opt)
+ : m_index(index), m_init(opt), m_left(opt)
{
- if (HasOptions(opt, bit))
- size += file->GetSize(bit);
+ m_pFile = &(storage.CountryByIndex(index).GetFile());
+
+ // Don't queue files with 0-size on server (empty or absent).
+ // Downloader has lots of assertions about it. If car routing was
+ // requested for downloading, try to download it first.
+ if (HasOptions(m_init, TMapOptions::ECarRouting) &&
+ m_pFile->GetRemoteSize(TMapOptions::ECarRouting) > 0)
+ {
+ m_current = TMapOptions::ECarRouting;
+ }
+ else
+ {
+ m_init = m_current = m_left = TMapOptions::EMap;
+ }
}
- return size;
-}
-uint64_t GetRemoteSize(CountryFile const & file, TMapOptions opt)
-{
- uint64_t size = 0;
- for (TMapOptions bit : {TMapOptions::EMap, TMapOptions::ECarRouting})
+ void Storage::QueuedCountry::AddOptions(TMapOptions opt)
{
- if (HasOptions(opt, bit))
- size += file.GetRemoteSize(bit);
+ TMapOptions const arr[] = { TMapOptions::EMap, TMapOptions::ECarRouting };
+ for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
+ {
+ if (HasOptions(opt, arr[i]) && !HasOptions(m_init, arr[i]))
+ {
+ m_init = SetOptions(m_init, arr[i]);
+ m_left = SetOptions(m_left, arr[i]);
+ }
+ }
}
- return size;
-}
-// TODO (@gorshenin): directory where country indexes are stored
-// should be abstracted out to LocalCountryIndexes.
-void DeleteCountryIndexes(CountryFile const & file)
-{
- Platform::FilesList files;
- Platform const & platform = GetPlatform();
- string const name = file.GetNameWithoutExt();
- string const path = platform.WritablePathForCountryIndexes(name);
-
- /// @todo We need correct regexp for any file (not including "." and "..").
- platform.GetFilesByRegExp(path, name + "\\..*", files);
- for (auto const & file : files)
- my::DeleteFileX(path + file);
-}
+ bool Storage::QueuedCountry::MoveNextFile()
+ {
+ if (m_current == m_left)
+ return false;
-class EqualFileName
-{
- string const & m_name;
+ /// if m_current != m_left than we download map and routing
+ /// routing already downloaded and we need to download map
+ ASSERT(m_current == TMapOptions::ECarRouting, ());
+ m_left = m_current = TMapOptions::EMap;
+ return true;
+ }
-public:
- explicit EqualFileName(string const & name) : m_name(name) {}
- bool operator()(SimpleTree<Country> const & node) const
+ bool Storage::QueuedCountry::Correct(TStatus currentStatus)
{
- Country const & c = node.Value();
- if (c.GetFilesCount() > 0)
- return (c.GetFile().GetNameWithoutExt() == m_name);
- else
+ ASSERT(currentStatus != TStatus::EDownloadFailed, ());
+ ASSERT(currentStatus != TStatus::EOutOfMemFailed, ());
+ ASSERT(currentStatus != TStatus::EInQueue, ());
+ ASSERT(currentStatus != TStatus::EDownloading, ());
+ ASSERT(currentStatus != TStatus::EUnknown, ());
+
+ if (m_init == TMapOptions::EMap && currentStatus == TStatus::EOnDisk)
return false;
- }
-};
-} // namespace
-Storage::Storage() : m_downloader(new HttpMapFilesDownloader()), m_currentSlotId(0)
-{
- LoadCountriesFile(false /* forceReload */);
-}
+#ifdef DEBUG
+ if (currentStatus == TStatus::EOnDiskOutOfDate && m_init == TMapOptions::EMap)
+ ASSERT(m_pFile->GetFileSize(TMapOptions::ECarRouting) == 0, ());
+#endif
-void Storage::Init(TUpdateAfterDownload const & updateFn) { m_updateAfterDownload = updateFn; }
+ if (HasOptions(m_init, TMapOptions::ECarRouting))
+ {
+ ASSERT(HasOptions(m_init, TMapOptions::EMap), ());
-void Storage::RegisterAllLocalMaps()
-{
- m_localFiles.clear();
- m_localFilesForFakeCountries.clear();
+ if (currentStatus == TStatus::EOnDisk)
+ {
+ if (m_pFile->GetFileSize(TMapOptions::ECarRouting) == 0)
+ m_init = m_left = m_current = TMapOptions::ECarRouting;
+ else
+ return false;
+ }
+ }
- vector<LocalCountryFile> localFiles;
- FindAllLocalMaps(localFiles);
+ return true;
+ }
- auto compareByCountryAndVersion = [](LocalCountryFile const & lhs, LocalCountryFile const & rhs)
+ uint64_t Storage::QueuedCountry::GetDownloadSize() const
{
- if (lhs.GetCountryFile() != rhs.GetCountryFile())
- return lhs.GetCountryFile() < rhs.GetCountryFile();
- return lhs.GetVersion() > rhs.GetVersion();
- };
+ return m_pFile->GetRemoteSize(m_current);
+ }
- auto equalByCountry = [](LocalCountryFile const & lhs, LocalCountryFile const & rhs)
+ LocalAndRemoteSizeT Storage::QueuedCountry::GetFullSize() const
{
- return lhs.GetCountryFile() == rhs.GetCountryFile();
- };
+ LocalAndRemoteSizeT res(0, 0);
+ TMapOptions const arr[] = { TMapOptions::EMap, TMapOptions::ECarRouting };
+ for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
+ {
+ if (HasOptions(m_init, arr[i]))
+ {
+ res.first += m_pFile->GetFileSize(arr[i]);
+ res.second += m_pFile->GetRemoteSize(arr[i]);
+ }
+ }
- sort(localFiles.begin(), localFiles.end(), compareByCountryAndVersion);
+ return res;
+ }
- auto i = localFiles.begin();
- while (i != localFiles.end())
+ size_t Storage::QueuedCountry::GetFullRemoteSize() const
{
- auto j = i + 1;
- while (j != localFiles.end() && equalByCountry(*i, *j))
+ size_t res = 0;
+ TMapOptions const arr[] = { TMapOptions::EMap, TMapOptions::ECarRouting };
+ for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
{
- LocalCountryFile & localFile = *j;
- LOG(LINFO, ("Removing obsolete", localFile));
- localFile.SyncWithDisk();
- localFile.DeleteFromDisk(TMapOptions::EMapWithCarRouting);
- ++j;
+ if (HasOptions(m_init, arr[i]))
+ res += m_pFile->GetRemoteSize(arr[i]);
}
- LocalCountryFile const & localFile = *i;
- string const name = localFile.GetCountryFile().GetNameWithoutExt();
- TIndex index = FindIndexByFile(name);
- if (index.IsValid())
- RegisterCountryFiles(index, localFile.GetDirectory(), localFile.GetVersion());
- else
- RegisterFakeCountryFiles(localFile);
- LOG(LINFO, ("Found file:", name, "in directory:", localFile.GetDirectory()));
-
- i = j;
+ return res;
}
-}
-void Storage::GetLocalMaps(vector<CountryFile> & maps)
-{
- for (auto const & p : m_localFiles)
+ string Storage::QueuedCountry::GetFileName() const
{
- TIndex const & index = p.first;
- maps.push_back(GetLatestLocalFile(index)->GetCountryFile());
+ return m_pFile->GetFileWithExt(m_current);
}
- for (auto const & p : m_localFilesForFakeCountries)
- maps.push_back(p.second->GetCountryFile());
-}
-CountriesContainerT const & NodeFromIndex(CountriesContainerT const & root, TIndex const & index)
-{
- // complex logic to avoid [] out_of_bounds exceptions
- if (index.m_group == TIndex::INVALID || index.m_group >= static_cast<int>(root.SiblingsCount()))
- return root;
- if (index.m_country == TIndex::INVALID ||
- index.m_country >= static_cast<int>(root[index.m_group].SiblingsCount()))
- {
- return root[index.m_group];
- }
- if (index.m_region == TIndex::INVALID ||
- index.m_region >= static_cast<int>(root[index.m_group][index.m_country].SiblingsCount()))
+ string Storage::QueuedCountry::GetMapFileName() const
{
- return root[index.m_group][index.m_country];
+ return m_pFile->GetFileWithExt(TMapOptions::EMap);
}
- return root[index.m_group][index.m_country][index.m_region];
-}
-Country const & Storage::CountryByIndex(TIndex const & index) const
-{
- return NodeFromIndex(m_countries, index).Value();
-}
-
-void Storage::GetGroupAndCountry(TIndex const & index, string & group, string & country) const
-{
- string fName = CountryByIndex(index).GetFile().GetNameWithoutExt();
- CountryInfo::FileName2FullName(fName);
- CountryInfo::FullName2GroupAndMap(fName, group, country);
-}
+ Storage::Storage() : m_downloader(new HttpMapFilesDownloader()), m_currentSlotId(0)
+ {
+ LoadCountriesFile(false);
-size_t Storage::CountriesCount(TIndex const & index) const
-{
- return NodeFromIndex(m_countries, index).SiblingsCount();
-}
+ if (Settings::IsFirstLaunchForDate(121031))
+ {
+ Platform & pl = GetPlatform();
+ string const dir = pl.WritableDir();
-string const & Storage::CountryName(TIndex const & index) const
-{
- return NodeFromIndex(m_countries, index).Value().Name();
-}
+ // Delete all: .mwm.downloading; .mwm.downloading2; .mwm.resume; .mwm.resume2
+ string const regexp = "\\" DATA_FILE_EXTENSION "\\.(downloading2?$|resume2?$)";
-string const & Storage::CountryFlag(TIndex const & index) const
-{
- return NodeFromIndex(m_countries, index).Value().Flag();
-}
+ Platform::FilesList files;
+ pl.GetFilesByRegExp(dir, regexp, files);
-LocalAndRemoteSizeT Storage::CountrySizeInBytes(TIndex const & index, TMapOptions opt) const
-{
- QueuedCountry const * queuedCountry = FindCountryInQueue(index);
- shared_ptr<LocalCountryFile> localFile = GetLatestLocalFile(index);
- CountryFile const & countryFile = GetCountryFile(index);
- if (queuedCountry == nullptr)
- {
- return LocalAndRemoteSizeT(GetLocalSize(localFile, opt), GetRemoteSize(countryFile, opt));
+ for (size_t j = 0; j < files.size(); ++j)
+ FileWriter::DeleteFileX(dir + files[j]);
+ }
}
- LocalAndRemoteSizeT sizes(0, GetRemoteSize(countryFile, opt));
- if (!m_downloader->IsIdle() && IsCountryFirstInQueue(index))
+ void Storage::Init(TUpdateAfterDownload const & updateFn)
{
- sizes.first = m_downloader->GetDownloadingProgress().first +
- GetRemoteSize(countryFile, queuedCountry->GetDownloadedFiles());
+ m_updateAfterDownload = updateFn;
}
- return sizes;
-}
-CountryFile const & Storage::GetCountryFile(TIndex const & index) const
-{
- return CountryByIndex(index).GetFile();
-}
-
-shared_ptr<LocalCountryFile> Storage::GetLatestLocalFile(CountryFile const & countryFile) const
-{
- TIndex const index = FindIndexByFile(countryFile.GetNameWithoutExt());
+ CountriesContainerT const & NodeFromIndex(CountriesContainerT const & root, TIndex const & index)
{
- shared_ptr<LocalCountryFile> localFile = GetLatestLocalFile(index);
- if (localFile.get())
- return localFile;
+ // complex logic to avoid [] out_of_bounds exceptions
+ if (index.m_group == TIndex::INVALID || index.m_group >= static_cast<int>(root.SiblingsCount()))
+ return root;
+ else
+ {
+ if (index.m_country == TIndex::INVALID || index.m_country >= static_cast<int>(root[index.m_group].SiblingsCount()))
+ return root[index.m_group];
+ if (index.m_region == TIndex::INVALID || index.m_region >= static_cast<int>(root[index.m_group][index.m_country].SiblingsCount()))
+ return root[index.m_group][index.m_country];
+ return root[index.m_group][index.m_country][index.m_region];
+ }
}
+
+ Country const & Storage::CountryByIndex(TIndex const & index) const
{
- auto const it = m_localFilesForFakeCountries.find(countryFile);
- if (it != m_localFilesForFakeCountries.end())
- return it->second;
+ return NodeFromIndex(m_countries, index).Value();
}
- return shared_ptr<LocalCountryFile>();
-}
-shared_ptr<LocalCountryFile> Storage::GetLatestLocalFile(TIndex const & index) const
-{
- auto const it = m_localFiles.find(index);
- if (it == m_localFiles.end() || it->second.empty())
- return shared_ptr<LocalCountryFile>();
- list<shared_ptr<LocalCountryFile>> const & files = it->second;
- shared_ptr<LocalCountryFile> latest = files.front();
- for (shared_ptr<LocalCountryFile> const & file : files)
+ void Storage::GetGroupAndCountry(TIndex const & index, string & group, string & country) const
{
- if (file->GetVersion() > latest->GetVersion())
- latest = file;
+ string fName = CountryByIndex(index).GetFile().GetFileWithoutExt();
+ CountryInfo::FileName2FullName(fName);
+ CountryInfo::FullName2GroupAndMap(fName, group, country);
}
- return latest;
-}
-TStatus Storage::CountryStatus(TIndex const & index) const
-{
- // Check if we already downloading this country or have it in the queue
- if (IsCountryInQueue(index))
+ size_t Storage::CountriesCount(TIndex const & index) const
{
- if (IsCountryFirstInQueue(index))
- return TStatus::EDownloading;
- else
- return TStatus::EInQueue;
+ return NodeFromIndex(m_countries, index).SiblingsCount();
}
- // Check if this country has failed while downloading.
- if (m_failedCountries.count(index) > 0)
- return TStatus::EDownloadFailed;
-
- return TStatus::EUnknown;
-}
-
-TStatus Storage::CountryStatusEx(TIndex const & index) const
-{
- return CountryStatusFull(index, CountryStatus(index));
-}
-
-void Storage::CountryStatusEx(TIndex const & index, TStatus & status, TMapOptions & options) const
-{
- status = CountryStatusEx(index);
-
- if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
+ string const & Storage::CountryName(TIndex const & index) const
{
- options = TMapOptions::EMap;
-
- shared_ptr<LocalCountryFile> localFile = GetLatestLocalFile(index);
- ASSERT(localFile.get(), ("Invariant violation: local file out of sync with disk."));
- if (localFile->OnDisk(TMapOptions::ECarRouting))
- options = SetOptions(options, TMapOptions::ECarRouting);
+ return NodeFromIndex(m_countries, index).Value().Name();
}
-}
-
-void Storage::DownloadCountry(TIndex const & index, TMapOptions opt)
-{
- opt = NormalizeDownloadFileSet(index, opt);
- if (opt == TMapOptions::ENothing)
- return;
- if (QueuedCountry * queuedCountry = FindCountryInQueue(index))
+ string const & Storage::CountryFlag(TIndex const & index) const
{
- queuedCountry->AddOptions(opt);
- return;
+ return NodeFromIndex(m_countries, index).Value().Flag();
}
- m_failedCountries.erase(index);
- m_queue.push_back(QueuedCountry(index, opt));
- if (m_queue.size() == 1)
- DownloadNextCountryFromQueue();
- else
- NotifyStatusChanged(index);
-}
-
-void Storage::DeleteCountry(TIndex const & index, TMapOptions opt)
-{
- opt = NormalizeDeleteFileSet(opt);
- DeleteCountryFiles(index, opt);
- DeleteCountryFilesFromDownloader(index, opt);
- KickDownloaderAfterDeletionOfCountryFiles(index);
- NotifyStatusChanged(index);
-}
-
-void Storage::DeleteCustomCountryVersion(LocalCountryFile const & localFile)
-{
- CountryFile const countryFile = localFile.GetCountryFile();
- localFile.DeleteFromDisk(TMapOptions::EMapWithCarRouting);
-
+ string Storage::CountryFileName(TIndex const & index, TMapOptions opt) const
{
- auto it = m_localFilesForFakeCountries.find(countryFile);
- if (it != m_localFilesForFakeCountries.end())
- {
- m_localFilesForFakeCountries.erase(it);
- return;
- }
+ return QueuedCountry(*this, index, opt).GetFileName();
}
- TIndex const index = FindIndexByFile(countryFile.GetNameWithoutExt());
- if (!index.IsValid())
+ string const & Storage::CountryFileNameWithoutExt(TIndex const & index) const
{
- LOG(LERROR, ("Removed files for an unknown country:", localFile));
- return;
+ return CountryByIndex(index).GetFile().GetFileWithoutExt();
}
- MY_SCOPE_GUARD(notifyStatusChanged, bind(&Storage::NotifyStatusChanged, this, index));
-
- // If file version equals to current data version, delete from downloader all pending requests for
- // the country.
- if (localFile.GetVersion() == GetCurrentDataVersion())
- DeleteCountryFilesFromDownloader(index, TMapOptions::EMapWithCarRouting);
- auto countryFilesIt = m_localFiles.find(index);
- if (countryFilesIt == m_localFiles.end())
+ string Storage::MapWithoutExt(string mapFile)
{
- LOG(LERROR, ("Deleted files of an unregistered country:", localFile));
- return;
+ string::size_type const pos = mapFile.rfind(DATA_FILE_EXTENSION);
+ if (pos != string::npos)
+ mapFile.resize(pos);
+ return std::move(mapFile);
}
- auto equalsToLocalFile = [&localFile](shared_ptr<LocalCountryFile> const & rhs)
+ LocalAndRemoteSizeT Storage::CountrySizeInBytes(TIndex const & index, TMapOptions opt) const
{
- return localFile == *rhs;
- };
- countryFilesIt->second.remove_if(equalsToLocalFile);
-}
-
-void Storage::NotifyStatusChanged(TIndex const & index)
-{
- for (CountryObservers const & observer : m_observers)
- observer.m_changeCountryFn(index);
-}
-
-void Storage::DownloadNextCountryFromQueue()
-{
- if (m_queue.empty())
- return;
-
- QueuedCountry & queuedCountry = m_queue.front();
- DownloadNextFile(queuedCountry);
-
- // New status for the country, "Downloading"
- NotifyStatusChanged(queuedCountry.GetIndex());
-}
-
-void Storage::DownloadNextFile(QueuedCountry const & country)
-{
- CountryFile const & countryFile = GetCountryFile(country.GetIndex());
+ LocalAndRemoteSizeT sizes(0, 0);
+ QueuedCountry cnt(*this, index, opt);
+ auto const found = find(m_queue.begin(), m_queue.end(), index);
+ if (found != m_queue.end())
+ {
+ sizes.second = cnt.GetFullRemoteSize();
+ if (!m_downloader->IsIdle() && m_queue.front().GetIndex() == index)
+ sizes.first = m_downloader->GetDownloadingProgress().first + m_countryProgress.first;
+ }
+ else
+ sizes = cnt.GetFullSize();
- // send Country name for statistics
- m_downloader->GetServersList(countryFile.GetNameWithoutExt(),
- bind(&Storage::OnServerListDownloaded, this, _1));
-}
+ return sizes;
+ }
-bool Storage::DeleteFromDownloader(TIndex const & index)
-{
- if (!DeleteCountryFilesFromDownloader(index, TMapOptions::EMapWithCarRouting))
- return false;
- KickDownloaderAfterDeletionOfCountryFiles(index);
- NotifyStatusChanged(index);
- return true;
-}
+ TStatus Storage::CountryStatus(TIndex const & index) const
+ {
+ // first, check if we already downloading this country or have in in the queue
+ auto const found = find(m_queue.begin(), m_queue.end(), index);
+ if (found != m_queue.end())
+ {
+ if (found == m_queue.begin())
+ return TStatus::EDownloading;
+ else
+ return TStatus::EInQueue;
+ }
-bool Storage::IsDownloadInProgress() const { return !m_queue.empty(); }
+ // second, check if this country has failed while downloading
+ if (m_failedCountries.count(index) > 0)
+ return TStatus::EDownloadFailed;
-void Storage::LoadCountriesFile(bool forceReload)
-{
- if (forceReload)
- m_countries.Clear();
+ return TStatus::EUnknown;
+ }
- if (m_countries.SiblingsCount() == 0)
+ TStatus Storage::CountryStatusEx(TIndex const & index) const
{
- string json;
- ReaderPtr<Reader>(GetPlatform().GetReader(COUNTRIES_FILE)).ReadAsString(json);
- m_currentVersion = LoadCountries(json, m_countries);
- if (m_currentVersion < 0)
- LOG(LERROR, ("Can't load countries file", COUNTRIES_FILE));
+ return CountryStatusFull(index, CountryStatus(index));
}
-}
-
-int Storage::Subscribe(TChangeCountryFunction const & change, TProgressFunction const & progress)
-{
- CountryObservers obs;
- obs.m_changeCountryFn = change;
- obs.m_progressFn = progress;
- obs.m_slotId = ++m_currentSlotId;
+ void Storage::CountryStatusEx(TIndex const & index, TStatus & status, TMapOptions & options) const
+ {
+ status = CountryStatusEx(index);
- m_observers.push_back(obs);
+ if (status == TStatus::EOnDisk || status == TStatus::EOnDiskOutOfDate)
+ {
+ options = TMapOptions::EMap;
- return obs.m_slotId;
-}
+ string const fName = QueuedCountry(*this, index, TMapOptions::ECarRouting).GetFileName();
+ Platform const & pl = GetPlatform();
+ if (pl.IsFileExistsByFullPath(pl.WritablePathForFile(fName)))
+ options = SetOptions(options, TMapOptions::ECarRouting);
+ }
+ }
-void Storage::Unsubscribe(int slotId)
-{
- for (auto i = m_observers.begin(); i != m_observers.end(); ++i)
+ void Storage::DownloadCountry(TIndex const & index, TMapOptions opt)
{
- if (i->m_slotId == slotId)
+ ASSERT(opt == TMapOptions::EMap || opt == TMapOptions::EMapWithCarRouting, ());
+ // check if we already downloading this country
+ auto const found = find(m_queue.begin(), m_queue.end(), index);
+ if (found != m_queue.end())
{
- m_observers.erase(i);
+ found->AddOptions(opt);
return;
}
- }
-}
-
-void Storage::OnMapFileDownloadFinished(bool success,
- MapFilesDownloader::TProgress const & progress)
-{
- if (m_queue.empty())
- return;
- QueuedCountry & queuedCountry = m_queue.front();
- TIndex const index = queuedCountry.GetIndex();
+ // remove it from failed list
+ m_failedCountries.erase(index);
- Platform & platform = GetPlatform();
- string const path = GetFileDownloadPath(index, queuedCountry.GetCurrentFile());
+ // add it into the queue
+ QueuedCountry cnt(*this, index, opt);
+ if (!cnt.Correct(CountryStatusWithoutFailed(index)))
+ return;
+ m_queue.push_back(cnt);
- success = success && platform.IsFileExistsByFullPath(path) &&
- RegisterDownloadedFile(path, progress.first /* size */, GetCurrentDataVersion());
+ // and start download if necessary
+ if (m_queue.size() == 1)
+ {
+ DownloadNextCountryFromQueue();
+ }
+ else
+ {
+ // notify about "In Queue" status
+ NotifyStatusChanged(index);
+ }
+ }
- if (success && queuedCountry.SwitchToNextFile())
+ void Storage::NotifyStatusChanged(TIndex const & index)
{
- DownloadNextFile(queuedCountry);
- return;
+ for (CountryObservers const & o : m_observers)
+ o.m_changeCountryFn(index);
}
+ void Storage::DownloadNextCountryFromQueue()
{
- string optionsName;
- switch (queuedCountry.GetInitOptions())
+ if (!m_queue.empty())
{
- case TMapOptions::ENothing:
- optionsName = "Nothing";
- break;
- case TMapOptions::EMap:
- optionsName = "Map";
- break;
- case TMapOptions::ECarRouting:
- optionsName = "CarRouting";
- break;
- case TMapOptions::EMapWithCarRouting:
- optionsName = "MapWithCarRouting";
- break;
+ QueuedCountry & cnt = m_queue.front();
+
+ m_countryProgress.first = 0;
+ m_countryProgress.second = cnt.GetFullRemoteSize();
+
+ DownloadNextFile(cnt);
+
+ // new status for country, "Downloading"
+ NotifyStatusChanged(cnt.GetIndex());
}
- alohalytics::LogEvent(
- "$OnMapDownloadFinished",
- alohalytics::TStringMap({{"name", GetCountryFile(index).GetNameWithoutExt()},
- {"status", success ? "ok" : "failed"},
- {"version", strings::to_string(GetCurrentDataVersion())},
- {"option", optionsName}}));
}
- if (success)
+
+ void Storage::DownloadNextFile(QueuedCountry const & cnt)
{
- shared_ptr<LocalCountryFile> localFile = GetLocalFile(index, GetCurrentDataVersion());
- ASSERT(localFile.get(), ());
- OnMapDownloadFinished(localFile);
+ // send Country name for statistics
+ m_downloader->GetServersList(cnt.GetFileName(),
+ bind(&Storage::OnServerListDownloaded, this, _1));
}
- else
+
+ /*
+ m2::RectD Storage::CountryBounds(TIndex const & index) const
{
- OnMapDownloadFailed();
+ Country const & country = CountryByIndex(index);
+ return country.Bounds();
}
+ */
- m_queue.pop_front();
-
- NotifyStatusChanged(index);
-
- m_downloader->Reset();
- DownloadNextCountryFromQueue();
-}
-
-void Storage::ReportProgress(TIndex const & idx, pair<int64_t, int64_t> const & p)
-{
- for (CountryObservers const & o : m_observers)
- o.m_progressFn(idx, p);
-}
-
-void Storage::OnServerListDownloaded(vector<string> const & urls)
-{
- // Queue can be empty because countries were deleted from queue.
- if (m_queue.empty())
- return;
-
- QueuedCountry const & queuedCountry = m_queue.front();
- TIndex const & index = queuedCountry.GetIndex();
- TMapOptions const file = queuedCountry.GetCurrentFile();
-
- vector<string> fileUrls;
- fileUrls.reserve(urls.size());
- for (string const & url : urls)
- fileUrls.push_back(GetFileDownloadUrl(url, index, file));
-
- string const filePath = GetFileDownloadPath(index, file);
- m_downloader->DownloadMapFile(fileUrls, filePath, GetDownloadSize(queuedCountry),
- bind(&Storage::OnMapFileDownloadFinished, this, _1, _2),
- bind(&Storage::OnMapFileDownloadProgress, this, _1));
-}
-
-void Storage::OnMapFileDownloadProgress(MapFilesDownloader::TProgress const & progress)
-{
- // Queue can be empty because countries were deleted from queue.
- if (m_queue.empty())
- return;
-
- if (!m_observers.empty())
+ bool Storage::DeleteFromDownloader(TIndex const & index)
{
- QueuedCountry & queuedCountry = m_queue.front();
- CountryFile const & countryFile = GetCountryFile(queuedCountry.GetIndex());
- MapFilesDownloader::TProgress p = progress;
- p.first += GetRemoteSize(countryFile, queuedCountry.GetDownloadedFiles());
- p.second = GetRemoteSize(countryFile, queuedCountry.GetInitOptions());
-
- ReportProgress(m_queue.front().GetIndex(), p);
- }
-}
+ // check if we already downloading this country
+ auto const found = find(m_queue.begin(), m_queue.end(), index);
+ if (found != m_queue.end())
+ {
+ if (found == m_queue.begin())
+ {
+ // stop download
+ m_downloader->Reset();
+ // remove from the queue
+ m_queue.erase(found);
+ // start another download if the queue is not empty
+ DownloadNextCountryFromQueue();
+ }
+ else
+ {
+ // remove from the queue
+ m_queue.erase(found);
+ }
-bool Storage::RegisterDownloadedFile(string const & path, uint64_t size, int64_t version)
-{
- QueuedCountry & queuedCountry = m_queue.front();
- TIndex const & index = queuedCountry.GetIndex();
- uint64_t const expectedSize = GetDownloadSize(queuedCountry);
+ NotifyStatusChanged(index);
+ return true;
+ }
- ASSERT_EQUAL(size, expectedSize, ("Downloaded file size mismatch:", size,
- "bytes were downloaded,", expectedSize, "bytes expected."));
+ return false;
+ }
- CountryFile const countryFile = GetCountryFile(index);
- shared_ptr<LocalCountryFile> localFile = GetLocalFile(index, version);
- if (localFile.get() == nullptr)
- localFile = PreparePlaceForCountryFiles(countryFile, version);
- if (localFile.get() == nullptr)
+ bool Storage::IsDownloadInProgress() const
{
- LOG(LERROR, ("Local file data structure can't prepared for downloaded file(", path, ")."));
- return false;
+ return !m_queue.empty();
}
- if (!my::RenameFileX(path, localFile->GetPath(queuedCountry.GetCurrentFile())))
- return false;
- RegisterCountryFiles(localFile);
- return true;
-}
-void Storage::OnMapDownloadFinished(shared_ptr<LocalCountryFile> localFile)
-{
- DeleteCountryIndexes(localFile->GetCountryFile());
+ void Storage::LoadCountriesFile(bool forceReload)
+ {
+ if (forceReload)
+ m_countries.Clear();
- // Notify framework that all requested files for the country were downloaded.
- m_updateAfterDownload(*localFile);
-}
+ if (m_countries.SiblingsCount() == 0)
+ {
+ string json;
+ ReaderPtr<Reader>(GetPlatform().GetReader(COUNTRIES_FILE)).ReadAsString(json);
+ m_currentVersion = LoadCountries(json, m_countries);
+ if (m_currentVersion < 0)
+ LOG(LERROR, ("Can't load countries file", COUNTRIES_FILE));
+ }
+ }
-void Storage::OnMapDownloadFailed()
-{
- TIndex const & index = m_queue.front().GetIndex();
+ int Storage::Subscribe(TChangeCountryFunction const & change,
+ TProgressFunction const & progress)
+ {
+ CountryObservers obs;
- // Add country to the failed countries set.
- m_failedCountries.insert(index);
- m_downloader->Reset();
- DownloadNextCountryFromQueue();
-}
+ obs.m_changeCountryFn = change;
+ obs.m_progressFn = progress;
+ obs.m_slotId = ++m_currentSlotId;
-string Storage::GetFileDownloadUrl(string const & baseUrl, TIndex const & index,
- TMapOptions file) const
-{
- CountryFile const & countryFile = GetCountryFile(index);
- return baseUrl + OMIM_OS_NAME "/" + strings::to_string(GetCurrentDataVersion()) + "/" +
- UrlEncode(countryFile.GetNameWithExt(file));
-}
+ m_observers.push_back(obs);
-TIndex Storage::FindIndexByFile(string const & name) const
-{
- EqualFileName fn(name);
+ return obs.m_slotId;
+ }
- for (size_t i = 0; i < m_countries.SiblingsCount(); ++i)
+ void Storage::Unsubscribe(int slotId)
{
- if (fn(m_countries[i]))
- return TIndex(static_cast<int>(i));
-
- for (size_t j = 0; j < m_countries[i].SiblingsCount(); ++j)
+ for (auto i = m_observers.begin(); i != m_observers.end(); ++i)
{
- if (fn(m_countries[i][j]))
- return TIndex(static_cast<int>(i), static_cast<int>(j));
-
- for (size_t k = 0; k < m_countries[i][j].SiblingsCount(); ++k)
+ if (i->m_slotId == slotId)
{
- if (fn(m_countries[i][j][k]))
- return TIndex(static_cast<int>(i), static_cast<int>(j), static_cast<int>(k));
+ m_observers.erase(i);
+ return;
}
}
}
- return TIndex();
-}
+ void Storage::OnMapDownloadFinished(bool success, MapFilesDownloader::TProgress const & progress)
+ {
+ if (m_queue.empty())
+ {
+ ASSERT ( false, ("queue can't be empty") );
+ return;
+ }
-vector<TIndex> Storage::FindAllIndexesByFile(string const & name) const
-{
- EqualFileName fn(name);
- vector<TIndex> res;
+ QueuedCountry & cnt = m_queue.front();
+ TIndex const index = cnt.GetIndex();
- for (size_t i = 0; i < m_countries.SiblingsCount(); ++i)
- {
- if (fn(m_countries[i]))
- res.emplace_back(static_cast<int>(i));
+ bool const downloadHasFailed = !success;
+ {
+ string optionName;
+ switch (cnt.GetInitOptions())
+ {
+ case TMapOptions::ENothing: optionName = "Nothing"; break;
+ case TMapOptions::EMap: optionName = "Map"; break;
+ case TMapOptions::ECarRouting: optionName = "CarRouting"; break;
+ case TMapOptions::EMapWithCarRouting: optionName = "MapWithCarRouting"; break;
+ }
+ alohalytics::LogEvent("$OnMapDownloadFinished",
+ alohalytics::TStringMap({{"name", cnt.GetMapFileName()},
+ {"status", downloadHasFailed ? "failed" : "ok"},
+ {"version", strings::to_string(GetCurrentDataVersion())},
+ {"option", optionName}}));
+ }
- for (size_t j = 0; j < m_countries[i].SiblingsCount(); ++j)
+ if (downloadHasFailed)
{
- if (fn(m_countries[i][j]))
- res.emplace_back(static_cast<int>(i), static_cast<int>(j));
+ // add to failed countries set
+ m_failedCountries.insert(index);
+ }
+ else
+ {
+ ASSERT_EQUAL(progress.first, progress.second, ());
+ ASSERT_EQUAL(progress.first, cnt.GetDownloadSize(), ());
- for (size_t k = 0; k < m_countries[i][j].SiblingsCount(); ++k)
+ m_countryProgress.first += progress.first;
+ if (cnt.MoveNextFile())
{
- if (fn(m_countries[i][j][k]))
- res.emplace_back(static_cast<int>(i), static_cast<int>(j), static_cast<int>(k));
+ DownloadNextFile(cnt);
+ return;
}
+
+ // notify framework that downloading is done
+ m_updateAfterDownload(cnt.GetMapFileName(), cnt.GetInitOptions());
}
+
+ m_queue.pop_front();
+
+ NotifyStatusChanged(index);
+
+ m_downloader->Reset();
+ DownloadNextCountryFromQueue();
}
- return res;
-}
+ void Storage::ReportProgress(TIndex const & idx, pair<int64_t, int64_t> const & p)
+ {
+ for (CountryObservers const & o : m_observers)
+ o.m_progressFn(idx, p);
+ }
-void Storage::GetOutdatedCountries(vector<Country const *> & countries) const
-{
- for (auto const & p : m_localFiles)
+ void Storage::OnMapDownloadProgress(MapFilesDownloader::TProgress const & progress)
{
- TIndex const & index = p.first;
- string const name = GetCountryFile(index).GetNameWithoutExt();
- shared_ptr<LocalCountryFile> const & file = GetLatestLocalFile(index);
- if (file.get() && file->GetVersion() != GetCurrentDataVersion() &&
- name != WORLD_COASTS_FILE_NAME && name != WORLD_FILE_NAME)
+ if (m_queue.empty())
{
- countries.push_back(&CountryByIndex(index));
+ ASSERT ( false, ("queue can't be empty") );
+ return;
}
- }
-}
-TStatus Storage::CountryStatusWithoutFailed(TIndex const & index) const
-{
- // First, check if we already downloading this country or have in in the queue.
- if (!IsCountryInQueue(index))
- return CountryStatusFull(index, TStatus::EUnknown);
- return IsCountryFirstInQueue(index) ? TStatus::EDownloading : TStatus::EInQueue;
-}
+ if (!m_observers.empty())
+ {
+ MapFilesDownloader::TProgress p = progress;
+ p.first += m_countryProgress.first;
+ p.second = m_countryProgress.second;
-TStatus Storage::CountryStatusFull(TIndex const & index, TStatus const status) const
-{
- if (status != TStatus::EUnknown)
- return status;
+ ReportProgress(m_queue.front().GetIndex(), p);
+ }
+ }
- shared_ptr<LocalCountryFile> localFile = GetLatestLocalFile(index);
- if (localFile.get() == nullptr || !localFile->OnDisk(TMapOptions::EMap))
- return TStatus::ENotDownloaded;
+ void Storage::OnServerListDownloaded(vector<string> const & urls)
+ {
+ if (m_queue.empty())
+ {
+ ASSERT ( false, ("queue can't be empty") );
+ return;
+ }
- CountryFile const & countryFile = GetCountryFile(index);
- if (GetRemoteSize(countryFile, TMapOptions::EMap) == 0)
- return TStatus::EUnknown;
+ QueuedCountry const & cnt = m_queue.front();
- if (localFile->GetVersion() != GetCurrentDataVersion())
- return TStatus::EOnDiskOutOfDate;
- return TStatus::EOnDisk;
-}
+ vector<string> fileUrls(urls.size());
+ // append actual version and file name
+ string const fileName = cnt.GetFileName();
+ for (size_t i = 0; i < urls.size(); ++i)
+ fileUrls[i] = GetFileDownloadUrl(urls[i], fileName);
-TMapOptions Storage::NormalizeDownloadFileSet(TIndex const & index, TMapOptions opt) const
-{
- // Car routing files are useless without map files.
- if (HasOptions(opt, TMapOptions::ECarRouting))
- opt = SetOptions(opt, TMapOptions::EMap);
+ string const filePath = GetPlatform().WritablePathForFile(fileName + READY_FILE_EXTENSION);
+ m_downloader->DownloadMapFile(fileUrls, filePath, cnt.GetDownloadSize(),
+ bind(&Storage::OnMapDownloadFinished, this, _1, _2),
+ bind(&Storage::OnMapDownloadProgress, this, _1));
+ }
- shared_ptr<LocalCountryFile> localCountryFile = GetLatestLocalFile(index);
- for (TMapOptions file : {TMapOptions::EMap, TMapOptions::ECarRouting})
+ string Storage::GetFileDownloadUrl(string const & baseUrl, string const & fName) const
+ {
+ return baseUrl + OMIM_OS_NAME "/" + strings::to_string(m_currentVersion) + "/" + UrlEncode(fName);
+ }
+
+ namespace
+ {
+ class EqualFileName
{
- // Check whether requested files are on disk and up-to-date.
- if (HasOptions(opt, file) && localCountryFile.get() && localCountryFile->OnDisk(file) &&
- localCountryFile->GetVersion() == GetCurrentDataVersion())
+ string const & m_name;
+ public:
+ explicit EqualFileName(string const & name) : m_name(name) {}
+ bool operator()(SimpleTree<Country> const & node) const
{
- opt = UnsetOptions(opt, file);
+ Country const & c = node.Value();
+ if (c.GetFilesCount() > 0)
+ return (c.GetFile().GetFileWithoutExt() == m_name);
+ else
+ return false;
}
+ };
}
- return opt;
-}
-TMapOptions Storage::NormalizeDeleteFileSet(TMapOptions opt) const
-{
- // Car routing files are useless without map files.
- if (HasOptions(opt, TMapOptions::EMap))
- opt = SetOptions(opt, TMapOptions::ECarRouting);
- return opt;
-}
+ TIndex Storage::FindIndexByFile(string const & name) const
+ {
+ EqualFileName fn(name);
-QueuedCountry * Storage::FindCountryInQueue(TIndex const & index)
-{
- auto it = find(m_queue.begin(), m_queue.end(), index);
- return it == m_queue.end() ? nullptr : &*it;
-}
+ for (size_t i = 0; i < m_countries.SiblingsCount(); ++i)
+ {
+ if (fn(m_countries[i]))
+ return TIndex(static_cast<int>(i));
-QueuedCountry const * Storage::FindCountryInQueue(TIndex const & index) const
-{
- auto it = find(m_queue.begin(), m_queue.end(), index);
- return it == m_queue.end() ? nullptr : &*it;
-}
+ for (size_t j = 0; j < m_countries[i].SiblingsCount(); ++j)
+ {
+ if (fn(m_countries[i][j]))
+ return TIndex(static_cast<int>(i), static_cast<int>(j));
+
+ for (size_t k = 0; k < m_countries[i][j].SiblingsCount(); ++k)
+ {
+ if (fn(m_countries[i][j][k]))
+ return TIndex(static_cast<int>(i), static_cast<int>(j), static_cast<int>(k));
+ }
+ }
+ }
-bool Storage::IsCountryInQueue(TIndex const & index) const
-{
- return FindCountryInQueue(index) != nullptr;
-}
+ return TIndex();
+ }
-bool Storage::IsCountryFirstInQueue(TIndex const & index) const
-{
- return !m_queue.empty() && m_queue.front().GetIndex() == index;
-}
+ vector<TIndex> Storage::FindAllIndexesByFile(string const & name) const
+ {
+ EqualFileName fn(name);
+ vector<TIndex> res;
-void Storage::SetDownloaderForTesting(unique_ptr<MapFilesDownloader> && downloader)
-{
- m_downloader = move(downloader);
-}
+ for (size_t i = 0; i < m_countries.SiblingsCount(); ++i)
+ {
+ if (fn(m_countries[i]))
+ res.emplace_back(static_cast<int>(i));
-shared_ptr<LocalCountryFile> Storage::GetLocalFile(TIndex const & index, int64_t version) const
-{
- auto const it = m_localFiles.find(index);
- if (it == m_localFiles.end() || it->second.empty())
- return shared_ptr<LocalCountryFile>();
- list<shared_ptr<LocalCountryFile>> const & files = it->second;
- for (shared_ptr<LocalCountryFile> const & file : files)
- {
- if (file->GetVersion() == version)
- return file;
- }
- return shared_ptr<LocalCountryFile>();
-}
+ for (size_t j = 0; j < m_countries[i].SiblingsCount(); ++j)
+ {
+ if (fn(m_countries[i][j]))
+ res.emplace_back(static_cast<int>(i), static_cast<int>(j));
+
+ for (size_t k = 0; k < m_countries[i][j].SiblingsCount(); ++k)
+ {
+ if (fn(m_countries[i][j][k]))
+ res.emplace_back(static_cast<int>(i), static_cast<int>(j), static_cast<int>(k));
+ }
+ }
+ }
-void Storage::RegisterCountryFiles(shared_ptr<LocalCountryFile> localFile)
-{
- CHECK(localFile.get(), ());
- localFile->SyncWithDisk();
-
- TIndex const index = FindIndexByFile(localFile->GetCountryFile().GetNameWithoutExt());
- shared_ptr<LocalCountryFile> existingFile = GetLocalFile(index, localFile->GetVersion());
- if (existingFile.get() != nullptr)
- ASSERT_EQUAL(localFile.get(), existingFile.get(), ());
- else
- m_localFiles[index].push_front(localFile);
-}
+ return res;
+ }
-void Storage::RegisterCountryFiles(TIndex const & index, string const & directory, int64_t version)
-{
- shared_ptr<LocalCountryFile> localFile = GetLocalFile(index, version);
- if (localFile)
- return;
+ void Storage::GetOutdatedCountries(vector<Country const *> & res) const
+ {
+ Platform & pl = GetPlatform();
+ Platform::FilesList fList;
+ pl.GetFilesByExt(pl.WritableDir(), DATA_FILE_EXTENSION, fList);
- CountryFile const & countryFile = GetCountryFile(index);
- localFile = make_shared<LocalCountryFile>(directory, countryFile, version);
- RegisterCountryFiles(localFile);
-}
+ for_each(fList.begin(), fList.end(), bind(&my::GetNameWithoutExt, _1));
-void Storage::RegisterFakeCountryFiles(platform::LocalCountryFile const & localFile)
-{
- shared_ptr<LocalCountryFile> fakeCountryLocalFile = make_shared<LocalCountryFile>(localFile);
- fakeCountryLocalFile->SyncWithDisk();
- m_localFilesForFakeCountries[fakeCountryLocalFile->GetCountryFile()] = fakeCountryLocalFile;
-}
+ fList.erase(remove_if(fList.begin(), fList.end(), [] (string const & t)
+ {
+ return (t == WORLD_COASTS_FILE_NAME) || (t == WORLD_FILE_NAME);
+ }), fList.end());
-void Storage::DeleteCountryFiles(TIndex const & index, TMapOptions opt)
-{
- auto const it = m_localFiles.find(index);
- if (it == m_localFiles.end())
- return;
+ fList.erase(remove_if(fList.begin(), fList.end(), [this] (string const & file)
+ {
+ return (CountryStatusEx(FindIndexByFile(file)) != TStatus::EOnDiskOutOfDate);
+ }), fList.end());
- // TODO (@gorshenin): map-only indexes should not be touched when
- // routing indexes are removed.
- if (!it->second.empty())
- DeleteCountryIndexes(it->second.front()->GetCountryFile());
+ for (size_t i = 0; i < fList.size(); ++i)
+ res.push_back(&CountryByIndex(FindIndexByFile(fList[i])));
+ }
- list<shared_ptr<platform::LocalCountryFile>> & localFiles = it->second;
- for (shared_ptr<LocalCountryFile> & localFile : localFiles)
+ void Storage::SetDownloaderForTesting(unique_ptr<MapFilesDownloader> && downloader)
{
- localFile->DeleteFromDisk(opt);
- localFile->SyncWithDisk();
- if (localFile->GetFiles() == TMapOptions::ENothing)
- localFile.reset();
+ m_downloader = move(downloader);
}
- auto isNull = [](shared_ptr<LocalCountryFile> const & localFile)
- {
- return !localFile.get();
- };
- localFiles.remove_if(isNull);
- if (localFiles.empty())
- m_localFiles.erase(index);
-}
-bool Storage::DeleteCountryFilesFromDownloader(TIndex const & index, TMapOptions opt)
-{
- QueuedCountry * queuedCountry = FindCountryInQueue(index);
- if (!queuedCountry)
- return false;
- if (IsCountryFirstInQueue(index))
+ TStatus Storage::CountryStatusWithoutFailed(TIndex const & index) const
{
- // Abrupt downloading of the current file if it should be removed.
- if (HasOptions(opt, queuedCountry->GetCurrentFile()))
- m_downloader->Reset();
+ // first, check if we already downloading this country or have in in the queue
+ auto const found = find(m_queue.begin(), m_queue.end(), index);
+ if (found != m_queue.end())
+ {
+ if (found == m_queue.begin())
+ return TStatus::EDownloading;
+ else
+ return TStatus::EInQueue;
+ }
+
+ return CountryStatusFull(index, TStatus::EUnknown);
}
- queuedCountry->RemoveOptions(opt);
- // Remove country from the queue if there's nothing to download.
- if (queuedCountry->GetInitOptions() == TMapOptions::ENothing)
- m_queue.erase(find(m_queue.begin(), m_queue.end(), index));
- return true;
-}
+ TStatus Storage::CountryStatusFull(TIndex const & index, TStatus const status) const
+ {
+ if (status != TStatus::EUnknown)
+ return status;
-void Storage::KickDownloaderAfterDeletionOfCountryFiles(TIndex const & index)
-{
- // Do nothing when there're no countries to download or when downloader is busy.
- if (m_queue.empty() || !m_downloader->IsIdle())
- return;
- if (IsCountryFirstInQueue(index))
- DownloadNextFile(m_queue.front());
- else
- DownloadNextCountryFromQueue();
-}
+ TStatus res = status;
+ Country const & c = CountryByIndex(index);
+ LocalAndRemoteSizeT const size = c.Size(TMapOptions::EMap);
-uint64_t Storage::GetDownloadSize(QueuedCountry const & queuedCountry) const
-{
- CountryFile const & file = GetCountryFile(queuedCountry.GetIndex());
- return GetRemoteSize(file, queuedCountry.GetCurrentFile());
-}
+ if (size.first == 0)
+ return TStatus::ENotDownloaded;
-string Storage::GetFileDownloadPath(TIndex const & index, TMapOptions file) const
-{
- Platform & platform = GetPlatform();
- CountryFile const & countryFile = GetCountryFile(index);
- return platform.WritablePathForFile(countryFile.GetNameWithExt(file) + READY_FILE_EXTENSION);
+ if (size.second == 0)
+ return TStatus::EUnknown;
+
+ res = TStatus::EOnDisk;
+ if (size.first != size.second)
+ {
+ /// @todo Do better version check, not just size comparison.
+
+ // Additional check for .ready file.
+ // Use EOnDisk status if it's good, or EOnDiskOutOfDate otherwise.
+ Platform const & pl = GetPlatform();
+ string const fName = c.GetFile().GetFileWithExt(TMapOptions::EMap) + READY_FILE_EXTENSION;
+
+ uint64_t sz = 0;
+ if (!pl.GetFileSizeByFullPath(pl.WritablePathForFile(fName), sz) || sz != size.second)
+ res = TStatus::EOnDiskOutOfDate;
+ }
+
+ return res;
+ }
}
-} // namespace storage
diff --git a/storage/storage.hpp b/storage/storage.hpp
index 0e3b1f1ccb..efdc07f4c6 100644
--- a/storage/storage.hpp
+++ b/storage/storage.hpp
@@ -3,230 +3,168 @@
#include "storage/country.hpp"
#include "storage/index.hpp"
#include "storage/map_files_downloader.hpp"
-#include "storage/queued_country.hpp"
-#include "storage/storage_defines.hpp"
#include "storage/storage_defines.hpp"
-#include "std/function.hpp"
+#include "std/vector.hpp"
#include "std/list.hpp"
-#include "std/set.hpp"
-#include "std/shared_ptr.hpp"
#include "std/string.hpp"
+#include "std/set.hpp"
+#include "std/function.hpp"
#include "std/unique_ptr.hpp"
-#include "std/vector.hpp"
+
namespace storage
{
-/// Can be used to store local maps and/or maps available for download
-class Storage
-{
- /// We support only one simultaneous request at the moment
- unique_ptr<MapFilesDownloader> m_downloader;
-
- /// stores timestamp for update checks
- int64_t m_currentVersion;
-
- CountriesContainerT m_countries;
-
- typedef list<QueuedCountry> TQueue;
-
- /// @todo. It appeared that our application uses m_queue from
- /// different threads without any synchronization. To reproduce it
- /// just download a map "from the map" on Android. (CountryStatus is
- /// called from a different thread.) It's necessary to check if we
- /// can call all the methods from a single thread using
- /// RunOnUIThread. If not, at least use a syncronization object.
- TQueue m_queue;
-
- /// stores countries whose download has failed recently
- typedef set<TIndex> TCountriesSet;
- TCountriesSet m_failedCountries;
-
- map<TIndex, list<shared_ptr<platform::LocalCountryFile>>> m_localFiles;
- map<platform::CountryFile, shared_ptr<platform::LocalCountryFile>> m_localFilesForFakeCountries;
-
- /// used to correctly calculate total country download progress with more than 1 file
- /// <current, total>
- MapFilesDownloader::TProgress m_countryProgress;
-
- /// @name Communicate with GUI
- //@{
- typedef function<void(TIndex const &)> TChangeCountryFunction;
- typedef function<void(TIndex const &, LocalAndRemoteSizeT const &)> TProgressFunction;
-
- int m_currentSlotId;
-
- struct CountryObservers
+ /// Can be used to store local maps and/or maps available for download
+ class Storage
{
- TChangeCountryFunction m_changeCountryFn;
- TProgressFunction m_progressFn;
- int m_slotId;
- };
-
- typedef list<CountryObservers> ObserversContT;
- ObserversContT m_observers;
- //@}
-
- typedef function<void(platform::LocalCountryFile const &)> TUpdateAfterDownload;
-
- // This function is called each time all files requested for a
- // country were successfully downloaded.
- TUpdateAfterDownload m_updateAfterDownload;
+ /// We support only one simultaneous request at the moment
+ unique_ptr<MapFilesDownloader> m_downloader;
- void DownloadNextCountryFromQueue();
+ /// stores timestamp for update checks
+ int64_t m_currentVersion;
- void LoadCountriesFile(bool forceReload);
+ CountriesContainerT m_countries;
- void ReportProgress(TIndex const & index, pair<int64_t, int64_t> const & p);
+ /// store queue for downloading
+ class QueuedCountry
+ {
+ TIndex m_index;
+ CountryFile const * m_pFile;
+ TMapOptions m_init, m_left, m_current;
- /// Called on the main thread by MapFilesDownloader when list of
- /// suitable servers is received.
- void OnServerListDownloaded(vector<string> const & urls);
+ public:
+ QueuedCountry(Storage const & storage, TIndex const & index, TMapOptions opt);
- /// Called on the main thread by MapFilesDownloader when
- /// downloading of a map file succeeds/fails.
- void OnMapFileDownloadFinished(bool success, MapFilesDownloader::TProgress const & progress);
+ void AddOptions(TMapOptions opt);
+ bool MoveNextFile();
+ bool Correct(TStatus currentStatus);
- /// Periodically called on the main thread by MapFilesDownloader
- /// during the downloading process.
- void OnMapFileDownloadProgress(MapFilesDownloader::TProgress const & progress);
+ TIndex const & GetIndex() const { return m_index; }
+ TMapOptions GetInitOptions() const { return m_init; }
+
+ bool operator== (TIndex const & index) const { return (m_index == index); }
+
+ uint64_t GetDownloadSize() const;
+ LocalAndRemoteSizeT GetFullSize() const;
+ size_t GetFullRemoteSize() const;
+ string GetFileName() const;
+ string GetMapFileName() const;
+ };
- bool RegisterDownloadedFile(string const & path, uint64_t size, int64_t version);
- void OnMapDownloadFinished(shared_ptr<platform::LocalCountryFile> localFile);
- void OnMapDownloadFailed();
+ typedef list<QueuedCountry> TQueue;
+ /// @todo. It appeared that our application uses m_queue from different threads
+ /// without any synchronization. To reproduce it just download a map "from the map"
+ /// on Android. (CountryStatus is called from a different thread.)
+ /// It's necessary to check if we can call all the methods from a single thread using RunOnUIThread.
+ /// If not, at least use a syncronization object.
+ TQueue m_queue;
- /// Initiates downloading of the next file from the queue.
- void DownloadNextFile(QueuedCountry const & country);
+ /// stores countries which download has failed recently
+ typedef set<TIndex> TCountriesSet;
+ TCountriesSet m_failedCountries;
-public:
- Storage();
+ /// used to correctly calculate total country download progress with more than 1 file
+ /// <current, total>
+ MapFilesDownloader::TProgress m_countryProgress;
- void Init(TUpdateAfterDownload const & updateFn);
+ /// @name Communicate with GUI
+ //@{
+ typedef function<void (TIndex const &)> TChangeCountryFunction;
+ typedef function<void (TIndex const &, LocalAndRemoteSizeT const &)> TProgressFunction;
- // Finds and registers all map files in maps directory. In the case
- // of several versions of the same map keeps only the latest one, others
- // are deleted from disk.
- // *NOTE* storage will forget all already known local maps.
- void RegisterAllLocalMaps();
+ int m_currentSlotId;
- // Returns list of all local maps, including fake countries.
- void GetLocalMaps(vector<platform::CountryFile> & maps);
+ struct CountryObservers
+ {
+ TChangeCountryFunction m_changeCountryFn;
+ TProgressFunction m_progressFn;
+ int m_slotId;
+ };
- /// @return unique identifier that should be used with Unsubscribe function
- int Subscribe(TChangeCountryFunction const & change, TProgressFunction const & progress);
- void Unsubscribe(int slotId);
+ typedef list<CountryObservers> ObserversContT;
+ ObserversContT m_observers;
+ //@}
- Country const & CountryByIndex(TIndex const & index) const;
- TIndex FindIndexByFile(string const & name) const;
- /// @todo Temporary function to gel all associated indexes for the country file name.
- /// Will be removed in future after refactoring.
- vector<TIndex> FindAllIndexesByFile(string const & name) const;
- void GetGroupAndCountry(TIndex const & index, string & group, string & country) const;
+ /// @name Communicate with Framework
+ //@{
+ typedef function<void (string const &, TMapOptions)> TUpdateAfterDownload;
+ TUpdateAfterDownload m_updateAfterDownload;
+ //@}
- size_t CountriesCount(TIndex const & index) const;
- string const & CountryName(TIndex const & index) const;
- string const & CountryFlag(TIndex const & index) const;
+ void DownloadNextCountryFromQueue();
- LocalAndRemoteSizeT CountrySizeInBytes(TIndex const & index, TMapOptions opt) const;
- platform::CountryFile const & GetCountryFile(TIndex const & index) const;
- shared_ptr<platform::LocalCountryFile> GetLatestLocalFile(
- platform::CountryFile const & countryFile) const;
- shared_ptr<platform::LocalCountryFile> GetLatestLocalFile(TIndex const & index) const;
+ void LoadCountriesFile(bool forceReload);
- /// Fast version, doesn't check if country is out of date
- TStatus CountryStatus(TIndex const & index) const;
- /// Slow version, but checks if country is out of date
- TStatus CountryStatusEx(TIndex const & index) const;
- void CountryStatusEx(TIndex const & index, TStatus & status, TMapOptions & options) const;
+ void ReportProgress(TIndex const & index, pair<int64_t, int64_t> const & p);
- /// Puts country denoted by index into the downloader's queue.
- /// During downloading process notifies observers about downloading
- /// progress and status changes.
- void DownloadCountry(TIndex const & index, TMapOptions opt);
+ /// Called on the main thread by MapFilesDownloader when list of
+ /// suitable servers is received.
+ void OnServerListDownloaded(vector<string> const & urls);
- /// Removes country files (for all versions) from the device.
- /// Notifies observers about country status change.
- void DeleteCountry(TIndex const & index, TMapOptions opt);
+ /// Called on the main thread by MapFilesDownloader when
+ /// downloading of a map file succeeds/fails.
+ void OnMapDownloadFinished(bool success, MapFilesDownloader::TProgress const & progress);
- /// Removes country files of a particular version from the device.
- /// Notifies observers about country status change.
- void DeleteCustomCountryVersion(platform::LocalCountryFile const & localFile);
+ /// Periodically called on the main thread by MapFilesDownloader
+ /// during the downloading process.
+ void OnMapDownloadProgress(MapFilesDownloader::TProgress const & progress);
- /// \return True iff country denoted by index was successfully
- /// deleted from the downloader's queue.
- bool DeleteFromDownloader(TIndex const & index);
- bool IsDownloadInProgress() const;
+ /// Initiates downloading of the next file from the queue.
+ void DownloadNextFile(QueuedCountry const & cnt);
- void NotifyStatusChanged(TIndex const & index);
+ public:
+ Storage();
- string GetFileDownloadUrl(string const & baseUrl, TIndex const & index, TMapOptions file) const;
+ void Init(TUpdateAfterDownload const & updateFn);
- /// @param[out] res Populated with oudated countries.
- void GetOutdatedCountries(vector<Country const *> & countries) const;
+ /// @return unique identifier that should be used with Unsubscribe function
+ int Subscribe(TChangeCountryFunction const & change,
+ TProgressFunction const & progress);
+ void Unsubscribe(int slotId);
- inline int64_t GetCurrentDataVersion() const { return m_currentVersion; }
+ Country const & CountryByIndex(TIndex const & index) const;
+ TIndex FindIndexByFile(string const & name) const;
+ /// @todo Temporary function to gel all associated indexes for the country file name.
+ /// Will be removed in future after refactoring.
+ vector<TIndex> FindAllIndexesByFile(string const & name) const;
+ void GetGroupAndCountry(TIndex const & index, string & group, string & country) const;
- void SetDownloaderForTesting(unique_ptr<MapFilesDownloader> && downloader);
+ size_t CountriesCount(TIndex const & index) const;
+ string const & CountryName(TIndex const & index) const;
+ string const & CountryFlag(TIndex const & index) const;
-private:
- TStatus CountryStatusWithoutFailed(TIndex const & index) const;
- TStatus CountryStatusFull(TIndex const & index, TStatus const status) const;
+ string CountryFileName(TIndex const & index, TMapOptions opt) const;
+ string const & CountryFileNameWithoutExt(TIndex const & index) const;
+ /// Removes map file extension.
+ static string MapWithoutExt(string mapFile);
+ LocalAndRemoteSizeT CountrySizeInBytes(TIndex const & index, TMapOptions opt) const;
- // Modifies file set of requested files - always adds a map file
- // when routing file is requested for downloading, but drops all
- // already downloaded and up-to-date files.
- TMapOptions NormalizeDownloadFileSet(TIndex const & index, TMapOptions opt) const;
+ /// Fast version, doesn't check if country is out of date
+ TStatus CountryStatus(TIndex const & index) const;
+ /// Slow version, but checks if country is out of date
+ TStatus CountryStatusEx(TIndex const & index) const;
+ void CountryStatusEx(TIndex const & index, TStatus & status, TMapOptions & options) const;
- // Modifies file set of file to deletion - always adds (marks for
- // removal) a routing file when map file is marked for deletion.
- TMapOptions NormalizeDeleteFileSet(TMapOptions opt) const;
+ //m2::RectD CountryBounds(TIndex const & index) const;
- // Returns a pointer to a country in the downloader's queue.
- QueuedCountry * FindCountryInQueue(TIndex const & index);
+ void DownloadCountry(TIndex const & index, TMapOptions opt);
+ bool DeleteFromDownloader(TIndex const & index);
+ bool IsDownloadInProgress() const;
- // Returns a pointer to a country in the downloader's queue.
- QueuedCountry const * FindCountryInQueue(TIndex const & index) const;
+ void NotifyStatusChanged(TIndex const & index);
- // Returns true when country is in the downloader's queue.
- bool IsCountryInQueue(TIndex const & index) const;
+ string GetFileDownloadUrl(string const & baseUrl, string const & fName) const;
- // Returns true when country is first in the downloader's queue.
- bool IsCountryFirstInQueue(TIndex const & index) const;
+ /// @param[out] res Populated with oudated countries.
+ void GetOutdatedCountries(vector<Country const *> & res) const;
- // Returns local country files of a particular version, or wrapped
- // nullptr if there're no country files corresponding to the
- // version.
- shared_ptr<platform::LocalCountryFile> GetLocalFile(TIndex const & index, int64_t version) const;
+ int64_t GetCurrentDataVersion() const { return m_currentVersion; }
- // Tries to register disk files for a real (listed in countries.txt)
- // country. If map files of the same version were already
- // registered, does nothing.
- void RegisterCountryFiles(shared_ptr<platform::LocalCountryFile> localFile);
+ void SetDownloaderForTesting(unique_ptr<MapFilesDownloader> && downloader);
- // Registers disk files for a country. This method must be used only
- // for real (listed in counties.txt) countries.
- void RegisterCountryFiles(TIndex const & index, string const & directory, int64_t version);
-
- // Registers disk files for a country. This method must be used only
- // for custom (made by user) map files.
- void RegisterFakeCountryFiles(platform::LocalCountryFile const & localFile);
-
- // Removes disk files for all versions of a country.
- void DeleteCountryFiles(TIndex const & index, TMapOptions opt);
-
- // Removes country files from downloader.
- bool DeleteCountryFilesFromDownloader(TIndex const & index, TMapOptions opt);
-
- // Resumes possibly cancelled downloading of countries after
- // deletion of country files.
- void KickDownloaderAfterDeletionOfCountryFiles(TIndex const & index);
-
- // Returns download size of the currently downloading file for the
- // queued country.
- uint64_t GetDownloadSize(QueuedCountry const & queuedCountry) const;
-
- // Returns a path to a place on disk downloader can use for
- // downloaded files.
- string GetFileDownloadPath(TIndex const & index, TMapOptions file) const;
-};
-} // storage
+ private:
+ TStatus CountryStatusWithoutFailed(TIndex const & index) const;
+ TStatus CountryStatusFull(TIndex const & index, TStatus const status) const;
+ };
+}
diff --git a/storage/storage.pro b/storage/storage.pro
index 5cd9da9f8a..ba4d116a3e 100644
--- a/storage/storage.pro
+++ b/storage/storage.pro
@@ -18,7 +18,6 @@ HEADERS += \
http_map_files_downloader.hpp \
index.hpp \
map_files_downloader.hpp \
- queued_country.hpp \
simple_tree.hpp \
storage.hpp \
storage_defines.hpp \
@@ -29,6 +28,5 @@ SOURCES += \
country_info.cpp \
http_map_files_downloader.cpp \
index.cpp \
- queued_country.cpp \
storage.cpp \
storage_defines.cpp \
diff --git a/storage/storage_defines.hpp b/storage/storage_defines.hpp
index 901ecc10d0..5aa9df921b 100644
--- a/storage/storage_defines.hpp
+++ b/storage/storage_defines.hpp
@@ -22,4 +22,4 @@ namespace storage
string DebugPrint(TStatus status);
typedef pair<uint64_t, uint64_t> LocalAndRemoteSizeT;
- } // namespace storage
+}
diff --git a/storage/storage_tests/fake_map_files_downloader.hpp b/storage/storage_tests/fake_map_files_downloader.hpp
index cb69bcb2fa..ae544db595 100644
--- a/storage/storage_tests/fake_map_files_downloader.hpp
+++ b/storage/storage_tests/fake_map_files_downloader.hpp
@@ -18,7 +18,6 @@ class FakeMapFilesDownloader : public MapFilesDownloader
{
public:
FakeMapFilesDownloader(TaskRunner & taskRunner);
-
virtual ~FakeMapFilesDownloader();
// MapFilesDownloader overrides:
diff --git a/storage/storage_tests/queued_country_tests.cpp b/storage/storage_tests/queued_country_tests.cpp
deleted file mode 100644
index 01634a6bcf..0000000000
--- a/storage/storage_tests/queued_country_tests.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "testing/testing.hpp"
-
-#include "storage/queued_country.hpp"
-#include "storage/storage.hpp"
-
-namespace storage
-{
-UNIT_TEST(QueuedCountry_AddOptions)
-{
- Storage storage;
- TIndex const index = storage.FindIndexByFile("USA_Georgia");
- QueuedCountry country(index, TMapOptions::ECarRouting);
-
- TEST_EQUAL(index, country.GetIndex(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetCurrentFile(), ());
-
- country.AddOptions(TMapOptions::EMap);
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetCurrentFile(), ());
-
- TEST(country.SwitchToNextFile(), ());
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetCurrentFile(), ());
-
- TEST(!country.SwitchToNextFile(), ());
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetCurrentFile(), ());
-}
-
-UNIT_TEST(QueuedCountry_RemoveOptions)
-{
- Storage storage;
- TIndex const index = storage.FindIndexByFile("USA_Georgia");
-
- {
- QueuedCountry country(index, TMapOptions::EMapWithCarRouting);
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
-
- country.RemoveOptions(TMapOptions::EMap);
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
-
- country.RemoveOptions(TMapOptions::ECarRouting);
- TEST_EQUAL(TMapOptions::ENothing, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
- }
-
- {
- QueuedCountry country(index, TMapOptions::EMapWithCarRouting);
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
-
- country.SwitchToNextFile();
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetDownloadedFiles(), ());
-
- country.RemoveOptions(TMapOptions::ECarRouting);
- TEST_EQUAL(TMapOptions::EMap, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetDownloadedFiles(), ());
- }
-
- {
- QueuedCountry country(index, TMapOptions::EMapWithCarRouting);
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
-
- country.SwitchToNextFile();
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetDownloadedFiles(), ());
-
- country.RemoveOptions(TMapOptions::EMap);
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
-
- country.SwitchToNextFile();
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetInitOptions(), ());
- TEST_EQUAL(TMapOptions::ENothing, country.GetCurrentFile(), ());
- TEST_EQUAL(TMapOptions::ECarRouting, country.GetDownloadedFiles(), ());
- }
-}
-
-UNIT_TEST(QueuedCountry_Bits)
-{
- Storage storage;
- TIndex const index = storage.FindIndexByFile("USA_Georgia");
- QueuedCountry country(index, TMapOptions::EMapWithCarRouting);
- TEST_EQUAL(TMapOptions::ENothing, country.GetDownloadedFiles(), ());
-
- TEST(country.SwitchToNextFile(), ());
- TEST_EQUAL(TMapOptions::EMap, country.GetDownloadedFiles(), ());
-
- TEST(!country.SwitchToNextFile(), ());
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, country.GetDownloadedFiles(), ());
-}
-} // namespace storage
diff --git a/storage/storage_tests/storage_tests.cpp b/storage/storage_tests/storage_tests.cpp
index 9bc206024c..60d795d4c7 100644
--- a/storage/storage_tests/storage_tests.cpp
+++ b/storage/storage_tests/storage_tests.cpp
@@ -5,9 +5,6 @@
#include "storage/storage_tests/fake_map_files_downloader.hpp"
#include "storage/storage_tests/task_runner.hpp"
-#include "platform/country_file.hpp"
-#include "platform/local_country_file.hpp"
-#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "coding/file_name_utils.hpp"
@@ -17,73 +14,67 @@
#include "defines.hpp"
#include "base/scope_guard.hpp"
-#include "base/string_utils.hpp"
#include "std/bind.hpp"
-#include "std/map.hpp"
#include "std/unique_ptr.hpp"
-#include "std/vector.hpp"
-using namespace platform;
using namespace storage;
namespace
{
-// This class checks steps Storage::DownloadMap() performs to download a map.
class CountryDownloaderChecker
{
public:
- CountryDownloaderChecker(Storage & storage, TIndex const & index, TMapOptions files,
- vector<TStatus> const & transitionList)
+ CountryDownloaderChecker(Storage & storage, string const & countryFileName, TMapOptions files)
: m_storage(storage),
- m_index(index),
- m_countryFile(storage.GetCountryFile(m_index)),
+ m_index(m_storage.FindIndexByFile(countryFileName)),
m_files(files),
+ m_lastStatus(TStatus::ENotDownloaded),
m_bytesDownloaded(0),
m_totalBytesToDownload(0),
- m_slot(0),
- m_currStatus(0),
- m_transitionList(transitionList)
+ m_slot(0)
{
m_slot = m_storage.Subscribe(
bind(&CountryDownloaderChecker::OnCountryStatusChanged, this, _1),
bind(&CountryDownloaderChecker::OnCountryDownloadingProgress, this, _1, _2));
- TEST(m_index.IsValid(), (m_countryFile));
- TEST(!m_transitionList.empty(), (m_countryFile));
+ CHECK(m_index.IsValid(), ());
}
void StartDownload()
{
- TEST_EQUAL(0, m_currStatus, (m_countryFile));
- TEST_LESS(m_currStatus, m_transitionList.size(), (m_countryFile));
- TEST_EQUAL(m_transitionList[m_currStatus], m_storage.CountryStatusEx(m_index),
- (m_countryFile));
+ CHECK_EQUAL(m_lastStatus, m_storage.CountryStatusEx(m_index), ());
m_storage.DownloadCountry(m_index, m_files);
}
virtual ~CountryDownloaderChecker()
{
- TEST_EQUAL(m_currStatus + 1, m_transitionList.size(), (m_countryFile));
m_storage.Unsubscribe(m_slot);
+
+ CHECK_EQUAL(TStatus::EOnDisk, m_lastStatus, ());
+ CHECK_EQUAL(m_bytesDownloaded, m_totalBytesToDownload, ());
+
+ LocalAndRemoteSizeT localAndRemoteSize = m_storage.CountrySizeInBytes(m_index, m_files);
+ CHECK_EQUAL(m_bytesDownloaded, localAndRemoteSize.first, ());
+ CHECK_EQUAL(m_totalBytesToDownload, localAndRemoteSize.second, ());
}
+protected:
+ virtual void CheckStatusTransition(TStatus oldStatus, TStatus newStatus) const = 0;
+
private:
void OnCountryStatusChanged(TIndex const & index)
{
if (index != m_index)
return;
+ TStatus status = m_storage.CountryStatusEx(m_index);
- TStatus const nextStatus = m_storage.CountryStatusEx(m_index);
- LOG(LINFO, (m_countryFile, "status transition: from", m_transitionList[m_currStatus], "to",
- nextStatus));
- TEST_LESS(m_currStatus + 1, m_transitionList.size(), (m_countryFile));
- TEST_EQUAL(nextStatus, m_transitionList[m_currStatus + 1], (m_countryFile));
- ++m_currStatus;
- if (m_transitionList[m_currStatus] == TStatus::EDownloading)
+ CheckStatusTransition(m_lastStatus, status);
+ if (status == TStatus::EDownloading)
{
LocalAndRemoteSizeT localAndRemoteSize = m_storage.CountrySizeInBytes(m_index, m_files);
m_totalBytesToDownload = localAndRemoteSize.second;
}
+ m_lastStatus = status;
}
void OnCountryDownloadingProgress(TIndex const & index, LocalAndRemoteSizeT const & progress)
@@ -91,410 +82,185 @@ private:
if (index != m_index)
return;
- LOG(LINFO, (m_countryFile, "downloading progress:", progress));
-
- TEST_GREATER(progress.first, m_bytesDownloaded, (m_countryFile));
+ CHECK_GREATER(progress.first, m_bytesDownloaded, ());
m_bytesDownloaded = progress.first;
- TEST_LESS_OR_EQUAL(m_bytesDownloaded, m_totalBytesToDownload, (m_countryFile));
+ CHECK_LESS_OR_EQUAL(m_bytesDownloaded, m_totalBytesToDownload, ());
LocalAndRemoteSizeT localAndRemoteSize = m_storage.CountrySizeInBytes(m_index, m_files);
- TEST_EQUAL(m_totalBytesToDownload, localAndRemoteSize.second, (m_countryFile));
+ CHECK_EQUAL(m_totalBytesToDownload, localAndRemoteSize.second, ());
}
Storage & m_storage;
TIndex const m_index;
- CountryFile const m_countryFile;
+
TMapOptions const m_files;
+ TStatus m_lastStatus;
int64_t m_bytesDownloaded;
int64_t m_totalBytesToDownload;
int m_slot;
-
- size_t m_currStatus;
- vector<TStatus> m_transitionList;
};
// Checks following state transitions:
// NotDownloaded -> Downloading -> OnDisk.
-unique_ptr<CountryDownloaderChecker> AbsentCountryDownloaderChecker(Storage & storage,
- TIndex const & index,
- TMapOptions files)
-{
- return make_unique<CountryDownloaderChecker>(
- storage, index, files,
- vector<TStatus>{TStatus::ENotDownloaded, TStatus::EDownloading, TStatus::EOnDisk});
-}
-
-// Checks following state transitions:
-// OnDisk -> Downloading -> OnDisk.
-unique_ptr<CountryDownloaderChecker> PresentCountryDownloaderChecker(Storage & storage,
- TIndex const & index,
- TMapOptions files)
-{
- return make_unique<CountryDownloaderChecker>(
- storage, index, files,
- vector<TStatus>{TStatus::EOnDisk, TStatus::EDownloading, TStatus::EOnDisk});
-}
-
-// Checks following state transitions:
-// NotDownloaded -> InQueue -> Downloading -> OnDisk.
-unique_ptr<CountryDownloaderChecker> QueuedCountryDownloaderChecker(Storage & storage,
- TIndex const & index,
- TMapOptions files)
-{
- return make_unique<CountryDownloaderChecker>(
- storage, index, files, vector<TStatus>{TStatus::ENotDownloaded, TStatus::EInQueue,
- TStatus::EDownloading, TStatus::EOnDisk});
-}
-
-// Checks following state transitions:
-// NotDownloaded -> Downloading -> NotDownloaded.
-unique_ptr<CountryDownloaderChecker> CancelledCountryDownloaderChecker(Storage & storage,
- TIndex const & index,
- TMapOptions files)
+class AbsentCountryDownloaderChecker : public CountryDownloaderChecker
{
- return make_unique<CountryDownloaderChecker>(
- storage, index, files,
- vector<TStatus>{TStatus::ENotDownloaded, TStatus::EDownloading, TStatus::ENotDownloaded});
-}
+public:
+ AbsentCountryDownloaderChecker(Storage & storage, string const & countryFileName,
+ TMapOptions files)
+ : CountryDownloaderChecker(storage, countryFileName, files)
+ {
+ }
-void OnCountryDownloaded(LocalCountryFile const & localFile)
-{
- LOG(LINFO, ("OnCountryDownloaded:", localFile));
-}
+ ~AbsentCountryDownloaderChecker() override = default;
-shared_ptr<LocalCountryFile> CreateDummyMapFile(CountryFile const & countryFile, int64_t version,
- size_t size)
-{
- shared_ptr<LocalCountryFile> localFile =
- platform::PreparePlaceForCountryFiles(countryFile, version);
- TEST(localFile.get(), ("Can't prepare place for", countryFile, "(version ", version, ")"));
+protected:
+ void CheckStatusTransition(TStatus oldStatus, TStatus newStatus) const override
{
- string const zeroes(size, '\0');
- FileWriter writer(localFile->GetPath(TMapOptions::EMap));
- writer.Write(zeroes.data(), zeroes.size());
+ switch (newStatus)
+ {
+ case TStatus::EDownloading:
+ CHECK_EQUAL(oldStatus, TStatus::ENotDownloaded,
+ ("It's only possible to move from NotDownloaded to Downloading."));
+ break;
+ case TStatus::EOnDisk:
+ CHECK_EQUAL(oldStatus, TStatus::EDownloading,
+ ("It's only possible to move from Downloading to OnDisk."));
+ break;
+ default:
+ CHECK(false, ("Unknown state change: from", oldStatus, "to", newStatus));
+ }
}
- localFile->SyncWithDisk();
- TEST_EQUAL(TMapOptions::EMap, localFile->GetFiles(), ());
- TEST_EQUAL(size, localFile->GetSize(TMapOptions::EMap), ());
- return localFile;
-}
+};
-class CountryStatusChecker
+// Checks following state transitions:
+// NotDownloaded -> InQueue -> Downloading -> OnDisk.
+class QueuedCountryDownloaderChecker : public CountryDownloaderChecker
{
public:
- CountryStatusChecker(Storage & storage, TIndex const & index, TStatus status)
- : m_storage(storage), m_index(index), m_status(status), m_triggered(false)
+ QueuedCountryDownloaderChecker(Storage & storage, string const & countryFileName,
+ TMapOptions files)
+ : CountryDownloaderChecker(storage, countryFileName, files)
{
- m_slot = m_storage.Subscribe(
- bind(&CountryStatusChecker::OnCountryStatusChanged, this, _1),
- bind(&CountryStatusChecker::OnCountryDownloadingProgress, this, _1, _2));
}
- ~CountryStatusChecker()
- {
- TEST(m_triggered, ("Status checker wasn't triggered."));
- m_storage.Unsubscribe(m_slot);
- }
+ ~QueuedCountryDownloaderChecker() override = default;
-private:
- void OnCountryStatusChanged(TIndex const & index)
+protected:
+ void CheckStatusTransition(TStatus oldStatus, TStatus newStatus) const override
{
- if (index != m_index)
- return;
- TEST(!m_triggered, ("Status checker can be triggered only once."));
- TStatus status = m_storage.CountryStatusEx(m_index);
- TEST_EQUAL(m_status, status, ());
- m_triggered = true;
- }
-
- void OnCountryDownloadingProgress(TIndex const & /* index */,
- LocalAndRemoteSizeT const & /* progress */)
- {
- TEST(false, ("Unexpected country downloading progress."));
+ switch (newStatus)
+ {
+ case TStatus::EInQueue:
+ CHECK_EQUAL(oldStatus, TStatus::ENotDownloaded,
+ ("It's only possible to move from NotDownloaded to InQueue."));
+ break;
+ case TStatus::EDownloading:
+ CHECK_EQUAL(oldStatus, TStatus::EInQueue,
+ ("It's only possible to move from InQueue to Downloading."));
+ break;
+ case TStatus::EOnDisk:
+ CHECK_EQUAL(oldStatus, TStatus::EDownloading,
+ ("It's only possible to move from Downloading to OnDisk."));
+ break;
+ default:
+ CHECK(false, ("Unknown state change: from", oldStatus, "to", newStatus));
+ }
}
-
- Storage & m_storage;
- TIndex const & m_index;
- TStatus m_status;
- bool m_triggered;
- int m_slot;
};
-void InitStorage(Storage & storage, TaskRunner & runner)
+// Removes country's files that can be created during and after downloading.
+void CleanupCountryFiles(string const & countryFileName)
{
- storage.Init(&OnCountryDownloaded);
- storage.RegisterAllLocalMaps();
- storage.SetDownloaderForTesting(make_unique<FakeMapFilesDownloader>(runner));
-}
-} // namespace
+ Platform & platform = GetPlatform();
-UNIT_TEST(StorageTest_Smoke)
-{
- Storage storage;
+ string const localMapFile =
+ my::JoinFoldersToPath(platform.WritableDir(), countryFileName + DATA_FILE_EXTENSION);
+ my::DeleteFileX(localMapFile);
+ my::DeleteFileX(localMapFile + READY_FILE_EXTENSION);
- TIndex const usaGeorgiaIndex = storage.FindIndexByFile("USA_Georgia");
- TEST(usaGeorgiaIndex.IsValid(), ());
- CountryFile usaGeorgiaFile = storage.GetCountryFile(usaGeorgiaIndex);
- TEST_EQUAL(usaGeorgiaFile.GetNameWithExt(TMapOptions::EMap), "USA_Georgia" DATA_FILE_EXTENSION,
- ());
-
- TIndex const georgiaIndex = storage.FindIndexByFile("Georgia");
- TEST(georgiaIndex.IsValid(), ());
- CountryFile georgiaFile = storage.GetCountryFile(georgiaIndex);
- TEST_EQUAL(georgiaFile.GetNameWithExt(TMapOptions::ECarRouting),
- "Georgia" DATA_FILE_EXTENSION ROUTING_FILE_EXTENSION, ());
-
- TEST_NOT_EQUAL(usaGeorgiaIndex, georgiaIndex, ());
+ string const localRoutingFile = localMapFile + ROUTING_FILE_EXTENSION;
+ my::DeleteFileX(localRoutingFile);
+ my::DeleteFileX(localRoutingFile + READY_FILE_EXTENSION);
}
-UNIT_TEST(StorageTest_SingleCountryDownloading)
+void OnCountryDownloaded(string const & mapFileName, TMapOptions files)
{
- Storage storage;
- TaskRunner runner;
- InitStorage(storage, runner);
+ Platform & platform = GetPlatform();
- TIndex const azerbaijanIndex = storage.FindIndexByFile("Azerbaijan");
- TEST(azerbaijanIndex.IsValid(), ());
+ string const localMapFile = my::JoinFoldersToPath(platform.WritableDir(), mapFileName);
+ string const localRoutingFile = localMapFile + ROUTING_FILE_EXTENSION;
- CountryFile azerbaijanFile = storage.GetCountryFile(azerbaijanIndex);
- storage.DeleteCountry(azerbaijanIndex, TMapOptions::EMapWithCarRouting);
-
- {
- MY_SCOPE_GUARD(cleanupCountryFiles,
- bind(&Storage::DeleteCountry, &storage, azerbaijanIndex, TMapOptions::EMap));
- unique_ptr<CountryDownloaderChecker> checker =
- AbsentCountryDownloaderChecker(storage, azerbaijanIndex, TMapOptions::EMapWithCarRouting);
- checker->StartDownload();
- runner.Run();
- }
-
- {
- MY_SCOPE_GUARD(cleanupCountryFiles, bind(&Storage::DeleteCountry, &storage, azerbaijanIndex,
- TMapOptions::EMapWithCarRouting));
- unique_ptr<CountryDownloaderChecker> checker =
- AbsentCountryDownloaderChecker(storage, azerbaijanIndex, TMapOptions::EMapWithCarRouting);
- checker->StartDownload();
- runner.Run();
- }
+ if (HasOptions(files, TMapOptions::EMap))
+ CHECK(my::RenameFileX(localMapFile + READY_FILE_EXTENSION, localMapFile), ());
+ if (HasOptions(files, TMapOptions::ECarRouting))
+ CHECK(my::RenameFileX(localRoutingFile + READY_FILE_EXTENSION, localRoutingFile), ());
}
-UNIT_TEST(StorageTest_TwoCountriesDownloading)
-{
- Storage storage;
- TaskRunner runner;
- InitStorage(storage, runner);
-
- TIndex const uruguayIndex = storage.FindIndexByFile("Uruguay");
- TEST(uruguayIndex.IsValid(), ());
- storage.DeleteCountry(uruguayIndex, TMapOptions::EMap);
- MY_SCOPE_GUARD(cleanupUruguayFiles,
- bind(&Storage::DeleteCountry, &storage, uruguayIndex, TMapOptions::EMap));
-
- TIndex const venezuelaIndex = storage.FindIndexByFile("Venezuela");
- TEST(venezuelaIndex.IsValid(), ());
- storage.DeleteCountry(venezuelaIndex, TMapOptions::EMapWithCarRouting);
- MY_SCOPE_GUARD(cleanupVenezuelaFiles, bind(&Storage::DeleteCountry, &storage, venezuelaIndex,
- TMapOptions::EMapWithCarRouting));
-
- unique_ptr<CountryDownloaderChecker> uruguayChecker =
- AbsentCountryDownloaderChecker(storage, uruguayIndex, TMapOptions::EMap);
- unique_ptr<CountryDownloaderChecker> venezuelaChecker =
- QueuedCountryDownloaderChecker(storage, venezuelaIndex, TMapOptions::EMapWithCarRouting);
- uruguayChecker->StartDownload();
- venezuelaChecker->StartDownload();
- runner.Run();
-}
-
-UNIT_TEST(StorageTest_DeleteTwoVersionsOfTheSameCountry)
-{
- Storage storage;
- storage.Init(&OnCountryDownloaded);
- storage.RegisterAllLocalMaps();
-
- TIndex const index = storage.FindIndexByFile("Azerbaijan");
- TEST(index.IsValid(), ());
- CountryFile const countryFile = storage.GetCountryFile(index);
-
- storage.DeleteCountry(index, TMapOptions::EMapWithCarRouting);
- shared_ptr<LocalCountryFile> latestLocalFile = storage.GetLatestLocalFile(index);
- TEST(!latestLocalFile.get(), ("Country wasn't deleted from disk."));
- TEST_EQUAL(TStatus::ENotDownloaded, storage.CountryStatusEx(index), ());
-
- shared_ptr<LocalCountryFile> localFileV1 =
- CreateDummyMapFile(countryFile, 1 /* version */, 1024 /* size */);
- storage.RegisterAllLocalMaps();
- latestLocalFile = storage.GetLatestLocalFile(index);
- TEST(latestLocalFile.get(), ("Created map file wasn't found by storage."));
- TEST_EQUAL(latestLocalFile->GetVersion(), localFileV1->GetVersion(), ());
- TEST_EQUAL(TStatus::EOnDiskOutOfDate, storage.CountryStatusEx(index), ());
-
- shared_ptr<LocalCountryFile> localFileV2 =
- CreateDummyMapFile(countryFile, 2 /* version */, 2048 /* size */);
- storage.RegisterAllLocalMaps();
- latestLocalFile = storage.GetLatestLocalFile(index);
- TEST(latestLocalFile.get(), ("Created map file wasn't found by storage."));
- TEST_EQUAL(latestLocalFile->GetVersion(), localFileV2->GetVersion(), ());
- TEST_EQUAL(TStatus::EOnDiskOutOfDate, storage.CountryStatusEx(index), ());
-
- storage.DeleteCountry(index, TMapOptions::EMap);
-
- localFileV1->SyncWithDisk();
- TEST_EQUAL(TMapOptions::ENothing, localFileV1->GetFiles(), ());
-
- localFileV2->SyncWithDisk();
- TEST_EQUAL(TMapOptions::ENothing, localFileV2->GetFiles(), ());
-
- TEST_EQUAL(TStatus::ENotDownloaded, storage.CountryStatusEx(index), ());
-}
+} // namespace
-UNIT_TEST(StorageTest_DownloadCountryAndDeleteRoutingOnly)
+UNIT_TEST(StorageTest_Smoke)
{
- Storage storage;
- TaskRunner runner;
- InitStorage(storage, runner);
-
- TIndex const index = storage.FindIndexByFile("Azerbaijan");
- TEST(index.IsValid(), ());
- storage.DeleteCountry(index, TMapOptions::EMapWithCarRouting);
-
- {
- unique_ptr<CountryDownloaderChecker> checker =
- AbsentCountryDownloaderChecker(storage, index, TMapOptions::EMapWithCarRouting);
- checker->StartDownload();
- runner.Run();
- }
+ Storage st;
- // Delete routing file only and check that latest local file wasn't changed.
- shared_ptr<LocalCountryFile> localFileA = storage.GetLatestLocalFile(index);
- TEST(localFileA.get(), ());
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, localFileA->GetFiles(), ());
+ TIndex const i1 = st.FindIndexByFile("USA_Georgia");
+ TEST(i1.IsValid(), ());
+ TEST_EQUAL(st.CountryFileName(i1, TMapOptions::EMap), "USA_Georgia" DATA_FILE_EXTENSION, ());
- storage.DeleteCountry(index, TMapOptions::ECarRouting);
-
- shared_ptr<LocalCountryFile> localFileB = storage.GetLatestLocalFile(index);
- TEST(localFileB.get(), ());
- TEST_EQUAL(localFileA.get(), localFileB.get(), (*localFileA, *localFileB));
- TEST_EQUAL(TMapOptions::EMap, localFileB->GetFiles(), ());
+ TIndex const i2 = st.FindIndexByFile("Georgia");
+ TEST(i2.IsValid(), ());
+ TEST_EQUAL(st.CountryFileName(i2, TMapOptions::ECarRouting),
+ "Georgia" DATA_FILE_EXTENSION ROUTING_FILE_EXTENSION, ());
- storage.DeleteCountry(index, TMapOptions::EMap);
- shared_ptr<LocalCountryFile> localFileC = storage.GetLatestLocalFile(index);
- TEST(!localFileC.get(), (*localFileC));
+ TEST_NOT_EQUAL(i1, i2, ());
}
-UNIT_TEST(StorageTest_DownloadMapAndRoutingSeparately)
+UNIT_TEST(StorageTest_SingleCountryDownloading)
{
- Storage storage;
- TaskRunner runner;
- InitStorage(storage, runner);
-
- TIndex const index = storage.FindIndexByFile("Azerbaijan");
- TEST(index.IsValid(), ());
- storage.DeleteCountry(index, TMapOptions::EMapWithCarRouting);
+ string const azerbaijanFileName = "Azerbaijan";
+ CleanupCountryFiles(azerbaijanFileName);
- // Download map file only.
- {
- unique_ptr<CountryDownloaderChecker> checker =
- AbsentCountryDownloaderChecker(storage, index, TMapOptions::EMap);
- checker->StartDownload();
- runner.Run();
- }
-
- shared_ptr<LocalCountryFile> localFileA = storage.GetLatestLocalFile(index);
- TEST(localFileA.get(), ());
- TEST_EQUAL(TMapOptions::EMap, localFileA->GetFiles(), ());
-
- // Download routing file in addition to exising map file.
- {
- unique_ptr<CountryDownloaderChecker> checker =
- PresentCountryDownloaderChecker(storage, index, TMapOptions::ECarRouting);
- checker->StartDownload();
- runner.Run();
- }
+ Storage storage;
+ storage.Init(&OnCountryDownloaded);
- shared_ptr<LocalCountryFile> localFileB = storage.GetLatestLocalFile(index);
- TEST(localFileB.get(), ());
- TEST_EQUAL(localFileA.get(), localFileB.get(), (*localFileA, *localFileB));
- TEST_EQUAL(TMapOptions::EMapWithCarRouting, localFileB->GetFiles(), ());
+ TaskRunner taskRunner;
+ storage.SetDownloaderForTesting(make_unique<FakeMapFilesDownloader>(taskRunner));
- // Delete routing file and check status update.
{
- CountryStatusChecker checker(storage, index, TStatus::EOnDisk);
- storage.DeleteCountry(index, TMapOptions::ECarRouting);
+ MY_SCOPE_GUARD(cleanupCountryFiles, bind(&CleanupCountryFiles, azerbaijanFileName));
+ AbsentCountryDownloaderChecker checker(storage, azerbaijanFileName, TMapOptions::EMap);
+ checker.StartDownload();
+ taskRunner.Run();
}
- shared_ptr<LocalCountryFile> localFileC = storage.GetLatestLocalFile(index);
- TEST(localFileC.get(), ());
- TEST_EQUAL(localFileB.get(), localFileC.get(), (*localFileB, *localFileC));
- TEST_EQUAL(TMapOptions::EMap, localFileC->GetFiles(), ());
- // Delete map file and check status update.
{
- CountryStatusChecker checker(storage, index, TStatus::ENotDownloaded);
- storage.DeleteCountry(index, TMapOptions::EMap);
+ MY_SCOPE_GUARD(cleanupCountryFiles, bind(&CleanupCountryFiles, azerbaijanFileName));
+ AbsentCountryDownloaderChecker checker(storage, azerbaijanFileName,
+ TMapOptions::EMapWithCarRouting);
+ checker.StartDownload();
+ taskRunner.Run();
}
}
-UNIT_TEST(StorageTest_DeletePendingCountry)
+UNIT_TEST(StorageTest_TwoCountriesDownloading)
{
- Storage storage;
- TaskRunner runner;
- InitStorage(storage, runner);
-
- TIndex const index = storage.FindIndexByFile("Azerbaijan");
- TEST(index.IsValid(), ());
- storage.DeleteCountry(index, TMapOptions::EMapWithCarRouting);
+ string const uruguayFileName = "Uruguay";
+ string const venezuelaFileName = "Venezuela";
+ CleanupCountryFiles(uruguayFileName);
+ MY_SCOPE_GUARD(cleanupUruguayFiles, bind(&CleanupCountryFiles, uruguayFileName));
- {
- unique_ptr<CountryDownloaderChecker> checker =
- CancelledCountryDownloaderChecker(storage, index, TMapOptions::EMap);
- checker->StartDownload();
- storage.DeleteCountry(index, TMapOptions::EMapWithCarRouting);
- runner.Run();
- }
-}
+ CleanupCountryFiles(venezuelaFileName);
+ MY_SCOPE_GUARD(cleanupVenezuelaFiles, bind(&CleanupCountryFiles, venezuelaFileName));
-UNIT_TEST(StorageTest_DownloadTwoCountriesAndDelete)
-{
Storage storage;
- TaskRunner runner;
- InitStorage(storage, runner);
-
- TIndex const uruguayIndex = storage.FindIndexByFile("Uruguay");
- TEST(uruguayIndex.IsValid(), ());
- storage.DeleteCountry(uruguayIndex, TMapOptions::EMapWithCarRouting);
- MY_SCOPE_GUARD(cleanupUruguayFiles, bind(&Storage::DeleteCountry, &storage, uruguayIndex,
- TMapOptions::EMapWithCarRouting));
-
- TIndex const venezuelaIndex = storage.FindIndexByFile("Venezuela");
- TEST(venezuelaIndex.IsValid(), ());
- storage.DeleteCountry(venezuelaIndex, TMapOptions::EMapWithCarRouting);
- MY_SCOPE_GUARD(cleanupVenezuelaFiles, bind(&Storage::DeleteCountry, &storage, venezuelaIndex,
- TMapOptions::EMapWithCarRouting));
+ storage.Init(&OnCountryDownloaded);
- {
- // Map file will be deleted for Uruguay, thus, routing file should also be deleted. Therefore,
- // Uruguay should pass through following states: NotDownloaded -> Downloading -> NotDownloaded.
- unique_ptr<CountryDownloaderChecker> uruguayChecker = make_unique<CountryDownloaderChecker>(
- storage, uruguayIndex, TMapOptions::EMapWithCarRouting,
- vector<TStatus>{TStatus::ENotDownloaded, TStatus::EDownloading, TStatus::ENotDownloaded});
- // Only routing file will be deleted for Venezuela, thus, Venezuela should pass through
- // following
- // states:
- // NotDownloaded -> InQueue (Venezuela is added after Uruguay) -> Downloading -> Downloading
- // (second notification will be sent after deletion of a routing file) -> OnDisk.
- unique_ptr<CountryDownloaderChecker> venezuelaChecker = make_unique<CountryDownloaderChecker>(
- storage, venezuelaIndex, TMapOptions::EMapWithCarRouting,
- vector<TStatus>{TStatus::ENotDownloaded, TStatus::EInQueue, TStatus::EDownloading,
- TStatus::EDownloading, TStatus::EOnDisk});
- uruguayChecker->StartDownload();
- venezuelaChecker->StartDownload();
- storage.DeleteCountry(uruguayIndex, TMapOptions::EMap);
- storage.DeleteCountry(venezuelaIndex, TMapOptions::ECarRouting);
- runner.Run();
- }
- shared_ptr<LocalCountryFile> uruguayFile = storage.GetLatestLocalFile(uruguayIndex);
- TEST(!uruguayFile.get(), (*uruguayFile));
+ TaskRunner taskRunner;
+ storage.SetDownloaderForTesting(make_unique<FakeMapFilesDownloader>(taskRunner));
- shared_ptr<LocalCountryFile> venezuelaFile = storage.GetLatestLocalFile(venezuelaIndex);
- TEST(venezuelaFile.get(), ());
- TEST_EQUAL(TMapOptions::EMap, venezuelaFile->GetFiles(), ());
+ AbsentCountryDownloaderChecker uruguayChecker(storage, uruguayFileName, TMapOptions::EMap);
+ QueuedCountryDownloaderChecker venezuelaChecker(storage, venezuelaFileName,
+ TMapOptions::EMapWithCarRouting);
+ uruguayChecker.StartDownload();
+ venezuelaChecker.StartDownload();
+ taskRunner.Run();
}
diff --git a/storage/storage_tests/storage_tests.pro b/storage/storage_tests/storage_tests.pro
index 1f59397d0d..86879502d5 100644
--- a/storage/storage_tests/storage_tests.pro
+++ b/storage/storage_tests/storage_tests.pro
@@ -21,11 +21,11 @@ HEADERS += \
fake_map_files_downloader.hpp \
task_runner.hpp \
+
SOURCES += \
../../testing/testingmain.cpp \
country_info_test.cpp \
fake_map_files_downloader.cpp \
- queued_country_tests.cpp \
simple_tree_test.cpp \
storage_tests.cpp \
task_runner.cpp \