mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-18 05:32:52 +00:00
5fc44df6b5
commit f9b478181cd49224154cc350fb57df7121842f1c Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Mar 19 04:06:36 2016 +0300 Database engines: development [#METR-19997]. commit f7a10a67761ccfd05f3dac32d6444920cd8d4d60 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Mar 19 03:44:37 2016 +0300 Database engines: development [#METR-19997]. commit bd98a8558e98bad2bed278e5762c4e0fc66e6f38 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Mar 19 00:33:59 2016 +0300 Database engines: development [#METR-19997]. commit 19712fd884c22a4e2c2b67474086dea8f44e7c7b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Sat Mar 19 00:03:11 2016 +0300 Database engines: development [#METR-19997]. commit 50274d6df7e91fcc34aab8a8c72347daa2c6512f Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Mar 18 23:24:57 2016 +0300 Database engines: development [#METR-19997]. commit 4a0b99b19b34e90ef8b7be2d199f6232e36ef3f7 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Mar 18 22:50:36 2016 +0300 Database engines: development [#METR-19997]. commit 44ff3ebba7a3e460a27a89f31ddf199dbea1d182 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Mar 18 15:09:17 2016 +0300 Database engines: development [#METR-19997]. commit 137c31f3004cfd282473b6acb01cbe1b4ca2aadd Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Mar 18 03:26:34 2016 +0300 Database engines: development [#METR-19997]. commit aa4c0496d4afe4a691164254be2bd5600542b38a Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Mar 18 03:22:59 2016 +0300 Database engines: development [#METR-19997]. commit 5a94d1f0607450a2dac28a4d7df8b1393a864c23 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Mar 18 01:02:40 2016 +0300 Database engines: development [#METR-19997]. commit 50fd5b52ea1141955a5dfba0dcb191f3289ac25b Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Thu Mar 17 23:23:40 2016 +0300 Database engines: development [#METR-19997]. commit a333d91b058e4f56dd83a6d2878c3c2bd8efc002 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Thu Mar 17 20:29:07 2016 +0300 Database engines: development [#METR-19997]. commit f81d366e7ac8348436f2698d040f8e341743a024 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Thu Mar 17 01:30:23 2016 +0300 Database engines: development [#METR-19997]. commit d0696860c9060827896214c08d147c759ea79376 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Wed Mar 16 21:55:31 2016 +0300 Database engines: development [#METR-19997]. commit 46a168c2ada140a0e95cd8d4b9d8ba9bac855d11 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Wed Mar 16 08:00:58 2016 +0300 Database engines: development [#METR-19997]. commit 20a2bad161454225fc1b5f9b919b842fbebc3231 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Wed Mar 16 06:51:10 2016 +0300 Database engines: development [#METR-19997]. commit ca0a77fcc2a8d0b276eb3743c53551ad3fe16314 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Wed Mar 16 06:02:20 2016 +0300 Reverted erroneous modification [#METR-19997]. commit 1370bdcc4594182f6ef2b146f9afabfe1c295080 Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Wed Mar 16 00:41:34 2016 +0300 Database engines: development [#METR-19997]. commit 16e72c67041cae6471509d3f0f3d4a9aa7b7dc0f Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Tue Mar 15 00:41:48 2016 +0300 Database engines: development [#METR-19997].
325 lines
17 KiB
C++
325 lines
17 KiB
C++
#pragma once
|
||
|
||
#include <common/logger_useful.h>
|
||
|
||
#include <DB/Core/Defines.h>
|
||
#include <DB/Core/Names.h>
|
||
#include <DB/Core/NamesAndTypes.h>
|
||
#include <DB/Common/Exception.h>
|
||
#include <DB/Core/QueryProcessingStage.h>
|
||
#include <DB/Parsers/IAST.h>
|
||
#include <DB/Parsers/ASTAlterQuery.h>
|
||
#include <DB/Interpreters/Settings.h>
|
||
#include <DB/Storages/ITableDeclaration.h>
|
||
#include <DB/Storages/AlterCommands.h>
|
||
#include <Poco/File.h>
|
||
#include <Poco/RWLock.h>
|
||
#include <memory>
|
||
|
||
|
||
namespace DB
|
||
{
|
||
|
||
namespace ErrorCodes
|
||
{
|
||
extern const int TABLE_IS_DROPPED;
|
||
}
|
||
|
||
class Context;
|
||
class IBlockInputStream;
|
||
class IBlockOutputStream;
|
||
|
||
typedef SharedPtr<IBlockOutputStream> BlockOutputStreamPtr;
|
||
typedef SharedPtr<IBlockInputStream> BlockInputStreamPtr;
|
||
typedef std::vector<BlockInputStreamPtr> BlockInputStreams;
|
||
|
||
|
||
class IStorage;
|
||
|
||
typedef std::shared_ptr<IStorage> StoragePtr;
|
||
|
||
|
||
/** Хранилище. Отвечает за:
|
||
* - хранение данных таблицы;
|
||
* - определение, в каком файле (или не файле) хранятся данные;
|
||
* - поиск данных и обновление данных;
|
||
* - структура хранения данных (сжатие, etc.)
|
||
* - конкуррентный доступ к данным (блокировки, etc.)
|
||
*/
|
||
class IStorage : private boost::noncopyable, public ITableDeclaration
|
||
{
|
||
public:
|
||
/// Основное имя типа таблицы (например, StorageMergeTree).
|
||
virtual std::string getName() const = 0;
|
||
|
||
/** Возвращает true, если хранилище получает данные с удалённого сервера или серверов. */
|
||
virtual bool isRemote() const { return false; }
|
||
|
||
/** Возвращает true, если хранилище поддерживает запросы с секцией SAMPLE. */
|
||
virtual bool supportsSampling() const { return false; }
|
||
|
||
/** Возвращает true, если хранилище поддерживает запросы с секцией FINAL. */
|
||
virtual bool supportsFinal() const { return false; }
|
||
|
||
/** Возвращает true, если хранилище поддерживает запросы с секцией PREWHERE. */
|
||
virtual bool supportsPrewhere() const { return false; }
|
||
|
||
/** Возвращает true, если хранилище поддерживает несколько реплик. */
|
||
virtual bool supportsParallelReplicas() const { return false; }
|
||
|
||
/** Не дает изменять описание таблицы (в том числе переименовывать и удалять таблицу).
|
||
* Если в течение какой-то операции структура таблицы должна оставаться неизменной, нужно держать такой лок на все ее время.
|
||
* Например, нужно держать такой лок на время всего запроса SELECT или INSERT и на все время слияния набора кусков
|
||
* (но между выбором кусков для слияния и их слиянием структура таблицы может измениться).
|
||
* NOTE: Это лок на "чтение" описания таблицы. Чтобы изменить описание таблицы, нужно взять TableStructureWriteLock.
|
||
*/
|
||
class TableStructureReadLock
|
||
{
|
||
private:
|
||
friend class IStorage;
|
||
|
||
StoragePtr storage;
|
||
/// Порядок важен.
|
||
Poco::SharedPtr<Poco::ScopedReadRWLock> data_lock;
|
||
Poco::SharedPtr<Poco::ScopedReadRWLock> structure_lock;
|
||
|
||
TableStructureReadLock(StoragePtr storage_, bool lock_structure, bool lock_data)
|
||
: storage(storage_),
|
||
data_lock(lock_data ? new Poco::ScopedReadRWLock(storage-> data_lock) : nullptr),
|
||
structure_lock(lock_structure ? new Poco::ScopedReadRWLock(storage->structure_lock) : nullptr) {}
|
||
};
|
||
|
||
typedef Poco::SharedPtr<TableStructureReadLock> TableStructureReadLockPtr;
|
||
typedef std::vector<TableStructureReadLockPtr> TableStructureReadLocks;
|
||
|
||
/** Не дает изменять структуру или имя таблицы.
|
||
* Если в рамках этого лока будут изменены данные в таблице, нужно указать will_modify_data=true.
|
||
* Это возьмет дополнительный лок, не позволяющий начать ALTER MODIFY.
|
||
*
|
||
* WARNING: Вызывать методы из ITableDeclaration нужно под такой блокировкой. Без нее они не thread safe.
|
||
* WARNING: Чтобы не было дедлоков, нельзя вызывать это метод при захваченном мьютексе в Context.
|
||
*/
|
||
TableStructureReadLockPtr lockStructure(bool will_modify_data)
|
||
{
|
||
TableStructureReadLockPtr res = new TableStructureReadLock(thisPtr(), true, will_modify_data);
|
||
if (is_dropped)
|
||
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
|
||
return res;
|
||
}
|
||
|
||
typedef std::unique_ptr<Poco::ScopedWriteRWLock> TableStructureWriteLockPtr;
|
||
typedef std::unique_ptr<Poco::ScopedWriteRWLock> TableDataWriteLockPtr;
|
||
typedef std::pair<TableDataWriteLockPtr, TableStructureWriteLockPtr> TableFullWriteLockPtr;
|
||
|
||
/** Не дает читать структуру таблицы. Берется для ALTER, RENAME и DROP.
|
||
*/
|
||
TableFullWriteLockPtr lockForAlter()
|
||
{
|
||
/// Порядок вычисления важен.
|
||
auto data_lock = lockDataForAlter();
|
||
auto structure_lock = lockStructureForAlter();
|
||
|
||
return {std::move(data_lock), std::move(structure_lock)};
|
||
}
|
||
|
||
/** Не дает изменять данные в таблице. (Более того, не дает посмотреть на структуру таблицы с намерением изменить данные).
|
||
* Берется на время записи временных данных в ALTER MODIFY.
|
||
* Под этим локом можно брать lockStructureForAlter(), чтобы изменить структуру таблицы.
|
||
*/
|
||
TableDataWriteLockPtr lockDataForAlter()
|
||
{
|
||
auto res = std::make_unique<Poco::ScopedWriteRWLock>(data_lock);
|
||
if (is_dropped)
|
||
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
|
||
return res;
|
||
}
|
||
|
||
TableStructureWriteLockPtr lockStructureForAlter()
|
||
{
|
||
auto res = std::make_unique<Poco::ScopedWriteRWLock>(structure_lock);
|
||
if (is_dropped)
|
||
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
|
||
return res;
|
||
}
|
||
|
||
|
||
/** Читать набор столбцов из таблицы.
|
||
* Принимает список столбцов, которых нужно прочитать, а также описание запроса,
|
||
* из которого может быть извлечена информация о том, каким способом извлекать данные
|
||
* (индексы, блокировки и т. п.)
|
||
* Возвращает поток с помощью которого можно последовательно читать данные
|
||
* или несколько потоков для параллельного чтения данных.
|
||
* Также в processed_stage записывается, до какой стадии запрос был обработан.
|
||
* (Обычно функция только читает столбцы из списка, но в других случаях,
|
||
* например, запрос может быть частично обработан на удалённом сервере.)
|
||
*
|
||
* settings - настройки на один запрос.
|
||
* Обычно Storage не заботится об этих настройках, так как они применяются в интерпретаторе.
|
||
* Но, например, при распределённой обработке запроса, настройки передаются на удалённый сервер.
|
||
*
|
||
* threads - рекомендация, сколько потоков возвращать,
|
||
* если хранилище может возвращать разное количество потоков.
|
||
*
|
||
* Гарантируется, что структура таблицы не изменится за время жизни возвращенных потоков (то есть не будет ALTER, RENAME и DROP).
|
||
*/
|
||
virtual BlockInputStreams read(
|
||
const Names & column_names,
|
||
ASTPtr query,
|
||
const Context & context,
|
||
const Settings & settings,
|
||
QueryProcessingStage::Enum & processed_stage,
|
||
size_t max_block_size = DEFAULT_BLOCK_SIZE,
|
||
unsigned threads = 1)
|
||
{
|
||
throw Exception("Method read is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Пишет данные в таблицу.
|
||
* Принимает описание запроса, в котором может содержаться информация о методе записи данных.
|
||
* Возвращает объект, с помощью которого можно последовательно писать данные.
|
||
*
|
||
* Гарантируется, что структура таблицы не изменится за время жизни возвращенных потоков (то есть не будет ALTER, RENAME и DROP).
|
||
*/
|
||
virtual BlockOutputStreamPtr write(
|
||
ASTPtr query,
|
||
const Settings & settings)
|
||
{
|
||
throw Exception("Method write is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Удалить данные таблицы. Вызывается перед удалением директории с данными.
|
||
* Если не требуется никаких действий, кроме удаления директории с данными, этот метод можно оставить пустым.
|
||
*/
|
||
virtual void drop() {}
|
||
|
||
/** Переименовать таблицу.
|
||
* Переименование имени в файле с метаданными, имени в списке таблиц в оперативке, осуществляется отдельно.
|
||
* В этой функции нужно переименовать директорию с данными, если она есть.
|
||
* Вызывается при заблокированной на запись структуре таблицы.
|
||
*/
|
||
virtual void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name)
|
||
{
|
||
throw Exception("Method rename is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** ALTER таблицы в виде изменения столбцов, не затрагивающий изменение Storage или его параметров.
|
||
* Этот метод должен полностью выполнить запрос ALTER, самостоятельно заботясь о блокировках.
|
||
* Для обновления метаданных таблицы на диске этот метод должен вызвать InterpreterAlterQuery::updateMetadata.
|
||
*/
|
||
virtual void alter(const AlterCommands & params, const String & database_name, const String & table_name, const Context & context)
|
||
{
|
||
throw Exception("Method alter is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Выполнить запрос (DROP|DETACH) PARTITION.
|
||
*/
|
||
virtual void dropPartition(ASTPtr query, const Field & partition, bool detach, bool unreplicated, const Settings & settings)
|
||
{
|
||
throw Exception("Method dropPartition is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Выполнить запрос ATTACH [UNREPLICATED] (PART|PARTITION).
|
||
*/
|
||
virtual void attachPartition(ASTPtr query, const Field & partition, bool unreplicated, bool part, const Settings & settings)
|
||
{
|
||
throw Exception("Method attachPartition is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Выполнить запрос FETCH PARTITION.
|
||
*/
|
||
virtual void fetchPartition(const Field & partition, const String & from, const Settings & settings)
|
||
{
|
||
throw Exception("Method fetchPartition is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Выполнить запрос FREEZE PARTITION. То есть, создать локальный бэкап (снэпшот) данных с помощью функции localBackup (см. localBackup.h)
|
||
*/
|
||
virtual void freezePartition(const Field & partition, const Settings & settings)
|
||
{
|
||
throw Exception("Method freezePartition is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Выполнить запрос RESHARD PARTITION.
|
||
*/
|
||
virtual void reshardPartitions(ASTPtr query, const String & database_name,
|
||
const Field & first_partition, const Field & last_partition,
|
||
const WeightedZooKeeperPaths & weighted_zookeeper_paths,
|
||
const ASTPtr & sharding_key_expr, const Field & coordinator,
|
||
const Settings & settings)
|
||
{
|
||
throw Exception("Method reshardPartition is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Выполнить какую-либо фоновую работу. Например, объединение кусков в таблице типа MergeTree.
|
||
* Возвращает - была ли выполнена какая-либо работа.
|
||
*/
|
||
virtual bool optimize(const Settings & settings)
|
||
{
|
||
throw Exception("Method optimize is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||
}
|
||
|
||
/** Если при уничтожении объекта надо сделать какую-то сложную работу - сделать её заранее.
|
||
* Например, если таблица содержит какие-нибудь потоки для фоновой работы - попросить их завершиться и дождаться завершения.
|
||
* По-умолчанию - ничего не делать.
|
||
* Может вызываться одновременно из разных потоков, даже после вызова drop().
|
||
*/
|
||
virtual void shutdown() {}
|
||
|
||
/** Возвращает владеющий указатель на себя.
|
||
*/
|
||
std::shared_ptr<IStorage> thisPtr()
|
||
{
|
||
std::shared_ptr<IStorage> res = this_ptr.lock();
|
||
if (!res)
|
||
{
|
||
res.reset(this);
|
||
this_ptr = res;
|
||
}
|
||
return res;
|
||
}
|
||
|
||
bool is_dropped{false};
|
||
|
||
/// Поддерживается ли индекс в секции IN
|
||
virtual bool supportsIndexForIn() const { return false; };
|
||
|
||
/// проверяет валидность данных
|
||
virtual bool checkData() const { throw DB::Exception("Check query is not supported for " + getName() + " storage"); }
|
||
|
||
protected:
|
||
using ITableDeclaration::ITableDeclaration;
|
||
|
||
private:
|
||
std::weak_ptr<IStorage> this_ptr;
|
||
|
||
/// Брать следующие два лока всегда нужно в этом порядке.
|
||
|
||
/** Берется на чтение на все время запроса INSERT и на все время слияния кусков (для MergeTree).
|
||
* Берется на запись на все время ALTER MODIFY.
|
||
*
|
||
* Формально:
|
||
* Ввзятие на запись гарантирует, что:
|
||
* 1) данные в таблице не изменится, пока лок жив,
|
||
* 2) все изменения данных после отпускания лока будут основаны на структуре таблицы на момент после отпускания лока.
|
||
* Нужно брать на чтение на все время операции, изменяющей данные.
|
||
*/
|
||
mutable Poco::RWLock data_lock;
|
||
|
||
/** Лок для множества столбцов и пути к таблице. Берется на запись в RENAME, ALTER (для ALTER MODIFY ненадолго) и DROP.
|
||
* Берется на чтение на все время SELECT, INSERT и слияния кусков (для MergeTree).
|
||
*
|
||
* Взятие этого лока на запись - строго более "сильная" операция, чем взятие parts_writing_lock на запись.
|
||
* То есть, если этот лок взят на запись, о parts_writing_lock можно не заботиться.
|
||
* parts_writing_lock нужен только для случаев, когда не хочется брать table_structure_lock надолго (ALTER MODIFY).
|
||
*/
|
||
mutable Poco::RWLock structure_lock;
|
||
};
|
||
|
||
using StorageVector = std::vector<StoragePtr>;
|
||
using TableLocks = IStorage::TableStructureReadLocks;
|
||
|
||
/// имя таблицы -> таблица
|
||
using Tables = std::map<String, StoragePtr>;
|
||
|
||
}
|