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:
parent
93dc75a011
commit
0c3fcfe302
@ -29,6 +29,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <maxscale/buffer.h>
|
||||
#include <maxscale/dcb.h>
|
||||
@ -367,6 +368,7 @@ public:
|
||||
class ChangeMasterConfig
|
||||
{
|
||||
public:
|
||||
std::string connection_name;
|
||||
std::string host;
|
||||
int port;
|
||||
std::string binlog_file;
|
||||
@ -392,6 +394,16 @@ struct ROUTER_INSTANCE;
|
||||
class ChangeMasterOptions
|
||||
{
|
||||
public:
|
||||
ChangeMasterOptions()
|
||||
{
|
||||
}
|
||||
|
||||
ChangeMasterOptions(const std::string& s)
|
||||
: connection_name(s)
|
||||
{
|
||||
}
|
||||
|
||||
std::string connection_name;
|
||||
std::string host;
|
||||
std::string port;
|
||||
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 */
|
||||
char *set_slave_hostname; /*< Send custom Hostname to Master */
|
||||
ROUTER_INSTANCE *next;
|
||||
ChangeMasterConfig config; /*< Current config. */
|
||||
std::vector<ChangeMasterConfig> configs; /*< Current config. */
|
||||
};
|
||||
|
||||
/** 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);
|
||||
int blr_file_get_next_binlogname(ROUTER_INSTANCE *router);
|
||||
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);
|
||||
static void blr_format_event_size(double *event_size, char *label);
|
||||
extern int MaxScaleUptime();
|
||||
|
@ -49,6 +49,9 @@
|
||||
#include <maxscale/utils.h>
|
||||
#include <maxscale/version.h>
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
/**
|
||||
* This struct is used by sqlite3_exec callback routine
|
||||
* 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->port = port;
|
||||
config->binlog_file = this->binlog_file;
|
||||
@ -4228,13 +4232,78 @@ bool ChangeMasterOptions::validate(ROUTER_INSTANCE* router,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
||||
const ChangeMasterConfig& new_config,
|
||||
char* error)
|
||||
namespace
|
||||
{
|
||||
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 */
|
||||
blr_master_get_config(router, ¤t_master);
|
||||
@ -4291,8 +4360,6 @@ static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
||||
current_master,
|
||||
error);
|
||||
|
||||
spinlock_release(&router->lock);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -4321,8 +4388,6 @@ static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
||||
error);
|
||||
MXS_FREE(master_logfile);
|
||||
|
||||
spinlock_release(&router->lock);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -4337,9 +4402,50 @@ static int blr_apply_change_master(ROUTER_INSTANCE* router,
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
/* 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(),
|
||||
error,
|
||||
&new_options) != 0)
|
||||
@ -8038,8 +8144,11 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
|
||||
{
|
||||
int rc;
|
||||
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;
|
||||
blr_master_get_config(router, ¤t_master);
|
||||
vector<ChangeMasterConfig> configs = router->configs;
|
||||
|
||||
ChangeMasterConfig 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 */
|
||||
spinlock_acquire(&router->lock);
|
||||
router->config = new_config;
|
||||
if (!router->service->dbref->server->is_active)
|
||||
{
|
||||
router->service->dbref->server->is_active = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user