2017-04-01 09:19:00 +00:00
|
|
|
#include <Dictionaries/Embedded/RegionsHierarchies.h>
|
|
|
|
#include <Dictionaries/Embedded/RegionsNames.h>
|
2017-08-24 14:51:13 +00:00
|
|
|
#include <Dictionaries/Embedded/TechDataHierarchy.h>
|
|
|
|
#include <Interpreters/Context.h>
|
|
|
|
#include <Interpreters/EmbeddedDictionaries.h>
|
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Common/setThreadName.h>
|
|
|
|
#include <Common/Exception.h>
|
2017-04-19 00:31:15 +00:00
|
|
|
#include <Common/config.h>
|
2017-08-24 14:51:13 +00:00
|
|
|
#include <common/logger_useful.h>
|
|
|
|
|
|
|
|
#include <Poco/Util/Application.h>
|
2017-01-21 04:24:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-08-24 18:19:06 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int UNFINISHED;
|
|
|
|
}
|
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
void EmbeddedDictionaries::handleException(const bool throw_on_error) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const auto exception_ptr = std::current_exception();
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
tryLogCurrentException(log, "Cannot load dictionary! You must resolve this manually.");
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (throw_on_error)
|
|
|
|
std::rethrow_exception(exception_ptr);
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Dictionary>
|
2017-08-24 18:19:06 +00:00
|
|
|
bool EmbeddedDictionaries::reloadDictionary(MultiVersion<Dictionary> & dictionary, const bool throw_on_error, const bool force_reload)
|
2017-01-21 04:24:28 +00:00
|
|
|
{
|
2017-08-24 14:51:13 +00:00
|
|
|
const auto & config = context.getConfigRef();
|
2017-08-30 21:23:39 +00:00
|
|
|
|
|
|
|
bool defined_in_config = Dictionary::isConfigured(config);
|
2017-08-24 18:19:06 +00:00
|
|
|
bool not_initialized = dictionary.get() == nullptr;
|
|
|
|
|
|
|
|
if (defined_in_config && (force_reload || !is_fast_start_stage || not_initialized))
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto new_dictionary = std::make_unique<Dictionary>();
|
2017-08-24 14:51:13 +00:00
|
|
|
new_dictionary->reload(config);
|
2017-04-01 07:20:54 +00:00
|
|
|
dictionary.set(new_dictionary.release());
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
handleException(throw_on_error);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-24 18:19:06 +00:00
|
|
|
bool EmbeddedDictionaries::reloadImpl(const bool throw_on_error, const bool force_reload)
|
2017-01-21 04:24:28 +00:00
|
|
|
{
|
2017-08-24 18:19:06 +00:00
|
|
|
std::unique_lock<std::mutex> lock(mutex);
|
|
|
|
|
2017-04-02 17:37:49 +00:00
|
|
|
/** If you can not update the directories, then despite this, do not throw an exception (use the old directories).
|
|
|
|
* If there are no old correct directories, then when using functions that depend on them,
|
|
|
|
* will throw an exception.
|
|
|
|
* An attempt is made to load each directory separately.
|
|
|
|
*/
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
LOG_INFO(log, "Loading dictionaries.");
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
bool was_exception = false;
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-19 00:31:15 +00:00
|
|
|
#if USE_MYSQL
|
2017-08-24 18:19:06 +00:00
|
|
|
if (!reloadDictionary<TechDataHierarchy>(tech_data_hierarchy, throw_on_error, force_reload))
|
2017-04-01 07:20:54 +00:00
|
|
|
was_exception = true;
|
2017-04-19 00:31:15 +00:00
|
|
|
#endif
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-08-24 18:19:06 +00:00
|
|
|
if (!reloadDictionary<RegionsHierarchies>(regions_hierarchies, throw_on_error, force_reload))
|
2017-04-01 07:20:54 +00:00
|
|
|
was_exception = true;
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-08-24 18:19:06 +00:00
|
|
|
if (!reloadDictionary<RegionsNames>(regions_names, throw_on_error, force_reload))
|
2017-04-01 07:20:54 +00:00
|
|
|
was_exception = true;
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (!was_exception)
|
|
|
|
LOG_INFO(log, "Loaded dictionaries.");
|
2017-01-21 04:24:28 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return !was_exception;
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void EmbeddedDictionaries::reloadPeriodically()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
setThreadName("DictReload");
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (destroy.tryWait(cur_reload_period * 1000))
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-24 14:51:13 +00:00
|
|
|
EmbeddedDictionaries::EmbeddedDictionaries(Context & context_, const bool throw_on_error)
|
|
|
|
: log(&Logger::get("EmbeddedDictionaries"))
|
|
|
|
, context(context_)
|
|
|
|
, reload_period(context_.getConfigRef().getInt("builtin_dictionaries_reload_interval", 3600))
|
2017-01-21 04:24:28 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
reloadImpl(throw_on_error);
|
|
|
|
reloading_thread = std::thread([this] { reloadPeriodically(); });
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EmbeddedDictionaries::~EmbeddedDictionaries()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
destroy.set();
|
|
|
|
reloading_thread.join();
|
2017-01-21 04:24:28 +00:00
|
|
|
}
|
|
|
|
|
2017-08-24 18:19:06 +00:00
|
|
|
void EmbeddedDictionaries::reload()
|
|
|
|
{
|
|
|
|
if (!reloadImpl(true, true))
|
|
|
|
throw Exception("Some embedded dictionaries were not successfully reloaded", ErrorCodes::UNFINISHED);
|
|
|
|
}
|
|
|
|
|
2017-01-21 04:24:28 +00:00
|
|
|
|
|
|
|
}
|