Commit de7eafc7 authored by Nirbhay Choubey's avatar Nirbhay Choubey

MDEV-6368: assertion xid_seqno > trx_sys_cur_xid_seqno

- Validate the specified wsrep_start_position value by also
checking the return status of wsrep->sst_received. This also
ensures that changes in wsrep_start_position is not allowed
when the node is not in JOINING state.
- Do not allow decrease in seqno within same UUID.
- The initial checkpoint in SEs should be [0...:-1].
parent eb86c322
...@@ -17,10 +17,6 @@ SELECT @@global.wsrep_start_position; ...@@ -17,10 +17,6 @@ SELECT @@global.wsrep_start_position;
00000000-0000-0000-0000-000000000000:-1 00000000-0000-0000-0000-000000000000:-1
# valid values # valid values
SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-2';
SELECT @@global.wsrep_start_position;
@@global.wsrep_start_position
00000000-0000-0000-0000-000000000000:-2
SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:100'; SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:100';
SELECT @@global.wsrep_start_position; SELECT @@global.wsrep_start_position;
@@global.wsrep_start_position @@global.wsrep_start_position
...@@ -31,6 +27,12 @@ SELECT @@global.wsrep_start_position; ...@@ -31,6 +27,12 @@ SELECT @@global.wsrep_start_position;
00000000-0000-0000-0000-000000000000:-1 00000000-0000-0000-0000-000000000000:-1
# invalid values # invalid values
call mtr.add_suppression("WSREP: SST postion can't be set in past.*");
SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-2';
ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '00000000-0000-0000-0000-000000000000:-2'
SELECT @@global.wsrep_start_position;
@@global.wsrep_start_position
00000000-0000-0000-0000-000000000000:-1
SET @@global.wsrep_start_position='000000000000000-0000-0000-0000-000000000000:-1'; SET @@global.wsrep_start_position='000000000000000-0000-0000-0000-000000000000:-1';
ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '000000000000000-0000-0000-0000-000000000000:-1' ERROR 42000: Variable 'wsrep_start_position' can't be set to the value of '000000000000000-0000-0000-0000-000000000000:-1'
SET @@global.wsrep_start_position='12345678-1234-1234-12345-123456789012:100'; SET @@global.wsrep_start_position='12345678-1234-1234-12345-123456789012:100';
......
...@@ -19,8 +19,6 @@ SELECT @@global.wsrep_start_position; ...@@ -19,8 +19,6 @@ SELECT @@global.wsrep_start_position;
--echo --echo
--echo # valid values --echo # valid values
SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-2';
SELECT @@global.wsrep_start_position;
SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:100'; SET @@global.wsrep_start_position='12345678-1234-1234-1234-123456789012:100';
SELECT @@global.wsrep_start_position; SELECT @@global.wsrep_start_position;
SET @@global.wsrep_start_position=default; SET @@global.wsrep_start_position=default;
...@@ -28,6 +26,10 @@ SELECT @@global.wsrep_start_position; ...@@ -28,6 +26,10 @@ SELECT @@global.wsrep_start_position;
--echo --echo
--echo # invalid values --echo # invalid values
call mtr.add_suppression("WSREP: SST postion can't be set in past.*");
--error ER_WRONG_VALUE_FOR_VAR
SET @@global.wsrep_start_position='00000000-0000-0000-0000-000000000000:-2';
SELECT @@global.wsrep_start_position;
--error ER_WRONG_VALUE_FOR_VAR --error ER_WRONG_VALUE_FOR_VAR
SET @@global.wsrep_start_position='000000000000000-0000-0000-0000-000000000000:-1'; SET @@global.wsrep_start_position='000000000000000-0000-0000-0000-000000000000:-1';
--error ER_WRONG_VALUE_FOR_VAR --error ER_WRONG_VALUE_FOR_VAR
......
...@@ -5979,7 +5979,10 @@ int mysqld_main(int argc, char **argv) ...@@ -5979,7 +5979,10 @@ int mysqld_main(int argc, char **argv)
wsrep_SE_init_grab(); wsrep_SE_init_grab();
wsrep_SE_init_done(); wsrep_SE_init_done();
/*! in case of SST wsrep waits for wsrep->sst_received */ /*! in case of SST wsrep waits for wsrep->sst_received */
wsrep_sst_continue(); if (wsrep_sst_continue())
{
WSREP_ERROR("Failed to signal the wsrep provider to continue.");
}
} }
else else
{ {
......
...@@ -556,8 +556,11 @@ int wsrep_init() ...@@ -556,8 +556,11 @@ int wsrep_init()
int rcode= -1; int rcode= -1;
DBUG_ASSERT(wsrep_inited == 0); DBUG_ASSERT(wsrep_inited == 0);
if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO)) if (strcmp(wsrep_start_position, WSREP_START_POSITION_ZERO) &&
wsrep_start_position_init(wsrep_start_position); wsrep_start_position_init(wsrep_start_position))
{
return 1;
}
wsrep_sst_auth_init(wsrep_sst_auth); wsrep_sst_auth_init(wsrep_sst_auth);
......
...@@ -40,8 +40,8 @@ extern wsrep_uuid_t local_uuid; ...@@ -40,8 +40,8 @@ extern wsrep_uuid_t local_uuid;
extern wsrep_seqno_t local_seqno; extern wsrep_seqno_t local_seqno;
// a helper function // a helper function
void wsrep_sst_received(wsrep_t*, const wsrep_uuid_t&, wsrep_seqno_t, bool wsrep_sst_received(wsrep_t*, const wsrep_uuid_t&, wsrep_seqno_t,
const void*, size_t); const void*, size_t, bool const);
/*! SST thread signals init thread about sst completion */ /*! SST thread signals init thread about sst completion */
void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool); void wsrep_sst_complete(const wsrep_uuid_t*, wsrep_seqno_t, bool);
......
...@@ -264,28 +264,66 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid, ...@@ -264,28 +264,66 @@ void wsrep_sst_complete (const wsrep_uuid_t* sst_uuid,
mysql_mutex_unlock (&LOCK_wsrep_sst); mysql_mutex_unlock (&LOCK_wsrep_sst);
} }
void wsrep_sst_received (wsrep_t* const wsrep, /*
If wsrep provider is loaded, inform that the new state snapshot
has been received. Also update the local checkpoint.
@param wsrep [IN] wsrep handle
@param uuid [IN] Initial state UUID
@param seqno [IN] Initial state sequence number
@param state [IN] Always NULL, also ignored by wsrep provider (?)
@param state_len [IN] Always 0, also ignored by wsrep provider (?)
@param implicit [IN] Whether invoked implicitly due to SST
(true) or explicitly because if change
in wsrep_start_position by user (false).
@return false Success
true Error
*/
bool wsrep_sst_received (wsrep_t* const wsrep,
const wsrep_uuid_t& uuid, const wsrep_uuid_t& uuid,
wsrep_seqno_t const seqno, const wsrep_seqno_t seqno,
const void* const state, const void* const state,
size_t const state_len) const size_t state_len,
const bool implicit)
{ {
wsrep_get_SE_checkpoint(local_uuid, local_seqno); /*
To keep track of whether the local uuid:seqno should be updated. Also, note
that local state (uuid:seqno) is updated/checkpointed only after we get an
OK from wsrep provider. By doing so, the values remain consistent across
the server & wsrep provider.
*/
bool do_update= false;
// Get the locally stored uuid:seqno.
if (wsrep_get_SE_checkpoint(local_uuid, local_seqno))
{
return true;
}
if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) || if (memcmp(&local_uuid, &uuid, sizeof(wsrep_uuid_t)) ||
local_seqno < seqno || seqno < 0) local_seqno < seqno)
{ {
wsrep_set_SE_checkpoint(uuid, seqno); do_update= true;
local_uuid = uuid;
local_seqno = seqno;
} }
else if (local_seqno > seqno) else if (local_seqno > seqno)
{ {
WSREP_WARN("SST postion is in the past: %lld, current: %lld. " WSREP_WARN("SST position can't be set in past. Requested: %lld, Current: "
"Can't continue.", " %lld.", (long long)seqno, (long long)local_seqno);
(long long)seqno, (long long)local_seqno); /*
If we are here because of SET command, simply return true (error) instead of
aborting.
*/
if (implicit)
{
WSREP_WARN("Can't continue.");
unireg_abort(1); unireg_abort(1);
} }
else
{
return true;
}
}
#ifdef GTID_SUPPORT #ifdef GTID_SUPPORT
wsrep_init_sidno(uuid); wsrep_init_sidno(uuid);
...@@ -294,22 +332,42 @@ void wsrep_sst_received (wsrep_t* const wsrep, ...@@ -294,22 +332,42 @@ void wsrep_sst_received (wsrep_t* const wsrep,
if (wsrep) if (wsrep)
{ {
int const rcode(seqno < 0 ? seqno : 0); int const rcode(seqno < 0 ? seqno : 0);
wsrep_gtid_t const state_id = { wsrep_gtid_t const state_id= {uuid,
uuid, (rcode ? WSREP_SEQNO_UNDEFINED : seqno) (rcode ? WSREP_SEQNO_UNDEFINED : seqno)};
};
wsrep_status_t ret= wsrep->sst_received(wsrep, &state_id, state,
state_len, rcode);
wsrep->sst_received(wsrep, &state_id, state, state_len, rcode); if (ret != WSREP_OK)
{
return true;
}
} }
// Now is the good time to update the local state and checkpoint.
if (do_update)
{
if (wsrep_set_SE_checkpoint(uuid, seqno))
{
return true;
}
local_uuid= uuid;
local_seqno= seqno;
}
return false;
} }
// Let applier threads to continue // Let applier threads to continue
void wsrep_sst_continue () bool wsrep_sst_continue ()
{ {
if (sst_needed) if (sst_needed)
{ {
WSREP_INFO("Signalling provider to continue."); WSREP_INFO("Signalling provider to continue.");
wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0); return wsrep_sst_received (wsrep, local_uuid, local_seqno, NULL, 0, true);
} }
return false;
} }
struct sst_thread_arg struct sst_thread_arg
......
...@@ -63,7 +63,7 @@ extern void wsrep_sst_grab(); ...@@ -63,7 +63,7 @@ extern void wsrep_sst_grab();
/*! Init thread waits for SST completion */ /*! Init thread waits for SST completion */
extern bool wsrep_sst_wait(); extern bool wsrep_sst_wait();
/*! Signals wsrep that initialization is complete, writesets can be applied */ /*! Signals wsrep that initialization is complete, writesets can be applied */
extern void wsrep_sst_continue(); extern bool wsrep_sst_continue();
extern void wsrep_sst_auth_free(); extern void wsrep_sst_auth_free();
extern void wsrep_SE_init_grab(); /*! grab init critical section */ extern void wsrep_SE_init_grab(); /*! grab init critical section */
......
...@@ -81,32 +81,68 @@ bool wsrep_sync_wait_update (sys_var* self, THD* thd, enum_var_type var_type) ...@@ -81,32 +81,68 @@ bool wsrep_sync_wait_update (sys_var* self, THD* thd, enum_var_type var_type)
return false; return false;
} }
static int wsrep_start_position_verify (const char* start_str)
/*
Verify the format of the given UUID:seqno.
@return
true Fail
false Pass
*/
static
bool wsrep_start_position_verify (const char* start_str)
{ {
size_t start_len; size_t start_len;
wsrep_uuid_t uuid; wsrep_uuid_t uuid;
ssize_t uuid_len; ssize_t uuid_len;
// Check whether it has minimum acceptable length.
start_len = strlen (start_str); start_len = strlen (start_str);
if (start_len < 34) if (start_len < 34)
return 1; return true;
/*
Parse the input to check whether UUID length is acceptable
and seqno has been provided.
*/
uuid_len = wsrep_uuid_scan (start_str, start_len, &uuid); uuid_len = wsrep_uuid_scan (start_str, start_len, &uuid);
if (uuid_len < 0 || (start_len - uuid_len) < 2) if (uuid_len < 0 || (start_len - uuid_len) < 2)
return 1; return true;
if (start_str[uuid_len] != ':') // separator should follow UUID // Separator must follow the UUID.
return 1; if (start_str[uuid_len] != ':')
return true;
char* endptr; char* endptr;
wsrep_seqno_t const seqno __attribute__((unused)) // to avoid GCC warnings wsrep_seqno_t const seqno __attribute__((unused)) // to avoid GCC warnings
(strtoll(&start_str[uuid_len + 1], &endptr, 10)); (strtoll(&start_str[uuid_len + 1], &endptr, 10));
if (*endptr == '\0') return 0; // remaining string was seqno // Remaining string was seqno.
if (*endptr == '\0') return false;
return 1; return true;
} }
static
bool wsrep_set_local_position(const char* const value, size_t length,
bool const sst)
{
wsrep_uuid_t uuid;
size_t const uuid_len = wsrep_uuid_scan(value, length, &uuid);
wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10);
if (sst) {
return wsrep_sst_received (wsrep, uuid, seqno, NULL, 0, false);
} else {
// initialization
local_uuid = uuid;
local_seqno = seqno;
}
return false;
}
bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var)
{ {
char start_pos_buf[FN_REFLEN]; char start_pos_buf[FN_REFLEN];
...@@ -119,52 +155,52 @@ bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var) ...@@ -119,52 +155,52 @@ bool wsrep_start_position_check (sys_var *self, THD* thd, set_var* var)
var->save_result.string_value.length); var->save_result.string_value.length);
start_pos_buf[var->save_result.string_value.length]= 0; start_pos_buf[var->save_result.string_value.length]= 0;
if (!wsrep_start_position_verify(start_pos_buf)) return 0; // Verify the format.
if (wsrep_start_position_verify(start_pos_buf)) return true;
/*
As part of further verification, we try to update the value and catch
errors (if any).
*/
if (wsrep_set_local_position(var->save_result.string_value.str,
var->save_result.string_value.length,
true))
{
goto err;
}
return false;
err: err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str, my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name.str,
var->save_result.string_value.str ? var->save_result.string_value.str ?
var->save_result.string_value.str : "NULL"); var->save_result.string_value.str : "NULL");
return 1; return true;
}
static
void wsrep_set_local_position(const char* const value, bool const sst)
{
size_t const value_len = strlen(value);
wsrep_uuid_t uuid;
size_t const uuid_len = wsrep_uuid_scan(value, value_len, &uuid);
wsrep_seqno_t const seqno = strtoll(value + uuid_len + 1, NULL, 10);
if (sst) {
wsrep_sst_received (wsrep, uuid, seqno, NULL, 0);
} else {
// initialization
local_uuid = uuid;
local_seqno = seqno;
}
} }
bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type) bool wsrep_start_position_update (sys_var *self, THD* thd, enum_var_type type)
{ {
WSREP_INFO ("wsrep_start_position var submitted: '%s'", // Print a confirmation that wsrep_start_position has been updated.
wsrep_start_position); WSREP_INFO ("wsrep_start_position set to '%s'", wsrep_start_position);
// since this value passed wsrep_start_position_check, don't check anything return false;
// here
wsrep_set_local_position (wsrep_start_position, true);
return 0;
} }
void wsrep_start_position_init (const char* val) bool wsrep_start_position_init (const char* val)
{ {
if (NULL == val || wsrep_start_position_verify (val)) if (NULL == val || wsrep_start_position_verify (val))
{ {
WSREP_ERROR("Bad initial value for wsrep_start_position: %s", WSREP_ERROR("Bad initial value for wsrep_start_position: %s",
(val ? val : "")); (val ? val : ""));
return; return true;
} }
wsrep_set_local_position (val, false); if (wsrep_set_local_position (val, strlen(val), false))
{
WSREP_ERROR("Failed to set initial wsep_start_position: %s", val);
return true;
}
return false;
} }
static bool refresh_provider_options() static bool refresh_provider_options()
......
...@@ -48,7 +48,7 @@ extern bool wsrep_on_update UPDATE_ARGS; ...@@ -48,7 +48,7 @@ extern bool wsrep_on_update UPDATE_ARGS;
extern bool wsrep_sync_wait_update UPDATE_ARGS; extern bool wsrep_sync_wait_update UPDATE_ARGS;
extern bool wsrep_start_position_check CHECK_ARGS; extern bool wsrep_start_position_check CHECK_ARGS;
extern bool wsrep_start_position_update UPDATE_ARGS; extern bool wsrep_start_position_update UPDATE_ARGS;
extern void wsrep_start_position_init INIT_ARGS; extern bool wsrep_start_position_init INIT_ARGS;
extern bool wsrep_provider_check CHECK_ARGS; extern bool wsrep_provider_check CHECK_ARGS;
extern bool wsrep_provider_update UPDATE_ARGS; extern bool wsrep_provider_update UPDATE_ARGS;
......
...@@ -89,16 +89,17 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) ...@@ -89,16 +89,17 @@ static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
return FALSE; return FALSE;
} }
void wsrep_set_SE_checkpoint(XID& xid) bool wsrep_set_SE_checkpoint(XID& xid)
{ {
plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid); return plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
&xid);
} }
void wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno) bool wsrep_set_SE_checkpoint(const wsrep_uuid_t& uuid, wsrep_seqno_t seqno)
{ {
XID xid; XID xid;
wsrep_xid_init(&xid, uuid, seqno); wsrep_xid_init(&xid, uuid, seqno);
wsrep_set_SE_checkpoint(xid); return wsrep_set_SE_checkpoint(xid);
} }
static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
...@@ -118,12 +119,13 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg) ...@@ -118,12 +119,13 @@ static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
return FALSE; return FALSE;
} }
void wsrep_get_SE_checkpoint(XID& xid) bool wsrep_get_SE_checkpoint(XID& xid)
{ {
plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN, &xid); return plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
&xid);
} }
void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
{ {
uuid= WSREP_UUID_UNDEFINED; uuid= WSREP_UUID_UNDEFINED;
seqno= WSREP_SEQNO_UNDEFINED; seqno= WSREP_SEQNO_UNDEFINED;
...@@ -132,16 +134,24 @@ void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) ...@@ -132,16 +134,24 @@ void wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno)
memset(&xid, 0, sizeof(xid)); memset(&xid, 0, sizeof(xid));
xid.formatID= -1; xid.formatID= -1;
wsrep_get_SE_checkpoint(xid); if (wsrep_get_SE_checkpoint(xid))
{
return true;
}
if (xid.formatID == -1) return; // nil XID if (xid.formatID == -1) // nil XID
{
return false;
}
if (!wsrep_is_wsrep_xid(&xid)) if (!wsrep_is_wsrep_xid(&xid))
{ {
WSREP_WARN("Read non-wsrep XID from storage engines."); WSREP_WARN("Read non-wsrep XID from storage engines.");
return; return false;
} }
uuid= *wsrep_xid_uuid(xid); uuid= *wsrep_xid_uuid(xid);
seqno= wsrep_xid_seqno(xid); seqno= wsrep_xid_seqno(xid);
return false;
} }
...@@ -28,9 +28,9 @@ const wsrep_uuid_t* wsrep_xid_uuid(const XID&); ...@@ -28,9 +28,9 @@ const wsrep_uuid_t* wsrep_xid_uuid(const XID&);
wsrep_seqno_t wsrep_xid_seqno(const XID&); wsrep_seqno_t wsrep_xid_seqno(const XID&);
//void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */ //void wsrep_get_SE_checkpoint(XID&); /* uncomment if needed */
void wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&); bool wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&);
//void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */ //void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */
void wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t); bool wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t);
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
#endif /* WSREP_UTILS_H */ #endif /* WSREP_UTILS_H */
...@@ -349,10 +349,17 @@ trx_sys_update_wsrep_checkpoint( ...@@ -349,10 +349,17 @@ trx_sys_update_wsrep_checkpoint(
unsigned char xid_uuid[16]; unsigned char xid_uuid[16];
long long xid_seqno = read_wsrep_xid_seqno(xid); long long xid_seqno = read_wsrep_xid_seqno(xid);
read_wsrep_xid_uuid(xid, xid_uuid); read_wsrep_xid_uuid(xid, xid_uuid);
if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8)) if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 16))
{
/*
This check is a protection against the initial seqno (-1)
assigned in read_wsrep_xid_uuid(), which, if not checked,
would cause the following assertion to fail.
*/
if (xid_seqno > -1 )
{ {
ut_ad(xid_seqno > trx_sys_cur_xid_seqno); ut_ad(xid_seqno > trx_sys_cur_xid_seqno);
trx_sys_cur_xid_seqno = xid_seqno; }
} }
else else
{ {
...@@ -411,6 +418,8 @@ trx_sys_read_wsrep_checkpoint(XID* xid) ...@@ -411,6 +418,8 @@ trx_sys_read_wsrep_checkpoint(XID* xid)
+ TRX_SYS_WSREP_XID_MAGIC_N_FLD)) + TRX_SYS_WSREP_XID_MAGIC_N_FLD))
!= TRX_SYS_WSREP_XID_MAGIC_N) { != TRX_SYS_WSREP_XID_MAGIC_N) {
memset(xid, 0, sizeof(*xid)); memset(xid, 0, sizeof(*xid));
long long seqno= -1;
memcpy(xid->data + 24, &seqno, sizeof(long long));
xid->formatID = -1; xid->formatID = -1;
trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr);
mtr_commit(&mtr); mtr_commit(&mtr);
......
...@@ -353,10 +353,17 @@ trx_sys_update_wsrep_checkpoint( ...@@ -353,10 +353,17 @@ trx_sys_update_wsrep_checkpoint(
unsigned char xid_uuid[16]; unsigned char xid_uuid[16];
long long xid_seqno = read_wsrep_xid_seqno(xid); long long xid_seqno = read_wsrep_xid_seqno(xid);
read_wsrep_xid_uuid(xid, xid_uuid); read_wsrep_xid_uuid(xid, xid_uuid);
if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8)) if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 16))
{
/*
This check is a protection against the initial seqno (-1)
assigned in read_wsrep_xid_uuid(), which, if not checked,
would cause the following assertion to fail.
*/
if (xid_seqno > -1 )
{ {
ut_ad(xid_seqno > trx_sys_cur_xid_seqno); ut_ad(xid_seqno > trx_sys_cur_xid_seqno);
trx_sys_cur_xid_seqno = xid_seqno; }
} }
else else
{ {
...@@ -415,6 +422,8 @@ trx_sys_read_wsrep_checkpoint(XID* xid) ...@@ -415,6 +422,8 @@ trx_sys_read_wsrep_checkpoint(XID* xid)
+ TRX_SYS_WSREP_XID_MAGIC_N_FLD)) + TRX_SYS_WSREP_XID_MAGIC_N_FLD))
!= TRX_SYS_WSREP_XID_MAGIC_N) { != TRX_SYS_WSREP_XID_MAGIC_N) {
memset(xid, 0, sizeof(*xid)); memset(xid, 0, sizeof(*xid));
long long seqno= -1;
memcpy(xid->data + 24, &seqno, sizeof(long long));
xid->formatID = -1; xid->formatID = -1;
trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr); trx_sys_update_wsrep_checkpoint(xid, sys_header, &mtr);
mtr_commit(&mtr); mtr_commit(&mtr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment