mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
types: Make seastar::inet_address the "native" type for CQL inet.
Fixes #3187 Requires seastar "inet_address: Add constructor and conversion function from/to IPv4" Implements support IPv6 for CQL inet data. The actual data stored will now vary between 4 and 16 bytes. gms::inet_address has been augumented to interop with seastar::inet_address, though of course actually trying to use an Ipv6 address there or in any of its tables with throw badly. Tests assuming ipv4 changed. Storing a ipv4_address should be transparent, as it now "widens". However, since all ipv4 is inet_address, but not vice versa, there is no implicit overloading on the read paths. I.e. tests and system_keyspace (where we read ip addresses from tables explicitly) are modified to use the proper type. Message-Id: <20180424161817.26316-1-calle@scylladb.com>
This commit is contained in:
committed by
Duarte Nunes
parent
9111c6e49a
commit
b1edf75c8b
@@ -68,6 +68,7 @@
|
||||
#include "log.hh"
|
||||
#include "serializer.hh"
|
||||
#include <core/enum.hh>
|
||||
#include <seastar/net/inet_address.hh>
|
||||
#include "service/storage_proxy.hh"
|
||||
#include "message/messaging_service.hh"
|
||||
#include "mutation_query.hh"
|
||||
@@ -996,8 +997,7 @@ static distributed<local_cache> _local_cache;
|
||||
static future<> build_dc_rack_info() {
|
||||
return execute_cql(sprint("SELECT peer, data_center, rack from system.%s", PEERS)).then([] (::shared_ptr<cql3::untyped_result_set> msg) {
|
||||
return do_for_each(*msg, [] (auto& row) {
|
||||
// Not ideal to assume ipv4 here, but currently this is what the cql types wraps.
|
||||
net::ipv4_address peer = row.template get_as<net::ipv4_address>("peer");
|
||||
net::inet_address peer = row.template get_as<net::inet_address>("peer");
|
||||
if (!row.has("data_center") || !row.has("rack")) {
|
||||
return make_ready_future<>();
|
||||
}
|
||||
@@ -1299,7 +1299,7 @@ future<std::unordered_map<gms::inet_address, std::unordered_set<dht::token>>> lo
|
||||
return execute_cql(req).then([] (::shared_ptr<cql3::untyped_result_set> cql_result) {
|
||||
std::unordered_map<gms::inet_address, std::unordered_set<dht::token>> ret;
|
||||
for (auto& row : *cql_result) {
|
||||
auto peer = gms::inet_address(row.get_as<net::ipv4_address>("peer"));
|
||||
auto peer = gms::inet_address(row.get_as<net::inet_address>("peer"));
|
||||
if (row.has("tokens")) {
|
||||
auto blob = row.get_blob("tokens");
|
||||
auto cdef = peers()->get_column_definition("tokens");
|
||||
@@ -1317,7 +1317,7 @@ future<std::unordered_map<gms::inet_address, utils::UUID>> load_host_ids() {
|
||||
return execute_cql(req).then([] (::shared_ptr<cql3::untyped_result_set> cql_result) {
|
||||
std::unordered_map<gms::inet_address, utils::UUID> ret;
|
||||
for (auto& row : *cql_result) {
|
||||
auto peer = gms::inet_address(row.get_as<net::ipv4_address>("peer"));
|
||||
auto peer = gms::inet_address(row.get_as<net::inet_address>("peer"));
|
||||
if (row.has("host_id")) {
|
||||
ret.emplace(peer, row.get_as<utils::UUID>("host_id"));
|
||||
}
|
||||
@@ -1332,7 +1332,7 @@ future<std::unordered_map<gms::inet_address, sstring>> load_peer_features() {
|
||||
std::unordered_map<gms::inet_address, sstring> ret;
|
||||
for (auto& row : *cql_result) {
|
||||
if (row.has("supported_features")) {
|
||||
ret.emplace(row.get_as<net::ipv4_address>("peer"),
|
||||
ret.emplace(row.get_as<net::inet_address>("peer"),
|
||||
row.get_as<sstring>("supported_features"));
|
||||
}
|
||||
}
|
||||
@@ -1354,8 +1354,8 @@ future<std::unordered_map<gms::inet_address, gms::inet_address>> get_preferred_i
|
||||
|
||||
for (auto& r : *cql_res_set) {
|
||||
if (r.has("preferred_ip")) {
|
||||
res.emplace(gms::inet_address(r.get_as<net::ipv4_address>("peer")),
|
||||
gms::inet_address(r.get_as<net::ipv4_address>("preferred_ip")));
|
||||
res.emplace(gms::inet_address(r.get_as<net::inet_address>("peer")),
|
||||
gms::inet_address(r.get_as<net::inet_address>("preferred_ip")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,18 @@
|
||||
*/
|
||||
|
||||
#include <seastar/net/inet_address.hh>
|
||||
#include <seastar/core/print.hh>
|
||||
#include <seastar/core/future.hh>
|
||||
#include "inet_address.hh"
|
||||
|
||||
using namespace seastar;
|
||||
|
||||
gms::inet_address::inet_address(const net::inet_address& in)
|
||||
: inet_address(in.as_ipv4_address())
|
||||
{}
|
||||
|
||||
future<gms::inet_address> gms::inet_address::lookup(sstring name) {
|
||||
return seastar::net::inet_address::find(name, seastar::net::inet_address::family::INET).then([](seastar::net::inet_address&& a) {
|
||||
::in_addr in = a;
|
||||
return make_ready_future<gms::inet_address>(net::ntoh(in.s_addr));
|
||||
return make_ready_future<gms::inet_address>(a);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
#include "utils/serialization.hh"
|
||||
#include <sstream>
|
||||
|
||||
namespace seastar::net {
|
||||
class inet_address;
|
||||
}
|
||||
|
||||
namespace gms {
|
||||
|
||||
class inet_address {
|
||||
@@ -49,11 +53,15 @@ public:
|
||||
throw std::invalid_argument("IPv6 socket addresses are not supported.");
|
||||
}
|
||||
}
|
||||
// Note: for now, will throw if given an ipv6 address
|
||||
inet_address(const seastar::net::inet_address&);
|
||||
|
||||
const net::ipv4_address& addr() const {
|
||||
return _addr;
|
||||
}
|
||||
|
||||
operator seastar::net::inet_address() const;
|
||||
|
||||
inet_address(const sstring& addr) {
|
||||
// FIXME: We need a real DNS resolver
|
||||
if (addr == "localhost") {
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include <seastar/net/inet_address.hh>
|
||||
|
||||
#include "tests/test-utils.hh"
|
||||
#include "tests/cql_test_env.hh"
|
||||
#include "tests/cql_assertions.hh"
|
||||
@@ -1586,7 +1588,7 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
ascii_type->decompose(sstring("ascii")), long_type->decompose(123456789l),
|
||||
from_hex("deadbeef"), boolean_type->decompose(true),
|
||||
double_type->decompose(3.14), float_type->decompose(3.14f),
|
||||
inet_addr_type->decompose(net::ipv4_address("127.0.0.1")),
|
||||
inet_addr_type->decompose(net::inet_address("127.0.0.1")),
|
||||
int32_type->decompose(3), utf8_type->decompose(sstring("zażółć gęślą jaźń")),
|
||||
timestamp_type->decompose(tp),
|
||||
timeuuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))),
|
||||
@@ -1638,7 +1640,7 @@ SEASTAR_TEST_CASE(test_types) {
|
||||
ascii_type->decompose(sstring("ascii2")), long_type->decompose(123456789l),
|
||||
from_hex("000000000000000c"), boolean_type->decompose(true),
|
||||
double_type->decompose(3.14), float_type->decompose(3.14f),
|
||||
inet_addr_type->decompose(net::ipv4_address("127.0.0.1")),
|
||||
inet_addr_type->decompose(net::inet_address("127.0.0.1")),
|
||||
int32_type->decompose(3), utf8_type->decompose(sstring("zażółć gęślą jaźń")),
|
||||
timestamp_type->decompose(tp),
|
||||
timeuuid_type->decompose(utils::UUID(sstring("d2177dd0-eaa2-11de-a572-001b779c76e3"))),
|
||||
@@ -2789,7 +2791,7 @@ SEASTAR_TEST_CASE(test_insert_json_types) {
|
||||
assert_that(msg).is_rows().with_rows({
|
||||
{
|
||||
ascii_type->decompose(sstring("ascii")),
|
||||
inet_addr_type->decompose(net::ipv4_address("127.0.0.1")), // note - case-sensitive columns go right after the key
|
||||
inet_addr_type->decompose(net::inet_address("127.0.0.1")), // note - case-sensitive columns go right after the key
|
||||
int32_type->decompose(3), utf8_type->decompose(sstring("zażółć gęślą jaźń")),
|
||||
long_type->decompose(123456789l),
|
||||
from_hex("deadbeef"), boolean_type->decompose(true),
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <seastar/net/inet_address.hh>
|
||||
#include "tests/test-utils.hh"
|
||||
#include "sstable_test.hh"
|
||||
#include "sstables/key.hh"
|
||||
@@ -506,7 +507,7 @@ SEASTAR_TEST_CASE(broken_ranges_collection) {
|
||||
return repeat([s, reader] {
|
||||
return read_mutation_from_flat_mutation_reader(*reader).then([s, reader] (mutation_opt mut) {
|
||||
auto key_equal = [s, &mut] (sstring ip) {
|
||||
return mut->key().equal(*s, partition_key::from_deeply_exploded(*s, { net::ipv4_address(ip) }));
|
||||
return mut->key().equal(*s, partition_key::from_deeply_exploded(*s, { net::inet_address(ip) }));
|
||||
};
|
||||
|
||||
if (!mut) {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <seastar/tests/test-utils.hh>
|
||||
#include <seastar/net/inet_address.hh>
|
||||
#include <utils/UUID_gen.hh>
|
||||
#include <boost/asio/ip/address_v4.hpp>
|
||||
#include <net/ip.hh>
|
||||
@@ -220,7 +221,7 @@ BOOST_AUTO_TEST_CASE(test_uuid_type_string_conversions) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_inet_type_string_conversions) {
|
||||
net::ipv4_address addr("127.0.0.1");
|
||||
net::inet_address addr("127.0.0.1");
|
||||
BOOST_REQUIRE(inet_addr_type->equal(inet_addr_type->from_string("127.0.0.1"), inet_addr_type->decompose(addr)));
|
||||
|
||||
test_parsing_fails(inet_addr_type, "something");
|
||||
|
||||
72
types.cc
72
types.cc
@@ -45,6 +45,7 @@
|
||||
#include <boost/locale/encoding_utf.hpp>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include <boost/algorithm/cxx11/any_of.hpp>
|
||||
#include <seastar/net/inet_address.hh>
|
||||
#include "utils/big_decimal.hh"
|
||||
#include "utils/date.h"
|
||||
#include "mutation_partition.hh"
|
||||
@@ -78,7 +79,7 @@ sstring boolean_to_string(const bool b) {
|
||||
return b ? "true" : "false";
|
||||
}
|
||||
|
||||
sstring inet_to_string(const net::ipv4_address& addr) {
|
||||
sstring inet_to_string(const seastar::net::inet_address& addr) {
|
||||
std::ostringstream out;
|
||||
out << addr;
|
||||
return out.str();
|
||||
@@ -1168,39 +1169,59 @@ struct uuid_type_impl : concrete_type<utils::UUID> {
|
||||
}
|
||||
};
|
||||
|
||||
struct inet_addr_type_impl : concrete_type<net::ipv4_address> {
|
||||
inet_addr_type_impl() : concrete_type<net::ipv4_address>(inet_addr_type_name) {}
|
||||
using inet_address = seastar::net::inet_address;
|
||||
|
||||
struct inet_addr_type_impl : concrete_type<inet_address> {
|
||||
inet_addr_type_impl() : concrete_type<inet_address>(inet_addr_type_name) {}
|
||||
virtual void serialize(const void* value, bytes::iterator& out) const override {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
// FIXME: support ipv6
|
||||
auto& ipv4e = from_value(value);
|
||||
if (ipv4e.empty()) {
|
||||
auto& ipv = from_value(value);
|
||||
if (ipv.empty()) {
|
||||
return;
|
||||
}
|
||||
auto& ipv4 = ipv4e.get();
|
||||
uint32_t u = htonl(ipv4.ip);
|
||||
out = std::copy_n(reinterpret_cast<const char*>(&u), sizeof(u), out);
|
||||
auto& ip = ipv.get();
|
||||
switch (ip.in_family()) {
|
||||
case inet_address::family::INET:
|
||||
{
|
||||
const ::in_addr& in = ip;
|
||||
out = std::copy_n(reinterpret_cast<const char*>(&in.s_addr), sizeof(in.s_addr), out);
|
||||
break;
|
||||
}
|
||||
case inet_address::family::INET6:
|
||||
{
|
||||
const ::in6_addr& i6 = ip;
|
||||
out = std::copy_n(i6.s6_addr, ip.size(), out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual size_t serialized_size(const void* value) const override {
|
||||
if (!value || from_value(value).empty()) {
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
return 4;
|
||||
// FIXME: support ipv6
|
||||
auto& ipv = from_value(value);
|
||||
if (ipv.empty()) {
|
||||
return 0;
|
||||
}
|
||||
return ipv.get().size();
|
||||
}
|
||||
virtual data_value deserialize(bytes_view v) const override {
|
||||
if (v.empty()) {
|
||||
return make_empty();
|
||||
}
|
||||
if (v.size() == 16) {
|
||||
throw std::runtime_error("IPv6 addresses not supported");
|
||||
switch (v.size()) {
|
||||
case 4:
|
||||
// gah. read_simple_be, please...
|
||||
return make_value(inet_address(::in_addr{net::hton(read_simple<uint32_t>(v))}));
|
||||
case 16:
|
||||
return make_value(inet_address(*reinterpret_cast<const ::in6_addr *>(v.data())));
|
||||
default:
|
||||
throw marshal_exception(sprint("Cannot deserialize inet_address, unsupported size %d bytes", v.size()));
|
||||
}
|
||||
auto ip = read_simple<int32_t>(v);
|
||||
if (!v.empty()) {
|
||||
throw marshal_exception(sprint("Cannot deserialize inet_addr, %d bytes left", v.size()));
|
||||
}
|
||||
return make_value(net::ipv4_address(ip));
|
||||
}
|
||||
virtual bool less(bytes_view v1, bytes_view v2) const override {
|
||||
return less_unsigned(v1, v2);
|
||||
@@ -1215,7 +1236,7 @@ struct inet_addr_type_impl : concrete_type<net::ipv4_address> {
|
||||
return std::hash<bytes_view>()(v);
|
||||
}
|
||||
virtual void validate(bytes_view v) const override {
|
||||
if (v.size() != 0 && v.size() != sizeof(uint32_t)) {
|
||||
if (v.size() != 0 && v.size() != sizeof(uint32_t) && v.size() != 16) {
|
||||
throw marshal_exception(sprint("Validation failed for inet_addr - got %d bytes", v.size()));
|
||||
}
|
||||
}
|
||||
@@ -1224,15 +1245,15 @@ struct inet_addr_type_impl : concrete_type<net::ipv4_address> {
|
||||
if (s.empty()) {
|
||||
return bytes();
|
||||
}
|
||||
native_type ipv4;
|
||||
native_type ip;
|
||||
try {
|
||||
ipv4 = net::ipv4_address(std::string(s.data(), s.size()));
|
||||
ip = inet_address(std::string(s.data(), s.size()));
|
||||
} catch (...) {
|
||||
throw marshal_exception(sprint("Failed to parse inet_addr from '%s'", s));
|
||||
}
|
||||
bytes b(bytes::initialized_later(), sizeof(uint32_t));
|
||||
bytes b(bytes::initialized_later(), ip.get().size());
|
||||
auto out = b.begin();
|
||||
serialize(&ipv4, out);
|
||||
serialize(&ip, out);
|
||||
return b;
|
||||
}
|
||||
virtual sstring to_string(const bytes& b) const override {
|
||||
@@ -3648,7 +3669,10 @@ data_value::data_value(float v) : data_value(make_new(float_type, v)) {
|
||||
data_value::data_value(double v) : data_value(make_new(double_type, v)) {
|
||||
}
|
||||
|
||||
data_value::data_value(net::ipv4_address v) : data_value(make_new(inet_addr_type, v)) {
|
||||
data_value::data_value(seastar::net::inet_address v) : data_value(make_new(inet_addr_type, v)) {
|
||||
}
|
||||
|
||||
data_value::data_value(seastar::net::ipv4_address v) : data_value(seastar::net::inet_address(v)) {
|
||||
}
|
||||
|
||||
data_value::data_value(simple_date_native_type v) : data_value(make_new(simple_date_type, v.days)) {
|
||||
@@ -3867,7 +3891,7 @@ std::function<data_value(data_value)> make_castas_fctn_from_boolean_to_string()
|
||||
|
||||
std::function<data_value(data_value)> make_castas_fctn_from_inet_to_string() {
|
||||
return [](data_value from) -> data_value {
|
||||
return inet_to_string(value_cast<net::ipv4_address>(from));
|
||||
return inet_to_string(value_cast<inet_address>(from));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
4
types.hh
4
types.hh
@@ -44,6 +44,7 @@
|
||||
#include <boost/range/numeric.hpp>
|
||||
#include <boost/range/combine.hpp>
|
||||
#include "net/ip.hh"
|
||||
#include <seastar/net/inet_address.hh>
|
||||
#include "util/backtrace.hh"
|
||||
#include "hashing.hh"
|
||||
#include <boost/multiprecision/cpp_int.hpp> // FIXME: remove somehow
|
||||
@@ -374,6 +375,7 @@ public:
|
||||
data_value(float);
|
||||
data_value(double);
|
||||
data_value(net::ipv4_address);
|
||||
data_value(seastar::net::inet_address);
|
||||
data_value(simple_date_native_type);
|
||||
data_value(timestamp_native_type);
|
||||
data_value(timeuuid_native_type);
|
||||
@@ -1283,7 +1285,7 @@ shared_ptr<const abstract_type> data_type_for<timeuuid_native_type>() {
|
||||
|
||||
template <>
|
||||
inline
|
||||
shared_ptr<const abstract_type> data_type_for<net::ipv4_address>() {
|
||||
shared_ptr<const abstract_type> data_type_for<net::inet_address>() {
|
||||
return inet_addr_type;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user