+++ /dev/null
-# name : innodb_overwrite_relay_log_info.patch
-# introduced : 11 or before
-# maintainer : Yasufumi
-#
-#!!! notice !!!
-# Any small change to this file in the main branch
-# should be done or reviewed by the maintainer!
---- a/storage/innobase/handler/ha_innodb.cc
-+++ b/storage/innobase/handler/ha_innodb.cc
-@@ -42,6 +42,8 @@
- #pragma implementation // gcc: Class implementation
- #endif
-
-+#define MYSQL_SERVER
-+
- #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
- // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
-
-@@ -53,6 +55,15 @@
- #include <mysql/psi/psi.h>
- #include <my_sys.h>
-
-+#ifdef MYSQL_SERVER
-+#include <rpl_mi.h>
-+#include <slave.h>
-+// Defined in slave.cc
-+int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
-+int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
-+ const char *default_val);
-+#endif /* MYSQL_SERVER */
-+
- /** @file ha_innodb.cc */
-
- /* Include necessary InnoDB headers */
-@@ -91,6 +102,14 @@
- #include "ha_innodb.h"
- #include "i_s.h"
-
-+#ifdef MYSQL_SERVER
-+// Defined in trx0sys.c
-+extern char trx_sys_mysql_master_log_name[];
-+extern ib_int64_t trx_sys_mysql_master_log_pos;
-+extern char trx_sys_mysql_relay_log_name[];
-+extern ib_int64_t trx_sys_mysql_relay_log_pos;
-+#endif /* MYSQL_SERVER */
-+
- # ifndef MYSQL_PLUGIN_IMPORT
- # define MYSQL_PLUGIN_IMPORT /* nothing */
- # endif /* MYSQL_PLUGIN_IMPORT */
-@@ -163,6 +182,7 @@
- static my_bool innobase_use_doublewrite = TRUE;
- static my_bool innobase_use_checksums = TRUE;
- static my_bool innobase_locks_unsafe_for_binlog = FALSE;
-+static my_bool innobase_overwrite_relay_log_info = FALSE;
- static my_bool innobase_rollback_on_timeout = FALSE;
- static my_bool innobase_create_status_file = FALSE;
- static my_bool innobase_stats_on_metadata = TRUE;
-@@ -2282,6 +2302,89 @@
- }
- #endif /* DBUG_OFF */
-
-+#ifndef MYSQL_SERVER
-+ innodb_overwrite_relay_log_info = FALSE;
-+#endif
-+
-+#ifdef HAVE_REPLICATION
-+#ifdef MYSQL_SERVER
-+ /* read master log position from relay-log.info if exists */
-+ char fname[FN_REFLEN+128];
-+ int pos;
-+ int info_fd;
-+ IO_CACHE info_file;
-+
-+ fname[0] = '\0';
-+
-+ if(innobase_overwrite_relay_log_info) {
-+
-+ fprintf(stderr,
-+ "InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
-+ " Updates by other storage engines may not be synchronized.\n");
-+
-+ bzero((char*) &info_file, sizeof(info_file));
-+ fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-+
-+ int error=0;
-+
-+ if (!access(fname,F_OK)) {
-+ /* exist */
-+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
-+ error=1;
-+ } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
-+ READ_CACHE, 0L, 0, MYF(MY_WME))) {
-+ error=1;
-+ }
-+
-+ if (error) {
-+relay_info_error:
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+ fname[0] = '\0';
-+ goto skip_relay;
-+ }
-+ } else {
-+ fname[0] = '\0';
-+ goto skip_relay;
-+ }
-+
-+ if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
-+ init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
-+ end_io_cache(&info_file);
-+ error=1;
-+ goto relay_info_error;
-+ }
-+
-+ fprintf(stderr,
-+ "InnoDB: relay-log.info is detected.\n"
-+ "InnoDB: relay log: position %u, file name %s\n",
-+ pos, fname);
-+
-+ strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-+ trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
-+
-+ if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
-+ init_intvar_from_file(&pos, &info_file, 0)) {
-+ end_io_cache(&info_file);
-+ error=1;
-+ goto relay_info_error;
-+ }
-+
-+ fprintf(stderr,
-+ "InnoDB: master log: position %u, file name %s\n",
-+ pos, fname);
-+
-+ strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-+ trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
-+
-+ end_io_cache(&info_file);
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+ }
-+skip_relay:
-+#endif /* MYSQL_SERVER */
-+#endif /* HAVE_REPLICATION */
-+
- /* Check that values don't overflow on 32-bit systems. */
- if (sizeof(ulint) == 4) {
- if (innobase_buffer_pool_size > UINT_MAX32) {
-@@ -2580,6 +2683,76 @@
- goto mem_free_and_error;
- }
-
-+#ifdef HAVE_REPLICATION
-+#ifdef MYSQL_SERVER
-+ if(innobase_overwrite_relay_log_info) {
-+ /* If InnoDB progressed from relay-log.info, overwrite it */
-+ if (fname[0] == '\0') {
-+ fprintf(stderr,
-+ "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
-+ } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
-+ || pos != trx_sys_mysql_master_log_pos) {
-+ /* Overwrite relay-log.info */
-+ bzero((char*) &info_file, sizeof(info_file));
-+ fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-+
-+ int error = 0;
-+
-+ if (!access(fname,F_OK)) {
-+ /* exist */
-+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
-+ error = 1;
-+ } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
-+ WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
-+ error = 1;
-+ }
-+
-+ if (error) {
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+ goto skip_overwrite;
-+ }
-+ } else {
-+ error = 1;
-+ goto skip_overwrite;
-+ }
-+
-+ char buff[FN_REFLEN*2+22*2+4], *pos;
-+
-+ my_b_seek(&info_file, 0L);
-+ pos=strmov(buff, trx_sys_mysql_relay_log_name);
-+ *pos++='\n';
-+ pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
-+ *pos++='\n';
-+ pos=strmov(pos, trx_sys_mysql_master_log_name);
-+ *pos++='\n';
-+ pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
-+ *pos='\n';
-+
-+ if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
-+ error = 1;
-+ if (flush_io_cache(&info_file))
-+ error = 1;
-+
-+ end_io_cache(&info_file);
-+ if (info_fd >= 0)
-+ my_close(info_fd, MYF(0));
-+skip_overwrite:
-+ if (error) {
-+ fprintf(stderr,
-+ "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
-+ } else {
-+ fprintf(stderr,
-+ "InnoDB: The file relay-log.info was successfully overwritten.\n");
-+ }
-+ } else {
-+ fprintf(stderr,
-+ "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
-+ }
-+ }
-+#endif /* MYSQL_SERVER */
-+#endif /* HAVE_REPLICATION */
-+
- innobase_old_blocks_pct = buf_LRU_old_ratio_update(
- innobase_old_blocks_pct, TRUE);
-
-@@ -2693,6 +2866,25 @@
- trx_t* trx) /*!< in: transaction handle */
- {
- if (trx_is_started(trx)) {
-+#ifdef HAVE_REPLICATION
-+#ifdef MYSQL_SERVER
-+ THD *thd=current_thd;
-+
-+ if (thd && thd->slave_thread) {
-+ /* Update the replication position info inside InnoDB */
-+ trx->mysql_master_log_file_name
-+ = active_mi->rli.group_master_log_name;
-+ trx->mysql_master_log_pos
-+ = ((ib_int64_t)active_mi->rli.group_master_log_pos +
-+ ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
-+ (ib_int64_t)active_mi->rli.group_relay_log_pos));
-+ trx->mysql_relay_log_file_name
-+ = active_mi->rli.group_relay_log_name;
-+ trx->mysql_relay_log_pos
-+ = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
-+ }
-+#endif /* MYSQL_SERVER */
-+#endif /* HAVE_REPLICATION */
-
- trx_commit_for_mysql(trx);
- }
-@@ -11130,6 +11322,12 @@
- "The common part for InnoDB table spaces.",
- NULL, NULL, NULL);
-
-+static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
-+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-+ "During InnoDB crash recovery on slave overwrite relay-log.info "
-+ "to align master log file position if information in InnoDB and relay-log.info is different.",
-+ NULL, NULL, FALSE);
-+
- static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
- PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
- "Enable InnoDB doublewrite buffer (enabled by default). "
-@@ -11647,6 +11845,7 @@
- MYSQL_SYSVAR(old_blocks_pct),
- MYSQL_SYSVAR(old_blocks_time),
- MYSQL_SYSVAR(open_files),
-+ MYSQL_SYSVAR(recovery_update_relay_log),
- MYSQL_SYSVAR(rollback_on_timeout),
- MYSQL_SYSVAR(stats_on_metadata),
- MYSQL_SYSVAR(stats_sample_pages),
---- a/storage/innobase/include/trx0sys.h
-+++ b/storage/innobase/include/trx0sys.h
-@@ -53,6 +53,9 @@
- extern ib_int64_t trx_sys_mysql_master_log_pos;
- /* @} */
-
-+extern char trx_sys_mysql_relay_log_name[];
-+extern ib_int64_t trx_sys_mysql_relay_log_pos;
-+
- /** If this MySQL server uses binary logging, after InnoDB has been inited
- and if it has done a crash recovery, we store the binlog file name and position
- here. */
-@@ -298,7 +301,8 @@
- void
- trx_sys_update_mysql_binlog_offset(
- /*===============================*/
-- const char* file_name,/*!< in: MySQL log file name */
-+ trx_sysf_t* sys_header,
-+ const char* file_name_in,/*!< in: MySQL log file name */
- ib_int64_t offset, /*!< in: position in that log file */
- ulint field, /*!< in: offset of the MySQL log info field in
- the trx sys header */
-@@ -493,6 +497,7 @@
- @see trx_sys_mysql_master_log_name
- @see trx_sys_mysql_bin_log_name */
- #define TRX_SYS_MYSQL_LOG_NAME_LEN 512
-+#define TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN 480 /* (500 - 12) is dead line. */
- /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
- #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
-
-@@ -502,6 +507,7 @@
- /** The offset of the MySQL replication info in the trx system header;
- this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
- #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
-+#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
-
- /** The offset of the MySQL binlog offset info in the trx system header */
- #define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
---- a/storage/innobase/include/trx0trx.h
-+++ b/storage/innobase/include/trx0trx.h
-@@ -580,6 +580,20 @@
- ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
- contains the end offset of the binlog
- entry */
-+ const char* mysql_master_log_file_name;
-+ /* if the database server is a MySQL
-+ replication slave, we have here the
-+ master binlog name up to which
-+ replication has processed; otherwise
-+ this is a pointer to a null
-+ character */
-+ ib_int64_t mysql_master_log_pos;
-+ /* if the database server is a MySQL
-+ replication slave, this is the
-+ position in the log file up to which
-+ replication has processed */
-+ const char* mysql_relay_log_file_name;
-+ ib_int64_t mysql_relay_log_pos;
- /*------------------------------*/
- ulint n_mysql_tables_in_use; /* number of Innobase tables
- used in the processing of the current
---- a/storage/innobase/trx/trx0sys.c
-+++ b/storage/innobase/trx/trx0sys.c
-@@ -76,13 +76,16 @@
- file name and position here. */
- /* @{ */
- /** Master binlog file name */
--UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
-+UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
- /** Master binlog file position. We have successfully got the updates
- up to this position. -1 means that no crash recovery was needed, or
- there was no master log position info inside InnoDB.*/
- UNIV_INTERN ib_int64_t trx_sys_mysql_master_log_pos = -1;
- /* @} */
-
-+UNIV_INTERN char trx_sys_mysql_relay_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
-+UNIV_INTERN ib_int64_t trx_sys_mysql_relay_log_pos = -1;
-+
- /** If this MySQL server uses binary logging, after InnoDB has been inited
- and if it has done a crash recovery, we store the binlog file name and position
- here. */
-@@ -684,23 +687,25 @@
- void
- trx_sys_update_mysql_binlog_offset(
- /*===============================*/
-- const char* file_name,/*!< in: MySQL log file name */
-+ trx_sysf_t* sys_header,
-+ const char* file_name_in,/*!< in: MySQL log file name */
- ib_int64_t offset, /*!< in: position in that log file */
- ulint field, /*!< in: offset of the MySQL log info field in
- the trx sys header */
- mtr_t* mtr) /*!< in: mtr */
- {
-- trx_sysf_t* sys_header;
-+ const char* file_name;
-
-- if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
-+ if (ut_strlen(file_name_in) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) {
-
- /* We cannot fit the name to the 512 bytes we have reserved */
-+ /* -> To store relay log file information, file_name must fit to the 480 bytes */
-
-- return;
-+ file_name = "";
-+ } else {
-+ file_name = file_name_in;
- }
-
-- sys_header = trx_sysf_get(mtr);
--
- if (mach_read_from_4(sys_header + field
- + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
- != TRX_SYS_MYSQL_LOG_MAGIC_N) {
-@@ -822,13 +827,26 @@
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME);
-+
-+ fprintf(stderr,
-+ "InnoDB: and relay log file\n"
-+ "InnoDB: position %lu %lu, file name %s\n",
-+ (ulong) mach_read_from_4(sys_header
-+ + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
-+ (ulong) mach_read_from_4(sys_header
-+ + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_NAME);
-+
- /* Copy the master log position info to global variables we can
- use in ha_innobase.cc to initialize glob_mi to right values */
-
- ut_memcpy(trx_sys_mysql_master_log_name,
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME,
-- TRX_SYS_MYSQL_LOG_NAME_LEN);
-+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-
- trx_sys_mysql_master_log_pos
- = (((ib_int64_t) mach_read_from_4(
-@@ -837,6 +855,19 @@
- + ((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
-+
-+ ut_memcpy(trx_sys_mysql_relay_log_name,
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_NAME,
-+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
-+
-+ trx_sys_mysql_relay_log_pos
-+ = (((ib_int64_t) mach_read_from_4(
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
-+ + ((ib_int64_t) mach_read_from_4(
-+ sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
-+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
- mtr_commit(&mtr);
- }
-
---- a/storage/innobase/trx/trx0trx.c
-+++ b/storage/innobase/trx/trx0trx.c
-@@ -138,6 +138,10 @@
-
- trx->mysql_log_file_name = NULL;
- trx->mysql_log_offset = 0;
-+ trx->mysql_master_log_file_name = "";
-+ trx->mysql_master_log_pos = 0;
-+ trx->mysql_relay_log_file_name = "";
-+ trx->mysql_relay_log_pos = 0;
-
- mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
-
-@@ -820,6 +824,7 @@
- {
- mtr_t mtr;
- trx_rseg_t* rseg;
-+ trx_sysf_t* sys_header = NULL;
-
- ut_ad(!mutex_own(&kernel_mutex));
-
-@@ -873,8 +878,12 @@
-
- if (trx->mysql_log_file_name
- && trx->mysql_log_file_name[0] != '\0') {
-+ if (!sys_header) {
-+ sys_header = trx_sysf_get(&mtr);
-+ }
-
- trx_sys_update_mysql_binlog_offset(
-+ sys_header,
- trx->mysql_log_file_name,
- trx->mysql_log_offset,
- TRX_SYS_MYSQL_LOG_INFO, &mtr);
-@@ -882,6 +891,27 @@
- trx->mysql_log_file_name = NULL;
- }
-
-+ if (trx->mysql_master_log_file_name[0] != '\0') {
-+ /* This database server is a MySQL replication slave */
-+ if (!sys_header) {
-+ sys_header = trx_sysf_get(&mtr);
-+ }
-+
-+ trx_sys_update_mysql_binlog_offset(
-+ sys_header,
-+ trx->mysql_relay_log_file_name,
-+ trx->mysql_relay_log_pos,
-+ TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
-+
-+ trx_sys_update_mysql_binlog_offset(
-+ sys_header,
-+ trx->mysql_master_log_file_name,
-+ trx->mysql_master_log_pos,
-+ TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
-+
-+ trx->mysql_master_log_file_name = "";
-+ }
-+
- /* The following call commits the mini-transaction, making the
- whole transaction committed in the file-based world, at this
- log sequence number. The transaction becomes 'durable' when