ClickHouse/src/Storages/MergeTree/ActiveDataPartSet.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

190 lines
5.1 KiB
C++
Raw Normal View History

#include <Storages/MergeTree/ActiveDataPartSet.h>
2021-05-13 11:29:59 +00:00
#include <Common/Exception.h>
2022-04-27 15:05:45 +00:00
#include <Common/logger_useful.h>
#include <algorithm>
2021-06-01 13:25:23 +00:00
#include <cassert>
namespace DB
{
2021-07-01 12:12:27 +00:00
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
2021-05-13 11:29:59 +00:00
ActiveDataPartSet::ActiveDataPartSet(MergeTreeDataFormatVersion format_version_, const Strings & names)
: format_version(format_version_)
{
for (const auto & name : names)
add(name);
}
2021-06-30 12:29:09 +00:00
bool ActiveDataPartSet::add(const String & name, Strings * out_replaced_parts)
{
auto part_info = MergeTreePartInfo::fromPartName(name, format_version);
2022-12-22 13:31:42 +00:00
return add(part_info, name, out_replaced_parts);
}
2022-12-22 13:31:42 +00:00
bool ActiveDataPartSet::add(const MergeTreePartInfo & part_info, const String & name, Strings * out_replaced_parts)
{
/// TODO make it exception safe (out_replaced_parts->push_back(...) may throw)
if (getContainingPartImpl(part_info) != part_info_to_name.end())
return false;
2017-08-15 16:21:13 +00:00
/// Parts contained in `part` are located contiguously in `part_info_to_name`, overlapping with the place where the part itself would be inserted.
auto it = part_info_to_name.lower_bound(part_info);
if (out_replaced_parts)
out_replaced_parts->clear();
2017-03-13 18:01:46 +00:00
/// Let's go left.
while (it != part_info_to_name.begin())
{
--it;
if (!part_info.contains(it->first))
{
2021-05-13 11:29:59 +00:00
if (!part_info.isDisjoint(it->first))
throw Exception(ErrorCodes::LOGICAL_ERROR, "Part {} intersects previous part {}. It is a bug or a result of manual intervention in the ZooKeeper data.", part_info.getPartNameForLogs(), it->first.getPartNameForLogs());
++it;
break;
}
if (out_replaced_parts)
out_replaced_parts->push_back(it->second);
2021-12-20 10:42:31 +00:00
it = part_info_to_name.erase(it);
}
if (out_replaced_parts)
std::reverse(out_replaced_parts->begin(), out_replaced_parts->end());
2017-03-13 18:01:46 +00:00
/// Let's go to the right.
while (it != part_info_to_name.end() && part_info.contains(it->first))
{
2021-06-01 13:25:23 +00:00
assert(part_info != it->first);
if (out_replaced_parts)
out_replaced_parts->push_back(it->second);
2021-12-20 10:42:31 +00:00
it = part_info_to_name.erase(it);
}
2021-05-13 11:29:59 +00:00
if (it != part_info_to_name.end() && !part_info.isDisjoint(it->first))
2022-12-20 21:44:27 +00:00
throw Exception(ErrorCodes::LOGICAL_ERROR, "Part {} intersects part {}. It is a bug or a result of manual intervention in the ZooKeeper data.", name, it->first.getPartNameForLogs());
2021-05-13 11:29:59 +00:00
part_info_to_name.emplace(part_info, name);
return true;
2022-12-22 13:31:42 +00:00
}
bool ActiveDataPartSet::add(const MergeTreePartInfo & part_info, Strings * out_replaced_parts)
{
return add(part_info, part_info.getPartNameAndCheckFormat(format_version), out_replaced_parts);
}
String ActiveDataPartSet::getContainingPart(const MergeTreePartInfo & part_info) const
{
auto it = getContainingPartImpl(part_info);
if (it != part_info_to_name.end())
return it->second;
return {};
}
String ActiveDataPartSet::getContainingPart(const String & name) const
{
auto it = getContainingPartImpl(MergeTreePartInfo::fromPartName(name, format_version));
if (it != part_info_to_name.end())
return it->second;
return {};
2016-06-08 13:08:20 +00:00
}
std::map<MergeTreePartInfo, String>::const_iterator
ActiveDataPartSet::getContainingPartImpl(const MergeTreePartInfo & part_info) const
2016-06-08 13:08:20 +00:00
{
2017-08-15 16:21:13 +00:00
/// A part can only be covered/overlapped by the previous or next one in `part_info_to_name`.
auto it = part_info_to_name.lower_bound(part_info);
if (it != part_info_to_name.end())
{
if (it->first.contains(part_info))
return it;
}
if (it != part_info_to_name.begin())
{
--it;
if (it->first.contains(part_info))
return it;
}
return part_info_to_name.end();
}
Strings ActiveDataPartSet::getPartsCoveredBy(const MergeTreePartInfo & part_info) const
{
auto it_middle = part_info_to_name.lower_bound(part_info);
auto begin = it_middle;
while (begin != part_info_to_name.begin())
{
auto prev = std::prev(begin);
if (!part_info.contains(prev->first))
{
if (prev->first.contains(part_info))
return {};
break;
}
begin = prev;
}
auto end = it_middle;
while (end != part_info_to_name.end())
{
if (!part_info.contains(end->first))
{
if (end->first.contains(part_info))
return {};
break;
}
++end;
}
Strings covered;
for (auto it = begin; it != end; ++it)
covered.push_back(it->second);
return covered;
}
Strings ActiveDataPartSet::getParts() const
{
Strings res;
res.reserve(part_info_to_name.size());
for (const auto & kv : part_info_to_name)
res.push_back(kv.second);
return res;
}
std::vector<MergeTreePartInfo> ActiveDataPartSet::getPartInfos() const
{
std::vector<MergeTreePartInfo> res;
res.reserve(part_info_to_name.size());
for (const auto & kv : part_info_to_name)
res.push_back(kv.first);
return res;
}
size_t ActiveDataPartSet::size() const
{
return part_info_to_name.size();
}
}