diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index bb646028285..c1dc5a54958 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7") +SET(WSREP_PATCH_VERSION "7a") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index d346eb240f2..d510477535c 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -38,7 +38,7 @@ cleanup_joiner() check_pid() { local pid_file=$1 - [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 + [ -r "$pid_file" ] && ps -p $(cat $pid_file) >/dev/null 2>&1 } check_pid_and_port() diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index dd8532d6485..08cd221c2a2 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -18,8 +18,6 @@ # This is a reference script for Percona XtraBackup-based state snapshot tansfer -TMPDIR="/tmp" - . $(dirname $0)/wsrep_sst_common cleanup_joiner() @@ -34,8 +32,8 @@ cleanup_joiner() check_pid() { - local pid_file=$1 - [ -r $pid_file ] && ps -p $(cat $pid_file) >/dev/null 2>&1 + local pid_file="$1" + [ -r "$pid_file" ] && ps -p $(cat "$pid_file") >/dev/null 2>&1 } kill_xtrabackup() @@ -100,6 +98,15 @@ then if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then + TMPDIR=${TMPDIR:-""} + if [ -z "${TMPDIR}" ]; then + # try to get it from my.cnf + TMPDIR=$(grep -E '^\s*tmpdir' $WSREP_SST_OPT_CONF | \ + awk -F = '{ print $2 }' | sed 's/^\s//g' | sed 's/\s.*//g' ) + # if failed default to /tmp + [ -z "${TMPDIR}" ] && TMPDIR="/tmp" + fi + INNOBACKUPEX_ARGS="--galera-info --tmpdir=${TMPDIR} --stream=tar --defaults-file=${WSREP_SST_OPT_CONF} --socket=${WSREP_SST_OPT_SOCKET}" @@ -114,9 +121,6 @@ then set +e - # This file and variable seems to have no effect and probably should be deleted - XTRABACKUP_PID=$(mktemp --tmpdir wsrep_sst_xtrabackupXXXX.pid) - ${INNOBACKUPEX_BIN} ${INNOBACKUPEX_ARGS} ${TMPDIR} \ 2> ${DATA}/innobackup.backup.log | \ ${NC_BIN} ${REMOTEIP} ${NC_PORT} @@ -133,14 +137,17 @@ then exit 22 fi - if check_pid ${XTRABACKUP_PID} + # innobackupex implicitly writes PID to fixed location in ${TMPDIR} + XTRABACKUP_PID="${TMPDIR}/xtrabackup_pid" + + if check_pid "${XTRABACKUP_PID}" then wsrep_log_error "xtrabackup process is still running. Killing... " kill_xtrabackup exit 22 fi - rm -f ${XTRABACKUP_PID} + rm -f "${XTRABACKUP_PID}" else # BYPASS STATE="${WSREP_SST_OPT_GTID}" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 68f85ea579f..f25c59db761 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1100,7 +1100,7 @@ THD::THD() #ifdef WITH_WSREP mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); - wsrep_trx_handle.trx_id = -1; + wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; wsrep_trx_handle.opaque = NULL; //wsrep_retry_autocommit= ::wsrep_retry_autocommit; wsrep_retry_counter = 0; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 1efe724e6f9..e3df253f873 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3662,7 +3662,7 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( static Sys_var_charptr Sys_wsrep_node_name ( "wsrep_node_name", "Node name", GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), - IN_FS_CHARSET, DEFAULT(glob_hostname), + IN_FS_CHARSET, DEFAULT(wsrep_node_name), NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_charptr Sys_wsrep_node_address ( diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index d1be802b286..0d5a9fde7ca 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -59,6 +59,7 @@ void wsrep_cleanup_transaction(THD *thd) } thd->wsrep_exec_mode= LOCAL_STATE; } + thd->wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; } /* @@ -321,7 +322,12 @@ wsrep_run_wsrep_commit( } DBUG_RETURN(WSREP_TRX_OK); } - if (!rcode) { + if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_trx_handle.trx_id) + { + WSREP_WARN("SQL statement was ineffective: %s\n => Skipping replication", thd->query()); + } + else if (!rcode) + { rcode = wsrep->pre_commit( wsrep, (wsrep_conn_id_t)thd->thread_id, diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index c31c02e6d33..62397c58a6e 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -21,6 +21,7 @@ #include #include "log_event.h" +extern Format_description_log_event *wsrep_format_desc; wsrep_t *wsrep = NULL; my_bool wsrep_emulate_bin_log = FALSE; // activating parts of binlog interface @@ -94,6 +95,11 @@ wsrep_seqno_t local_seqno = WSREP_SEQNO_UNDEFINED; wsp::node_status local_status; long wsrep_protocol_version = 2; +// Boolean denoting if server is in initial startup phase. This is needed +// to make sure that main thread waiting in wsrep_sst_wait() is signaled +// if there was no state gap on receiving first view event. +static my_bool wsrep_startup = TRUE; + // action execute callback extern wsrep_status_t wsrep_apply_cb(void *ctx, const void* buf, size_t buf_len, @@ -283,13 +289,12 @@ static void wsrep_view_handler_cb (void* app_ctx, * NOTE: Initialize wsrep_group_uuid here only if it wasn't initialized * before - OR - it was reinitilized on startup (lp:992840) */ - if (!memcmp (&local_uuid, &WSREP_UUID_UNDEFINED, sizeof(wsrep_uuid_t)) || - 0 == wsrep_cluster_conf_id) + if (wsrep_startup) { - if (wsrep_init_first()) + if (wsrep_before_SE()) { wsrep_SE_init_grab(); - // Signal init thread to continue + // Signal mysqld init thread to continue wsrep_sst_complete (&cluster_uuid, view->seqno, false); // and wait for SE initialization wsrep_SE_init_wait(); @@ -305,15 +310,14 @@ static void wsrep_view_handler_cb (void* app_ctx, wsrep_set_SE_checkpoint(&xid); new_status= WSREP_MEMBER_JOINED; } - else // just some sanity check + + // just some sanity check + if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t))) { - if (memcmp (&local_uuid, &cluster_uuid, sizeof (wsrep_uuid_t))) - { - WSREP_ERROR("Undetected state gap. Can't continue."); - wsrep_log_states (WSREP_LOG_FATAL, &cluster_uuid, view->seqno, - &local_uuid, -1); - abort(); - } + WSREP_ERROR("Undetected state gap. Can't continue."); + wsrep_log_states(WSREP_LOG_FATAL, &cluster_uuid, view->seqno, + &local_uuid, -1); + unireg_abort(1); } } @@ -324,7 +328,7 @@ static void wsrep_view_handler_cb (void* app_ctx, } out: - + wsrep_startup= FALSE; local_status.set(new_status, view); } @@ -415,7 +419,7 @@ int wsrep_init() wsrep_ready_set(FALSE); assert(wsrep_provider); - + wsrep_format_desc= new Format_description_log_event(4); wsrep_init_position(); if ((rcode= wsrep_load(wsrep_provider, &wsrep, wsrep_log_cb)) != WSREP_OK) @@ -476,8 +480,10 @@ int wsrep_init() } static char inc_addr[512]= { 0, }; + if ((!wsrep_node_incoming_address || - !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) { + !strcmp (wsrep_node_incoming_address, WSREP_NODE_INCOMING_AUTO))) + { size_t const node_addr_len= strlen(node_addr); if (node_addr_len > 0) { @@ -579,6 +585,9 @@ void wsrep_deinit() provider_name[0]= '\0'; provider_version[0]= '\0'; provider_vendor[0]= '\0'; + + delete wsrep_format_desc; + wsrep_format_desc= NULL; } void wsrep_recover() @@ -1181,6 +1190,21 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, const TABLE_LIST* table_list) { int ret= 0; + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) + { + WSREP_INFO("thread: %lu, %s has been aborted due to multi-master conflict", + thd->thread_id, thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + return WSREP_TRX_FAIL; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (wsrep_debug && thd->mdl_context.has_locks()) + { + WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", + thd->query(), thd->thread_id); + } if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { switch (wsrep_OSU_method_options) { @@ -1236,24 +1260,28 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, { mysql_mutex_unlock(&request_thd->LOCK_wsrep_thd); WSREP_MDL_LOG(DEBUG, "MDL conflict ", request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); mysql_mutex_lock(&granted_thd->LOCK_wsrep_thd); if (granted_thd->wsrep_exec_mode == TOTAL_ORDER || granted_thd->wsrep_exec_mode == REPL_RECV) { WSREP_MDL_LOG(INFO, "MDL BF-BF conflict", request_thd, granted_thd); + ticket->wsrep_report(true); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH) { WSREP_DEBUG("mdl granted over FLUSH BF"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); ret = TRUE; } else if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE) { WSREP_DEBUG("DROP caused BF abort"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; @@ -1261,6 +1289,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, else if (granted_thd->wsrep_query_state == QUERY_COMMITTING) { WSREP_DEBUG("mdl granted, but commiting thd abort scheduled"); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; @@ -1268,6 +1297,7 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx, else { WSREP_MDL_LOG(DEBUG, "MDL conflict-> BF abort", request_thd, granted_thd); + ticket->wsrep_report(wsrep_debug); mysql_mutex_unlock(&granted_thd->LOCK_wsrep_thd); wsrep_abort_thd((void*)request_thd, (void*)granted_thd, 1); ret = FALSE; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index d1c72e6001f..e9cd227efcf 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -21,6 +21,8 @@ typedef struct st_mysql_show_var SHOW_VAR; #include #include "../wsrep/wsrep_api.h" +#define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX + class set_var; class THD; @@ -167,7 +169,7 @@ extern bool wsrep_sst_donor_update UPDATE_ARGS; extern bool wsrep_slave_threads_check CHECK_ARGS; extern bool wsrep_slave_threads_update UPDATE_ARGS; -extern bool wsrep_init_first(); // initialize wsrep before storage +extern bool wsrep_before_SE(); // initialize wsrep before storage // engines (true) or after (false) extern int wsrep_init(); extern void wsrep_deinit(); @@ -206,8 +208,8 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); /* wsrep initialization sequence at startup - * @param first wsrep_init_first() value */ -extern void wsrep_init_startup(bool first); + * @param first wsrep_before_SE() value */ +extern void wsrep_init_startup(bool before); extern void wsrep_close_client_connections(my_bool wait_to_end); extern int wsrep_wait_committing_connections_close(int wait_time); @@ -258,11 +260,11 @@ extern wsrep_seqno_t wsrep_locked_seqno; #define WSREP_LOG_CONFLICT_THD(thd, role) \ WSREP_LOG(sql_print_information, \ "%s: \n " \ - " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %ld\n " \ + " THD: %lu, mode: %s, state: %s, conflict: %s, seqno: %lld\n " \ " SQL: %s", \ role, wsrep_thd_thread_id(thd), wsrep_thd_exec_mode_str(thd), \ wsrep_thd_query_state_str(thd), \ - wsrep_thd_conflict_state_str(thd), wsrep_thd_trx_seqno(thd), \ + wsrep_thd_conflict_state_str(thd), (long long)wsrep_thd_trx_seqno(thd), \ wsrep_thd_query(thd) \ ); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 53e3bbcfc79..597d0ea087d 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -164,10 +164,10 @@ bool wsrep_sst_donor_update (sys_var *self, THD* thd, enum_var_type type) static wsrep_uuid_t cluster_uuid = WSREP_UUID_UNDEFINED; -bool wsrep_init_first() +bool wsrep_before_SE() { return (wsrep_provider != NULL - && strcmp (wsrep_provider, WSREP_NONE) + && strcmp (wsrep_provider, WSREP_NONE) && strcmp (wsrep_sst_method, WSREP_SST_SKIP) && strcmp (wsrep_sst_method, WSREP_SST_MYSQLDUMP)); } diff --git a/sql/wsrep_utils.cc b/sql/wsrep_utils.cc index b1bd6de07cf..daba0e4cab2 100644 --- a/sql/wsrep_utils.cc +++ b/sql/wsrep_utils.cc @@ -354,8 +354,9 @@ size_t guess_ip (char* buf, size_t buf_len) // try to find the address of the first one #if (TARGET_OS_LINUX == 1) const char cmd[] = "/sbin/ifconfig | " - "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " - "awk '{ print $2 }' | awk -F : '{ print $2 }'"; +// "grep -m1 -1 -E '^[a-z]?eth[0-9]' | tail -n 1 | " + "grep -E '^[[:space:]]+inet addr:' | grep -m1 -v 'inet addr:127' | " + "sed 's/:/ /' | awk '{ print $3 }'"; #elif defined(__sun__) const char cmd[] = "/sbin/ifconfig -a | " "/usr/gnu/bin/grep -m1 -1 -E 'net[0-9]:' | tail -n 1 | awk '{ print $2 }'"; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 3136f905109..36d73369c7d 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -24,21 +24,28 @@ #include #define WSREP_START_POSITION_ZERO "00000000-0000-0000-0000-000000000000:-1" +#define WSREP_CLUSTER_NAME "my_wsrep_cluster" -// trx history position to start with -const char* wsrep_start_position = WSREP_START_POSITION_ZERO; -const char* wsrep_provider = WSREP_NONE; -const char* wsrep_provider_options = (const char*)my_memdup("", 1, MYF(MY_WME)); -const char* wsrep_cluster_address = NULL; -const char* wsrep_cluster_name = "my_wsrep_cluster"; -const char* wsrep_node_name = glob_hostname; -static char node_address[256] = { 0, }; -const char* wsrep_node_address = node_address; +const char* wsrep_provider = 0; +const char* wsrep_provider_options = 0; +const char* wsrep_cluster_address = 0; +const char* wsrep_cluster_name = 0; +const char* wsrep_node_name = 0; +static char node_address[256] = { 0, }; +const char* wsrep_node_address = node_address; // ??? +const char* wsrep_start_position = 0; ulong wsrep_OSU_method_options; static int wsrep_thread_change = 0; int wsrep_init_vars() { + wsrep_provider = my_strdup(WSREP_NONE, MYF(MY_WME)); + wsrep_provider_options= my_strdup("", MYF(MY_WME)); + wsrep_cluster_address = my_strdup("", MYF(MY_WME)); + wsrep_cluster_name = my_strdup(WSREP_CLUSTER_NAME, MYF(MY_WME)); + wsrep_node_name = my_strdup("", MYF(MY_WME)); + wsrep_start_position = my_strdup(WSREP_START_POSITION_ZERO, MYF(MY_WME)); + global_system_variables.binlog_format=BINLOG_FORMAT_ROW; return 0; } @@ -152,13 +159,13 @@ void wsrep_start_position_init (const char* val) return; } - wsrep_start_position = my_strdup(val, MYF(0)); - wsrep_set_local_position (val); } static bool refresh_provider_options() { + WSREP_DEBUG("refresh_provider_options: %s", + (wsrep_provider_options) ? wsrep_provider_options : "null"); char* opts= wsrep->options_get(wsrep); if (opts) { @@ -225,6 +232,8 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_on_saved= thd->variables.wsrep_on; thd->variables.wsrep_on= false; + WSREP_DEBUG("wsrep_provider_update: %s", wsrep_provider); + wsrep_stop_replication(thd); wsrep_deinit(); @@ -250,12 +259,17 @@ bool wsrep_provider_update (sys_var *self, THD* thd, enum_var_type type) void wsrep_provider_init (const char* value) { + WSREP_DEBUG("wsrep_provider_init: %s -> %s", + (wsrep_provider) ? wsrep_provider : "null", + (value) ? value : "null"); if (NULL == value || wsrep_provider_verify (value)) { WSREP_ERROR("Bad initial value for wsrep_provider: %s", (value ? value : "")); return; } + + if (wsrep_provider) my_free((void *)wsrep_provider); wsrep_provider = my_strdup(value, MYF(0)); } @@ -327,9 +341,11 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type) void wsrep_cluster_address_init (const char* value) { - if (wsrep_cluster_address && wsrep_cluster_address != value) - my_free ((void*)wsrep_cluster_address); + WSREP_DEBUG("wsrep_cluster_address_init: %s -> %s", + (wsrep_cluster_address) ? wsrep_cluster_address : "null", + (value) ? value : "null"); + if (wsrep_cluster_address) my_free ((void*)wsrep_cluster_address); wsrep_cluster_address = (value) ? my_strdup(value, MYF(0)) : NULL; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ebcb5fdff6e..9070345e161 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7030,9 +7030,15 @@ wsrep_append_foreign_key( mutex_enter(&(dict_sys->mutex)); if (referenced) { +<<<<<<< TREE foreign->referenced_table = dict_table_check_if_in_cache_low( +======= + foreign->referenced_table = + dict_table_get_low( +>>>>>>> MERGE-SOURCE foreign->referenced_table_name_lookup); +<<<<<<< TREE foreign->referenced_index = wsrep_dict_foreign_find_index( foreign->referenced_table, @@ -7040,12 +7046,30 @@ wsrep_append_foreign_key( foreign->n_fields, foreign->foreign_index, TRUE, FALSE); +======= + if (foreign->referenced_table) + { + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } +>>>>>>> MERGE-SOURCE } else { +<<<<<<< TREE foreign->foreign_table = dict_table_check_if_in_cache_low( +======= + foreign->foreign_table = + dict_table_get_low( +>>>>>>> MERGE-SOURCE foreign->foreign_table_name_lookup); +<<<<<<< TREE foreign->foreign_index = wsrep_dict_foreign_find_index( foreign->foreign_table, @@ -7054,6 +7078,18 @@ wsrep_append_foreign_key( foreign->referenced_index, TRUE, FALSE); +======= + if (foreign->foreign_table) + { + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + } +>>>>>>> MERGE-SOURCE } mutex_exit(&(dict_sys->mutex)); } @@ -7072,7 +7108,7 @@ wsrep_append_foreign_key( ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; dict_index_t *idx_target = (referenced) ? - foreign->referenced_index : foreign->foreign_index; + foreign->referenced_index : index; dict_index_t *idx = (referenced) ? UT_LIST_GET_FIRST(foreign->referenced_table->indexes) : UT_LIST_GET_FIRST(foreign->foreign_table->indexes); @@ -7084,8 +7120,8 @@ wsrep_append_foreign_key( ut_a(idx); key[0] = (char)i; - rcode = wsrep_rec_get_primary_key( - &key[1], &len, rec, index, + rcode = wsrep_rec_get_foreign_key( + &key[1], &len, rec, index, idx, wsrep_protocol_version > 1); if (rcode != DB_SUCCESS) { WSREP_ERROR( @@ -11448,6 +11484,9 @@ innobase_xa_prepare( to the session variable take effect only in the next transaction */ if (!trx->support_xa) { +#ifdef WITH_WSREP + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); +#endif // WITH_WSREP return(0); } diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 30ef3048ff1..e2af5998899 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -833,11 +833,12 @@ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) #ifdef WITH_WSREP -int wsrep_rec_get_primary_key( +int wsrep_rec_get_foreign_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ + dict_index_t* index_for, /* in: index for foreign table */ + dict_index_t* index_ref, /* in: index for referenced table */ ibool new_protocol); /* in: protocol > 1 */ #endif /* WITH_WSREP */ #ifndef UNIV_NONINL diff --git a/storage/innobase/rem/rem0rec.c b/storage/innobase/rem/rem0rec.c index 44249c3a87e..d921889aaef 100644 --- a/storage/innobase/rem/rem0rec.c +++ b/storage/innobase/rem/rem0rec.c @@ -1777,11 +1777,12 @@ rec_print( #endif /* !UNIV_HOTBACKUP */ #ifdef WITH_WSREP int -wsrep_rec_get_primary_key( +wsrep_rec_get_foreign_key( byte *buf, /* out: extracted key */ ulint *buf_len, /* in/out: length of buf */ const rec_t* rec, /* in: physical record */ - dict_index_t* index, /* in: record descriptor */ + dict_index_t* index_for, /* in: index in foreign table */ + dict_index_t* index_ref, /* in: index in referenced table */ ibool new_protocol) /* in: protocol > 1 */ { const byte* data; @@ -1793,22 +1794,28 @@ wsrep_rec_get_primary_key( ulint offsets_[REC_OFFS_NORMAL_SIZE]; const ulint* offsets; - ut_ad(index); + ut_ad(index_for); + ut_ad(index_ref); rec_offs_init(offsets_); - offsets = rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap); + offsets = rec_get_offsets(rec, index_for, offsets_, + ULINT_UNDEFINED, &heap); ut_ad(rec_offs_validate(rec, NULL, offsets)); ut_ad(rec); - key_parts = dict_index_get_n_unique_in_tree(index); + key_parts = dict_index_get_n_unique_in_tree(index_for); for (i = 0; - i < key_parts && (index->type & DICT_CLUSTERED || i < key_parts - 1); + i < key_parts && + (index_for->type & DICT_CLUSTERED || i < key_parts - 1); i++) { - - dict_field_t* field = dict_index_get_nth_field(index, i); - const dict_col_t* col = dict_field_get_col(field); + dict_field_t* field_f = + dict_index_get_nth_field(index_for, i); + const dict_col_t* col_f = dict_field_get_col(field_f); + dict_field_t* field_r = + dict_index_get_nth_field(index_ref, i); + const dict_col_t* col_r = dict_field_get_col(field_r); data = rec_get_nth_field(rec, offsets, i, &len); if (key_len + ((len != UNIV_SQL_NULL) ? len + 1 : 1) > @@ -1820,25 +1827,25 @@ wsrep_rec_get_primary_key( } if (len == UNIV_SQL_NULL) { - ut_a(!(col->prtype & DATA_NOT_NULL)); + ut_a(!(col_f->prtype & DATA_NOT_NULL)); *buf++ = 1; key_len++; } else if (!new_protocol) { - if (!(col->prtype & DATA_NOT_NULL)) { + if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; } memcpy(buf, data, len); wsrep_innobase_mysql_sort( - (int)(col->prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(col->prtype), + (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col_f->prtype), buf, len); } else { /* new protocol */ - if (!(col->prtype & DATA_NOT_NULL)) { + if (!(col_r->prtype & DATA_NOT_NULL)) { *buf++ = 0; key_len++; } - switch (col->mtype) { + switch (col_f->mtype) { case DATA_INT: { byte* ptr = buf+len; for (;;) { @@ -1850,7 +1857,7 @@ wsrep_rec_get_primary_key( data++; } - if (!(col->prtype & DATA_UNSIGNED)) { + if (!(col_f->prtype & DATA_UNSIGNED)) { buf[len-1] = (byte) (buf[len-1] ^ 128); } @@ -1862,8 +1869,10 @@ wsrep_rec_get_primary_key( /* Copy the actual data */ ut_memcpy(buf, data, len); wsrep_innobase_mysql_sort( - (int)(col->prtype & DATA_MYSQL_TYPE_MASK), - (uint)dtype_get_charset_coll(col->prtype), + (int) + (col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint) + dtype_get_charset_coll(col_f->prtype), buf, len); break; case DATA_BLOB: