ClickHouse/dbms/include/DB/Interpreters/Dictionaries.h

179 lines
4.7 KiB
C++
Raw Normal View History

2012-12-19 20:15:15 +00:00
#pragma once
#include <thread>
2015-09-29 19:19:54 +00:00
#include <common/MultiVersion.h>
#include <common/logger_useful.h>
#include <DB/Dictionaries/Embedded/RegionsHierarchies.h>
#include <DB/Dictionaries/Embedded/TechDataHierarchy.h>
#include <DB/Dictionaries/Embedded/RegionsNames.h>
#include <DB/Common/setThreadName.h>
2012-12-19 20:15:15 +00:00
namespace DB
{
class Context;
/// Metrica's Dictionaries which can be used in functions.
2012-12-19 20:15:15 +00:00
class Dictionaries
{
private:
MultiVersion<RegionsHierarchies> regions_hierarchies;
MultiVersion<TechDataHierarchy> tech_data_hierarchy;
MultiVersion<RegionsNames> regions_names;
2012-12-19 20:15:15 +00:00
/// Directories' updating periodicity (in seconds).
2012-12-19 20:15:15 +00:00
int reload_period;
int cur_reload_period = 1;
bool is_fast_start_stage = true;
std::thread reloading_thread;
Poco::Event destroy;
2012-12-19 20:15:15 +00:00
Logger * log = &Logger::get("Dictionaries");
2012-12-19 20:15:15 +00:00
void handleException(const bool throw_on_error) const
{
const auto exception_ptr = std::current_exception();
tryLogCurrentException(log, "Cannot load dictionary! You must resolve this manually.");
if (throw_on_error)
std::rethrow_exception(exception_ptr);
}
/// Updates dictionaries.
bool reloadImpl(const bool throw_on_error)
2012-12-19 20:15:15 +00:00
{
/** Если не удаётся обновить справочники, то несмотря на это, не кидаем исключение (используем старые справочники).
* Если старых корректных справочников нет, то при использовании функций, которые от них зависят,
* будет кидаться исключение.
* Производится попытка загрузить каждый справочник по-отдельности.
2012-12-19 20:15:15 +00:00
*/
LOG_INFO(log, "Loading dictionaries.");
auto & config = Poco::Util::Application::instance().config();
bool was_exception = false;
if (config.has(TechDataHierarchy::required_key) && (!is_fast_start_stage || !tech_data_hierarchy.get()))
2012-12-19 20:15:15 +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;
}
}
if (config.has(RegionsHierarchies::required_key) && (!is_fast_start_stage || !regions_hierarchies.get()))
{
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;
}
}
if (config.has(RegionsNames::required_key) && (!is_fast_start_stage || !regions_names.get()))
2012-12-19 20:15:15 +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
}
if (!was_exception)
LOG_INFO(log, "Loaded dictionaries.");
2012-12-19 20:15:15 +00:00
return !was_exception;
}
/** 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()
{
setThreadName("DictReload");
2012-12-19 20:15:15 +00:00
while (true)
{
if (destroy.tryWait(cur_reload_period * 1000))
2012-12-19 20:15:15 +00:00
return;
if (reloadImpl(false))
{
/// Success
cur_reload_period = reload_period;
is_fast_start_stage = false;
}
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:
/// Every reload_period seconds directories are updated inside a separate thread.
Dictionaries(const bool throw_on_error, const int reload_period_)
: reload_period(reload_period_)
2012-12-19 20:15:15 +00:00
{
reloadImpl(throw_on_error);
reloading_thread = std::thread([this] { reloadPeriodically(); });
2012-12-19 20:15:15 +00:00
}
Dictionaries(const bool throw_on_error)
: Dictionaries(throw_on_error,
Poco::Util::Application::instance().config().getInt("builtin_dictionaries_reload_interval", 3600))
{}
2012-12-19 20:15:15 +00:00
~Dictionaries()
{
destroy.set();
reloading_thread.join();
}
MultiVersion<RegionsHierarchies>::Version getRegionsHierarchies() const
2012-12-19 20:15:15 +00:00
{
return regions_hierarchies.get();
2012-12-19 20:15:15 +00:00
}
MultiVersion<TechDataHierarchy>::Version getTechDataHierarchy() const
2012-12-19 20:15:15 +00:00
{
return tech_data_hierarchy.get();
}
MultiVersion<RegionsNames>::Version getRegionsNames() const
{
return regions_names.get();
}
2012-12-19 20:15:15 +00:00
};
}