Skip to content

Commit 07f8ade

Browse files
mpenickabsurdfarce
andauthored
Fix SNI events (#513)
* Fix events when using SNI routing The address in status/topology events needs to be mapped to internal SNI address so that nodes will be properly added and removed. * Additional fixes * Formatting fix * Simplify logic Co-authored-by: Bret McGuire <[email protected]>
1 parent cf594b7 commit 07f8ade

File tree

7 files changed

+73
-38
lines changed

7 files changed

+73
-38
lines changed

src/address_factory.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020

2121
using namespace datastax::internal::core;
2222

23-
bool DefaultAddressFactory::create(const Row* peers_row, const Host::Ptr& connected_host,
24-
Address* output) {
23+
bool AddressFactory::create(const Row* peers_row, const Host::Ptr& connected_host,
24+
Address* output) {
2525
Address connected_address = connected_host->address();
2626
const Value* peer_value = peers_row->get_by_name("peer");
2727
const Value* rpc_value = peers_row->get_by_name("rpc_address");
@@ -59,6 +59,12 @@ bool DefaultAddressFactory::create(const Row* peers_row, const Host::Ptr& connec
5959
return true;
6060
}
6161

62+
bool AddressFactory::is_peer(const Row* peers_row, const Host::Ptr& connected_host,
63+
const Address& expected) {
64+
Address address;
65+
return create(peers_row, connected_host, &address) && address == expected;
66+
}
67+
6268
bool SniAddressFactory::create(const Row* peers_row, const Host::Ptr& connected_host,
6369
Address* output) {
6470
CassUuid host_id;
@@ -78,3 +84,14 @@ bool SniAddressFactory::create(const Row* peers_row, const Host::Ptr& connected_
7884
connected_host->address().port(), to_string(host_id));
7985
return true;
8086
}
87+
88+
bool SniAddressFactory::is_peer(const Row* peers_row, const Host::Ptr& connected_host,
89+
const Address& expected) {
90+
const Value* value = peers_row->get_by_name("rpc_address");
91+
Address rpc_address;
92+
if (!value ||
93+
!value->decoder().as_inet(value->size(), connected_host->address().port(), &rpc_address)) {
94+
return false;
95+
}
96+
return rpc_address == expected;
97+
}

src/address_factory.hpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,15 @@ namespace datastax { namespace internal { namespace core {
2626
class Row;
2727

2828
/**
29-
* An interface for constructing `Address` from `system.local`/`system.peers` row data.
29+
* An address factory that creates `Address` using the `rpc_address` column.
3030
*/
3131
class AddressFactory : public RefCounted<AddressFactory> {
3232
public:
3333
typedef SharedRefPtr<AddressFactory> Ptr;
3434
virtual ~AddressFactory() {}
35-
virtual bool create(const Row* peers_row, const Host::Ptr& connected_host, Address* output) = 0;
36-
};
37-
38-
/**
39-
* An address factory that creates `Address` using the `rpc_address` column.
40-
*/
41-
class DefaultAddressFactory : public AddressFactory {
4235
virtual bool create(const Row* peers_row, const Host::Ptr& connected_host, Address* output);
36+
virtual bool is_peer(const Row* peers_row, const Host::Ptr& connected_host,
37+
const Address& expected);
4338
};
4439

4540
/**
@@ -48,13 +43,15 @@ class DefaultAddressFactory : public AddressFactory {
4843
*/
4944
class SniAddressFactory : public AddressFactory {
5045
virtual bool create(const Row* peers_row, const Host::Ptr& connected_host, Address* output);
46+
virtual bool is_peer(const Row* peers_row, const Host::Ptr& connected_host,
47+
const Address& expected);
5148
};
5249

5350
inline AddressFactory* create_address_factory_from_config(const Config& config) {
5451
if (config.cloud_secure_connection_config().is_loaded()) {
5552
return new SniAddressFactory();
5653
} else {
57-
return new DefaultAddressFactory();
54+
return new AddressFactory();
5855
}
5956
}
6057

src/cluster.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,17 @@ LockedHostMap::LockedHostMap(const HostMap& hosts)
169169
LockedHostMap::~LockedHostMap() { uv_mutex_destroy(&mutex_); }
170170

171171
LockedHostMap::const_iterator LockedHostMap::find(const Address& address) const {
172-
return hosts_.find(address);
172+
HostMap::const_iterator it = hosts_.find(address);
173+
if (it == hosts_.end()) {
174+
// If this is from an event (not SNI) and we're using SNI addresses then fallback to using the
175+
// "rpc_address" to compare.
176+
for (HostMap::const_iterator i = hosts_.begin(), end = hosts_.end(); i != end; ++i) {
177+
if (i->second->rpc_address() == address) {
178+
return i;
179+
}
180+
}
181+
}
182+
return it;
173183
}
174184

175185
Host::Ptr LockedHostMap::get(const Address& address) const {
@@ -633,7 +643,7 @@ void Cluster::notify_host_remove(const Address& address) {
633643
notify_or_record(ClusterEvent(ClusterEvent::HOST_DOWN, host));
634644
}
635645

636-
hosts_.erase(address);
646+
hosts_.erase(it->first);
637647
for (LoadBalancingPolicy::Vec::const_iterator it = load_balancing_policies_.begin(),
638648
end = load_balancing_policies_.end();
639649
it != end; ++it) {

src/control_connection.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ static NopControlConnectionListener nop_listener__;
307307
ControlConnectionSettings::ControlConnectionSettings()
308308
: use_schema(CASS_DEFAULT_USE_SCHEMA)
309309
, use_token_aware_routing(CASS_DEFAULT_USE_TOKEN_AWARE_ROUTING)
310-
, address_factory(new DefaultAddressFactory()) {}
310+
, address_factory(new AddressFactory()) {}
311311

312312
ControlConnectionSettings::ControlConnectionSettings(const Config& config)
313313
: connection_settings(config)
@@ -395,17 +395,16 @@ void ControlConnection::handle_refresh_node(RefreshNodeCallback* callback) {
395395
const Row* row = NULL;
396396
ResultIterator rows(callback->result().get());
397397

398-
while (rows.next() && !found_host) {
399-
row = rows.row();
400-
if (callback->is_all_peers) {
401-
Address address;
402-
bool is_valid_address = settings_.address_factory->create(row, connection_->host(), &address);
403-
if (is_valid_address && callback->address == address) {
398+
if (callback->is_all_peers) {
399+
while (!found_host && rows.next()) {
400+
row = rows.row();
401+
if (settings_.address_factory->is_peer(row, connection_->host(), callback->address)) {
404402
found_host = true;
405403
}
406-
} else {
407-
found_host = true;
408404
}
405+
} else if (rows.next()) {
406+
row = rows.row();
407+
found_host = true;
409408
}
410409

411410
if (!found_host) {

src/host.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ void Host::set(const Row* row, bool use_tokens) {
123123
if (dse_server_version_ < VersionNumber(6, 7, 0)) {
124124
server_version_ = VersionNumber(3, 11, 0);
125125
}
126-
} else {
127-
LOG_WARN("Invalid DSE version string \"%s\" on host %s", dse_version_str.c_str(),
128-
address().to_string().c_str());
129126
}
130127
}
131128

@@ -153,37 +150,51 @@ void Host::set(const Row* row, bool use_tokens) {
153150
"If this is incorrect you should configure a specific interface for rpc_address on "
154151
"the server.",
155152
address_string_.c_str());
153+
v = row->get_by_name("listen_address"); // Available in system.local
154+
if (v && !v->is_null()) {
155+
v->decoder().as_inet(v->size(), address_.port(), &rpc_address_);
156+
} else {
157+
v = row->get_by_name("peer"); // Available in system.peers
158+
if (v && !v->is_null()) {
159+
v->decoder().as_inet(v->size(), address_.port(), &rpc_address_);
160+
}
161+
}
162+
if (!rpc_address_.is_valid()) {
163+
LOG_WARN("Unable to set rpc_address from either listen_address or peer");
164+
}
156165
}
157166
} else {
158167
LOG_WARN("No rpc_address for host %s in system.local or system.peers.",
159168
address_string_.c_str());
160169
}
161170
}
162171

172+
static CassInet to_inet(const Host::Ptr& host) {
173+
CassInet address;
174+
if (host->address().is_resolved()) {
175+
address.address_length = host->address().to_inet(address.address);
176+
} else {
177+
address.address_length = host->rpc_address().to_inet(&address.address);
178+
}
179+
return address;
180+
}
181+
163182
ExternalHostListener::ExternalHostListener(const CassHostListenerCallback callback, void* data)
164183
: callback_(callback)
165184
, data_(data) {}
166185

167186
void ExternalHostListener::on_host_up(const Host::Ptr& host) {
168-
CassInet address;
169-
address.address_length = host->address().to_inet(address.address);
170-
callback_(CASS_HOST_LISTENER_EVENT_UP, address, data_);
187+
callback_(CASS_HOST_LISTENER_EVENT_UP, to_inet(host), data_);
171188
}
172189

173190
void ExternalHostListener::on_host_down(const Host::Ptr& host) {
174-
CassInet address;
175-
address.address_length = host->address().to_inet(address.address);
176-
callback_(CASS_HOST_LISTENER_EVENT_DOWN, address, data_);
191+
callback_(CASS_HOST_LISTENER_EVENT_DOWN, to_inet(host), data_);
177192
}
178193

179194
void ExternalHostListener::on_host_added(const Host::Ptr& host) {
180-
CassInet address;
181-
address.address_length = host->address().to_inet(address.address);
182-
callback_(CASS_HOST_LISTENER_EVENT_ADD, address, data_);
195+
callback_(CASS_HOST_LISTENER_EVENT_ADD, to_inet(host), data_);
183196
}
184197

185198
void ExternalHostListener::on_host_removed(const Host::Ptr& host) {
186-
CassInet address;
187-
address.address_length = host->address().to_inet(address.address);
188-
callback_(CASS_HOST_LISTENER_EVENT_REMOVE, address, data_);
199+
callback_(CASS_HOST_LISTENER_EVENT_REMOVE, to_inet(host), data_);
189200
}

src/request_processor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ RequestProcessorSettings::RequestProcessorSettings()
146146
, max_tracing_wait_time_ms(CASS_DEFAULT_MAX_TRACING_DATA_WAIT_TIME_MS)
147147
, retry_tracing_wait_time_ms(CASS_DEFAULT_RETRY_TRACING_DATA_WAIT_TIME_MS)
148148
, tracing_consistency(CASS_DEFAULT_TRACING_CONSISTENCY)
149-
, address_factory(new DefaultAddressFactory()) {
149+
, address_factory(new AddressFactory()) {
150150
profiles.set_empty_key("");
151151
}
152152

src/wkt.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// clang-format off
12

23
#line 1 "wkt.rl"
34
/*

0 commit comments

Comments
 (0)