mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge pull request #6082 from vitlibar/fix-segfault-in-reload-outdated
Fix segfault in ExternalLoader::reloadOutdated().
This commit is contained in:
commit
adfc369172
@ -511,12 +511,14 @@ public:
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
for (auto & [name, info] : infos)
|
||||
{
|
||||
if ((info.was_loading() || load_never_loading) && filter_by_name(name))
|
||||
{
|
||||
cancelLoading(info);
|
||||
info.forced_to_reload = true;
|
||||
startLoading(name, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts reloading of all the objects.
|
||||
@ -528,20 +530,22 @@ public:
|
||||
/// The function doesn't touch the objects which were never tried to load.
|
||||
void reloadOutdated()
|
||||
{
|
||||
/// Iterate through all the objects and find loaded ones which should be checked if they were modified.
|
||||
std::unordered_map<LoadablePtr, bool> is_modified_map;
|
||||
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
TimePoint now = std::chrono::system_clock::now();
|
||||
for (const auto & name_and_info : infos)
|
||||
{
|
||||
const auto & info = name_and_info.second;
|
||||
if ((now >= info.next_update_time) && !info.loading() && info.was_loading())
|
||||
if ((now >= info.next_update_time) && !info.loading() && info.loaded())
|
||||
is_modified_map.emplace(info.object, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// The `mutex` should be unlocked while we're calling the function is_object_modified().
|
||||
/// Find out which of the loaded objects were modified.
|
||||
/// We couldn't perform these checks while we were building `is_modified_map` because
|
||||
/// the `mutex` should be unlocked while we're calling the function is_object_modified().
|
||||
for (auto & [object, is_modified_flag] : is_modified_map)
|
||||
{
|
||||
try
|
||||
@ -554,21 +558,38 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate through all the objects again and either start loading or just set `next_update_time`.
|
||||
{
|
||||
std::lock_guard lock{mutex};
|
||||
TimePoint now = std::chrono::system_clock::now();
|
||||
for (auto & [name, info] : infos)
|
||||
if ((now >= info.next_update_time) && !info.loading() && info.was_loading())
|
||||
{
|
||||
if ((now >= info.next_update_time) && !info.loading())
|
||||
{
|
||||
auto it = is_modified_map.find(info.object);
|
||||
if (it == is_modified_map.end())
|
||||
continue; /// Object has been just added, it can be simply omitted from this update of outdated.
|
||||
bool is_modified_flag = it->second;
|
||||
if (info.loaded() && !is_modified_flag)
|
||||
info.next_update_time = calculate_next_update_time(info.object, info.error_count);
|
||||
else
|
||||
if (info.loaded())
|
||||
{
|
||||
auto it = is_modified_map.find(info.object);
|
||||
if (it == is_modified_map.end())
|
||||
continue; /// Object has been just loaded (it wasn't loaded while we were building the map `is_modified_map`), so we don't have to reload it right now.
|
||||
|
||||
bool is_modified_flag = it->second;
|
||||
if (!is_modified_flag)
|
||||
{
|
||||
/// Object wasn't modified so we only have to set `next_update_time`.
|
||||
info.next_update_time = calculate_next_update_time(info.object, info.error_count);
|
||||
continue;
|
||||
}
|
||||
|
||||
/// Object was modified and should be reloaded.
|
||||
startLoading(name, info);
|
||||
}
|
||||
else if (info.failed())
|
||||
{
|
||||
/// Object was never loaded successfully and should be reloaded.
|
||||
startLoading(name, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user