2015-07-14 22:05:29 +02:00
|
|
|
/* Copyright 2015 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
|
2019-05-11 21:19:05 +02:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
2015-07-14 22:05:29 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
//! @file some utility functions and classes not directly related to replication
|
|
|
|
|
2017-06-18 05:42:16 +02:00
|
|
|
#include "mariadb.h"
|
2015-07-14 22:05:29 +02:00
|
|
|
#include "wsrep_xid.h"
|
|
|
|
#include "sql_class.h"
|
|
|
|
#include "wsrep_mysqld.h" // for logging macros
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
#include <mysql/service_wsrep.h>
|
|
|
|
|
|
|
|
#include <algorithm> /* std::sort() */
|
2015-07-14 22:05:29 +02:00
|
|
|
/*
|
|
|
|
* WSREPXid
|
|
|
|
*/
|
|
|
|
|
2018-03-12 11:39:30 +01:00
|
|
|
#define WSREP_XID_PREFIX "WSREPXi"
|
|
|
|
#define WSREP_XID_PREFIX_LEN 7
|
|
|
|
#define WSREP_XID_VERSION_OFFSET WSREP_XID_PREFIX_LEN
|
|
|
|
#define WSREP_XID_VERSION_1 'd'
|
|
|
|
#define WSREP_XID_VERSION_2 'e'
|
2019-04-01 13:23:05 +02:00
|
|
|
#define WSREP_XID_VERSION_3 'f'
|
2015-07-14 22:05:29 +02:00
|
|
|
#define WSREP_XID_UUID_OFFSET 8
|
|
|
|
#define WSREP_XID_SEQNO_OFFSET (WSREP_XID_UUID_OFFSET + sizeof(wsrep_uuid_t))
|
2019-04-01 13:23:05 +02:00
|
|
|
#define WSREP_XID_GTRID_LEN_V_1_2 (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
|
|
|
|
#define WSREP_XID_RPL_GTID_OFFSET (WSREP_XID_SEQNO_OFFSET + sizeof(wsrep_seqno_t))
|
|
|
|
#define WSREP_XID_GTRID_LEN_V_3 (WSREP_XID_RPL_GTID_OFFSET + sizeof(wsrep_server_gtid_t))
|
2015-07-14 22:05:29 +02:00
|
|
|
|
2019-04-01 13:23:05 +02:00
|
|
|
void wsrep_xid_init(XID* xid, const wsrep::gtid& wsgtid, const wsrep_server_gtid_t& gtid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
|
|
|
xid->formatID= 1;
|
2019-04-01 13:23:05 +02:00
|
|
|
xid->gtrid_length= WSREP_XID_GTRID_LEN_V_3;
|
2015-07-14 22:05:29 +02:00
|
|
|
xid->bqual_length= 0;
|
|
|
|
memset(xid->data, 0, sizeof(xid->data));
|
|
|
|
memcpy(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN);
|
2019-04-01 13:23:05 +02:00
|
|
|
xid->data[WSREP_XID_VERSION_OFFSET]= WSREP_XID_VERSION_3;
|
2019-01-23 12:30:00 +01:00
|
|
|
memcpy(xid->data + WSREP_XID_UUID_OFFSET, wsgtid.id().data(),sizeof(wsrep::id));
|
|
|
|
int8store(xid->data + WSREP_XID_SEQNO_OFFSET, wsgtid.seqno().get());
|
2019-04-01 13:23:05 +02:00
|
|
|
memcpy(xid->data + WSREP_XID_RPL_GTID_OFFSET, >id, sizeof(wsrep_server_gtid_t));
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
extern "C"
|
|
|
|
int wsrep_is_wsrep_xid(const void* xid_ptr)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
const XID* xid= static_cast<const XID*>(xid_ptr);
|
2015-07-14 22:05:29 +02:00
|
|
|
return (xid->formatID == 1 &&
|
|
|
|
xid->bqual_length == 0 &&
|
2019-04-01 13:23:05 +02:00
|
|
|
!memcmp(xid->data, WSREP_XID_PREFIX, WSREP_XID_PREFIX_LEN) &&
|
|
|
|
(((xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_1 ||
|
|
|
|
xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_2) &&
|
|
|
|
xid->gtrid_length == WSREP_XID_GTRID_LEN_V_1_2) ||
|
|
|
|
(xid->data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_3 &&
|
|
|
|
xid->gtrid_length == WSREP_XID_GTRID_LEN_V_3)));
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
const unsigned char* wsrep_xid_uuid(const xid_t* xid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
DBUG_ASSERT(xid);
|
|
|
|
static wsrep::id const undefined;
|
|
|
|
if (wsrep_is_wsrep_xid(xid))
|
|
|
|
return reinterpret_cast<const unsigned char*>
|
|
|
|
(xid->data + WSREP_XID_UUID_OFFSET);
|
2015-07-14 22:05:29 +02:00
|
|
|
else
|
2019-01-23 12:30:00 +01:00
|
|
|
return static_cast<const unsigned char*>(wsrep::id::undefined().data());
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
const wsrep::id& wsrep_xid_uuid(const XID& xid)
|
2018-03-07 17:40:15 +01:00
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
compile_time_assert(sizeof(wsrep::id) == sizeof(wsrep_uuid_t));
|
|
|
|
return *reinterpret_cast<const wsrep::id*>(wsrep_xid_uuid(&xid));
|
2018-03-07 17:40:15 +01:00
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
long long wsrep_xid_seqno(const xid_t* xid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
DBUG_ASSERT(xid);
|
|
|
|
long long ret= wsrep::seqno::undefined().get();
|
|
|
|
if (wsrep_is_wsrep_xid(xid))
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
switch (xid->data[WSREP_XID_VERSION_OFFSET])
|
2018-03-12 11:39:30 +01:00
|
|
|
{
|
|
|
|
case WSREP_XID_VERSION_1:
|
2019-01-23 12:30:00 +01:00
|
|
|
memcpy(&ret, xid->data + WSREP_XID_SEQNO_OFFSET, sizeof ret);
|
2018-03-12 11:39:30 +01:00
|
|
|
break;
|
|
|
|
case WSREP_XID_VERSION_2:
|
2019-04-01 13:23:05 +02:00
|
|
|
case WSREP_XID_VERSION_3:
|
2019-01-23 12:30:00 +01:00
|
|
|
ret= sint8korr(xid->data + WSREP_XID_SEQNO_OFFSET);
|
2018-03-12 11:39:30 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
2018-03-12 11:39:30 +01:00
|
|
|
return ret;
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
wsrep::seqno wsrep_xid_seqno(const XID& xid)
|
2018-03-07 17:40:15 +01:00
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
return wsrep::seqno(wsrep_xid_seqno(&xid));
|
2018-03-07 17:40:15 +01:00
|
|
|
}
|
|
|
|
|
2015-07-14 22:05:29 +02:00
|
|
|
static my_bool set_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
|
|
|
|
{
|
|
|
|
XID* xid= static_cast<XID*>(arg);
|
|
|
|
handlerton* hton= plugin_data(plugin, handlerton *);
|
|
|
|
|
|
|
|
if (hton->set_checkpoint)
|
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
const unsigned char* uuid= wsrep_xid_uuid(xid);
|
|
|
|
char uuid_str[40]= {0, };
|
|
|
|
wsrep_uuid_print((const wsrep_uuid_t*)uuid, uuid_str, sizeof(uuid_str));
|
2015-07-14 22:05:29 +02:00
|
|
|
WSREP_DEBUG("Set WSREPXid for InnoDB: %s:%lld",
|
2019-01-23 12:30:00 +01:00
|
|
|
uuid_str, (long long)wsrep_xid_seqno(xid));
|
2015-07-14 22:05:29 +02:00
|
|
|
hton->set_checkpoint(hton, xid);
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-06-01 02:37:00 +02:00
|
|
|
bool wsrep_set_SE_checkpoint(XID& xid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2016-06-01 02:37:00 +02:00
|
|
|
return plugin_foreach(NULL, set_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
|
|
|
|
&xid);
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-04-01 13:23:05 +02:00
|
|
|
bool wsrep_set_SE_checkpoint(const wsrep::gtid& wsgtid, const wsrep_server_gtid_t& gtid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
|
|
|
XID xid;
|
2019-04-01 13:23:05 +02:00
|
|
|
wsrep_xid_init(&xid, wsgtid, gtid);
|
2016-06-01 02:37:00 +02:00
|
|
|
return wsrep_set_SE_checkpoint(xid);
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static my_bool get_SE_checkpoint(THD* unused, plugin_ref plugin, void* arg)
|
|
|
|
{
|
|
|
|
XID* xid= reinterpret_cast<XID*>(arg);
|
|
|
|
handlerton* hton= plugin_data(plugin, handlerton *);
|
|
|
|
|
|
|
|
if (hton->get_checkpoint)
|
|
|
|
{
|
|
|
|
hton->get_checkpoint(hton, xid);
|
2019-01-23 12:30:00 +01:00
|
|
|
wsrep_uuid_t uuid;
|
|
|
|
memcpy(&uuid, wsrep_xid_uuid(xid), sizeof(uuid));
|
|
|
|
char uuid_str[40]= {0, };
|
|
|
|
wsrep_uuid_print(&uuid, uuid_str, sizeof(uuid_str));
|
2015-07-14 22:05:29 +02:00
|
|
|
WSREP_DEBUG("Read WSREPXid from InnoDB: %s:%lld",
|
2019-01-23 12:30:00 +01:00
|
|
|
uuid_str, (long long)wsrep_xid_seqno(xid));
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-06-01 02:37:00 +02:00
|
|
|
bool wsrep_get_SE_checkpoint(XID& xid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2016-06-01 02:37:00 +02:00
|
|
|
return plugin_foreach(NULL, get_SE_checkpoint, MYSQL_STORAGE_ENGINE_PLUGIN,
|
|
|
|
&xid);
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-04-01 13:23:05 +02:00
|
|
|
static bool wsrep_get_SE_checkpoint_common(XID& xid)
|
2015-07-14 22:05:29 +02:00
|
|
|
{
|
2018-08-03 11:21:13 +02:00
|
|
|
xid.null();
|
2015-07-14 22:05:29 +02:00
|
|
|
|
2016-06-01 02:37:00 +02:00
|
|
|
if (wsrep_get_SE_checkpoint(xid))
|
|
|
|
{
|
2019-04-01 13:23:05 +02:00
|
|
|
return FALSE;
|
2016-06-01 02:37:00 +02:00
|
|
|
}
|
2015-07-14 22:05:29 +02:00
|
|
|
|
2018-08-03 12:02:56 +02:00
|
|
|
if (xid.is_null())
|
2016-06-01 02:37:00 +02:00
|
|
|
{
|
2019-04-01 13:23:05 +02:00
|
|
|
return FALSE;
|
2016-06-01 02:37:00 +02:00
|
|
|
}
|
2015-07-14 22:05:29 +02:00
|
|
|
|
|
|
|
if (!wsrep_is_wsrep_xid(&xid))
|
|
|
|
{
|
|
|
|
WSREP_WARN("Read non-wsrep XID from storage engines.");
|
2019-04-01 13:23:05 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
wsrep::gtid wsrep_get_SE_checkpoint()
|
|
|
|
{
|
|
|
|
XID xid;
|
|
|
|
|
|
|
|
if (!wsrep_get_SE_checkpoint_common(xid))
|
|
|
|
{
|
2019-01-23 12:30:00 +01:00
|
|
|
return wsrep::gtid();
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
return wsrep::gtid(wsrep_xid_uuid(xid),wsrep_xid_seqno(xid));
|
|
|
|
}
|
|
|
|
|
2019-04-01 13:23:05 +02:00
|
|
|
template<>
|
|
|
|
wsrep_server_gtid_t wsrep_get_SE_checkpoint()
|
|
|
|
{
|
|
|
|
XID xid;
|
|
|
|
wsrep_server_gtid_t gtid= {0,0,0};
|
|
|
|
|
|
|
|
if (!wsrep_get_SE_checkpoint_common(xid))
|
|
|
|
{
|
|
|
|
return gtid;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xid.data[WSREP_XID_VERSION_OFFSET] == WSREP_XID_VERSION_3)
|
|
|
|
{
|
|
|
|
memcpy(>id, &xid.data[WSREP_XID_RPL_GTID_OFFSET], sizeof(wsrep_server_gtid_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
return gtid;
|
|
|
|
}
|
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
/*
|
|
|
|
Sort order for XIDs. Wsrep XIDs are sorted according to
|
|
|
|
seqno in ascending order. Non-wsrep XIDs are considered
|
|
|
|
equal among themselves and greater than with respect
|
|
|
|
to wsrep XIDs.
|
|
|
|
*/
|
|
|
|
struct Wsrep_xid_cmp
|
|
|
|
{
|
|
|
|
bool operator()(const XID& left, const XID& right) const
|
|
|
|
{
|
|
|
|
const bool left_is_wsrep= wsrep_is_wsrep_xid(&left);
|
|
|
|
const bool right_is_wsrep= wsrep_is_wsrep_xid(&right);
|
|
|
|
if (left_is_wsrep && right_is_wsrep)
|
|
|
|
{
|
|
|
|
return (wsrep_xid_seqno(&left) < wsrep_xid_seqno(&right));
|
|
|
|
}
|
|
|
|
else if (left_is_wsrep)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2016-06-01 02:37:00 +02:00
|
|
|
|
2019-01-23 12:30:00 +01:00
|
|
|
void wsrep_sort_xid_array(XID *array, int len)
|
|
|
|
{
|
|
|
|
std::sort(array, array + len, Wsrep_xid_cmp());
|
2015-07-14 22:05:29 +02:00
|
|
|
}
|