Skip to content

Commit

Permalink
Allow clients to disable server-initiated instant failovers
Browse files Browse the repository at this point in the history
This adds a new boolean option, `follow-instant-failovers` (ENABLED by
default), to allow the client to disable server-initiated instant failover
and simply return an error message.

All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the
BSD-new license. I am contributing on behalf of my employer Amazon Web
Services, Inc.
  • Loading branch information
dlenski committed Apr 25, 2024
1 parent d6055fb commit c93c566
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 16 deletions.
9 changes: 9 additions & 0 deletions include/mysql.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ extern const char *SQLSTATE_UNKNOWN;
/* MariaDB specific */
MYSQL_PROGRESS_CALLBACK=5999,
MYSQL_OPT_NONBLOCK,
MARIADB_OPT_FOLLOW_INSTANT_FAILOVERS,

/* MariaDB Connector/C specific */
MYSQL_DATABASE_DRIVER=7000,
MARIADB_OPT_SSL_FP, /* deprecated, use MARIADB_OPT_TLS_PEER_FP instead */
Expand Down Expand Up @@ -337,12 +339,19 @@ struct st_mysql_options {
char *bind_address;
my_bool secure_auth;
my_bool report_data_truncation;
my_bool follow_instant_failovers;

/* function pointers for local infile support */
int (*local_infile_init)(void **, const char *, void *);
int (*local_infile_read)(void *, char *, unsigned int);
void (*local_infile_end)(void *);
int (*local_infile_error)(void *, char *, unsigned int);
void *local_infile_userdata;

/* WHY are some options relegated to this "extension" structure?
* What is the logic for distinguishing the "main" options from
* the extension options?
*/
struct st_mysql_options_extension *extension;
};

Expand Down
45 changes: 29 additions & 16 deletions libmariadb/mariadb_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ struct st_default_options mariadb_defaults[] =
{{MYSQL_SET_CHARSET_NAME}, MARIADB_OPTION_STR, "default-character-set"},
{{MARIADB_OPT_INTERACTIVE}, MARIADB_OPTION_NONE, "interactive-timeout"},
{{MYSQL_OPT_CONNECT_TIMEOUT}, MARIADB_OPTION_INT, "connect-timeout"},
{{MARIADB_OPT_FOLLOW_INSTANT_FAILOVERS}, MARIADB_OPTION_BOOL, "follow-instant-failovers"},
{{MYSQL_OPT_LOCAL_INFILE}, MARIADB_OPTION_BOOL, "local-infile"},
{{0}, 0 ,"disable-local-infile",},
{{MYSQL_OPT_SSL_CIPHER}, MARIADB_OPTION_STR, "ssl-cipher"},
Expand Down Expand Up @@ -1294,6 +1295,7 @@ mysql_init(MYSQL *mysql)
goto error;
mysql->options.report_data_truncation= 1;
mysql->options.connect_timeout=CONNECT_TIMEOUT;
mysql->options.follow_instant_failovers= TRUE;
mysql->charset= mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
mysql->methods= &MARIADB_DEFAULT_METHODS;
strcpy(mysql->net.sqlstate, "00000");
Expand Down Expand Up @@ -1995,23 +1997,31 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
{
if (mysql->net.last_errno == ER_INSTANT_FAILOVER)
{
char *p= mysql->net.last_error; /* Should look like '|message|host[:port]' */
if (p && p[0] == '|')
p= strchr(p + 1, '|') ? : NULL;
if (p && *++p) {
host= p;
p= strchr(p, ':') ? : NULL;
if (p) {
*p++ = '\0';
port= atoi(p);
}
else
{
/* Restore to the default port, rather than reusing our current one */
port= 0;
}
if (!mysql->options.follow_instant_failovers)
{
/* Client has disabled instant failover. Fall through and treat this
* as a "normal" error. */
}
else
{
char *p= mysql->net.last_error; /* Should look like '|message|host[:port]' */
if (p && p[0] == '|')
p= strchr(p + 1, '|') ? : NULL;
if (p && *++p) {
host= p;
p= strchr(p, ':') ? : NULL;
if (p) {
*p++ = '\0';
port= atoi(p);
}
else
{
/* Restore to the default port, rather than reusing our current one */
port= 0;
}
fprintf(stderr, "Got instant failover to '%s' (port %d)\n", host, port);
goto tcp_redirect;
goto tcp_redirect;
}
}
}
goto error;
Expand Down Expand Up @@ -3521,6 +3531,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
case MYSQL_OPT_RECONNECT:
mysql->options.reconnect= *(my_bool *)arg1;
break;
case MARIADB_OPT_FOLLOW_INSTANT_FAILOVERS:
mysql->options.follow_instant_failovers= *(my_bool *)arg1;
break;
case MYSQL_OPT_PROTOCOL:
mysql->options.protocol= *((uint *)arg1);
break;
Expand Down

0 comments on commit c93c566

Please sign in to comment.