2021-10-20 08:35:37 +00:00
|
|
|
#include <Common/GetPriorityForLoadBalancing.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2022-03-21 14:55:01 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int LOGICAL_ERROR;
|
|
|
|
}
|
|
|
|
|
2021-10-22 12:23:25 +00:00
|
|
|
std::function<size_t(size_t index)> GetPriorityForLoadBalancing::getPriorityFunc(LoadBalancing load_balance, size_t offset, size_t pool_size) const
|
2021-10-20 08:35:37 +00:00
|
|
|
{
|
|
|
|
std::function<size_t(size_t index)> get_priority;
|
2021-10-22 12:23:25 +00:00
|
|
|
switch (load_balance)
|
2021-10-20 08:35:37 +00:00
|
|
|
{
|
|
|
|
case LoadBalancing::NEAREST_HOSTNAME:
|
2022-03-21 14:55:01 +00:00
|
|
|
if (hostname_differences.empty())
|
|
|
|
throw Exception(ErrorCodes::LOGICAL_ERROR, "It's a bug: hostname_differences is not initialized");
|
Fix stack-use-after-return in GetPriorityForLoadBalancing::getPriorityFunc()
clang-15 reports [1]:
<details>
<summary>ASan report</summary>
```
==1==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f1d04c4eb20 at pc 0x000031c4803c bp 0x7f1d05e19a00 sp 0x7f1d05e199f8
READ of size 8 at 0x7f1d04c4eb20 thread T200 (QueryPullPipeEx)
#0 0x31c4803b in DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3::operator()(unsigned long) const build_docker/../src/Common/GetPriorityForLoadBalancing.cpp:42:40
#1 0x31c4803b in decltype(static_cast<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&>(fp)(static_cast<unsigned long>(fp0))) std::__1::__invoke<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long>(DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long&&) build_docker/../contrib/libcxx/include/type_traits:3640:23
#2 0x31c4803b in unsigned long std::__1::__invoke_void_return_wrapper<unsigned long, false>::__call<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long>(DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long&&) build_docker/../contrib/libcxx/include/__functional/invoke.h:30:16
#3 0x31c4803b in std::__1::__function::__default_alloc_func<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3, unsigned long (unsigned long)>::operator()(unsigned long&&) build_docker/../contrib/libcxx/include/__functional/function.h:230:12
#4 0x31c4803b in unsigned long std::__1::__function::__policy_invoker<unsigned long (unsigned long)>::__call_impl<std::__1::__function::__default_alloc_func<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3, unsigned long (unsigned long)>>(std::__1::__function::__policy_storage const*, unsigned long) build_docker/../contrib/libcxx/include/__functional/function.h:711:16
#5 0x31c38b07 in std::__1::__function::__policy_func<unsigned long (unsigned long)>::operator()(unsigned long&&) const build_docker/../contrib/libcxx/include/__functional/function.h:843:16
#6 0x31c38b07 in std::__1::function<unsigned long (unsigned long)>::operator()(unsigned long) const build_docker/../contrib/libcxx/include/__functional/function.h:1184:12
#7 0x31c38b07 in PoolWithFailoverBase<DB::IConnectionPool>::getShuffledPools(unsigned long, std::__1::function<unsigned long (unsigned long)> const&) build_docker/../src/Common/PoolWithFailoverBase.h:174:39
This frame has 2 object(s):
[32, 40) 'pool_size.addr' <== Memory access at offset 32 is inside this variable
[64, 88) 'ref.tmp' (line 18)
```
</details>
[1]: https://s3.amazonaws.com/clickhouse-test-reports/41046/adea92f847373d1fcfd733d8979c63024f9b80bf/integration_tests__asan__[1/3].html
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
2022-09-09 12:48:32 +00:00
|
|
|
get_priority = [this](size_t i) { return hostname_differences[i]; };
|
2021-10-20 08:35:37 +00:00
|
|
|
break;
|
|
|
|
case LoadBalancing::IN_ORDER:
|
|
|
|
get_priority = [](size_t i) { return i; };
|
|
|
|
break;
|
|
|
|
case LoadBalancing::RANDOM:
|
|
|
|
break;
|
|
|
|
case LoadBalancing::FIRST_OR_RANDOM:
|
2021-10-22 12:23:25 +00:00
|
|
|
get_priority = [offset](size_t i) -> size_t { return i != offset; };
|
2021-10-20 08:35:37 +00:00
|
|
|
break;
|
|
|
|
case LoadBalancing::ROUND_ROBIN:
|
|
|
|
if (last_used >= pool_size)
|
|
|
|
last_used = 0;
|
|
|
|
++last_used;
|
|
|
|
/* Consider pool_size equals to 5
|
|
|
|
* last_used = 1 -> get_priority: 0 1 2 3 4
|
|
|
|
* last_used = 2 -> get_priority: 4 0 1 2 3
|
|
|
|
* last_used = 3 -> get_priority: 4 3 0 1 2
|
|
|
|
* ...
|
|
|
|
* */
|
Fix stack-use-after-return in GetPriorityForLoadBalancing::getPriorityFunc()
clang-15 reports [1]:
<details>
<summary>ASan report</summary>
```
==1==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f1d04c4eb20 at pc 0x000031c4803c bp 0x7f1d05e19a00 sp 0x7f1d05e199f8
READ of size 8 at 0x7f1d04c4eb20 thread T200 (QueryPullPipeEx)
#0 0x31c4803b in DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3::operator()(unsigned long) const build_docker/../src/Common/GetPriorityForLoadBalancing.cpp:42:40
#1 0x31c4803b in decltype(static_cast<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&>(fp)(static_cast<unsigned long>(fp0))) std::__1::__invoke<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long>(DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long&&) build_docker/../contrib/libcxx/include/type_traits:3640:23
#2 0x31c4803b in unsigned long std::__1::__invoke_void_return_wrapper<unsigned long, false>::__call<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long>(DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3&, unsigned long&&) build_docker/../contrib/libcxx/include/__functional/invoke.h:30:16
#3 0x31c4803b in std::__1::__function::__default_alloc_func<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3, unsigned long (unsigned long)>::operator()(unsigned long&&) build_docker/../contrib/libcxx/include/__functional/function.h:230:12
#4 0x31c4803b in unsigned long std::__1::__function::__policy_invoker<unsigned long (unsigned long)>::__call_impl<std::__1::__function::__default_alloc_func<DB::GetPriorityForLoadBalancing::getPriorityFunc(DB::LoadBalancing, unsigned long, unsigned long) const::$_3, unsigned long (unsigned long)>>(std::__1::__function::__policy_storage const*, unsigned long) build_docker/../contrib/libcxx/include/__functional/function.h:711:16
#5 0x31c38b07 in std::__1::__function::__policy_func<unsigned long (unsigned long)>::operator()(unsigned long&&) const build_docker/../contrib/libcxx/include/__functional/function.h:843:16
#6 0x31c38b07 in std::__1::function<unsigned long (unsigned long)>::operator()(unsigned long) const build_docker/../contrib/libcxx/include/__functional/function.h:1184:12
#7 0x31c38b07 in PoolWithFailoverBase<DB::IConnectionPool>::getShuffledPools(unsigned long, std::__1::function<unsigned long (unsigned long)> const&) build_docker/../src/Common/PoolWithFailoverBase.h:174:39
This frame has 2 object(s):
[32, 40) 'pool_size.addr' <== Memory access at offset 32 is inside this variable
[64, 88) 'ref.tmp' (line 18)
```
</details>
[1]: https://s3.amazonaws.com/clickhouse-test-reports/41046/adea92f847373d1fcfd733d8979c63024f9b80bf/integration_tests__asan__[1/3].html
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
2022-09-09 12:48:32 +00:00
|
|
|
get_priority = [this, pool_size](size_t i)
|
2021-10-21 07:57:21 +00:00
|
|
|
{
|
2021-10-20 08:35:37 +00:00
|
|
|
++i;
|
|
|
|
return i < last_used ? pool_size - i : i - last_used;
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return get_priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|