ClickHouse/dbms/include/DB/Interpreters/Quota.h
2013-08-12 00:36:18 +00:00

152 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <string.h>
#include <tr1/unordered_map>
#include <Poco/Timespan.h>
#include <Poco/Util/Application.h>
#include <Poco/Util/AbstractConfiguration.h>
#include <Poco/Net/IPAddress.h>
#include <Yandex/Common.h>
#include <DB/Core/Types.h>
#include <DB/Core/Exception.h>
#include <DB/Core/ErrorCodes.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/Common/SipHash.h>
namespace DB
{
/** Квота на потребление ресурсов за заданный интервал - часть настроек.
* Используются, чтобы ограничить потребление ресурсов пользователем.
* Квота действует "мягко" - может быть немного превышена, так как проверяется, как правило, на каждый блок.
* Квота не сохраняется при перезапуске сервера.
* Квота распространяется только на один сервер.
*/
/// Используется как для максимальных значений, так и в качестве счётчика накопившихся значений.
struct QuotaValues
{
/// Нули в качестве ограничений означают "не ограничено".
size_t queries; /// Количество запросов.
size_t errors; /// Количество запросов с эксепшенами.
size_t result_rows; /// Количество строк, отданных в качестве результата.
size_t read_rows; /// Количество строк, прочитанных из таблиц.
Poco::Timespan execution_time; /// Суммарное время выполнения запросов.
QuotaValues()
{
clear();
}
void clear()
{
memset(this, 0, sizeof(*this));
}
void initFromConfig(const String & config_elem);
};
/// Время, округлённое до границы интервала, квота за интервал и накопившиеся за этот интервал значения.
struct QuotaForInterval
{
time_t rounded_time;
size_t duration;
QuotaValues max;
QuotaValues used;
QuotaForInterval() : rounded_time() {}
QuotaForInterval(time_t duration_) : duration(duration_) {}
void initFromConfig(const String & config_elem, time_t duration_);
/// Увеличить соответствующее значение.
void addQuery(time_t current_time, const String & quota_name);
void addError(time_t current_time, const String & quota_name);
/// Проверить, не превышена ли квота уже. Если превышена - кидает исключение.
void checkExceeded(time_t current_time, const String & quota_name);
/// Проверить соответствующее значение. Если превышено - кинуть исключение. Иначе - увеличить его.
void checkAndAddResultRows(time_t current_time, const String & quota_name, size_t ammount);
void checkAndAddReadRows(time_t current_time, const String & quota_name, size_t ammount);
void checkAndAddExecutionTime(time_t current_time, const String & quota_name, Poco::Timespan ammount);
private:
/// Сбросить счётчик использованных ресурсов, если соответствующий интервал, за который считается квота, прошёл.
void updateTime(time_t current_time);
void check(size_t max_ammount, size_t used_ammount, time_t current_time, const String & quota_name, const char * resource_name);
};
struct Quota;
/// Длина интервала -> квота и накопившиеся за текущий интервал такой длины значения (например, 3600 -> значения за текущий час).
class QuotaForIntervals
{
private:
/// При проверке, будем обходить интервалы в порядке, обратном величине - от самого большого до самого маленького.
typedef std::map<size_t, QuotaForInterval> Container;
Container cont;
Quota * parent;
public:
QuotaForIntervals(Quota * parent_) : parent(parent_) {}
void initFromConfig(const String & config_elem);
void addQuery(time_t current_time);
void addError(time_t current_time);
void checkExceeded(time_t current_time);
void checkAndAddResultRows(time_t current_time, size_t ammount);
void checkAndAddReadRows(time_t current_time, size_t ammount);
void checkAndAddExecutionTime(time_t current_time, Poco::Timespan ammount);
};
/// Ключ квоты -> квоты за интервалы. Если квота не допускает ключей, то накопленные значения хранятся по ключу 0.
struct Quota
{
typedef std::tr1::unordered_map<UInt64, QuotaForIntervals> Container;
String name;
/// Максимальные значения из конфига.
QuotaForIntervals max;
/// Максимальные и накопленные значения для разных ключей.
Container quota_for_keys;
Poco::FastMutex mutex;
bool is_keyed;
bool keyed_by_ip;
Quota() : max(this), is_keyed(false), keyed_by_ip(false) {}
void initFromConfig(const String & config_elem, const String & name_);
QuotaForIntervals & get(const String & quota_key, const Poco::Net::IPAddress & ip);
};
class Quotas
{
private:
/// Имя квоты -> квоты.
typedef std::tr1::unordered_map<String, SharedPtr<Quota> > Container;
Container cont;
public:
void initFromConfig();
QuotaForIntervals & get(const String & name, const String & quota_key, const Poco::Net::IPAddress & ip);
};
}