/* * Copyright (C) 2020-present ScyllaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #include "thrift/controller.hh" #include #include "thrift/server.hh" #include "replica/database.hh" #include "db/config.hh" #include "log.hh" static logging::logger clogger("thrift_controller"); thrift_controller::thrift_controller(distributed& db, sharded& auth, sharded& qp, sharded& ml, sharded& ss, sharded& proxy) : _ops_sem(1) , _db(db) , _auth_service(auth) , _qp(qp) , _mem_limiter(ml) , _ss(ss) , _proxy(proxy) { } sstring thrift_controller::name() const { return "rpc"; } sstring thrift_controller::protocol() const { return "thrift"; } sstring thrift_controller::protocol_version() const { return ::cassandra::thrift_version; } std::vector thrift_controller::listen_addresses() const { if (_server && _addr) { return {*_addr}; } return {}; } future<> thrift_controller::start_server() { if (!_ops_sem.try_wait()) { throw std::runtime_error(format("Thrift server is stopping, try again later")); } return do_start_server().finally([this] { _ops_sem.signal(); }); } future<> thrift_controller::do_start_server() { if (_server) { return make_ready_future<>(); } return seastar::async([this] { auto tserver = std::make_unique>(); _addr.reset(); auto& cfg = _db.local().get_config(); auto preferred = cfg.rpc_interface_prefer_ipv6() ? std::make_optional(net::inet_address::family::INET6) : std::nullopt; auto family = cfg.enable_ipv6_dns_lookup() || preferred ? std::nullopt : std::make_optional(net::inet_address::family::INET); auto keepalive = cfg.rpc_keepalive(); auto ip = utils::resolve(cfg.rpc_address, family, preferred).get(); auto port = cfg.rpc_port(); _addr.emplace(ip, port); auto tsc = sharded_parameter([&cfg] { return thrift_server_config { .timeout_config = updateable_timeout_config(cfg), .max_request_size = cfg.thrift_max_message_length_in_mb() * (uint64_t(1) << 20), }; }); tserver->start(sharded_parameter([this] { return _db.local().as_data_dictionary(); }), std::ref(_qp), std::ref(_ss), std::ref(_proxy), std::ref(_auth_service), std::ref(_mem_limiter), std::move(tsc)).get(); // #293 - do not stop anything //engine().at_exit([tserver] { // return tserver->stop(); //}); tserver->invoke_on_all(&thrift_server::listen, socket_address{ip, port}, keepalive).get(); clogger.info("Thrift server listening on {}:{} ...", ip, port); _server = std::move(tserver); }); } future<> thrift_controller::stop_server() { assert(this_shard_id() == 0); if (_stopped) { return make_ready_future<>(); } return _ops_sem.wait().then([this] { _stopped = true; _ops_sem.broken(); _addr.reset(); return do_stop_server(); }); } future<> thrift_controller::request_stop_server() { if (!_ops_sem.try_wait()) { throw std::runtime_error(format("Thrift server is starting, try again later")); } return do_stop_server().finally([this] { _ops_sem.signal(); }); } future<> thrift_controller::do_stop_server() { return do_with(std::move(_server), [] (std::unique_ptr>& tserver) { if (tserver) { return tserver->stop().then([] { clogger.info("Thrift server stopped"); }); } return make_ready_future<>(); }); }