mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
Store only root system node
This commit is contained in:
parent
7d30ab80c4
commit
75476d5110
@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <IO/WriteHelpers.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
const std::string keeper_system_path = "/keeper";
|
||||
const std::string keeper_api_version_path = keeper_system_path + "/api_version";
|
||||
|
||||
enum class KeeperApiVersion : uint8_t
|
||||
{
|
||||
V0 = 0, // ZooKeeper compatible version
|
||||
@ -14,4 +13,13 @@ enum class KeeperApiVersion : uint8_t
|
||||
|
||||
inline constexpr auto current_keeper_api_version = KeeperApiVersion::V1;
|
||||
|
||||
const std::string keeper_system_path = "/keeper";
|
||||
const std::string keeper_api_version_path = keeper_system_path + "/api_version";
|
||||
|
||||
using PathWithData = std::pair<std::string_view, std::string>;
|
||||
const std::vector<PathWithData> data_for_system_paths
|
||||
{
|
||||
{keeper_api_version_path, toString(static_cast<uint8_t>(current_keeper_api_version))}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -145,6 +145,16 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool isChildSystemPath(const std::string_view path)
|
||||
{
|
||||
auto [first_it, second_it] = std::mismatch(path.begin(), path.end(), keeper_system_path.begin(), keeper_system_path.end());
|
||||
return first_it != path.end() && *first_it == '/' && second_it == keeper_system_path.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void KeeperStorageSnapshot::serialize(const KeeperStorageSnapshot & snapshot, WriteBuffer & out)
|
||||
{
|
||||
@ -183,11 +193,16 @@ void KeeperStorageSnapshot::serialize(const KeeperStorageSnapshot & snapshot, Wr
|
||||
}
|
||||
|
||||
/// Serialize data tree
|
||||
writeBinary(snapshot.snapshot_container_size, out);
|
||||
writeBinary(snapshot.snapshot_container_size - data_for_system_paths.size(), out);
|
||||
size_t counter = 0;
|
||||
for (auto it = snapshot.begin; counter < snapshot.snapshot_container_size; ++counter)
|
||||
{
|
||||
const auto & path = it->key;
|
||||
|
||||
// write only the root system path because of digest
|
||||
if (isChildSystemPath(path.toView()))
|
||||
continue;
|
||||
|
||||
const auto & node = it->value;
|
||||
|
||||
/// Benign race condition possible while taking snapshot: NuRaft decide to create snapshot at some log id
|
||||
|
@ -244,39 +244,46 @@ void KeeperStorage::initializeSystemNodes()
|
||||
if (initialized)
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "KeeperStorage system nodes initialized twice");
|
||||
|
||||
const auto create_system_node = [&](const auto & path, auto data)
|
||||
// insert root system path
|
||||
Node system_node;
|
||||
system_node.setData("");
|
||||
container.insertOrReplace(keeper_system_path, system_node);
|
||||
// store digest for the empty node because we won't update
|
||||
// its stats
|
||||
addDigest(system_node, keeper_system_path);
|
||||
|
||||
// update root and the digest based on it
|
||||
auto current_root_it = container.find("/");
|
||||
assert(current_root_it != container.end());
|
||||
removeDigest(current_root_it->value, "/");
|
||||
auto updated_root_it = container.updateValue(
|
||||
"/",
|
||||
[](auto & node)
|
||||
{
|
||||
auto node_it = container.find(path);
|
||||
if (node_it == container.end())
|
||||
{
|
||||
// we update numChildren during preprocessing so and createNode is called during
|
||||
// commit so we need to update it manually here
|
||||
container.updateValue(
|
||||
parentPath(path),
|
||||
[](KeeperStorage::Node & parent)
|
||||
{
|
||||
++parent.stat.numChildren;
|
||||
++node.stat.numChildren;
|
||||
node.addChild(keeper_system_path);
|
||||
}
|
||||
);
|
||||
createNode(path, std::move(data), {}, false, {});
|
||||
}
|
||||
else
|
||||
{
|
||||
container.updateValue(
|
||||
path,
|
||||
[data = std::move(data)](KeeperStorage::Node & node)
|
||||
{
|
||||
node.setData(std::move(data));
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
create_system_node(keeper_system_path, "");
|
||||
addDigest(updated_root_it->value, "/");
|
||||
|
||||
// insert child system nodes
|
||||
for (const auto & [path, data] : data_for_system_paths)
|
||||
{
|
||||
assert(keeper_api_version_path.starts_with(keeper_system_path));
|
||||
auto api_version_data = toString(static_cast<uint8_t>(current_keeper_api_version));
|
||||
create_system_node(keeper_api_version_path, std::move(api_version_data));
|
||||
Node child_system_node;
|
||||
system_node.setData(data);
|
||||
auto [map_key, _] = container.insert(std::string{path}, child_system_node);
|
||||
/// Take child path from key owned by map.
|
||||
auto child_path = getBaseName(map_key->getKey());
|
||||
container.updateValue(
|
||||
parentPath(child_path),
|
||||
[child_path](auto & parent)
|
||||
{
|
||||
// don't update stats so digest is okay
|
||||
parent.addChild(child_path);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user