Merge 2.1 in 2.2
Merge 2.1 in 2.2
This commit is contained in:
parent
ba22e3b1db
commit
8a10b72e4d
52
Documentation/Release-Notes/MaxScale-2.1.12-Release-Notes.md
Normal file
52
Documentation/Release-Notes/MaxScale-2.1.12-Release-Notes.md
Normal file
@ -0,0 +1,52 @@
|
||||
# MariaDB MaxScale 2.1.12 Release Notes
|
||||
|
||||
Release 2.1.12 is a GA release.
|
||||
|
||||
This document describes the changes in release 2.1.12, when compared
|
||||
to release [2.1.11](MaxScale-2.1.11-Release-Notes.md).
|
||||
|
||||
If you are upgrading from release 2.0, please also read the following
|
||||
release notes:
|
||||
|
||||
* [2.1.11](./MaxScale-2.1.11-Release-Notes.md)
|
||||
* [2.1.10](./MaxScale-2.1.10-Release-Notes.md)
|
||||
* [2.1.9](./MaxScale-2.1.9-Release-Notes.md)
|
||||
* [2.1.8](./MaxScale-2.1.8-Release-Notes.md)
|
||||
* [2.1.7](./MaxScale-2.1.7-Release-Notes.md)
|
||||
* [2.1.6](./MaxScale-2.1.6-Release-Notes.md)
|
||||
* [2.1.5](./MaxScale-2.1.5-Release-Notes.md)
|
||||
* [2.1.4](./MaxScale-2.1.4-Release-Notes.md)
|
||||
* [2.1.3](./MaxScale-2.1.3-Release-Notes.md)
|
||||
* [2.1.2](./MaxScale-2.1.2-Release-Notes.md)
|
||||
* [2.1.1](./MaxScale-2.1.1-Release-Notes.md)
|
||||
* [2.1.0](./MaxScale-2.1.0-Release-Notes.md)
|
||||
|
||||
For any problems you encounter, please consider submitting a bug report at
|
||||
[Jira](https://jira.mariadb.org).
|
||||
|
||||
## Changed Features
|
||||
|
||||
### Binlogrouter Mandatory Router Options
|
||||
|
||||
It is no longer necessary to always define the `router_options` parameter for
|
||||
the binlogrouter if no `router_options` are needed. This allows configurations
|
||||
where only parameters are used with the binlogrouter.
|
||||
|
||||
## Bug fixes
|
||||
|
||||
[Here is a list of bugs fixed in MaxScale 2.1.12.](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.1.12)
|
||||
|
||||
## Packaging
|
||||
|
||||
RPM and Debian packages are provided for the Linux distributions supported by
|
||||
MariaDB Enterprise.
|
||||
|
||||
Packages can be downloaded [here](https://mariadb.com/resources/downloads).
|
||||
|
||||
## Source Code
|
||||
|
||||
The source code of MaxScale is tagged at GitHub with a tag, which is identical
|
||||
with the version of MaxScale. For instance, the tag of version X.Y.Z of MaxScale
|
||||
is maxscale-X.Y.Z.
|
||||
|
||||
The source code is available [here](https://github.com/mariadb-corporation/MaxScale).
|
@ -291,7 +291,7 @@ public:
|
||||
* @param param command line parameters for DB server start command
|
||||
* @return 0 if success
|
||||
*/
|
||||
int start_node(int node, const char* param);
|
||||
int start_node(int node, const char* param = "");
|
||||
|
||||
/**
|
||||
* @brief Check node via ssh and restart it if it is not resposible
|
||||
|
@ -13,25 +13,25 @@ void do_test(TestConnections& test, int master, int slave)
|
||||
test.try_query(test.conn_rwsplit, "CREATE TABLE test.t1 (id int)");
|
||||
test.try_query(test.conn_rwsplit, "INSERT INTO test.t1 VALUES (1)");
|
||||
|
||||
test.tprintf("Block a slave node and perform an insert");
|
||||
test.galera->block_node(slave);
|
||||
test.tprintf("Stop a slave node and perform an insert");
|
||||
test.galera->stop_node(slave);
|
||||
sleep(5);
|
||||
test.try_query(test.conn_rwsplit, "INSERT INTO test.t1 VALUES (1)");
|
||||
|
||||
test.tprintf("Unblock the slave node and perform another insert");
|
||||
test.galera->unblock_node(slave);
|
||||
test.tprintf("Start the slave node and perform another insert");
|
||||
test.galera->start_node(slave);
|
||||
sleep(5);
|
||||
test.try_query(test.conn_rwsplit, "INSERT INTO test.t1 VALUES (1)");
|
||||
test.close_maxscale_connections();
|
||||
|
||||
test.tprintf("Block the master node and perform an insert");
|
||||
test.galera->block_node(master);
|
||||
test.tprintf("Stop the master node and perform an insert");
|
||||
test.galera->stop_node(master);
|
||||
sleep(5);
|
||||
test.connect_maxscale();
|
||||
test.try_query(test.conn_rwsplit, "INSERT INTO test.t1 VALUES (1)");
|
||||
|
||||
test.tprintf("Unblock the master node and perform another insert (expecting failure)");
|
||||
test.galera->unblock_node(master);
|
||||
test.tprintf("Start the master node and perform another insert (expecting failure)");
|
||||
test.galera->start_node(master);
|
||||
sleep(5);
|
||||
test.add_result(execute_query_silent(test.conn_rwsplit, "INSERT INTO test.t1 VALUES (1)") == 0, "Query should fail");
|
||||
test.close_maxscale_connections();
|
||||
|
@ -2567,7 +2567,7 @@ int maxscale_getline(char** dest, int* size, FILE* file)
|
||||
char* destptr = *dest;
|
||||
int offset = 0;
|
||||
|
||||
if (feof(file))
|
||||
if (feof(file) || ferror(file))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -2590,11 +2590,18 @@ int maxscale_getline(char** dest, int* size, FILE* file)
|
||||
}
|
||||
}
|
||||
|
||||
if ((destptr[offset] = fgetc(file)) == '\n' || feof(file))
|
||||
int c = fgetc(file);
|
||||
|
||||
if ((c == '\n') || (c == EOF))
|
||||
{
|
||||
destptr[offset] = '\0';
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
destptr[offset] = c;
|
||||
}
|
||||
|
||||
offset++;
|
||||
}
|
||||
|
||||
|
@ -153,8 +153,9 @@ static bool file_write_header(FILE* outfile);
|
||||
static bool file_write_footer(FILE* outfile);
|
||||
static void write_footer(void);
|
||||
static int ntfw_cb(const char*, const struct stat*, int, struct FTW*);
|
||||
static bool file_is_readable(const char* absolute_pathname);
|
||||
static bool file_is_writable(const char* absolute_pathname);
|
||||
static bool is_file_and_readable(const char* absolute_pathname);
|
||||
static bool path_is_readable(const char* absolute_pathname);
|
||||
static bool path_is_writable(const char* absolute_pathname);
|
||||
bool handle_path_arg(char** dest, const char* path, const char* arg, bool rd, bool wr);
|
||||
static bool handle_debug_args(char* args);
|
||||
static void set_log_augmentation(const char* value);
|
||||
@ -733,7 +734,7 @@ static bool resolve_maxscale_conf_fname(char** cnf_full_path,
|
||||
*cnf_full_path = get_expanded_pathname(NULL, home_dir, default_cnf_fname);
|
||||
}
|
||||
|
||||
return *cnf_full_path && file_is_readable(*cnf_full_path);
|
||||
return *cnf_full_path && is_file_and_readable(*cnf_full_path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -762,7 +763,7 @@ static char* check_dir_access(char* dirname, bool rd, bool wr)
|
||||
goto retblock;
|
||||
}
|
||||
|
||||
if (rd && !file_is_readable(dirname))
|
||||
if (rd && !path_is_readable(dirname))
|
||||
{
|
||||
snprintf(errbuf, PATH_MAX * 2 - 1, "MaxScale doesn't have read permission "
|
||||
"to '%s'.", dirname);
|
||||
@ -771,7 +772,7 @@ static char* check_dir_access(char* dirname, bool rd, bool wr)
|
||||
goto retblock;
|
||||
}
|
||||
|
||||
if (wr && !file_is_writable(dirname))
|
||||
if (wr && !path_is_writable(dirname))
|
||||
{
|
||||
snprintf(errbuf, PATH_MAX * 2 - 1, "MaxScale doesn't have write permission "
|
||||
"to '%s'.", dirname);
|
||||
@ -827,12 +828,54 @@ static void print_log_n_stderr(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a path refers to a readable file.
|
||||
*
|
||||
* @param absolute_pathname The path to check.
|
||||
* @return True if the path refers to a readable file. is readable
|
||||
*/
|
||||
static bool is_file_and_readable(const char* absolute_pathname)
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
struct stat info;
|
||||
|
||||
if (stat(absolute_pathname, &info) == 0)
|
||||
{
|
||||
if ((info.st_mode & S_IFMT) == S_IFREG)
|
||||
{
|
||||
// There is a race here as the file can be deleted and a directory
|
||||
// created in its stead between the stat() call here and the access()
|
||||
// call in file_is_readable().
|
||||
rv = path_is_readable(absolute_pathname);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char FORMAT[] = "'%s' does not refer to a regular file.";
|
||||
char buff[sizeof(FORMAT) + strlen(absolute_pathname)];
|
||||
snprintf(buff, sizeof(buff), FORMAT, absolute_pathname);
|
||||
print_log_n_stderr(true, true, buff, buff, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
const char FORMAT[] = "Could not access '%s'.";
|
||||
char buff[sizeof(FORMAT) + strlen(absolute_pathname)];
|
||||
snprintf(buff, sizeof(buff), FORMAT, absolute_pathname);
|
||||
print_log_n_stderr(true, true, buff, buff, eno);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the file or directory is readable
|
||||
* @param absolute_pathname Path of the file or directory to check
|
||||
* @return True if file is readable
|
||||
*/
|
||||
static bool file_is_readable(const char* absolute_pathname)
|
||||
static bool path_is_readable(const char* absolute_pathname)
|
||||
{
|
||||
bool succp = true;
|
||||
|
||||
@ -853,7 +896,7 @@ static bool file_is_readable(const char* absolute_pathname)
|
||||
* @param absolute_pathname Path of the file or directory to check
|
||||
* @return True if file is writable
|
||||
*/
|
||||
static bool file_is_writable(const char* absolute_pathname)
|
||||
static bool path_is_writable(const char* absolute_pathname)
|
||||
{
|
||||
bool succp = true;
|
||||
|
||||
@ -949,7 +992,7 @@ static char* get_expanded_pathname(char** output_path,
|
||||
}
|
||||
snprintf(cnf_file_buf, pathlen, "%s/%s", expanded_path, fname);
|
||||
|
||||
if (!file_is_readable(cnf_file_buf))
|
||||
if (!path_is_readable(cnf_file_buf))
|
||||
{
|
||||
MXS_FREE(expanded_path);
|
||||
MXS_FREE(cnf_file_buf);
|
||||
@ -964,7 +1007,7 @@ static char* get_expanded_pathname(char** output_path,
|
||||
* If only directory was provided, check that it is
|
||||
* readable.
|
||||
*/
|
||||
if (!file_is_readable(expanded_path))
|
||||
if (!path_is_readable(expanded_path))
|
||||
{
|
||||
MXS_FREE(expanded_path);
|
||||
expanded_path = NULL;
|
||||
|
@ -1980,10 +1980,12 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
|
||||
router->current_pos = pos;
|
||||
|
||||
MXS_WARNING("an error has been found in %s. "
|
||||
"Setting safe pos to %lu, current pos %lu",
|
||||
"Setting safe pos to %lu, current pos %lu. "
|
||||
"ErrMsg [%s]",
|
||||
router->binlog_name,
|
||||
router->binlog_position,
|
||||
router->current_pos);
|
||||
router->current_pos,
|
||||
errmsg);
|
||||
|
||||
if (fix)
|
||||
{
|
||||
|
@ -1298,7 +1298,12 @@ blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gather statistics about the replication event types */
|
||||
/**
|
||||
* Check Event Type limit:
|
||||
* If supported, gather statistics about
|
||||
* the replication event types
|
||||
* else stop replication from master
|
||||
*/
|
||||
int event_limit = router->mariadb10_compat ?
|
||||
MAX_EVENT_TYPE_MARIADB10 : MAX_EVENT_TYPE;
|
||||
|
||||
@ -1306,6 +1311,38 @@ blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt)
|
||||
{
|
||||
router->stats.events[hdr.event_type]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
char errmsg[BINLOG_ERROR_MSG_LEN + 1];
|
||||
sprintf(errmsg,
|
||||
"Event type [%d] not supported yet. "
|
||||
"Check master server configuration and "
|
||||
"disable any new feature. "
|
||||
"Replication from master has been stopped.",
|
||||
hdr.event_type);
|
||||
MXS_ERROR("%s", errmsg);
|
||||
gwbuf_free(pkt);
|
||||
pkt = NULL;
|
||||
|
||||
spinlock_acquire(&router->lock);
|
||||
|
||||
/* Handle error messages */
|
||||
char* old_errmsg = router->m_errmsg;
|
||||
router->m_errmsg = MXS_STRDUP_A(errmsg);
|
||||
router->m_errno = 1235;
|
||||
|
||||
/* Set state to stopped */
|
||||
router->master_state = BLRM_SLAVE_STOPPED;
|
||||
router->stats.n_binlog_errors++;
|
||||
|
||||
spinlock_release(&router->lock);
|
||||
|
||||
MXS_FREE(old_errmsg);
|
||||
|
||||
/* Stop replication */
|
||||
blr_master_close(router);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -2691,6 +2691,30 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
|
||||
ss_dassert(hdr.ok == SLAVE_POS_READ_OK);
|
||||
|
||||
/**
|
||||
* Handle Heartbeat: don't check anything else
|
||||
* set CS_WAIT_DATA and return
|
||||
*/
|
||||
if (slave->lastEventReceived == HEARTBEAT_EVENT)
|
||||
{
|
||||
#ifndef BLFILE_IN_SLAVE
|
||||
blr_close_binlog(router, file);
|
||||
#endif
|
||||
spinlock_acquire(&router->binlog_lock);
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
|
||||
/**
|
||||
* Set the CS_WAIT_DATA that allows notification
|
||||
* of new events after HEARTBEAT_EVENT
|
||||
*/
|
||||
slave->cstate |= CS_WAIT_DATA;
|
||||
|
||||
spinlock_release(&slave->catch_lock);
|
||||
spinlock_release(&router->binlog_lock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check now slave position with read indicator = SLAVE_POS_READ_OK
|
||||
*
|
||||
@ -5878,7 +5902,6 @@ blr_send_slave_heartbeat(void *inst)
|
||||
|
||||
while (sptr)
|
||||
{
|
||||
|
||||
/* skip servers with state = 0 */
|
||||
if ( (sptr->state == BLRS_DUMPING) && (sptr->heartbeat > 0) &&
|
||||
((t_now + 1 - sptr->lastReply) >= sptr->heartbeat) )
|
||||
@ -5888,7 +5911,13 @@ blr_send_slave_heartbeat(void *inst)
|
||||
sptr->serverid, sptr->heartbeat,
|
||||
(unsigned long)sptr->lastReply);
|
||||
|
||||
blr_slave_send_heartbeat(router, sptr);
|
||||
if (blr_slave_send_heartbeat(router, sptr))
|
||||
{
|
||||
/* Set last event */
|
||||
sptr->lastEventReceived = HEARTBEAT_EVENT;
|
||||
/* Set last time */
|
||||
sptr->lastReply = t_now;
|
||||
}
|
||||
|
||||
sptr->lastReply = t_now;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user