ClickHouse/dbms/src/Server/ConfigReloader.cpp

166 lines
4.0 KiB
C++
Raw Normal View History

#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-16 20:01:38 +00:00
constexpr decltype(ConfigReloader::reload_interval) ConfigReloader::reload_interval;
ConfigReloader::ConfigReloader(const std::string & main_config_path_, const std::string & users_config_path_,
const std::string & include_from_path_, Context * context_)
: 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
{
/// If path to users' config isn't absolute, try guess its root (current) dir.
/// At first, try to find it in dir of main config, after will use current dir.
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();
2017-03-09 04:26:17 +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
}
/// Setup users on server init
reloadIfNewer(false, true);
thread = std::thread(&ConfigReloader::run, this);
2016-01-17 13:34:36 +00:00
}
ConfigReloader::~ConfigReloader()
2016-01-17 13:34:36 +00:00
{
try
{
2016-10-23 10:52:32 +00:00
{
std::lock_guard<std::mutex> lock{mutex};
quit = true;
}
cond.notify_one();
2016-01-17 13:34:36 +00:00
thread.join();
}
catch (...)
{
2016-10-23 10:52:32 +00:00
DB::tryLogCurrentException(__PRETTY_FUNCTION__);
2016-01-17 13:34:36 +00:00
}
}
void ConfigReloader::run()
2016-01-17 13:34:36 +00:00
{
setThreadName("ConfigReloader");
2016-01-17 13:34:36 +00:00
2016-10-23 10:52:32 +00:00
std::unique_lock<std::mutex> lock{mutex};
while (true)
2016-01-17 13:34:36 +00:00
{
2016-10-23 10:52:32 +00:00
if (cond.wait_for(lock, reload_interval, [this] { return quit; }))
break;
reloadIfNewer(false, false);
2016-01-17 13:34:36 +00:00
}
}
ConfigReloader::FilesChangesTracker ConfigReloader::getFileListFor(const std::string & root_config_path)
2016-01-17 13:34:36 +00:00
{
FilesChangesTracker file_list;
2016-01-17 13:34:36 +00:00
file_list.addIfExists(root_config_path);
file_list.addIfExists(include_from_path);
2016-01-17 13:34:36 +00:00
for (const auto & path : ConfigProcessor::getConfigMergeFiles(root_config_path))
file_list.addIfExists(path);
return file_list;
}
ConfigurationPtr ConfigReloader::loadConfigFor(const std::string & root_config_path, bool throw_on_error)
{
2016-01-17 13:34:36 +00:00
ConfigurationPtr config;
LOG_DEBUG(log, "Loading config '" << root_config_path << "'");
2016-01-17 13:34:36 +00:00
try
{
config = ConfigProcessor().loadConfig(root_config_path);
2016-01-17 13:34:36 +00:00
}
catch (...)
{
if (throw_on_error)
2016-01-17 13:34:36 +00:00
throw;
tryLogCurrentException(log, "Error loading config from '" + root_config_path + "' ");
return nullptr;
2016-01-17 13:34:36 +00:00
}
return config;
}
void ConfigReloader::reloadIfNewer(bool force_main, bool force_users)
{
FilesChangesTracker main_config_files = getFileListFor(main_config_path);
if (force_main || main_config_files.isDifferOrNewerThan(last_main_config_files))
{
ConfigurationPtr config = loadConfigFor(main_config_path, force_main);
if (config)
{
/** We should remember last modification time if and only if config was sucessfully loaded
* Otherwise a race condition could occur during config files update:
* File is contain raw (and non-valid) data, therefore config is not applied.
* When file has been written (and contain valid data), we don't load new data since modification time remains the same.
*/
last_main_config_files = std::move(main_config_files);
try
{
context->setClustersConfig(config);
}
catch (...)
{
if (force_main)
throw;
tryLogCurrentException(log, "Error updating remote_servers config from '" + main_config_path + "' ");
}
}
}
FilesChangesTracker users_config_files = getFileListFor(users_config_path);
if (force_users || users_config_files.isDifferOrNewerThan(last_users_config_files))
{
ConfigurationPtr config = loadConfigFor(users_config_path, force_users);
if (config)
{
last_users_config_files = std::move(users_config_files);
try
{
context->setUsersConfig(config);
}
catch (...)
{
if (force_users)
throw;
tryLogCurrentException(log, "Error updating users config from '" + users_config_path + "' ");
}
}
2016-01-17 13:34:36 +00:00
}
}
}