1 /* 2 Copyright (c) DataStax, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 #ifndef DATASTAX_INTERNAL_CONTROL_CONNECTOR_HPP 18 #define DATASTAX_INTERNAL_CONTROL_CONNECTOR_HPP 19 20 #include "callback.hpp" 21 #include "control_connection.hpp" 22 #include "event_response.hpp" 23 #include "ref_counted.hpp" 24 25 namespace datastax { namespace internal { namespace core { 26 27 class HostsConnectorRequestCallback; 28 class Metrics; 29 class SchemaConnectorRequestCallback; 30 31 /** 32 * The initial schema metadata retrieved from the cluster when the control 33 * connection is established. 34 */ 35 struct ControlConnectionSchema { 36 ResultResponse::Ptr keyspaces; 37 ResultResponse::Ptr tables; 38 ResultResponse::Ptr views; 39 ResultResponse::Ptr columns; 40 ResultResponse::Ptr indexes; 41 ResultResponse::Ptr user_types; 42 ResultResponse::Ptr functions; 43 ResultResponse::Ptr aggregates; 44 ResultResponse::Ptr virtual_keyspaces; 45 ResultResponse::Ptr virtual_tables; 46 ResultResponse::Ptr virtual_columns; 47 }; 48 49 /** 50 * A connector that establishes a control connection, negotiates the protocol 51 * version, and registers for cluster events (topology and schema changes). It 52 * also retrieves the initial host and schema metadata for the cluster. 53 */ 54 class ControlConnector 55 : public RefCounted<ControlConnector> 56 , public RecordingConnectionListener { 57 public: 58 typedef SharedRefPtr<ControlConnector> Ptr; 59 typedef Vector<Ptr> Vec; 60 typedef internal::Callback<void, ControlConnector*> Callback; 61 62 enum ControlConnectionError { 63 CONTROL_CONNECTION_OK, 64 CONTROL_CONNECTION_CANCELED, 65 CONTROL_CONNECTION_ERROR_CLOSE, 66 CONTROL_CONNECTION_ERROR_CONNECTION, 67 CONTROL_CONNECTION_ERROR_HOSTS, 68 CONTROL_CONNECTION_ERROR_SCHEMA 69 }; 70 71 /** 72 * Constructor 73 * 74 * @param host The host to connect to. 75 * @param protocol_version The initial protocol version to use for the 76 * connection. 77 * @param callback 78 */ 79 ControlConnector(const Host::Ptr& host, ProtocolVersion protocol_version, 80 const Callback& callback); 81 82 /** 83 * Sets the listener to use after the control connection has been 84 * established. 85 * 86 * @param listener The control connection listener. 87 * @return The connector to chain calls. 88 */ 89 ControlConnector* with_listener(ControlConnectionListener* listener); 90 91 /** 92 * Set the metrics object to use to record metrics for the connection. 93 * 94 * @param metrics A metrics object. 95 * @return The connector to chain calls. 96 */ 97 ControlConnector* with_metrics(Metrics* metrics); 98 99 /** 100 * Sets the control connection settings as well as the underlying settings 101 * for the connection and socket. 102 * 103 * @param settings The settings to be used for the connection process. 104 * @return The connector to chain calls. 105 */ 106 ControlConnector* with_settings(const ControlConnectionSettings& settings); 107 108 /** 109 * Start the connection process. 110 * 111 * @param loop An event loop to use for connecting the connection. 112 */ 113 void connect(uv_loop_t* loop); 114 115 /** 116 * Cancel the connection process. 117 */ 118 void cancel(); 119 120 /** 121 * Release the connection from the connector. If not released in the callback 122 * the connection will automatically be closed. 123 * 124 * @return The connection object for this connector. This returns a null object 125 * if the connection is not connected or an error occurred. 126 */ 127 ControlConnection::Ptr release_connection(); 128 129 public: 130 /** 131 * Gets the server version of the connection. 132 * 133 * @return The server version number. 134 */ server_version() const135 const VersionNumber server_version() const { return server_version_; } 136 137 /** 138 * The initial list of hosts available in the cluster. 139 * 140 * @return 141 */ hosts() const142 const HostMap& hosts() const { return hosts_; } 143 144 /** 145 * The initial schema metadata. 146 * 147 * @return 148 */ schema() const149 const ControlConnectionSchema& schema() const { return schema_; } 150 151 public: address() const152 const Address& address() const { return connector_->address(); } 153 protocol_version() const154 const ProtocolVersion protocol_version() const { return connector_->protocol_version(); } 155 is_ok() const156 bool is_ok() const { return error_code_ == CONTROL_CONNECTION_OK; } is_canceled() const157 bool is_canceled() const { return error_code_ == CONTROL_CONNECTION_CANCELED; } is_invalid_protocol() const158 bool is_invalid_protocol() const { 159 return error_code_ == CONTROL_CONNECTION_ERROR_CONNECTION && connector_->is_invalid_protocol(); 160 } is_ssl_error() const161 bool is_ssl_error() const { 162 return error_code_ == CONTROL_CONNECTION_ERROR_CONNECTION && connector_->is_ssl_error(); 163 } is_auth_error() const164 bool is_auth_error() const { 165 return error_code_ == CONTROL_CONNECTION_ERROR_CONNECTION && connector_->is_auth_error(); 166 } 167 supported_options() const168 const StringMultimap& supported_options() const { return connector_->supported_options(); } 169 error_code() const170 ControlConnectionError error_code() const { return error_code_; } error_message() const171 const String& error_message() const { return error_message_; } ssl_error_code()172 CassError ssl_error_code() { return connector_->ssl_error_code(); } 173 connection_error_code()174 Connector::ConnectionError connection_error_code() { return connector_->error_code(); } connection_error_message()175 const String& connection_error_message() { return connector_->error_message(); } 176 177 private: 178 friend class HostsConnectorRequestCallback; 179 friend class SchemaConnectorRequestCallback; 180 181 private: 182 void finish(); 183 184 void on_success(); 185 void on_error(ControlConnectionError code, const String& message); 186 187 void on_connect(Connector* connector); 188 void handle_connect(Connector* connector); 189 190 void query_hosts(); 191 void handle_query_hosts(HostsConnectorRequestCallback* callback); 192 193 void query_schema(); 194 void handle_query_schema(SchemaConnectorRequestCallback* callback); 195 196 private: 197 // Connection listener methods 198 virtual void on_close(Connection* connection); 199 200 private: 201 Connector::Ptr connector_; 202 Connection::Ptr connection_; 203 ControlConnection::Ptr control_connection_; 204 VersionNumber server_version_; 205 VersionNumber dse_server_version_; 206 HostMap hosts_; 207 208 /** 209 * This is used to keep track of the "listen address" which is used to look 210 * up a host in the "system.peers" table by its primary key "peer". No other 211 * component cares about this information so it's not need in the `Host` type. 212 */ 213 ListenAddressMap listen_addresses_; 214 ControlConnectionSchema schema_; 215 216 Callback callback_; 217 218 ControlConnectionError error_code_; 219 String error_message_; 220 221 ControlConnectionListener* listener_; 222 Metrics* metrics_; 223 Host::Ptr host_; 224 ControlConnectionSettings settings_; 225 }; 226 227 }}} // namespace datastax::internal::core 228 229 #endif 230