2018-11-28 11:37:12 +00:00
|
|
|
#include "RegionsNames.h"
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2018-12-10 15:25:45 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2017-01-21 04:24:28 +00:00
|
|
|
#include <Poco/Exception.h>
|
2018-12-10 15:25:45 +00:00
|
|
|
#include <Poco/Util/Application.h>
|
2017-01-21 04:24:28 +00:00
|
|
|
#include <common/logger_useful.h>
|
2018-12-10 15:25:45 +00:00
|
|
|
#include "GeodataProviders/INamesProvider.h"
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2018-11-22 21:19:58 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
2018-12-10 15:25:45 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int INCORRECT_DATA;
|
|
|
|
}
|
2018-11-22 21:19:58 +00:00
|
|
|
}
|
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
RegionsNames::RegionsNames(IRegionsNamesDataProviderPtr data_provider)
|
|
|
|
{
|
|
|
|
for (size_t language_id = 0; language_id < SUPPORTED_LANGUAGES_COUNT; ++language_id)
|
|
|
|
{
|
2019-11-11 20:54:57 +00:00
|
|
|
const std::string & language = supported_languages[language_id];
|
2017-11-28 22:15:06 +00:00
|
|
|
names_sources[language_id] = data_provider->getLanguageRegionsNamesSource(language);
|
|
|
|
}
|
2017-12-04 14:35:03 +00:00
|
|
|
|
|
|
|
reload();
|
2017-11-28 22:15:06 +00:00
|
|
|
}
|
2017-01-21 04:24:28 +00:00
|
|
|
|
|
|
|
std::string RegionsNames::dumpSupportedLanguagesNames()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
std::string res = "";
|
|
|
|
for (size_t i = 0; i < LANGUAGE_ALIASES_COUNT; ++i)
|
|
|
|
{
|
|
|
|
if (i > 0)
|
|
|
|
res += ", ";
|
|
|
|
res += '\'';
|
2019-11-11 20:54:57 +00:00
|
|
|
res += language_aliases[i].first;
|
2017-04-01 07:20:54 +00:00
|
|
|
res += '\'';
|
|
|
|
}
|
|
|
|
return res;
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
void RegionsNames::reload()
|
2017-01-21 04:24:28 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
Logger * log = &Logger::get("RegionsNames");
|
|
|
|
LOG_DEBUG(log, "Reloading regions names");
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
RegionID max_region_id = 0;
|
|
|
|
for (size_t language_id = 0; language_id < SUPPORTED_LANGUAGES_COUNT; ++language_id)
|
|
|
|
{
|
2019-11-11 20:54:57 +00:00
|
|
|
const std::string & language = supported_languages[language_id];
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
auto names_source = names_sources[language_id];
|
|
|
|
|
|
|
|
if (!names_source->isModified())
|
2017-04-01 07:20:54 +00:00
|
|
|
continue;
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
LOG_DEBUG(log, "Reloading regions names for language: " << language);
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
auto names_reader = names_source->createReader();
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
const size_t initial_size = 10000;
|
|
|
|
const size_t max_size = 15000000;
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
Chars new_chars;
|
|
|
|
StringRefs new_names_refs(initial_size, StringRef("", 0));
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/// Allocate a continuous slice of memory, which is enough to store all names.
|
2017-11-28 22:15:06 +00:00
|
|
|
new_chars.reserve(names_source->estimateTotalSize());
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
RegionNameEntry name_entry;
|
|
|
|
while (names_reader->readNext(name_entry))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
size_t old_size = new_chars.size();
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-12-06 13:03:02 +00:00
|
|
|
if (new_chars.capacity() < old_size + name_entry.name.length() + 1)
|
|
|
|
throw Poco::Exception("Logical error. Maybe size estimate of " + names_source->getSourceName() + " is wrong.");
|
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
new_chars.resize(old_size + name_entry.name.length() + 1);
|
2019-03-07 20:04:59 +00:00
|
|
|
memcpy(new_chars.data() + old_size, name_entry.name.c_str(), name_entry.name.length() + 1);
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
if (name_entry.id > max_region_id)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
2017-11-28 22:15:06 +00:00
|
|
|
max_region_id = name_entry.id;
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
if (name_entry.id > max_size)
|
2018-12-10 15:25:45 +00:00
|
|
|
throw DB::Exception(
|
|
|
|
"Region id is too large: " + DB::toString(name_entry.id) + ", should be not more than " + DB::toString(max_size),
|
2018-11-22 21:19:58 +00:00
|
|
|
DB::ErrorCodes::INCORRECT_DATA);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-11-28 22:15:06 +00:00
|
|
|
while (name_entry.id >= new_names_refs.size())
|
2017-04-01 07:20:54 +00:00
|
|
|
new_names_refs.resize(new_names_refs.size() * 2, StringRef("", 0));
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2019-03-07 20:04:59 +00:00
|
|
|
new_names_refs[name_entry.id] = StringRef(new_chars.data() + old_size, name_entry.name.length());
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
chars[language_id].swap(new_chars);
|
|
|
|
names_refs[language_id].swap(new_names_refs);
|
|
|
|
}
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
for (size_t language_id = 0; language_id < SUPPORTED_LANGUAGES_COUNT; ++language_id)
|
|
|
|
names_refs[language_id].resize(max_region_id + 1, StringRef("", 0));
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|