dbms: added fault injection in memory tracker to more easily reproducing the bug [#METR-19278].

This commit is contained in:
Alexey Milovidov 2015-12-23 10:39:28 +03:00
parent 8da3abcd94
commit d51e03da61
5 changed files with 28 additions and 2 deletions

View File

@ -13,6 +13,9 @@ class MemoryTracker
Int64 peak = 0;
Int64 limit = 0;
/// В целях тестирования exception safety - кидать исключение при каждом выделении памяти с указанной вероятностью.
double fault_probability = 0;
public:
MemoryTracker(Int64 limit_) : limit(limit_) {}
@ -43,6 +46,11 @@ public:
{
return peak;
}
void setFaultProbability(double value)
{
fault_probability = value;
}
};

View File

@ -48,11 +48,14 @@ struct ProcessListElement
ProcessListElement(const String & query_, const String & user_,
const String & query_id_, const Poco::Net::IPAddress & ip_address_,
size_t max_memory_usage, QueryPriorities::Handle && priority_handle_)
size_t max_memory_usage, double memory_tracker_fault_probability, QueryPriorities::Handle && priority_handle_)
: query(query_), user(user_), query_id(query_id_), ip_address(ip_address_), memory_tracker(max_memory_usage),
priority_handle(std::move(priority_handle_))
{
current_memory_tracker = &memory_tracker;
if (memory_tracker_fault_probability)
memory_tracker.setFaultProbability(memory_tracker_fault_probability);
}
~ProcessListElement()

View File

@ -188,6 +188,9 @@ struct Settings
M(SettingMilliseconds, read_backoff_min_interval_between_events_ms, 1000) \
/** Количество событий, после которого количество потоков будет уменьшено. */ \
M(SettingUInt64, read_backoff_min_events, 2) \
\
/** В целях тестирования exception safety - кидать исключение при каждом выделении памяти с указанной вероятностью. */ \
M(SettingFloat, memory_tracker_fault_probability, 0.) \
/// Всевозможные ограничения на выполнение запроса.
Limits limits;

View File

@ -17,6 +17,16 @@ void MemoryTracker::alloc(Int64 size)
{
Int64 will_be = __sync_add_and_fetch(&amount, size);
/// Используется непотокобезопасный генератор случайных чисел. Совместное распределение в разных потоках не будет равномерным.
/// В данном случае, это нормально.
if (unlikely(fault_probability && drand48() < fault_probability))
{
free(size);
throw DB::Exception("Memory tracker: fault injected. Would use " + formatReadableSizeWithBinarySuffix(will_be) + ""
" (attempt to allocate chunk of " + DB::toString(size) + " bytes)"
", maximum: " + formatReadableSizeWithBinarySuffix(limit), DB::ErrorCodes::MEMORY_LIMIT_EXCEEDED);
}
if (unlikely(limit && will_be > limit))
{
free(size);

View File

@ -45,7 +45,9 @@ ProcessList::EntryPtr ProcessList::insert(
++cur_size;
res.reset(new Entry(*this, cont.emplace(cont.end(),
query_, user_, query_id_, ip_address_, settings.limits.max_memory_usage, priorities.insert(settings.priority))));
query_, user_, query_id_, ip_address_,
settings.limits.max_memory_usage, settings.memory_tracker_fault_probability,
priorities.insert(settings.priority))));
if (!query_id_.empty())
user_to_queries[user_][query_id_] = &res->get();