26#ifndef MYSQLROUTER_CLUSTER_AWARE_SESSION_INCLUDED 
   27#define MYSQLROUTER_CLUSTER_AWARE_SESSION_INCLUDED 
   41#include <system_error> 
   45#include "mysqld_error.h" 
   67      const std::string &cluster_initial_username,
 
   68      const std::string &cluster_initial_password,
 
   69      const std::string &cluster_initial_hostname,
 
   70      unsigned long cluster_initial_port,
 
   71      const std::string &cluster_initial_socket,
 
   72      unsigned long connection_timeout,
 
   75      : metadata_(metadata),
 
   76        cluster_initial_username_(cluster_initial_username),
 
   77        cluster_initial_password_(cluster_initial_password),
 
   78        cluster_initial_hostname_(cluster_initial_hostname),
 
   79        cluster_initial_port_(cluster_initial_port),
 
   80        cluster_initial_socket_(cluster_initial_socket),
 
   81        connection_timeout_(connection_timeout),
 
   82        failure_codes_(std::move(failure_codes)) {}
 
   97    bool fetched_cluster_servers = 
false;
 
   98    std::vector<std::tuple<std::string, unsigned long>> cluster_servers;
 
  100    auto cluster_servers_it = cluster_servers.begin();
 
  101    const auto cluster_specific_initial_id =
 
  102        metadata_.get_cluster_type_specific_id();
 
  104    bool initial_node = 
true;
 
  106      bool skip_node = 
false;
 
  110        const auto cluster_specific_id =
 
  111            metadata_.get_cluster_type_specific_id();
 
  113        if (cluster_specific_id != cluster_specific_initial_id) {
 
  115              "Node on '%s' that the bootstrap failed over to, seems to belong " 
  116              "to different cluster(%s != %s), skipping...",
 
  117              metadata_.get_session().get_address().c_str(),
 
  118              cluster_specific_initial_id.c_str(), cluster_specific_id.c_str());
 
  122        initial_node = 
false;
 
  127          return wrapped_func();
 
  132              "Executing statements failed with: '%s' (%d), trying to connect " 
  138          if (failure_codes_.find(ec) == failure_codes_.end()) {
 
  146        if (!fetched_cluster_servers) {
 
  149          fetched_cluster_servers = 
true;
 
  151          log_info(
"Fetching Cluster Members");
 
  153          for (
auto &cluster_node : metadata_.fetch_cluster_hosts()) {
 
  154            auto const &node_host = std::get<0>(cluster_node);
 
  155            auto node_port = std::get<1>(cluster_node);
 
  158            if (cluster_initial_socket_.size() == 0 &&
 
  159                (node_host == cluster_initial_hostname_ &&
 
  160                 node_port == cluster_initial_port_)) {
 
  164            log_debug(
"added cluster node: %s:%ld", node_host.c_str(),
 
  166            cluster_servers.emplace_back(node_host, node_port);
 
  170          cluster_servers_it = cluster_servers.begin();
 
  172          std::advance(cluster_servers_it, 1);
 
  175        if (cluster_servers_it == cluster_servers.end()) {
 
  176          throw std::runtime_error(
 
  177              "no more nodes to fail-over too, giving up.");
 
  180        if (metadata_.get_session().is_connected()) {
 
  181          log_debug(
"%s", 
"disconnecting from mysql-server");
 
  182          metadata_.get_session().disconnect();
 
  185        auto const &tp = *cluster_servers_it;
 
  187        auto const &
host = std::get<0>(tp);
 
  188        auto port = std::get<1>(tp);
 
  190        log_info(
"trying to connect to mysql-server at %s:%ld", 
host.c_str(),
 
  195        } 
catch (
const std::exception &inner_e) {
 
  196          log_info(
"Failed connecting to %s:%ld: %s, trying next", 
host.c_str(),
 
  197                   port, inner_e.what());
 
  204          metadata_.get_session().disconnect();
 
  206              "Failed setting up a metadata session %s:%ld: %s, trying next",
 
  211      } 
while (!metadata_.get_session().is_connected());
 
  219               const unsigned port);
 
Cluster (GR or AR)-aware decorator for MySQL Sessions.
Definition: cluster_aware_session.h:63
 
unsigned long cluster_initial_port_
Definition: cluster_aware_session.h:225
 
const std::string & cluster_initial_password_
Definition: cluster_aware_session.h:223
 
mysqlrouter::ClusterMetadata & metadata_
Definition: cluster_aware_session.h:221
 
virtual ~ClusterAwareDecorator()=default
 
R failover_on_failure(std::function< R()> wrapped_func)
Cluster (GR or AR) aware failover.
Definition: cluster_aware_session.h:96
 
ClusterAwareDecorator(mysqlrouter::ClusterMetadata &metadata, const std::string &cluster_initial_username, const std::string &cluster_initial_password, const std::string &cluster_initial_hostname, unsigned long cluster_initial_port, const std::string &cluster_initial_socket, unsigned long connection_timeout, std::set< MySQLErrorc > failure_codes={MySQLErrorc::kSuperReadOnly, MySQLErrorc::kLostConnection})
Definition: cluster_aware_session.h:65
 
const std::string & cluster_initial_username_
Definition: cluster_aware_session.h:222
 
unsigned long connection_timeout_
Definition: cluster_aware_session.h:227
 
std::set< MySQLErrorc > failure_codes_
Definition: cluster_aware_session.h:228
 
const std::string & cluster_initial_hostname_
Definition: cluster_aware_session.h:224
 
const std::string & cluster_initial_socket_
Definition: cluster_aware_session.h:226
 
Definition: mysql_session.h:289
 
unsigned int code() const
Definition: mysql_session.h:303
 
Definition: mysql_session.h:157
 
Log log_debug(std::cout, "DEBUG")
 
MySQLErrorc
Error codes for MySQL Errors that we handle specifically.
Definition: cluster_aware_session.h:55
 
#define CR_SERVER_LOST
Definition: errmsg.h:72
 
#define log_warning(...)
Definition: log_client.h:154
 
#define log_info(...)
Definition: log_client.h:153
 
Logging interface for using and extending the logging subsystem.
 
#define IMPORT_LOG_FUNCTIONS()
convenience macro to avoid common boilerplate
Definition: logging.h:331
 
const char * host
Definition: mysqladmin.cc:66
 
stdx::expected< void, std::string > ROUTER_CLUSTER_EXPORT setup_metadata_session(MySQLSession &session)
Definition: cluster_metadata.cc:1358
 
stdx::expected< void, error_type > connect(native_handle_type native_handle, const struct sockaddr *addr, size_t addr_len)
wrap connect() in a portable way.
Definition: socket.h:353
 
required uint64 port
Definition: replication_asynchronous_connection_failover.proto:33
 
#define ROUTER_CLUSTER_EXPORT
Definition: router_cluster_export.h:15