mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-22 17:50:47 +00:00
escape user, password and host. [#METR-12221]
This commit is contained in:
parent
61af8baa77
commit
ec0cee0afe
@ -33,7 +33,6 @@ public:
|
|||||||
{
|
{
|
||||||
std::string dir_name;
|
std::string dir_name;
|
||||||
int weight;
|
int weight;
|
||||||
bool internal_replication;
|
|
||||||
};
|
};
|
||||||
std::vector<ShardInfo> shard_info_vec;
|
std::vector<ShardInfo> shard_info_vec;
|
||||||
std::vector<size_t> slot_to_shard;
|
std::vector<size_t> slot_to_shard;
|
||||||
@ -67,7 +66,7 @@ public:
|
|||||||
Address(const String & host_port_, const String & user_, const String & password_);
|
Address(const String & host_port_, const String & user_, const String & password_);
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool isLocal(const Address & address);
|
static bool addressIsLocal(const Poco::Net::SocketAddress & address);
|
||||||
|
|
||||||
// private:
|
// private:
|
||||||
/// Массив шардов. Каждый шард - адреса одного сервера.
|
/// Массив шардов. Каждый шард - адреса одного сервера.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <DB/Interpreters/Cluster.h>
|
#include <DB/Interpreters/Cluster.h>
|
||||||
|
#include <DB/Common/escapeForFileName.h>
|
||||||
#include <Poco/Util/AbstractConfiguration.h>
|
#include <Poco/Util/AbstractConfiguration.h>
|
||||||
#include <Poco/Util/Application.h>
|
#include <Poco/Util/Application.h>
|
||||||
#include <Poco/Net/NetworkInterface.h>
|
#include <Poco/Net/NetworkInterface.h>
|
||||||
@ -38,8 +39,10 @@ namespace
|
|||||||
inline std::string addressToDirName(const Cluster::Address & address)
|
inline std::string addressToDirName(const Cluster::Address & address)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
address.user + (address.password.empty() ? "" : (':' + address.password)) + '@' +
|
escapeForFileName(address.user) +
|
||||||
address.host_port.host().toString() + ':' + std::to_string(address.host_port.port());
|
(address.password.empty() ? "" : (':' + escapeForFileName(address.password))) + '@' +
|
||||||
|
escapeForFileName(address.host_port.host().toString()) + ':' +
|
||||||
|
std::to_string(address.host_port.port());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +75,12 @@ Cluster::Cluster(const Settings & settings, const DataTypeFactory & data_type_fa
|
|||||||
{
|
{
|
||||||
const auto & prefix = config_prefix + *it;
|
const auto & prefix = config_prefix + *it;
|
||||||
const auto weight = config.getInt(prefix + ".weight", 1);
|
const auto weight = config.getInt(prefix + ".weight", 1);
|
||||||
const auto internal_replication = config.getBool(prefix + ".internal_replication", false);
|
if (weight == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
addresses.emplace_back(prefix);
|
addresses.emplace_back(prefix);
|
||||||
slot_to_shard.insert(std::end(slot_to_shard), weight, shard_info_vec.size());
|
slot_to_shard.insert(std::end(slot_to_shard), weight, shard_info_vec.size());
|
||||||
shard_info_vec.push_back({addressToDirName(addresses.back()), weight, internal_replication});
|
shard_info_vec.push_back({addressToDirName(addresses.back()), weight});
|
||||||
}
|
}
|
||||||
else if (0 == strncmp(it->c_str(), "shard", strlen("shard")))
|
else if (0 == strncmp(it->c_str(), "shard", strlen("shard")))
|
||||||
{
|
{
|
||||||
@ -88,14 +92,18 @@ Cluster::Cluster(const Settings & settings, const DataTypeFactory & data_type_fa
|
|||||||
|
|
||||||
const auto & partial_prefix = config_prefix + *it + ".";
|
const auto & partial_prefix = config_prefix + *it + ".";
|
||||||
const auto weight = config.getInt(partial_prefix + ".weight", 1);
|
const auto weight = config.getInt(partial_prefix + ".weight", 1);
|
||||||
const auto internal_replication = config.getBool(partial_prefix + ".internal_replication", false);
|
if (weight == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// const auto internal_replication = config.getBool(partial_prefix + ".internal_replication", false);
|
||||||
|
|
||||||
std::string dir_name{};
|
std::string dir_name{};
|
||||||
|
|
||||||
auto first = true;
|
auto first = true;
|
||||||
for (auto jt = replica_keys.begin(); jt != replica_keys.end(); ++jt)
|
for (auto jt = replica_keys.begin(); jt != replica_keys.end(); ++jt)
|
||||||
{
|
{
|
||||||
if (0 == strncmp(jt->data(), "weight", strlen("weight")))
|
if (0 == strncmp(jt->data(), "weight", strlen("weight")) ||
|
||||||
|
0 == strncmp(jt->data(), "internal_replication", strlen("internal_replication")))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (0 == strncmp(jt->c_str(), "replica", strlen("replica")))
|
if (0 == strncmp(jt->c_str(), "replica", strlen("replica")))
|
||||||
@ -111,7 +119,7 @@ Cluster::Cluster(const Settings & settings, const DataTypeFactory & data_type_fa
|
|||||||
}
|
}
|
||||||
|
|
||||||
slot_to_shard.insert(std::end(slot_to_shard), weight, shard_info_vec.size());
|
slot_to_shard.insert(std::end(slot_to_shard), weight, shard_info_vec.size());
|
||||||
shard_info_vec.push_back({dir_name, weight, internal_replication});
|
shard_info_vec.push_back({dir_name, weight});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw Exception("Unknown element in config: " + *it, ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
|
throw Exception("Unknown element in config: " + *it, ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG);
|
||||||
@ -130,7 +138,7 @@ Cluster::Cluster(const Settings & settings, const DataTypeFactory & data_type_fa
|
|||||||
bool has_local_replics = false;
|
bool has_local_replics = false;
|
||||||
for (Addresses::const_iterator jt = it->begin(); jt != it->end(); ++jt)
|
for (Addresses::const_iterator jt = it->begin(); jt != it->end(); ++jt)
|
||||||
{
|
{
|
||||||
if (isLocal(*jt))
|
if (addressIsLocal(jt->host_port))
|
||||||
{
|
{
|
||||||
has_local_replics = true;
|
has_local_replics = true;
|
||||||
break;
|
break;
|
||||||
@ -156,7 +164,7 @@ Cluster::Cluster(const Settings & settings, const DataTypeFactory & data_type_fa
|
|||||||
{
|
{
|
||||||
for (Addresses::const_iterator it = addresses.begin(); it != addresses.end(); ++it)
|
for (Addresses::const_iterator it = addresses.begin(); it != addresses.end(); ++it)
|
||||||
{
|
{
|
||||||
if (isLocal(*it))
|
if (addressIsLocal(it->host_port))
|
||||||
{
|
{
|
||||||
++local_nodes_num;
|
++local_nodes_num;
|
||||||
}
|
}
|
||||||
@ -215,20 +223,20 @@ Poco::Timespan Cluster::saturate(const Poco::Timespan & v, const Poco::Timespan
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Cluster::isLocal(const Address & address)
|
bool Cluster::addressIsLocal(const Poco::Net::SocketAddress & address)
|
||||||
{
|
{
|
||||||
/// Если среди реплик существует такая, что:
|
/// Если среди реплик существует такая, что:
|
||||||
/// - её порт совпадает с портом, который слушает сервер;
|
/// - её порт совпадает с портом, который слушает сервер;
|
||||||
/// - её хост резолвится в набор адресов, один из которых совпадает с одним из адресов сетевых интерфейсов сервера
|
/// - её хост резолвится в набор адресов, один из которых совпадает с одним из адресов сетевых интерфейсов сервера
|
||||||
/// то нужно всегда ходить на этот шард без межпроцессного взаимодействия
|
/// то нужно всегда ходить на этот шард без межпроцессного взаимодействия
|
||||||
UInt16 clickhouse_port = Poco::Util::Application::instance().config().getInt("tcp_port", 0);
|
const UInt16 clickhouse_port = Poco::Util::Application::instance().config().getInt("tcp_port", 0);
|
||||||
static Poco::Net::NetworkInterface::NetworkInterfaceList interfaces = Poco::Net::NetworkInterface::list();
|
static auto interfaces = Poco::Net::NetworkInterface::list();
|
||||||
|
|
||||||
if (clickhouse_port == address.host_port.port() &&
|
if (clickhouse_port == address.port() &&
|
||||||
interfaces.end() != std::find_if(interfaces.begin(), interfaces.end(),
|
interfaces.end() != std::find_if(interfaces.begin(), interfaces.end(),
|
||||||
[&](const Poco::Net::NetworkInterface & interface) { return interface.address() == address.host_port.host(); }))
|
[&](const Poco::Net::NetworkInterface & interface) { return interface.address() == address.host(); }))
|
||||||
{
|
{
|
||||||
LOG_INFO(&Poco::Util::Application::instance().logger(), "Replica with address " << address.host_port.toString() << " will be processed as local.");
|
LOG_INFO(&Poco::Util::Application::instance().logger(), "Replica with address " << address.toString() << " will be processed as local.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -259,7 +259,9 @@ void StorageDistributed::directoryMonitorFunc(const std::string & name)
|
|||||||
const auto & path = this->path + name + '/';
|
const auto & path = this->path + name + '/';
|
||||||
std::cout << "created monitor for directory " << path << std::endl;
|
std::cout << "created monitor for directory " << path << std::endl;
|
||||||
|
|
||||||
// ConnectionPools pools;
|
auto is_local = false;
|
||||||
|
ConnectionPools pools;
|
||||||
|
|
||||||
for (auto it = boost::make_split_iterator(name, boost::first_finder(",")); it != decltype(it){}; ++it)
|
for (auto it = boost::make_split_iterator(name, boost::first_finder(",")); it != decltype(it){}; ++it)
|
||||||
{
|
{
|
||||||
const auto & address = boost::copy_range<std::string>(*it);
|
const auto & address = boost::copy_range<std::string>(*it);
|
||||||
@ -270,25 +272,42 @@ void StorageDistributed::directoryMonitorFunc(const std::string & name)
|
|||||||
throw Exception{"Shard address '" + address + "' does not match to 'user[:password]@host:port' pattern"};
|
throw Exception{"Shard address '" + address + "' does not match to 'user[:password]@host:port' pattern"};
|
||||||
|
|
||||||
const auto has_pw = colon < user_pw_end;
|
const auto has_pw = colon < user_pw_end;
|
||||||
const auto host_end = has_pw ? colon : strchr(user_pw_end + 1, ':');
|
const auto host_end = has_pw ? strchr(user_pw_end + 1, ':') : colon;
|
||||||
if (!host_end)
|
if (!host_end)
|
||||||
throw Exception{"Shard address '" + address + "' does not contain port"};
|
throw Exception{"Shard address '" + address + "' does not contain port"};
|
||||||
|
|
||||||
const std::string user{address.data(), has_pw ? colon : user_pw_end};
|
const auto user = unescapeForFileName({address.data(), has_pw ? colon : user_pw_end});
|
||||||
const auto password = has_pw ? std::string{colon + 1, user_pw_end} : std::string{};
|
const auto password = has_pw ? unescapeForFileName({colon + 1, user_pw_end}) : std::string{};
|
||||||
const std::string host{user_pw_end + 1, host_end};
|
const auto host = unescapeForFileName({user_pw_end + 1, host_end});
|
||||||
const auto port = DB::parse<UInt16>(host_end + 1);
|
const auto port = DB::parse<UInt16>(host_end + 1);
|
||||||
|
|
||||||
// pools.emplace_back(new ConnectionPool(1, host, port, remote_database, "default", "", getName() + '_' + name));
|
|
||||||
std::cout
|
std::cout
|
||||||
<< "\taddress " << host
|
<< "\taddress " << host
|
||||||
<< " port " << port
|
<< " port " << port
|
||||||
<< " user " << user
|
<< " user " << user
|
||||||
<< " password " << password
|
<< " password " << password
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
|
if (Cluster::addressIsLocal({host, port}))
|
||||||
|
{
|
||||||
|
is_local = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pools.emplace_back(new ConnectionPool{
|
||||||
|
1, host, port, "",
|
||||||
|
user, password, context.getDataTypeFactory(),
|
||||||
|
getName() + '_' + name
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto pool = pools.size() == 1 ? pools[0] : new ConnectionPoolWithFailover(pools, DB::LoadBalancing::RANDOM);
|
std::cout << "local? " << std::boolalpha << is_local << std::endl;
|
||||||
|
const auto pool = is_local
|
||||||
|
? (pools.size() == 1
|
||||||
|
? pools[0]
|
||||||
|
: new ConnectionPoolWithFailover(pools, DB::LoadBalancing::RANDOM)
|
||||||
|
)
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
while (!quit.load(std::memory_order_relaxed))
|
while (!quit.load(std::memory_order_relaxed))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user