2015-02-10 17:40:40 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Dictionaries/IDictionary.h>
|
|
|
|
#include <Common/Exception.h>
|
|
|
|
#include <Common/setThreadName.h>
|
|
|
|
#include <Common/randomSeed.h>
|
2015-09-29 19:19:54 +00:00
|
|
|
#include <common/MultiVersion.h>
|
|
|
|
#include <common/logger_useful.h>
|
2015-02-10 17:40:40 +00:00
|
|
|
#include <Poco/Event.h>
|
2015-06-09 16:12:51 +00:00
|
|
|
#include <unistd.h>
|
2015-02-10 17:40:40 +00:00
|
|
|
#include <time.h>
|
|
|
|
#include <mutex>
|
|
|
|
#include <thread>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <chrono>
|
|
|
|
#include <random>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
class Context;
|
|
|
|
|
|
|
|
/** Manages user-defined dictionaries.
|
2017-04-01 07:20:54 +00:00
|
|
|
* Monitors configuration file and automatically reloads dictionaries in a separate thread.
|
|
|
|
* The monitoring thread wakes up every @check_period_sec seconds and checks
|
|
|
|
* modification time of dictionaries' configuration file. If said time is greater than
|
|
|
|
* @config_last_modified, the dictionaries are created from scratch using configuration file,
|
|
|
|
* possibly overriding currently existing dictionaries with the same name (previous versions of
|
|
|
|
* overridden dictionaries will live as long as there are any users retaining them).
|
2015-02-10 17:40:40 +00:00
|
|
|
*
|
2017-04-01 07:20:54 +00:00
|
|
|
* Apart from checking configuration file for modifications, each non-cached dictionary
|
|
|
|
* has a lifetime of its own and may be updated if it's source reports that it has been
|
|
|
|
* modified. The time of next update is calculated by choosing uniformly a random number
|
|
|
|
* distributed between lifetime.min_sec and lifetime.max_sec.
|
|
|
|
* If either of lifetime.min_sec and lifetime.max_sec is zero, such dictionary is never updated.
|
2015-02-10 17:40:40 +00:00
|
|
|
*/
|
|
|
|
class ExternalDictionaries
|
|
|
|
{
|
|
|
|
private:
|
2017-04-01 07:20:54 +00:00
|
|
|
friend class StorageSystemDictionaries;
|
2015-03-24 09:46:07 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
mutable std::mutex dictionaries_mutex;
|
2015-03-18 16:07:15 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
using DictionaryPtr = std::shared_ptr<MultiVersion<IDictionaryBase>>;
|
|
|
|
struct DictionaryInfo final
|
|
|
|
{
|
|
|
|
DictionaryPtr dict;
|
|
|
|
std::string origin;
|
|
|
|
std::exception_ptr exception;
|
|
|
|
};
|
2015-05-26 11:53:58 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
struct FailedDictionaryInfo final
|
|
|
|
{
|
|
|
|
std::unique_ptr<IDictionaryBase> dict;
|
|
|
|
std::chrono::system_clock::time_point next_attempt_time;
|
|
|
|
UInt64 error_count;
|
|
|
|
};
|
2015-06-09 16:12:51 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/** name -> dictionary.
|
|
|
|
*/
|
|
|
|
std::unordered_map<std::string, DictionaryInfo> dictionaries;
|
2015-08-12 03:57:32 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/** Here are dictionaries, that has been never loaded sussessfully.
|
|
|
|
* They are also in 'dictionaries', but with nullptr as 'dict'.
|
|
|
|
*/
|
|
|
|
std::unordered_map<std::string, FailedDictionaryInfo> failed_dictionaries;
|
2015-08-12 03:57:32 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
/** Both for dictionaries and failed_dictionaries.
|
|
|
|
*/
|
|
|
|
std::unordered_map<std::string, std::chrono::system_clock::time_point> update_times;
|
2015-08-12 03:57:32 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
std::mt19937_64 rnd_engine{randomSeed()};
|
2015-02-10 17:40:40 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
Context & context;
|
2015-02-10 17:40:40 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
std::thread reloading_thread;
|
|
|
|
Poco::Event destroy;
|
2015-02-10 17:40:40 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
Logger * log;
|
2015-02-10 17:40:40 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
std::unordered_map<std::string, Poco::Timestamp> last_modification_times;
|
2015-02-10 17:40:40 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
void reloadImpl(bool throw_on_error = false);
|
|
|
|
void reloadFromFile(const std::string & config_path, bool throw_on_error);
|
2015-02-10 17:40:40 +00:00
|
|
|
|
2017-04-08 01:32:05 +00:00
|
|
|
void reloadPeriodically();
|
2015-02-10 17:40:40 +00:00
|
|
|
|
|
|
|
public:
|
2017-04-01 07:20:54 +00:00
|
|
|
/// Dictionaries will be loaded immediately and then will be updated in separate thread, each 'reload_period' seconds.
|
2017-04-08 01:32:05 +00:00
|
|
|
ExternalDictionaries(Context & context, const bool throw_on_error);
|
|
|
|
~ExternalDictionaries();
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
MultiVersion<IDictionaryBase>::Version getDictionary(const std::string & name) const;
|
2015-02-10 17:40:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|