Browse Source

Review fixes.

pull/9/head
Jan Lindström 11 years ago
parent
commit
21b4dec072
  1. 24
      include/thr_lock.h
  2. 58
      include/wsrep.h
  3. 2
      mysys/my_default.c
  4. 4
      mysys/my_static.c
  5. 2
      mysys/mysys_priv.h
  6. 56
      mysys/thr_lock.c
  7. 4
      scripts/wsrep_sst_common
  8. 4
      scripts/wsrep_sst_common.sh
  9. 7
      scripts/wsrep_sst_mysqldump
  10. 7
      scripts/wsrep_sst_mysqldump.sh
  11. 3
      sql/events.cc
  12. 5
      sql/ha_partition.cc
  13. 138
      sql/handler.cc
  14. 1
      sql/handler.h
  15. 14
      sql/item_func.cc
  16. 60
      sql/lock.cc
  17. 288
      sql/log.cc
  18. 27
      sql/log.h
  19. 165
      sql/log_event.cc
  20. 7
      sql/log_event.h
  21. 95
      sql/mdl.cc
  22. 8
      sql/mdl.h
  23. 641
      sql/mysqld.cc
  24. 9
      sql/mysqld.h
  25. 10
      sql/protocol.cc
  26. 33
      sql/rpl_record.cc
  27. 19
      sql/slave.cc
  28. 39
      sql/sp.cc
  29. 15
      sql/sp.h
  30. 33
      sql/sql_acl.cc
  31. 3
      sql/sql_admin.cc
  32. 6
      sql/sql_alter.cc
  33. 31
      sql/sql_base.cc
  34. 279
      sql/sql_class.cc
  35. 26
      sql/sql_class.h
  36. 6
      sql/sql_connect.cc
  37. 29
      sql/sql_delete.cc
  38. 57
      sql/sql_insert.cc
  39. 4
      sql/sql_lex.cc
  40. 251
      sql/sql_parse.cc
  41. 17
      sql/sql_parse.h
  42. 23
      sql/sql_partition_admin.cc
  43. 22
      sql/sql_plugin.cc
  44. 36
      sql/sql_prepare.cc
  45. 10
      sql/sql_repl.cc
  46. 10
      sql/sql_show.cc
  47. 76
      sql/sql_table.cc
  48. 60
      sql/sql_trigger.cc
  49. 2
      sql/sql_truncate.cc
  50. 23
      sql/sql_update.cc
  51. 2
      sql/sys_vars.cc
  52. 2
      sql/table.cc
  53. 42
      sql/transaction.cc
  54. 3
      sql/tztime.cc
  55. 8
      sql/wsrep_binlog.cc
  56. 2
      sql/wsrep_hton.cc
  57. 880
      sql/wsrep_mysqld.cc
  58. 57
      sql/wsrep_mysqld.h
  59. 2
      sql/wsrep_sst.h
  60. 2
      sql/wsrep_thd.h
  61. 2
      sql/wsrep_var.h
  62. 52
      storage/innobase/handler/ha_innodb.cc

24
include/thr_lock.h

@ -20,16 +20,6 @@
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WITH_WSREP
#include <my_sys.h>
typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool);
typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool);
typedef int (* wsrep_on_fun)(void *);
void wsrep_thr_lock_init(
wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun,
my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun);
#endif
#include <my_pthread.h>
#include <my_list.h>
@ -104,10 +94,7 @@ typedef struct st_thr_lock_info
{
pthread_t thread;
my_thread_id thread_id;
#ifdef WITH_WSREP
void *mysql_thd; // THD pointer
my_bool in_lock_tables; // true, if inside locking session
#endif
} THR_LOCK_INFO;
@ -177,6 +164,17 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data,
ulong lock_wait_timeout);
void thr_set_lock_wait_callback(void (*before_wait)(void),
void (*after_wait)(void));
#ifdef WITH_WSREP
#include <my_sys.h>
typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool);
typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool);
typedef int (* wsrep_on_fun)(void *);
void wsrep_thr_lock_init(
wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun,
my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun);
#endif
#ifdef __cplusplus
}
#endif

58
include/wsrep.h

@ -0,0 +1,58 @@
/* Copyright 2014 Codership Oy <http://www.codership.com> & SkySQL Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef WSREP_INCLUDED
#define WSERP_INCLUDED
#ifdef WITH_WSREP
#define IF_WSREP(A,B) A
#define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A)
#if !defined(EMBEDDED_LIBRARY)
#define WSREP_FORMAT(my_format) \
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
#else
#define WSREP_FORMAT(my_format) my_format
#endif /* && !EMBEDDED_LIBRARY */
#define WSREP_MYSQL_DB (char *)"mysql"
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
goto error;
#define WSREP_TO_ISOLATION_END \
if (WSREP_ON && (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER))) \
wsrep_to_isolation_end(thd);
#define WSREP_DEBUG(...) \
if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
#define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__)
#define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__)
#else
#define IF_WSREP(A,B) B
#define DBUG_ASSERT_IF_WSREP(A)
#define WSREP_DEBUG(...)
#define WSREP_INFO(...)
#define WSREP_WARN(...)
#define WSREP_ERROR(...)
#define WSREP_FORMAT(my_format) my_format
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_)
#define WSREP_TO_ISOLATION_END
#endif
#endif /* WSERP_INCLUDED */

2
mysys/my_default.c

@ -813,7 +813,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
#ifdef WITH_WSREP
/* make sure we do this only once - for top-level file */
if ('\0' == wsrep_defaults_file[0])
strncpy(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1);
strmake(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1);
#endif /* WITH_WSREP */
while (mysql_file_fgets(buff, sizeof(buff) - 1, fp))

4
mysys/my_static.c

@ -68,6 +68,10 @@ uint my_large_page_size= 0;
int volatile my_have_got_alarm=0; /* declare variable to reset */
ulong my_time_to_wait_for_lock=2; /* In seconds */
#ifdef WITH_WSREP
my_bool mysys_wsrep= 0;
#endif
/* from errors.c */
#ifdef SHARED_LIBRARY
const char *globerrs[GLOBERRS]; /* my_error_messages is here */

2
mysys/mysys_priv.h

@ -62,6 +62,8 @@ extern mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache;
extern mysql_mutex_t THR_LOCK_lock, THR_LOCK_net;
extern mysql_mutex_t THR_LOCK_charset;
extern my_bool mysys_wsrep;
#include <mysql/psi/mysql_file.h>
#ifdef HAVE_PSI_INTERFACE

56
mysys/thr_lock.c

@ -683,10 +683,10 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
* This needs an condition to check for bf locks first.
* TODO: we still have a debug fprintf, this should be removed
*/
static inline my_bool
static my_bool
wsrep_break_lock(
THR_LOCK_DATA *data, struct st_lock_list *lock_queue1,
struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue)
struct st_lock_list *wait_queue)
{
if (wsrep_on(data->owner->mysql_thd) &&
wsrep_thd_is_brute_force &&
@ -698,7 +698,7 @@ wsrep_break_lock(
we know that this conflicting lock must be read lock and furthermore,
lock holder is read-only. It is safe to wait for him.
*/
#ifdef TODO
#ifdef TODO_WHEN_LOCK_TABLES_IS_A_TRANSACTION
if (wsrep_convert_LOCK_to_trx &&
(THD*)(data->owner->mysql_thd)->in_lock_tables)
{
@ -727,22 +727,6 @@ wsrep_break_lock(
return FALSE;
}
}
for (holder=(lock_queue2) ? lock_queue2->data : NULL;
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);
}
else
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
return FALSE;
}
}
/* Add our lock to the head of the wait queue */
if (*(wait_queue->last)==wait_queue->data)
@ -846,14 +830,6 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
}
if (lock->write.data->type == TL_WRITE_ONLY)
{
#ifdef WITH_WSREP
if (wsrep_break_lock(data, &lock->write, NULL, &lock->read_wait))
{
wsrep_lock_inserted= TRUE;
goto wsrep_read_wait;
}
#endif
/* We are not allowed to get a READ lock in this case */
data->type=TL_UNLOCK;
result= THR_LOCK_ABORTED; /* Can't wait for this one */
@ -882,7 +858,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
In the latter case we should yield the lock to the writer.
*/
#ifdef WITH_WSREP
if (wsrep_break_lock(data, &lock->write, NULL, &lock->read_wait))
if (mysys_wsrep && wsrep_break_lock(data, &lock->write, &lock->read_wait))
{
wsrep_lock_inserted= TRUE;
}
@ -897,25 +873,12 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
{
if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY)
{
#ifdef WITH_WSREP
if (wsrep_break_lock(data, &lock->write, NULL, &lock->write_wait))
{
wsrep_lock_inserted=TRUE;
goto wsrep_write_wait;
}
#endif
data->type=TL_UNLOCK;
result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
if (lock->write.data || lock->read.data)
{
#ifdef WITH_WSREP
if (wsrep_break_lock(data, &lock->write, NULL, &lock->write_wait))
{
goto end;
}
#endif
/* Add delayed write lock to write_wait queue, and return at once */
(*lock->write_wait.last)=data;
data->prev=lock->write_wait.last;
@ -940,13 +903,6 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
/* Allow lock owner to bypass TL_WRITE_ONLY. */
if (!thr_lock_owner_equal(data->owner, lock->write.data->owner))
{
#ifdef WITH_WSREP
if (wsrep_break_lock(data, &lock->write, NULL, &lock->write_wait))
{
wsrep_lock_inserted=TRUE;
goto wsrep_write_wait;
}
#endif
/* We are not allowed to get a lock in this case */
data->type=TL_UNLOCK;
result= THR_LOCK_ABORTED; /* Can't wait for this one */
@ -1051,7 +1007,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
lock->read.data->owner->thread_id, data->type));
}
#ifdef WITH_WSREP
if (wsrep_break_lock(data, &lock->write, NULL, &lock->write_wait))
if (mysys_wsrep && wsrep_break_lock(data, &lock->write, &lock->write_wait))
{
wsrep_lock_inserted= TRUE;
}
@ -1063,7 +1019,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
}
/* Can't get lock yet; Wait for it */
#ifdef WITH_WSREP
if (wsrep_on(data->owner->mysql_thd) && wsrep_lock_inserted)
if (mysys_wsrep && wsrep_lock_inserted && wsrep_on(data->owner->mysql_thd))
DBUG_RETURN(wait_for_lock(wait_queue, data, 1, lock_wait_timeout));
#endif
result= wait_for_lock(wait_queue, data, 0, lock_wait_timeout);

4
scripts/wsrep_sst_common

@ -94,7 +94,7 @@ done
readonly WSREP_SST_OPT_BYPASS
readonly WSREP_SST_OPT_BINLOG
# For Bug:1200727
# State Snapshot Transfer authentication password was displayed in the ps output. Bug fixed #1200727.
if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then
if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then
WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
@ -114,7 +114,7 @@ wsrep_log()
# echo everything to stderr so that it gets into common error log
# deliberately made to look different from the rest of the log
local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)"
echo "WSREP_SST: $* ($tst)" >&2
echo "$tst WSREP_SST: " >&2
}
wsrep_log_error()

4
scripts/wsrep_sst_common.sh

@ -94,7 +94,7 @@ done
readonly WSREP_SST_OPT_BYPASS
readonly WSREP_SST_OPT_BINLOG
# For Bug:1200727
# State Snapshot Transfer authentication password was displayed in the ps output. Bug fixed #1200727.
if my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -q "wsrep_sst_auth";then
if [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ];then
WSREP_SST_OPT_AUTH=$(my_print_defaults -c $WSREP_SST_OPT_CONF sst | grep -- "--wsrep_sst_auth" | cut -d= -f2)
@ -114,7 +114,7 @@ wsrep_log()
# echo everything to stderr so that it gets into common error log
# deliberately made to look different from the rest of the log
local readonly tst="$(date +%Y%m%d\ %H:%M:%S.%N | cut -b -21)"
echo "WSREP_SST: $* ($tst)" >&2
echo "$tst WSREP_SST: " >&2
}
wsrep_log_error()

7
scripts/wsrep_sst_mysqldump

@ -24,11 +24,10 @@ WSREP_SST_OPT_CONF=""
. $(dirname $0)/wsrep_sst_common
EINVAL=22
PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
local_ip()
{
PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
[ "$1" = "127.0.0.1" ] && return 0
[ "$1" = "localhost" ] && return 0
[ "$1" = "$(hostname -s)" ] && return 0
@ -58,10 +57,10 @@ then
fi
# Check client version
if ! mysql --version | grep 'Distrib 10.0' >/dev/null
if ! mysql --version | grep 'Distrib 10' >/dev/null
then
mysql --version >&2
wsrep_log_error "this operation requires MySQL client version 10.0.x"
wsrep_log_error "this operation requires MySQL client version 10 or newer"
exit $EINVAL
fi

7
scripts/wsrep_sst_mysqldump.sh

@ -24,11 +24,10 @@ WSREP_SST_OPT_CONF=""
. $(dirname $0)/wsrep_sst_common
EINVAL=22
PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
local_ip()
{
PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
[ "$1" = "127.0.0.1" ] && return 0
[ "$1" = "localhost" ] && return 0
[ "$1" = "$(hostname -s)" ] && return 0
@ -58,10 +57,10 @@ then
fi
# Check client version
if ! mysql --version | grep 'Distrib 10.0' >/dev/null
if ! mysql --version | grep 'Distrib 10' >/dev/null
then
mysql --version >&2
wsrep_log_error "this operation requires MySQL client version 10.0.x"
wsrep_log_error "this operation requires MySQL client version 10 or newer"
exit $EINVAL
fi

3
sql/events.cc

@ -1190,7 +1190,8 @@ end:
#ifdef WITH_WSREP
int wsrep_create_event_query(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
char buffer[1024];
String log_query(buffer, sizeof(buffer), &my_charset_bin);
if (create_query_string(thd, &log_query))
{

5
sql/ha_partition.cc

@ -386,14 +386,17 @@ const char *ha_partition::table_type() const
// we can do this since we only support a single engine type
return m_file[0]->table_type();
}
#if defined(WITH_WSREP) && !defined(EMBEDDED_LIBRARY)
int ha_partition::wsrep_db_type() const
{
// we can do this since we only support a single engine type
return ha_legacy_type(m_file[0]->ht);
return partition_ht()->db_type;
}
#endif /* WITH_WSREP && !EMBEDDED_LIBRARY */
/*
Destructor method

138
sql/handler.cc

@ -50,9 +50,9 @@
#include "../storage/maria/ha_maria.h"
#endif
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif
#include "wsrep.h"
/*
While we have legacy_db_type, we have this array to
check for dups and to find handlerton from legacy_db_type.
@ -1169,26 +1169,24 @@ int ha_prepare(THD *thd)
if ((err= ht->prepare(ht, thd, all)))
{
#ifdef WITH_WSREP
if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP)
if (ht == wsrep_hton)
{
error= 1;
/* avoid sending error, if we need to replay */
error= 1;
/* avoid sending error, if we need to replay */
if (thd->wsrep_conflict_state!= MUST_REPLAY)
{
my_error(ER_LOCK_DEADLOCK, MYF(0), err);
}
}
else
#endif
{
/* not wsrep hton, bail to native mysql behavior */
#endif
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
ha_rollback_trans(thd, all);
error=1;
break;
#ifdef WITH_WSREP
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
ha_rollback_trans(thd, all);
error=1;
break;
}
#endif
}
}
else
@ -1386,13 +1384,9 @@ int ha_commit_trans(THD *thd, bool all)
mdl_request.init(MDL_key::COMMIT, "", "", MDL_INTENTION_EXCLUSIVE,
MDL_EXPLICIT);
#ifdef WITH_WSREP
if (!WSREP(thd) &&
if (IF_WSREP(!WSREP(thd),1) &&
thd->mdl_context.acquire_lock(&mdl_request,
#else
if (thd->mdl_context.acquire_lock(&mdl_request,
#endif /* WITH_WSREP */
thd->variables.lock_wait_timeout))
thd->variables.lock_wait_timeout))
{
ha_rollback_trans(thd, all);
thd->wakeup_subsequent_commits(1);
@ -1439,15 +1433,13 @@ int ha_commit_trans(THD *thd, bool all)
err= ht->prepare(ht, thd, all);
status_var_increment(thd->status_var.ha_prepare_count);
if (err)
#ifdef WITH_WSREP
{
if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP)
#ifdef WITH_WSREP
if (ht == wsrep_hton)
{
error= 1;
switch (err)
{
switch (err) {
case WSREP_TRX_SIZE_EXCEEDED:
/* give user size exeeded erro from wsrep_api.h */
/* give user size exeeded error from wsrep_api.h */
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
break;
case WSREP_TRX_CERT_FAIL:
@ -1458,15 +1450,11 @@ int ha_commit_trans(THD *thd, bool all)
my_error(ER_LOCK_DEADLOCK, MYF(0), err);
}
}
goto err;
}
else
/* not wsrep hton, bail to native mysql behavior */
#endif /* WITH_WSREP */
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
if (err)
goto err;
@ -1477,12 +1465,13 @@ int ha_commit_trans(THD *thd, bool all)
DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE(););
#ifdef WITH_WSREP
if (!error && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid))
if (!error && WSREP_ON && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid))
{
// xid was rewritten by wsrep
xid= wsrep_xid_seqno(&thd->transaction.xid_state.xid);
}
#endif // WITH_WSREP
if (!is_real_trans)
{
error= commit_one_phase_2(thd, all, trans, is_real_trans);
@ -1859,13 +1848,10 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
got, hton_name(hton)->str);
for (int i=0; i < got; i ++)
{
#ifdef WITH_WSREP
my_xid x=(wsrep_is_wsrep_xid(&info->list[i]) ?
wsrep_xid_seqno(&info->list[i]) :
info->list[i].get_my_xid());
#else
my_xid x=info->list[i].get_my_xid();
#endif /* WITH_WSREP */
my_xid x= IF_WSREP(WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ?
wsrep_xid_seqno(&info->list[i]) :
info->list[i].get_my_xid(),
info->list[i].get_my_xid());
if (!x) // not "mine" - that is generated by external TM
{
#ifndef DBUG_OFF
@ -3150,15 +3136,12 @@ int handler::update_auto_increment()
variables->auto_increment_increment);
auto_inc_intervals_count++;
/* Row-based replication does not need to store intervals in binlog */
#ifdef WITH_WSREP
if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) &&
!thd->is_current_stmt_binlog_format_row())
#else
if (mysql_bin_log.is_open() && !thd->is_current_stmt_binlog_format_row())
#endif /* WITH_WSREP */
thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
auto_inc_interval_for_cur_row.values(),
variables->auto_increment_increment);
if (IF_WSREP((WSREP(thd) && (wsrep_emulate_bin_log || mysql_bin_log.is_open())), mysql_bin_log.is_open())
&& !thd->is_current_stmt_binlog_format_row())
thd->auto_inc_intervals_in_cur_stmt_for_binlog.
append(auto_inc_interval_for_cur_row.minimum(),
auto_inc_interval_for_cur_row.values(),
variables->auto_increment_increment);
}
/*
@ -5776,13 +5759,9 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
return (thd->is_current_stmt_binlog_format_row() &&
table->s->cached_row_logging_check &&
(thd->variables.option_bits & OPTION_BIN_LOG) &&
#ifdef WITH_WSREP
/* applier and replayer should not binlog */
((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) ||
(IF_WSREP((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)),0) ||
mysql_bin_log.is_open()));
#else
mysql_bin_log.is_open());
#endif
}
@ -5884,14 +5863,9 @@ static int binlog_log_row(TABLE* table,
#ifdef WITH_WSREP
/* only InnoDB tables will be replicated through binlog emulation */
if (WSREP_EMULATE_BINLOG(thd) &&
table->file->ht->db_type != DB_TYPE_INNODB &&
!(table->file->ht->db_type == DB_TYPE_PARTITION_DB &&
(((ha_partition*)(table->file))->wsrep_db_type() == DB_TYPE_INNODB)))
// !strcmp(table->file->table_type(), "InnoDB"))
{
if (WSREP_ON && WSREP_EMULATE_BINLOG(thd) &&
table->file->partition_ht()->db_type != DB_TYPE_INNODB)
return 0;
}
#endif /* WITH_WSREP */
if (check_table_binlog_row_based(thd, table))
{
@ -6240,46 +6214,58 @@ void handler::set_lock_type(enum thr_lock_type lock)
int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal)
{
DBUG_ENTER("ha_wsrep_abort_transaction");
if (!WSREP(bf_thd) &&
if (!WSREP(bf_thd) &&
!(wsrep_OSU_method_options == WSREP_OSU_RSU &&
bf_thd->wsrep_exec_mode == TOTAL_ORDER)) {
DBUG_RETURN(0);
}
handlerton *hton= installed_htons[DB_TYPE_INNODB];
if (hton && hton->wsrep_abort_transaction)
{
hton->wsrep_abort_transaction(hton, bf_thd, victim_thd, signal);
}
else
THD_TRANS *trans= &victim_thd->transaction.all;
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
for (; ha_info; ha_info= ha_info_next)
{
WSREP_WARN("cannot abort InnoDB transaction");
handlerton *hton= ha_info->ht();
if (!hton->wsrep_abort_transaction)
{
WSREP_WARN("cannot abort WRESP transaction");
}
else
hton->wsrep_abort_transaction(hton, bf_thd, victim_thd, signal);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
}
DBUG_RETURN(0);
}
void ha_wsrep_fake_trx_id(THD *thd)
{
DBUG_ENTER("ha_wsrep_fake_trx_id");
if (!WSREP(thd))
if (!WSREP(thd))
{
DBUG_VOID_RETURN;
}
handlerton *hton= installed_htons[DB_TYPE_INNODB];
if (hton && hton->wsrep_fake_trx_id)
{
hton->wsrep_fake_trx_id(hton, thd);
}
else
THD_TRANS *trans= &thd->transaction.all;
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
for (; ha_info; ha_info= ha_info_next)
{
WSREP_WARN("cannot get fake InnoDB transaction ID");
handlerton *hton= ha_info->ht();
if (!hton->wsrep_fake_trx_id)
{
WSREP_WARN("cannot get fake InnoDB transaction ID");
}
else
hton->wsrep_fake_trx_id(hton, thd);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
}
DBUG_VOID_RETURN;
}
#endif /* WITH_WSREP */
#ifdef TRANS_LOG_MGM_EXAMPLE_CODE
/*
Example of transaction log management functions based on assumption that logs

1
sql/handler.h

@ -439,7 +439,6 @@ enum legacy_db_type
DB_TYPE_BINLOG=21,
DB_TYPE_PBXT=23,
DB_TYPE_PERFORMANCE_SCHEMA=28,
DB_TYPE_WSREP=41,
DB_TYPE_ARIA=42,
DB_TYPE_TOKUDB=43,
DB_TYPE_FIRST_DYNAMIC=44,

14
sql/item_func.cc

@ -2769,7 +2769,19 @@ void Item_func_rand::seed_random(Item *arg)
TODO: do not do reinit 'rand' for every execute of PS/SP if
args[0] is a constant.
*/
uint32 tmp= (uint32) arg->val_int();
uint32 tmp;
#ifdef WITH_WSREP
if (WSREP(current_thd))
{
if (current_thd->wsrep_exec_mode==REPL_RECV)
tmp= current_thd->wsrep_rand;
else
tmp= current_thd->wsrep_rand= (uint32) arg->val_int();
}
else
#endif /* WITH_WSREP */
tmp= (uint32) arg->val_int();
my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L),
(uint32) (tmp*0x10000001L));
}

60
sql/lock.cc

@ -83,10 +83,7 @@
#include "sql_acl.h" // SUPER_ACL
#include <hash.h>
#include <assert.h>
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif /* WITH_WSREP */
/**
@defgroup Locking Locking
@ -318,9 +315,6 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags)
/* Copy the lock data array. thr_multi_lock() reorders its contents. */
memmove(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
sql_lock->lock_count * sizeof(*sql_lock->locks));
#ifdef WITH_WSREP
thd->lock_info.in_lock_tables= thd->in_lock_tables;
#endif
/* Lock on the copied half of the lock data array. */
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
@ -332,26 +326,21 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags)
end:
THD_STAGE_INFO(thd, stage_after_table_lock);
#ifdef WITH_WSREP
thd_proc_info(thd, "mysql_lock_tables(): unlocking tables II");
#else /* WITH_WSREP */
thd_proc_info(thd, 0);
#endif /* WITH_WSREP */
if (thd->killed)
{
thd->send_kill_message();
if (!rc)
{
mysql_unlock_tables(thd, sql_lock, 0);
THD_STAGE_INFO(thd, stage_after_table_lock);
}
rc= 1;
}
else if (rc > 1)
my_error(rc, MYF(0));
thd->set_time_after_lock();
#ifdef WITH_WSREP
thd_proc_info(thd, "exit mysqld_lock_tables()");
#endif /* WITH_WSREP */
DBUG_RETURN(rc);
}
@ -396,6 +385,8 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
{
DBUG_ENTER("mysql_unlock_tables");
THD_STAGE_INFO(thd, stage_unlocking_tables);
if (sql_lock->table_count)
unlock_external(thd, sql_lock->table, sql_lock->table_count);
if (sql_lock->lock_count)
@ -1069,8 +1060,11 @@ void Global_read_lock::unlock_global_read_lock(THD *thd)
thd->mdl_context.release_lock(m_mdl_blocks_commits_lock);
m_mdl_blocks_commits_lock= NULL;
#ifdef WITH_WSREP
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
wsrep->resume(wsrep);
if (WSREP_ON)
{
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
wsrep->resume(wsrep);
}
#endif /* WITH_WSREP */
}
thd->mdl_context.release_lock(m_mdl_global_shared_lock);
@ -1105,8 +1099,11 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
make_global_read_lock_block_commit(), do nothing.
*/
if (m_state != GRL_ACQUIRED)
DBUG_RETURN(0);
#ifdef WITH_WSREP
if (m_mdl_blocks_commits_lock)
if (WSREP_ON && m_mdl_blocks_commits_lock)
{
WSREP_DEBUG("GRL was in block commit mode when entering "
"make_global_read_lock_block_commit");
@ -1114,13 +1111,9 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
m_mdl_blocks_commits_lock= NULL;
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
wsrep->resume(wsrep);
m_state= GRL_ACQUIRED;
}
#endif /* WITH_WSREP */
if (m_state != GRL_ACQUIRED)
DBUG_RETURN(0);
mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT);
if (thd->mdl_context.acquire_lock(&mdl_request,
@ -1131,19 +1124,22 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT;
#ifdef WITH_WSREP
long long ret = wsrep->pause(wsrep);
if (ret >= 0)
if (WSREP_ON)
{
wsrep_locked_seqno= ret;
}
else if (ret != -ENOSYS) /* -ENOSYS - no provider */
{
WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret));
long long ret = wsrep->pause(wsrep);
if (ret >= 0)
{
wsrep_locked_seqno= ret;
}
else if (ret != -ENOSYS) /* -ENOSYS - no provider */
{
WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret));
/* m_mdl_blocks_commits_lock is always NULL here */
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
my_error(ER_LOCK_DEADLOCK, MYF(0));
DBUG_RETURN(TRUE);
DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL);
wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
my_error(ER_LOCK_DEADLOCK, MYF(0));
DBUG_RETURN(TRUE);
}
}
#endif /* WITH_WSREP */
DBUG_RETURN(FALSE);

288
sql/log.cc

@ -52,12 +52,11 @@
#include "sql_plugin.h"
#include "rpl_handler.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif /* WITH_WSREP */
#include "debug_sync.h"
#include "sql_show.h"
#include "my_pthread.h"
#include "wsrep_mysqld.h"
/* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024
@ -66,6 +65,7 @@
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
handlerton *binlog_hton;
LOGGER logger;
MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period);
@ -514,11 +514,6 @@ private:
binlog_cache_mngr(const binlog_cache_mngr& info);
};
handlerton *binlog_hton;
#ifdef WITH_WSREP
extern handlerton *wsrep_hton;
#endif
bool LOGGER::is_log_table_enabled(uint log_table_type)
{
switch (log_table_type) {
@ -532,129 +527,6 @@ bool LOGGER::is_log_table_enabled(uint log_table_type)
}
}
#ifdef WITH_WSREP
IO_CACHE * get_trans_log(THD * thd)
{
binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*)
thd_get_ha_data(thd, binlog_hton);
if (cache_mngr)
{
return cache_mngr->get_binlog_cache_log(true);
}
else
{
WSREP_DEBUG("binlog cache not initialized, conn :%ld", thd->thread_id);
return NULL;
}
}
bool wsrep_trans_cache_is_empty(THD *thd)
{
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
return (!cache_mngr || cache_mngr->trx_cache.empty());
}
void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end)
{
thd->binlog_flush_pending_rows_event(stmt_end);
}
void thd_binlog_trx_reset(THD * thd)
{
/*
todo: fix autocommit select to not call the caller
*/
if (thd_get_ha_data(thd, binlog_hton) != NULL)
{
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
if (cache_mngr) cache_mngr->reset(false, true);
}
thd->clear_binlog_table_maps();
}
void thd_binlog_rollback_stmt(THD * thd)
{
WSREP_DEBUG("thd_binlog_rollback_stmt :%ld", thd->thread_id);
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
if (cache_mngr) cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
}
#ifdef REMOVED
/*
Write the contents of a cache to memory buffer.
This function quite the same as MYSQL_BIN_LOG::write_cache(),
with the exception that here we write in buffer instead of log file.
*/
int wsrep_write_cache(IO_CACHE *cache, uchar **buf, int *buf_len)
{
if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0))
return ER_ERROR_ON_WRITE;
uint length= my_b_bytes_in_cache(cache);
long long total_length = 0;
uchar *buf_ptr = NULL;
do
{
/* bail out if buffer grows too large
This is a temporary fix to avoid flooding replication
TODO: remove this check for 0.7.4 release
*/
if (total_length > wsrep_max_ws_size)
{
WSREP_WARN("transaction size limit (%lld) exceeded: %lld",
wsrep_max_ws_size, total_length);
if (reinit_io_cache(cache, WRITE_CACHE, 0, 0, 0))
{
WSREP_WARN("failed to initialize io-cache");
}
if (buf_ptr) my_free(*buf);
*buf_len = 0;
return ER_ERROR_ON_WRITE;
}
if (total_length > 0)
{
*buf_len += length;
*buf = (uchar *)my_realloc(*buf, total_length+length,
MYF(MY_ALLOW_ZERO_PTR));
if (!*buf)
{
WSREP_ERROR("io cache write problem: %d %d", *buf_len, length);
return ER_ERROR_ON_WRITE;
}
buf_ptr = *buf+total_length;
}
else
{
if (buf_ptr != NULL)
{
WSREP_ERROR("io cache alloc error: %d %d", *buf_len, length);
my_free(*buf);
}
if (length > 0)
{
*buf = (uchar *) my_malloc(length, MYF(0));
buf_ptr = *buf;
*buf_len = length;
}
}
total_length += length;
memcpy(buf_ptr, cache->read_pos, length);
cache->read_pos=cache->read_end;
} while ((cache->file >= 0) && (length= my_b_fill(cache)));
return 0;
}
#endif /* REMOVED */
#endif
/**
Check if a given table is opened log table
@ -1705,11 +1577,8 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos)
DBUG_ENTER("binlog_trans_log_savepos");
DBUG_ASSERT(pos != NULL);
binlog_cache_mngr *const cache_mngr= thd->binlog_setup_trx_data();
#ifdef WITH_WSREP
DBUG_ASSERT((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open());
#else
DBUG_ASSERT(mysql_bin_log.is_open());
#endif
DBUG_ASSERT_IF_WSREP(((WSREP(thd) && wsrep_emulate_bin_log)) || mysql_bin_log.is_open());
DBUG_ASSERT(IF_WSREP(1, mysql_bin_log.is_open()));
*pos= cache_mngr->trx_cache.get_byte_position();
DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos));
DBUG_VOID_RETURN;
@ -1757,16 +1626,8 @@ binlog_trans_log_truncate(THD *thd, my_off_t pos)
int binlog_init(void *p)
{
binlog_hton= (handlerton *)p;
#ifdef WITH_WSREP
if (WSREP_ON)
binlog_hton->state= SHOW_OPTION_YES;
else
{
#endif /* WITH_WSREP */
binlog_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO;
#ifdef WITH_WSREP
}
#endif /* WITH_WSREP */
binlog_hton->state=IF_WSREP(WSREP_ON || opt_bin_log, opt_bin_log) ?
SHOW_OPTION_YES : SHOW_OPTION_NO;
binlog_hton->db_type=DB_TYPE_BINLOG;
binlog_hton->savepoint_offset= sizeof(my_off_t);
binlog_hton->close_connection= binlog_close_connection;
@ -1889,7 +1750,9 @@ binlog_commit_flush_stmt_cache(THD *thd, bool all,
#ifdef WITH_WSREP
if (thd->wsrep_mysql_replicated > 0)
{
WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d", thd->wsrep_mysql_replicated);
DBUG_ASSERT(WSREP_ON);
WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d",
thd->wsrep_mysql_replicated);
return 0;
}
#endif
@ -2077,7 +1940,11 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
#ifdef WITH_WSREP
if (!cache_mngr) DBUG_RETURN(0);
if (!cache_mngr)
{
DBUG_ASSERT(WSREP(thd));
DBUG_RETURN(0);
}
#endif /* WITH_WSREP */
DBUG_PRINT("debug",
@ -2136,7 +2003,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
#ifdef WITH_WSREP
if (!cache_mngr) DBUG_RETURN(0);
if (!cache_mngr)
{
DBUG_ASSERT(WSREP(thd));
DBUG_RETURN(0);
}
#endif /* WITH_WSREP */
DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s",
@ -2166,12 +2038,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
cache_mngr->reset(false, true);
DBUG_RETURN(error);
}
#ifdef WITH_WSREP
if (!wsrep_emulate_bin_log &&
if (IF_WSREP(!wsrep_emulate_bin_log,1) &&
mysql_bin_log.check_write_error(thd))
#else
if (mysql_bin_log.check_write_error(thd))
#endif
{
/*
"all == true" means that a "rollback statement" triggered the error and
@ -2309,13 +2177,15 @@ bool MYSQL_BIN_LOG::check_write_error(THD *thd)
static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv)
{
DBUG_ENTER("binlog_savepoint_set");
int error= 1;
DBUG_ENTER("binlog_savepoint_set");
char buf[1024];
#ifdef WITH_WSREP
if (wsrep_emulate_bin_log) DBUG_RETURN(0);
if (wsrep_emulate_bin_log)
DBUG_RETURN(0);
#endif /* WITH_WSREP */
char buf[1024];
String log_query(buf, sizeof(buf), &my_charset_bin);
if (log_query.copy(STRING_WITH_LEN("SAVEPOINT "), &my_charset_bin) ||
append_identifier(thd, &log_query,
@ -2352,14 +2222,9 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
non-transactional table. Otherwise, truncate the binlog cache starting
from the SAVEPOINT command.
*/
#ifdef WITH_WSREP
if (!wsrep_emulate_bin_log &&
if (IF_WSREP(!wsrep_emulate_bin_log, 1) &&
unlikely(trans_has_updated_non_trans_table(thd) ||
(thd->variables.option_bits & OPTION_KEEP_LOG)))
#else
if (unlikely(trans_has_updated_non_trans_table(thd) ||
(thd->variables.option_bits & OPTION_KEEP_LOG)))
#endif
{
char buf[1024];
String log_query(buf, sizeof(buf), &my_charset_bin);
@ -2373,10 +2238,8 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
DBUG_RETURN(mysql_bin_log.write(&qinfo));
}
#ifdef WITH_WSREP
if (!wsrep_emulate_bin_log)
#endif
binlog_trans_log_truncate(thd, *(my_off_t*)sv);
if (IF_WSREP(!wsrep_emulate_bin_log, 1))
binlog_trans_log_truncate(thd, *(my_off_t*)sv);
DBUG_RETURN(0);
}
@ -5505,12 +5368,8 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional,
is_transactional= 1;
/* Pre-conditions */
#ifdef WITH_WSREP
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open()));
#else
DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
#endif
DBUG_ASSERT(is_current_stmt_binlog_format_row());
DBUG_ASSERT(IF_WSREP(WSREP_EMULATE_BINLOG(this), 0) || mysql_bin_log.is_open());
DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
Table_map_log_event
@ -5643,11 +5502,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
bool is_transactional)
{
DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)");
#ifdef WITH_WSREP
DBUG_ASSERT(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open());
#else
DBUG_ASSERT(mysql_bin_log.is_open());
#endif
DBUG_ASSERT(IF_WSREP(WSREP_EMULATE_BINLOG(thd),0) || mysql_bin_log.is_open());
DBUG_PRINT("enter", ("event: 0x%lx", (long) event));
int error= 0;
@ -5973,13 +5828,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
mostly called if is_open() *was* true a few instructions before, but it
could have changed since.
*/
#ifdef WITH_WSREP
/* applier and replayer can skip writing binlog events */
if ((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) ||
is_open())
#else
if (likely(is_open()))
#endif
if (IF_WSREP((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)), 0) ||
likely(is_open()))
{
my_off_t UNINIT_VAR(my_org_b_tell);
#ifdef HAVE_REPLICATION
@ -6317,14 +6168,16 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge)
{
int error= 0;
DBUG_ENTER("MYSQL_BIN_LOG::rotate");
#ifdef WITH_WSREP
if (WSREP_ON && wsrep_to_isolation)
{
*check_purge= false;
WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d",
wsrep_to_isolation);
DBUG_RETURN(0);
}
if (wsrep_to_isolation)
{
DBUG_ASSERT(WSREP_ON);
*check_purge= false;
WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d",
wsrep_to_isolation);
DBUG_RETURN(0);
}
#endif
//todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log);
@ -6873,8 +6726,10 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd,
DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_to_binlog");
#ifdef WITH_WSREP
if (wsrep_emulate_bin_log) DBUG_RETURN(0);
if (wsrep_emulate_bin_log)
DBUG_RETURN(0);
#endif /* WITH_WSREP */
entry.thd= thd;
entry.cache_mngr= cache_mngr;
entry.error= 0;
@ -9020,14 +8875,10 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all,
binlog_cache_mngr *cache_mngr= thd->binlog_setup_trx_data();
if (!cache_mngr)
#ifdef WITH_WSREP
{
WSREP_DEBUG("Skipping empty log_xid: %s", thd->query());
DBUG_RETURN(0);
}
#else
DBUG_RETURN(0);
#endif /* WITH_WSREP */
cache_mngr->using_xa= TRUE;
cache_mngr->xa_xid= xid;
@ -9857,3 +9708,50 @@ maria_declare_plugin(binlog)
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
}
maria_declare_plugin_end;
#ifdef WITH_WSREP
IO_CACHE * get_trans_log(THD * thd)
{
binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*)
thd_get_ha_data(thd, binlog_hton);
if (cache_mngr)
return cache_mngr->get_binlog_cache_log(true);
WSREP_DEBUG("binlog cache not initialized, conn :%ld", thd->thread_id);
return NULL;
}
bool wsrep_trans_cache_is_empty(THD *thd)
{
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
return (!cache_mngr || cache_mngr->trx_cache.empty());
}
void thd_binlog_trx_reset(THD * thd)
{
/*
todo: fix autocommit select to not call the caller
*/
if (thd_get_ha_data(thd, binlog_hton) != NULL)
{
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
if (cache_mngr)
cache_mngr->reset(false, true);
}
thd->clear_binlog_table_maps();
}
void thd_binlog_rollback_stmt(THD * thd)
{
WSREP_DEBUG("thd_binlog_rollback_stmt :%ld", thd->thread_id);
binlog_cache_mngr *const cache_mngr=
(binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
if (cache_mngr)
cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF);
}
#endif /* WITH_WSREP */

27
sql/log.h

@ -19,6 +19,8 @@
#include "unireg.h" // REQUIRED: for other includes
#include "handler.h" /* my_xid */
#include "wsrep.h"
#include "wsrep_mysqld.h"
class Relay_log_info;
@ -106,10 +108,11 @@ public:
int log_and_order(THD *thd, my_xid xid, bool all,
bool need_prepare_ordered, bool need_commit_ordered)
{
#ifndef WITH_WSREP
DBUG_ASSERT(0 /* Internal error - TC_LOG_DUMMY::log_and_order() called
*/);
#endif
/*
If we are not using WSREP this is an Internal error
- TC_LOG_DUMMY::log_and_order() called
*/
DBUG_ASSERT(IF_WSREP(1,0));
return 1;
}
int unlog(ulong cookie, my_xid xid) { return 0; }
@ -984,22 +987,6 @@ enum enum_binlog_format {
BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed
};
#ifdef WITH_WSREP
IO_CACHE * get_trans_log(THD * thd);
bool wsrep_trans_cache_is_empty(THD *thd);
void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end);
void thd_binlog_trx_reset(THD * thd);
void thd_binlog_rollback_stmt(THD * thd);
#endif /* WITH_WSREP */
#if defined(WITH_WSREP) && !defined(EMBEDDED_LIBRARY)
#define WSREP_FORMAT(my_format) \
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
#else
#define WSREP_FORMAT(my_format) my_format
#endif /* WITH_WSREP && !EMBEDDED_LIBRARY */
int query_error_code(THD *thd, bool not_killed);
uint purge_log_get_error_code(int res);

165
sql/log_event.cc

@ -44,10 +44,7 @@
#include <mysql/psi/mysql_statement.h>
#include <strfunc.h>
#include "compat56.h"
#if WITH_WSREP
#include "wsrep_mysqld.h"
#endif
#endif /* MYSQL_CLIENT */
#include <base64.h>
@ -3094,14 +3091,16 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
master_data_written(0)
{
time_t end_time;
#ifdef WITH_WSREP
/*
If Query_log_event will contain non trans keyword (not BEGIN, COMMIT,
SAVEPOINT or ROLLBACK) we disable PA for this transaction.
*/
if (!is_trans_keyword())
if (WSREP_ON && !is_trans_keyword())
thd->wsrep_PA_safe= false;
#endif /* WITH_WSREP */
memset(&user, 0, sizeof(user));
memset(&host, 0, sizeof(host));
@ -4055,11 +4054,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
uint64 sub_id= 0;
rpl_gtid gtid;
Relay_log_info const *rli= rgi->rli;
#ifdef WITH_WSREP
Rpl_filter *rpl_filter= (rli->mi) ? rli->mi->rpl_filter: NULL;
#else
Rpl_filter *rpl_filter= rli->mi->rpl_filter;
#endif /* WITH_WSREP */
bool current_stmt_is_commit;
DBUG_ENTER("Query_log_event::do_apply_event");
@ -4534,8 +4529,9 @@ Query_log_event::do_shall_skip(rpl_group_info *rgi)
}
}
#ifdef WITH_WSREP
else if (wsrep_mysql_replication_bundle && WSREP_ON && thd->wsrep_mysql_replicated > 0 &&
(!strncasecmp(query , "BEGIN", 5) || !strncasecmp(query , "COMMIT", 6)))
else if (WSREP_ON && wsrep_mysql_replication_bundle && opt_slave_domain_parallel_threads == 0 &&
thd->wsrep_mysql_replicated > 0 &&
(is_begin() || is_commit()))
{
if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle)
{
@ -7378,7 +7374,8 @@ Xid_log_event::do_shall_skip(rpl_group_info *rgi)
DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
}
#ifdef WITH_WSREP
else if (wsrep_mysql_replication_bundle && WSREP_ON)
else if (wsrep_mysql_replication_bundle && WSREP_ON &&
opt_slave_domain_parallel_threads == 0)
{
if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle)
{
@ -8413,14 +8410,6 @@ err:
end_io_cache(&file);
if (fd >= 0)
mysql_file_close(fd, MYF(0));
#ifdef WITH_WSREP
if (WSREP(thd))
thd_proc_info(thd, "exit Create_file_log_event::do_apply_event()");
else
thd_proc_info(thd, 0);
#else /* WITH_WSREP */
thd_proc_info(thd, 0);
#endif /* WITH_WSREP */
return error != 0;
}
#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
@ -8592,14 +8581,6 @@ int Append_block_log_event::do_apply_event(rpl_group_info *rgi)
err:
if (fd >= 0)
mysql_file_close(fd, MYF(0));
#ifdef WITH_WSREP
if (WSREP(thd))
thd_proc_info(thd, "exit Append_block_log_event::do_apply_event()");
else
thd_proc_info(thd, 0);
#else /* WITH_WSREP */
thd_proc_info(thd, 0);
#endif /* WITH_WSREP */
DBUG_RETURN(error);
}
#endif
@ -9694,7 +9675,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
thd->wsrep_exec_mode,
thd->wsrep_conflict_state,
(long long)wsrep_thd_trx_seqno(thd));
}
}
#endif
if (thd->is_slave_error || thd->is_fatal_error)
{
@ -10842,13 +10823,8 @@ check_table_map(rpl_group_info *rgi, RPL_TABLE_LIST *table_list)
DBUG_ENTER("check_table_map");
enum_tbl_map_status res= OK_TO_PROCESS;
Relay_log_info *rli= rgi->rli;
#ifdef WITH_WSREP
if ((rgi->thd->slave_thread /* filtering is for slave only */ ||
(WSREP(rgi->thd) && rgi->thd->wsrep_applier)) &&
#else
if (rgi->thd->slave_thread /* filtering is for slave only */ &&
#endif /* WITH_WSREP */
if ((rgi->thd->slave_thread /* filtering is for slave only */ ||
IF_WSREP((WSREP(rgi->thd) && rgi->thd->wsrep_applier), 0)) &&
(!rli->mi->rpl_filter->db_ok(table_list->db) ||
(rli->mi->rpl_filter->is_on() && !rli->mi->rpl_filter->tables_ok("", table_list))))
res= FILTERED_OUT;
@ -11596,23 +11572,20 @@ int
Write_rows_log_event::do_exec_row(rpl_group_info *rgi)
{
DBUG_ASSERT(m_table != NULL);
#ifdef WITH_WSREP
const char *tmp= thd->get_proc_info();
const char *message= "Write_rows_log_event::write_row()";
#ifdef WSREP_PROC_INFO
char info[64];
info[sizeof(info) - 1] = '\0';
snprintf(info, sizeof(info) - 1, "Write_rows_log_event::write_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL;
#else
const char* tmp = (WSREP(thd)) ?
thd_proc_info(thd,"Write_rows_log_event::write_row()") : NULL;
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
"Write_rows_log_event::write_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
thd_proc_info(thd, message);
int error= write_row(rgi, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
thd_proc_info(thd, tmp);
#ifdef WITH_WSREP
if (WSREP(thd)) thd_proc_info(thd, tmp);
#endif /* WITH_WSREP */
if (error && !thd->is_error())
{
DBUG_ASSERT(0);
@ -12289,37 +12262,34 @@ Delete_rows_log_event::do_after_row_operations(const Slave_reporting_capability
int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi)
{
int error;
const char *tmp= thd->get_proc_info();
const char *message= "Delete_rows_log_event::find_row()";
const bool invoke_triggers=
slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers;
DBUG_ASSERT(m_table != NULL);
#ifdef WITH_WSREP
#ifdef WSREP_PROC_INFO
char info[64];
info[sizeof(info) - 1] = '\0';
snprintf(info, sizeof(info) - 1, "Delete_rows_log_event::find_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL;
#else
const char* tmp = (WSREP(thd)) ?
thd_proc_info(thd,"Delete_rows_log_event::find_row()") : NULL;
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
"Delete_rows_log_event::find_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
thd_proc_info(thd, message);
if (!(error= find_row(rgi)))
{
/*
Delete the record found, located in record[0]
*/
#ifdef WITH_WSREP
message= "Delete_rows_log_event::ha_delete_row()";
#ifdef WSREP_PROC_INFO
snprintf(info, sizeof(info) - 1,
snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
"Delete_rows_log_event::ha_delete_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
if (WSREP(thd)) thd_proc_info(thd, info);
#else
if (WSREP(thd)) thd_proc_info(thd,"Delete_rows_log_event::ha_delete_row()");
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
message= thd->wsrep_info;
#endif
thd_proc_info(thd, message);
if (invoke_triggers &&
process_triggers(TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE))
error= HA_ERR_GENERIC; // in case if error is not set yet
@ -12330,9 +12300,7 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi)
error= HA_ERR_GENERIC; // in case if error is not set yet
m_table->file->ha_index_or_rnd_end();
}
#ifdef WITH_WSREP
if (WSREP(thd)) thd_proc_info(thd, tmp);
#endif /* WITH_WSREP */
thd_proc_info(thd, tmp);
return error;
}
@ -12460,20 +12428,18 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
{
const bool invoke_triggers=
slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers;
const char *tmp= thd->get_proc_info();
const char *message= "Update_rows_log_event::find_row()";
DBUG_ASSERT(m_table != NULL);
#ifdef WITH_WSREP
#ifdef WSREP_PROC_INFO
char info[64];
info[sizeof(info) - 1] = '\0';
snprintf(info, sizeof(info) - 1, "Update_rows_log_event::find_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL;
#else
const char* tmp = (WSREP(thd)) ?
thd_proc_info(thd,"Update_rows_log_event::find_row()") : NULL;
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
"Update_rows_log_event::find_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
thd_proc_info(thd, message);
int error= find_row(rgi);
if (error)
{
@ -12483,6 +12449,7 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
*/
m_curr_row= m_curr_row_end;
unpack_current_row(rgi);
thd_proc_info(thd, tmp);
return error;
}
@ -12500,18 +12467,16 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
store_record(m_table,record[1]);
m_curr_row= m_curr_row_end;
#ifdef WITH_WSREP
message= "Update_rows_log_event::unpack_current_row()";
#ifdef WSREP_PROC_INFO
snprintf(info, sizeof(info) - 1,
"Update_rows_log_event::unpack_current_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
if (WSREP(thd)) thd_proc_info(thd, info);
#else
if (WSREP(thd))
thd_proc_info(thd,"Update_rows_log_event::unpack_current_row()");
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
"Update_rows_log_event::unpack_current_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
/* this also updates m_curr_row_end */
thd_proc_info(thd, message);
if ((error= unpack_current_row(rgi)))
goto err;
@ -12529,17 +12494,15 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
#endif
#ifdef WITH_WSREP
message= "Update_rows_log_event::ha_update_row()";
#ifdef WSREP_PROC_INFO
snprintf(info, sizeof(info) - 1,
"Update_rows_log_event::ha_update_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
if (WSREP(thd)) thd_proc_info(thd, info);
#else
if (WSREP(thd)) thd_proc_info(thd,"Update_rows_log_event::ha_update_row()");
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
"Update_rows_log_event::ha_update_row(%lld)",
(long long) wsrep_thd_trx_seqno(thd));
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
thd_proc_info(thd, message);
if (invoke_triggers &&
process_triggers(TRG_EVENT_UPDATE, TRG_ACTION_BEFORE, TRUE))
{
@ -12555,9 +12518,8 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
process_triggers(TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))
error= HA_ERR_GENERIC; // in case if error is not set yet
#ifdef WITH_WSREP
if (WSREP(thd)) thd_proc_info(thd, tmp);
#endif /* WITH_WSREP */
thd_proc_info(thd, tmp);
err:
m_table->file->ha_index_or_rnd_end();
return error;
@ -12647,7 +12609,9 @@ void Incident_log_event::pack_info(THD *thd, Protocol *protocol)
m_incident, description(), m_message.str);
protocol->store(buf, bytes, &my_charset_bin);
}
#endif
#endif /* MYSQL_CLIENT */
#if WITH_WSREP && !defined(MYSQL_CLIENT)
Format_description_log_event *wsrep_format_desc; // TODO: free them at the end
/*
@ -12661,13 +12625,12 @@ Log_event* wsrep_read_log_event(
char **arg_buf, size_t *arg_buf_len,
const Format_description_log_event *description_event)
{
DBUG_ENTER("wsrep_read_log_event");
char *head= (*arg_buf);
uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
char *buf= (*arg_buf);
const char *error= 0;
Log_event *res= 0;
DBUG_ENTER("wsrep_read_log_event");
if (data_len > WSREP_MAX_ALLOWED_PACKET)
{

7
sql/log_event.h

@ -1340,7 +1340,12 @@ public:
*/
int apply_event(rpl_group_info *rgi)
{
return do_apply_event(rgi);
int res;
THD_STAGE_INFO(thd, stage_apply_event);
res= do_apply_event(rgi);
THD_STAGE_INFO(thd, stage_after_apply_event);
res= 0;
return res;
}

95
sql/mdl.cc

@ -22,19 +22,9 @@
#include <mysql/plugin.h>
#include <mysql/service_thd_wait.h>
#include <mysql/psi/mysql_stage.h>
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
extern "C" my_thread_id wsrep_thd_thread_id(THD *thd);
extern "C" char *wsrep_thd_query(THD *thd);
void sql_print_information(const char *format, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
MDL_ticket *ticket);
#endif /* WITH_WSREP */
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_MDL_map_mutex;
static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
@ -1511,22 +1501,23 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
DBUG_ASSERT(ticket->get_lock());
#ifdef WITH_WSREP
if ((this == &(ticket->get_lock()->m_waiting)) &&
wsrep_thd_is_BF((void *)(ticket->get_ctx()->wsrep_get_thd()), false))
wsrep_thd_is_BF((void *)(ticket->get_ctx()->get_thd()), false))
{
Ticket_iterator itw(ticket->get_lock()->m_waiting);
Ticket_iterator itg(ticket->get_lock()->m_granted);
DBUG_ASSERT(WSREP_ON);
MDL_ticket *waiting, *granted;
MDL_ticket *prev=NULL;
bool added= false;
while ((waiting= itw++) && !added)
{
if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->wsrep_get_thd()), true))
if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->get_thd()), true))
{
WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
wsrep_thd_thread_id(waiting->get_ctx()->wsrep_get_thd()),
wsrep_thd_query(waiting->get_ctx()->wsrep_get_thd()));
wsrep_thd_thread_id(waiting->get_ctx()->get_thd()),
wsrep_thd_query(waiting->get_ctx()->get_thd()));
m_list.insert_after(prev, ticket);
added= true;
}
@ -1547,16 +1538,14 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
}
}
else
{
#endif /* WITH_WSREP */
/*
Add ticket to the *back* of the queue to ensure fairness
among requests with the same priority.
*/
m_list.push_back(ticket);
#ifdef WITH_WSREP
{
/*
Add ticket to the *back* of the queue to ensure fairness
among requests with the same priority.
*/
m_list.push_back(ticket);
}
#endif /* WITH_WSREP */
m_bitmap|= MDL_BIT(ticket->get_type());
}
@ -1897,9 +1886,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
bool can_grant= FALSE;
bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
#ifdef WITH_WSREP
bool wsrep_can_grant= TRUE;
#endif /* WITH_WSREP */
/*
New lock request can be satisfied iff:
@ -1922,55 +1909,49 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
{
if (ticket->get_ctx() != requestor_ctx &&
ticket->is_incompatible_when_granted(type_arg))
#ifdef WITH_WSREP
{
if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()),false) &&
if (IF_WSREP(!WSREP_ON, 0))
break;
#ifdef WITH_WSREP
if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()),false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF: %lu %s",
wsrep_thd_thread_id(requestor_ctx->wsrep_get_thd()),
wsrep_thd_query(requestor_ctx->wsrep_get_thd()));
wsrep_thd_thread_id(requestor_ctx->get_thd()),
wsrep_thd_query(requestor_ctx->get_thd()));
can_grant = true;
}
else if (!wsrep_grant_mdl_exception(requestor_ctx, ticket))
{
wsrep_can_grant= FALSE;
if (wsrep_log_conflicts)
{
MDL_lock * lock = ticket->get_lock();
WSREP_INFO(
"MDL conflict db=%s table=%s ticket=%d solved by %s",
lock->key.db_name(), lock->key.name(), ticket->get_type(), "abort"
);
if (wsrep_log_conflicts)
{
MDL_lock * lock = ticket->get_lock();
WSREP_INFO(
"MDL conflict db=%s table=%s ticket=%d solved by %s",
lock->key.db_name(), lock->key.name(), ticket->get_type(),
"abort" );
}
}
else
{
can_grant= TRUE;
}
/* Continue loop */
}
#else
break;
#endif /* WITH_WSREP */
}
#ifdef WITH_WSREP
if ((ticket == NULL) && wsrep_can_grant)
#else
if (ticket == NULL) /* Incompatible locks are our own. */
#endif /* WITH_WSREP */
if ((ticket == NULL) && IF_WSREP(wsrep_can_grant, 1))
can_grant= TRUE;
}
}
#ifdef WITH_WSREP
else
{
if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()), false) &&
if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s",
wsrep_thd_thread_id(requestor_ctx->wsrep_get_thd()),
wsrep_thd_query(requestor_ctx->wsrep_get_thd()));
wsrep_thd_thread_id(requestor_ctx->get_thd()),
wsrep_thd_query(requestor_ctx->get_thd()));
can_grant = true;
}
}
@ -3019,12 +3000,7 @@ void MDL_context::release_locks_stored_before(enum_mdl_duration duration,
DBUG_VOID_RETURN;
}
#ifdef WITH_WSREP
void MDL_context::release_explicit_locks()
{
release_locks_stored_before(MDL_EXPLICIT, NULL);
}
#endif
/**
Release all explicit locks in the context which correspond to the
same name/object as this lock request.
@ -3332,7 +3308,16 @@ void MDL_context::set_transaction_duration_for_all_locks()
ticket->m_duration= MDL_TRANSACTION;
#endif
}
#ifdef WITH_WSREP
void MDL_context::release_explicit_locks()
{
release_locks_stored_before(MDL_EXPLICIT, NULL);
}
void MDL_ticket::wsrep_report(bool debug)
{
if (debug)

8
sql/mdl.h

@ -776,13 +776,10 @@ public:
m_tickets[MDL_TRANSACTION].is_empty() &&
m_tickets[MDL_EXPLICIT].is_empty());
}
#ifdef WITH_WSREP
inline bool has_transactional_locks() const
{
return !m_tickets[MDL_TRANSACTION].is_empty();
}
#endif /* WITH_WSREP */
MDL_savepoint mdl_savepoint()
{
@ -923,7 +920,6 @@ private:
*/
MDL_wait_for_subgraph *m_waiting_for;
private:
THD *get_thd() const { return m_owner->get_thd(); }
MDL_ticket *find_ticket(MDL_request *mdl_req,
enum_mdl_duration *duration);
void release_locks_stored_before(enum_mdl_duration duration, MDL_ticket *sentinel);
@ -932,9 +928,7 @@ private:
MDL_ticket **out_ticket);
public:
#ifdef WITH_WSREP
THD *wsrep_get_thd() const { return get_thd(); }
#endif
THD *get_thd() const { return m_owner->get_thd(); }
void find_deadlock();
ulong get_thread_id() const { return thd_get_thread_id(get_thd()); }

641
sql/mysqld.cc

@ -71,13 +71,11 @@
#include "scheduler.h"
#include <waiting_threads.h>
#include "debug_sync.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_var.h"
#include "wsrep_thd.h"
#include "wsrep_sst.h"
ulong wsrep_running_threads = 0; // # of currently running wsrep threads
#endif
#include "sql_callback.h"
#include "threadpool.h"
@ -359,7 +357,8 @@ static bool volatile select_thread_in_use, signal_thread_in_use;
static volatile bool ready_to_exit;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
static uint kill_cached_threads, wake_thread;
uint kill_cached_threads;
static uint wake_thread;
ulong max_used_connections;
static volatile ulong cached_thread_count= 0;
static char *mysqld_user, *mysqld_chroot;
@ -367,25 +366,19 @@ static char *default_character_set_name;
static char *character_set_filesystem_name;
static char *lc_messages;
static char *lc_time_names_name;
#ifndef WITH_WSREP
static char *my_bind_addr_str;
#else
char *my_bind_addr_str;
#endif /* WITH_WSREP */
static char *default_collation_name;
char *default_storage_engine, *default_tmp_storage_engine;
static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
static I_List<THD> thread_cache;
static bool binlog_format_used= false;
LEX_STRING opt_init_connect, opt_init_slave;
static mysql_cond_t COND_thread_cache, COND_flush_thread_cache;
mysql_cond_t COND_thread_cache;
static mysql_cond_t COND_flush_thread_cache;
static DYNAMIC_ARRAY all_options;
/* Global variables */
#ifdef WITH_WSREP
ulong my_bind_addr;
#endif /* WITH_WSREP */
bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0;
my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0;
static my_bool opt_abort;
@ -479,10 +472,6 @@ ulong opt_binlog_rows_event_max_size;
my_bool opt_master_verify_checksum= 0;
my_bool opt_slave_sql_verify_checksum= 1;
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
#ifdef WITH_WSREP
const char *wsrep_binlog_format_names[]=
{"MIXED", "STATEMENT", "ROW", "NONE", NullS};
#endif /*WITH_WSREP */
#ifdef HAVE_INITGROUPS
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
#endif
@ -748,6 +737,7 @@ mysql_cond_t COND_server_started;
int mysqld_server_started=0, mysqld_server_initialized= 0;
File_parser_dummy_hook file_parser_dummy_hook;
#ifdef WITH_WSREP
mysql_mutex_t LOCK_wsrep_ready;
mysql_cond_t COND_wsrep_ready;
@ -763,7 +753,10 @@ mysql_cond_t COND_wsrep_replaying;
mysql_mutex_t LOCK_wsrep_slave_threads;
mysql_mutex_t LOCK_wsrep_desync;
int wsrep_replaying= 0;
static void wsrep_close_threads(THD* thd);
ulong wsrep_running_threads = 0; // # of currently running wsrep threads
ulong my_bind_addr;
const char *wsrep_binlog_format_names[]=
{"MIXED", "STATEMENT", "ROW", "NONE", NullS};
#endif /* WITH_WSREP */
/* replication parameters, if master_host is not NULL, we are a slave */
@ -1465,7 +1458,7 @@ bool mysqld_embedded=0;
bool mysqld_embedded=1;
#endif
static my_bool plugins_are_initialized= FALSE;
my_bool plugins_are_initialized= FALSE;
#ifndef DBUG_OFF
static const char* default_dbug_option;
@ -1772,7 +1765,8 @@ static void close_connections(void)
#endif
#ifdef WITH_WSREP
/*
* TODO: this code block may turn out redundant. wsrep->disconnect()
* WSREP_TODO:
* this code block may turn out redundant. wsrep->disconnect()
* should terminate slave threads gracefully, and we don't need
* to signal them here.
* The code here makes sure mysqld will not hang during shutdown
@ -1950,15 +1944,19 @@ static void __cdecl kill_server(int sig_ptr)
}
}
#endif
#ifdef WITH_WSREP
if (WSREP_ON) wsrep_stop_replication(NULL);
if (WSREP_ON)
wsrep_stop_replication(NULL);
#endif
close_connections();
#ifdef WITH_WSREP
if (wsrep_inited == 1)
if (WSREP_ON && wsrep_inited == 1)
wsrep_deinit(true);
#endif
if (sig != MYSQL_KILL_SIGNAL &&
sig != 0)
unireg_abort(1); /* purecov: inspected */
@ -2053,14 +2051,18 @@ extern "C" void unireg_abort(int exit_code)
usage();
if (exit_code)
sql_print_error("Aborting\n");
#ifdef WITH_WSREP
/* Check if wsrep class is used. If yes, then cleanup wsrep */
if (wsrep)
{
/* This is an abort situation, we cannot expect to gracefully close all
* wsrep threads here, we can only diconnect from service */
/*
This is an abort situation, we cannot expect to gracefully close all
wsrep threads here, we can only diconnect from service
*/
wsrep_close_client_connections(FALSE);
shutdown_in_progress= 1;
THD* thd(0);
THD *thd(0);
wsrep->disconnect(wsrep);
WSREP_INFO("Service disconnected.");
wsrep_close_threads(thd); /* this won't close all threads */
@ -2072,6 +2074,7 @@ extern "C" void unireg_abort(int exit_code)
wsrep_deinit(true);
}
#endif // WITH_WSREP
clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
mysqld_exit(exit_code);
@ -2621,6 +2624,7 @@ static MYSQL_SOCKET activate_tcp_port(uint port)
unireg_abort(1);
}
#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
if (WSREP_ON)
(void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC);
#endif /* WITH_WSREP */
@ -2751,7 +2755,8 @@ static void network_init(void)
sql_print_warning("listen() on Unix socket failed with error %d",
socket_errno);
#if defined(WITH_WSREP) && defined(HAVE_FCNTL)
(void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC);
if (WSREP_ON)
(void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC);
#endif /* WITH_WSREP */
}
#endif
@ -2833,15 +2838,16 @@ void dec_connection_count(THD *thd)
applier as well as rollbacker threads.
*/
if (!thd->wsrep_applier)
return;
#endif /* WITH_WSREP */
{
DBUG_ASSERT(*thd->scheduler->connection_count > 0);
mysql_mutex_lock(&LOCK_connection_count);
(*thd->scheduler->connection_count)--;
mysql_mutex_unlock(&LOCK_connection_count);
}
DBUG_ASSERT(*thd->scheduler->connection_count > 0);
mysql_mutex_lock(&LOCK_connection_count);
(*thd->scheduler->connection_count)--;
mysql_mutex_unlock(&LOCK_connection_count);
}
/*
Delete THD and decrement thread counters, including thread_running
*/
@ -3014,11 +3020,7 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
/* Mark that current_thd is not valid anymore */
set_current_thd(0);
#ifdef WITH_WSREP
if (put_in_cache && cache_thread() && !wsrep_applier)
#else
if (put_in_cache && cache_thread())
#endif /* WITH_WSREP */
if (put_in_cache && cache_thread() && IF_WSREP(!wsrep_applier, 1))
DBUG_RETURN(0); // Thread is reused
/*
@ -4139,6 +4141,7 @@ static int init_common_variables()
}
else
opt_log_basename= glob_hostname;
#ifdef WITH_WSREP
if (0 == wsrep_node_name || 0 == wsrep_node_name[0])
{
@ -4146,6 +4149,7 @@ static int init_common_variables()
wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME));
}
#endif /* WITH_WSREP */
if (!*pidfile_name)
{
strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5);
@ -4205,11 +4209,16 @@ static int init_common_variables()
compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
SQLCOM_END + 8);
#endif
#ifdef WITH_WSREP
/* This is a protection against mutually incompatible option values. */
/*
This is a protection against mutually incompatible option values.
Note WSREP_ON == global_system_variables.wsrep_on
*/
if (WSREP_ON && wsrep_check_opts (remaining_argc, remaining_argv))
global_system_variables.wsrep_on= 0;
#endif /* WITH_WSREP */
if (get_options(&remaining_argc, &remaining_argv))
return 1;
set_server_version();
@ -4923,18 +4932,10 @@ static int init_server_components()
/* need to configure logging before initializing storage engines */
if (!opt_bin_log_used)
{
#ifdef WITH_WSREP
if (!WSREP_ON && opt_log_slave_updates)
#else
if (opt_log_slave_updates)
#endif
if (IF_WSREP(!WSREP_ON,1) && opt_log_slave_updates)
sql_print_warning("You need to use --log-bin to make "
"--log-slave-updates work.");
#ifdef WITH_WSREP
if (!WSREP_ON && binlog_format_used)
#else
if (binlog_format_used)
#endif
if (IF_WSREP(!WSREP_ON, 1) && binlog_format_used)
sql_print_warning("You need to use --log-bin to make "
"--binlog-format work.");
}
@ -5018,7 +5019,7 @@ a file name for --log-bin-index option", opt_binlog_index_name);
after SST has happened
*/
}
if (!wsrep_recovery)
if (WSREP_ON && !wsrep_recovery)
{
if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
{
@ -5192,23 +5193,34 @@ a file name for --log-bin-index option", opt_binlog_index_name);
#endif
#ifdef WITH_WSREP
if (!opt_bin_log)
if (WSREP_ON && !opt_bin_log)
{
wsrep_emulate_bin_log= 1;
}
#endif
/* if total_ha_2pc <= 1
tc_log = tc_log_dummy
else
if opt_bin_log == true
tc_log = mysql_bin_log
else
if WITH_WSREP
if WSREP_ON
tc_log = tc_log_dummy
else
tc_log = tc_log_mmap
else
tc_log=tc_log_mmap
*/
tc_log= (total_ha_2pc > 1 ? (opt_bin_log ?
(TC_LOG *) &mysql_bin_log :
IF_WSREP((WSREP_ON ? (TC_LOG *) &tc_log_dummy :
(TC_LOG *) &tc_log_mmap), (TC_LOG *) &tc_log_mmap)) :
(TC_LOG *) &tc_log_dummy);
#ifdef WITH_WSREP
(WSREP_ON ?
(TC_LOG *) &tc_log_dummy :
(TC_LOG *) &tc_log_mmap)) :
#else
(TC_LOG *) &tc_log_mmap) :
#endif
(TC_LOG *) &tc_log_dummy);
#ifdef WITH_WSREP
WSREP_DEBUG("Initial TC log open: %s",
WSREP_DEBUG("Initial TC log open: %s",
(tc_log == &mysql_bin_log) ? "binlog" :
(tc_log == &tc_log_mmap) ? "mmap" :
(tc_log == &tc_log_dummy) ? "dummy" : "unknown"
@ -5296,468 +5308,6 @@ static void create_shutdown_thread()
#endif /* EMBEDDED_LIBRARY */
#ifdef WITH_WSREP
typedef void (*wsrep_thd_processor_fun)(THD *);
pthread_handler_t start_wsrep_THD(void *arg)
{
THD *thd;
rpl_sql_thread_info sql_info(NULL);
wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
if (my_thread_init())
{
WSREP_ERROR("Could not initialize thread");
return(NULL);
}
if (!(thd= new THD(true)))
{
return(NULL);
}
mysql_mutex_lock(&LOCK_thread_count);
thd->thread_id=thread_id++;
thd->real_id=pthread_self(); // Keep purify happy
thread_count++;
thread_created++;
threads.append(thd);
my_net_init(&thd->net,(st_vio*) 0, MYF(0));
DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id));
thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
(void) mysql_mutex_unlock(&LOCK_thread_count);
/* from bootstrap()... */
thd->bootstrap=1;
thd->max_client_packet_length= thd->net.max_packet;
thd->security_ctx->master_access= ~(ulong)0;
thd->system_thread_info.rpl_sql_info= &sql_info;
/* from handle_one_connection... */
pthread_detach_this_thread();
mysql_thread_set_psi_id(thd->thread_id);
thd->thr_create_utime= microsecond_interval_timer();
if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
{
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
return(NULL);
}
// </5.1.17>
/*
handle_one_connection() is normally the only way a thread would
start and would always be on the very high end of the stack ,
therefore, the thread stack always starts at the address of the
first local variable of handle_one_connection, which is thd. We
need to know the start of the stack so that we could check for
stack overruns.
*/
DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n",
(long long)thd->thread_id));
/* now that we've called my_thread_init(), it is safe to call DBUG_* */
thd->thread_stack= (char*) &thd;
if (thd->store_globals())
{
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
delete thd;
return(NULL);
}
thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
thd->security_ctx->skip_grants();
/* handle_one_connection() again... */
//thd->version= refresh_version;
thd->proc_info= 0;
thd->set_command(COM_SLEEP);
thd->set_time();
thd->init_for_queries();
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads++;
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
processor(thd);
close_connection(thd, 0);
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads--;
WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
// Note: We can't call THD destructor without crashing
// if plugins have not been initialized. However, in most of the
// cases this means that pre SE initialization SST failed and
// we are going to exit anyway.
if (plugins_are_initialized)
{
net_end(&thd->net);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1));
}
else
{
// TODO: lightweight cleanup to get rid of:
// 'Error in my_thread_global_end(): 2 threads didn't exit'
// at server shutdown
}
my_thread_end();
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_lock(&LOCK_thread_count);
delete thd;
thread_count--;
mysql_mutex_unlock(&LOCK_thread_count);
}
return(NULL);
}
/**/
static bool abort_replicated(THD *thd)
{
bool ret_code= false;
if (thd->wsrep_query_state== QUERY_COMMITTING)
{
if (wsrep_debug) WSREP_INFO("aborting replicated trx: %lu", thd->real_id);
(void)wsrep_abort_thd(thd, thd, TRUE);
ret_code= true;
}
return ret_code;
}
/**/
static inline bool is_client_connection(THD *thd)
{
#if REMOVE
// REMOVE THIS LATER (lp:777201). Below we had to add an explicit check for
// wsrep_applier since wsrep_exec_mode didn't seem to always work
if (thd->wsrep_applier && thd->wsrep_exec_mode != REPL_RECV)
WSREP_WARN("applier has wsrep_exec_mode = %d", thd->wsrep_exec_mode);
if ( thd->slave_thread || /* declared as mysql slave */
thd->system_thread || /* declared as system thread */
!thd->vio_ok() || /* server internal thread */
thd->wsrep_exec_mode==REPL_RECV || /* applier or replaying thread */
thd->wsrep_applier || /* wsrep slave applier */
!thd->variables.wsrep_on) /* client, but fenced outside wsrep */
return false;
return true;
#else
return (thd->wsrep_client_thread && thd->variables.wsrep_on);
#endif /* REMOVE */
}
static inline bool is_replaying_connection(THD *thd)
{
bool ret;
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false;
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
return ret;
}
static inline bool is_committing_connection(THD *thd)
{
bool ret;
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false;
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
return ret;
}
static bool have_client_connections()
{
THD *tmp;
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION)
{
(void)abort_replicated(tmp);
return true;
}
}
return false;
}
/*
returns the number of wsrep appliers running.
However, the caller (thd parameter) is not taken in account
*/
static int have_wsrep_appliers(THD *thd)
{
int ret= 0;
THD *tmp;
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
ret+= (tmp != thd && tmp->wsrep_applier);
}
return ret;
}
static void wsrep_close_thread(THD *thd)
{
thd->killed= KILL_CONNECTION;
MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd));
if (thd->mysys_var)
{
thd->mysys_var->abort=1;
mysql_mutex_lock(&thd->mysys_var->mutex);
if (thd->mysys_var->current_cond)
{
mysql_mutex_lock(thd->mysys_var->current_mutex);
mysql_cond_broadcast(thd->mysys_var->current_cond);
mysql_mutex_unlock(thd->mysys_var->current_mutex);
}
mysql_mutex_unlock(&thd->mysys_var->mutex);
}
}
static my_bool have_committing_connections()
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
if (!is_client_connection(tmp))
continue;
if (is_committing_connection(tmp))
{
mysql_mutex_unlock(&LOCK_thread_count);
return TRUE;
}
}
mysql_mutex_unlock(&LOCK_thread_count);
return FALSE;
}
int wsrep_wait_committing_connections_close(int wait_time)
{
int sleep_time= 100;
while (have_committing_connections() && wait_time > 0)
{
WSREP_DEBUG("wait for committing transaction to close: %d", wait_time);
my_sleep(sleep_time);
wait_time -= sleep_time;
}
if (have_committing_connections())
{
return 1;
}
return 0;
}
void wsrep_close_client_connections(my_bool wait_to_end)
{
/*
First signal all threads that it's time to die
*/
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
bool kill_cached_threads_saved= kill_cached_threads;
kill_cached_threads= true; // prevent future threads caching
mysql_cond_broadcast(&COND_thread_cache); // tell cached threads to die
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (!is_client_connection(tmp))
continue;
if (is_replaying_connection(tmp))
{
tmp->killed= KILL_CONNECTION;
continue;
}
/* replicated transactions must be skipped */
if (abort_replicated(tmp))
continue;
WSREP_DEBUG("closing connection %ld", tmp->thread_id);
wsrep_close_thread(tmp);
}
mysql_mutex_unlock(&LOCK_thread_count);
if (thread_count)
sleep(2); // Give threads time to die
mysql_mutex_lock(&LOCK_thread_count);
/*
Force remaining threads to die by closing the connection to the client
*/
I_List_iterator<THD> it2(threads);
while ((tmp=it2++))
{
#ifndef __bsdi__ // Bug in BSDI kernel
if (is_client_connection(tmp) &&
!abort_replicated(tmp) &&
!is_replaying_connection(tmp))
{
WSREP_INFO("killing local connection: %ld",tmp->thread_id);
close_connection(tmp,0);
}
#endif
}
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
if (wsrep_debug)
WSREP_INFO("waiting for client connections to close: %u", thread_count);
while (wait_to_end && have_client_connections())
{
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
DBUG_PRINT("quit",("One thread died (count=%u)", thread_count));
}
kill_cached_threads= kill_cached_threads_saved;
mysql_mutex_unlock(&LOCK_thread_count);
/* All client connection threads have now been aborted */
}
void wsrep_close_applier(THD *thd)
{
WSREP_DEBUG("closing applier %ld", thd->thread_id);
wsrep_close_thread(thd);
}
static void wsrep_close_threads(THD *thd)
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (tmp->wsrep_applier && tmp != thd)
{
WSREP_DEBUG("closing wsrep thread %ld", tmp->thread_id);
wsrep_close_thread (tmp);
}
}
mysql_mutex_unlock(&LOCK_thread_count);
}
void wsrep_close_applier_threads(int count)
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++) && count)
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (tmp->wsrep_applier)
{
WSREP_DEBUG("closing wsrep applier thread %ld", tmp->thread_id);
tmp->wsrep_applier_closing= TRUE;
count--;
}
}
mysql_mutex_unlock(&LOCK_thread_count);
}
void wsrep_wait_appliers_close(THD *thd)
{
/* Wait for wsrep appliers to gracefully exit */
mysql_mutex_lock(&LOCK_thread_count);
while (have_wsrep_appliers(thd) > 1)
// 1 is for rollbacker thread which needs to be killed explicitly.
// This gotta be fixed in a more elegant manner if we gonna have arbitrary
// number of non-applier wsrep threads.
{
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_unlock(&LOCK_thread_count);
my_sleep(100);
mysql_mutex_lock(&LOCK_thread_count);
}
else
mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
DBUG_PRINT("quit",("One applier died (count=%u)",thread_count));
}
mysql_mutex_unlock(&LOCK_thread_count);
/* Now kill remaining wsrep threads: rollbacker */
wsrep_close_threads (thd);
/* and wait for them to die */
mysql_mutex_lock(&LOCK_thread_count);
while (have_wsrep_appliers(thd) > 0)
{
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_unlock(&LOCK_thread_count);
my_sleep(100);
mysql_mutex_lock(&LOCK_thread_count);
}
else
mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
}
mysql_mutex_unlock(&LOCK_thread_count);
/* All wsrep applier threads have now been aborted. However, if this thread
is also applier, we are still running...
*/
}
void wsrep_kill_mysql(THD *thd)
{
if (mysqld_server_started)
{
if (!shutdown_in_progress)
{
WSREP_INFO("starting shutdown");
kill_mysql();
}
}
else
{
unireg_abort(1);
}
}
#endif /* WITH_WSREP */
#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
static void handle_connections_methods()
@ -5935,7 +5485,8 @@ int mysqld_main(int argc, char **argv)
}
#endif
#ifdef WITH_WSREP
wsrep_filter_new_cluster (&argc, argv);
if (WSREP_ON)
wsrep_filter_new_cluster (&argc, argv);
#endif /* WITH_WSREP */
orig_argc= argc;
@ -6154,7 +5705,7 @@ int mysqld_main(int argc, char **argv)
#endif
#ifdef WITH_WSREP /* WSREP AFTER SE */
if (wsrep_recovery)
if (WSREP_ON && wsrep_recovery)
{
select_thread_in_use= 0;
wsrep_recover();
@ -6219,28 +5770,31 @@ int mysqld_main(int argc, char **argv)
unireg_abort(1);
#ifdef WITH_WSREP /* WSREP AFTER SE */
if (opt_bootstrap)
if (WSREP_ON)
{
/*! bootstrap wsrep init was taken care of above */
}
else
{
wsrep_SE_initialized();
if (wsrep_before_SE())
if (opt_bootstrap)
{
/*! in case of no SST wsrep waits in view handler callback */
wsrep_SE_init_grab();
wsrep_SE_init_done();
/*! in case of SST wsrep waits for wsrep->sst_received */
wsrep_sst_continue();
/*! bootstrap wsrep init was taken care of above */
}
else
{
wsrep_init_startup (false);
}
wsrep_SE_initialized();
wsrep_create_appliers(wsrep_slave_threads - 1);
if (wsrep_before_SE())
{
/*! in case of no SST wsrep waits in view handler callback */
wsrep_SE_init_grab();
wsrep_SE_init_done();
/*! in case of SST wsrep waits for wsrep->sst_received */
wsrep_sst_continue();
}
else
{
wsrep_init_startup (false);
}
wsrep_create_appliers(wsrep_slave_threads - 1);
}
}
#endif /* WITH_WSREP */
if (opt_bootstrap)
@ -6311,9 +5865,7 @@ int mysqld_main(int argc, char **argv)
#ifdef EXTRA_DEBUG2
sql_print_error("Before Lock_thread_count");
#endif
#ifdef WITH_WSREP
WSREP_DEBUG("Before Lock_thread_count");
#endif
mysql_mutex_lock(&LOCK_thread_count);
DBUG_PRINT("quit", ("Got thread_count mutex"));
select_thread_in_use=0; // For close_connections
@ -10140,7 +9692,8 @@ void refresh_status(THD *thd)
/* Reset some global variables */
reset_status_vars();
#ifdef WITH_WSREP
wsrep->stats_reset(wsrep);
if (WSREP_ON)
wsrep->stats_reset(wsrep);
#endif /* WITH_WSREP */
/* Reset the counters of all key caches (default and named). */
@ -10193,6 +9746,7 @@ static PSI_file_info all_server_files[]=
};
#endif /* HAVE_PSI_INTERFACE */
PSI_stage_info stage_after_apply_event= { 0, "after apply log event", 0};
PSI_stage_info stage_after_create= { 0, "After create", 0};
PSI_stage_info stage_after_opening_tables= { 0, "After opening tables", 0};
PSI_stage_info stage_after_table_lock= { 0, "After table lock", 0};
@ -10200,6 +9754,7 @@ PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0};
PSI_stage_info stage_alter_inplace= { 0, "altering table", 0};
PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0};
PSI_stage_info stage_apply_event= { 0, "apply log event", 0};
PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0};
@ -10273,6 +9828,7 @@ PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DEL
PSI_stage_info stage_storing_result_in_query_cache= { 0, "storing result in query cache", 0};
PSI_stage_info stage_storing_row_into_queue= { 0, "storing row into queue", 0};
PSI_stage_info stage_system_lock= { 0, "System lock", 0};
PSI_stage_info stage_unlocking_tables= { 0, "Unlocking tables", 0};
PSI_stage_info stage_update= { 0, "update", 0};
PSI_stage_info stage_updating= { 0, "updating", 0};
PSI_stage_info stage_updating_main_table= { 0, "updating main table", 0};
@ -10317,6 +9873,7 @@ PSI_stage_info stage_gtid_wait_other_connection= { 0, "Waiting for other master
PSI_stage_info *all_server_stages[]=
{
& stage_after_apply_event,
& stage_after_create,
& stage_after_opening_tables,
& stage_after_table_lock,
@ -10324,6 +9881,7 @@ PSI_stage_info *all_server_stages[]=
& stage_alter_inplace,
& stage_alter_inplace_commit,
& stage_alter_inplace_prepare,
& stage_apply_event,
& stage_binlog_processing_checkpoint_notify,
& stage_binlog_stopping_background_thread,
& stage_binlog_waiting_background_tasks,
@ -10405,6 +9963,7 @@ PSI_stage_info *all_server_stages[]=
& stage_storing_result_in_query_cache,
& stage_storing_row_into_queue,
& stage_system_lock,
& stage_unlocking_tables,
& stage_update,
& stage_updating,
& stage_updating_main_table,

9
sql/mysqld.h

@ -25,6 +25,7 @@
#include "sql_list.h" /* I_List */
#include "sql_cmd.h"
#include <my_rnd.h>
#include "my_pthread.h"
class THD;
struct handlerton;
@ -333,6 +334,7 @@ void init_server_psi_keys();
MAINTAINER: Please keep this list in order, to limit merge collisions.
Hint: grep PSI_stage_info | sort -u
*/
extern PSI_stage_info stage_apply_event;
extern PSI_stage_info stage_after_create;
extern PSI_stage_info stage_after_opening_tables;
extern PSI_stage_info stage_after_table_lock;
@ -340,6 +342,7 @@ extern PSI_stage_info stage_allocating_local_table;
extern PSI_stage_info stage_alter_inplace_prepare;
extern PSI_stage_info stage_alter_inplace;
extern PSI_stage_info stage_alter_inplace_commit;
extern PSI_stage_info stage_after_apply_event;
extern PSI_stage_info stage_changing_master;
extern PSI_stage_info stage_checking_master_version;
extern PSI_stage_info stage_checking_permissions;
@ -413,6 +416,7 @@ extern PSI_stage_info stage_statistics;
extern PSI_stage_info stage_storing_result_in_query_cache;
extern PSI_stage_info stage_storing_row_into_queue;
extern PSI_stage_info stage_system_lock;
extern PSI_stage_info stage_unlocking_tables;
extern PSI_stage_info stage_update;
extern PSI_stage_info stage_updating;
extern PSI_stage_info stage_updating_main_table;
@ -766,9 +770,4 @@ extern uint internal_tmp_table_max_key_segments;
extern uint volatile global_disable_checkpoint;
extern my_bool opt_help;
#ifdef WITH_WSREP
#include "my_pthread.h"
pthread_handler_t start_wsrep_THD(void*);
#endif /* WITH_WSREP */
#endif /* MYSQLD_INCLUDED */

10
sql/protocol.cc

@ -488,14 +488,8 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
void Protocol::end_statement()
{
#ifdef WITH_WSREP
/*sanity check, can be removed before 1.0 release */
if (WSREP(thd) && thd->wsrep_conflict_state== REPLAYING)
{
WSREP_ERROR("attempting net_end_statement while replaying");
return;
}
#endif
/* sanity check*/
DBUG_ASSERT_IF_WSREP(!(WSREP_ON && WSREP(thd) && thd->wsrep_conflict_state == REPLAYING));
DBUG_ENTER("Protocol::end_statement");
DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
bool error= FALSE;

33
sql/rpl_record.cc

@ -305,13 +305,8 @@ unpack_row(rpl_group_info *rgi,
normal unpack operation.
*/
uint16 const metadata= tabledef->field_metadata(i);
#ifndef DBUG_OFF
uchar const *const old_pack_ptr= pack_ptr;
#else
#ifdef WITH_WSREP
uchar const *const old_pack_ptr= pack_ptr;
#endif /* WITH_WSREP */
#endif /* !DBUF_OFF */
pack_ptr= f->unpack(f->ptr, pack_ptr, row_end, metadata);
DBUG_PRINT("debug", ("field: %s; metadata: 0x%x;"
" pack_ptr: 0x%lx; pack_ptr': 0x%lx; bytes: %d",
@ -321,17 +316,21 @@ unpack_row(rpl_group_info *rgi,
if (!pack_ptr)
{
#ifdef WITH_WSREP
/*
Debug message to troubleshoot bug:
https://mariadb.atlassian.net/browse/MDEV-4404
*/
WSREP_WARN("ROW event unpack field: %s metadata: 0x%x;"
" pack_ptr: 0x%lx; conv_table %p conv_field %p table %s"
" row_end: 0x%lx",
f->field_name, metadata,
(ulong) old_pack_ptr, conv_table, conv_field,
(table_found) ? "found" : "not found", (ulong)row_end
);
if (WSREP_ON)
{
/*
Debug message to troubleshoot bug:
https://mariadb.atlassian.net/browse/MDEV-4404
Galera Node throws "Could not read field" error and drops out of cluster
*/
WSREP_WARN("ROW event unpack field: %s metadata: 0x%x;"
" pack_ptr: 0x%lx; conv_table %p conv_field %p table %s"
" row_end: 0x%lx",
f->field_name, metadata,
(ulong) old_pack_ptr, conv_table, conv_field,
(table_found) ? "found" : "not found", (ulong)row_end
);
}
#endif /* WITH_WSREP */
rgi->rli->report(ERROR_LEVEL, ER_SLAVE_CORRUPT_EVENT,

19
sql/slave.cc

@ -52,10 +52,8 @@
#include "log_event.h" // Rotate_log_event,
// Create_file_log_event,
// Format_description_log_event
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif
#ifdef HAVE_REPLICATION
#include "rpl_tblmap.h"
@ -4370,9 +4368,7 @@ pthread_handler_t handle_slave_sql(void *arg)
my_off_t saved_skip= 0;
Master_info *mi= ((Master_info*)arg);
Relay_log_info* rli = &mi->rli;
#ifdef WITH_WSREP
my_bool wsrep_node_dropped= FALSE;
#endif /* WITH_WSREP */
const char *errmsg;
rpl_group_info *serial_rgi;
rpl_sql_thread_info sql_info(mi->rpl_filter);
@ -4380,9 +4376,8 @@ pthread_handler_t handle_slave_sql(void *arg)
// needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff
my_thread_init();
DBUG_ENTER("handle_slave_sql");
#ifdef WITH_WSREP
wsrep_restart_point:
#endif /* WITH_WSREP */
LINT_INIT(saved_master_log_pos);
LINT_INIT(saved_log_pos);
@ -4515,7 +4510,8 @@ pthread_handler_t handle_slave_sql(void *arg)
#ifdef WITH_WSREP
thd->wsrep_exec_mode= LOCAL_STATE;
/* synchronize with wsrep replication */
if (WSREP_ON) wsrep_ready_wait();
if (WSREP_ON)
wsrep_ready_wait();
#endif
DBUG_PRINT("master_info",("log_file_name: %s position: %s",
rli->group_master_log_name,
@ -4617,7 +4613,7 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME,
rli->group_master_log_name, (ulong) rli->group_master_log_pos);
saved_skip= 0;
}
if (exec_relay_log_event(thd, rli, serial_rgi))
{
DBUG_PRINT("info", ("exec_relay_log_event() failed"));
@ -4626,8 +4622,7 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME,
{
slave_output_error_info(rli, thd);
#ifdef WITH_WSREP
uint32 const last_errno= rli->last_error().number;
if (WSREP_ON && last_errno == ER_UNKNOWN_COM_ERROR)
if (WSREP_ON && rli->last_error().number == ER_UNKNOWN_COM_ERROR)
{
wsrep_node_dropped= TRUE;
}
@ -4721,7 +4716,7 @@ err_during_init:
/* if slave stopped due to node going non primary, we set global flag to
trigger automatic restart of slave when node joins back to cluster
*/
if (wsrep_node_dropped && wsrep_restart_slave)
if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave)
{
if (wsrep_ready)
{

39
sql/sp.cc

@ -32,7 +32,7 @@
#include <my_user.h>
static bool
bool
create_string(THD *thd, String *buf,
stored_procedure_type sp_type,
const char *db, ulong dblen,
@ -924,7 +924,7 @@ end:
}
static void
void
sp_returns_type(THD *thd, String &result, sp_head *sp)
{
TABLE table;
@ -2126,7 +2126,7 @@ int sp_cache_routine(THD *thd, enum stored_procedure_type type, sp_name *name,
@return
Returns TRUE on success, FALSE on (alloc) failure.
*/
static bool
bool
create_string(THD *thd, String *buf,
stored_procedure_type type,
const char *db, ulong dblen,
@ -2271,37 +2271,4 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db,
thd->lex= old_lex;
return sp;
}
#ifdef WITH_WSREP
int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
sp_head *sp = thd->lex->sphead;
ulong saved_mode= thd->variables.sql_mode;
String retstr(64);
retstr.set_charset(system_charset_info);
log_query.set_charset(system_charset_info);
if (sp->m_type == TYPE_ENUM_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
}
if (!create_string(thd, &log_query,
sp->m_type,
(sp->m_explicit_name ? sp->m_db.str : NULL),
(sp->m_explicit_name ? sp->m_db.length : 0),
sp->m_name.str, sp->m_name.length,
sp->m_params.str, sp->m_params.length,
retstr.c_ptr(), retstr.length(),
sp->m_body.str, sp->m_body.length,
sp->m_chistics, &(thd->lex->definer->user),
&(thd->lex->definer->host),
saved_mode))
{
WSREP_WARN("SP create string failed: %s", thd->query());
return 1;
}
return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len);
}
#endif /* WITH_WSREP */

15
sql/sp.h

@ -214,4 +214,19 @@ bool load_collation(MEM_ROOT *mem_root,
CHARSET_INFO *dflt_cl,
CHARSET_INFO **cl);
void sp_returns_type(THD *thd,
String &result,
sp_head *sp);
bool create_string(THD *thd, String *buf,
stored_procedure_type type,
const char *db, ulong dblen,
const char *name, ulong namelen,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
st_sp_chistics *chistics,
const LEX_STRING *definer_user,
const LEX_STRING *definer_host,
ulonglong sql_mode);
#endif /* _SP_H_ */

33
sql/sql_acl.cc

@ -2560,12 +2560,8 @@ int check_alter_user(THD *thd, const char *host, const char *user)
goto end;
}
#ifdef WITH_WSREP
if ((!WSREP(thd) || !thd->wsrep_applier) &&
if (IF_WSREP((!WSREP(thd) || !thd->wsrep_applier), 1) &&
!thd->slave_thread && !thd->security_ctx->priv_user[0])
#else
if (!thd->slave_thread && !thd->security_ctx->priv_user[0])
#endif /* WITH_WSREP */
{
my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER),
MYF(0));
@ -2576,10 +2572,9 @@ int check_alter_user(THD *thd, const char *host, const char *user)
my_error(ER_PASSWORD_NO_MATCH, MYF(0));
goto end;
}
if (!thd->slave_thread &&
#ifdef WITH_WSREP
(!WSREP(thd) || !thd->wsrep_applier) &&
#endif /* WITH_WSREP */
IF_WSREP((!WSREP(thd) || !thd->wsrep_applier),1) &&
(strcmp(thd->security_ctx->priv_user, user) ||
my_strcasecmp(system_charset_info, host,
thd->security_ctx->priv_host)))
@ -2648,9 +2643,8 @@ bool change_password(THD *thd, const char *host, const char *user,
enum_binlog_format save_binlog_format;
uint new_password_len= (uint) strlen(new_password);
int result=0;
#ifdef WITH_WSREP
const CSET_STRING query_save = thd->query_string;
#endif /* WITH_WSREP */
DBUG_ENTER("change_password");
DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'",
host,user,new_password));
@ -2658,10 +2652,11 @@ bool change_password(THD *thd, const char *host, const char *user,
if (check_change_password(thd, host, user, new_password, new_password_len))
DBUG_RETURN(1);
#ifdef WITH_WSREP
if (WSREP(thd) && !thd->wsrep_applier)
{
query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
user ? user : "",
host ? host : "",
new_password);
@ -2736,11 +2731,10 @@ end:
DBUG_RETURN(result);
#ifdef WITH_WSREP
error:
WSREP_ERROR("Replication of SET PASSWORD failed: %s", buff);
error:
WSREP_ERROR("Repliation of SET PASSWORD failed: %s", buff);
DBUG_RETURN(result);
#endif /* WITH_WSREP */
}
int acl_check_set_default_role(THD *thd, const char *host, const char *user)
@ -2759,9 +2753,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
bool clear_role= FALSE;
char buff[512];
enum_binlog_format save_binlog_format;
#ifdef WITH_WSREP
const CSET_STRING query_save = thd->query_string;
#endif /* WITH_WSREP */
DBUG_ENTER("acl_set_default_role");
DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'",
@ -2867,6 +2859,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
}
end:
close_mysql_tables(thd);
#ifdef WITH_WSREP
if (WSREP(thd) && !thd->wsrep_applier)
{
@ -2876,14 +2869,10 @@ end:
thd->wsrep_exec_mode = LOCAL_STATE;
}
#endif /* WITH_WSREP */
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(result);
#ifdef WITH_WSREP
error:
WSREP_ERROR("Replication of SET PASSWORD failed: %s", buff);
DBUG_RETURN(result);
#endif /* WITH_WSREP */
}

3
sql/sql_admin.cc

@ -1143,9 +1143,8 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
FALSE, UINT_MAX, FALSE))
goto error;
thd->enable_slow_log= opt_log_slow_admin_statements;
#ifdef WITH_WSREP
WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL);
#endif
res= mysql_admin_table(thd, first_table, &m_lex->check_opt,
"analyze", lock_type, 1, 0, 0, 0,
&handler::ha_analyze, 0);

6
sql/sql_alter.cc

@ -18,9 +18,8 @@
// mysql_exchange_partition
#include "sql_base.h" // open_temporary_tables
#include "sql_alter.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif /* WITH_WSREP */
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
alter_list(rhs.alter_list, mem_root),
@ -320,6 +319,7 @@ bool Sql_cmd_alter_table::execute(THD *thd)
DBUG_RETURN(TRUE);
}
#endif /* WITH_WSREP */
result= mysql_alter_table(thd, select_lex->db, lex->name.str,
&create_info,
first_table,
@ -328,8 +328,6 @@ bool Sql_cmd_alter_table::execute(THD *thd)
select_lex->order_list.first,
lex->ignore);
#ifdef WITH_WSREP
#endif /* WITH_WSREP */
DBUG_RETURN(result);
}

31
sql/sql_base.cc

@ -61,11 +61,8 @@
#ifdef __WIN__
#include <io.h>
#endif
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
#endif // WITH_WSREP
bool
No_such_table_error_handler::handle_condition(THD *,
@ -4588,8 +4585,10 @@ restart:
}
}
}
#ifdef WITH_WSREP
if ((thd->lex->sql_command== SQLCOM_INSERT ||
if (WSREP_ON &&
(thd->lex->sql_command== SQLCOM_INSERT ||
thd->lex->sql_command== SQLCOM_INSERT_SELECT ||
thd->lex->sql_command== SQLCOM_REPLACE ||
thd->lex->sql_command== SQLCOM_REPLACE_SELECT ||
@ -4608,15 +4607,7 @@ restart:
err:
THD_STAGE_INFO(thd, stage_after_opening_tables);
#ifdef WITH_WSREP
if (WSREP(thd))
thd_proc_info(thd, "exit open_tables()");
else
thd_proc_info(thd, 0);
#else /* WITH_WSREP */
thd_proc_info(thd, 0);
#endif /* WITH_WSREP */
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
@ -5072,15 +5063,7 @@ end:
}
THD_STAGE_INFO(thd, stage_after_opening_tables);
#ifdef WITH_WSREP
if (WSREP(thd))
thd_proc_info(thd, "End opening table");
else
thd_proc_info(thd, 0);
#else /* WITH_WSREP */
thd_proc_info(thd, 0);
#endif /* WITH_WSREP */
DBUG_RETURN(table);
}
@ -9034,19 +9017,17 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use,
(e.g. see partitioning code).
*/
if (!thd_table->needs_reopen())
#ifdef WITH_WSREP
{
signalled|= mysql_lock_abort_for_thread(thd, thd_table);
if (thd && WSREP(thd) && wsrep_thd_is_BF((void *)thd, true))
#ifdef WITH_WSREP
if (thd && WSREP(thd) && wsrep_thd_is_BF((void *)thd, true))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) thd->real_id);
wsrep_abort_thd((void *)thd, (void *)in_use, FALSE);
}
}
#else
signalled|= mysql_lock_abort_for_thread(thd, thd_table);
#endif
}
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
}

279
sql/sql_class.cc

@ -64,10 +64,8 @@
#include "sql_parse.h" // is_update_query
#include "sql_callback.h"
#include "lock.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
#endif
#include "sql_connect.h"
/*
@ -820,176 +818,6 @@ char *thd_get_error_context_description(THD *thd, char *buffer,
return buffer;
}
#ifdef WITH_WSREP
extern int wsrep_on(void *thd)
{
return (int)(WSREP(((THD*)thd)));
}
extern "C" bool wsrep_thd_is_wsrep_on(THD *thd)
{
return thd->variables.wsrep_on;
}
extern "C" bool wsrep_consistency_check(void *thd)
{
return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
}
extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode)
{
thd->wsrep_exec_mode= mode;
}
extern "C" void wsrep_thd_set_query_state(
THD *thd, enum wsrep_query_state state)
{
thd->wsrep_query_state= state;
}
extern "C" void wsrep_thd_set_conflict_state(
THD *thd, enum wsrep_conflict_state state)
{
thd->wsrep_conflict_state= state;
}
extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd)
{
return thd->wsrep_exec_mode;
}
extern "C" const char *wsrep_thd_exec_mode_str(THD *thd)
{
return
(!thd) ? "void" :
(thd->wsrep_exec_mode == LOCAL_STATE) ? "local" :
(thd->wsrep_exec_mode == REPL_RECV) ? "applier" :
(thd->wsrep_exec_mode == TOTAL_ORDER) ? "total order" :
(thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void";
}
extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd)
{
return thd->wsrep_query_state;
}
extern "C" const char *wsrep_thd_query_state_str(THD *thd)
{
return
(!thd) ? "void" :
(thd->wsrep_query_state == QUERY_IDLE) ? "idle" :
(thd->wsrep_query_state == QUERY_EXEC) ? "executing" :
(thd->wsrep_query_state == QUERY_COMMITTING) ? "committing" :
(thd->wsrep_query_state == QUERY_EXITING) ? "exiting" :
(thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back" : "void";
}
extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd)
{
return thd->wsrep_conflict_state;
}
extern "C" const char *wsrep_thd_conflict_state_str(THD *thd)
{
return
(!thd) ? "void" :
(thd->wsrep_conflict_state == NO_CONFLICT) ? "no conflict" :
(thd->wsrep_conflict_state == MUST_ABORT) ? "must abort" :
(thd->wsrep_conflict_state == ABORTING) ? "aborting" :
(thd->wsrep_conflict_state == MUST_REPLAY) ? "must replay" :
(thd->wsrep_conflict_state == REPLAYING) ? "replaying" :
(thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying" :
(thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void";
}
extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd)
{
return &thd->wsrep_ws_handle;
}
extern "C" void wsrep_thd_LOCK(THD *thd)
{
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
}
extern "C" void wsrep_thd_UNLOCK(THD *thd)
{
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
extern "C" time_t wsrep_thd_query_start(THD *thd)
{
return thd->query_start();
}
extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd)
{
return thd->wsrep_rand;
}
extern "C" my_thread_id wsrep_thd_thread_id(THD *thd)
{
return thd->thread_id;
}
extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd)
{
return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED;
}
extern "C" query_id_t wsrep_thd_query_id(THD *thd)
{
return thd->query_id;
}
extern "C" char *wsrep_thd_query(THD *thd)
{
return (thd) ? thd->query() : NULL;
}
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd)
{
return thd->wsrep_last_query_id;
}
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id)
{
thd->wsrep_last_query_id= id;
}
extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
{
if (signal)
{
mysql_mutex_lock(&thd->LOCK_thd_data);
thd->awake(KILL_QUERY);
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
else
{
mysql_mutex_lock(&LOCK_wsrep_replaying);
mysql_cond_broadcast(&COND_wsrep_replaying);
mysql_mutex_unlock(&LOCK_wsrep_replaying);
}
}
extern "C" int wsrep_thd_retry_counter(THD *thd)
{
return(thd->wsrep_retry_counter);
}
extern int
wsrep_trx_order_before(void *thd1, void *thd2)
{
if (wsrep_thd_trx_seqno((THD*)thd1) < wsrep_thd_trx_seqno((THD*)thd2)) {
WSREP_DEBUG("BF conflict, order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno((THD*)thd1),
(long long)wsrep_thd_trx_seqno((THD*)thd2));
return 1;
}
WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno((THD*)thd1),
(long long)wsrep_thd_trx_seqno((THD*)thd2));
return 0;
}
extern "C" int
wsrep_trx_is_aborting(void *thd_ptr)
{
if (thd_ptr) {
if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) ||
(((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) {
return 1;
}
}
return 0;
}
#endif
#if MARIA_PLUGIN_INTERFACE_VERSION < 0x0200
/**
@ -1069,7 +897,7 @@ THD::THD(bool is_applier)
wsrep_client_thread(false),
wsrep_po_handle(WSREP_PO_INITIALIZER),
wsrep_po_cnt(0),
wsrep_po_in_trans(false),
// wsrep_po_in_trans(false),
wsrep_apply_format(0),
wsrep_apply_toi(false),
#endif
@ -1243,13 +1071,9 @@ THD::THD(bool is_applier)
my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
substitute_null_with_insert_id = FALSE;
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
#ifdef WITH_WSREP
lock_info.mysql_thd= (void *)this;
lock_info.in_lock_tables= false;
#ifdef WSREP_PROC_INFO
wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */
#endif /* WSREP_PROC_INFO */
#endif /* WITH_WSREP */
m_internal_handler= NULL;
m_binlog_invoker= INVOKER_NONE;
@ -1992,9 +1816,6 @@ void THD::awake(killed_state state_to_set)
/* Interrupt target waiting inside a storage engine. */
if (state_to_set != NOT_KILLED)
#ifdef WITH_WSREP
/* TODO: prevent applier close here */
#endif /* WITH_WSREP */
ha_kill_query(this, thd_kill_level(this));
/* Broadcast a condition to kick the target if it is waiting on it. */
@ -2127,19 +1948,17 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
(e.g. see partitioning code).
*/
if (!thd_table->needs_reopen())
#ifdef WITH_WSREP
{
signalled|= mysql_lock_abort_for_thread(this, thd_table);
if (this && WSREP(this) && wsrep_thd_is_BF((void *)this, FALSE))
#if WITH_WSREP
if (WSREP_ON && this && WSREP(this) && wsrep_thd_is_BF((void *)this, FALSE))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) this->real_id);
wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
}
#endif /* WITH_WSREP */
}
#else
signalled|= mysql_lock_abort_for_thread(this, thd_table);
#endif
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
}
@ -2322,11 +2141,10 @@ void THD::cleanup_after_query()
table_map_for_update= 0;
m_binlog_invoker= INVOKER_NONE;
#ifdef WITH_WSREP
if (TOTAL_ORDER == wsrep_exec_mode)
{
wsrep_exec_mode = LOCAL_STATE;
}
//wsrep_trx_seqno = 0;
if (WSREP_ON && TOTAL_ORDER == wsrep_exec_mode)
{
wsrep_exec_mode = LOCAL_STATE;
}
#endif /* WITH_WSREP */
#ifndef EMBEDDED_LIBRARY
@ -2751,7 +2569,7 @@ bool select_send::send_result_set_metadata(List<Item> &list, uint flags)
{
bool res;
#ifdef WITH_WSREP
if (WSREP(thd) && thd->wsrep_retry_query)
if (WSREP_ON && WSREP(thd) && thd->wsrep_retry_query)
{
WSREP_DEBUG("skipping select metadata");
return FALSE;
@ -4502,12 +4320,9 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
extern "C" int thd_binlog_format(const MYSQL_THD thd)
{
#ifdef WITH_WSREP
if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) &&
(thd->variables.option_bits & OPTION_BIN_LOG))
#else
if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG))
#endif
if (IF_WSREP(((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()) &&
thd->variables.option_bits & OPTION_BIN_LOG)
return (int) WSREP_FORMAT(thd->variables.binlog_format);
else
return BINLOG_FORMAT_UNSPEC;
@ -5494,14 +5309,10 @@ int THD::decide_logging_format(TABLE_LIST *tables)
5. Error: Cannot modify table that uses a storage engine
limited to row-logging when binlog_format = STATEMENT
*/
#ifdef WITH_WSREP
if (!WSREP(this) || wsrep_exec_mode == LOCAL_STATE)
if (IF_WSREP(WSREP_ON && (!WSREP(this) || wsrep_exec_mode == LOCAL_STATE),1))
{
#endif /* WITH_WSREP */
my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), "");
#ifdef WITH_WSREP
my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), "");
}
#endif /* WITH_WSREP */
}
else if (is_write && (unsafe_flags= lex->get_stmt_unsafe_flags()) != 0)
{
@ -5849,15 +5660,11 @@ CPP_UNNAMED_NS_END
int THD::binlog_write_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, size_t colcnt,
uchar const *record)
{
#ifdef WITH_WSREP
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log) ||
mysql_bin_log.is_open()));
#else
DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
#endif
{
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
IF_WSREP(((WSREP_ON && WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()));
/*
Pack records into format for transfer. We are allocating more
memory than needed, but that doesn't matter.
@ -5889,14 +5696,10 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, size_t colcnt,
const uchar *before_record,
const uchar *after_record)
{
#ifdef WITH_WSREP
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log)
|| mysql_bin_log.is_open()));
#else
DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
#endif
{
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
IF_WSREP(((WSREP_ON && WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()));
size_t const before_maxlen = max_row_length(table, before_record);
size_t const after_maxlen = max_row_length(table, after_record);
@ -5944,14 +5747,10 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
int THD::binlog_delete_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, size_t colcnt,
uchar const *record)
{
#ifdef WITH_WSREP
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log)
|| mysql_bin_log.is_open()));
#else
DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open());
#endif
{
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
IF_WSREP(((WSREP_ON && WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()));
/*
Pack records into format for transfer. We are allocating more
@ -5986,11 +5785,8 @@ int THD::binlog_remove_pending_rows_event(bool clear_maps,
{
DBUG_ENTER("THD::binlog_remove_pending_rows_event");
#ifdef WITH_WSREP
if (!(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open()))
#else
if (!mysql_bin_log.is_open())
#endif
IF_WSREP(WSREP_ON && !(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open()),
!mysql_bin_log.is_open());
DBUG_RETURN(0);
/* Ensure that all events in a GTID group are in the same cache */
@ -6013,11 +5809,8 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional)
mode: it might be the case that we left row-based mode before
flushing anything (e.g., if we have explicitly locked tables).
*/
#ifdef WITH_WSREP
if (!(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open()))
#else
if (!mysql_bin_log.is_open())
#endif
IF_WSREP(WSREP_ON && !(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open()),
!mysql_bin_log.is_open());
DBUG_RETURN(0);
/* Ensure that all events in a GTID group are in the same cache */
@ -6269,12 +6062,10 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
DBUG_ENTER("THD::binlog_query");
DBUG_PRINT("enter", ("qtype: %s query: '%-.*s'",
show_query_type(qtype), (int) query_len, query_arg));
#ifdef WITH_WSREP
DBUG_ASSERT(query_arg && (WSREP_EMULATE_BINLOG(this)
|| mysql_bin_log.is_open()));
#else
DBUG_ASSERT(query_arg && mysql_bin_log.is_open());
#endif
DBUG_ASSERT(query_arg &&
IF_WSREP(WSREP_ON && (WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()));
/* If this is withing a BEGIN ... COMMIT group, don't log it */
if (variables.option_bits & OPTION_GTID_BEGIN)

26
sql/sql_class.h

@ -50,25 +50,14 @@ void set_thd_stage_info(void *thd,
const char *calling_func,
const char *calling_file,
const unsigned int calling_line);
#define THD_STAGE_INFO(thd, stage) \
(thd)->enter_stage(& stage, NULL, __func__, __FILE__, __LINE__)
#include "my_apc.h"
#include "rpl_gtid.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
struct wsrep_thd_shadow {
ulonglong options;
uint server_status;
enum wsrep_exec_mode wsrep_exec_mode;
Vio *vio;
ulong tx_isolation;
char *db;
size_t db_length;
};
#endif
class Reprepare_observer;
class Relay_log_info;
struct rpl_group_info;
@ -2746,6 +2735,9 @@ public:
const bool wsrep_applier; /* dedicated slave applier thread */
bool wsrep_applier_closing; /* applier marked to close */
bool wsrep_client_thread; /* to identify client threads*/
bool wsrep_PA_safe;
bool wsrep_converted_lock_session;
bool wsrep_apply_toi; /* applier processing in TOI */
enum wsrep_exec_mode wsrep_exec_mode;
query_id_t wsrep_last_query_id;
enum wsrep_query_state wsrep_query_state;
@ -2758,17 +2750,13 @@ public:
uint32 wsrep_rand;
Relay_log_info* wsrep_rli;
rpl_group_info* wsrep_rgi;
bool wsrep_converted_lock_session;
wsrep_ws_handle_t wsrep_ws_handle;
#ifdef WSREP_PROC_INFO
char wsrep_info[128]; /* string for dynamic proc info */
#endif /* WSREP_PROC_INFO */
ulong wsrep_retry_counter; // of autocommit
bool wsrep_PA_safe;
char* wsrep_retry_query;
size_t wsrep_retry_query_len;
enum enum_server_command wsrep_retry_command;
enum wsrep_consistency_check_mode
enum wsrep_consistency_check_mode
wsrep_consistency_check;
wsrep_stats_var* wsrep_status_vars;
int wsrep_mysql_replicated;
@ -2777,12 +2765,10 @@ public:
size_t wsrep_TOI_pre_query_len;
wsrep_po_handle_t wsrep_po_handle;
size_t wsrep_po_cnt;
my_bool wsrep_po_in_trans;
#ifdef GTID_SUPPORT
rpl_sid wsrep_po_sid;
#endif /* GTID_SUPPORT */
void* wsrep_apply_format;
bool wsrep_apply_toi; /* applier processing in TOI */
#endif /* WITH_WSREP */
/**
Internal parser state.

6
sql/sql_connect.cc

@ -37,6 +37,7 @@
// reset_host_errors
#include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL
#include "sql_callback.h"
#include "wsrep_mysqld.h"
HASH global_user_stats, global_client_stats, global_table_stats;
HASH global_index_stats;
@ -44,9 +45,6 @@ HASH global_index_stats;
extern mysql_mutex_t LOCK_global_user_client_stats;
extern mysql_mutex_t LOCK_global_table_stats;
extern mysql_mutex_t LOCK_global_index_stats;
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif
/*
Get structure for logging connection data for the current user
@ -1397,7 +1395,7 @@ void do_handle_one_connection(THD *thd_arg)
break;
}
end_connection(thd);
#ifdef WITH_WSREP
if (WSREP(thd))
{

29
sql/sql_delete.cc

@ -642,22 +642,19 @@ cleanup:
if (!transactional_table && deleted > 0)
thd->transaction.stmt.modified_non_trans_table=
thd->transaction.all.modified_non_trans_table= TRUE;
/* See similar binlogging code in sql_update.cc, for comments */
if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
{
#ifdef WITH_WSREP
if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()))
#else
if (mysql_bin_log.is_open())
#endif
if(IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= 0;
if (error < 0)
thd->clear_error();
else
errcode= query_error_code(thd, killed_status == NOT_KILLED);
/*
[binlog]: If 'handler::delete_all_rows()' was called and the
storage engine does not inject the rows itself, we replicate
@ -1111,17 +1108,14 @@ void multi_delete::abort_result_set()
DBUG_ASSERT(error_handled);
DBUG_VOID_RETURN;
}
if (thd->transaction.stmt.modified_non_trans_table)
{
/*
/*
there is only side effects; to binlog with the error
*/
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if (IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= query_error_code(thd, thd->killed == NOT_KILLED);
/* possible error of writing binary log is ignored deliberately */
@ -1297,11 +1291,8 @@ bool multi_delete::send_eof()
}
if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table)
{
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if(IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= 0;
if (local_error == 0)

57
sql/sql_insert.cc

@ -1014,11 +1014,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->transaction.stmt.modified_non_trans_table ||
was_insert_delayed)
{
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if(IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= 0;
if (error <= 0)
@ -3199,6 +3196,7 @@ bool Delayed_insert::handle_inserts(void)
mysql_cond_broadcast(&cond_client); // If waiting clients
}
}
#ifdef WITH_WSREP
if (WSREP((&thd)))
thd_proc_info(&thd, "insert done");
@ -3657,15 +3655,11 @@ bool select_insert::send_eof()
DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'",
trans_table, table->file->table_type()));
#ifdef WITH_WSREP
error= (thd->wsrep_conflict_state == MUST_ABORT ||
thd->wsrep_conflict_state == CERT_FAILURE) ? -1 :
(thd->locked_tables_mode <= LTM_LOCK_TABLES ?
table->file->ha_end_bulk_insert() : 0);
#else
error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ?
table->file->ha_end_bulk_insert() : 0);
#endif /* WITH_WSREP */
error = IF_WSREP((thd->wsrep_conflict_state == MUST_ABORT ||
thd->wsrep_conflict_state == CERT_FAILURE) ? -1 :, )
(thd->locked_tables_mode <= LTM_LOCK_TABLES ?
table->file->ha_end_bulk_insert() : 0);
if (!error && thd->is_error())
error= thd->get_stmt_da()->sql_errno();
@ -3693,13 +3687,9 @@ bool select_insert::send_eof()
events are in the transaction cache and will be written when
ha_autocommit_or_rollback() is issued below.
*/
#ifdef WITH_WSREP
if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
(!error || thd->transaction.stmt.modified_non_trans_table))
#else
if (mysql_bin_log.is_open() &&
(!error || thd->transaction.stmt.modified_non_trans_table))
#endif
if(IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()) &&
(!error || thd->transaction.stmt.modified_non_trans_table))
{
int errcode= 0;
if (!error)
@ -3783,11 +3773,8 @@ void select_insert::abort_result_set() {
if (!can_rollback_data())
thd->transaction.all.modified_non_trans_table= TRUE;
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if(IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= query_error_code(thd, thd->killed == NOT_KILLED);
/* error of writing binary log is ignored */
@ -4195,11 +4182,8 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
create_info->table_was_deleted);
DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif /* WITH_WSREP */
if(IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= query_error_code(thd, thd->killed == NOT_KILLED);
result= thd->binlog_query(THD::STMT_QUERY_TYPE,
@ -4209,9 +4193,9 @@ select_create::binlog_show_create_table(TABLE **tables, uint count)
/* suppress_use */ FALSE,
errcode);
}
#ifdef WITH_WSREP
ha_wsrep_fake_trx_id(thd);
#endif
IF_WSREP(ha_wsrep_fake_trx_id(thd), );
return result;
}
@ -4242,16 +4226,19 @@ bool select_create::send_eof()
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
trans_commit_implicit(thd);
#ifdef WITH_WSREP
if (WSREP_ON)
{
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
if (thd->wsrep_conflict_state != NO_CONFLICT)
{
WSREP_DEBUG("select_create commit failed, thd: %lu err: %d %s",
WSREP_DEBUG("select_create commit failed, thd: %lu err: %d %s",
thd->thread_id, thd->wsrep_conflict_state, thd->query());
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
abort_result_set();
return TRUE;
}
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
#endif /* WITH_WSREP */
}
else if (!thd->is_current_stmt_binlog_format_row())

4
sql/sql_lex.cc

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2009, 2013, Monty Program Ab.
Copyright (c) 2009, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -1580,7 +1580,7 @@ int lex_one_token(void *arg, THD *thd)
else
{
#ifdef WITH_WSREP
if (version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE)
if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE)
{
WSREP_DEBUG("consistency check: %s", thd->query());
thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED;

251
sql/sql_parse.cc

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2008, 2013, Monty Program Ab
Copyright (c) 2008, 2014, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -103,12 +103,14 @@
#include "../storage/maria/ha_maria.h"
#endif
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#include "wsrep_thd.h"
#ifdef WITH_WSREP
static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state);
#endif /* WITH_WSREP */
/**
@defgroup Runtime_Environment Runtime Environment
@{
@ -895,18 +897,20 @@ bool do_command(THD *thd)
NET *net= &thd->net;
enum enum_server_command command;
DBUG_ENTER("do_command");
#ifdef WITH_WSREP
if (WSREP(thd))
{
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
thd->wsrep_query_state= QUERY_IDLE;
if (thd->wsrep_conflict_state==MUST_ABORT)
if (thd->wsrep_conflict_state==MUST_ABORT)
{
wsrep_client_rollback(thd);
}
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
#endif /* WITH_WSREP */
/*
indicator of uninitialized lex => normal flow of errors handling
(see my_message_sql)
@ -976,19 +980,17 @@ bool do_command(THD *thd)
thd->wsrep_query_state= QUERY_EXEC;
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
#endif /* WITH_WSREP */
if ((WSREP(thd) && packet_length == packet_error) ||
(!WSREP(thd) && (packet_length == packet_error)))
#else
if (packet_length == packet_error)
#endif /* WITH_WSREP */
{
DBUG_PRINT("info",("Got error %d reading command from socket %s",
net->error,
vio_description(net->vio)));
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
if (thd->wsrep_conflict_state == MUST_ABORT)
{
@ -998,6 +1000,7 @@ bool do_command(THD *thd)
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
#endif /* WITH_WSREP */
/* Instrument this broken statement as "statement/com/error" */
thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
com_statement_info[COM_END].
@ -1053,7 +1056,8 @@ bool do_command(THD *thd)
command_name[command].str));
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
/*
* bail out if DB snapshot has not been installed. We however,
* allow queries "SET" and "SHOW", they are trapped later in execute_command
@ -1087,7 +1091,8 @@ bool do_command(THD *thd)
DBUG_ASSERT(!thd->apc_target.is_enabled());
return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1));
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT)
{
WSREP_DEBUG("Retry autocommit for: %s\n", thd->wsrep_retry_query);
@ -1105,13 +1110,14 @@ bool do_command(THD *thd)
thd->wsrep_retry_query_len);
thd->variables.character_set_client = current_charset;
}
}
if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING)
{
my_free(thd->wsrep_retry_query);
thd->wsrep_retry_query = NULL;
thd->wsrep_retry_query_len = 0;
thd->wsrep_retry_command = COM_CONNECT;
if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING)
{
my_free(thd->wsrep_retry_query);
thd->wsrep_retry_query = NULL;
thd->wsrep_retry_query_len = 0;
thd->wsrep_retry_command = COM_CONNECT;
}
}
#endif /* WITH_WSREP */
DBUG_ASSERT(!thd->apc_target.is_enabled());
@ -1137,7 +1143,7 @@ out:
@retval FALSE The statement isn't updating any relevant tables.
*/
static my_bool deny_updates_if_read_only_option(THD *thd,
my_bool deny_updates_if_read_only_option(THD *thd,
TABLE_LIST *all_tables)
{
DBUG_ENTER("deny_updates_if_read_only_option");
@ -1191,33 +1197,7 @@ static my_bool deny_updates_if_read_only_option(THD *thd,
DBUG_RETURN(FALSE);
}
#ifdef WITH_WSREP
static my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables)
{
int opt_readonly_saved = opt_readonly;
ulong flag_saved = (ulong)(thd->security_ctx->master_access & SUPER_ACL);
opt_readonly = 0;
thd->security_ctx->master_access &= ~SUPER_ACL;
my_bool ret = !deny_updates_if_read_only_option(thd, all_tables);
opt_readonly = opt_readonly_saved;
thd->security_ctx->master_access |= flag_saved;
return ret;
}
static void wsrep_copy_query(THD *thd)
{
thd->wsrep_retry_command = thd->get_command();
thd->wsrep_retry_query_len = thd->query_length();
thd->wsrep_retry_query = (char *)my_malloc(
thd->wsrep_retry_query_len + 1, MYF(0));
strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len);
thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0';
}
#endif /* WITH_WSREP */
/**
Perform one connection-level (COM_XXXX) command.
@ -1248,7 +1228,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_PRINT("info", ("command: %d", command));
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
if (!thd->in_multi_stmt_transaction_mode())
{
thd->wsrep_PA_safe= true;
@ -1480,10 +1461,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
#ifdef WITH_WSREP
wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
#else
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
if (WSREP_ON)
wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
else
#endif /* WITH_WSREP */
mysql_parse(thd, thd->query(), thd->query_length(), &parser_state);
while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) &&
! thd->is_error())
@ -1557,19 +1539,20 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
Count each statement from the client.
*/
statistic_increment(thd->status_var.questions, &LOCK_status);
#ifdef WITH_WSREP
if (!WSREP(thd))
if(IF_WSREP(!WSREP(thd), 1))
thd->set_time(); /* Reset the query start time. */
#else
thd->set_time(); /* Reset the query start time. */
#endif /* WITH_WSREP */
parser_state.reset(beginning_of_next_stmt, length);
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
#ifdef WITH_WSREP
wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state);
#else
mysql_parse(thd, beginning_of_next_stmt, length, &parser_state);
if (WSREP_ON)
wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state);
else
#endif /* WITH_WSREP */
mysql_parse(thd, beginning_of_next_stmt, length, &parser_state);
}
DBUG_PRINT("info",("query ready"));
@ -1909,7 +1892,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#ifdef WITH_WSREP
dispatch_end:
if (WSREP(thd)) {
if (WSREP(thd))
{
/* wsrep BF abort in query exec phase */
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
if ((thd->wsrep_conflict_state != REPLAYING) &&
@ -1919,25 +1903,25 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->update_server_status();
thd->protocol->end_statement();
query_cache_end_of_result(thd);
}
}
else
{
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
} else { /* if (WSREP(thd))... */
}
else
#endif /* WITH_WSREP */
DBUG_ASSERT(thd->derived_tables == NULL &&
(thd->open_tables == NULL ||
{
DBUG_ASSERT(thd->derived_tables == NULL &&
(thd->open_tables == NULL ||
(thd->locked_tables_mode == LTM_LOCK_TABLES)));
thd_proc_info(thd, "updating status");
/* Finalize server status flags after executing a command. */
thd->update_server_status();
thd->protocol->end_statement();
query_cache_end_of_result(thd);
#ifdef WITH_WSREP
thd_proc_info(thd, "updating status");
/* Finalize server status flags after executing a command. */
thd->update_server_status();
thd->protocol->end_statement();
query_cache_end_of_result(thd);
}
#endif /* WITH_WSREP */
if (!thd->is_error() && !thd->killed_errno())
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);
@ -2389,13 +2373,6 @@ err:
return TRUE;
}
#ifdef WITH_WSREP
static bool wsrep_is_show_query(enum enum_sql_command command)
{
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0;
}
#endif /* WITH_WSREP */
/**
Execute command saved in thd and lex->sql_command.
@ -2598,7 +2575,8 @@ mysql_execute_command(THD *thd)
} /* endif unlikely slave */
#endif
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
/*
change LOCK TABLE WRITE to transaction
*/
@ -2630,31 +2608,10 @@ mysql_execute_command(THD *thd)
lex->sql_command != SQLCOM_SET_OPTION &&
!wsrep_is_show_query(lex->sql_command))
{
#if DIRTY_HACK
/* Dirty hack for lp:1002714 - trying to recognize mysqldump connection
* and allow it to continue. Actuall mysqldump_magic_str may be longer
* and is obviously version dependent and may be issued by any client
* connection after which connection becomes non-replicating. */
static char const mysqldump_magic_str[]=
"SELECT LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG' AND FILE_NAME IS NOT NULL";
static const size_t mysqldump_magic_str_len= sizeof(mysqldump_magic_str) -1;
if (SQLCOM_SELECT != lex->sql_command ||
thd->query_length() < mysqldump_magic_str_len ||
strncmp(thd->query(), mysqldump_magic_str, mysqldump_magic_str_len))
{
#endif /* DIRTY_HACK */
my_message(ER_UNKNOWN_COM_ERROR,
"WSREP has not yet prepared node for application use",
MYF(0));
goto error;
#if DIRTY_HACK
}
else
{
/* mysqldump connection, allow all further queries to pass */
thd->variables.wsrep_on= FALSE;
}
#endif /* DIRTY_HACK */
}
}
#endif /* WITH_WSREP */
@ -2701,16 +2658,14 @@ mysql_execute_command(THD *thd)
if (trans_commit_implicit(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
/* Release metadata locks acquired in this transaction. */
thd->mdl_context.release_transactional_locks();
}
}
#ifndef DBUG_OFF
if (lex->sql_command != SQLCOM_SET_OPTION)
DEBUG_SYNC(thd,"before_execute_sql_command");
@ -2764,7 +2719,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STATUS:
{
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error;
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
goto error;
#endif /* WITH_WSREP */
execute_show_status(thd, all_tables);
break;
@ -2799,7 +2755,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error;
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
goto error;
#endif /* WITH_WSREP */
case SQLCOM_SHOW_DATABASES:
@ -2823,7 +2780,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_SHOW_INDEX_STATS:
case SQLCOM_SELECT:
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error;
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
goto error;
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_CHARSETS:
case SQLCOM_SHOW_COLLATIONS:
@ -3187,7 +3145,7 @@ case SQLCOM_PREPARE:
*/
if(lex->ignore)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_IGNORE_SELECT);
if(lex->duplicates == DUP_REPLACE)
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_REPLACE_SELECT);
@ -3199,7 +3157,7 @@ case SQLCOM_PREPARE:
raise a warning, as it may cause problems
(see 'NAME_CONST issues' in 'Binary Logging of Stored Programs')
*/
if (thd->query_name_consts &&
if (thd->query_name_consts &&
mysql_bin_log.is_open() &&
WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT &&
!mysql_bin_log.is_query_in_union(thd, thd->query_id))
@ -3320,8 +3278,8 @@ case SQLCOM_PREPARE:
/* in STATEMENT format, we probably have to replicate also temporary
tables, like mysql replication does
*/
if (!thd->is_current_stmt_binlog_format_row() ||
!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
if (WSREP_ON && (!thd->is_current_stmt_binlog_format_row() ||
!(create_info.options & HA_LEX_CREATE_TMP_TABLE)))
WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name,
NULL)
#endif /* WITH_WSREP */
@ -3510,7 +3468,8 @@ end_with_restore_list:
#else
{
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error;
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
goto error;
#endif /* WITH_WSREP */
/*
@ -3576,7 +3535,8 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef WITH_WSREP
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error;
if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd))
goto error;
#endif /* WITH_WSREP */
if (check_table_access(thd, SELECT_ACL, all_tables,
@ -3790,14 +3750,14 @@ end_with_restore_list:
if ((res= insert_precheck(thd, all_tables)))
break;
#ifdef WITH_WSREP
if (lex->sql_command == SQLCOM_INSERT_SELECT &&
if (WSREP_ON && lex->sql_command == SQLCOM_INSERT_SELECT &&
thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED)
{
thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING;
WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL);
}
#endif /* WITH_WSREP */
#endif
/*
INSERT...SELECT...ON DUPLICATE KEY UPDATE/REPLACE SELECT/
INSERT...IGNORE...SELECT can be unsafe, unless ORDER BY PRIMARY KEY
@ -4015,14 +3975,17 @@ end_with_restore_list:
thd->variables.option_bits|= OPTION_KEEP_LOG;
}
#ifdef WITH_WSREP
for (TABLE_LIST *table= all_tables; table; table= table->next_global)
if (WSREP_ON)
{
if (!lex->drop_temporary &&
(!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, table)))
for (TABLE_LIST *table= all_tables; table; table= table->next_global)
{
WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables);
break;
if (!lex->drop_temporary &&
(!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, table)))
{
WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables);
break;
}
}
}
#endif /* WITH_WSREP */
@ -4755,17 +4718,10 @@ end_with_restore_list:
able to open it (with SQLCOM_HA_OPEN) in the first place.
*/
unit->set_limit(select_lex);
#ifdef WITH_WSREP
{ char* tmp_info= NULL;
if (WSREP(thd)) tmp_info = (char *)thd_proc_info(thd, "mysql_ha_read()");
#endif /* WITH_WSREP */
res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
lex->insert_list, lex->ha_rkey_mode, select_lex->where,
unit->select_limit_cnt, unit->offset_limit_cnt);
#ifdef WITH_WSREP
if (WSREP(thd)) thd_proc_info(thd, tmp_info);
}
#endif /* WITH_WSREP */
break;
case SQLCOM_BEGIN:
@ -4773,9 +4729,7 @@ end_with_restore_list:
if (trans_begin(thd, lex->start_transaction_opt))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
my_ok(thd);
@ -4793,9 +4747,7 @@ end_with_restore_list:
if (trans_commit(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -4818,19 +4770,16 @@ end_with_restore_list:
thd->print_aborted_warning(3, "RELEASE");
}
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
if (thd->wsrep_conflict_state == NO_CONFLICT ||
thd->wsrep_conflict_state == REPLAYING)
{
my_ok(thd);
}
} else {
#endif /* WITH_WSREP */
my_ok(thd);
#ifdef WITH_WSREP
}
} else
#endif /* WITH_WSREP */
my_ok(thd);
break;
}
case SQLCOM_ROLLBACK:
@ -4847,9 +4796,7 @@ end_with_restore_list:
if (trans_rollback(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -4869,16 +4816,15 @@ end_with_restore_list:
if (tx_release)
thd->killed= KILL_CONNECTION;
#ifdef WITH_WSREP
if (WSREP(thd)) {
if (WSREP(thd))
{
if (thd->wsrep_conflict_state == NO_CONFLICT) {
my_ok(thd);
}
} else {
#endif /* WITH_WSREP */
my_ok(thd);
#ifdef WITH_WSREP
}
else
#endif /* WITH_WSREP */
my_ok(thd);
break;
}
case SQLCOM_RELEASE_SAVEPOINT:
@ -5394,9 +5340,7 @@ create_sp_error:
if (trans_xa_commit(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -5412,9 +5356,7 @@ create_sp_error:
if (trans_xa_rollback(thd))
{
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
goto error;
}
thd->mdl_context.release_transactional_locks();
@ -5764,7 +5706,8 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
else
status_var_add(thd->status_var.rows_sent, thd->get_sent_row_count());
#ifdef WITH_WSREP
if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd);
if (WSREP_ON && lex->sql_command == SQLCOM_SHOW_STATUS)
wsrep_free_status(thd);
#endif /* WITH_WSREP */
return res;
}
@ -6610,7 +6553,8 @@ void THD::reset_for_next_command()
transactions. Appliers and replayers are either processing ROW
events or get autoinc variable values from Query_log_event.
*/
if (WSREP(thd) && thd->wsrep_exec_mode == LOCAL_STATE) {
if (WSREP(thd) && thd->wsrep_exec_mode == LOCAL_STATE)
{
if (wsrep_auto_increment_control)
{
if (thd->variables.auto_increment_offset !=
@ -6831,7 +6775,7 @@ void mysql_init_multi_delete(LEX *lex)
static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length,
Parser_state *parser_state)
{
bool is_autocommit=
bool is_autocommit=
!thd->in_multi_stmt_transaction_mode() &&
thd->wsrep_conflict_state == NO_CONFLICT &&
!thd->wsrep_applier &&
@ -7959,14 +7903,9 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
faster and do a harder kill than KILL_SYSTEM_THREAD;
*/
#ifdef WITH_WSREP
if (((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) &&
!wsrep_thd_is_BF((void *)tmp, true))
#else
if ((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx))
#endif /* WITH_WSREP */
IF_WSREP(!wsrep_thd_is_BF((void *)tmp, true), 1))
{
tmp->awake(kill_signal);
error=0;

17
sql/sql_parse.h

@ -202,22 +202,5 @@ inline bool is_supported_parser_charset(CHARSET_INFO *cs)
{
return MY_TEST(cs->mbminlen == 1);
}
#ifdef WITH_WSREP
#define WSREP_MYSQL_DB (char *)"mysql"
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error;
#define WSREP_TO_ISOLATION_END \
if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \
wsrep_to_isolation_end(thd);
#else
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_)
#define WSREP_TO_ISOLATION_END
#endif /* WITH_WSREP */
#endif /* SQL_PARSE_INCLUDED */

23
sql/sql_partition_admin.cc

@ -1,4 +1,5 @@
/* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2014, SkySQL Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -764,18 +765,22 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
DBUG_RETURN(TRUE);
#ifdef WITH_WSREP
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if ((!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)) &&
wsrep_to_isolation_begin(
thd, first_table->db, first_table->table_name, NULL)
)
if (WSREP_ON)
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
if ((!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)) &&
wsrep_to_isolation_begin(
thd, first_table->db, first_table->table_name, NULL)
)
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
}
}
#endif /* WITH_WSREP */
if (open_tables(thd, &first_table, &table_counter, 0))
DBUG_RETURN(true);

22
sql/sql_plugin.cc

@ -3087,21 +3087,19 @@ void plugin_thdvar_init(THD *thd)
thd->variables.dynamic_variables_size= 0;
thd->variables.dynamic_variables_ptr= 0;
#ifdef WITH_WSREP
if (!WSREP(thd) || !thd->wsrep_applier) {
#endif
mysql_mutex_lock(&LOCK_plugin);
thd->variables.table_plugin=
if (IF_WSREP((!WSREP(thd) || !thd->wsrep_applier),1))
{
mysql_mutex_lock(&LOCK_plugin);
thd->variables.table_plugin=
intern_plugin_lock(NULL, global_system_variables.table_plugin);
if (global_system_variables.tmp_table_plugin)
thd->variables.tmp_table_plugin=
if (global_system_variables.tmp_table_plugin)
thd->variables.tmp_table_plugin=
intern_plugin_lock(NULL, global_system_variables.tmp_table_plugin);
intern_plugin_unlock(NULL, old_table_plugin);
intern_plugin_unlock(NULL, old_tmp_table_plugin);
mysql_mutex_unlock(&LOCK_plugin);
#ifdef WITH_WSREP
intern_plugin_unlock(NULL, old_table_plugin);
intern_plugin_unlock(NULL, old_tmp_table_plugin);
mysql_mutex_unlock(&LOCK_plugin);
}
#endif
DBUG_VOID_RETURN;
}

36
sql/sql_prepare.cc

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2013, Oracle and/or its affiliates.
Copyright (c) 2008, 2013, Monty Program Ab
Copyright (c) 2008, 2014, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -117,6 +117,7 @@ When one supplies long data for a placeholder:
#include "lock.h" // MYSQL_OPEN_FORCE_SHARED_MDL
#include "sql_handler.h"
#include "transaction.h" // trans_rollback_implicit
#include "wsrep_mysqld.h"
/**
A result class used to send cursor rows using the binary protocol.
@ -3547,9 +3548,7 @@ Prepared_statement::set_parameters(String *expanded_query,
return res;
}
#ifdef WITH_WSREP
void wsrep_replay_transaction(THD *thd);
#endif /* WITH_WSREP */
/**
Execute a prepared statement. Re-prepare it a limited number
of times if necessary.
@ -3629,20 +3628,25 @@ reexecute:
thd->m_reprepare_observer= NULL;
#ifdef WITH_WSREP
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
switch (thd->wsrep_conflict_state)
{
case CERT_FAILURE:
WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %ld err: %d",
thd->thread_id, thd->get_stmt_da()->sql_errno() );
thd->wsrep_conflict_state = NO_CONFLICT;
break;
case MUST_REPLAY:
(void)wsrep_replay_transaction(thd);
default: break;
if (WSREP_ON)
{
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
switch (thd->wsrep_conflict_state)
{
case CERT_FAILURE:
WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %ld err: %d",
thd->thread_id, thd->get_stmt_da()->sql_errno() );
thd->wsrep_conflict_state = NO_CONFLICT;
break;
case MUST_REPLAY:
(void)wsrep_replay_transaction(thd);
default:
break;
}
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
#endif /* WITH_WSREP */
if ((sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) &&

10
sql/sql_repl.cc

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2008, 2013, Monty Program Ab
Copyright (c) 2008, 2014, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -2946,15 +2946,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
err:
unlock_slave_threads(mi);
#ifdef WITH_WSREP
if (WSREP(thd))
thd_proc_info(thd, "exit stop_slave()");
else
thd_proc_info(thd, 0);
#else /* WITH_WSREP */
thd_proc_info(thd, 0);
#endif /* WITH_WSREP */
if (slave_errno)
{

10
sql/sql_show.cc

@ -2972,13 +2972,9 @@ static bool show_status_array(THD *thd, const char *wild,
DBUG_ASSERT(name_buffer[0] >= 'a');
DBUG_ASSERT(name_buffer[0] <= 'z');
#ifdef WITH_WSREP
// TODO: remove once lp:1306875 has been addressed.
if (status_var && (is_wsrep_var == FALSE))
#else
/* traditionally status variables have a first letter uppercased */
if (status_var)
#endif /* WITH_WSREP */
// WSREP_TODO: remove once lp:1306875 has been addressed.
if (IF_WSREP(WSREP_ON && is_wsrep_var == FALSE, 1) &&
status_var)
name_buffer[0]-= 'a' - 'A';
}

76
sql/sql_table.cc

@ -5265,58 +5265,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
DBUG_ENTER("mysql_create_like_table");
#ifdef WITH_WSREP
if (WSREP(thd) && !thd->wsrep_applier)
{
TABLE *tmp_table;
bool is_tmp_table= FALSE;
for (tmp_table= thd->temporary_tables; tmp_table; tmp_table=tmp_table->next)
{
if (!strcmp(src_table->db, tmp_table->s->db.str) &&
!strcmp(src_table->table_name, tmp_table->s->table_name.str))
{
is_tmp_table= TRUE;
break;
}
}
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
thd->query());
}
else if (!is_tmp_table)
{
/* this is straight CREATE TABLE LIKE... eith no tmp tables */
WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
}
else
{
/* here we have CREATE TABLE LIKE <temporary table>
the temporary table definition will be needed in slaves to
enable the create to succeed
*/
TABLE_LIST tbl;
bzero((void*) &tbl, sizeof(tbl));
tbl.db= src_table->db;
tbl.table_name= tbl.alias= src_table->table_name;
tbl.table= tmp_table;
char buf[2048];
String query(buf, sizeof(buf), system_charset_info);
query.length(0); // Have to zero it since constructor doesn't
(void) store_create_info(thd, &tbl, &query, NULL, TRUE, FALSE);
WSREP_DEBUG("TMP TABLE: %s", query.ptr());
thd->wsrep_TOI_pre_query= query.ptr();
thd->wsrep_TOI_pre_query_len= query.length();
WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
thd->wsrep_TOI_pre_query= NULL;
thd->wsrep_TOI_pre_query_len= 0;
}
}
if (WSREP_ON && !thd->wsrep_applier &&
wsrep_create_like_table(thd, table, src_table, create_info))
goto end;
#endif
/*
@ -5580,14 +5531,9 @@ err:
thd->query_length(), is_trans))
res= 1;
}
DBUG_RETURN(res);
#ifdef WITH_WSREP
error:
thd->wsrep_TOI_pre_query= NULL;
DBUG_RETURN(TRUE);
#endif /* WITH_WSREP */
end:
DBUG_RETURN(res);
}
@ -8119,10 +8065,6 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
: HA_EXTRA_FORCE_REOPEN;
DBUG_ENTER("simple_rename_or_index_change");
#ifdef WITH_WSREP
bool do_log_write(true);
#endif /* WITH_WSREP */
if (keys_onoff != Alter_info::LEAVE_AS_IS)
{
if (wait_while_table_is_used(thd, table, extra_func))
@ -8182,13 +8124,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
if (!error)
{
#ifdef WITH_WSREP
if (!WSREP(thd) || do_log_write) {
#endif /* WITH_WSREP */
error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
#ifdef WITH_WSREP
}
#endif /* !WITH_WSREP */
error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
if (!error)
my_ok(thd);

60
sql/sql_trigger.cc

@ -434,14 +434,9 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
binlogged, so they share the same danger, so trust_function_creators
applies to them too.
*/
#ifdef WITH_WSREP
if (!trust_function_creators &&
(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
if (!trust_function_creators &&
IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()), mysql_bin_log.is_open()) &&
!(thd->security_ctx->master_access & SUPER_ACL))
#else
if (!trust_function_creators && mysql_bin_log.is_open() &&
!(thd->security_ctx->master_access & SUPER_ACL))
#endif /* WITH_WSREP */
{
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
DBUG_RETURN(TRUE);
@ -2443,55 +2438,4 @@ bool load_table_name_for_trigger(THD *thd,
DBUG_RETURN(FALSE);
}
#ifdef WITH_WSREP
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
{
LEX *lex= thd->lex;
String stmt_query;
LEX_STRING definer_user;
LEX_STRING definer_host;
if (!lex->definer)
{
if (!thd->slave_thread)
{
if (!(lex->definer= create_default_definer(thd, false)))
return 1;
}
}
if (lex->definer)
{
/* SUID trigger. */
definer_user= lex->definer->user;
definer_host= lex->definer->host;
}
else
{
/* non-SUID trigger. */
definer_user.str= 0;
definer_user.length= 0;
definer_host.str= 0;
definer_host.length= 0;
}
stmt_query.append(STRING_WITH_LEN("CREATE "));
append_definer(thd, &stmt_query, &definer_user, &definer_host);
LEX_STRING stmt_definition;
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
stmt_definition.length= thd->lex->stmt_definition_end
- thd->lex->stmt_definition_begin;
trim_whitespace(thd->charset(), & stmt_definition);
stmt_query.append(stmt_definition.str, stmt_definition.length);
return wsrep_to_buf_helper(thd, stmt_query.c_ptr(), stmt_query.length(),
buf, buf_len);
}
#endif /* WITH_WSREP */

2
sql/sql_truncate.cc

@ -24,9 +24,7 @@
#include "sql_acl.h" // DROP_ACL
#include "sql_parse.h" // check_one_table_access()
#include "sql_truncate.h"
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif /* WITH_WSREP */
#include "sql_show.h" //append_identifier()

23
sql/sql_update.cc

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2011, 2013, Monty Program Ab.
Copyright (c) 2011, 2014, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -976,11 +976,8 @@ int mysql_update(THD *thd,
*/
if ((error < 0) || thd->transaction.stmt.modified_non_trans_table)
{
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if (IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= 0;
if (error < 0)
@ -2223,11 +2220,8 @@ void multi_update::abort_result_set()
The query has to binlog because there's a modified non-transactional table
either from the query's list or via a stored routine: bug#13270,23333
*/
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if (IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
/*
THD::killed status might not have been set ON at time of an error
@ -2496,11 +2490,8 @@ bool multi_update::send_eof()
if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table)
{
#ifdef WITH_WSREP
if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())
#else
if (mysql_bin_log.is_open())
#endif
if (IF_WSREP((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()),
mysql_bin_log.is_open()))
{
int errcode= 0;
if (local_error == 0)

2
sql/sys_vars.cc

@ -3338,9 +3338,7 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type)
{
thd->variables.option_bits&= ~OPTION_AUTOCOMMIT;
thd->mdl_context.release_transactional_locks();
#ifdef WITH_WSREP
WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id);
#endif /* WITH_WSREP */
return true;
}
/*

2
sql/table.cc

@ -40,9 +40,7 @@
#include "sql_statistics.h"
#include "discover.h"
#include "mdl.h" // MDL_wait_for_graph_visitor
#ifdef WITH_WSREP
#include "ha_partition.h"
#endif /* WITH_WSREP */
/* INFORMATION_SCHEMA name */
LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")};

42
sql/transaction.cc

@ -98,7 +98,8 @@ static bool xa_trans_force_rollback(THD *thd)
*/
thd->transaction.xid_state.rm_error= 0;
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
if (ha_rollback_trans(thd, true))
{
@ -139,14 +140,16 @@ bool trans_begin(THD *thd, uint flags)
{
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= MY_TEST(ha_commit_trans(thd, TRUE));
#ifdef WITH_WSREP
wsrep_post_commit(thd, TRUE);
if (WSREP_ON)
wsrep_post_commit(thd, TRUE);
#endif /* WITH_WSREP */
}
@ -228,14 +231,16 @@ bool trans_commit(THD *thd)
DBUG_RETURN(TRUE);
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= ha_commit_trans(thd, TRUE);
#ifdef WITH_WSREP
wsrep_post_commit(thd, TRUE);
if (WSREP_ON)
wsrep_post_commit(thd, TRUE);
#endif /* WITH_WSREP */
/*
if res is non-zero, then ha_commit_trans has rolled back the
@ -283,14 +288,16 @@ bool trans_commit_implicit(THD *thd)
if (!thd->locked_tables_mode)
thd->variables.option_bits&= ~OPTION_TABLE_LOCK;
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
res= MY_TEST(ha_commit_trans(thd, TRUE));
#ifdef WITH_WSREP
wsrep_post_commit(thd, TRUE);
if (WSREP_ON)
wsrep_post_commit(thd, TRUE);
#endif /* WITH_WSREP */
}
@ -331,7 +338,8 @@ bool trans_rollback(THD *thd)
DBUG_RETURN(TRUE);
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
thd->server_status&=
~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
@ -424,7 +432,8 @@ bool trans_commit_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
#ifdef WITH_WSREP
wsrep_register_hton(thd, FALSE);
if (WSREP_ON)
wsrep_register_hton(thd, FALSE);
#endif /* WITH_WSREP */
res= ha_commit_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
@ -432,7 +441,8 @@ bool trans_commit_stmt(THD *thd)
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
#ifdef WITH_WSREP
wsrep_post_commit(thd, FALSE);
if (WSREP_ON)
wsrep_post_commit(thd, FALSE);
#endif /* WITH_WSREP */
}
}
@ -475,7 +485,8 @@ bool trans_rollback_stmt(THD *thd)
if (thd->transaction.stmt.ha_list)
{
#ifdef WITH_WSREP
wsrep_register_hton(thd, FALSE);
if (WSREP_ON)
wsrep_register_hton(thd, FALSE);
#endif /* WITH_WSREP */
ha_rollback_trans(thd, FALSE);
if (! thd->in_active_multi_stmt_transaction())
@ -855,13 +866,15 @@ bool trans_xa_commit(THD *thd)
else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
{
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
int r= ha_commit_trans(thd, TRUE);
if ((res= MY_TEST(r)))
my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
#ifdef WITH_WSREP
wsrep_post_commit(thd, TRUE);
if (WSREP_ON)
wsrep_post_commit(thd, TRUE);
#endif /* WITH_WSREP */
}
else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
@ -882,7 +895,8 @@ bool trans_xa_commit(THD *thd)
thd->variables.lock_wait_timeout))
{
#ifdef WITH_WSREP
wsrep_register_hton(thd, TRUE);
if (WSREP_ON)
wsrep_register_hton(thd, TRUE);
#endif /* WITH_WSREP */
ha_rollback_trans(thd, TRUE);
my_error(ER_XAER_RMERR, MYF(0));

3
sql/tztime.cc

@ -2711,7 +2711,8 @@ main(int argc, char **argv)
#ifdef WITH_WSREP
// Replicate MyISAM DDL for this session, cf. lp:1161432
printf("SET GLOBAL wsrep_replicate_myisam= ON;\n");
// timezone info unfixable in XtraDB Cluster
printf("SET GLOBAL wsrep_replicate_myisam= ON;\n");
#endif /* WITH_WSREP */
if (argc == 1 && !opt_leap)

8
sql/wsrep_binlog.cc

@ -15,7 +15,9 @@
#include "wsrep_binlog.h"
#include "wsrep_priv.h"
#include "log.h"
extern handlerton *binlog_hton;
/*
Write the contents of a cache to a memory buffer.
@ -320,7 +322,6 @@ void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len)
filename, errno, strerror(errno));
}
}
extern handlerton *binlog_hton;
/*
wsrep exploits binlog's caches even if binlogging itself is not
@ -406,3 +407,8 @@ cleanup:
// close file
if (of) fclose(of);
}
void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end)
{
thd->binlog_flush_pending_rows_event(stmt_end);
}

2
sql/wsrep_hton.cc

@ -539,7 +539,7 @@ static int wsrep_hton_init(void *p)
wsrep_hton= (handlerton *)p;
//wsrep_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO;
wsrep_hton->state= SHOW_OPTION_YES;
wsrep_hton->db_type=DB_TYPE_WSREP;
wsrep_hton->db_type=(legacy_db_type)0;
wsrep_hton->savepoint_offset= sizeof(my_off_t);
wsrep_hton->close_connection= wsrep_close_connection;
wsrep_hton->savepoint_set= wsrep_savepoint_set;

880
sql/wsrep_mysqld.cc

@ -1,4 +1,4 @@
/* Copyright 2008-2013 Codership Oy <http://www.codership.com>
/* Copyright 2008-2014 Codership Oy <http://www.codership.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,6 +16,13 @@
#include <mysqld.h>
#include <sql_class.h>
#include <sql_parse.h>
#include "slave.h"
#include "rpl_mi.h"
#include "sql_repl.h"
#include "rpl_filter.h"
#include "sql_callback.h"
#include "sp_head.h"
#include "sp.h"
#include "wsrep_priv.h"
#include "wsrep_thd.h"
#include "wsrep_sst.h"
@ -40,6 +47,13 @@ my_bool wsrep_preordered_opt= FALSE;
* Begin configuration options and their default values
*/
extern int wsrep_replaying;
extern ulong wsrep_running_threads;
extern ulong my_bind_addr;
extern my_bool plugins_are_initialized;
extern uint kill_cached_threads;
extern mysql_cond_t COND_thread_cache;
const char* wsrep_data_home_dir = NULL;
const char* wsrep_dbug_option = "";
@ -1292,7 +1306,7 @@ static int wsrep_TOI_begin(THD *thd, char *db_, char *table_,
{
thd->wsrep_exec_mode= TOTAL_ORDER;
wsrep_to_isolation++;
if (buf) my_free(buf);
my_free(buf);
wsrep_keys_free(&key_arr);
WSREP_DEBUG("TO BEGIN: %lld, %d",(long long)wsrep_thd_trx_seqno(thd),
thd->wsrep_exec_mode);
@ -1407,13 +1421,14 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_,
const TABLE_LIST* table_list)
{
int ret= 0;
/*
No isolation for applier or replaying threads.
*/
if (thd->wsrep_exec_mode == REPL_RECV) return 0;
if (thd->wsrep_exec_mode == REPL_RECV)
return 0;
int ret= 0;
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
if (thd->wsrep_conflict_state == MUST_ABORT)
@ -1501,8 +1516,8 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
) {
if (!WSREP_ON) return FALSE;
THD *request_thd = requestor_ctx->wsrep_get_thd();
THD *granted_thd = ticket->get_ctx()->wsrep_get_thd();
THD *request_thd = requestor_ctx->get_thd();
THD *granted_thd = ticket->get_ctx()->get_thd();
bool ret = FALSE;
mysql_mutex_lock(&request_thd->LOCK_wsrep_thd);
@ -1560,3 +1575,856 @@ wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
}
return ret;
}
pthread_handler_t start_wsrep_THD(void *arg)
{
THD *thd;
rpl_sql_thread_info sql_info(NULL);
wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
if (my_thread_init())
{
WSREP_ERROR("Could not initialize thread");
return(NULL);
}
if (!(thd= new THD(true)))
{
return(NULL);
}
mysql_mutex_lock(&LOCK_thread_count);
thd->thread_id=thread_id++;
thd->real_id=pthread_self(); // Keep purify happy
thread_count++;
thread_created++;
threads.append(thd);
my_net_init(&thd->net,(st_vio*) 0, MYF(0));
DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id));
thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer();
(void) mysql_mutex_unlock(&LOCK_thread_count);
/* from bootstrap()... */
thd->bootstrap=1;
thd->max_client_packet_length= thd->net.max_packet;
thd->security_ctx->master_access= ~(ulong)0;
thd->system_thread_info.rpl_sql_info= &sql_info;
/* from handle_one_connection... */
pthread_detach_this_thread();
mysql_thread_set_psi_id(thd->thread_id);
thd->thr_create_utime= microsecond_interval_timer();
if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
{
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
return(NULL);
}
// </5.1.17>
/*
handle_one_connection() is normally the only way a thread would
start and would always be on the very high end of the stack ,
therefore, the thread stack always starts at the address of the
first local variable of handle_one_connection, which is thd. We
need to know the start of the stack so that we could check for
stack overruns.
*/
DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n",
(long long)thd->thread_id));
/* now that we've called my_thread_init(), it is safe to call DBUG_* */
thd->thread_stack= (char*) &thd;
if (thd->store_globals())
{
close_connection(thd, ER_OUT_OF_RESOURCES);
statistic_increment(aborted_connects,&LOCK_status);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
delete thd;
return(NULL);
}
thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
thd->security_ctx->skip_grants();
/* handle_one_connection() again... */
//thd->version= refresh_version;
thd->proc_info= 0;
thd->set_command(COM_SLEEP);
thd->set_time();
thd->init_for_queries();
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads++;
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
processor(thd);
close_connection(thd, 0);
mysql_mutex_lock(&LOCK_thread_count);
wsrep_running_threads--;
WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
mysql_cond_broadcast(&COND_thread_count);
mysql_mutex_unlock(&LOCK_thread_count);
// Note: We can't call THD destructor without crashing
// if plugins have not been initialized. However, in most of the
// cases this means that pre SE initialization SST failed and
// we are going to exit anyway.
if (plugins_are_initialized)
{
net_end(&thd->net);
MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1));
}
else
{
// TODO: lightweight cleanup to get rid of:
// 'Error in my_thread_global_end(): 2 threads didn't exit'
// at server shutdown
}
my_thread_end();
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_lock(&LOCK_thread_count);
delete thd;
thread_count--;
mysql_mutex_unlock(&LOCK_thread_count);
}
return(NULL);
}
/**/
static bool abort_replicated(THD *thd)
{
bool ret_code= false;
if (thd->wsrep_query_state== QUERY_COMMITTING)
{
if (wsrep_debug) WSREP_INFO("aborting replicated trx: %lu", thd->real_id);
(void)wsrep_abort_thd(thd, thd, TRUE);
ret_code= true;
}
return ret_code;
}
/**/
static inline bool is_client_connection(THD *thd)
{
return (thd->wsrep_client_thread && thd->variables.wsrep_on);
}
static inline bool is_replaying_connection(THD *thd)
{
bool ret;
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false;
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
return ret;
}
static inline bool is_committing_connection(THD *thd)
{
bool ret;
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false;
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
return ret;
}
static bool have_client_connections()
{
THD *tmp;
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION)
{
(void)abort_replicated(tmp);
return true;
}
}
return false;
}
/*
returns the number of wsrep appliers running.
However, the caller (thd parameter) is not taken in account
*/
static int have_wsrep_appliers(THD *thd)
{
int ret= 0;
THD *tmp;
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
ret+= (tmp != thd && tmp->wsrep_applier);
}
return ret;
}
static void wsrep_close_thread(THD *thd)
{
thd->killed= KILL_CONNECTION;
MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd));
if (thd->mysys_var)
{
thd->mysys_var->abort=1;
mysql_mutex_lock(&thd->mysys_var->mutex);
if (thd->mysys_var->current_cond)
{
mysql_mutex_lock(thd->mysys_var->current_mutex);
mysql_cond_broadcast(thd->mysys_var->current_cond);
mysql_mutex_unlock(thd->mysys_var->current_mutex);
}
mysql_mutex_unlock(&thd->mysys_var->mutex);
}
}
static my_bool have_committing_connections()
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
if (!is_client_connection(tmp))
continue;
if (is_committing_connection(tmp))
{
mysql_mutex_unlock(&LOCK_thread_count);
return TRUE;
}
}
mysql_mutex_unlock(&LOCK_thread_count);
return FALSE;
}
int wsrep_wait_committing_connections_close(int wait_time)
{
int sleep_time= 100;
while (have_committing_connections() && wait_time > 0)
{
WSREP_DEBUG("wait for committing transaction to close: %d", wait_time);
my_sleep(sleep_time);
wait_time -= sleep_time;
}
if (have_committing_connections())
{
return 1;
}
return 0;
}
void wsrep_close_client_connections(my_bool wait_to_end)
{
/*
First signal all threads that it's time to die
*/
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
bool kill_cached_threads_saved= kill_cached_threads;
kill_cached_threads= true; // prevent future threads caching
mysql_cond_broadcast(&COND_thread_cache); // tell cached threads to die
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (!is_client_connection(tmp))
continue;
if (is_replaying_connection(tmp))
{
tmp->killed= KILL_CONNECTION;
continue;
}
/* replicated transactions must be skipped */
if (abort_replicated(tmp))
continue;
WSREP_DEBUG("closing connection %ld", tmp->thread_id);
wsrep_close_thread(tmp);
}
mysql_mutex_unlock(&LOCK_thread_count);
if (thread_count)
sleep(2); // Give threads time to die
mysql_mutex_lock(&LOCK_thread_count);
/*
Force remaining threads to die by closing the connection to the client
*/
I_List_iterator<THD> it2(threads);
while ((tmp=it2++))
{
#ifndef __bsdi__ // Bug in BSDI kernel
if (is_client_connection(tmp) &&
!abort_replicated(tmp) &&
!is_replaying_connection(tmp))
{
WSREP_INFO("killing local connection: %ld",tmp->thread_id);
close_connection(tmp,0);
}
#endif
}
DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
if (wsrep_debug)
WSREP_INFO("waiting for client connections to close: %u", thread_count);
while (wait_to_end && have_client_connections())
{
mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
DBUG_PRINT("quit",("One thread died (count=%u)", thread_count));
}
kill_cached_threads= kill_cached_threads_saved;
mysql_mutex_unlock(&LOCK_thread_count);
/* All client connection threads have now been aborted */
}
void wsrep_close_applier(THD *thd)
{
WSREP_DEBUG("closing applier %ld", thd->thread_id);
wsrep_close_thread(thd);
}
void wsrep_close_threads(THD *thd)
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++))
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (tmp->wsrep_applier && tmp != thd)
{
WSREP_DEBUG("closing wsrep thread %ld", tmp->thread_id);
wsrep_close_thread (tmp);
}
}
mysql_mutex_unlock(&LOCK_thread_count);
}
void wsrep_close_applier_threads(int count)
{
THD *tmp;
mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
I_List_iterator<THD> it(threads);
while ((tmp=it++) && count)
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
/* We skip slave threads & scheduler on this first loop through. */
if (tmp->wsrep_applier)
{
WSREP_DEBUG("closing wsrep applier thread %ld", tmp->thread_id);
tmp->wsrep_applier_closing= TRUE;
count--;
}
}
mysql_mutex_unlock(&LOCK_thread_count);
}
void wsrep_wait_appliers_close(THD *thd)
{
/* Wait for wsrep appliers to gracefully exit */
mysql_mutex_lock(&LOCK_thread_count);
while (have_wsrep_appliers(thd) > 1)
// 1 is for rollbacker thread which needs to be killed explicitly.
// This gotta be fixed in a more elegant manner if we gonna have arbitrary
// number of non-applier wsrep threads.
{
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_unlock(&LOCK_thread_count);
my_sleep(100);
mysql_mutex_lock(&LOCK_thread_count);
}
else
mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
DBUG_PRINT("quit",("One applier died (count=%u)",thread_count));
}
mysql_mutex_unlock(&LOCK_thread_count);
/* Now kill remaining wsrep threads: rollbacker */
wsrep_close_threads (thd);
/* and wait for them to die */
mysql_mutex_lock(&LOCK_thread_count);
while (have_wsrep_appliers(thd) > 0)
{
if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION)
{
mysql_mutex_unlock(&LOCK_thread_count);
my_sleep(100);
mysql_mutex_lock(&LOCK_thread_count);
}
else
mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
}
mysql_mutex_unlock(&LOCK_thread_count);
/* All wsrep applier threads have now been aborted. However, if this thread
is also applier, we are still running...
*/
}
void wsrep_kill_mysql(THD *thd)
{
if (mysqld_server_started)
{
if (!shutdown_in_progress)
{
WSREP_INFO("starting shutdown");
kill_mysql();
}
}
else
{
unireg_abort(1);
}
}
int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len)
{
String log_query;
sp_head *sp = thd->lex->sphead;
ulong saved_mode= thd->variables.sql_mode;
String retstr(64);
retstr.set_charset(system_charset_info);
log_query.set_charset(system_charset_info);
if (sp->m_type == TYPE_ENUM_FUNCTION)
{
sp_returns_type(thd, retstr, sp);
}
if (!create_string(thd, &log_query,
sp->m_type,
(sp->m_explicit_name ? sp->m_db.str : NULL),
(sp->m_explicit_name ? sp->m_db.length : 0),
sp->m_name.str, sp->m_name.length,
sp->m_params.str, sp->m_params.length,
retstr.c_ptr(), retstr.length(),
sp->m_body.str, sp->m_body.length,
sp->m_chistics, &(thd->lex->definer->user),
&(thd->lex->definer->host),
saved_mode))
{
WSREP_WARN("SP create string failed: %s", thd->query());
return 1;
}
return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len);
}
extern int wsrep_on(void *thd)
{
return (int)(WSREP(((THD*)thd)));
}
extern "C" bool wsrep_thd_is_wsrep_on(THD *thd)
{
return thd->variables.wsrep_on;
}
extern "C" bool wsrep_consistency_check(void *thd)
{
return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
}
extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode)
{
thd->wsrep_exec_mode= mode;
}
extern "C" void wsrep_thd_set_query_state(
THD *thd, enum wsrep_query_state state)
{
thd->wsrep_query_state= state;
}
extern "C" void wsrep_thd_set_conflict_state(
THD *thd, enum wsrep_conflict_state state)
{
thd->wsrep_conflict_state= state;
}
extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd)
{
return thd->wsrep_exec_mode;
}
extern "C" const char *wsrep_thd_exec_mode_str(THD *thd)
{
return
(!thd) ? "void" :
(thd->wsrep_exec_mode == LOCAL_STATE) ? "local" :
(thd->wsrep_exec_mode == REPL_RECV) ? "applier" :
(thd->wsrep_exec_mode == TOTAL_ORDER) ? "total order" :
(thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void";
}
extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd)
{
return thd->wsrep_query_state;
}
extern "C" const char *wsrep_thd_query_state_str(THD *thd)
{
return
(!thd) ? "void" :
(thd->wsrep_query_state == QUERY_IDLE) ? "idle" :
(thd->wsrep_query_state == QUERY_EXEC) ? "executing" :
(thd->wsrep_query_state == QUERY_COMMITTING) ? "committing" :
(thd->wsrep_query_state == QUERY_EXITING) ? "exiting" :
(thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back" : "void";
}
extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd)
{
return thd->wsrep_conflict_state;
}
extern "C" const char *wsrep_thd_conflict_state_str(THD *thd)
{
return
(!thd) ? "void" :
(thd->wsrep_conflict_state == NO_CONFLICT) ? "no conflict" :
(thd->wsrep_conflict_state == MUST_ABORT) ? "must abort" :
(thd->wsrep_conflict_state == ABORTING) ? "aborting" :
(thd->wsrep_conflict_state == MUST_REPLAY) ? "must replay" :
(thd->wsrep_conflict_state == REPLAYING) ? "replaying" :
(thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying" :
(thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void";
}
extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd)
{
return &thd->wsrep_ws_handle;
}
extern "C" void wsrep_thd_LOCK(THD *thd)
{
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
}
extern "C" void wsrep_thd_UNLOCK(THD *thd)
{
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
extern "C" time_t wsrep_thd_query_start(THD *thd)
{
return thd->query_start();
}
extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd)
{
return thd->wsrep_rand;
}
extern "C" my_thread_id wsrep_thd_thread_id(THD *thd)
{
return thd->thread_id;
}
extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd)
{
return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED;
}
extern "C" query_id_t wsrep_thd_query_id(THD *thd)
{
return thd->query_id;
}
extern "C" char *wsrep_thd_query(THD *thd)
{
return (thd) ? thd->query() : NULL;
}
extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd)
{
return thd->wsrep_last_query_id;
}
extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id)
{
thd->wsrep_last_query_id= id;
}
extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
{
if (signal)
{
mysql_mutex_lock(&thd->LOCK_thd_data);
thd->awake(KILL_QUERY);
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
else
{
mysql_mutex_lock(&LOCK_wsrep_replaying);
mysql_cond_broadcast(&COND_wsrep_replaying);
mysql_mutex_unlock(&LOCK_wsrep_replaying);
}
}
extern "C" int wsrep_thd_retry_counter(THD *thd)
{
return(thd->wsrep_retry_counter);
}
extern int
wsrep_trx_order_before(void *thd1, void *thd2)
{
if (wsrep_thd_trx_seqno((THD*)thd1) < wsrep_thd_trx_seqno((THD*)thd2)) {
WSREP_DEBUG("BF conflict, order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno((THD*)thd1),
(long long)wsrep_thd_trx_seqno((THD*)thd2));
return 1;
}
WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno((THD*)thd1),
(long long)wsrep_thd_trx_seqno((THD*)thd2));
return 0;
}
extern "C" int
wsrep_trx_is_aborting(void *thd_ptr)
{
if (thd_ptr) {
if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) ||
(((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) {
return 1;
}
}
return 0;
}
my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables)
{
int opt_readonly_saved = opt_readonly;
ulong flag_saved = (ulong)(thd->security_ctx->master_access & SUPER_ACL);
opt_readonly = 0;
thd->security_ctx->master_access &= ~SUPER_ACL;
my_bool ret = !deny_updates_if_read_only_option(thd, all_tables);
opt_readonly = opt_readonly_saved;
thd->security_ctx->master_access |= flag_saved;
return ret;
}
void wsrep_copy_query(THD *thd)
{
thd->wsrep_retry_command = thd->get_command();
thd->wsrep_retry_query_len = thd->query_length();
thd->wsrep_retry_query = (char *)my_malloc(
thd->wsrep_retry_query_len + 1, MYF(0));
strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len);
thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0';
}
bool wsrep_is_show_query(enum enum_sql_command command)
{
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0;
}
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table,
HA_CREATE_INFO *create_info)
{
TABLE *tmp_table;
bool is_tmp_table= FALSE;
for (tmp_table= thd->temporary_tables; tmp_table; tmp_table=tmp_table->next)
{
if (!strcmp(src_table->db, tmp_table->s->db.str) &&
!strcmp(src_table->table_name, tmp_table->s->table_name.str))
{
is_tmp_table= TRUE;
break;
}
}
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
/* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
thd->query());
}
else if (!is_tmp_table)
{
/* this is straight CREATE TABLE LIKE... eith no tmp tables */
WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
}
else
{
/* here we have CREATE TABLE LIKE <temporary table>
the temporary table definition will be needed in slaves to
enable the create to succeed
*/
TABLE_LIST tbl;
bzero((void*) &tbl, sizeof(tbl));
tbl.db= src_table->db;
tbl.table_name= tbl.alias= src_table->table_name;
tbl.table= tmp_table;
char buf[2048];
String query(buf, sizeof(buf), system_charset_info);
query.length(0); // Have to zero it since constructor doesn't
(void) store_create_info(thd, &tbl, &query, NULL, TRUE, FALSE);
WSREP_DEBUG("TMP TABLE: %s", query.ptr());
thd->wsrep_TOI_pre_query= query.ptr();
thd->wsrep_TOI_pre_query_len= query.length();
WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
thd->wsrep_TOI_pre_query= NULL;
thd->wsrep_TOI_pre_query_len= 0;
}
return(false);
error:
thd->wsrep_TOI_pre_query= NULL;
return (true);
}
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len)
{
LEX *lex= thd->lex;
String stmt_query;
LEX_STRING definer_user;
LEX_STRING definer_host;
if (!lex->definer)
{
if (!thd->slave_thread)
{
if (!(lex->definer= create_default_definer(thd, false)))
return 1;
}
}
if (lex->definer)
{
/* SUID trigger. */
definer_user= lex->definer->user;
definer_host= lex->definer->host;
}
else
{
/* non-SUID trigger. */
definer_user.str= 0;
definer_user.length= 0;
definer_host.str= 0;
definer_host.length= 0;
}
stmt_query.append(STRING_WITH_LEN("CREATE "));
append_definer(thd, &stmt_query, &definer_user, &definer_host);
LEX_STRING stmt_definition;
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
stmt_definition.length= thd->lex->stmt_definition_end
- thd->lex->stmt_definition_begin;
trim_whitespace(thd->charset(), & stmt_definition);
stmt_query.append(stmt_definition.str, stmt_definition.length);
return wsrep_to_buf_helper(thd, stmt_query.c_ptr(), stmt_query.length(),
buf, buf_len);
}

57
sql/wsrep_mysqld.h

@ -13,14 +13,18 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef WSREP_MYSQLD_H
#include <wsrep.h>
#if !defined(WSREP_MYSQLD_H) && defined(WITH_WSREP)
#define WSREP_MYSQLD_H
#include "mysqld.h"
typedef struct st_mysql_show_var SHOW_VAR;
#include <sql_priv.h>
//#include "rpl_gtid.h"
#include "../wsrep/wsrep_api.h"
#include "mdl.h"
#include "mysqld.h"
#include "sql_table.h"
#define WSREP_UNDEFINED_TRX_ID ULONGLONG_MAX
@ -59,6 +63,15 @@ enum wsrep_consistency_check_mode {
CONSISTENCY_CHECK_RUNNING,
};
struct wsrep_thd_shadow {
ulonglong options;
uint server_status;
enum wsrep_exec_mode wsrep_exec_mode;
Vio *vio;
ulong tx_isolation;
char *db;
size_t db_length;
};
// Global wsrep parameters
extern wsrep_t* wsrep;
@ -203,12 +216,6 @@ extern wsrep_seqno_t wsrep_locked_seqno;
fun("WSREP: %s", msg); \
}
#define WSREP_DEBUG(...) \
if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
#define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__)
#define WSREP_WARN(...) WSREP_LOG(sql_print_warning, ##__VA_ARGS__)
#define WSREP_ERROR(...) WSREP_LOG(sql_print_error, ##__VA_ARGS__)
#define WSREP_LOG_CONFLICT_THD(thd, role) \
WSREP_LOG(sql_print_information, \
"%s: \n " \
@ -279,6 +286,7 @@ extern int wsrep_to_isolation;
extern rpl_sidno wsrep_sidno;
#endif /* GTID_SUPPORT */
extern my_bool wsrep_preordered_opt;
extern handlerton *wsrep_hton;
#ifdef HAVE_PSI_INTERFACE
extern PSI_mutex_key key_LOCK_wsrep_ready;
@ -317,4 +325,37 @@ const wsrep_uuid_t* wsrep_xid_uuid(const xid_t*);
wsrep_seqno_t wsrep_xid_seqno(const xid_t*);
extern "C" int wsrep_is_wsrep_xid(const void* xid);
extern "C" my_thread_id wsrep_thd_thread_id(THD *thd);
extern "C" char *wsrep_thd_query(THD *thd);
extern bool
wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
MDL_ticket *ticket);
IO_CACHE * get_trans_log(THD * thd);
bool wsrep_trans_cache_is_empty(THD *thd);
void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end);
void thd_binlog_rollback_stmt(THD * thd);
void thd_binlog_trx_reset(THD * thd);
typedef void (*wsrep_thd_processor_fun)(THD *);
pthread_handler_t start_wsrep_THD(void *arg);
int wsrep_wait_committing_connections_close(int wait_time);
void wsrep_close_client_connections(my_bool wait_to_end);
void wsrep_close_applier(THD *thd);
void wsrep_close_applier_threads(int count);
void wsrep_wait_appliers_close(THD *thd);
void wsrep_kill_mysql(THD *thd);
void wsrep_close_threads(THD *thd);
int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len);
my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables);
void wsrep_copy_query(THD *thd);
bool wsrep_is_show_query(enum enum_sql_command command);
void wsrep_replay_transaction(THD *thd);
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
TABLE_LIST* src_table,
HA_CREATE_INFO *create_info);
int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
extern my_bool deny_updates_if_read_only_option(THD *thd,
TABLE_LIST *all_tables);
#endif /* WSREP_MYSQLD_H */

2
sql/wsrep_sst.h

@ -13,7 +13,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#ifndef WSREP_SST_H
#if !defined(WSREP_SST_H) && defined(WITH_WSREP)
#define WSREP_SST_H
#include <mysql.h> // my_bool

2
sql/wsrep_thd.h

@ -13,7 +13,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#ifndef WSREP_THD_H
#if !defined(WSREP_THD_H) && defined(WITH_WSREP)
#define WSREP_THD_H
#include "sql_class.h"

2
sql/wsrep_var.h

@ -13,7 +13,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#ifndef WSREP_VAR_H
#if !defined (WSREP_VAR_H) && defined(WITH_WSREP)
#define WSREP_VAR_H
#define WSREP_CLUSTER_NAME "my_wsrep_cluster"

52
storage/innobase/handler/ha_innodb.cc

@ -17326,44 +17326,44 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
if (!thd) {
DBUG_PRINT("wsrep", ("no thd for conflicting lock"));
WSREP_WARN("no THD for trx: %llu", victim_trx->id);
WSREP_WARN("no THD for trx: %lu", victim_trx->id);
DBUG_RETURN(1);
}
if (!bf_thd) {
DBUG_PRINT("wsrep", ("no BF thd for conflicting lock"));
WSREP_WARN("no BF THD for trx: %llu", (bf_trx) ? bf_trx->id : 0);
WSREP_WARN("no BF THD for trx: %lu", (bf_trx) ? bf_trx->id : 0);
DBUG_RETURN(1);
}
WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu",
WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %lu",
signal, (long long)bf_seqno,
wsrep_thd_thread_id(thd),
victim_trx->id);
WSREP_DEBUG("Aborting query: %s",
WSREP_DEBUG("Aborting query: %s",
(thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
wsrep_thd_LOCK(thd);
if (wsrep_thd_query_state(thd) == QUERY_EXITING) {
WSREP_DEBUG("kill trx EXITING for %llu", victim_trx->id);
WSREP_DEBUG("kill trx EXITING for %lu", victim_trx->id);
wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0);
}
if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
WSREP_DEBUG("withdraw for BF trx: %llu, state: %d",
WSREP_DEBUG("withdraw for BF trx: %lu, state: %d",
victim_trx->id,
wsrep_thd_conflict_state(thd));
}
switch (wsrep_thd_conflict_state(thd)) {
case NO_CONFLICT:
case NO_CONFLICT:
wsrep_thd_set_conflict_state(thd, MUST_ABORT);
break;
case MUST_ABORT:
WSREP_DEBUG("victim %llu in MUST ABORT state",
WSREP_DEBUG("victim %lu in MUST ABORT state",
victim_trx->id);
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal);
@ -17372,7 +17372,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
case ABORTED:
case ABORTING: // fall through
default:
WSREP_DEBUG("victim %llu in state %d",
WSREP_DEBUG("victim %lu in state %d",
victim_trx->id, wsrep_thd_conflict_state(thd));
wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0);
@ -17385,7 +17385,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd));
WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu",
WSREP_DEBUG("kill trx QUERY_COMMITTING for %lu",
victim_trx->id);
if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
@ -17399,7 +17399,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
switch (rcode) {
case WSREP_WARNING:
WSREP_DEBUG("cancel commit warning: %llu",
WSREP_DEBUG("cancel commit warning: %lu",
victim_trx->id);
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal);
@ -17409,8 +17409,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
break;
default:
WSREP_ERROR(
"cancel commit bad exit: %d %llu",
rcode,
"cancel commit bad exit: %d %lu",
rcode,
victim_trx->id);
/* unable to interrupt, must abort */
/* note: kill_mysql() will block, if we cannot.
@ -17424,10 +17424,10 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_awake(thd, signal);
break;
case QUERY_EXEC:
/* it is possible that victim trx is itself waiting for some
/* it is possible that victim trx is itself waiting for some
* other lock. We need to cancel this waiting
*/
WSREP_DEBUG("kill trx QUERY_EXEC for %llu", victim_trx->id);
WSREP_DEBUG("kill trx QUERY_EXEC for %lu", victim_trx->id);
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
if (victim_trx->lock.wait_lock) {
@ -17444,7 +17444,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_awake(thd, signal);
} else {
/* abort currently executing query */
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld",
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld",
wsrep_thd_thread_id(thd)));
WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd));
@ -17464,8 +17464,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
{
bool skip_abort= false;
wsrep_aborting_thd_t abortees;
WSREP_DEBUG("kill IDLE for %llu", victim_trx->id);
WSREP_DEBUG("kill IDLE for %lu", victim_trx->id);
if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
WSREP_DEBUG("kill BF IDLE, seqno: %lld",
@ -17485,14 +17485,14 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
/* check if we have a kill message for this already */
if (abortees->aborting_thd == thd) {
skip_abort = true;
WSREP_WARN("duplicate thd aborter %lu",
WSREP_WARN("duplicate thd aborter %lu",
wsrep_thd_thread_id(thd));
}
abortees = abortees->next;
}
if (!skip_abort) {
wsrep_aborting_thd_t aborting = (wsrep_aborting_thd_t)
my_malloc(sizeof(struct wsrep_aborting_thd),
my_malloc(sizeof(struct wsrep_aborting_thd),
MYF(0));
aborting->aborting_thd = thd;
aborting->next = wsrep_aborting_thd;
@ -17512,22 +17512,24 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
break;
}
default:
WSREP_WARN("bad wsrep query state: %d",
WSREP_WARN("bad wsrep query state: %d",
wsrep_thd_query_state(thd));
wsrep_thd_UNLOCK(thd);
break;
}
DBUG_RETURN(0);
}
static int
wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
static
int
wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
my_bool signal)
{
DBUG_ENTER("wsrep_innobase_abort_thd");
trx_t* victim_trx = thd_to_trx(victim_thd);
trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
WSREP_DEBUG("abort transaction: BF: %s victim: %s",
WSREP_DEBUG("abort transaction: BF: %s victim: %s",
wsrep_thd_query(bf_thd),
wsrep_thd_query(victim_thd));

Loading…
Cancel
Save