ClickHouse/dbms/src/Storages/MergeTree/ActiveDataPartSet.cpp

162 lines
4.1 KiB
C++
Raw Normal View History

#include <DB/Storages/MergeTree/ActiveDataPartSet.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/IO/ReadHelpers.h>
#include <Yandex/time2str.h>
namespace DB
{
ActiveDataPartSet::ActiveDataPartSet() {}
void ActiveDataPartSet::add(const String & name)
{
Poco::ScopedLock<Poco::Mutex> lock(mutex);
if (getContainingPart(name) != "")
return;
Part part;
part.name = name;
parsePartName(name, part);
/// Куски, содержащиеся в part, идут в data_parts подряд, задевая место, куда вставился бы сам part.
Parts::iterator it = parts.lower_bound(part);
/// Пойдем влево.
while (it != parts.begin())
{
--it;
if (!part.contains(*it))
{
++it;
break;
}
parts.erase(it++);
}
/// Пойдем вправо.
while (it != parts.end() && part.contains(*it))
{
parts.erase(it++);
}
parts.insert(part);
}
2014-05-26 18:14:52 +00:00
String ActiveDataPartSet::getContainingPart(const String & part_name) const
{
Poco::ScopedLock<Poco::Mutex> lock(mutex);
Part part;
parsePartName(part_name, part);
/// Кусок может покрываться только предыдущим или следующим в parts.
Parts::iterator it = parts.lower_bound(part);
if (it != parts.end())
{
if (it->name == part_name)
return it->name;
if (it->contains(part))
return it->name;
}
if (it != parts.begin())
{
--it;
if (it->contains(part))
return it->name;
}
return "";
}
2014-05-26 18:14:52 +00:00
Strings ActiveDataPartSet::getParts() const
{
Poco::ScopedLock<Poco::Mutex> lock(mutex);
Strings res;
for (const Part & part : parts)
{
res.push_back(part.name);
}
return res;
}
2014-08-08 08:28:13 +00:00
size_t ActiveDataPartSet::size() const
{
Poco::ScopedLock<Poco::Mutex> lock(mutex);
return parts.size();
}
String ActiveDataPartSet::getPartName(DayNum_t left_date, DayNum_t right_date, UInt64 left_id, UInt64 right_id, UInt64 level)
{
2014-07-08 23:52:53 +00:00
DateLUT & date_lut = DateLUT::instance();
/// Имя директории для куска иммет вид: YYYYMMDD_YYYYMMDD_N_N_L.
String res;
{
unsigned left_date_id = Date2OrderedIdentifier(date_lut.fromDayNum(left_date));
unsigned right_date_id = Date2OrderedIdentifier(date_lut.fromDayNum(right_date));
WriteBufferFromString wb(res);
writeIntText(left_date_id, wb);
writeChar('_', wb);
writeIntText(right_date_id, wb);
writeChar('_', wb);
writeIntText(left_id, wb);
writeChar('_', wb);
writeIntText(right_id, wb);
writeChar('_', wb);
writeIntText(level, wb);
}
return res;
}
2014-08-08 08:28:13 +00:00
bool ActiveDataPartSet::isPartDirectory(const String & dir_name, Poco::RegularExpression::MatchVec * out_matches)
{
2014-08-08 08:28:13 +00:00
Poco::RegularExpression::MatchVec matches;
static Poco::RegularExpression file_name_regexp("^(\\d{8})_(\\d{8})_(\\d+)_(\\d+)_(\\d+)");
2014-08-08 08:28:13 +00:00
bool res = (file_name_regexp.match(dir_name, 0, matches) && 6 == matches.size());
if (out_matches)
*out_matches = matches;
return res;
}
void ActiveDataPartSet::parsePartName(const String & file_name, Part & part, const Poco::RegularExpression::MatchVec * matches_p)
{
Poco::RegularExpression::MatchVec match_vec;
if (!matches_p)
{
2014-08-08 08:28:13 +00:00
if (!isPartDirectory(file_name, &match_vec))
throw Exception("Unexpected part name: " + file_name, ErrorCodes::BAD_DATA_PART_NAME);
matches_p = &match_vec;
}
const Poco::RegularExpression::MatchVec & matches = *matches_p;
2014-07-08 23:52:53 +00:00
DateLUT & date_lut = DateLUT::instance();
part.left_date = date_lut.toDayNum(OrderedIdentifier2Date(file_name.substr(matches[1].offset, matches[1].length)));
part.right_date = date_lut.toDayNum(OrderedIdentifier2Date(file_name.substr(matches[2].offset, matches[2].length)));
part.left = parse<UInt64>(file_name.substr(matches[3].offset, matches[3].length));
part.right = parse<UInt64>(file_name.substr(matches[4].offset, matches[4].length));
part.level = parse<UInt32>(file_name.substr(matches[5].offset, matches[5].length));
part.left_month = date_lut.toFirstDayNumOfMonth(part.left_date);
part.right_month = date_lut.toFirstDayNumOfMonth(part.right_date);
}
2014-07-22 13:49:52 +00:00
bool ActiveDataPartSet::contains(const String & outer_part_name, const String & inner_part_name)
{
Part outer, inner;
parsePartName(outer_part_name, outer);
parsePartName(inner_part_name, inner);
return outer.contains(inner);
}
}