2013-09-03 20:21:28 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2014-02-12 17:31:02 +00:00
|
|
|
|
#include <map>
|
2013-09-03 20:21:28 +00:00
|
|
|
|
#include <list>
|
2015-06-21 06:06:04 +00:00
|
|
|
|
#include <memory>
|
2013-09-07 04:54:59 +00:00
|
|
|
|
#include <Poco/Mutex.h>
|
|
|
|
|
#include <Poco/Condition.h>
|
2013-11-03 05:32:42 +00:00
|
|
|
|
#include <Poco/Net/IPAddress.h>
|
2013-09-03 20:21:28 +00:00
|
|
|
|
#include <statdaemons/Stopwatch.h>
|
2013-09-07 04:54:59 +00:00
|
|
|
|
#include <DB/Core/Defines.h>
|
2014-10-25 18:33:52 +00:00
|
|
|
|
#include <DB/Core/Progress.h>
|
2013-09-03 20:21:28 +00:00
|
|
|
|
#include <DB/Core/Exception.h>
|
|
|
|
|
#include <DB/Core/ErrorCodes.h>
|
2014-05-03 22:57:43 +00:00
|
|
|
|
#include <DB/Common/MemoryTracker.h>
|
2013-09-03 20:21:28 +00:00
|
|
|
|
#include <DB/IO/WriteHelpers.h>
|
2015-06-21 06:06:04 +00:00
|
|
|
|
#include <DB/Interpreters/QueryPriorities.h>
|
2015-09-04 20:52:00 +00:00
|
|
|
|
#include <DB/Storages/IStorage.h>
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/** Список исполняющихся в данный момент запросов.
|
2013-09-07 04:54:59 +00:00
|
|
|
|
* Также реализует ограничение на их количество.
|
2013-09-03 20:21:28 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
/// Запрос и данные о его выполнении.
|
|
|
|
|
struct ProcessListElement
|
2013-09-03 20:21:28 +00:00
|
|
|
|
{
|
2015-04-16 06:12:35 +00:00
|
|
|
|
String query;
|
|
|
|
|
String user;
|
|
|
|
|
String query_id;
|
|
|
|
|
Poco::Net::IPAddress ip_address;
|
2014-09-10 11:34:26 +00:00
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
Stopwatch watch;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
Progress progress;
|
2014-02-12 17:31:02 +00:00
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
MemoryTracker memory_tracker;
|
2014-05-03 22:57:43 +00:00
|
|
|
|
|
2015-06-21 06:06:04 +00:00
|
|
|
|
QueryPriorities::Handle priority_handle;
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
bool is_cancelled = false;
|
2014-09-10 11:34:26 +00:00
|
|
|
|
|
2015-09-04 20:52:00 +00:00
|
|
|
|
/// Здесь могут быть зарегистрированы временные таблицы. Изменять под mutex-ом.
|
|
|
|
|
Tables temporary_tables;
|
|
|
|
|
|
2013-11-03 05:32:42 +00:00
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
ProcessListElement(const String & query_, const String & user_,
|
|
|
|
|
const String & query_id_, const Poco::Net::IPAddress & ip_address_,
|
2015-06-21 06:06:04 +00:00
|
|
|
|
size_t max_memory_usage, 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_))
|
2015-04-16 06:12:35 +00:00
|
|
|
|
{
|
|
|
|
|
current_memory_tracker = &memory_tracker;
|
|
|
|
|
}
|
2014-05-03 22:57:43 +00:00
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
~ProcessListElement()
|
|
|
|
|
{
|
|
|
|
|
current_memory_tracker = nullptr;
|
|
|
|
|
}
|
2013-11-03 05:32:42 +00:00
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
bool update(const Progress & value)
|
|
|
|
|
{
|
|
|
|
|
progress.incrementPiecewiseAtomically(value);
|
2015-06-21 06:06:04 +00:00
|
|
|
|
|
|
|
|
|
if (priority_handle)
|
|
|
|
|
priority_handle->waitIfNeed(std::chrono::seconds(1)); /// NOTE Можно сделать настраиваемым таймаут.
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
return !is_cancelled;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-06-21 06:06:04 +00:00
|
|
|
|
class ProcessList;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Держит итератор на список, и удаляет элемент из списка в деструкторе.
|
|
|
|
|
class ProcessListEntry
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
using Container = std::list<ProcessListElement>;
|
|
|
|
|
|
|
|
|
|
ProcessList & parent;
|
|
|
|
|
Container::iterator it;
|
|
|
|
|
public:
|
|
|
|
|
ProcessListEntry(ProcessList & parent_, Container::iterator it_)
|
|
|
|
|
: parent(parent_), it(it_) {}
|
|
|
|
|
|
|
|
|
|
~ProcessListEntry();
|
|
|
|
|
|
|
|
|
|
ProcessListElement * operator->() { return &*it; }
|
|
|
|
|
const ProcessListElement * operator->() const { return &*it; }
|
|
|
|
|
|
|
|
|
|
ProcessListElement & get() { return *it; }
|
|
|
|
|
const ProcessListElement & get() const { return *it; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
class ProcessList
|
|
|
|
|
{
|
2015-06-21 06:06:04 +00:00
|
|
|
|
friend class ProcessListEntry;
|
2015-04-16 06:12:35 +00:00
|
|
|
|
public:
|
|
|
|
|
using Element = ProcessListElement;
|
2015-06-21 06:06:04 +00:00
|
|
|
|
using Entry = ProcessListEntry;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
|
|
|
|
/// list, чтобы итераторы не инвалидировались. NOTE: можно заменить на cyclic buffer, но почти незачем.
|
2015-06-21 06:06:04 +00:00
|
|
|
|
using Container = std::list<Element>;
|
2014-02-12 17:31:02 +00:00
|
|
|
|
/// Query_id -> Element *
|
2015-06-21 06:06:04 +00:00
|
|
|
|
using QueryToElement = std::unordered_map<String, Element *>;
|
2014-02-12 17:31:02 +00:00
|
|
|
|
/// User -> Query_id -> Element *
|
2015-06-21 06:06:04 +00:00
|
|
|
|
using UserToQueries = std::unordered_map<String, QueryToElement>;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
|
|
|
|
private:
|
2013-09-14 05:14:22 +00:00
|
|
|
|
mutable Poco::FastMutex mutex;
|
|
|
|
|
mutable Poco::Condition have_space; /// Количество одновременно выполняющихся запросов стало меньше максимального.
|
2014-09-10 11:34:26 +00:00
|
|
|
|
|
2015-06-21 06:06:04 +00:00
|
|
|
|
Container cont;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
size_t cur_size; /// В C++03 std::list::size не O(1).
|
2013-09-07 04:54:59 +00:00
|
|
|
|
size_t max_size; /// Если 0 - не ограничено. Иначе, если пытаемся добавить больше - кидается исключение.
|
2014-02-14 13:22:45 +00:00
|
|
|
|
UserToQueries user_to_queries;
|
2015-06-21 06:06:04 +00:00
|
|
|
|
QueryPriorities priorities;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
ProcessList(size_t max_size_ = 0) : cur_size(0), max_size(max_size_) {}
|
|
|
|
|
|
2015-06-21 06:06:04 +00:00
|
|
|
|
typedef std::shared_ptr<ProcessListEntry> EntryPtr;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
2013-09-07 04:54:59 +00:00
|
|
|
|
/** Зарегистрировать выполняющийся запрос. Возвращает refcounted объект, который удаляет запрос из списка при уничтожении.
|
|
|
|
|
* Если выполняющихся запросов сейчас слишком много - ждать не более указанного времени.
|
|
|
|
|
* Если времени не хватило - кинуть исключение.
|
|
|
|
|
*/
|
2014-02-12 17:31:02 +00:00
|
|
|
|
EntryPtr insert(const String & query_, const String & user_, const String & query_id_, const Poco::Net::IPAddress & ip_address_,
|
2015-09-08 21:01:43 +00:00
|
|
|
|
const Settings & settings);
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
|
|
|
|
/// Количество одновременно выполняющихся запросов.
|
2014-09-12 16:05:29 +00:00
|
|
|
|
size_t size() const { return cur_size; }
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
|
|
|
|
/// Получить текущее состояние (копию) списка запросов.
|
2015-06-21 06:06:04 +00:00
|
|
|
|
Container get() const
|
2013-09-03 20:21:28 +00:00
|
|
|
|
{
|
2014-09-12 16:05:29 +00:00
|
|
|
|
Poco::ScopedLock<Poco::FastMutex> lock(mutex);
|
|
|
|
|
return cont;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setMaxSize(size_t max_size_)
|
|
|
|
|
{
|
|
|
|
|
Poco::ScopedLock<Poco::FastMutex> lock(mutex);
|
|
|
|
|
max_size = max_size_;
|
|
|
|
|
}
|
2015-09-04 20:52:00 +00:00
|
|
|
|
|
|
|
|
|
/// Зарегистрировать временную таблицу. Потом её можно будет получить по query_id и по названию.
|
|
|
|
|
void addTemporaryTable(ProcessListElement & elem, const String & table_name, StoragePtr storage);
|
|
|
|
|
|
|
|
|
|
/// Найти временную таблицу по query_id и по названию. Замечание: плохо работает, если есть разные запросы с одним query_id.
|
|
|
|
|
StoragePtr tryGetTemporaryTable(const String & query_id, const String & table_name) const;
|
2013-09-03 20:21:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|