2017-03-03 00:24:56 +00:00
|
|
|
#include "Server.h"
|
2014-04-15 16:39:56 +00:00
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <memory>
|
2017-03-03 00:24:56 +00:00
|
|
|
#include <sys/resource.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <Poco/DirectoryIterator.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
#include <Poco/Net/DNS.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <Poco/Net/HTTPServerRequest.h>
|
2016-06-25 03:06:36 +00:00
|
|
|
#include <Poco/Net/NetException.h>
|
2014-02-13 07:17:22 +00:00
|
|
|
#include <Poco/Util/XMLConfiguration.h>
|
2016-10-25 12:27:09 +00:00
|
|
|
#include <common/ApplicationServerExt.h>
|
2015-09-29 19:19:54 +00:00
|
|
|
#include <common/ErrorHandlers.h>
|
2015-10-05 00:33:43 +00:00
|
|
|
#include <ext/scope_guard.hpp>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <zkutil/ZooKeeper.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
#include <DB/Common/Macros.h>
|
2016-07-14 05:22:09 +00:00
|
|
|
#include <DB/Common/StringUtils.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <DB/Common/getFQDNOrHostName.h>
|
|
|
|
#include <DB/Databases/DatabaseOrdinary.h>
|
2016-12-30 20:52:56 +00:00
|
|
|
#include <DB/IO/HTTPCommon.h>
|
2016-10-24 04:06:27 +00:00
|
|
|
#include <DB/Interpreters/AsynchronousMetrics.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <DB/Interpreters/ProcessList.h>
|
|
|
|
#include <DB/Interpreters/loadMetadata.h>
|
|
|
|
#include <DB/Storages/MergeTree/ReshardingWorker.h>
|
|
|
|
#include <DB/Storages/StorageReplicatedMergeTree.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemAsynchronousMetrics.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemBuildOptions.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemClusters.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemColumns.h>
|
2015-09-24 03:50:09 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemDatabases.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemDictionaries.h>
|
2015-09-24 03:50:09 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemEvents.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemFunctions.h>
|
2015-09-24 03:50:09 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemMerges.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemMetrics.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemNumbers.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemOne.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemParts.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemProcesses.h>
|
2015-09-24 03:50:09 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemReplicas.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemReplicationQueue.h>
|
2017-03-03 18:59:42 +00:00
|
|
|
#include <DB/Storages/System/StorageSystemSettings.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemTables.h>
|
|
|
|
#include <DB/Storages/System/StorageSystemZooKeeper.h>
|
|
|
|
#include "ConfigReloader.h"
|
2012-03-09 15:46:52 +00:00
|
|
|
#include "HTTPHandler.h"
|
2014-03-21 13:42:14 +00:00
|
|
|
#include "InterserverIOHTTPHandler.h"
|
2016-01-17 13:34:36 +00:00
|
|
|
#include "MetricsTransmitter.h"
|
2017-03-03 18:59:42 +00:00
|
|
|
#include "ReplicasStatusHandler.h"
|
2016-01-17 13:34:36 +00:00
|
|
|
#include "StatusFile.h"
|
2017-03-03 18:59:42 +00:00
|
|
|
#include "TCPHandler.h"
|
2012-03-09 03:06:09 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2016-09-21 15:22:38 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int NO_ELEMENTS_IN_CONFIG;
|
|
|
|
}
|
|
|
|
|
2015-11-05 20:08:18 +00:00
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Response with "Ok.\n". Used for availability checks.
|
2012-03-09 03:06:09 +00:00
|
|
|
class PingRequestHandler : public Poco::Net::HTTPRequestHandler
|
|
|
|
{
|
|
|
|
public:
|
2016-10-10 08:44:52 +00:00
|
|
|
void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override
|
2012-03-09 03:06:09 +00:00
|
|
|
{
|
2015-11-05 20:08:18 +00:00
|
|
|
try
|
|
|
|
{
|
2016-12-30 20:52:56 +00:00
|
|
|
setResponseDefaultHeaders(response);
|
2015-11-05 20:08:18 +00:00
|
|
|
const char * data = "Ok.\n";
|
|
|
|
response.sendBuffer(data, strlen(data));
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException("PingRequestHandler");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Response with 404 and verbose description.
|
2015-11-05 20:08:18 +00:00
|
|
|
class NotFoundHandler : public Poco::Net::HTTPRequestHandler
|
|
|
|
{
|
|
|
|
public:
|
2016-10-10 08:44:52 +00:00
|
|
|
void handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) override
|
2015-11-05 20:08:18 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
|
|
|
|
response.send() << "There is no handle " << request.getURI() << "\n\n"
|
2017-03-03 18:59:42 +00:00
|
|
|
<< "Use / or /ping for health checks.\n"
|
|
|
|
<< "Or /replicas_status for more sophisticated health checks.\n\n"
|
|
|
|
<< "Send queries from your program with POST method or GET /?query=...\n\n"
|
|
|
|
<< "Use clickhouse-client:\n\n"
|
|
|
|
<< "For interactive data analysis:\n"
|
|
|
|
<< " clickhouse-client\n\n"
|
|
|
|
<< "For batch query processing:\n"
|
|
|
|
<< " clickhouse-client --query='SELECT 1' > result\n"
|
|
|
|
<< " clickhouse-client < query > result\n";
|
2015-11-05 20:08:18 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException("NotFoundHandler");
|
2014-07-16 00:53:56 +00:00
|
|
|
}
|
2012-03-09 03:06:09 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-09-25 16:28:17 +00:00
|
|
|
template <typename HandlerType>
|
2012-12-14 11:21:07 +00:00
|
|
|
class HTTPRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
|
2012-03-09 03:06:09 +00:00
|
|
|
{
|
2012-12-14 11:21:07 +00:00
|
|
|
private:
|
|
|
|
Server & server;
|
|
|
|
Logger * log;
|
|
|
|
std::string name;
|
2014-07-16 00:53:56 +00:00
|
|
|
|
2012-12-14 11:21:07 +00:00
|
|
|
public:
|
2017-03-03 18:59:42 +00:00
|
|
|
HTTPRequestHandlerFactory(Server & server_, const std::string & name_) : server(server_), log(&Logger::get(name_)), name(name_)
|
|
|
|
{
|
|
|
|
}
|
2014-07-16 00:53:56 +00:00
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
Poco::Net::HTTPRequestHandler * createRequestHandler(const Poco::Net::HTTPServerRequest & request) override
|
2012-12-14 11:21:07 +00:00
|
|
|
{
|
2017-03-03 18:59:42 +00:00
|
|
|
LOG_TRACE(log,
|
|
|
|
"HTTP Request for " << name << ". "
|
|
|
|
<< "Method: "
|
|
|
|
<< request.getMethod()
|
|
|
|
<< ", Address: "
|
|
|
|
<< request.clientAddress().toString()
|
|
|
|
<< ", User-Agent: "
|
|
|
|
<< (request.has("User-Agent") ? request.get("User-Agent") : "none"));
|
2012-12-14 11:21:07 +00:00
|
|
|
|
2015-11-05 20:08:18 +00:00
|
|
|
const auto & uri = request.getURI();
|
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET || request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD)
|
2015-09-25 16:28:17 +00:00
|
|
|
{
|
2015-11-05 20:08:18 +00:00
|
|
|
if (uri == "/" || uri == "/ping")
|
|
|
|
return new PingRequestHandler;
|
2016-07-14 05:22:09 +00:00
|
|
|
else if (startsWith(uri, "/replicas_status"))
|
2015-11-05 20:24:27 +00:00
|
|
|
return new ReplicasStatusHandler(*server.global_context);
|
2015-09-25 16:28:17 +00:00
|
|
|
}
|
2016-01-17 13:41:36 +00:00
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
if (uri.find('?') != std::string::npos || request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
|
2016-01-17 13:41:36 +00:00
|
|
|
{
|
|
|
|
return new HandlerType(server);
|
|
|
|
}
|
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
if (request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET || request.getMethod() == Poco::Net::HTTPRequest::HTTP_HEAD
|
2016-01-17 13:41:36 +00:00
|
|
|
|| request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
|
|
|
|
{
|
|
|
|
return new NotFoundHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2012-12-14 11:21:07 +00:00
|
|
|
}
|
|
|
|
};
|
2012-03-09 03:06:09 +00:00
|
|
|
|
|
|
|
|
2012-12-14 11:21:07 +00:00
|
|
|
class TCPConnectionFactory : public Poco::Net::TCPServerConnectionFactory
|
2012-03-09 15:46:52 +00:00
|
|
|
{
|
2012-12-14 11:21:07 +00:00
|
|
|
private:
|
|
|
|
Server & server;
|
|
|
|
Logger * log;
|
2014-07-16 00:53:56 +00:00
|
|
|
|
2012-12-14 11:21:07 +00:00
|
|
|
public:
|
2017-03-03 18:59:42 +00:00
|
|
|
TCPConnectionFactory(Server & server_) : server(server_), log(&Logger::get("TCPConnectionFactory"))
|
|
|
|
{
|
|
|
|
}
|
2012-03-09 15:46:52 +00:00
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
Poco::Net::TCPServerConnection * createConnection(const Poco::Net::StreamSocket & socket) override
|
2012-12-14 11:21:07 +00:00
|
|
|
{
|
2017-03-03 18:59:42 +00:00
|
|
|
LOG_TRACE(log,
|
|
|
|
"TCP Request. "
|
|
|
|
<< "Address: "
|
|
|
|
<< socket.peerAddress().toString());
|
2014-07-16 00:53:56 +00:00
|
|
|
|
2012-12-14 11:21:07 +00:00
|
|
|
return new TCPHandler(server, socket);
|
|
|
|
}
|
|
|
|
};
|
2012-03-09 15:46:52 +00:00
|
|
|
|
|
|
|
|
2016-12-13 18:51:19 +00:00
|
|
|
static std::string getCanonicalPath(std::string && path)
|
2012-03-09 03:06:09 +00:00
|
|
|
{
|
2014-12-21 03:18:40 +00:00
|
|
|
Poco::trimInPlace(path);
|
|
|
|
if (path.empty())
|
2016-10-25 12:27:09 +00:00
|
|
|
throw Exception("path configuration parameter is empty");
|
2014-12-21 03:18:40 +00:00
|
|
|
if (path.back() != '/')
|
|
|
|
path += '/';
|
2016-12-13 18:51:19 +00:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2017-01-09 13:42:29 +00:00
|
|
|
std::string Server::getDefaultCorePath() const
|
|
|
|
{
|
|
|
|
return getCanonicalPath(config().getString("path")) + "cores";
|
|
|
|
}
|
2016-12-13 18:51:19 +00:00
|
|
|
|
|
|
|
int Server::main(const std::vector<std::string> & args)
|
|
|
|
{
|
|
|
|
Logger * log = &logger();
|
2014-12-21 03:18:40 +00:00
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/** Context contains all that query execution is dependent:
|
|
|
|
* settings, available functions, data types, aggregate functions, databases...
|
|
|
|
*/
|
|
|
|
global_context = std::make_unique<Context>();
|
|
|
|
global_context->setGlobalContext(*global_context);
|
2016-11-11 17:01:02 +00:00
|
|
|
global_context->setApplicationType(Context::ApplicationType::SERVER);
|
2016-10-13 20:01:18 +00:00
|
|
|
|
2016-12-13 18:51:19 +00:00
|
|
|
std::string path = getCanonicalPath(config().getString("path"));
|
2016-10-13 20:01:18 +00:00
|
|
|
std::string default_database = config().getString("default_database", "default");
|
|
|
|
|
2016-12-13 18:51:19 +00:00
|
|
|
global_context->setPath(path);
|
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Create directories for 'path' and for default database, if not exist.
|
2016-10-25 12:27:09 +00:00
|
|
|
Poco::File(path + "data/" + default_database).createDirectories();
|
|
|
|
Poco::File(path + "metadata/" + default_database).createDirectories();
|
2016-10-13 20:01:18 +00:00
|
|
|
|
2014-12-21 03:18:40 +00:00
|
|
|
StatusFile status{path + "status"};
|
|
|
|
|
2016-11-03 19:59:53 +00:00
|
|
|
/// Try to increase limit on number of open files.
|
2014-04-15 16:39:56 +00:00
|
|
|
{
|
|
|
|
rlimit rlim;
|
|
|
|
if (getrlimit(RLIMIT_NOFILE, &rlim))
|
|
|
|
throw Poco::Exception("Cannot getrlimit");
|
|
|
|
|
|
|
|
if (rlim.rlim_cur == rlim.rlim_max)
|
|
|
|
{
|
|
|
|
LOG_DEBUG(log, "rlimit on number of file descriptors is " << rlim.rlim_cur);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rlim_t old = rlim.rlim_cur;
|
2016-11-03 19:59:53 +00:00
|
|
|
rlim.rlim_cur = config().getUInt("max_open_files", rlim.rlim_max);
|
|
|
|
int rc = setrlimit(RLIMIT_NOFILE, &rlim);
|
|
|
|
if (rc != 0)
|
2017-03-03 18:59:42 +00:00
|
|
|
LOG_WARNING(log,
|
|
|
|
std::string("Cannot set max number of file descriptors to ") + std::to_string(rlim.rlim_cur)
|
|
|
|
+ ". Try to specify max_open_files according to your system limits. error: "
|
|
|
|
+ strerror(errno));
|
2017-01-26 21:46:17 +00:00
|
|
|
else
|
2017-02-03 14:59:09 +00:00
|
|
|
LOG_DEBUG(log, "Set max number of file descriptors to " << rlim.rlim_cur << " (was " << old << ").");
|
2014-04-15 16:39:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-14 22:51:21 +00:00
|
|
|
static ServerErrorHandler error_handler;
|
|
|
|
Poco::ErrorHandler::set(&error_handler);
|
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Initialize DateLUT early, to not interfere with running time of first query.
|
2012-06-24 23:25:07 +00:00
|
|
|
LOG_DEBUG(log, "Initializing DateLUT.");
|
2014-07-08 23:52:53 +00:00
|
|
|
DateLUT::instance();
|
2012-06-24 23:25:07 +00:00
|
|
|
LOG_TRACE(log, "Initialized DateLUT.");
|
2012-03-09 03:56:12 +00:00
|
|
|
|
2016-08-10 00:47:00 +00:00
|
|
|
/// Directory with temporary data for processing of hard queries.
|
2015-12-08 01:43:39 +00:00
|
|
|
{
|
|
|
|
std::string tmp_path = config().getString("tmp_path", path + "tmp/");
|
|
|
|
global_context->setTemporaryPath(tmp_path);
|
|
|
|
Poco::File(tmp_path).createDirectories();
|
|
|
|
|
2016-08-10 00:47:00 +00:00
|
|
|
/// Clearing old temporary files.
|
2015-12-08 01:43:39 +00:00
|
|
|
Poco::DirectoryIterator dir_end;
|
|
|
|
for (Poco::DirectoryIterator it(tmp_path); it != dir_end; ++it)
|
|
|
|
{
|
2016-07-14 05:22:09 +00:00
|
|
|
if (it->isFile() && startsWith(it.name(), "tmp"))
|
2015-12-08 01:43:39 +00:00
|
|
|
{
|
|
|
|
LOG_DEBUG(log, "Removing old temporary file " << it->path());
|
|
|
|
it->remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-07 17:19:23 +00:00
|
|
|
|
2016-08-10 00:47:00 +00:00
|
|
|
/** Directory with 'flags': files indicating temporary settings for the server set by system administrator.
|
|
|
|
* Flags may be cleared automatically after being applied by the server.
|
|
|
|
* Examples: do repair of local data; clone all replicated tables from replica.
|
|
|
|
*/
|
2016-10-25 12:27:09 +00:00
|
|
|
Poco::File(path + "flags/").createDirectories();
|
2016-12-07 19:13:24 +00:00
|
|
|
global_context->setFlagsPath(path + "flags/");
|
2016-08-10 00:47:00 +00:00
|
|
|
|
2014-10-06 03:49:56 +00:00
|
|
|
bool has_zookeeper = false;
|
2016-10-25 12:27:09 +00:00
|
|
|
if (config().has("zookeeper"))
|
2014-10-06 03:49:56 +00:00
|
|
|
{
|
2015-04-16 07:32:40 +00:00
|
|
|
global_context->setZooKeeper(std::make_shared<zkutil::ZooKeeper>(config(), "zookeeper"));
|
2014-10-06 03:49:56 +00:00
|
|
|
has_zookeeper = true;
|
|
|
|
}
|
2014-03-21 19:17:59 +00:00
|
|
|
|
2016-10-25 12:27:09 +00:00
|
|
|
if (config().has("interserver_http_port"))
|
2014-04-03 08:47:59 +00:00
|
|
|
{
|
2015-08-11 21:11:54 +00:00
|
|
|
String this_host = config().getString("interserver_http_host", "");
|
|
|
|
|
|
|
|
if (this_host.empty())
|
2015-05-29 00:33:56 +00:00
|
|
|
{
|
|
|
|
this_host = getFQDNOrHostName();
|
2017-03-03 18:59:42 +00:00
|
|
|
LOG_DEBUG(log,
|
|
|
|
"Configuration parameter 'interserver_http_host' doesn't exist or exists and empty. Will use '" + this_host
|
|
|
|
+ "' as replica host.");
|
2015-05-29 00:33:56 +00:00
|
|
|
}
|
2014-04-03 08:47:59 +00:00
|
|
|
|
2014-05-12 00:49:24 +00:00
|
|
|
String port_str = config().getString("interserver_http_port");
|
2014-04-03 08:47:59 +00:00
|
|
|
int port = parse<int>(port_str);
|
|
|
|
|
2014-11-19 20:40:51 +00:00
|
|
|
if (port < 0 || port > 0xFFFF)
|
|
|
|
throw Exception("Out of range 'interserver_http_port': " + toString(port), ErrorCodes::ARGUMENT_OUT_OF_BOUND);
|
|
|
|
|
|
|
|
global_context->setInterserverIOAddress(this_host, port);
|
2014-04-03 08:47:59 +00:00
|
|
|
}
|
|
|
|
|
2014-08-11 15:59:01 +00:00
|
|
|
if (config().has("macros"))
|
|
|
|
global_context->setMacros(Macros(config(), "macros"));
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
/// Initialize automatic config updater
|
2016-10-25 12:27:09 +00:00
|
|
|
std::string main_config_path = config().getString("config-file", "config.xml");
|
|
|
|
std::string users_config_path = config().getString("users_config", main_config_path);
|
|
|
|
std::string include_from_path = config().getString("include_from", "/etc/metrika.xml");
|
|
|
|
auto config_reloader = std::make_unique<ConfigReloader>(main_config_path, users_config_path, include_from_path, global_context.get());
|
2013-08-12 00:36:18 +00:00
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Limit on total number of coucurrently executed queries.
|
2014-05-12 00:49:24 +00:00
|
|
|
global_context->getProcessList().setMaxSize(config().getInt("max_concurrent_queries", 0));
|
2013-09-03 20:21:28 +00:00
|
|
|
|
2017-01-19 19:11:12 +00:00
|
|
|
/// Setup protection to avoid accidental DROP for big tables (that are greater than 50 GB by default)
|
|
|
|
if (config().has("max_table_size_to_drop"))
|
|
|
|
global_context->setMaxTableSizeToDrop(config().getUInt64("max_table_size_to_drop"));
|
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Size of cache for uncompressed blocks. Zero means disabled.
|
2014-05-12 00:49:24 +00:00
|
|
|
size_t uncompressed_cache_size = parse<size_t>(config().getString("uncompressed_cache_size", "0"));
|
2013-09-08 05:53:10 +00:00
|
|
|
if (uncompressed_cache_size)
|
2013-09-14 05:14:22 +00:00
|
|
|
global_context->setUncompressedCache(uncompressed_cache_size);
|
2013-09-08 05:53:10 +00:00
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Size of cache for marks (index of MergeTree family of tables). It is necessary.
|
2014-06-04 13:39:56 +00:00
|
|
|
size_t mark_cache_size = parse<size_t>(config().getString("mark_cache_size"));
|
2014-02-11 13:30:42 +00:00
|
|
|
if (mark_cache_size)
|
|
|
|
global_context->setMarkCache(mark_cache_size);
|
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/// Load global settings from default profile.
|
2013-09-14 05:14:22 +00:00
|
|
|
Settings & settings = global_context->getSettingsRef();
|
2014-05-12 00:49:24 +00:00
|
|
|
global_context->setSetting("profile", config().getString("default_profile", "default"));
|
2012-10-22 20:08:28 +00:00
|
|
|
|
2016-10-25 12:27:09 +00:00
|
|
|
LOG_INFO(log, "Loading metadata.");
|
|
|
|
loadMetadata(*global_context);
|
|
|
|
LOG_DEBUG(log, "Loaded metadata.");
|
2016-08-09 21:48:05 +00:00
|
|
|
|
2016-10-25 12:27:09 +00:00
|
|
|
global_context->setCurrentDatabase(default_database);
|
|
|
|
|
|
|
|
/// Create system tables.
|
|
|
|
if (!global_context->isDatabaseExist("system"))
|
2016-10-24 14:01:24 +00:00
|
|
|
{
|
2016-10-25 12:27:09 +00:00
|
|
|
Poco::File(path + "data/system").createDirectories();
|
|
|
|
Poco::File(path + "metadata/system").createDirectories();
|
|
|
|
|
|
|
|
auto system_database = std::make_shared<DatabaseOrdinary>("system", path + "metadata/system/");
|
|
|
|
global_context->addDatabase("system", system_database);
|
|
|
|
|
|
|
|
/// 'has_force_restore_data_flag' is true, to not fail on loading query_log table, if it is corrupted.
|
|
|
|
system_database->loadTables(*global_context, nullptr, true);
|
2015-06-26 22:37:55 +00:00
|
|
|
}
|
2014-07-16 00:53:56 +00:00
|
|
|
|
2016-10-25 12:27:09 +00:00
|
|
|
DatabasePtr system_database = global_context->getDatabase("system");
|
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
system_database->attachTable("one", StorageSystemOne::create("one"));
|
|
|
|
system_database->attachTable("numbers", StorageSystemNumbers::create("numbers"));
|
|
|
|
system_database->attachTable("numbers_mt", StorageSystemNumbers::create("numbers_mt", true));
|
|
|
|
system_database->attachTable("tables", StorageSystemTables::create("tables"));
|
|
|
|
system_database->attachTable("parts", StorageSystemParts::create("parts"));
|
|
|
|
system_database->attachTable("databases", StorageSystemDatabases::create("databases"));
|
|
|
|
system_database->attachTable("processes", StorageSystemProcesses::create("processes"));
|
|
|
|
system_database->attachTable("settings", StorageSystemSettings::create("settings"));
|
|
|
|
system_database->attachTable("events", StorageSystemEvents::create("events"));
|
|
|
|
system_database->attachTable("metrics", StorageSystemMetrics::create("metrics"));
|
|
|
|
system_database->attachTable("merges", StorageSystemMerges::create("merges"));
|
|
|
|
system_database->attachTable("replicas", StorageSystemReplicas::create("replicas"));
|
2016-10-25 12:27:09 +00:00
|
|
|
system_database->attachTable("replication_queue", StorageSystemReplicationQueue::create("replication_queue"));
|
|
|
|
system_database->attachTable("dictionaries", StorageSystemDictionaries::create("dictionaries"));
|
2017-03-03 18:59:42 +00:00
|
|
|
system_database->attachTable("columns", StorageSystemColumns::create("columns"));
|
|
|
|
system_database->attachTable("functions", StorageSystemFunctions::create("functions"));
|
|
|
|
system_database->attachTable("clusters", StorageSystemClusters::create("clusters", *global_context));
|
|
|
|
system_database->attachTable("build_options", StorageSystemBuildOptions::create("build_options"));
|
2016-10-25 12:27:09 +00:00
|
|
|
|
|
|
|
if (has_zookeeper)
|
|
|
|
system_database->attachTable("zookeeper", StorageSystemZooKeeper::create("zookeeper"));
|
2014-10-06 03:49:56 +00:00
|
|
|
|
2016-03-01 17:47:53 +00:00
|
|
|
bool has_resharding_worker = false;
|
2016-01-28 01:00:42 +00:00
|
|
|
if (has_zookeeper && config().has("resharding"))
|
2016-01-28 01:00:27 +00:00
|
|
|
{
|
2016-01-28 01:00:42 +00:00
|
|
|
auto resharding_worker = std::make_shared<ReshardingWorker>(config(), "resharding", *global_context);
|
|
|
|
global_context->setReshardingWorker(resharding_worker);
|
|
|
|
resharding_worker->start();
|
2016-03-01 17:47:53 +00:00
|
|
|
has_resharding_worker = true;
|
2016-01-28 01:00:27 +00:00
|
|
|
}
|
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
SCOPE_EXIT({
|
2016-10-13 20:01:18 +00:00
|
|
|
/** Ask to cancel background jobs all table engines,
|
|
|
|
* and also query_log.
|
|
|
|
* It is important to do early, not in destructor of Context, because
|
|
|
|
* table engines could use Context on destroy.
|
2015-04-02 16:30:18 +00:00
|
|
|
*/
|
2017-03-03 21:10:41 +00:00
|
|
|
LOG_INFO(log, "Shutting down storages.");
|
|
|
|
global_context->shutdown();
|
|
|
|
LOG_DEBUG(log, "Shutted down storages.");
|
2015-04-02 16:30:18 +00:00
|
|
|
|
2016-10-13 20:01:18 +00:00
|
|
|
/** Explicitly destroy Context. It is more convenient than in destructor of Server, becuase logger is still available.
|
|
|
|
* At this moment, no one could own shared part of Context.
|
2015-04-02 16:30:18 +00:00
|
|
|
*/
|
|
|
|
global_context.reset();
|
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
LOG_DEBUG(log, "Destroyed global context.");
|
|
|
|
});
|
2015-04-02 16:30:18 +00:00
|
|
|
|
2013-09-14 05:14:22 +00:00
|
|
|
{
|
2014-05-12 00:49:24 +00:00
|
|
|
Poco::Timespan keep_alive_timeout(config().getInt("keep_alive_timeout", 10), 0);
|
2013-09-14 05:14:22 +00:00
|
|
|
|
2014-05-12 00:49:24 +00:00
|
|
|
Poco::ThreadPool server_pool(3, config().getInt("max_connections", 1024));
|
2014-03-21 13:42:14 +00:00
|
|
|
Poco::Net::HTTPServerParams::Ptr http_params = new Poco::Net::HTTPServerParams;
|
2013-09-14 05:14:22 +00:00
|
|
|
http_params->setTimeout(settings.receive_timeout);
|
|
|
|
http_params->setKeepAliveTimeout(keep_alive_timeout);
|
|
|
|
|
2017-03-03 00:24:56 +00:00
|
|
|
std::vector<std::unique_ptr<Poco::Net::TCPServer>> servers;
|
|
|
|
|
|
|
|
std::vector<std::string> listen_hosts;
|
|
|
|
Poco::Util::AbstractConfiguration::Keys config_keys;
|
|
|
|
config().keys("", config_keys);
|
|
|
|
for (const auto & key : config_keys)
|
|
|
|
{
|
|
|
|
if (!startsWith(key.data(), "listen_host"))
|
|
|
|
continue;
|
|
|
|
listen_hosts.emplace_back(config().getString(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listen_hosts.empty())
|
|
|
|
{
|
|
|
|
listen_hosts.emplace_back("::1");
|
|
|
|
listen_hosts.emplace_back("127.0.0.1");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto & listen_host : listen_hosts)
|
|
|
|
{
|
2017-03-03 00:39:42 +00:00
|
|
|
/// For testing purposes, user may omit tcp_port or http_port in configuration file.
|
2017-03-03 00:24:56 +00:00
|
|
|
|
2017-03-03 00:39:42 +00:00
|
|
|
/// HTTP
|
|
|
|
if (config().has("http_port"))
|
2016-06-25 03:06:36 +00:00
|
|
|
{
|
2017-03-03 00:39:42 +00:00
|
|
|
Poco::Net::SocketAddress http_socket_address;
|
|
|
|
|
|
|
|
try
|
2016-09-21 15:22:38 +00:00
|
|
|
{
|
2017-03-03 00:39:42 +00:00
|
|
|
http_socket_address = Poco::Net::SocketAddress(listen_host, config().getInt("http_port"));
|
|
|
|
}
|
|
|
|
catch (const Poco::Net::DNSException & e)
|
|
|
|
{
|
|
|
|
/// Better message when IPv6 is disabled on host.
|
|
|
|
if (e.code() == EAI_FAMILY
|
2017-03-03 18:59:42 +00:00
|
|
|
#if defined(EAI_ADDRFAMILY)
|
2017-03-03 00:39:42 +00:00
|
|
|
|| e.code() == EAI_ADDRFAMILY
|
2017-03-03 18:59:42 +00:00
|
|
|
#endif
|
|
|
|
)
|
2017-03-03 00:39:42 +00:00
|
|
|
{
|
2017-03-03 18:59:42 +00:00
|
|
|
LOG_ERROR(log,
|
|
|
|
"Cannot resolve listen_host (" << listen_host + "), error: " << e.message()
|
|
|
|
<< ". "
|
|
|
|
"If it is an IPv6 address and your host has disabled IPv6, then consider to "
|
|
|
|
"specify IPv4 address to listen in <listen_host> element of configuration "
|
|
|
|
"file. Example: <listen_host>0.0.0.0</listen_host>");
|
2017-03-03 00:39:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
throw;
|
2016-09-21 15:22:38 +00:00
|
|
|
}
|
|
|
|
|
2017-03-03 00:39:42 +00:00
|
|
|
Poco::Net::ServerSocket http_socket(http_socket_address);
|
|
|
|
http_socket.setReceiveTimeout(settings.receive_timeout);
|
|
|
|
http_socket.setSendTimeout(settings.send_timeout);
|
2017-03-03 00:24:56 +00:00
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
servers.emplace_back(new Poco::Net::HTTPServer(
|
|
|
|
new HTTPRequestHandlerFactory<HTTPHandler>(*this, "HTTPHandler-factory"), server_pool, http_socket, http_params));
|
2017-02-02 15:43:08 +00:00
|
|
|
|
|
|
|
LOG_INFO(log, "Listening http://" + http_socket_address.toString());
|
2017-03-03 00:39:42 +00:00
|
|
|
}
|
2016-06-25 03:06:36 +00:00
|
|
|
|
2017-03-03 00:39:42 +00:00
|
|
|
/// TCP
|
|
|
|
if (config().has("tcp_port"))
|
|
|
|
{
|
|
|
|
Poco::Net::SocketAddress tcp_address(listen_host, config().getInt("tcp_port"));
|
|
|
|
Poco::Net::ServerSocket tcp_socket(tcp_address);
|
|
|
|
tcp_socket.setReceiveTimeout(settings.receive_timeout);
|
|
|
|
tcp_socket.setSendTimeout(settings.send_timeout);
|
|
|
|
servers.emplace_back(
|
2017-03-03 18:59:42 +00:00
|
|
|
new Poco::Net::TCPServer(new TCPConnectionFactory(*this), server_pool, tcp_socket, new Poco::Net::TCPServerParams));
|
2017-02-02 15:43:08 +00:00
|
|
|
|
|
|
|
LOG_INFO(log, "Listening tcp: " + tcp_address.toString());
|
2017-03-03 00:39:42 +00:00
|
|
|
}
|
2016-09-21 15:22:38 +00:00
|
|
|
|
2017-03-03 00:24:56 +00:00
|
|
|
|
2017-03-03 00:39:42 +00:00
|
|
|
/// At least one of TCP and HTTP servers must be created.
|
|
|
|
if (servers.empty())
|
|
|
|
throw Exception("No 'tcp_port' and 'http_port' is specified in configuration file.", ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
|
|
|
|
|
|
|
/// Interserver IO HTTP
|
|
|
|
if (config().has("interserver_http_port"))
|
|
|
|
{
|
|
|
|
Poco::Net::SocketAddress interserver_address(listen_host, config().getInt("interserver_http_port"));
|
|
|
|
Poco::Net::ServerSocket interserver_io_http_socket(interserver_address);
|
|
|
|
interserver_io_http_socket.setReceiveTimeout(settings.receive_timeout);
|
|
|
|
interserver_io_http_socket.setSendTimeout(settings.send_timeout);
|
2017-03-03 18:59:42 +00:00
|
|
|
servers.emplace_back(new Poco::Net::HTTPServer(
|
2017-03-03 00:39:42 +00:00
|
|
|
new HTTPRequestHandlerFactory<InterserverIOHTTPHandler>(*this, "InterserverIOHTTPHandler-factory"),
|
|
|
|
server_pool,
|
|
|
|
interserver_io_http_socket,
|
|
|
|
http_params));
|
2013-09-14 05:14:22 +00:00
|
|
|
|
2017-02-02 15:43:08 +00:00
|
|
|
LOG_INFO(log, "Listening interserver: " + interserver_address.toString());
|
2017-03-03 00:39:42 +00:00
|
|
|
}
|
2014-03-21 13:42:14 +00:00
|
|
|
}
|
|
|
|
|
2017-03-03 00:24:56 +00:00
|
|
|
for (auto & server : servers)
|
|
|
|
server->start();
|
2013-09-14 05:14:22 +00:00
|
|
|
|
2015-04-02 16:41:07 +00:00
|
|
|
LOG_INFO(log, "Ready for connections.");
|
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
SCOPE_EXIT({
|
|
|
|
LOG_DEBUG(log, "Received termination signal.");
|
2016-03-02 20:08:38 +00:00
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
if (has_resharding_worker)
|
|
|
|
{
|
|
|
|
LOG_INFO(log, "Shutting down resharding thread");
|
|
|
|
auto & resharding_worker = global_context->getReshardingWorker();
|
|
|
|
if (resharding_worker.isStarted())
|
|
|
|
resharding_worker.shutdown();
|
|
|
|
LOG_DEBUG(log, "Shut down resharding thread");
|
|
|
|
}
|
2016-03-02 20:08:38 +00:00
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
LOG_DEBUG(log, "Waiting for current connections to close.");
|
2015-04-02 16:30:18 +00:00
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
is_cancelled = true;
|
2015-04-02 16:30:18 +00:00
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
for (auto & server : servers)
|
|
|
|
server->stop();
|
2016-10-23 10:52:32 +00:00
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
LOG_DEBUG(log, "Closed all connections.");
|
2016-10-23 10:52:32 +00:00
|
|
|
|
2017-03-03 21:10:41 +00:00
|
|
|
config_reloader.reset();
|
|
|
|
});
|
2015-04-02 16:30:18 +00:00
|
|
|
|
2015-03-27 13:11:22 +00:00
|
|
|
/// try to load dictionaries immediately, throw on error and die
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (!config().getBool("dictionaries_lazy_load", true))
|
|
|
|
{
|
2017-01-21 04:24:28 +00:00
|
|
|
global_context->tryCreateEmbeddedDictionaries();
|
2015-04-02 16:30:18 +00:00
|
|
|
global_context->tryCreateExternalDictionaries();
|
2015-03-27 13:11:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
LOG_ERROR(log, "Caught exception while loading dictionaries.");
|
2015-04-02 16:30:18 +00:00
|
|
|
throw;
|
2015-03-27 13:11:22 +00:00
|
|
|
}
|
2016-10-23 06:12:50 +00:00
|
|
|
|
|
|
|
/// This object will periodically calculate some metrics.
|
2016-10-24 04:06:27 +00:00
|
|
|
AsynchronousMetrics async_metrics(*global_context);
|
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
system_database->attachTable(
|
|
|
|
"asynchronous_metrics", StorageSystemAsynchronousMetrics::create("asynchronous_metrics", async_metrics));
|
2016-10-24 04:06:27 +00:00
|
|
|
|
2017-03-03 18:59:42 +00:00
|
|
|
const auto metrics_transmitter
|
|
|
|
= config().getBool("use_graphite", true) ? std::make_unique<MetricsTransmitter>(async_metrics) : nullptr;
|
2016-10-23 06:12:50 +00:00
|
|
|
|
|
|
|
waitForTerminationRequest();
|
2012-12-14 11:21:07 +00:00
|
|
|
}
|
2012-03-09 15:46:52 +00:00
|
|
|
|
2012-03-09 03:06:09 +00:00
|
|
|
return Application::EXIT_OK;
|
|
|
|
}
|
|
|
|
}
|
2016-10-31 19:54:49 +00:00
|
|
|
|
2016-11-11 17:01:02 +00:00
|
|
|
YANDEX_APP_SERVER_MAIN_FUNC(DB::Server, mainEntryClickHouseServer);
|