2012-12-19 20:15:15 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2015-04-16 07:22:29 +00:00
|
|
|
|
#include <thread>
|
2015-09-29 19:19:54 +00:00
|
|
|
|
#include <common/MultiVersion.h>
|
|
|
|
|
#include <common/logger_useful.h>
|
2016-01-15 02:47:19 +00:00
|
|
|
|
#include <DB/Dictionaries/Embedded/RegionsHierarchies.h>
|
|
|
|
|
#include <DB/Dictionaries/Embedded/TechDataHierarchy.h>
|
|
|
|
|
#include <DB/Dictionaries/Embedded/RegionsNames.h>
|
2015-09-24 18:54:21 +00:00
|
|
|
|
#include <DB/Common/setThreadName.h>
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2015-01-22 14:32:38 +00:00
|
|
|
|
class Context;
|
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
/// Metrica's Dictionaries which can be used in functions.
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
|
|
|
|
class Dictionaries
|
|
|
|
|
{
|
|
|
|
|
private:
|
2014-04-04 18:08:01 +00:00
|
|
|
|
MultiVersion<RegionsHierarchies> regions_hierarchies;
|
2013-08-11 03:40:14 +00:00
|
|
|
|
MultiVersion<TechDataHierarchy> tech_data_hierarchy;
|
|
|
|
|
MultiVersion<RegionsNames> regions_names;
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
2016-09-05 18:55:23 +00:00
|
|
|
|
/// Directories' updating periodicity (in seconds).
|
2012-12-19 20:15:15 +00:00
|
|
|
|
int reload_period;
|
2016-09-06 10:07:37 +00:00
|
|
|
|
int cur_reload_period = 1;
|
|
|
|
|
bool is_fast_start_stage = true;
|
2016-09-05 18:55:23 +00:00
|
|
|
|
|
2014-10-16 01:21:03 +00:00
|
|
|
|
std::thread reloading_thread;
|
2015-02-10 17:40:40 +00:00
|
|
|
|
Poco::Event destroy;
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
|
|
|
|
Logger * log;
|
|
|
|
|
|
2015-01-26 15:27:51 +00:00
|
|
|
|
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
2015-03-27 13:11:22 +00:00
|
|
|
|
void handleException(const bool throw_on_error) const
|
2013-10-21 13:56:11 +00:00
|
|
|
|
{
|
2015-03-27 13:11:22 +00:00
|
|
|
|
const auto exception_ptr = std::current_exception();
|
|
|
|
|
|
2013-10-21 13:56:11 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
catch (const Poco::Exception & e)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR(log, "Cannot load dictionary! You must resolve this manually. " << e.displayText());
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR(log, "Cannot load dictionary! You must resolve this manually.");
|
|
|
|
|
}
|
2015-03-27 13:11:22 +00:00
|
|
|
|
|
|
|
|
|
if (throw_on_error)
|
|
|
|
|
std::rethrow_exception(exception_ptr);
|
2013-10-21 13:56:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-09-05 18:55:23 +00:00
|
|
|
|
/// Updates directories (dictionaries).
|
2016-09-06 10:07:37 +00:00
|
|
|
|
bool reloadImpl(const bool throw_on_error = false)
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
|
|
|
|
/** Если не удаётся обновить справочники, то несмотря на это, не кидаем исключение (используем старые справочники).
|
|
|
|
|
* Если старых корректных справочников нет, то при использовании функций, которые от них зависят,
|
|
|
|
|
* будет кидаться исключение.
|
2013-10-21 13:56:11 +00:00
|
|
|
|
* Производится попытка загрузить каждый справочник по-отдельности.
|
2012-12-19 20:15:15 +00:00
|
|
|
|
*/
|
2013-10-21 13:56:11 +00:00
|
|
|
|
|
|
|
|
|
LOG_INFO(log, "Loading dictionaries.");
|
|
|
|
|
|
2015-03-27 15:44:32 +00:00
|
|
|
|
auto & config = Poco::Util::Application::instance().config();
|
|
|
|
|
|
2013-10-21 13:56:11 +00:00
|
|
|
|
bool was_exception = false;
|
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
if (config.has(TechDataHierarchy::required_key) && (!is_fast_start_stage || !tech_data_hierarchy.get()))
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
2015-03-27 15:44:32 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
auto new_tech_data_hierarchy = std::make_unique<TechDataHierarchy>();
|
|
|
|
|
tech_data_hierarchy.set(new_tech_data_hierarchy.release());
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
handleException(throw_on_error);
|
|
|
|
|
was_exception = true;
|
|
|
|
|
}
|
2013-10-21 13:56:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
if (config.has(RegionsHierarchies::required_key) && (!is_fast_start_stage || !regions_hierarchies.get()))
|
2013-10-21 13:56:11 +00:00
|
|
|
|
{
|
2015-03-27 15:44:32 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
auto new_regions_hierarchies = std::make_unique<RegionsHierarchies>();
|
|
|
|
|
new_regions_hierarchies->reload();
|
|
|
|
|
regions_hierarchies.set(new_regions_hierarchies.release());
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
handleException(throw_on_error);
|
|
|
|
|
was_exception = true;
|
|
|
|
|
}
|
2013-10-21 13:56:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
if (config.has(RegionsNames::required_key) && (!is_fast_start_stage || !regions_names.get()))
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
2015-03-27 15:44:32 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
auto new_regions_names = std::make_unique<RegionsNames>();
|
|
|
|
|
new_regions_names->reload();
|
|
|
|
|
regions_names.set(new_regions_names.release());
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
handleException(throw_on_error);
|
|
|
|
|
was_exception = true;
|
|
|
|
|
}
|
2012-12-19 20:15:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 13:56:11 +00:00
|
|
|
|
if (!was_exception)
|
|
|
|
|
LOG_INFO(log, "Loaded dictionaries.");
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
return !was_exception;
|
2016-09-05 18:55:23 +00:00
|
|
|
|
}
|
2015-01-21 11:39:48 +00:00
|
|
|
|
|
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
/** Updates directories (dictionaries) every reload_period seconds.
|
|
|
|
|
* If all dictionaries are not loaded at least once, try reload them with exponential delay (1, 2, ... reload_period).
|
|
|
|
|
* If all dictionaries are loaded, update them using constant reload_period delay.
|
|
|
|
|
*/
|
2012-12-19 20:15:15 +00:00
|
|
|
|
void reloadPeriodically()
|
|
|
|
|
{
|
2015-09-24 18:54:21 +00:00
|
|
|
|
setThreadName("DictReload");
|
|
|
|
|
|
2012-12-19 20:15:15 +00:00
|
|
|
|
while (true)
|
|
|
|
|
{
|
2016-09-05 18:55:23 +00:00
|
|
|
|
if (destroy.tryWait(cur_reload_period * 1000))
|
2012-12-19 20:15:15 +00:00
|
|
|
|
return;
|
2012-12-20 12:58:47 +00:00
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
if (reloadImpl())
|
|
|
|
|
{
|
|
|
|
|
/// Success
|
|
|
|
|
cur_reload_period = reload_period;
|
|
|
|
|
is_fast_start_stage = false;
|
|
|
|
|
}
|
2016-09-05 18:55:23 +00:00
|
|
|
|
|
2016-09-06 10:07:37 +00:00
|
|
|
|
if (is_fast_start_stage)
|
|
|
|
|
{
|
|
|
|
|
cur_reload_period = std::min(reload_period, 2 * cur_reload_period); /// exponentially increase delay
|
|
|
|
|
is_fast_start_stage = cur_reload_period < reload_period; /// leave fast start state
|
|
|
|
|
}
|
2012-12-19 20:15:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2016-09-05 18:55:23 +00:00
|
|
|
|
/// Every reload_period seconds directories are updated inside a separate thread.
|
2015-05-07 14:40:35 +00:00
|
|
|
|
Dictionaries(const bool throw_on_error, const int reload_period_)
|
2016-09-05 18:55:23 +00:00
|
|
|
|
: reload_period(reload_period_),
|
|
|
|
|
log(&Logger::get("Dictionaries"))
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
2015-03-27 13:11:22 +00:00
|
|
|
|
reloadImpl(throw_on_error);
|
2014-10-16 01:21:03 +00:00
|
|
|
|
reloading_thread = std::thread([this] { reloadPeriodically(); });
|
2012-12-19 20:15:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-07 14:40:35 +00:00
|
|
|
|
Dictionaries(const bool throw_on_error)
|
|
|
|
|
: Dictionaries(throw_on_error,
|
2015-10-05 07:04:42 +00:00
|
|
|
|
Poco::Util::Application::instance().config()
|
2015-05-07 14:40:35 +00:00
|
|
|
|
.getInt("builtin_dictionaries_reload_interval", 3600))
|
|
|
|
|
{}
|
|
|
|
|
|
2012-12-19 20:15:15 +00:00
|
|
|
|
~Dictionaries()
|
|
|
|
|
{
|
|
|
|
|
destroy.set();
|
|
|
|
|
reloading_thread.join();
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-04 18:08:01 +00:00
|
|
|
|
MultiVersion<RegionsHierarchies>::Version getRegionsHierarchies() const
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
2014-04-04 18:08:01 +00:00
|
|
|
|
return regions_hierarchies.get();
|
2012-12-19 20:15:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-11 03:40:14 +00:00
|
|
|
|
MultiVersion<TechDataHierarchy>::Version getTechDataHierarchy() const
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
|
|
|
|
return tech_data_hierarchy.get();
|
|
|
|
|
}
|
2014-10-16 01:21:03 +00:00
|
|
|
|
|
2013-08-11 03:40:14 +00:00
|
|
|
|
MultiVersion<RegionsNames>::Version getRegionsNames() const
|
2013-06-05 13:40:14 +00:00
|
|
|
|
{
|
|
|
|
|
return regions_names.get();
|
|
|
|
|
}
|
2012-12-19 20:15:15 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|