2013-06-15 06:16:17 +00:00
|
|
|
|
#include <iomanip>
|
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
#include <Poco/DirectoryIterator.h>
|
|
|
|
|
#include <Poco/FileStream.h>
|
|
|
|
|
|
|
|
|
|
#include <DB/Parsers/ParserCreateQuery.h>
|
|
|
|
|
#include <DB/Parsers/ASTCreateQuery.h>
|
2015-04-11 03:10:23 +00:00
|
|
|
|
#include <DB/Parsers/parseQuery.h>
|
2011-10-30 11:30:52 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Interpreters/InterpreterCreateQuery.h>
|
|
|
|
|
#include <DB/Interpreters/loadMetadata.h>
|
|
|
|
|
|
2013-01-17 19:36:34 +00:00
|
|
|
|
#include <DB/IO/ReadBufferFromFile.h>
|
|
|
|
|
#include <DB/IO/WriteBufferFromString.h>
|
|
|
|
|
#include <DB/IO/copyData.h>
|
|
|
|
|
|
2013-06-15 06:14:41 +00:00
|
|
|
|
#include <statdaemons/Stopwatch.h>
|
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void executeCreateQuery(const String & query, Context & context, const String & database, const String & file_name)
|
|
|
|
|
{
|
|
|
|
|
ParserCreateQuery parser;
|
2015-04-11 03:10:23 +00:00
|
|
|
|
ASTPtr ast = parseQuery(parser, query.data(), query.data() + query.size(), "in file " + file_name);
|
2011-10-30 11:30:52 +00:00
|
|
|
|
|
2014-06-26 00:58:14 +00:00
|
|
|
|
ASTCreateQuery & ast_create_query = typeid_cast<ASTCreateQuery &>(*ast);
|
2011-10-30 11:30:52 +00:00
|
|
|
|
ast_create_query.attach = true;
|
|
|
|
|
ast_create_query.database = database;
|
2012-03-09 03:06:09 +00:00
|
|
|
|
|
2015-06-18 02:11:05 +00:00
|
|
|
|
InterpreterCreateQuery(ast, context).executeLoadExisting();
|
2011-10-30 11:30:52 +00:00
|
|
|
|
}
|
2014-04-13 08:52:50 +00:00
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
|
|
|
|
|
void loadMetadata(Context & context)
|
|
|
|
|
{
|
2013-03-18 08:03:44 +00:00
|
|
|
|
/// Создадим все таблицы атомарно (иначе какой-нибудь движок таблицы может успеть в фоновом потоке попытаться выполнить запрос).
|
|
|
|
|
Poco::ScopedLock<Poco::Mutex> lock(context.getMutex());
|
2013-09-15 01:41:09 +00:00
|
|
|
|
|
|
|
|
|
Logger * log = &Logger::get("loadMetadata");
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
/// Здесь хранятся определения таблиц
|
2012-08-02 17:33:31 +00:00
|
|
|
|
String path = context.getPath() + "metadata";
|
2011-10-30 11:30:52 +00:00
|
|
|
|
|
|
|
|
|
/// Цикл по базам данных
|
|
|
|
|
Poco::DirectoryIterator dir_end;
|
|
|
|
|
for (Poco::DirectoryIterator it(path); it != dir_end; ++it)
|
|
|
|
|
{
|
|
|
|
|
if (!it->isDirectory())
|
|
|
|
|
continue;
|
|
|
|
|
|
2012-03-09 03:56:12 +00:00
|
|
|
|
/// Для директории .svn
|
|
|
|
|
if (it.name().at(0) == '.')
|
|
|
|
|
continue;
|
|
|
|
|
|
2013-09-15 01:41:09 +00:00
|
|
|
|
LOG_INFO(log, "Loading database " << it.name());
|
2013-06-15 04:16:14 +00:00
|
|
|
|
|
2011-11-05 23:31:19 +00:00
|
|
|
|
executeCreateQuery("ATTACH DATABASE " + it.name(), context, it.name(), it->path());
|
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
/// Цикл по таблицам
|
2013-06-15 05:51:12 +00:00
|
|
|
|
typedef std::vector<std::string> Tables;
|
|
|
|
|
Tables tables;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
for (Poco::DirectoryIterator jt(it->path()); jt != dir_end; ++jt)
|
|
|
|
|
{
|
2013-01-20 23:47:23 +00:00
|
|
|
|
if (jt.name() == ".svn")
|
|
|
|
|
continue;
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2011-10-30 11:30:52 +00:00
|
|
|
|
/// Файлы имеют имена вида table_name.sql
|
|
|
|
|
if (jt.name().compare(jt.name().size() - 4, 4, ".sql"))
|
|
|
|
|
throw Exception("Incorrect file extension: " + jt.name() + " in metadata directory " + it->path(), ErrorCodes::INCORRECT_FILE_NAME);
|
|
|
|
|
|
2013-06-15 06:14:41 +00:00
|
|
|
|
tables.push_back(jt->path());
|
2013-06-15 05:51:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-15 01:41:09 +00:00
|
|
|
|
LOG_INFO(log, "Found " << tables.size() << " tables.");
|
2013-06-15 05:51:12 +00:00
|
|
|
|
|
|
|
|
|
/** Таблицы быстрее грузятся, если их грузить в сортированном (по именам) порядке.
|
|
|
|
|
* Иначе (для файловой системы ext4) DirectoryIterator перебирает их в некотором порядке,
|
|
|
|
|
* который не соответствует порядку создания таблиц и не соответствует порядку их расположения на диске.
|
|
|
|
|
*/
|
|
|
|
|
std::sort(tables.begin(), tables.end());
|
|
|
|
|
|
2013-06-15 06:14:41 +00:00
|
|
|
|
Stopwatch watch;
|
|
|
|
|
|
|
|
|
|
for (size_t j = 0, size = tables.size(); j < size; ++j)
|
2013-06-15 05:51:12 +00:00
|
|
|
|
{
|
2013-06-15 06:14:41 +00:00
|
|
|
|
/// Сообщения, чтобы было не скучно ждать, когда сервер долго загружается.
|
|
|
|
|
if (j % 256 == 0 && watch.elapsedSeconds() > 5)
|
|
|
|
|
{
|
2013-09-15 01:41:09 +00:00
|
|
|
|
LOG_INFO(log, std::fixed << std::setprecision(2) << j * 100.0 / size << "%");
|
2013-06-15 06:14:41 +00:00
|
|
|
|
watch.restart();
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2013-01-17 19:36:34 +00:00
|
|
|
|
String s;
|
|
|
|
|
{
|
2013-06-15 04:44:19 +00:00
|
|
|
|
static const size_t in_buf_size = 32768;
|
|
|
|
|
char in_buf[in_buf_size];
|
2014-01-04 04:52:22 +00:00
|
|
|
|
ReadBufferFromFile in(tables[j], 32768, -1, in_buf);
|
2013-01-17 19:36:34 +00:00
|
|
|
|
WriteBufferFromString out(s);
|
|
|
|
|
copyData(in, out);
|
|
|
|
|
}
|
2011-10-30 11:30:52 +00:00
|
|
|
|
|
2013-09-15 01:41:09 +00:00
|
|
|
|
/** Пустые файлы с метаданными образуются после грубого перезапуска сервера.
|
|
|
|
|
* Удаляем эти файлы, чтобы чуть-чуть уменьшить работу админов по запуску.
|
|
|
|
|
*/
|
|
|
|
|
if (s.empty())
|
|
|
|
|
{
|
|
|
|
|
LOG_ERROR(log, "File " << tables[j] << " is empty. Removing.");
|
|
|
|
|
Poco::File(tables[j]).remove();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-27 18:27:05 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2013-06-15 06:14:41 +00:00
|
|
|
|
executeCreateQuery(s, context, it.name(), tables[j]);
|
2012-09-27 18:27:05 +00:00
|
|
|
|
}
|
2013-10-26 03:20:51 +00:00
|
|
|
|
catch (const Exception & e)
|
2012-09-27 18:27:05 +00:00
|
|
|
|
{
|
2014-04-03 12:49:01 +00:00
|
|
|
|
throw Exception("Cannot create table from metadata file " + tables[j] + ", error: " + e.displayText() +
|
|
|
|
|
", stack trace:\n" + e.getStackTrace().toString(),
|
2012-09-27 18:27:05 +00:00
|
|
|
|
ErrorCodes::CANNOT_CREATE_TABLE_FROM_METADATA);
|
|
|
|
|
}
|
2011-10-30 11:30:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|