Merge pull request #466 from ygorshenin/fix-indexes-removal

[platform, storage] Implemented cleanup of absent countries indexes.
This commit is contained in:
mpimenov 2015-11-10 12:01:57 +03:00
commit 80befbcb60
16 changed files with 254 additions and 138 deletions

View file

@ -16,7 +16,8 @@ UNIT_TEST(CheckMWM_LoadAll)
{
Platform & platform = GetPlatform();
vector<platform::LocalCountryFile> localFiles;
platform::FindAllLocalMapsInDirectory(platform.WritableDir(), 0 /* version */, localFiles);
platform::FindAllLocalMapsInDirectoryAndCleanup(platform.WritableDir(), 0 /* version */,
-1 /* latestVersion */, localFiles);
model::FeaturesFetcher m;
m.InitClassificator();

View file

@ -477,7 +477,6 @@ void Framework::RegisterAllMaps()
("Registering maps while map downloading leads to removing downloading maps from "
"ActiveMapsListener::m_items."));
platform::CleanupMapsDirectory(m_storage.GetCurrentDataVersion());
m_storage.RegisterAllLocalMaps();
int minFormat = numeric_limits<int>::max();

View file

@ -81,7 +81,8 @@ public:
private:
friend string DebugPrint(LocalCountryFile const &);
friend void UnitTest_LocalCountryFile_DirectoryLookup();
friend void FindAllLocalMaps(vector<LocalCountryFile> & localFiles);
friend void FindAllLocalMapsAndCleanup(int64_t latestVersion,
vector<LocalCountryFile> & 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.

View file

@ -1,6 +1,8 @@
#include "local_country_file_utils.hpp"
#include "mwm_version.hpp"
#include "platform.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/country_file.hpp"
#include "platform/mwm_version.hpp"
#include "platform/platform.hpp"
#include "coding/file_name_utils.hpp"
#include "coding/internal/file_data.hpp"
@ -15,6 +17,7 @@
#include "std/cctype.hpp"
#include "std/sstream.hpp"
#include "std/unique_ptr.hpp"
#include "std/unordered_set.hpp"
#include "defines.hpp"
@ -74,13 +77,44 @@ string GetSpecialFilesSearchScope()
#endif // defined(OMIM_OS_ANDROID)
}
void DeleteDownloaderFilesForAllCountries(string const & directory)
class StringsRegexpFilter
{
static string const regexp = "\\.(downloading|resume|ready)[0-9]?$";
Platform::FilesList files;
Platform::GetFilesByRegExp(directory, regexp, files);
for (auto const & file : files)
my::DeleteFileX(my::JoinFoldersToPath(directory, file));
public:
StringsRegexpFilter(string const & regexp) { regexp::Create(regexp, m_regexp); }
bool Matches(string const & s) const { return regexp::Matches(s, m_regexp); }
private:
regexp::RegExpT m_regexp;
};
bool IsSpecialName(string const & name) { return name == "." || name == ".."; }
bool IsDownloaderFile(string const & name)
{
static StringsRegexpFilter const filter(".*\\.(downloading|resume|ready)[0-9]?$");
return filter.Matches(name);
}
bool DirectoryHasIndexesOnly(string const & directory)
{
Platform::TFilesWithType fwts;
Platform::GetFilesByType(directory, Platform::FILE_TYPE_REGULAR | Platform::FILE_TYPE_DIRECTORY,
fwts);
for (auto const & fwt : fwts)
{
auto const & name = fwt.first;
auto const & type = fwt.second;
if (type == Platform::FILE_TYPE_DIRECTORY)
{
if (!IsSpecialName(name))
return false;
continue;
}
if (!CountryIndexes::IsIndexFile(name))
return false;
}
return true;
}
} // namespace
@ -96,93 +130,93 @@ void DeleteDownloaderFilesForCountry(CountryFile const & countryFile, int64_t ve
}
}
void CleanupMapsDirectory(int64_t latestVersion)
{
Platform & platform = GetPlatform();
string const mapsDir = platform.WritableDir();
{
// Delete Brazil.mwm and Japan.mwm maps, because they was replaces with
// smaler regions after osrm routing implementation.
vector<LocalCountryFile> localFiles;
FindAllLocalMapsInDirectory(mapsDir, 0 /* version */, localFiles);
for (LocalCountryFile & localFile : localFiles)
{
string const & countryName = localFile.GetCountryFile().GetNameWithoutExt();
if (countryName == "Japan" || countryName == "Brazil")
{
localFile.SyncWithDisk();
localFile.DeleteFromDisk(MapOptions::MapWithCarRouting);
}
}
}
// Try to delete empty folders.
Platform::FilesList subdirs;
platform.GetFilesByType(mapsDir, Platform::FILE_TYPE_DIRECTORY, subdirs);
for (string const & subdir : subdirs)
{
// No need to visit parent directory.
if (subdir == "..")
continue;
int64_t version = 0;
if (subdir != "." && !ParseVersion(subdir, version))
continue;
string const subdirPath = my::JoinFoldersToPath(mapsDir, subdir);
// It's OK to remove all temprorary files for maps older than app.
if (version != latestVersion)
DeleteDownloaderFilesForAllCountries(subdirPath);
// Remove subdirectory if it does not contain any files except "." and "..".
if (subdir != "." && Platform::IsDirectoryEmpty(subdirPath))
{
Platform::EError const ret = Platform::RmDir(subdirPath);
ASSERT_EQUAL(Platform::ERR_OK, ret,
("Can't remove empty directory:", subdirPath, "error:", ret));
UNUSED_VALUE(ret);
}
}
/// @todo Cleanup temporary index files for already absent mwm files.
/// https://trello.com/c/PKiiOsB4/28--
}
void FindAllLocalMapsInDirectory(string const & directory, int64_t version,
vector<LocalCountryFile> & localFiles)
void FindAllLocalMapsInDirectoryAndCleanup(string const & directory, int64_t version,
int64_t latestVersion,
vector<LocalCountryFile> & localFiles)
{
vector<string> files;
Platform & platform = GetPlatform();
platform.GetFilesByRegExp(directory, ".*\\" DATA_FILE_EXTENSION "$", files);
for (string const & file : files)
Platform::TFilesWithType fwts;
platform.GetFilesByType(directory, Platform::FILE_TYPE_REGULAR | Platform::FILE_TYPE_DIRECTORY,
fwts);
unordered_set<string> names;
for (auto const & fwt : fwts)
{
if (fwt.second != Platform::FILE_TYPE_REGULAR)
continue;
string name = fwt.first;
// Remove downloader files for old version directories.
if (IsDownloaderFile(name) && version < latestVersion)
{
my::DeleteFileX(my::JoinFoldersToPath(directory, name));
continue;
}
if (!strings::EndsWith(name, DATA_FILE_EXTENSION))
continue;
// Remove DATA_FILE_EXTENSION and use base name as a country file name.
string name = file;
my::GetNameWithoutExt(name);
localFiles.emplace_back(directory, CountryFile(name), version);
names.insert(name);
LocalCountryFile localFile(directory, CountryFile(name), version);
// Delete Brazil.mwm and Japan.mwm maps, because they were
// replaced with smaller regions after osrm routing
// implementation.
if (name == "Japan" || name == "Brazil")
{
localFile.SyncWithDisk();
localFile.DeleteFromDisk(MapOptions::MapWithCarRouting);
continue;
}
localFiles.push_back(localFile);
}
for (auto const & fwt : fwts)
{
if (fwt.second != Platform::FILE_TYPE_DIRECTORY)
continue;
string name = fwt.first;
if (IsSpecialName(name))
continue;
if (names.count(name) == 0 && DirectoryHasIndexesOnly(my::JoinFoldersToPath(directory, name)))
{
// Directory which looks like a directory with indexes for absent country. It's OK to remove
// it.
LocalCountryFile absentCountry(directory, CountryFile(name), version);
CountryIndexes::DeleteFromDisk(absentCountry);
}
}
}
void FindAllLocalMaps(vector<LocalCountryFile> & localFiles)
void FindAllLocalMapsAndCleanup(int64_t latestVersion, vector<LocalCountryFile> & localFiles)
{
localFiles.clear();
Platform & platform = GetPlatform();
string const directory = platform.WritableDir();
FindAllLocalMapsInDirectory(directory, 0 /* version */, localFiles);
string const dir = platform.WritableDir();
FindAllLocalMapsInDirectoryAndCleanup(dir, 0 /* version */, latestVersion, localFiles);
Platform::FilesList subdirs;
Platform::GetFilesByType(directory, Platform::FILE_TYPE_DIRECTORY, subdirs);
for (string const & subdir : subdirs)
Platform::TFilesWithType fwts;
Platform::GetFilesByType(dir, Platform::FILE_TYPE_DIRECTORY, fwts);
for (auto const & fwt : fwts)
{
string const & subdir = fwt.first;
int64_t version;
if (ParseVersion(subdir, version))
FindAllLocalMapsInDirectory(my::JoinFoldersToPath(directory, subdir), version, localFiles);
if (!ParseVersion(subdir, version))
continue;
string const fullPath = my::JoinFoldersToPath(dir, subdir);
FindAllLocalMapsInDirectoryAndCleanup(fullPath, version, latestVersion, localFiles);
Platform::EError err = Platform::RmDir(fullPath);
if (err != Platform::ERR_OK && err != Platform::ERR_DIRECTORY_NOT_EMPTY)
LOG(LWARNING, ("Can't remove directory:", fullPath, err));
}
// World and WorldCoasts can be stored in app bundle or in resources
@ -198,10 +232,12 @@ void FindAllLocalMaps(vector<LocalCountryFile> & localFiles)
try
{
ModelReaderPtr reader(platform.GetReader(file + DATA_FILE_EXTENSION, GetSpecialFilesSearchScope()));
ModelReaderPtr reader(
platform.GetReader(file + DATA_FILE_EXTENSION, GetSpecialFilesSearchScope()));
// Assume that empty path means the resource file.
LocalCountryFile worldFile(string(), CountryFile(file), version::ReadVersionTimestamp(reader));
LocalCountryFile worldFile(string(), CountryFile(file),
version::ReadVersionTimestamp(reader));
worldFile.m_files = MapOptions::Map;
if (i != localFiles.end())
{
@ -222,6 +258,12 @@ void FindAllLocalMaps(vector<LocalCountryFile> & localFiles)
}
}
void CleanupMapsDirectory(int64_t latestVersion)
{
vector<LocalCountryFile> localFiles;
FindAllLocalMapsAndCleanup(latestVersion, localFiles);
}
bool ParseVersion(string const & s, int64_t & version)
{
if (s.empty() || s.size() > kMaxTimestampLength)
@ -265,7 +307,10 @@ ModelReader * GetCountryReader(platform::LocalCountryFile const & file, MapOptio
Platform & platform = GetPlatform();
// See LocalCountryFile comment for explanation.
if (file.GetDirectory().empty())
return platform.GetReader(file.GetCountryName() + DATA_FILE_EXTENSION, GetSpecialFilesSearchScope());
{
return platform.GetReader(file.GetCountryName() + DATA_FILE_EXTENSION,
GetSpecialFilesSearchScope());
}
return platform.GetReader(file.GetPath(options), "f");
}
@ -329,6 +374,13 @@ void CountryIndexes::GetIndexesExts(vector<string> & exts)
exts.push_back(kOffsetsExt);
}
// static
bool CountryIndexes::IsIndexFile(string const & file)
{
return strings::EndsWith(file, kBitsExt) || strings::EndsWith(file, kNodesExt) ||
strings::EndsWith(file, kOffsetsExt);
}
// static
string CountryIndexes::IndexesDir(LocalCountryFile const & localFile)
{

View file

@ -3,6 +3,7 @@
#include "platform/country_defines.hpp"
#include "platform/local_country_file.hpp"
#include "std/function.hpp"
#include "std/shared_ptr.hpp"
#include "std/utility.hpp"
#include "std/vector.hpp"
@ -14,20 +15,16 @@ namespace platform
// Removes all files downloader creates during downloading of a country.
void DeleteDownloaderFilesForCountry(CountryFile const & countryFile, int64_t version);
// Removes partially downloaded maps, empty directories and old
// (format v1) maps. Also, removes old (splitted) Japan and Brazil
// maps. |version| must be set to the latest data version this app can
// work with.
void CleanupMapsDirectory(int64_t latestVersion);
// Finds all local map files in |directory|. Version of these files is
// passed as an argument. Also, performs cleanup described in comment
// for FindAllLocalMapsAndCleanup().
void FindAllLocalMapsInDirectoryAndCleanup(string const & directory, int64_t version,
int64_t latestVersion,
vector<LocalCountryFile> & localFiles);
// Finds all local map files in a directory. Version of these files is
// passed as an argument.
void FindAllLocalMapsInDirectory(string const & directory, int64_t version,
vector<LocalCountryFile> & localFiles);
// Finds all local map files in resources and writable
// directory. Also, for Android, checks /Android/obb directory.
// Directories should have the following structure:
// Finds all local map files in resources and writable directory. For
// Android, checks /Android/obb directory. Subdirectories in the
// writable directory should have the following structure:
//
// dir/*.mwm -- map files, base name should correspond to countries.txt,
// -- version is assumed to be zero (unknown).
@ -38,10 +35,17 @@ void FindAllLocalMapsInDirectory(string const & directory, int64_t version,
// dir/[0-9]{1,18}/*.mwm.routing -- routing file for corresponding map files,
// -- version is assumed to be the name of a directory.
//
// We can't derive version of a map file from its header because
// currently header stores format version + individual mwm's file
// generation timestamp, not timestamp mentioned in countries.txt.
void FindAllLocalMaps(vector<LocalCountryFile> & localFiles);
// Also, this method performs cleanup described in a comment for
// CleanupMapsDirectory().
void FindAllLocalMapsAndCleanup(int64_t latestVersion, vector<LocalCountryFile> & localFiles);
// This method removes:
// * partially downloaded non-latest maps (with version less than |latestVersion|)
// * empty directories
// * old (format v1) maps
// * old (split) Japan and Brazil maps
// * indexes for absent countries
void CleanupMapsDirectory(int64_t latestVersion);
// Tries to parse a version from a string of size not longer than 18
// symbols and representing an unsigned decimal number. Leading zeroes
@ -84,6 +88,9 @@ public:
// Pushes to the exts's end possible index files extensions.
static void GetIndexesExts(vector<string> & exts);
// Returns true if |file| corresponds to an index file.
static bool IsIndexFile(string const & file);
private:
friend void UnitTest_LocalCountryFile_CountryIndexes();
friend void UnitTest_LocalCountryFile_DoNotDeleteUserFiles();

View file

@ -120,7 +120,8 @@ void Platform::GetFilesByExt(string const & directory, string const & ext, Files
}
// static
void Platform::GetFilesByType(string const & directory, unsigned typeMask, FilesList & outFiles)
void Platform::GetFilesByType(string const & directory, unsigned typeMask,
TFilesWithType & outFiles)
{
FilesList allFiles;
GetFilesByRegExp(directory, ".*", allFiles);
@ -130,7 +131,7 @@ void Platform::GetFilesByType(string const & directory, unsigned typeMask, Files
if (GetFileType(my::JoinFoldersToPath(directory, file), type) != ERR_OK)
continue;
if (typeMask & type)
outFiles.push_back(file);
outFiles.emplace_back(file, type);
}
}

View file

@ -49,6 +49,8 @@ public:
CONNECTION_WWAN
};
using TFilesWithType = vector<pair<string, EFileType>>;
protected:
/// Usually read-only directory for application resources
string m_resourcesDir;
@ -138,7 +140,8 @@ public:
static void GetFilesByRegExp(string const & directory, string const & regexp, FilesList & outFiles);
//@}
static void GetFilesByType(string const & directory, unsigned typeMask, FilesList & outFiles);
static void GetFilesByType(string const & directory, unsigned typeMask,
TFilesWithType & outFiles);
static bool IsDirectoryEmpty(string const & directory);

View file

@ -137,6 +137,13 @@ UNIT_TEST(LocalCountryFile_CleanupMapFiles)
Platform & platform = GetPlatform();
string const mapsDir = platform.WritableDir();
// Two fake directories for test country files and indexes.
ScopedDir dir3("3");
ScopedDir dir4("4");
ScopedDir absentCountryIndexesDir(dir4, "Absent");
ScopedDir irelandIndexesDir(dir4, "Ireland");
CountryFile japanFile("Japan");
CountryFile brazilFile("Brazil");
CountryFile irelandFile("Ireland");
@ -147,27 +154,19 @@ UNIT_TEST(LocalCountryFile_CleanupMapFiles)
LocalCountryFile brazilLocalFile(mapsDir, brazilFile, 0 /* version */);
ScopedFile brazilMapFile("Brazil.mwm", "Brazil");
LocalCountryFile irelandLocalFile(mapsDir, irelandFile, 0 /* version */);
ScopedFile irelandMapFile("Ireland.mwm", "Ireland");
LocalCountryFile irelandLocalFile(dir4.GetFullPath(), irelandFile, 4 /* version */);
ScopedFile irelandMapFile(dir4, irelandFile, MapOptions::Map, "Ireland");
ScopedDir emptyDir("3");
// Check that FindAllLocalMaps()
// Check FindAllLocalMaps()
vector<LocalCountryFile> localFiles;
FindAllLocalMaps(localFiles);
TEST(Contains(localFiles, japanLocalFile), (japanLocalFile, localFiles));
TEST(Contains(localFiles, brazilLocalFile), (brazilLocalFile, localFiles));
FindAllLocalMapsAndCleanup(-1 /* latestVersion */, localFiles);
TEST(!Contains(localFiles, japanLocalFile), (japanLocalFile, localFiles));
TEST(!Contains(localFiles, brazilLocalFile), (brazilLocalFile, localFiles));
TEST(Contains(localFiles, irelandLocalFile), (irelandLocalFile, localFiles));
CleanupMapsDirectory(0 /* latestVersion */);
japanLocalFile.SyncWithDisk();
TEST_EQUAL(MapOptions::Nothing, japanLocalFile.GetFiles(), ());
TEST(!japanMapFile.Exists(), (japanMapFile));
japanMapFile.Reset();
brazilLocalFile.SyncWithDisk();
TEST_EQUAL(MapOptions::Nothing, brazilLocalFile.GetFiles(), ());
TEST(!brazilMapFile.Exists(), (brazilMapFile));
brazilMapFile.Reset();
@ -177,8 +176,15 @@ UNIT_TEST(LocalCountryFile_CleanupMapFiles)
TEST(!irelandMapFile.Exists(), (irelandMapFile));
irelandMapFile.Reset();
TEST(!emptyDir.Exists(), ("Empty directory", emptyDir, "wasn't removed."));
emptyDir.Reset();
TEST(!dir3.Exists(), ("Empty directory", dir3, "wasn't removed."));
dir3.Reset();
TEST(dir4.Exists(), ());
TEST(!absentCountryIndexesDir.Exists(), ("Indexes for absent country weren't deleted."));
absentCountryIndexesDir.Reset();
TEST(irelandIndexesDir.Exists(), ());
}
UNIT_TEST(LocalCountryFile_CleanupPartiallyDownloadedFiles)
@ -235,7 +241,8 @@ UNIT_TEST(LocalCountryFile_DirectoryLookup)
"Netherlands-routing");
vector<LocalCountryFile> localFiles;
FindAllLocalMapsInDirectory(testDir.GetFullPath(), 150309, localFiles);
FindAllLocalMapsInDirectoryAndCleanup(testDir.GetFullPath(), 150309 /* version */,
-1 /* latestVersion */, localFiles);
sort(localFiles.begin(), localFiles.end());
for (LocalCountryFile & localFile : localFiles)
localFile.SyncWithDisk();
@ -259,11 +266,11 @@ UNIT_TEST(LocalCountryFile_AllLocalFilesLookup)
{
CountryFile const italyFile("Italy");
ScopedDir testDir("010101");
ScopedDir testDir("10101");
ScopedFile testItalyMapFile(testDir, italyFile, MapOptions::Map, "Italy-map");
vector<LocalCountryFile> localFiles;
FindAllLocalMaps(localFiles);
FindAllLocalMapsAndCleanup(-1 /* latestVersion */, localFiles);
multiset<LocalCountryFile> localFilesSet(localFiles.begin(), localFiles.end());
bool worldFound = false;

View file

@ -22,9 +22,13 @@ char const * TEST_FILE_NAME = "some_temporary_unit_test_file.tmp";
void CheckFilesPresence(string const & baseDir, unsigned typeMask,
initializer_list<pair<string, size_t>> const & files)
{
Platform::FilesList filesList;
Platform::GetFilesByType(baseDir, typeMask, filesList);
multiset<string> filesSet(filesList.begin(), filesList.end());
Platform::TFilesWithType fwts;
Platform::GetFilesByType(baseDir, typeMask, fwts);
multiset<string> filesSet;
for (auto const & fwt : fwts)
filesSet.insert(fwt.first);
for (auto const & file : files)
TEST_EQUAL(filesSet.count(file.first), file.second, (file.first, file.second));
}

View file

@ -34,6 +34,11 @@ ScopedDir::ScopedDir(string const & relativePath)
}
}
ScopedDir::ScopedDir(ScopedDir const & parent, string const & name)
: ScopedDir(my::JoinFoldersToPath(parent.GetRelativePath(), name))
{
}
ScopedDir::~ScopedDir()
{
if (m_reset)

View file

@ -18,6 +18,8 @@ public:
/// @param path Path for a testing directory, should be relative to writable-dir.
ScopedDir(string const & relativePath);
ScopedDir(ScopedDir const & parent, string const & name);
~ScopedDir();
inline void Reset() { m_reset = true; }

View file

@ -18,7 +18,7 @@ UNIT_TEST(CheckCrossSections)
{
static double constexpr kPointEquality = 0.01;
vector<platform::LocalCountryFile> localFiles;
platform::FindAllLocalMaps(localFiles);
platform::FindAllLocalMapsAndCleanup(-1 /* latestVersion */, localFiles);
size_t ingoingErrors = 0;
size_t outgoingErrors = 0;

View file

@ -159,7 +159,7 @@ namespace integration
pl.SetResourceDir(options.m_resourcePath);
vector<LocalCountryFile> localFiles;
platform::FindAllLocalMaps(localFiles);
platform::FindAllLocalMapsAndCleanup(-1, localFiles);
for (auto & file : localFiles)
file.SyncWithDisk();
ASSERT(!localFiles.empty(), ());

View file

@ -66,6 +66,12 @@ void DeleteCountryIndexes(LocalCountryFile const & localFile)
platform::CountryIndexes::DeleteFromDisk(localFile);
}
void DeleteFromDiskWithIndexes(LocalCountryFile const & localFile, MapOptions options)
{
DeleteCountryIndexes(localFile);
localFile.DeleteFromDisk(options);
}
class EqualFileName
{
string const & m_name;
@ -105,7 +111,7 @@ void Storage::RegisterAllLocalMaps()
m_localFilesForFakeCountries.clear();
vector<LocalCountryFile> localFiles;
FindAllLocalMaps(localFiles);
FindAllLocalMapsAndCleanup(GetCurrentDataVersion(), localFiles);
auto compareByCountryAndVersion = [](LocalCountryFile const & lhs, LocalCountryFile const & rhs)
{
@ -130,7 +136,7 @@ void Storage::RegisterAllLocalMaps()
LocalCountryFile & localFile = *j;
LOG(LINFO, ("Removing obsolete", localFile));
localFile.SyncWithDisk();
localFile.DeleteFromDisk(MapOptions::MapWithCarRouting);
DeleteFromDiskWithIndexes(localFile, MapOptions::MapWithCarRouting);
++j;
}
@ -340,8 +346,7 @@ void Storage::DeleteCountry(TIndex const & index, MapOptions opt)
void Storage::DeleteCustomCountryVersion(LocalCountryFile const & localFile)
{
CountryFile const countryFile = localFile.GetCountryFile();
localFile.DeleteFromDisk(MapOptions::MapWithCarRouting);
CountryIndexes::DeleteFromDisk(localFile);
DeleteFromDiskWithIndexes(localFile, MapOptions::MapWithCarRouting);
{
auto it = m_localFilesForFakeCountries.find(countryFile);
@ -844,9 +849,8 @@ void Storage::DeleteCountryFiles(TIndex const & index, MapOptions opt)
auto & localFiles = it->second;
for (auto & localFile : localFiles)
{
localFile->DeleteFromDisk(opt);
DeleteFromDiskWithIndexes(*localFile, opt);
localFile->SyncWithDisk();
DeleteCountryIndexes(*localFile);
if (localFile->GetFiles() == MapOptions::Nothing)
localFile.reset();
}

View file

@ -6,6 +6,8 @@
#include "storage/queued_country.hpp"
#include "storage/storage_defines.hpp"
#include "platform/local_country_file.hpp"
#include "std/function.hpp"
#include "std/list.hpp"
#include "std/set.hpp"
@ -14,7 +16,6 @@
#include "std/unique_ptr.hpp"
#include "std/vector.hpp"
namespace storage
{
/// Can be used to store local maps and/or maps available for download
@ -48,7 +49,9 @@ private:
using TLocalFilePtr = shared_ptr<platform::LocalCountryFile>;
map<TIndex, list<TLocalFilePtr>> m_localFiles;
// Our World.mwm and WorldCoasts.mwm are fake countries, together with any custom mwm in data folder.
// Our World.mwm and WorldCoasts.mwm are fake countries, together with any custom mwm in data
// folder.
map<platform::CountryFile, TLocalFilePtr> m_localFilesForFakeCountries;
/// used to correctly calculate total country download progress with more than 1 file

View file

@ -12,6 +12,7 @@
#include "platform/local_country_file.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/platform_tests_support/scoped_dir.hpp"
#include "platform/platform_tests_support/scoped_file.hpp"
#include "coding/file_name_utils.hpp"
@ -732,4 +733,30 @@ UNIT_TEST(StorageTest_EmptyRoutingFile)
checker->StartDownload();
runner.Run();
}
UNIT_TEST(StorageTest_ObsoleteMapsRemoval)
{
CountryFile country("Azerbaijan");
tests_support::ScopedDir dir1("1");
tests_support::ScopedFile map1(dir1, country, MapOptions::Map, "map1");
LocalCountryFile file1(dir1.GetFullPath(), country, 1 /* version */);
CountryIndexes::PreparePlaceOnDisk(file1);
tests_support::ScopedDir dir2("2");
tests_support::ScopedFile map2(dir2, country, MapOptions::Map, "map2");
LocalCountryFile file2(dir2.GetFullPath(), country, 2 /* version */);
CountryIndexes::PreparePlaceOnDisk(file2);
TEST(map1.Exists(), ());
TEST(map2.Exists(), ());
Storage storage;
storage.RegisterAllLocalMaps();
TEST(!map1.Exists(), ());
map1.Reset();
TEST(map2.Exists(), ());
}
} // namespace storage