diff --git a/server/modules/routing/binlogrouter/blr.h b/server/modules/routing/binlogrouter/blr.h index cf35b1b53..0eadbc543 100644 --- a/server/modules/routing/binlogrouter/blr.h +++ b/server/modules/routing/binlogrouter/blr.h @@ -342,29 +342,56 @@ typedef struct mariadb_gtid_info } MARIADB_GTID_INFO; /* Master Server configuration struct */ -struct MasterServerConfig +class MasterServerConfig { - std::string host; +public: + std::string host; unsigned short port; - std::string logfile; - uint64_t pos; - uint64_t safe_pos; + std::string logfile; + uint64_t pos; + uint64_t safe_pos; + std::string user; + std::string password; + std::string filestem; + /* SSL options */ + std::string ssl_key; + std::string ssl_cert; + std::string ssl_ca; + int ssl_enabled; + std::string ssl_version; + /* Connect options */ + int heartbeat; +}; + +/* Config struct for CHANGE MASTER TO */ +class ChangeMasterConfig +{ +public: + std::string host; + int port; + std::string binlog_file; + std::string binlog_pos; std::string user; std::string password; - std::string filestem; /* SSL options */ std::string ssl_key; std::string ssl_cert; std::string ssl_ca; - int ssl_enabled; + std::string ssl_enabled; std::string ssl_version; - /* Connect options */ - int heartbeat; + /* MariaDB 10 GTID */ + std::string use_mariadb10_gtid; + /* Connection options */ + int heartbeat_period; + int connect_retry; }; +struct ROUTER_INSTANCE; + /* Config struct for CHANGE MASTER TO options */ -struct ChangeMasterOptions +class ChangeMasterOptions { +public: std::string host; std::string port; std::string binlog_file; @@ -382,6 +409,10 @@ struct ChangeMasterOptions /* Connection options */ std::string heartbeat_period; std::string connect_retry; + + bool validate(ROUTER_INSTANCE* router, + char* error, + ChangeMasterConfig* config); }; /** @@ -520,7 +551,7 @@ typedef struct router_slave bool mariadb10_compat;/*< MariaDB 10.0 compatibility */ SPINLOCK rses_lock; /*< Protects rses_deleted */ pthread_t pthread; - struct router_instance *router; /*< Pointer to the owning router */ + ROUTER_INSTANCE *router; /*< Pointer to the owning router */ struct router_slave *next; SLAVE_STATS stats; /*< Slave statistics */ time_t connect_time; /*< Connect time of slave */ @@ -658,7 +689,7 @@ typedef struct binlog_encryption_ctx /** * The per instance data for the router. */ -typedef struct router_instance: public MXS_ROUTER +struct ROUTER_INSTANCE: public MXS_ROUTER { SERVICE *service; /*< Pointer to the service using this router */ ROUTER_SLAVE *slaves; /*< Link list of all the slave connections */ @@ -756,8 +787,8 @@ typedef struct router_instance: public MXS_ROUTER sqlite3 *gtid_maps; /*< MariaDB 10 GTID storage */ enum binlog_storage_type storage_type;/*< Enables hierachical binlog file storage */ char *set_slave_hostname; /*< Send custom Hostname to Master */ - struct router_instance *next; -} ROUTER_INSTANCE; + ROUTER_INSTANCE *next; +}; /** Master Semi-Sync capability */ typedef enum diff --git a/server/modules/routing/binlogrouter/blr_slave.cc b/server/modules/routing/binlogrouter/blr_slave.cc index 2d38746ce..940ed5e6b 100644 --- a/server/modules/routing/binlogrouter/blr_slave.cc +++ b/server/modules/routing/binlogrouter/blr_slave.cc @@ -4128,6 +4128,102 @@ blr_slave_send_error_packet(ROUTER_SLAVE *slave, MXS_SESSION_ROUTE_REPLY(slave->dcb->session, pkt); } +bool ChangeMasterOptions::validate(ROUTER_INSTANCE* router, + char* error, + ChangeMasterConfig* config) +{ + /* Abort if MASTER_USE_GTID is in use and + * router->mariadb10_master_gtid is not set + */ + if (!router->mariadb10_master_gtid && !this->use_mariadb10_gtid.empty()) + { + snprintf(error, + BINLOG_ERROR_MSG_LEN, + "Cannot use MASTER_USE_GTID. " + "Enable 'mariadb10_master_gtid' option first."); + + MXS_ERROR("%s: %s", router->service->name, error); + + return false; + } + + int heartbeat_period = -1; + if (!this->heartbeat_period.empty()) + { + heartbeat_period = (int)strtol(this->heartbeat_period.c_str(), NULL, 10); + + if (heartbeat_period < 0 || + (errno == ERANGE) || + heartbeat_period > BLR_HEARTBEAT_MAX_INTERVAL) + { + snprintf(error, + BINLOG_ERROR_MSG_LEN, + "The requested value for the heartbeat period is " + "either negative or exceeds the maximum allowed " + "(%d seconds).", + BLR_HEARTBEAT_MAX_INTERVAL); + + MXS_ERROR("%s: %s", router->service->name, error); + + return false; + } + } + + int connect_retry = -1; + if (!this->connect_retry.empty()) + { + connect_retry = (int)strtol(this->connect_retry.c_str(), NULL, 10); + if (connect_retry <= 0 || + (errno == ERANGE)) + { + snprintf(error, + BINLOG_ERROR_MSG_LEN, + "The requested value for MASTER_CONNECT_RETRY " + "interval is not valid: %s.", + this->connect_retry.c_str()); + + MXS_ERROR("%s: %s", router->service->name, error); + + return false; + } + } + + int port = -1; + if (!this->port.empty()) + { + port = (int)strtol(this->port.c_str(), NULL, 10); + if ((port < 0) || (port > std::numeric_limits::max())) + { + snprintf(error, + BINLOG_ERROR_MSG_LEN, + "The specified value for MASTER_PORT " + "is not valid: %s.", + this->port.c_str()); + + MXS_ERROR("%s: %s", router->service->name, error); + + return false; + } + } + + config->host = this->host; + config->port = port; + config->binlog_file = this->binlog_file; + config->binlog_pos = this->binlog_pos; + config->user = this->user; + config->password = this->password; + config->ssl_key = this->ssl_key; + config->ssl_cert = this->ssl_cert; + config->ssl_ca = this->ssl_ca; + config->ssl_enabled = this->ssl_enabled; + config->ssl_version = this->ssl_version; + config->use_mariadb10_gtid = this->use_mariadb10_gtid; + config->heartbeat_period = heartbeat_period; + config->connect_retry = connect_retry; + + return true; +} + /** * handle a 'change master' operation *