MXS-2011 Allow alternative connections to be specified
Alternative masters can now be specified like CHANGE MASTER TO ... CHANGE MASTER ":2" TO ... CHANGE MASTER ":3" TO ... Now only the data is stored, but it is neither used nor saved.
This commit is contained in:
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <maxscale/buffer.h>
|
#include <maxscale/buffer.h>
|
||||||
#include <maxscale/dcb.h>
|
#include <maxscale/dcb.h>
|
||||||
@ -367,6 +368,7 @@ public:
|
|||||||
class ChangeMasterConfig
|
class ChangeMasterConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::string connection_name;
|
||||||
std::string host;
|
std::string host;
|
||||||
int port;
|
int port;
|
||||||
std::string binlog_file;
|
std::string binlog_file;
|
||||||
@ -392,6 +394,16 @@ struct ROUTER_INSTANCE;
|
|||||||
class ChangeMasterOptions
|
class ChangeMasterOptions
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ChangeMasterOptions()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeMasterOptions(const std::string& s)
|
||||||
|
: connection_name(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string connection_name;
|
||||||
std::string host;
|
std::string host;
|
||||||
std::string port;
|
std::string port;
|
||||||
std::string binlog_file;
|
std::string binlog_file;
|
||||||
@ -788,7 +800,7 @@ struct ROUTER_INSTANCE: public MXS_ROUTER
|
|||||||
enum binlog_storage_type storage_type;/*< Enables hierachical binlog file storage */
|
enum binlog_storage_type storage_type;/*< Enables hierachical binlog file storage */
|
||||||
char *set_slave_hostname; /*< Send custom Hostname to Master */
|
char *set_slave_hostname; /*< Send custom Hostname to Master */
|
||||||
ROUTER_INSTANCE *next;
|
ROUTER_INSTANCE *next;
|
||||||
ChangeMasterConfig config; /*< Current config. */
|
std::vector<ChangeMasterConfig> configs; /*< Current config. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Master Semi-Sync capability */
|
/** Master Semi-Sync capability */
|
||||||
|
@ -136,7 +136,6 @@ static void blr_log_header(int priority, const char *msg, uint8_t *ptr);
|
|||||||
void blr_cache_read_master_data(ROUTER_INSTANCE *router);
|
void blr_cache_read_master_data(ROUTER_INSTANCE *router);
|
||||||
int blr_file_get_next_binlogname(ROUTER_INSTANCE *router);
|
int blr_file_get_next_binlogname(ROUTER_INSTANCE *router);
|
||||||
int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file);
|
int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file);
|
||||||
int blr_file_write_master_config(ROUTER_INSTANCE *router, char *error);
|
|
||||||
extern uint32_t extract_field(uint8_t *src, int bits);
|
extern uint32_t extract_field(uint8_t *src, int bits);
|
||||||
static void blr_format_event_size(double *event_size, char *label);
|
static void blr_format_event_size(double *event_size, char *label);
|
||||||
extern int MaxScaleUptime();
|
extern int MaxScaleUptime();
|
||||||
|
@ -49,6 +49,9 @@
|
|||||||
#include <maxscale/utils.h>
|
#include <maxscale/utils.h>
|
||||||
#include <maxscale/version.h>
|
#include <maxscale/version.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This struct is used by sqlite3_exec callback routine
|
* This struct is used by sqlite3_exec callback routine
|
||||||
* for SHOW BINARY LOGS.
|
* for SHOW BINARY LOGS.
|
||||||
@ -4210,6 +4213,7 @@ bool ChangeMasterOptions::validate(ROUTER_INSTANCE* router,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config->connection_name = this->connection_name;
|
||||||
config->host = this->host;
|
config->host = this->host;
|
||||||
config->port = port;
|
config->port = port;
|
||||||
config->binlog_file = this->binlog_file;
|
config->binlog_file = this->binlog_file;
|
||||||
@ -4228,13 +4232,78 @@ bool ChangeMasterOptions::validate(ROUTER_INSTANCE* router,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
namespace
|
||||||
const ChangeMasterConfig& new_config,
|
|
||||||
char* error)
|
|
||||||
{
|
{
|
||||||
MasterServerConfig current_master;
|
|
||||||
|
|
||||||
spinlock_acquire(&router->lock);
|
bool validate_connection_name(ROUTER_INSTANCE* router, const std::string& name, char* error)
|
||||||
|
{
|
||||||
|
static const char DEFAULT_MESSAGE[] =
|
||||||
|
"If a connection name is provided, it must be of the format ':N' where N "
|
||||||
|
"is an integer larger than 1.";
|
||||||
|
char custom_message[BINLOG_ERROR_MSG_LEN + 1];
|
||||||
|
|
||||||
|
const char* message = DEFAULT_MESSAGE;
|
||||||
|
|
||||||
|
if (name.length() >= 2) // At minimum ":N".
|
||||||
|
{
|
||||||
|
if (name.front() == ':')
|
||||||
|
{
|
||||||
|
string tail = name.substr(1);
|
||||||
|
int n = strtol(tail.c_str(), NULL, 10);
|
||||||
|
|
||||||
|
if ((n > 1) && (std::to_string(n) == tail)) // Nothing funky in the string
|
||||||
|
{
|
||||||
|
if (router->configs.size() == static_cast<size_t>(n - 1))
|
||||||
|
{
|
||||||
|
message = nullptr;
|
||||||
|
}
|
||||||
|
else if (router->configs.size() == 0)
|
||||||
|
{
|
||||||
|
snprintf(custom_message,
|
||||||
|
BINLOG_ERROR_MSG_LEN,
|
||||||
|
"The provided connection name '%s' is not valid. Currently "
|
||||||
|
"no primary connection exists and it must be specified using "
|
||||||
|
"a 'CHANGE MASTER TO ...' command without a connection name.",
|
||||||
|
name.c_str());
|
||||||
|
message = custom_message;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(custom_message,
|
||||||
|
BINLOG_ERROR_MSG_LEN,
|
||||||
|
"The provided connection name '%s' is not valid. Currently "
|
||||||
|
"the primary connection and %d alternative connections have "
|
||||||
|
"been specified and the next valid name for an alternative "
|
||||||
|
"connection is ':%d'.",
|
||||||
|
name.c_str(),
|
||||||
|
(int)router->configs.size() - 1,
|
||||||
|
(int)router->configs.size() + 1);
|
||||||
|
message = custom_message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message)
|
||||||
|
{
|
||||||
|
snprintf(error, BINLOG_ERROR_MSG_LEN, "%s", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
int blr_apply_change_master_0(ROUTER_INSTANCE* router,
|
||||||
|
const ChangeMasterConfig& new_config,
|
||||||
|
char* error)
|
||||||
|
{
|
||||||
|
mxb_assert(new_config.connection_name.empty());
|
||||||
|
|
||||||
|
MasterServerConfig current_master;
|
||||||
|
|
||||||
/* save current config option data */
|
/* save current config option data */
|
||||||
blr_master_get_config(router, ¤t_master);
|
blr_master_get_config(router, ¤t_master);
|
||||||
@ -4291,8 +4360,6 @@ static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
|||||||
current_master,
|
current_master,
|
||||||
error);
|
error);
|
||||||
|
|
||||||
spinlock_release(&router->lock);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4321,8 +4388,6 @@ static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
|||||||
error);
|
error);
|
||||||
MXS_FREE(master_logfile);
|
MXS_FREE(master_logfile);
|
||||||
|
|
||||||
spinlock_release(&router->lock);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4337,9 +4402,50 @@ static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
|||||||
change_binlog = 1;
|
change_binlog = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return change_binlog;
|
||||||
|
}
|
||||||
|
|
||||||
|
int blr_apply_change_master_N(ROUTER_INSTANCE* router,
|
||||||
|
const ChangeMasterConfig& new_config,
|
||||||
|
char* error)
|
||||||
|
{
|
||||||
|
int rc = -1;
|
||||||
|
|
||||||
|
if (validate_connection_name(router, new_config.connection_name, error))
|
||||||
|
{
|
||||||
|
router->configs.push_back(new_config);
|
||||||
|
rc = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
||||||
|
const ChangeMasterConfig& new_config,
|
||||||
|
char* error)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
spinlock_acquire(&router->lock);
|
||||||
|
|
||||||
|
if (new_config.connection_name.empty())
|
||||||
|
{
|
||||||
|
// An empty connection name means we reset the whole thing.
|
||||||
|
router->configs.clear();
|
||||||
|
router->configs.push_back(new_config);
|
||||||
|
|
||||||
|
rc = blr_apply_change_master_0(router, new_config, error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = blr_apply_change_master_N(router, new_config, error);
|
||||||
|
}
|
||||||
|
|
||||||
spinlock_release(&router->lock);
|
spinlock_release(&router->lock);
|
||||||
|
|
||||||
return change_binlog;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4429,7 +4535,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
|
|||||||
std::vector<char> cmd_string(command, command + strlen(command) + 1); // Include the NULL
|
std::vector<char> cmd_string(command, command + strlen(command) + 1); // Include the NULL
|
||||||
|
|
||||||
/* Parse SQL command and populate the change_master struct */
|
/* Parse SQL command and populate the change_master struct */
|
||||||
ChangeMasterOptions new_options;
|
ChangeMasterOptions new_options(connection_name);
|
||||||
if (blr_parse_change_master_command(&cmd_string.front(),
|
if (blr_parse_change_master_command(&cmd_string.front(),
|
||||||
error,
|
error,
|
||||||
&new_options) != 0)
|
&new_options) != 0)
|
||||||
@ -8038,8 +8144,11 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char error_string[BINLOG_ERROR_MSG_LEN + 1 + BINLOG_ERROR_MSG_LEN + 1] = "";
|
char error_string[BINLOG_ERROR_MSG_LEN + 1 + BINLOG_ERROR_MSG_LEN + 1] = "";
|
||||||
|
// TODO: Why is this without a lock, but blr_master_apply_config() below with
|
||||||
|
// TODO: a lock. One of them must be wrong.
|
||||||
MasterServerConfig current_master;
|
MasterServerConfig current_master;
|
||||||
blr_master_get_config(router, ¤t_master);
|
blr_master_get_config(router, ¤t_master);
|
||||||
|
vector<ChangeMasterConfig> configs = router->configs;
|
||||||
|
|
||||||
ChangeMasterConfig new_config;
|
ChangeMasterConfig new_config;
|
||||||
rc = blr_handle_change_master(router, brkb, error_string, &new_config);
|
rc = blr_handle_change_master(router, brkb, error_string, &new_config);
|
||||||
@ -8088,7 +8197,6 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
|
|||||||
|
|
||||||
/* Mark as active the master server struct */
|
/* Mark as active the master server struct */
|
||||||
spinlock_acquire(&router->lock);
|
spinlock_acquire(&router->lock);
|
||||||
router->config = new_config;
|
|
||||||
if (!router->service->dbref->server->is_active)
|
if (!router->service->dbref->server->is_active)
|
||||||
{
|
{
|
||||||
router->service->dbref->server->is_active = true;
|
router->service->dbref->server->is_active = true;
|
||||||
|
Reference in New Issue
Block a user