Files
scylladb/message/messaging_service.cc

304 lines
13 KiB
C++

/*
* Copyright (C) 2015 Cloudius Systems, Ltd.
*/
#include "message/messaging_service.hh"
#include "core/distributed.hh"
#include "gms/failure_detector.hh"
#include "gms/gossiper.hh"
#include "service/storage_service.hh"
#include "streaming/messages/stream_init_message.hh"
#include "streaming/messages/prepare_message.hh"
#include "gms/gossip_digest_syn.hh"
#include "gms/gossip_digest_ack.hh"
#include "gms/gossip_digest_ack2.hh"
#include "query-request.hh"
#include "query-result.hh"
namespace net {
using inet_address = gms::inet_address;
using gossip_digest_syn = gms::gossip_digest_syn;
using gossip_digest_ack = gms::gossip_digest_ack;
using gossip_digest_ack2 = gms::gossip_digest_ack2;
future<> ser_messaging_verb(output_stream<char>& out, messaging_verb& v) {
bytes b(bytes::initialized_later(), sizeof(v));
auto _out = b.begin();
serialize_int32(_out, int32_t(v));
return out.write(reinterpret_cast<const char*>(b.c_str()), sizeof(v));
}
future<> des_messaging_verb(input_stream<char>& in, messaging_verb& v) {
return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
if (buf.size() != sizeof(v)) {
throw rpc::closed_error();
}
bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sizeof(v));
v = messaging_verb(read_simple<int32_t>(bv));
});
}
future<> ser_sstring(output_stream<char>& out, sstring& v) {
auto serialize_string_size = serialize_int16_size + v.size();
auto sz = serialize_int16_size + serialize_string_size;
bytes b(bytes::initialized_later(), sz);
auto _out = b.begin();
serialize_int16(_out, serialize_string_size);
serialize_string(_out, v);
return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
}
future<> des_sstring(input_stream<char>& in, sstring& v) {
return in.read_exactly(serialize_int16_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
if (buf.size() != serialize_int16_size) {
throw rpc::closed_error();
}
size_t serialize_string_size = net::ntoh(*reinterpret_cast<const net::packed<int16_t>*>(buf.get()));
return in.read_exactly(serialize_string_size).then([serialize_string_size, &v]
(temporary_buffer<char> buf) mutable {
if (buf.size() != serialize_string_size) {
throw rpc::closed_error();
}
bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), serialize_string_size);
new (&v) sstring(read_simple_short_string(bv));
return make_ready_future<>();
});
});
}
distributed<messaging_service> _the_messaging_service;
future<> deinit_messaging_service() {
return gms::get_gossiper().stop().then([] {
return gms::get_failure_detector().stop();
}).then([] {
return net::get_messaging_service().stop();
}).then([]{
return service::deinit_storage_service();
});
}
future<> init_messaging_service(sstring listen_address, db::config::seed_provider_type seed_provider) {
const gms::inet_address listen(listen_address);
std::set<gms::inet_address> seeds;
if (seed_provider.parameters.count("seeds") > 0) {
size_t begin = 0;
size_t next = 0;
sstring& seeds_str = seed_provider.parameters.find("seeds")->second;
while (begin < seeds_str.length() && begin != (next=seeds_str.find(",",begin))) {
seeds.emplace(gms::inet_address(seeds_str.substr(begin,next-begin)));
begin = next+1;
}
}
if (seeds.empty()) {
seeds.emplace(gms::inet_address("127.0.0.1"));
}
engine().at_exit([]{
return deinit_messaging_service();
});
return net::get_messaging_service().start(listen).then([seeds] {
auto& ms = net::get_local_messaging_service();
print("Messaging server listening on ip %s port %d ...\n", ms.listen_address(), ms.port());
return gms::get_failure_detector().start().then([seeds] {
return gms::get_gossiper().start().then([seeds] {
auto& gossiper = gms::get_local_gossiper();
gossiper.set_seeds(seeds);
});
});
});
}
bool operator==(const shard_id& x, const shard_id& y) {
return x.addr == y.addr && x.cpu_id == y.cpu_id ;
}
bool operator<(const shard_id& x, const shard_id& y) {
if (x.addr < y.addr) {
return true;
} else if (y.addr < x.addr) {
return false;
} else {
return x.cpu_id < y.cpu_id;
}
}
std::ostream& operator<<(std::ostream& os, const shard_id& x) {
return os << x.addr << ":" << x.cpu_id;
}
size_t shard_id::hash::operator()(const shard_id& id) const {
return std::hash<uint32_t>()(id.cpu_id) + std::hash<uint32_t>()(id.addr.raw_addr());
}
messaging_service::shard_info::shard_info(std::unique_ptr<rpc_protocol_client_wrapper>&& client)
: rpc_client(std::move(client)) {
}
void messaging_service::foreach_client(std::function<void(const shard_id& id, const shard_info& info)> f) const {
for (auto i = _clients.cbegin(); i != _clients.cend(); i++) {
f(i->first, i->second);
}
}
void messaging_service::increment_dropped_messages(messaging_verb verb) {
_dropped_messages[static_cast<int32_t>(verb)]++;
}
uint64_t messaging_service::get_dropped_messages(messaging_verb verb) const {
return _dropped_messages[static_cast<int32_t>(verb)];
}
const uint64_t* messaging_service::get_dropped_messages() const {
return _dropped_messages;
}
int32_t messaging_service::get_raw_version(const gms::inet_address& endpoint) const {
// FIXME: messaging service versioning
return current_version;
}
bool messaging_service::knows_version(const gms::inet_address& endpoint) const {
// FIXME: messaging service versioning
return true;
}
messaging_service::messaging_service(gms::inet_address ip)
: _listen_address(ip)
, _port(_default_port)
, _rpc(new rpc_protocol_wrapper(serializer{}))
, _server(new rpc_protocol_server_wrapper(*_rpc, ipv4_addr{_listen_address.raw_addr(), _port})) {
}
messaging_service::~messaging_service() = default;
uint16_t messaging_service::port() {
return _port;
}
gms::inet_address messaging_service::listen_address() {
return _listen_address;
}
future<> messaging_service::stop() {
return when_all(_server->stop(),
parallel_for_each(_clients, [](std::pair<const shard_id, shard_info>& c) {
return c.second.rpc_client->stop();
})
).discard_result();
}
rpc::no_wait_type messaging_service::no_wait() {
return rpc::no_wait;
}
messaging_service::rpc_protocol_client_wrapper& messaging_service::get_rpc_client(shard_id id) {
auto it = _clients.find(id);
if (it == _clients.end()) {
auto remote_addr = ipv4_addr(id.addr.raw_addr(), _port);
auto client = std::make_unique<rpc_protocol_client_wrapper>(*_rpc, remote_addr, ipv4_addr{_listen_address.raw_addr(), 0});
it = _clients.emplace(id, shard_info(std::move(client))).first;
return *it->second.rpc_client;
} else {
return *it->second.rpc_client;
}
}
void messaging_service::remove_rpc_client(shard_id id) {
_clients.erase(id);
}
void messaging_service::register_stream_init_message(std::function<future<unsigned> (streaming::messages::stream_init_message msg, unsigned src_cpu_id)>&& func) {
register_handler(messaging_verb::STREAM_INIT_MESSAGE, std::move(func));
}
future<unsigned> messaging_service::send_stream_init_message(shard_id id, streaming::messages::stream_init_message msg, unsigned src_cpu_id) {
return send_message<unsigned>(messaging_verb::STREAM_INIT_MESSAGE, std::move(id), std::move(msg), std::move(src_cpu_id));
}
void messaging_service::register_prepare_message(std::function<future<streaming::messages::prepare_message> (streaming::messages::prepare_message msg, UUID plan_id,
inet_address from, inet_address connecting, unsigned dst_cpu_id)>&& func) {
register_handler(messaging_verb::PREPARE_MESSAGE, std::move(func));
}
future<streaming::messages::prepare_message> messaging_service::send_prepare_message(shard_id id, streaming::messages::prepare_message msg, UUID plan_id,
inet_address from, inet_address connecting, unsigned dst_cpu_id) {
return send_message<streaming::messages::prepare_message>(messaging_verb::PREPARE_MESSAGE, std::move(id), std::move(msg),
std::move(plan_id), std::move(from), std::move(connecting), std::move(dst_cpu_id));
}
void messaging_service::register_stream_mutation(std::function<future<> (frozen_mutation fm, unsigned dst_cpu_id)>&& func) {
register_handler(messaging_verb::STREAM_MUTATION, std::move(func));
}
future<> messaging_service::send_stream_mutation(shard_id id, frozen_mutation fm, unsigned dst_cpu_id) {
return send_message<void>(messaging_verb::STREAM_MUTATION, std::move(id), std::move(fm), std::move(dst_cpu_id));
}
void messaging_service::register_echo(std::function<future<> ()>&& func) {
register_handler(messaging_verb::ECHO, std::move(func));
}
future<> messaging_service::send_echo(shard_id id) {
return send_message<void>(messaging_verb::ECHO, std::move(id));
}
void messaging_service::register_gossip_shutdown(std::function<rpc::no_wait_type (inet_address from)>&& func) {
register_handler(messaging_verb::GOSSIP_SHUTDOWN, std::move(func));
}
future<> messaging_service::send_gossip_shutdown(shard_id id, inet_address from) {
return send_message_oneway(messaging_verb::GOSSIP_SHUTDOWN, std::move(id), std::move(from));
}
void messaging_service::register_gossip_digest_syn(std::function<future<gossip_digest_ack> (gossip_digest_syn)>&& func) {
register_handler(messaging_verb::GOSSIP_DIGEST_SYN, std::move(func));
}
future<gossip_digest_ack> messaging_service::send_gossip_digest_syn(shard_id id, gossip_digest_syn msg) {
return send_message<gossip_digest_ack>(messaging_verb::GOSSIP_DIGEST_SYN, std::move(id), std::move(msg));
}
void messaging_service::register_gossip_digest_ack2(std::function<rpc::no_wait_type (gossip_digest_ack2)>&& func) {
register_handler(messaging_verb::GOSSIP_DIGEST_ACK2, std::move(func));
}
future<> messaging_service::send_gossip_digest_ack2(shard_id id, gossip_digest_ack2 msg) {
return send_message_oneway(messaging_verb::GOSSIP_DIGEST_ACK2, std::move(id), std::move(msg));
}
void messaging_service::register_definitions_update(std::function<rpc::no_wait_type (std::vector<frozen_mutation> fm)>&& func) {
register_handler(net::messaging_verb::DEFINITIONS_UPDATE, std::move(func));
}
future<> messaging_service::send_definitions_update(shard_id id, std::vector<frozen_mutation> fm) {
return send_message_oneway(messaging_verb::DEFINITIONS_UPDATE, std::move(id), std::move(fm));
}
void messaging_service::register_mutation(std::function<rpc::no_wait_type (frozen_mutation fm, std::vector<inet_address> forward,
inet_address reply_to, unsigned shard, response_id_type response_id)>&& func) {
register_handler(net::messaging_verb::MUTATION, std::move(func));
}
future<> messaging_service::send_mutation(shard_id id, const frozen_mutation& fm, std::vector<inet_address> forward,
inet_address reply_to, unsigned shard, response_id_type response_id) {
return send_message_oneway(messaging_verb::MUTATION, std::move(id), fm, std::move(forward),
std::move(reply_to), std::move(shard), std::move(response_id));
}
void messaging_service::register_mutation_done(std::function<rpc::no_wait_type (rpc::client_info cinfo, unsigned shard, response_id_type response_id)>&& func) {
register_handler(net::messaging_verb::MUTATION_DONE, std::move(func));
}
future<> messaging_service::send_mutation_done(shard_id id, unsigned shard, response_id_type response_id) {
return send_message_oneway(messaging_verb::MUTATION_DONE, std::move(id), std::move(shard), std::move(response_id));
}
void messaging_service::register_read_data(std::function<future<foreign_ptr<lw_shared_ptr<query::result>>> (query::read_command cmd, query::partition_range pr)>&& func) {
register_handler(net::messaging_verb::READ_DATA, std::move(func));
}
future<query::result> messaging_service::send_read_data(shard_id id, query::read_command& cmd, query::partition_range& pr) {
return send_message<query::result>(messaging_verb::READ_DATA, std::move(id), cmd, pr);
}
void messaging_service::register_read_mutation_data(std::function<future<foreign_ptr<lw_shared_ptr<reconcilable_result>>> (query::read_command cmd, query::partition_range pr)>&& func) {
register_handler(net::messaging_verb::READ_MUTATION_DATA, std::move(func));
}
future<reconcilable_result> messaging_service::send_read_mutation_data(shard_id id, query::read_command& cmd, query::partition_range& pr) {
return send_message<reconcilable_result>(messaging_verb::READ_MUTATION_DATA, std::move(id), cmd, pr);
}
} // namespace net