Merge 2.1 in 2.2

Merge 2.1 in 2.2
This commit is contained in:
MassimilianoPinto 2017-11-29 11:30:33 +01:00
parent ba22e3b1db
commit 8a10b72e4d
8 changed files with 195 additions and 25 deletions

View 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).

View File

@ -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

View File

@ -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();

View File

@ -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++;
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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;
}
/*

View File

@ -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;