2016-10-11 14:37:27 +00:00
|
|
|
|
#include "ConfigReloader.h"
|
2016-01-17 13:34:36 +00:00
|
|
|
|
|
|
|
|
|
#include <Poco/Util/Application.h>
|
|
|
|
|
#include <Poco/File.h>
|
|
|
|
|
|
|
|
|
|
#include <common/logger_useful.h>
|
|
|
|
|
|
|
|
|
|
#include <DB/Interpreters/Context.h>
|
|
|
|
|
#include <DB/Common/setThreadName.h>
|
|
|
|
|
#include <DB/Common/ConfigProcessor.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
namespace ErrorCodes { extern const int FILE_DOESNT_EXIST; }
|
|
|
|
|
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
ConfigReloader::ConfigReloader(const std::string & main_config_path_, const std::string & users_config_path_, const std::string & include_from_path_, Context * context_)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
: main_config_path(main_config_path_), users_config_path(users_config_path_), include_from_path(include_from_path_), context(context_)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
/// Assume that paths derived from --config-file, <users_config> and <include_from> are not changed
|
|
|
|
|
|
2016-01-17 13:34:36 +00:00
|
|
|
|
/// Если путь к конфигу не абсолютный, угадаем, относительно чего он задан.
|
2016-10-10 08:44:52 +00:00
|
|
|
|
/// Сначала поищем его рядом с основным конфигом, потом - в текущей директории.
|
|
|
|
|
if (users_config_path.empty() || users_config_path[0] != '/')
|
2016-01-17 13:34:36 +00:00
|
|
|
|
{
|
|
|
|
|
std::string config_dir = Poco::Path(main_config_path).parent().toString();
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (Poco::File(config_dir + users_config_path).exists())
|
|
|
|
|
users_config_path = config_dir + users_config_path;
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
/// Setup users on server init
|
|
|
|
|
reloadIfNewer(false, true);
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
thread = std::thread(&ConfigReloader::run, this);
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
ConfigReloader::~ConfigReloader()
|
2016-01-17 13:34:36 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2016-10-11 14:37:27 +00:00
|
|
|
|
LOG_DEBUG(log, "ConfigReloader::~ConfigReloader()");
|
2016-01-17 13:34:36 +00:00
|
|
|
|
quit = true;
|
|
|
|
|
thread.join();
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
2016-10-11 14:37:27 +00:00
|
|
|
|
tryLogCurrentException("~ConfigReloader");
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
void ConfigReloader::run()
|
2016-01-17 13:34:36 +00:00
|
|
|
|
{
|
|
|
|
|
setThreadName("UserConfReload");
|
|
|
|
|
|
|
|
|
|
while (!quit)
|
|
|
|
|
{
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
2016-10-10 08:44:52 +00:00
|
|
|
|
reloadIfNewer(false, false);
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
ConfigReloader::FilesChangesTracker ConfigReloader::getFileListFor(const std::string & root_config_path)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
FilesChangesTracker file_list;
|
2016-01-17 13:34:36 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
file_list.addIfExists(root_config_path);
|
|
|
|
|
file_list.addIfExists(this->include_from_path);
|
2016-01-17 13:34:36 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
for (auto & path : ConfigProcessor::getConfigMergeFiles(root_config_path))
|
|
|
|
|
file_list.addIfExists(path);
|
|
|
|
|
|
|
|
|
|
return file_list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
ConfigurationPtr ConfigReloader::loadConfigFor(const std::string & root_config_path, bool throw_on_error)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
{
|
2016-01-17 13:34:36 +00:00
|
|
|
|
ConfigurationPtr config;
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
LOG_DEBUG(log, "Loading config '" << root_config_path << "'");
|
|
|
|
|
|
2016-01-17 13:34:36 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
config = ConfigProcessor().loadConfig(root_config_path);
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Poco::Exception & e)
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (throw_on_error)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
throw;
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
LOG_ERROR(log, "Error loading config from '" << root_config_path << "' : " << e.what() << ": " << e.displayText());
|
|
|
|
|
return nullptr;
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (throw_on_error)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
throw;
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
LOG_ERROR(log, "Error loading config from '" << root_config_path << "'.");
|
|
|
|
|
return nullptr;
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
bool ConfigReloader::applyConfigFor(bool for_main, ConfigurationPtr config, bool throw_on_error)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
{
|
|
|
|
|
auto & root_config_path = (for_main) ? main_config_path : users_config_path;
|
|
|
|
|
|
2016-01-17 13:34:36 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (for_main)
|
|
|
|
|
{
|
|
|
|
|
context->setClustersConfig(config);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
context->setUsersConfig(config);
|
|
|
|
|
}
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Exception & e)
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (throw_on_error)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
throw;
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
LOG_ERROR(log, "Error updating config from '" << root_config_path << "': " << e.what() << ": " << e.displayText() << "\n" << e.getStackTrace().toString());
|
|
|
|
|
return false;
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Poco::Exception & e)
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (throw_on_error)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
throw;
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
LOG_ERROR(log, "Error updating config from '" << root_config_path << "': " << e.what() << ": " << e.displayText());
|
|
|
|
|
return false;
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
if (throw_on_error)
|
2016-01-17 13:34:36 +00:00
|
|
|
|
throw;
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
LOG_ERROR(log, "Error updating config from '" << root_config_path << "'.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-11 14:37:27 +00:00
|
|
|
|
void ConfigReloader::reloadIfNewer(bool force_main, bool force_users)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
{
|
|
|
|
|
FilesChangesTracker main_config_files = getFileListFor(main_config_path);
|
|
|
|
|
if (force_main || main_config_files.isDifferOrNewerThan(last_main_config_files))
|
|
|
|
|
{
|
|
|
|
|
last_main_config_files = std::move(main_config_files);
|
|
|
|
|
|
|
|
|
|
ConfigurationPtr config = loadConfigFor(main_config_path, force_main);
|
|
|
|
|
if (config)
|
|
|
|
|
applyConfigFor(true, config, force_main);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FilesChangesTracker users_config_files = getFileListFor(users_config_path);
|
|
|
|
|
if (force_users || users_config_files.isDifferOrNewerThan(last_users_config_files))
|
|
|
|
|
{
|
|
|
|
|
last_users_config_files = std::move(users_config_files);
|
|
|
|
|
|
|
|
|
|
ConfigurationPtr config = loadConfigFor(users_config_path, force_users);
|
|
|
|
|
if (config)
|
|
|
|
|
applyConfigFor(false, config, force_users);
|
2016-01-17 13:34:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|