diff --git a/indexer/features_offsets_table.cpp b/indexer/features_offsets_table.cpp index fdd4f87481..f9fd17a59b 100644 --- a/indexer/features_offsets_table.cpp +++ b/indexer/features_offsets_table.cpp @@ -50,6 +50,7 @@ namespace feature return unique_ptr(new FeaturesOffsetsTable(elias_fano_builder)); } + // static unique_ptr FeaturesOffsetsTable::LoadImpl(string const & filePath) { return unique_ptr(new FeaturesOffsetsTable(filePath)); @@ -64,20 +65,14 @@ namespace feature } // static - unique_ptr FeaturesOffsetsTable::CreateIfNotExistsAndLoad( - LocalCountryFile const & localFile) + unique_ptr FeaturesOffsetsTable::CreateImpl( + platform::LocalCountryFile const & localFile, + FilesContainerR const & cont, string const & storePath) { - string const offsetsFilePath = CountryIndexes::GetPath(localFile, CountryIndexes::Index::Offsets); - - if (GetPlatform().IsFileExistsByFullPath(offsetsFilePath)) - return LoadImpl(offsetsFilePath); - - LOG(LINFO, ("Creating features offset table file", offsetsFilePath)); + LOG(LINFO, ("Creating features offset table file", storePath)); VERIFY(CountryIndexes::PreparePlaceOnDisk(localFile), ()); - FilesContainerR cont(localFile.GetPath(MapOptions::Map)); - Builder builder; FeaturesVector::ForEachOffset(cont.GetReader(DATA_FILE_TAG), [&builder] (uint32_t offset) { @@ -85,13 +80,38 @@ namespace feature }); unique_ptr table(Build(builder)); - table->Save(offsetsFilePath); + table->Save(storePath); return table; } + // static + unique_ptr FeaturesOffsetsTable::CreateIfNotExistsAndLoad( + LocalCountryFile const & localFile, FilesContainerR const & cont) + { + string const offsetsFilePath = CountryIndexes::GetPath(localFile, CountryIndexes::Index::Offsets); + + if (Platform::IsFileExistsByFullPath(offsetsFilePath)) + return LoadImpl(offsetsFilePath); + + return CreateImpl(localFile, cont, offsetsFilePath); + } + + // static + unique_ptr FeaturesOffsetsTable::CreateIfNotExistsAndLoad( + LocalCountryFile const & localFile) + { + string const offsetsFilePath = CountryIndexes::GetPath(localFile, CountryIndexes::Index::Offsets); + + if (Platform::IsFileExistsByFullPath(offsetsFilePath)) + return LoadImpl(offsetsFilePath); + + return CreateImpl(localFile, FilesContainerR(localFile.GetPath(MapOptions::Map)), offsetsFilePath); + } + + // static unique_ptr FeaturesOffsetsTable::CreateIfNotExistsAndLoad(FilesContainerR const & cont) { - return CreateIfNotExistsAndLoad((LocalCountryFile::MakeTemporary(cont.GetFileName()))); + return CreateIfNotExistsAndLoad(LocalCountryFile::MakeTemporary(cont.GetFileName()), cont); } void FeaturesOffsetsTable::Save(string const & filePath) diff --git a/indexer/features_offsets_table.hpp b/indexer/features_offsets_table.hpp index f962619949..b1b52f4ddb 100644 --- a/indexer/features_offsets_table.hpp +++ b/indexer/features_offsets_table.hpp @@ -54,32 +54,18 @@ namespace feature /// \return a pointer to an instance of FeaturesOffsetsTable static unique_ptr Build(Builder & builder); - /// Loads FeaturesOffsetsTable from FilesMappingContainer. Note - /// that some part of a file referenced by container will be - /// mapped to the memory and used by internal structures of - /// FeaturesOffsetsTable. - /// - /// \param filePath a full path of the file to load or store data - /// \return a pointer to an instance of FeaturesOffsetsTable or nullptr - /// when it's not possible to load FeaturesOffsetsTable. + /// Load table by full path to the table file. static unique_ptr Load(string const & filePath); - /// Loads FeaturesOffsetsTable from FilesMappingContainer. Note - /// that some part of a file referenced by container will be - /// mapped to the memory and used by internal structures of - /// FeaturesOffsetsTable. - /// If there is no FeaturesOffsetsTable section in the container, - /// the function builds it from section devoted to features. - /// - /// \warning May take a lot of time if there is no precomputed section - /// - /// \param localFile Representation of the map files with features data ( uses only if we need to construct them) - /// \return a pointer to an instance of FeaturesOffsetsTable or nullptr - /// when it's not possible to create FeaturesOffsetsTable. - static unique_ptr CreateIfNotExistsAndLoad(platform::LocalCountryFile const & localFile); + /// Get table for the MWM map, represented by localFile and cont. + static unique_ptr CreateIfNotExistsAndLoad( + platform::LocalCountryFile const & localFile, FilesContainerR const & cont); /// @todo The easiest solution for now. Need to be removed in future. + //@{ + static unique_ptr CreateIfNotExistsAndLoad(platform::LocalCountryFile const & localFile); static unique_ptr CreateIfNotExistsAndLoad(FilesContainerR const & cont); + //@} FeaturesOffsetsTable(FeaturesOffsetsTable const &) = delete; FeaturesOffsetsTable const & operator=(FeaturesOffsetsTable const &) = delete; @@ -110,6 +96,9 @@ namespace feature FeaturesOffsetsTable(string const & filePath); static unique_ptr LoadImpl(string const & filePath); + static unique_ptr CreateImpl(platform::LocalCountryFile const & localFile, + FilesContainerR const & cont, + string const & storePath); succinct::elias_fano m_table; diff --git a/indexer/index.cpp b/indexer/index.cpp index d08767e1c2..e384ab973b 100644 --- a/indexer/index.cpp +++ b/indexer/index.cpp @@ -16,7 +16,7 @@ using platform::LocalCountryFile; MwmValue::MwmValue(LocalCountryFile const & localFile) : m_cont(platform::GetCountryReader(localFile, MapOptions::Map)), - m_countryFile(localFile.GetCountryFile()), + m_file(localFile), m_table(0) { m_factory.Load(m_cont); @@ -28,7 +28,7 @@ void MwmValue::SetTable(MwmInfoEx & info) return; if (!info.m_table) - info.m_table = feature::FeaturesOffsetsTable::CreateIfNotExistsAndLoad(m_cont); + info.m_table = feature::FeaturesOffsetsTable::CreateIfNotExistsAndLoad(m_file, m_cont); m_table = info.m_table.get(); } diff --git a/indexer/index.hpp b/indexer/index.hpp index 611fd7e8da..d0eb1a4f6f 100644 --- a/indexer/index.hpp +++ b/indexer/index.hpp @@ -30,9 +30,9 @@ public: class MwmValue : public MwmSet::MwmValueBase { public: - FilesContainerR m_cont; + FilesContainerR const m_cont; IndexFactory m_factory; - platform::CountryFile const m_countryFile; + platform::LocalCountryFile const m_file; feature::FeaturesOffsetsTable const * m_table; explicit MwmValue(platform::LocalCountryFile const & localFile); @@ -41,7 +41,7 @@ public: 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; } + inline platform::CountryFile const & GetCountryFile() const { return m_file.GetCountryFile(); } }; class Index : public MwmSet diff --git a/platform/local_country_file.hpp b/platform/local_country_file.hpp index 9bf7939781..ecf448838f 100644 --- a/platform/local_country_file.hpp +++ b/platform/local_country_file.hpp @@ -83,9 +83,12 @@ private: friend void UnitTest_LocalCountryFile_DirectoryLookup(); friend void FindAllLocalMaps(vector & localFiles); + /// @note! If directory is empty, the file is stored in resources. + /// In this case, the only valid params are m_countryFile and m_version. string m_directory; CountryFile m_countryFile; int64_t m_version; + MapOptions m_files; uint64_t m_mapSize; diff --git a/platform/local_country_file_utils.cpp b/platform/local_country_file_utils.cpp index 90af416e25..192b976273 100644 --- a/platform/local_country_file_utils.cpp +++ b/platform/local_country_file_utils.cpp @@ -1,6 +1,6 @@ -#include "platform/local_country_file_utils.hpp" - -#include "platform/platform.hpp" +#include "local_country_file_utils.hpp" +#include "mwm_version.hpp" +#include "platform.hpp" #include "coding/file_name_utils.hpp" #include "coding/internal/file_data.hpp" @@ -14,6 +14,7 @@ #include "std/sstream.hpp" #include "std/unique_ptr.hpp" + namespace platform { namespace @@ -175,11 +176,10 @@ void FindAllLocalMaps(vector & localFiles) try { - unique_ptr guard(platform.GetReader(file + DATA_FILE_EXTENSION, GetSpecialFilesSearchScope())); - UNUSED_VALUE(guard); + ModelReaderPtr reader(platform.GetReader(file + DATA_FILE_EXTENSION, GetSpecialFilesSearchScope())); // Assume that empty path means the resource file. - LocalCountryFile worldFile(string(), CountryFile(file), 0 /* version */); + LocalCountryFile worldFile(string(), CountryFile(file), version::ReadVersionTimestamp(reader)); worldFile.m_files = MapOptions::Map; if (i != localFiles.end()) { @@ -296,8 +296,31 @@ void CountryIndexes::GetIndexesExts(vector & exts) // static string CountryIndexes::IndexesDir(LocalCountryFile const & localFile) { - return my::JoinFoldersToPath(localFile.GetDirectory(), - localFile.GetCountryFile().GetNameWithoutExt()); + string dir = localFile.GetDirectory(); + CountryFile const & file = localFile.GetCountryFile(); + + if (dir.empty()) + { + // Local file is stored in resources. Need to prepare index folder in the writable directory. + int64_t const version = localFile.GetVersion(); + ASSERT_GREATER(version, 0, ()); + Platform & pl = GetPlatform(); + + dir = my::JoinFoldersToPath(pl.WritableDir(), strings::to_string(version)); + switch (pl.MkDir(dir)) + { + case Platform::ERR_OK: + /// @todo Cleanup old World directories ... + break; + case Platform::ERR_FILE_ALREADY_EXISTS: + break; + default: + LOG(LERROR, ("Can't create indecies directory")); + return string(); + } + } + + return my::JoinFoldersToPath(dir, file.GetNameWithoutExt()); } string DebugPrint(CountryIndexes::Index index)