2021-10-27 21:54:06 +00:00
|
|
|
#include "MarkRange.h"
|
|
|
|
|
2023-02-03 13:34:18 +00:00
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
|
2021-10-27 21:54:06 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2021-12-09 10:39:28 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int LOGICAL_ERROR;
|
|
|
|
}
|
|
|
|
|
2023-02-03 13:34:18 +00:00
|
|
|
size_t MarkRange::getNumberOfMarks() const
|
|
|
|
{
|
|
|
|
return end - begin;
|
|
|
|
}
|
|
|
|
|
2021-12-09 10:39:28 +00:00
|
|
|
bool MarkRange::operator==(const MarkRange & rhs) const
|
|
|
|
{
|
|
|
|
return begin == rhs.begin && end == rhs.end;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MarkRange::operator<(const MarkRange & rhs) const
|
|
|
|
{
|
|
|
|
/// We allow only consecutive non-intersecting ranges
|
|
|
|
/// Here we check whether a beginning of one range lies inside another range
|
|
|
|
/// (ranges are intersect)
|
2023-01-24 22:56:26 +00:00
|
|
|
if (this != &rhs)
|
|
|
|
{
|
|
|
|
const bool is_intersection = (begin <= rhs.begin && rhs.begin < end) ||
|
|
|
|
(rhs.begin <= begin && begin < rhs.end);
|
2021-12-09 10:39:28 +00:00
|
|
|
|
2023-01-24 22:56:26 +00:00
|
|
|
if (is_intersection)
|
|
|
|
throw Exception(
|
|
|
|
ErrorCodes::LOGICAL_ERROR,
|
|
|
|
"Intersecting mark ranges are not allowed, it is a bug! "
|
|
|
|
"First range ({}, {}), second range ({}, {})",
|
|
|
|
begin, end, rhs.begin, rhs.end);
|
|
|
|
}
|
2021-12-09 10:39:28 +00:00
|
|
|
|
|
|
|
return begin < rhs.begin && end <= rhs.begin;
|
|
|
|
}
|
|
|
|
|
2021-10-27 21:54:06 +00:00
|
|
|
size_t getLastMark(const MarkRanges & ranges)
|
|
|
|
{
|
|
|
|
size_t current_task_last_mark = 0;
|
|
|
|
for (const auto & mark_range : ranges)
|
|
|
|
current_task_last_mark = std::max(current_task_last_mark, mark_range.end);
|
|
|
|
return current_task_last_mark;
|
|
|
|
}
|
|
|
|
|
2022-09-05 16:55:00 +00:00
|
|
|
std::string toString(const MarkRanges & ranges)
|
|
|
|
{
|
|
|
|
std::string result;
|
|
|
|
for (const auto & mark_range : ranges)
|
|
|
|
{
|
|
|
|
if (!result.empty())
|
|
|
|
result += ", ";
|
|
|
|
result += "(" + std::to_string(mark_range.begin) + ", " + std::to_string(mark_range.end) + ")";
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-01-24 22:56:26 +00:00
|
|
|
void assertSortedAndNonIntersecting(const MarkRanges & ranges)
|
|
|
|
{
|
|
|
|
MarkRanges ranges_copy(ranges.begin(), ranges.end());
|
|
|
|
/// Should also throw an exception if interseting range is found during comparison.
|
|
|
|
std::sort(ranges_copy.begin(), ranges_copy.end());
|
|
|
|
if (ranges_copy != ranges)
|
|
|
|
throw Exception(
|
|
|
|
ErrorCodes::LOGICAL_ERROR, "Expected sorted and non intersecting ranges. Ranges: {}",
|
|
|
|
toString(ranges));
|
|
|
|
}
|
|
|
|
|
2023-02-03 13:34:18 +00:00
|
|
|
size_t MarkRanges::getNumberOfMarks() const
|
|
|
|
{
|
|
|
|
size_t result = 0;
|
|
|
|
for (const auto & mark : *this)
|
|
|
|
result += mark.getNumberOfMarks();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MarkRanges::serialize(WriteBuffer & out) const
|
|
|
|
{
|
2023-06-22 03:15:12 +00:00
|
|
|
writeBinaryLittleEndian(this->size(), out);
|
2023-02-03 13:34:18 +00:00
|
|
|
|
|
|
|
for (const auto & [begin, end] : *this)
|
|
|
|
{
|
2023-06-22 03:15:12 +00:00
|
|
|
writeBinaryLittleEndian(begin, out);
|
|
|
|
writeBinaryLittleEndian(end, out);
|
2023-02-03 13:34:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
String MarkRanges::describe() const
|
|
|
|
{
|
|
|
|
return fmt::format("Size: {}, Data: {}", this->size(), fmt::join(*this, ","));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MarkRanges::deserialize(ReadBuffer & in)
|
|
|
|
{
|
|
|
|
size_t size = 0;
|
2023-06-22 03:15:12 +00:00
|
|
|
readBinaryLittleEndian(size, in);
|
2023-02-03 13:34:18 +00:00
|
|
|
|
|
|
|
this->resize(size);
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
2023-06-22 03:15:12 +00:00
|
|
|
readBinaryLittleEndian((*this)[i].begin, in);
|
|
|
|
readBinaryLittleEndian((*this)[i].end, in);
|
2023-02-03 13:34:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-27 21:54:06 +00:00
|
|
|
}
|