diff options
author | Seppo Jaakola <seppo.jaakola@codership.com> | 2013-11-27 00:18:44 +0200 |
---|---|---|
committer | Seppo Jaakola <seppo.jaakola@codership.com> | 2013-11-27 00:18:44 +0200 |
commit | b098b7a84c374ee7e5a133cbf16be643609c1543 (patch) | |
tree | 7ccafb77802062c13a0fa5f2a316cd3cfbaca872 | |
parent | 6422d276fa8d1217aa68be1d90c712efa4d71409 (diff) | |
download | mariadb-git-b098b7a84c374ee7e5a133cbf16be643609c1543.tar.gz |
bzr merge -r3904..3928 lp:codership-mysql/5.5
This is now otherwise on level wsrep-25.9, but storage/innobase has not been fully merged
wsrep-5.5 is not good source for that, so we probably have to cherry pick innodb changes from wsrep-5.6
27 files changed, 1705 insertions, 82 deletions
diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 6a4e9a21049..c75b5f0b99b 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -17,7 +17,7 @@ # so WSREP_VERSION is produced regardless # Set the patch version -SET(WSREP_PATCH_VERSION "7.6") +SET(WSREP_PATCH_VERSION "9") # Obtain patch revision number SET(WSREP_PATCH_REVNO $ENV{WSREP_REV}) diff --git a/sql/log.cc b/sql/log.cc index d5cafb7de0a..9462c28301d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6195,6 +6195,7 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge) #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); diff --git a/sql/mdl.h b/sql/mdl.h index 498c9fc3ba3..8d22eff1eff 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -770,6 +770,13 @@ public: 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() { return MDL_savepoint(m_tickets[MDL_STATEMENT].front(), diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7b825574a7f..ecc29fe6303 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8453,8 +8453,9 @@ SHOW_VAR status_vars[]= { {"wsrep_cluster_state_uuid", (char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR}, {"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG}, {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR}, - {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG}, - {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG}, + {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG_NOFLUSH}, + {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG_NOFLUSH}, + {"wsrep_local_bf_aborts", (char*) &wsrep_show_bf_aborts, SHOW_FUNC}, {"wsrep_provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR}, {"wsrep_provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR}, {"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR}, @@ -9798,6 +9799,9 @@ void refresh_status(THD *thd) /* Reset some global variables */ reset_status_vars(); +#ifdef WITH_WSREP + wsrep->stats_reset(wsrep); +#endif /* WITH_WSREP */ /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters, 0); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f367ca293c8..7d87e245035 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1022,6 +1022,7 @@ THD::THD() wsrep_applier(is_applier), wsrep_applier_closing(FALSE), wsrep_client_thread(0), + wsrep_apply_toi(false), #endif m_parser_state(NULL), #if defined(ENABLED_DEBUG_SYNC) diff --git a/sql/sql_class.h b/sql/sql_class.h index 24132fb0913..946d69a2759 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -61,9 +61,12 @@ void set_thd_stage_info(void *thd, #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; @@ -2563,6 +2566,7 @@ public: const char* wsrep_TOI_pre_query; /* a query to apply before the actual TOI query */ size_t wsrep_TOI_pre_query_len; + bool wsrep_apply_toi; /* applier processing in TOI */ #endif /* WITH_WSREP */ /** Internal parser state. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3abedd40047..3b4c2dee2bb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1858,12 +1858,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if ((thd->wsrep_conflict_state != REPLAYING) && (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); thd->update_server_status(); thd->protocol->end_statement(); query_cache_end_of_result(thd); + } + else + { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); } - mysql_mutex_unlock(&thd->LOCK_wsrep_thd); - } else { /* if (WSREP(thd))... */ #endif /* WITH_WSREP */ DBUG_ASSERT(thd->derived_tables == NULL && @@ -3249,8 +3252,11 @@ case SQLCOM_PREPARE: else { #ifdef WITH_WSREP - if (!thd->is_current_stmt_binlog_format_row() || - !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) + /* 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)) WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, NULL) #endif /* WITH_WSREP */ @@ -5455,7 +5461,22 @@ finish: { thd->mdl_context.release_statement_locks(); } - WSREP_TO_ISOLATION_END + WSREP_TO_ISOLATION_END; + +#ifdef WITH_WSREP + /* + Force release of transactional locks if not in active MST and wsrep is on. + */ + if (WSREP(thd) && + ! thd->in_sub_stmt && + ! thd->in_active_multi_stmt_transaction() && + thd->mdl_context.has_transactional_locks()) + { + WSREP_DEBUG("Forcing release of transactional locks for thd %lu", + thd->thread_id); + thd->mdl_context.release_transactional_locks(); + } +#endif /* WITH_WSREP */ DBUG_RETURN(res || thd->is_error()); } @@ -6356,7 +6377,12 @@ void THD::reset_for_next_command(bool calculate_userstat) thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; #ifdef WITH_WSREP - if (WSREP(thd)) { + /* + Autoinc variables should be adjusted only for locally executed + 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_auto_increment_control) { if (thd->variables.auto_increment_offset != diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2c268207494..d113ea85a26 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4898,12 +4898,23 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, break; } } - if (!is_tmp_table) + 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; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 37e5f3315e3..18defddb36f 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4092,7 +4092,7 @@ static Sys_var_charptr Sys_wsrep_data_home_dir( static Sys_var_charptr Sys_wsrep_cluster_name( "wsrep_cluster_name", "Name for the cluster", - GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_cluster_name), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_cluster_name_check), @@ -4110,13 +4110,13 @@ static Sys_var_charptr Sys_wsrep_cluster_address ( static Sys_var_charptr Sys_wsrep_node_name ( "wsrep_node_name", "Node name", - GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_name), NO_MUTEX_GUARD, NOT_IN_BINLOG); static Sys_var_charptr Sys_wsrep_node_address ( "wsrep_node_address", "Node address", - GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_address), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(wsrep_node_address_check), @@ -4124,7 +4124,7 @@ static Sys_var_charptr Sys_wsrep_node_address ( static Sys_var_charptr Sys_wsrep_node_incoming_address( "wsrep_node_incoming_address", "Client connection address", - GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), + PREALLOCATED GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(wsrep_node_incoming_address), NO_MUTEX_GUARD, NOT_IN_BINLOG); @@ -4216,7 +4216,7 @@ static Sys_var_mybool Sys_wsrep_on ( static Sys_var_charptr Sys_wsrep_start_position ( "wsrep_start_position", "global transaction position to start from ", - GLOBAL_VAR(wsrep_start_position), + PREALLOCATED GLOBAL_VAR(wsrep_start_position), CMD_LINE(REQUIRED_ARG, OPT_WSREP_START_POSITION), IN_FS_CHARSET, DEFAULT(wsrep_start_position), NO_MUTEX_GUARD, NOT_IN_BINLOG, diff --git a/sql/transaction.cc b/sql/transaction.cc index 5195e456432..be1330d0a97 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -423,14 +423,7 @@ bool trans_rollback_stmt(THD *thd) #endif /* WITH_WSREP */ ha_rollback_trans(thd, FALSE); if (thd->transaction_rollback_request && !thd->in_sub_stmt) -#ifdef WITH_WSREP - { - wsrep_register_hton(thd, TRUE); -#endif /* WITH_WSREP */ ha_rollback_trans(thd, TRUE); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ if (! thd->in_active_multi_stmt_transaction()) { thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; diff --git a/sql/wsrep_applier.h b/sql/wsrep_applier.h new file mode 100644 index 00000000000..816970db67c --- /dev/null +++ b/sql/wsrep_applier.h @@ -0,0 +1,38 @@ +/* Copyright 2013 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 + 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_APPLIER_H +#define WSREP_APPLIER_H + +#include <sys/types.h> + +/* wsrep callback prototypes */ + +wsrep_cb_status_t wsrep_apply_cb(void *ctx, + const void* buf, size_t buf_len, + uint32_t flags, + const wsrep_trx_meta_t* meta); + +wsrep_cb_status_t wsrep_commit_cb(void *ctx, + uint32_t flags, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit, + bool commit); + +wsrep_cb_status_t wsrep_unordered_cb(void* ctx, + const void* data, + size_t size); + +#endif /* WSREP_APPLIER_H */ diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 24f193e8c7b..1a3b3d64cbe 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -68,7 +68,7 @@ handlerton *wsrep_hton; */ void wsrep_register_hton(THD* thd, bool all) { - if (thd->wsrep_exec_mode != TOTAL_ORDER) + if (thd->wsrep_exec_mode != TOTAL_ORDER && !thd->wsrep_apply_toi) { THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; for (Ha_trx_info *i= trans->ha_list; WSREP(thd) && i; i = i->next()) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a842aa84fc9..137841c776f 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -22,6 +22,7 @@ #include "wsrep_utils.h" #include "wsrep_var.h" #include "wsrep_binlog.h" +#include "wsrep_applier.h" #include <cstdio> #include <cstdlib> #include "log_event.h" @@ -86,6 +87,7 @@ long long wsrep_cluster_conf_id = WSREP_SEQNO_UNDEFINED; const char* wsrep_cluster_status = cluster_status_str[WSREP_VIEW_DISCONNECTED]; long wsrep_cluster_size = 0; long wsrep_local_index = -1; +long long wsrep_local_bf_aborts = 0; const char* wsrep_provider_name = provider_name; const char* wsrep_provider_version = provider_version; const char* wsrep_provider_vendor = provider_vendor; @@ -101,18 +103,6 @@ long wsrep_protocol_version = 2; // if there was no state gap on receiving first view event. static my_bool wsrep_startup = TRUE; -extern wsrep_cb_status_t wsrep_apply_cb(void *ctx, - const void* buf, size_t buf_len, - const wsrep_trx_meta_t* meta); - -extern wsrep_cb_status_t wsrep_commit_cb(void *ctx, - const wsrep_trx_meta_t* meta, - wsrep_bool_t *exit, - wsrep_bool_t commit); - -extern wsrep_cb_status_t wsrep_unordered_cb(void* ctx, - const void* data, - size_t size); static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { switch (level) { @@ -1326,6 +1316,20 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", thd->query(), thd->thread_id); } + + /* + It makes sense to set auto_increment_* to defaults in TOI operations. + Must be done before wsrep_TOI_begin() since Query_log_event encapsulating + TOI statement and auto inc variables for wsrep replication is constructed + there. Variables are reset back in THD::reset_for_next_command() before + processing of next command. + */ + if (wsrep_auto_increment_control) + { + thd->variables.auto_increment_offset = 1; + thd->variables.auto_increment_increment = 1; + } + if (thd->variables.wsrep_on && thd->wsrep_exec_mode==LOCAL_STATE) { switch (wsrep_OSU_method_options) { @@ -1336,12 +1340,6 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (!ret) { thd->wsrep_exec_mode= TOTAL_ORDER; - /* It makes sense to set auto_increment_* to defaults in TOI operations */ - if (wsrep_auto_increment_control) - { - thd->variables.auto_increment_offset = 1; - thd->variables.auto_increment_increment = 1; - } } } return ret; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index c5647f8d984..8580729c389 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -94,7 +94,6 @@ extern my_bool wsrep_recovery; extern my_bool wsrep_replicate_myisam; extern my_bool wsrep_log_conflicts; extern ulong wsrep_mysql_replication_bundle; -extern ulong wsrep_mysql_replication_bundle; extern my_bool wsrep_load_data_splitting; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; @@ -107,6 +106,7 @@ extern long long wsrep_cluster_conf_id; extern const char* wsrep_cluster_status; extern long wsrep_cluster_size; extern long wsrep_local_index; +extern long long wsrep_local_bf_aborts; extern const char* wsrep_provider_name; extern const char* wsrep_provider_version; extern const char* wsrep_provider_vendor; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index c25281b7a77..1ea9b84a692 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -23,12 +23,24 @@ #include "sql_base.h" // close_thread_tables() #include "mysqld.h" // start_wsrep_THD(); +static long long wsrep_bf_aborts_counter = 0; + +int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff) +{ + wsrep_local_bf_aborts = my_atomic_load64(&wsrep_bf_aborts_counter); + var->type = SHOW_LONGLONG; + var->value = (char*)&wsrep_local_bf_aborts; + return 0; +} + /* must have (&thd->LOCK_wsrep_thd) */ void wsrep_client_rollback(THD *thd) { WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", thd->thread_id, thd->query()); + my_atomic_add64(&wsrep_bf_aborts_counter, 1); + thd->wsrep_conflict_state= ABORTING; mysql_mutex_unlock(&thd->LOCK_wsrep_thd); trans_rollback(thd); @@ -79,6 +91,7 @@ static Relay_log_info* wsrep_relay_log_init(const char* log_fname) static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) { shadow->options = thd->variables.option_bits; + shadow->server_status = thd->server_status; shadow->wsrep_exec_mode = thd->wsrep_exec_mode; shadow->vio = thd->net.vio; @@ -96,14 +109,20 @@ static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) shadow->tx_isolation = thd->variables.tx_isolation; thd->variables.tx_isolation = ISO_READ_COMMITTED; thd->tx_isolation = ISO_READ_COMMITTED; + + shadow->db = thd->db; + shadow->db_length = thd->db_length; + thd->reset_db(NULL, 0); } static void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) { thd->variables.option_bits = shadow->options; + thd->server_status = shadow->server_status; thd->wsrep_exec_mode = shadow->wsrep_exec_mode; thd->net.vio = shadow->vio; thd->variables.tx_isolation = shadow->tx_isolation; + thd->reset_db(shadow->db, shadow->db_length); } void wsrep_replay_transaction(THD *thd) diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 2397230b0a2..bded13b5684 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -18,6 +18,7 @@ #include "sql_class.h" +int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff); void wsrep_client_rollback(THD *thd); void wsrep_replay_transaction(THD *thd); void wsrep_create_appliers(long threads); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 32c9ea3aa6a..30bfdf23e0f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7201,9 +7201,9 @@ no_commit: DBUG_RETURN(1); } - binlog_hton->commit(binlog_hton, user_thd, 1); - - wsrep_cleanup_transaction(user_thd); + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Source table is not in InnoDB format: no need to re-acquire locks on it. */ @@ -7224,8 +7224,10 @@ no_commit: case WSREP_TRX_ERROR: DBUG_RETURN(1); } - binlog_hton->commit(binlog_hton, user_thd, 1); - wsrep_cleanup_transaction(user_thd); + + if (binlog_hton->commit(binlog_hton, user_thd, 1)) + DBUG_RETURN(1); + wsrep_post_commit(user_thd, TRUE); #endif /* WITH_WSREP */ /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ @@ -16889,7 +16891,8 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) if (wsrep_is_wsrep_xid(xid)) { mtr_t mtr; mtr_start(&mtr); - trx_sys_update_wsrep_checkpoint(xid, &mtr); + trx_sysf_t* sys_header = trx_sysf_get(&mtr); + trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); mtr_commit(&mtr); return 0; } else { diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 5cff7e8b9ed..cbc64ecc3c9 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -296,6 +296,9 @@ trx_sys_update_mysql_binlog_offset( ib_int64_t offset, /*!< in: position in that log file */ ulint field, /*!< in: offset of the MySQL log info field in the trx sys header */ +#ifdef WITH_WSREP + trx_sysf_t* sys_header, /*!< in: trx sys header */ +#endif /* WITH_WSREP */ mtr_t* mtr); /*!< in: mtr */ /*****************************************************************//** Prints to stderr the MySQL binlog offset info in the trx system header if @@ -308,8 +311,10 @@ trx_sys_print_mysql_binlog_offset(void); /** Update WSREP checkpoint XID in sys header. */ void trx_sys_update_wsrep_checkpoint( - const XID* xid, /*!< in: WSREP XID */ - mtr_t* mtr); /*!< in: mtr */ + const XID* xid, /*!< in: WSREP XID */ + trx_sysf_t* sys_header, /*!< in: sys_header */ + mtr_t* mtr); /*!< in: mtr */ + void /** Read WSREP checkpoint XID from sys header. */ trx_sys_read_wsrep_checkpoint( diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 4ff18563c29..c678b8a5132 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -840,7 +840,9 @@ trx_write_serialisation_history( /*============================*/ trx_t* trx) /*!< in: transaction */ { - +#ifdef WITH_WSREP + trx_sysf_t* sys_header; +#endif /* WITH_WSREP */ mtr_t mtr; trx_rseg_t* rseg; @@ -891,10 +893,11 @@ trx_write_serialisation_history( MONITOR_INC(MONITOR_TRX_COMMIT_UNDO); #ifdef WITH_WSREP + sys_header = trx_sysf_get(&mtr); /* Update latest MySQL wsrep XID in trx sys header. */ if (wsrep_is_wsrep_xid(&trx->xid)) { - //trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); } #endif /* WITH_WSREP */ @@ -908,7 +911,11 @@ trx_write_serialisation_history( trx_sys_update_mysql_binlog_offset( trx->mysql_log_file_name, trx->mysql_log_offset, - TRX_SYS_MYSQL_LOG_INFO, &mtr); + TRX_SYS_MYSQL_LOG_INFO, +#ifdef WITH_WSREP + sys_header, +#endif /* WITH_WSREP */ + &mtr); trx->mysql_log_file_name = NULL; } diff --git a/wsrep/CMakeLists.txt b/wsrep.moved/CMakeLists.txt index 11d0e34d1b0..11d0e34d1b0 100644 --- a/wsrep/CMakeLists.txt +++ b/wsrep.moved/CMakeLists.txt diff --git a/wsrep/Makefile.am b/wsrep.moved/Makefile.am index 40e4b501e86..40e4b501e86 100644 --- a/wsrep/Makefile.am +++ b/wsrep.moved/Makefile.am diff --git a/wsrep.moved/wsrep_api.h b/wsrep.moved/wsrep_api.h new file mode 100644 index 00000000000..987a47db578 --- /dev/null +++ b/wsrep.moved/wsrep_api.h @@ -0,0 +1,1110 @@ +/* Copyright (C) 2009-2013 Codership Oy <info@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 + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/*! + @file wsrep API declaration. + + HOW TO READ THIS FILE. + + Due to C language rules this header layout doesn't lend itself to intuitive + reading. So here's the scoop: in the end this header declares two main types: + + * struct wsrep_init_args + + and + + * struct wsrep + + wsrep_init_args contains initialization parameters for wsrep provider like + names, addresses, etc. and pointers to callbacks. The callbacks will be called + by provider when it needs to do something application-specific, like log a + message or apply a writeset. It should be passed to init() call from + wsrep API. It is an application part of wsrep API contract. + + struct wsrep is the interface to wsrep provider. It contains all wsrep API + calls. It is a provider part of wsrep API contract. + + Finally, wsrep_load() method loads (dlopens) wsrep provider library. It is + defined in wsrep_loader.c unit and is part of libwsrep.a (which is not a + wsrep provider, but a convenience library). + + wsrep_unload() does the reverse. + +*/ +#ifndef WSREP_H +#define WSREP_H + +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************** + * * + * wsrep replication API * + * * + **************************************************************************/ + +#define WSREP_INTERFACE_VERSION "24" + +/*! Empty backend spec */ +#define WSREP_NONE "none" + + +/*! + * @brief log severity levels, passed as first argument to log handler + */ +typedef enum wsrep_log_level +{ + WSREP_LOG_FATAL, //!< Unrecoverable error, application must quit. + WSREP_LOG_ERROR, //!< Operation failed, must be repeated. + WSREP_LOG_WARN, //!< Unexpected condition, but no operational failure. + WSREP_LOG_INFO, //!< Informational message. + WSREP_LOG_DEBUG //!< Debug message. Shows only of compiled with debug. +} wsrep_log_level_t; + +/*! + * @brief error log handler + * + * All messages from wsrep provider are directed to this + * handler, if present. + * + * @param level log level + * @param message log message + */ +typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); + + +/*! + * Certain provider capabilities application may want to know about + */ +#define WSREP_CAP_MULTI_MASTER ( 1ULL << 0 ) +#define WSREP_CAP_CERTIFICATION ( 1ULL << 1 ) +#define WSREP_CAP_PARALLEL_APPLYING ( 1ULL << 2 ) +#define WSREP_CAP_TRX_REPLAY ( 1ULL << 3 ) +#define WSREP_CAP_ISOLATION ( 1ULL << 4 ) +#define WSREP_CAP_PAUSE ( 1ULL << 5 ) +#define WSREP_CAP_CAUSAL_READS ( 1ULL << 6 ) +#define WSREP_CAP_CAUSAL_TRX ( 1ULL << 7 ) +#define WSREP_CAP_INCREMENTAL_WRITESET ( 1ULL << 8 ) +#define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) +#define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) +#define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) +#define WSREP_CAP_UNORDERED ( 1ULL << 12 ) +#define WSREP_CAP_ANNOTATION ( 1ULL << 13 ) +#define WSREP_CAP_PREORDERED ( 1ULL << 14 ) + + +/*! + * Writeset flags + * + * COMMIT the writeset and all preceding writesets must be committed + * ROLLBACK all preceding writesets in a transaction must be rolled back + * PA_UNSAFE the writeset cannot be applied in parallel + * ISOLATION the writeset must be applied AND committed in isolation + * COMMUTATIVE the order in which the writeset is applied does not matter + * NATIVE the writeset contains another writeset in this provider format + * + * Note that some of the flags are mutually exclusive (e.g. COMMIT and + * ROLLBACK). + */ +#define WSREP_FLAG_COMMIT ( 1ULL << 0 ) +#define WSREP_FLAG_ROLLBACK ( 1ULL << 1 ) +#define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 ) +#define WSREP_FLAG_ISOLATION ( 1ULL << 2 ) +#define WSREP_FLAG_COMMUTATIVE ( 1ULL << 4 ) +#define WSREP_FLAG_NATIVE ( 1ULL << 5 ) + + +typedef uint64_t wsrep_trx_id_t; //!< application transaction ID +typedef uint64_t wsrep_conn_id_t; //!< application connection ID +typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc. +typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool + +/*! undefined seqno */ +#define WSREP_SEQNO_UNDEFINED (-1) + + +/*! wsrep provider status codes */ +typedef enum wsrep_status +{ + WSREP_OK = 0, //!< success + WSREP_WARNING, //!< minor warning, error logged + WSREP_TRX_MISSING, //!< transaction is not known by wsrep + WSREP_TRX_FAIL, //!< transaction aborted, server can continue + WSREP_BF_ABORT, //!< trx was victim of brute force abort + WSREP_SIZE_EXCEEDED, //!< data exceeded maximum supported size + WSREP_CONN_FAIL, //!< error in client connection, must abort + WSREP_NODE_FAIL, //!< error in node state, wsrep must reinit + WSREP_FATAL, //!< fatal error, server must abort + WSREP_NOT_IMPLEMENTED //!< feature not implemented +} wsrep_status_t; + + +/*! wsrep callbacks status codes */ +typedef enum wsrep_cb_status +{ + WSREP_CB_SUCCESS = 0, //!< success (as in "not critical failure") + WSREP_CB_FAILURE //!< critical failure (consistency violation) + /* Technically, wsrep provider has no use for specific failure codes since + * there is nothing it can do about it but abort execution. Therefore any + * positive number shall indicate a critical failure. Optionally that value + * may be used by provider to come to a consensus about state consistency + * in a group of nodes. */ +} wsrep_cb_status_t; + + +/*! + * UUID type - for all unique IDs + */ +typedef struct wsrep_uuid { + uint8_t data[16]; +} wsrep_uuid_t; + +/*! Undefined UUID */ +static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}}; + +/*! UUID string representation length, terminating '\0' not included */ +#define WSREP_UUID_STR_LEN 36 + +/*! + * Scan UUID from string + * @return length of UUID string representation or negative error code + */ +extern int +wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid); + +/*! + * Print UUID to string + * @return length of UUID string representation or negative error code + */ +extern int +wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len); + +#define WSREP_MEMBER_NAME_LEN 32 //!< maximum logical member name length +#define WSREP_INCOMING_LEN 256 //!< max Domain Name length + 0x00 + + +/*! + * Global transaction identifier + */ +typedef struct wsrep_gtid +{ + wsrep_uuid_t uuid; /*!< History UUID */ + wsrep_seqno_t seqno; /*!< Sequence number */ +} wsrep_gtid_t; + +/*! Undefined GTID */ +static const wsrep_gtid_t WSREP_GTID_UNDEFINED = {{{0, }}, -1}; + +/*! Minimum number of bytes guaranteed to store GTID string representation, + * terminating '\0' not included (36 + 1 + 20) */ +#define WSREP_GTID_STR_LEN 57 + + +/*! + * Scan GTID from string + * @return length of GTID string representation or negative error code + */ +extern int +wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid); + +/*! + * Print GTID to string + * @return length of GTID string representation or negative error code + */ +extern int +wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len); + + +/*! + * Transaction meta data + */ +typedef struct wsrep_trx_meta +{ + wsrep_gtid_t gtid; /*!< Global transaction identifier */ + wsrep_seqno_t depends_on; /*!< Sequence number part of the last transaction + this transaction depends on */ +} wsrep_trx_meta_t; + + +/*! + * member status + */ +typedef enum wsrep_member_status { + WSREP_MEMBER_UNDEFINED, //!< undefined state + WSREP_MEMBER_JOINER, //!< incomplete state, requested state transfer + WSREP_MEMBER_DONOR, //!< complete state, donates state transfer + WSREP_MEMBER_JOINED, //!< complete state + WSREP_MEMBER_SYNCED, //!< complete state, synchronized with group + WSREP_MEMBER_ERROR, //!< this and above is provider-specific error code + WSREP_MEMBER_MAX +} wsrep_member_status_t; + +/*! + * static information about a group member (some fields are tentative yet) + */ +typedef struct wsrep_member_info { + wsrep_uuid_t id; //!< group-wide unique member ID + char name[WSREP_MEMBER_NAME_LEN]; //!< human-readable name + char incoming[WSREP_INCOMING_LEN]; //!< address for client requests +} wsrep_member_info_t; + +/*! + * group status + */ +typedef enum wsrep_view_status { + WSREP_VIEW_PRIMARY, //!< primary group configuration (quorum present) + WSREP_VIEW_NON_PRIMARY, //!< non-primary group configuration (quorum lost) + WSREP_VIEW_DISCONNECTED, //!< not connected to group, retrying. + WSREP_VIEW_MAX +} wsrep_view_status_t; + +/*! + * view of the group + */ +typedef struct wsrep_view_info { + wsrep_gtid_t state_id; //!< global state ID + wsrep_seqno_t view; //!< global view number + wsrep_view_status_t status; //!< view status + wsrep_bool_t state_gap; //!< gap between global and local states + int my_idx; //!< index of this member in the view + int memb_num; //!< number of members in the view + int proto_ver; //!< application protocol agreed on the view + wsrep_member_info_t members[1];//!< array of member information +} wsrep_view_info_t; + +/*! + * Magic string to tell provider to engage into trivial (empty) state transfer. + * No data will be passed, but the node shall be considered JOINED. + * Should be passed in sst_req parameter of wsrep_view_cb_t. + */ +#define WSREP_STATE_TRANSFER_TRIVIAL "trivial" + +/*! + * Magic string to tell provider not to engage in state transfer at all. + * The member will stay in WSREP_MEMBER_UNDEFINED state but will keep on + * receiving all writesets. + * Should be passed in sst_req parameter of wsrep_view_cb_t. + */ +#define WSREP_STATE_TRANSFER_NONE "none" + +/*! + * @brief group view handler + * + * This handler is called in total order corresponding to the group + * configuration change. It is to provide a vital information about + * new group view. If view info indicates existence of discontinuity + * between group and member states, state transfer request message + * should be filled in by the callback implementation. + * + * @note Currently it is assumed that sst_req is allocated using + * malloc()/calloc()/realloc() and it will be freed by + * wsrep implementation. + * + * @param app_ctx application context + * @param recv_ctx receiver context + * @param view new view on the group + * @param state current state + * @param state_len lenght of current state + * @param sst_req location to store SST request + * @param sst_req_len location to store SST request length or error code, + * value of 0 means no SST. + */ +typedef enum wsrep_cb_status (*wsrep_view_cb_t) ( + void* app_ctx, + void* recv_ctx, + const wsrep_view_info_t* view, + const char* state, + size_t state_len, + void** sst_req, + size_t* sst_req_len +); + + +/*! + * @brief apply callback + * + * This handler is called from wsrep library to apply replicated writeset + * Must support brute force applying for multi-master operation + * + * @param recv_ctx receiver context pointer provided by the application + * @param data data buffer containing the writeset + * @param size data buffer size + * @param meta transaction meta data of the writeset to be applied + * + * @return success code: + * @retval WSREP_OK + * @retval WSREP_NOT_IMPLEMENTED appl. does not support the writeset format + * @retval WSREP_ERROR failed to apply the writeset + */ +typedef enum wsrep_cb_status (*wsrep_apply_cb_t) ( + void* recv_ctx, + const void* data, + size_t size, + const wsrep_trx_meta_t* meta +); + + +/*! + * @brief commit callback + * + * This handler is called to commit the changes made by apply callback. + * + * @param recv_ctx receiver context pointer provided by the application + * @param meta transaction meta data of the writeset to be committed + * @param exit set to true to exit recv loop + * @param commit true - commit writeset, false - rollback writeset + * + * @return success code: + * @retval WSREP_OK + * @retval WSREP_ERROR call failed + */ +typedef enum wsrep_cb_status (*wsrep_commit_cb_t) ( + void* recv_ctx, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit, + wsrep_bool_t commit +); + + +/*! + * @brief unordered callback + * + * This handler is called to execute unordered actions (actions that need not + * to be executed in any particular order) attached to writeset. + * + * @param recv_ctx receiver context pointer provided by the application + * @param data data buffer containing the writeset + * @param size data buffer size + */ +typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) ( + void* recv_ctx, + const void* data, + size_t size +); + + +/*! + * @brief a callback to donate state snapshot + * + * This handler is called from wsrep library when it needs this node + * to deliver state to a new cluster member. + * No state changes will be committed for the duration of this call. + * Wsrep implementation may provide internal state to be transmitted + * to new cluster member for initial state. + * + * @param app_ctx application context + * @param recv_ctx receiver context + * @param msg state transfer request message + * @param msg_len state transfer request message length + * @param gtid current state ID on this node + * @param state current wsrep internal state buffer + * @param state_len current wsrep internal state buffer len + * @param bypass bypass snapshot transfer, only transfer uuid:seqno pair + */ +typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) ( + void* app_ctx, + void* recv_ctx, + const void* msg, + size_t msg_len, + const wsrep_gtid_t* state_id, + const char* state, + size_t state_len, + wsrep_bool_t bypass +); + + +/*! + * @brief a callback to signal application that wsrep state is synced + * with cluster + * + * This callback is called after wsrep library has got in sync with + * rest of the cluster. + * + * @param app_ctx application context + */ +typedef void (*wsrep_synced_cb_t) (void* app_ctx); + + +/*! + * Initialization parameters for wsrep provider. + */ +struct wsrep_init_args +{ + void* app_ctx; //!< Application context for callbacks + + /* Configuration parameters */ + const char* node_name; //!< Symbolic name of this node (e.g. hostname) + const char* node_address; //!< Address to be used by wsrep provider + const char* node_incoming; //!< Address for incoming client connections + const char* data_dir; //!< Directory where wsrep files are kept if any + const char* options; //!< Provider-specific configuration string + int proto_ver; //!< Max supported application protocol version + + /* Application initial state information. */ + const wsrep_gtid_t* state_id; //!< Application state GTID + const char* state; //!< Initial state for wsrep provider + size_t state_len; //!< Length of state buffer + + /* Application callbacks */ + wsrep_log_cb_t logger_cb; //!< logging handler + wsrep_view_cb_t view_handler_cb; //!< group view change handler + + /* Applier callbacks */ + wsrep_apply_cb_t apply_cb; //!< apply callback + wsrep_commit_cb_t commit_cb; //!< commit callback + wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions + + /* State Snapshot Transfer callbacks */ + wsrep_sst_donate_cb_t sst_donate_cb; //!< starting to donate + wsrep_synced_cb_t synced_cb; //!< synced with group +}; + + +/*! Type of the stats variable value in struct wsrep_status_var */ +typedef enum wsrep_var_type +{ + WSREP_VAR_STRING, //!< pointer to null-terminated string + WSREP_VAR_INT64, //!< int64_t + WSREP_VAR_DOUBLE //!< double +} +wsrep_var_type_t; + +/*! Generalized stats variable representation */ +struct wsrep_stats_var +{ + const char* name; //!< variable name + wsrep_var_type_t type; //!< variable value type + union { + int64_t _int64; + double _double; + const char* _string; + } value; //!< variable value +}; + + +/*! Abstract data buffer structure */ +typedef struct wsrep_buf +{ + const void* ptr; /*!< Pointer to data buffer */ + size_t len; /*!< Length of buffer */ +} wsrep_buf_t; + +/*! Key struct used to pass certification keys for transaction handling calls. + * A key consists of zero or more key parts. */ +typedef struct wsrep_key +{ + const wsrep_buf_t* key_parts; /*!< Array of key parts */ + size_t key_parts_num; /*!< Number of key parts */ +} wsrep_key_t; + +/*! Key type: + * EXCLUSIVE conflicts with any key type + * SEMI reserved. If not supported, should be interpeted as EXCLUSIVE + * SHARED conflicts only with EXCLUSIVE keys */ +typedef enum wsrep_key_type +{ + WSREP_KEY_SHARED = 0, + WSREP_KEY_SEMI, + WSREP_KEY_EXCLUSIVE +} wsrep_key_type_t; + +/*! Data type: + * ORDERED state modification event that should be applied and committed + * in order. + * UNORDERED some action that does not modify state and execution of which is + * optional and does not need to happen in order. + * ANNOTATION (human readable) writeset annotation. */ +typedef enum wsrep_data_type +{ + WSREP_DATA_ORDERED = 0, + WSREP_DATA_UNORDERED, + WSREP_DATA_ANNOTATION +} wsrep_data_type_t; + + +/*! Transaction handle struct passed for wsrep transaction handling calls */ +typedef struct wsrep_ws_handle +{ + wsrep_trx_id_t trx_id; //!< transaction ID + void* opaque; //!< opaque provider transaction context data +} wsrep_ws_handle_t; + +/*! + * @brief Helper method to reset trx writeset handle state when trx id changes + * + * Instead of passing wsrep_ws_handle_t directly to wsrep calls, + * wrapping handle with this call offloads bookkeeping from + * application. + */ +static inline wsrep_ws_handle_t* wsrep_ws_handle_for_trx( + wsrep_ws_handle_t* ws_handle, + wsrep_trx_id_t trx_id) +{ + if (ws_handle->trx_id != trx_id) + { + ws_handle->trx_id = trx_id; + ws_handle->opaque = NULL; + } + return ws_handle; +} + + +/*! + * A handle for processing preordered actions. + * Must be initialized to WSREP_PO_INITIALIZER before use. + */ +typedef struct wsrep_po_handle { void* opaque; } wsrep_po_handle_t; + +static const wsrep_po_handle_t WSREP_PO_INITIALIZER = { NULL }; + + +typedef struct wsrep wsrep_t; +/*! + * wsrep interface for dynamically loadable libraries + */ +struct wsrep { + + const char *version; //!< interface version string + + /*! + * @brief Initializes wsrep provider + * + * @param wsrep provider handle + * @param args wsrep initialization parameters + */ + wsrep_status_t (*init) (wsrep_t* wsrep, + const struct wsrep_init_args* args); + + /*! + * @brief Returns provider capabilities flag bitmap + * + * @param wsrep provider handle + */ + uint64_t (*capabilities) (wsrep_t* wsrep); + + /*! + * @brief Passes provider-specific configuration string to provider. + * + * @param wsrep provider handle + * @param conf configuration string + * + * @retval WSREP_OK configuration string was parsed successfully + * @retval WSREP_WARNING could't not parse conf string, no action taken + */ + wsrep_status_t (*options_set) (wsrep_t* wsrep, const char* conf); + + /*! + * @brief Returns provider-specific string with current configuration values. + * + * @param wsrep provider handle + * + * @return a dynamically allocated string with current configuration + * parameter values + */ + char* (*options_get) (wsrep_t* wsrep); + + /*! + * @brief Opens connection to cluster + * + * Returns when either node is ready to operate as a part of the clsuter + * or fails to reach operating status. + * + * @param wsrep provider handle + * @param cluster_name unique symbolic cluster name + * @param cluster_url URL-like cluster address (backend://address) + * @param state_donor name of the node to be asked for state transfer. + * @param bootstrap a flag to request initialization of a new wsrep + * service rather then a connection to the existing one. + * clister_url may still carry important initialization + * parameters, like backend spec and/or listen address. + */ + wsrep_status_t (*connect) (wsrep_t* wsrep, + const char* cluster_name, + const char* cluster_url, + const char* state_donor, + wsrep_bool_t bootstrap); + + /*! + * @brief Closes connection to cluster. + * + * If state_uuid and/or state_seqno is not NULL, will store final state + * in there. + * + * @param wsrep this wsrep handler + */ + wsrep_status_t (*disconnect)(wsrep_t* wsrep); + + /*! + * @brief start receiving replication events + * + * This function never returns + * + * @param wsrep provider handle + * @param recv_ctx receiver context + */ + wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx); + + /*! + * @brief Replicates/logs result of transaction to other nodes and allocates + * required resources. + * + * Must be called before transaction commit. Returns success code, which + * caller must check. + * In case of WSREP_OK, starts commit critical section, transaction can + * commit. Otherwise transaction must rollback. + * + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction + * @param conn_id connection ID + * @param flags fine tuning the replication WSREP_FLAG_* + * @param meta transaction meta data + * + * @retval WSREP_OK cluster-wide commit succeeded + * @retval WSREP_TRX_FAIL must rollback transaction + * @retval WSREP_CONN_FAIL must close client connection + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*pre_commit)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + wsrep_ws_handle_t* ws_handle, + uint64_t flags, + wsrep_trx_meta_t* meta); + + /*! + * @brief Releases resources after transaction commit. + * + * Ends commit critical section. + * + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction + * @retval WSREP_OK post_commit succeeded + */ + wsrep_status_t (*post_commit) (wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle); + + /*! + * @brief Releases resources after transaction rollback. + * + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction + * @retval WSREP_OK post_rollback succeeded + */ + wsrep_status_t (*post_rollback)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle); + + /*! + * @brief Replay trx as a slave writeset + * + * If local trx has been aborted by brute force, and it has already + * replicated before this abort, we must try if we can apply it as + * slave trx. Note that slave nodes see only trx writesets and certification + * test based on write set content can be different to DBMS lock conflicts. + * + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction + * @param trx_ctx transaction context + * + * @retval WSREP_OK cluster commit succeeded + * @retval WSREP_TRX_FAIL must rollback transaction + * @retval WSREP_BF_ABORT brute force abort happened after trx replicated + * must rollback transaction and try to replay + * @retval WSREP_CONN_FAIL must close client connection + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*replay_trx)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle, + void* trx_ctx); + + /*! + * @brief Abort pre_commit() call of another thread. + * + * It is possible, that some high-priority transaction needs to abort + * another transaction which is in pre_commit() call waiting for resources. + * + * The kill routine checks that abort is not attmpted against a transaction + * which is front of the caller (in total order). + * + * @param wsrep provider handle + * @param bf_seqno seqno of brute force trx, running this cancel + * @param victim_trx transaction to be aborted, and which is committing + * + * @retval WSREP_OK abort secceded + * @retval WSREP_WARNING abort failed + */ + wsrep_status_t (*abort_pre_commit)(wsrep_t* wsrep, + wsrep_seqno_t bf_seqno, + wsrep_trx_id_t victim_trx); + + /*! + * @brief Appends a row reference to transaction writeset + * + * Both copy flag and key_type can be ignored by provider (key type + * interpreted as WSREP_KEY_EXCLUSIVE). + * + * @param wsrep provider handle + * @param ws_handle writeset handle + * @param keys array of keys + * @param count length of the array of keys + * @param type type ot the key + * @param copy can be set to FALSE if keys persist through commit. + */ + wsrep_status_t (*append_key)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle, + const wsrep_key_t* keys, + size_t count, + enum wsrep_key_type type, + wsrep_bool_t copy); + + /*! + * @brief Appends data to transaction writeset + * + * This method can be called any time before commit and it + * appends a number of data buffers to transaction writeset. + * + * Both copy and unordered flags can be ignored by provider. + * + * @param wsrep provider handle + * @param ws_handle writeset handle + * @param data array of data buffers + * @param count buffer count + * @param type type of data + * @param copy can be set to FALSE if data persists through commit. + */ + wsrep_status_t (*append_data)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle, + const struct wsrep_buf* data, + size_t count, + enum wsrep_data_type type, + wsrep_bool_t copy); + + /*! + * @brief Get causal ordering for read operation + * + * This call will block until causal ordering with all possible + * preceding writes in the cluster is guaranteed. If pointer to + * gtid is non-null, the call stores the global transaction ID + * of the last transaction which is guaranteed to be ordered + * causally before this call. + * + * @param wsrep provider handle + * @param gtid location to store GTID + */ + wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_gtid_t* gtid); + + /*! + * @brief Clears allocated connection context. + * + * Whenever a new connection ID is passed to wsrep provider through + * any of the API calls, a connection context is allocated for this + * connection. This call is to explicitly notify provider fo connection + * closing. + * + * @param wsrep provider handle + * @param conn_id connection ID + * @param query the 'set database' query + * @param query_len length of query (does not end with 0) + */ + wsrep_status_t (*free_connection)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id); + + /*! + * @brief Replicates a query and starts "total order isolation" section. + * + * Replicates the action spec and returns success code, which caller must + * check. Total order isolation continues until to_execute_end() is called. + * + * @param wsrep provider handle + * @param conn_id connection ID + * @param keys array of keys + * @param keys_num lenght of the array of keys + * @param action action buffer array to be executed + * @param count action buffer count + * @param meta transaction meta data + * + * @retval WSREP_OK cluster commit succeeded + * @retval WSREP_CONN_FAIL must close client connection + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*to_execute_start)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + const wsrep_key_t* keys, + size_t keys_num, + const struct wsrep_buf* action, + size_t count, + wsrep_trx_meta_t* meta); + + /*! + * @brief Ends the total order isolation section. + * + * Marks the end of total order isolation. TO locks are freed + * and other transactions are free to commit from this point on. + * + * @param wsrep provider handle + * @param conn_id connection ID + * + * @retval WSREP_OK cluster commit succeeded + * @retval WSREP_CONN_FAIL must close client connection + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*to_execute_end)(wsrep_t* wsrep, wsrep_conn_id_t conn_id); + + /*! + * @brief Collects preordered replication events into a writeset. + * + * @param wsrep wsrep provider handle + * @param handle a handle associated with a given writeset + * @param data an array of data buffers. + * @param count length of data buffer array. + * @param copy whether provider needs to make a copy of events. + * + * @retval WSREP_OK cluster-wide commit succeeded + * @retval WSREP_TRX_FAIL operation failed (e.g. trx size exceeded limit) + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*preordered_collect) (wsrep_t* wsrep, + wsrep_po_handle_t* handle, + const struct wsrep_buf* data, + size_t count, + wsrep_bool_t copy); + + /*! + * @brief "Commits" preordered writeset to cluster. + * + * The contract is that the writeset will be committed in the same (partial) + * order this method was called. Frees resources associated with the writeset + * handle and reinitializes the handle. + * + * @param wsrep wsrep provider handle + * @param po_handle a handle associated with a given writeset + * @param source_id ID of the event producer, also serves as the partial order + * or stream ID - events with different source_ids won't be + * ordered with respect to each other. + * @param flags WSREP_FLAG_... flags + * @param pa_range the number of preceding events this event can be processed + * in parallel with. A value of 0 means strict serial + * processing. Note: commits always happen in wsrep order. + * @param commit 'true' to commit writeset to cluster (replicate) or + * 'false' to rollback (cancel) the writeset. + * + * @retval WSREP_OK cluster-wide commit succeeded + * @retval WSREP_TRX_FAIL operation failed (e.g. NON-PRIMARY component) + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*preordered_commit) (wsrep_t* wsrep, + wsrep_po_handle_t* handle, + const wsrep_uuid_t* source_id, + uint64_t flags, + int pa_range, + wsrep_bool_t commit); + + /*! + * @brief Signals to wsrep provider that state snapshot has been sent to + * joiner. + * + * @param wsrep provider handle + * @param state_id state ID + * @param rcode 0 or negative error code of the operation. + */ + wsrep_status_t (*sst_sent)(wsrep_t* wsrep, + const wsrep_gtid_t* state_id, + int rcode); + + /*! + * @brief Signals to wsrep provider that new state snapshot has been received. + * May deadlock if called from sst_prepare_cb. + * + * @param wsrep provider handle + * @param state_id state ID + * @param state initial state provided by SST donor + * @param state_len length of state buffer + * @param rcode 0 or negative error code of the operation. + */ + wsrep_status_t (*sst_received)(wsrep_t* wsrep, + const wsrep_gtid_t* state_id, + const void* state, + size_t state_len, + int rcode); + + + /*! + * @brief Generate request for consistent snapshot. + * + * If successfull, this call will generate internally SST request + * which in turn triggers calling SST donate callback on the nodes + * specified in donor_spec. If donor_spec is null, callback is + * called only locally. This call will block until sst_sent is called + * from callback. + * + * @param wsrep provider handle + * @param msg context message for SST donate callback + * @param msg_len length of context message + * @param donor_spec list of snapshot donors + */ + wsrep_status_t (*snapshot)(wsrep_t* wsrep, + const void* msg, + size_t msg_len, + const char* donor_spec); + + /*! + * @brief Returns an array fo status variables. + * Array is terminated by Null variable name. + * + * @param wsrep provider handle + * @return array of struct wsrep_status_var. + */ + struct wsrep_stats_var* (*stats_get) (wsrep_t* wsrep); + + /*! + * @brief Release resources that might be associated with the array. + * + * @param wsrep provider handle. + * @param var_array array returned by stats_get(). + */ + void (*stats_free) (wsrep_t* wsrep, struct wsrep_stats_var* var_array); + + /*! + * @brief Reset some stats variables to inital value, provider-dependent. + * + * @param wsrep provider handle. + */ + void (*stats_reset) (wsrep_t* wsrep); + + /*! + * @brief Pauses writeset applying/committing. + * + * @return global sequence number of the paused state or negative error code. + */ + wsrep_seqno_t (*pause) (wsrep_t* wsrep); + + /*! + * @brief Resumes writeset applying/committing. + */ + wsrep_status_t (*resume) (wsrep_t* wsrep); + + /*! + * @brief Desynchronize from cluster + * + * Effectively turns off flow control for this node, allowing it + * to fall behind the cluster. + */ + wsrep_status_t (*desync) (wsrep_t* wsrep); + + /*! + * @brief Request to resynchronize with cluster. + * + * Effectively turns on flow control. Asynchronous - actual synchronization + * event to be deliverred via sync_cb. + */ + wsrep_status_t (*resync) (wsrep_t* wsrep); + + /*! + * @brief Acquire global named lock + * + * @param wsrep wsrep provider handle + * @param name lock name + * @param shared shared or exclusive lock + * @param owner 64-bit owner ID + * @param tout timeout in nanoseconds. + * 0 - return immediately, -1 wait forever. + * @return wsrep status or negative error code + * @retval -EDEADLK lock was already acquired by this thread + * @retval -EBUSY lock was busy + */ + wsrep_status_t (*lock) (wsrep_t* wsrep, + const char* name, wsrep_bool_t shared, + uint64_t owner, int64_t tout); + + /*! + * @brief Release global named lock + * + * @param wsrep wsrep provider handle + * @param name lock name + * @param owner 64-bit owner ID + * @return wsrep status or negative error code + * @retval -EPERM lock does not belong to this owner + */ + wsrep_status_t (*unlock) (wsrep_t* wsrep, const char* name, uint64_t owner); + + /*! + * @brief Check if global named lock is locked + * + * @param wsrep wsrep provider handle + * @param name lock name + * @param owner if not NULL will contain 64-bit owner ID + * @param node if not NULL will contain owner's node UUID + * @return true if lock is locked + */ + wsrep_bool_t (*is_locked) (wsrep_t* wsrep, const char* name, uint64_t* conn, + wsrep_uuid_t* node); + + /*! + * wsrep provider name + */ + const char* provider_name; + + /*! + * wsrep provider version + */ + const char* provider_version; + + /*! + * wsrep provider vendor name + */ + const char* provider_vendor; + + /*! + * @brief Frees allocated resources before unloading the library. + * @param wsrep provider handle + */ + void (*free)(wsrep_t* wsrep); + + void *dlh; //!< reserved for future use + void *ctx; //!< reserved for implemetation private context +}; + + +/*! + * + * @brief Loads wsrep library + * + * @param spec path to wsrep library. If NULL or WSREP_NONE initialises dummy + * pass-through implementation. + * @param hptr wsrep handle + * @param log_cb callback to handle loader messages. Otherwise writes to stderr. + * + * @return zero on success, errno on failure + */ +int wsrep_load(const char* spec, wsrep_t** hptr, wsrep_log_cb_t log_cb); + +/*! + * @brief Unloads wsrep library and frees associated resources + * + * @param hptr wsrep handler pointer + */ +void wsrep_unload(wsrep_t* hptr); + +#ifdef __cplusplus +} +#endif + +#endif /* WSREP_H */ diff --git a/wsrep.moved/wsrep_dummy.c b/wsrep.moved/wsrep_dummy.c new file mode 100644 index 00000000000..33b61e6821f --- /dev/null +++ b/wsrep.moved/wsrep_dummy.c @@ -0,0 +1,383 @@ +/* Copyright (C) 2009-2010 Codership Oy <info@codersihp.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 + 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 + */ + +/*! @file Dummy wsrep API implementation. */ + +#include "wsrep_api.h" + +#include <errno.h> +#include <stdbool.h> + +/*! Dummy backend context. */ +typedef struct wsrep_dummy +{ + wsrep_log_cb_t log_fn; +} wsrep_dummy_t; + +/* Get pointer to wsrep_dummy context from wsrep_t pointer */ +#define WSREP_DUMMY(_p) ((wsrep_dummy_t *) (_p)->ctx) + +/* Trace function usage a-la DBUG */ +#define WSREP_DBUG_ENTER(_w) do { \ + if (WSREP_DUMMY(_w)) { \ + if (WSREP_DUMMY(_w)->log_fn) \ + WSREP_DUMMY(_w)->log_fn(WSREP_LOG_DEBUG, __FUNCTION__); \ + } \ + } while (0) + + +static void dummy_free(wsrep_t *w) +{ + WSREP_DBUG_ENTER(w); + free(w->ctx); + w->ctx = NULL; +} + +static wsrep_status_t dummy_init (wsrep_t* w, + const struct wsrep_init_args* args) +{ + WSREP_DUMMY(w)->log_fn = args->logger_cb; + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static uint64_t dummy_capabilities (wsrep_t* w __attribute__((unused))) +{ + return 0; +} + +static wsrep_status_t dummy_options_set( + wsrep_t* w, + const char* conf __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static char* dummy_options_get (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return NULL; +} + +static wsrep_status_t dummy_connect( + wsrep_t* w, + const char* name __attribute__((unused)), + const char* url __attribute__((unused)), + const char* donor __attribute__((unused)), + wsrep_bool_t bootstrap __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_disconnect(wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_recv(wsrep_t* w, + void* recv_ctx __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_pre_commit( + wsrep_t* w, + const wsrep_conn_id_t conn_id __attribute__((unused)), + wsrep_ws_handle_t* ws_handle __attribute__((unused)), +// const struct wsrep_buf* data __attribute__((unused)), +// const long count __attribute__((unused)), + uint64_t flags __attribute__((unused)), + wsrep_trx_meta_t* meta __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_post_commit( + wsrep_t* w, + wsrep_ws_handle_t* ws_handle __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_post_rollback( + wsrep_t* w, + wsrep_ws_handle_t* ws_handle __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_replay_trx( + wsrep_t* w, + wsrep_ws_handle_t* ws_handle __attribute__((unused)), + void* trx_ctx __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_abort_pre_commit( + wsrep_t* w, + const wsrep_seqno_t bf_seqno __attribute__((unused)), + const wsrep_trx_id_t trx_id __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_append_key( + wsrep_t* w, + wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const wsrep_key_t* key __attribute__((unused)), + const int key_num __attribute__((unused)), + const wsrep_key_type_t key_type __attribute__((unused)), + const bool copy __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_append_data( + wsrep_t* w, + wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + const int count __attribute__((unused)), + const wsrep_data_type_t type __attribute__((unused)), + const bool copy __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_causal_read( + wsrep_t* w, + wsrep_gtid_t* gtid __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_free_connection( + wsrep_t* w, + const wsrep_conn_id_t conn_id __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_to_execute_start( + wsrep_t* w, + const wsrep_conn_id_t conn_id __attribute__((unused)), + const wsrep_key_t* key __attribute__((unused)), + const int key_num __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + const int count __attribute__((unused)), + wsrep_trx_meta_t* meta __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_to_execute_end( + wsrep_t* w, + const wsrep_conn_id_t conn_id __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_preordered( + wsrep_t* w, + const wsrep_uuid_t* source_id __attribute__((unused)), + int pa_range __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + int count __attribute__((unused)), + uint64_t flags __attribute__((unused)), + wsrep_bool_t copy __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_sst_sent( + wsrep_t* w, + const wsrep_uuid_t* uuid __attribute__((unused)), + wsrep_seqno_t seqno __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_sst_received( + wsrep_t* w, + const wsrep_uuid_t* uuid __attribute__((unused)), + const wsrep_seqno_t seqno __attribute__((unused)), + const char* state __attribute__((unused)), + const size_t state_len __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_snapshot( + wsrep_t* w, + const void* msg __attribute__((unused)), + const int msg_len __attribute__((unused)), + const char* donor_spec __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static struct wsrep_stats_var dummy_stats[] = { + { NULL, WSREP_VAR_STRING, { 0 } } +}; + +static struct wsrep_stats_var* dummy_stats_get (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return dummy_stats; +} + +static void dummy_stats_free ( + wsrep_t* w, + struct wsrep_stats_var* stats __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); +} + +static void dummy_stats_reset (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); +} + +static wsrep_seqno_t dummy_pause (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return -ENOSYS; +} + +static wsrep_status_t dummy_resume (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_desync (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return WSREP_NOT_IMPLEMENTED; +} + +static wsrep_status_t dummy_resync (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_lock (wsrep_t* w, + const char* s __attribute__((unused)), + bool r __attribute__((unused)), + uint64_t o __attribute__((unused)), + int64_t t __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_NOT_IMPLEMENTED; +} + +static wsrep_status_t dummy_unlock (wsrep_t* w, + const char* s __attribute__((unused)), + uint64_t o __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static bool dummy_is_locked (wsrep_t* w, + const char* s __attribute__((unused)), + uint64_t* o __attribute__((unused)), + wsrep_uuid_t* t __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return false; +} + +static wsrep_t dummy_iface = { + WSREP_INTERFACE_VERSION, + &dummy_init, + &dummy_capabilities, + &dummy_options_set, + &dummy_options_get, + &dummy_connect, + &dummy_disconnect, + &dummy_recv, + &dummy_pre_commit, + &dummy_post_commit, + &dummy_post_rollback, + &dummy_replay_trx, + &dummy_abort_pre_commit, + &dummy_append_key, + &dummy_append_data, + &dummy_causal_read, + &dummy_free_connection, + &dummy_to_execute_start, + &dummy_to_execute_end, + &dummy_preordered, + &dummy_sst_sent, + &dummy_sst_received, + &dummy_snapshot, + &dummy_stats_get, + &dummy_stats_free, + &dummy_stats_reset, + &dummy_pause, + &dummy_resume, + &dummy_desync, + &dummy_resync, + &dummy_lock, + &dummy_unlock, + &dummy_is_locked, + WSREP_NONE, + WSREP_INTERFACE_VERSION, + "Codership Oy <info@codership.com>", + 0xdeadbeef, + &dummy_free, + NULL, + NULL +}; + +int wsrep_dummy_loader(wsrep_t* w) +{ + if (!w) + return EINVAL; + + *w = dummy_iface; + + // allocate private context + if (!(w->ctx = malloc(sizeof(wsrep_dummy_t)))) + return ENOMEM; + + // initialize private context + WSREP_DUMMY(w)->log_fn = NULL; + + return 0; +} + diff --git a/wsrep/wsrep_loader.c b/wsrep.moved/wsrep_loader.c index 8ae6ea962ec..8ae6ea962ec 100644 --- a/wsrep/wsrep_loader.c +++ b/wsrep.moved/wsrep_loader.c diff --git a/wsrep/wsrep_uuid.c b/wsrep.moved/wsrep_uuid.c index baa95b2578a..baa95b2578a 100644 --- a/wsrep/wsrep_uuid.c +++ b/wsrep.moved/wsrep_uuid.c diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h index 987a47db578..f713de66d57 100644 --- a/wsrep/wsrep_api.h +++ b/wsrep/wsrep_api.h @@ -63,7 +63,7 @@ extern "C" { * * **************************************************************************/ -#define WSREP_INTERFACE_VERSION "24" +#define WSREP_INTERFACE_VERSION "25" /*! Empty backend spec */ #define WSREP_NONE "none" @@ -118,8 +118,8 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); * * COMMIT the writeset and all preceding writesets must be committed * ROLLBACK all preceding writesets in a transaction must be rolled back - * PA_UNSAFE the writeset cannot be applied in parallel * ISOLATION the writeset must be applied AND committed in isolation + * PA_UNSAFE the writeset cannot be applied in parallel * COMMUTATIVE the order in which the writeset is applied does not matter * NATIVE the writeset contains another writeset in this provider format * @@ -128,8 +128,8 @@ typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); */ #define WSREP_FLAG_COMMIT ( 1ULL << 0 ) #define WSREP_FLAG_ROLLBACK ( 1ULL << 1 ) -#define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 ) #define WSREP_FLAG_ISOLATION ( 1ULL << 2 ) +#define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 ) #define WSREP_FLAG_COMMUTATIVE ( 1ULL << 4 ) #define WSREP_FLAG_NATIVE ( 1ULL << 5 ) @@ -349,6 +349,7 @@ typedef enum wsrep_cb_status (*wsrep_view_cb_t) ( * @param recv_ctx receiver context pointer provided by the application * @param data data buffer containing the writeset * @param size data buffer size + * @param flags WSREP_FLAG_... flags * @param meta transaction meta data of the writeset to be applied * * @return success code: @@ -360,6 +361,7 @@ typedef enum wsrep_cb_status (*wsrep_apply_cb_t) ( void* recv_ctx, const void* data, size_t size, + uint32_t flags, const wsrep_trx_meta_t* meta ); @@ -370,6 +372,7 @@ typedef enum wsrep_cb_status (*wsrep_apply_cb_t) ( * This handler is called to commit the changes made by apply callback. * * @param recv_ctx receiver context pointer provided by the application + * @param flags WSREP_FLAG_... flags * @param meta transaction meta data of the writeset to be committed * @param exit set to true to exit recv loop * @param commit true - commit writeset, false - rollback writeset @@ -380,6 +383,7 @@ typedef enum wsrep_cb_status (*wsrep_apply_cb_t) ( */ typedef enum wsrep_cb_status (*wsrep_commit_cb_t) ( void* recv_ctx, + uint32_t flags, const wsrep_trx_meta_t* meta, wsrep_bool_t* exit, wsrep_bool_t commit @@ -687,7 +691,7 @@ struct wsrep { wsrep_status_t (*pre_commit)(wsrep_t* wsrep, wsrep_conn_id_t conn_id, wsrep_ws_handle_t* ws_handle, - uint64_t flags, + uint32_t flags, wsrep_trx_meta_t* meta); /*! @@ -913,7 +917,7 @@ struct wsrep { wsrep_status_t (*preordered_commit) (wsrep_t* wsrep, wsrep_po_handle_t* handle, const wsrep_uuid_t* source_id, - uint64_t flags, + uint32_t flags, int pa_range, wsrep_bool_t commit); diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index 33b61e6821f..3c7a7c2e354 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -101,9 +101,7 @@ static wsrep_status_t dummy_pre_commit( wsrep_t* w, const wsrep_conn_id_t conn_id __attribute__((unused)), wsrep_ws_handle_t* ws_handle __attribute__((unused)), -// const struct wsrep_buf* data __attribute__((unused)), -// const long count __attribute__((unused)), - uint64_t flags __attribute__((unused)), + uint32_t flags __attribute__((unused)), wsrep_trx_meta_t* meta __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -148,7 +146,7 @@ static wsrep_status_t dummy_append_key( wsrep_t* w, wsrep_ws_handle_t* ws_handle __attribute__((unused)), const wsrep_key_t* key __attribute__((unused)), - const int key_num __attribute__((unused)), + const size_t key_num __attribute__((unused)), const wsrep_key_type_t key_type __attribute__((unused)), const bool copy __attribute__((unused))) { @@ -160,7 +158,7 @@ static wsrep_status_t dummy_append_data( wsrep_t* w, wsrep_ws_handle_t* ws_handle __attribute__((unused)), const struct wsrep_buf* data __attribute__((unused)), - const int count __attribute__((unused)), + const size_t count __attribute__((unused)), const wsrep_data_type_t type __attribute__((unused)), const bool copy __attribute__((unused))) { @@ -188,9 +186,9 @@ static wsrep_status_t dummy_to_execute_start( wsrep_t* w, const wsrep_conn_id_t conn_id __attribute__((unused)), const wsrep_key_t* key __attribute__((unused)), - const int key_num __attribute__((unused)), + const size_t key_num __attribute__((unused)), const struct wsrep_buf* data __attribute__((unused)), - const int count __attribute__((unused)), + const size_t count __attribute__((unused)), wsrep_trx_meta_t* meta __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -205,14 +203,24 @@ static wsrep_status_t dummy_to_execute_end( return WSREP_OK; } -static wsrep_status_t dummy_preordered( - wsrep_t* w, - const wsrep_uuid_t* source_id __attribute__((unused)), - int pa_range __attribute__((unused)), - const struct wsrep_buf* data __attribute__((unused)), - int count __attribute__((unused)), - uint64_t flags __attribute__((unused)), - wsrep_bool_t copy __attribute__((unused))) +static wsrep_status_t dummy_preordered_collect( + wsrep_t* w, + wsrep_po_handle_t* handle __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + size_t count __attribute__((unused)), + wsrep_bool_t copy __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + +static wsrep_status_t dummy_preordered_commit( + wsrep_t* w, + wsrep_po_handle_t* handle __attribute__((unused)), + const wsrep_uuid_t* source_id __attribute__((unused)), + uint32_t flags __attribute__((unused)), + int pa_range __attribute__((unused)), + wsrep_bool_t commit __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -220,8 +228,8 @@ static wsrep_status_t dummy_preordered( static wsrep_status_t dummy_sst_sent( wsrep_t* w, - const wsrep_uuid_t* uuid __attribute__((unused)), - wsrep_seqno_t seqno __attribute__((unused))) + const wsrep_gtid_t* state_id __attribute__((unused)), + const int rcode __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -229,10 +237,10 @@ static wsrep_status_t dummy_sst_sent( static wsrep_status_t dummy_sst_received( wsrep_t* w, - const wsrep_uuid_t* uuid __attribute__((unused)), - const wsrep_seqno_t seqno __attribute__((unused)), - const char* state __attribute__((unused)), - const size_t state_len __attribute__((unused))) + const wsrep_gtid_t* state_id __attribute__((unused)), + const void* state __attribute__((unused)), + const size_t state_len __attribute__((unused)), + const int rcode __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -241,7 +249,7 @@ static wsrep_status_t dummy_sst_received( static wsrep_status_t dummy_snapshot( wsrep_t* w, const void* msg __attribute__((unused)), - const int msg_len __attribute__((unused)), + const size_t msg_len __attribute__((unused)), const char* donor_spec __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -341,7 +349,8 @@ static wsrep_t dummy_iface = { &dummy_free_connection, &dummy_to_execute_start, &dummy_to_execute_end, - &dummy_preordered, + &dummy_preordered_collect, + &dummy_preordered_commit, &dummy_sst_sent, &dummy_sst_received, &dummy_snapshot, @@ -358,7 +367,6 @@ static wsrep_t dummy_iface = { WSREP_NONE, WSREP_INTERFACE_VERSION, "Codership Oy <info@codership.com>", - 0xdeadbeef, &dummy_free, NULL, NULL |