Merge pull request #37980 from ClickHouse/more_strict_num_children_check

Add checks for numChildren in Keeper
This commit is contained in:
alesapin 2022-06-12 11:55:12 +02:00 committed by GitHub
commit 18a0b58ee7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 4 deletions

View File

@ -405,7 +405,7 @@ void Changelog::readChangelogAndInitWriter(uint64_t last_commited_log_index, uin
if (last_log_read_result->last_read_index == 0 || last_log_read_result->error) /// If it's broken log then remove it if (last_log_read_result->last_read_index == 0 || last_log_read_result->error) /// If it's broken log then remove it
{ {
LOG_INFO(log, "Removing log {} because it's empty or read finished with error", description.path); LOG_INFO(log, "Removing chagelog {} because it's empty or read finished with error", description.path);
std::filesystem::remove(description.path); std::filesystem::remove(description.path);
existing_changelogs.erase(last_log_read_result->log_start_index); existing_changelogs.erase(last_log_read_result->log_start_index);
std::erase_if(logs, [last_log_read_result] (const auto & item) { return item.first >= last_log_read_result->log_start_index; }); std::erase_if(logs, [last_log_read_result] (const auto & item) { return item.first >= last_log_read_result->log_start_index; });

View File

@ -12,6 +12,7 @@
#include <Coordination/pathUtils.h> #include <Coordination/pathUtils.h>
#include <filesystem> #include <filesystem>
#include <memory> #include <memory>
#include <Common/logger_useful.h>
namespace DB namespace DB
{ {
@ -20,6 +21,7 @@ namespace ErrorCodes
{ {
extern const int UNKNOWN_FORMAT_VERSION; extern const int UNKNOWN_FORMAT_VERSION;
extern const int UNKNOWN_SNAPSHOT; extern const int UNKNOWN_SNAPSHOT;
extern const int LOGICAL_ERROR;
} }
namespace namespace
@ -296,6 +298,25 @@ void KeeperStorageSnapshot::deserialize(SnapshotDeserializationResult & deserial
} }
} }
for (const auto & itr : storage.container)
{
if (itr.key != "/")
{
if (itr.value.stat.numChildren != static_cast<int32_t>(itr.value.getChildren().size()))
{
#ifdef NDEBUG
/// TODO (alesapin) remove this, it should be always CORRUPTED_DATA.
LOG_ERROR(&Poco::Logger::get("KeeperSnapshotManager"), "Children counter in stat.numChildren {}"
" is different from actual children size {} for node {}", itr.value.stat.numChildren, itr.value.getChildren().size(), itr.key);
#else
throw Exception(ErrorCodes::LOGICAL_ERROR, "Children counter in stat.numChildren {}"
" is different from actual children size {} for node {}", itr.value.stat.numChildren, itr.value.getChildren().size(), itr.key);
#endif
}
}
}
size_t active_sessions_size; size_t active_sessions_size;
readBinary(active_sessions_size, in); readBinary(active_sessions_size, in);

View File

@ -13,7 +13,7 @@
#include <iomanip> #include <iomanip>
#include <mutex> #include <mutex>
#include <functional> #include <functional>
#include <Common/logger_useful.h> #include <base/defines.h>
namespace DB namespace DB
{ {
@ -349,7 +349,9 @@ struct KeeperStorageCreateRequestProcessor final : public KeeperStorageRequestPr
container.updateValue(parent_path, [child_path, zxid, &prev_parent_zxid, container.updateValue(parent_path, [child_path, zxid, &prev_parent_zxid,
parent_cversion, &prev_parent_cversion] (KeeperStorage::Node & parent) parent_cversion, &prev_parent_cversion] (KeeperStorage::Node & parent)
{ {
++parent.stat.numChildren;
parent.addChild(child_path); parent.addChild(child_path);
prev_parent_cversion = parent.stat.cversion; prev_parent_cversion = parent.stat.cversion;
prev_parent_zxid = parent.stat.pzxid; prev_parent_zxid = parent.stat.pzxid;
@ -363,7 +365,7 @@ struct KeeperStorageCreateRequestProcessor final : public KeeperStorageRequestPr
if (zxid > parent.stat.pzxid) if (zxid > parent.stat.pzxid)
parent.stat.pzxid = zxid; parent.stat.pzxid = zxid;
++parent.stat.numChildren; chassert(parent.stat.numChildren == static_cast<int32_t>(parent.getChildren().size()));
}); });
response.path_created = path_created; response.path_created = path_created;
@ -385,6 +387,7 @@ struct KeeperStorageCreateRequestProcessor final : public KeeperStorageRequestPr
undo_parent.stat.cversion = prev_parent_cversion; undo_parent.stat.cversion = prev_parent_cversion;
undo_parent.stat.pzxid = prev_parent_zxid; undo_parent.stat.pzxid = prev_parent_zxid;
undo_parent.removeChild(child_path); undo_parent.removeChild(child_path);
chassert(undo_parent.stat.numChildren == static_cast<int32_t>(undo_parent.getChildren().size()));
}); });
storage.container.erase(path_created); storage.container.erase(path_created);
@ -494,7 +497,7 @@ struct KeeperStorageRemoveRequestProcessor final : public KeeperStorageRequestPr
{ {
response.error = Coordination::Error::ZBADVERSION; response.error = Coordination::Error::ZBADVERSION;
} }
else if (it->value.stat.numChildren) else if (!it->value.getChildren().empty())
{ {
response.error = Coordination::Error::ZNOTEMPTY; response.error = Coordination::Error::ZNOTEMPTY;
} }
@ -519,6 +522,7 @@ struct KeeperStorageRemoveRequestProcessor final : public KeeperStorageRequestPr
--parent.stat.numChildren; --parent.stat.numChildren;
++parent.stat.cversion; ++parent.stat.cversion;
parent.removeChild(child_basename); parent.removeChild(child_basename);
chassert(parent.stat.numChildren == static_cast<int32_t>(parent.getChildren().size()));
}); });
response.error = Coordination::Error::ZOK; response.error = Coordination::Error::ZOK;
@ -540,6 +544,7 @@ struct KeeperStorageRemoveRequestProcessor final : public KeeperStorageRequestPr
++parent.stat.numChildren; ++parent.stat.numChildren;
--parent.stat.cversion; --parent.stat.cversion;
parent.addChild(child_name); parent.addChild(child_name);
chassert(parent.stat.numChildren == static_cast<int32_t>(parent.getChildren().size()));
}); });
}; };
} }
@ -1110,6 +1115,7 @@ KeeperStorage::ResponsesForSessions KeeperStorage::processRequest(const Coordina
++parent.stat.cversion; ++parent.stat.cversion;
auto base_name = getBaseName(ephemeral_path); auto base_name = getBaseName(ephemeral_path);
parent.removeChild(base_name); parent.removeChild(base_name);
chassert(parent.stat.numChildren == static_cast<int32_t>(parent.getChildren().size()));
}); });
container.erase(ephemeral_path); container.erase(ephemeral_path);