Skip to content

Commit

Permalink
BUG#29913991: HEARTBEAT EVENT CAN ONLY ADDRESS 32 BIT FILE OFFSET
Browse files Browse the repository at this point in the history
   Problem:

   When source sends a heartbeat event to replicas, the content of the
   heartbeat is the source's current positions (log file name and
   position).

   The log file name has its own field in the event, but the position is
   sent as the event log_pos (a 32 bits field).

   When the source sends a heartbeat event while above 4GB offset of a
   large binary log file, the log_pos of the event will overflow and will
   not match the coordinates that the replica knows about. This causes
   the replica's receiver thread to stop with an error.

   Solution:

   To fix this we have created a new flag and an event(HEARTBEAT_EVENT_V2),
   when this flag is set the source will generate the V2 of heartbeat_event.
   The new heartbeat_event will have the log_pos field type as uint64,
   so that it will be able to hold the values greater than 4 gb without any issues.

   ReviewBoard: 26931
  • Loading branch information
Neha Kumari committed Nov 19, 2021
1 parent b490ff4 commit 59e5907
Show file tree
Hide file tree
Showing 19 changed files with 795 additions and 165 deletions.
6 changes: 6 additions & 0 deletions include/mysql.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,12 @@ typedef struct MYSQL_RES {
*/
#define MYSQL_RPL_SKIP_HEARTBEAT (1 << 17)

/**
Flag to indicate that the heartbeat_event being generated
is using the class Heartbeat_event_v2
*/
#define USE_HEARTBEAT_EVENT_V2 (1 << 1)

/**
Struct for information about a replication stream.
Expand Down
1 change: 1 addition & 0 deletions libbinlogevents/include/binlog_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ enum Log_event_type {

TRANSACTION_PAYLOAD_EVENT = 40,

HEARTBEAT_LOG_EVENT_V2 = 41,
/**
Add new events here - right above this comment!
Existing events (except ENUM_END_EVENT) should never change their numbers
Expand Down
76 changes: 75 additions & 1 deletion libbinlogevents/include/codecs/binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
#ifndef CODECS_BINARY_INCLUDED
#define CODECS_BINARY_INCLUDED

#include "base.h"
#include "libbinlogevents/include/binary_log.h"
#include "libbinlogevents/include/codecs/base.h"

namespace binary_log {
namespace codecs {
Expand Down Expand Up @@ -58,6 +58,25 @@ class Base_codec : public binary_log::codecs::Codec {
*/
class Transaction_payload : public Base_codec {
public:
/**
The on-the-wire fields
*/
enum fields {
/** Marks the end of the payload header. */
OTW_PAYLOAD_HEADER_END_MARK = 0,

/** The payload field */
OTW_PAYLOAD_SIZE_FIELD = 1,

/** The compression type field */
OTW_PAYLOAD_COMPRESSION_TYPE_FIELD = 2,

/** The uncompressed size field */
OTW_PAYLOAD_UNCOMPRESSED_SIZE_FIELD = 3,

/** Other fields are appended here. */
};

Transaction_payload() = default;
/**
This member function shall decode the contents of the buffer provided and
Expand Down Expand Up @@ -92,6 +111,61 @@ class Transaction_payload : public Base_codec {
std::size_t size) const override;
};

/**
Binary codec for the heartbeat log event.
*/
class Heartbeat : public Base_codec {
public:
/**
The on-the-wire fields
*/
enum fields {
/** Marks the end of the fields. */
OTW_HB_HEADER_END_MARK = 0,

/** The log file name */
OTW_HB_LOG_FILENAME_FIELD = 1,

/** The log position field */
OTW_HB_LOG_POSITION_FIELD = 2,

/** Other fields are appended here. */
};

Heartbeat() {}
/**
This member function shall decode the contents of the buffer provided and
fill in the event referenced. Note that the event provided needs to be of
type HEARTBEAT_EVENT_V2.
@param from the buffer to decode
@param size the size of the buffer to decode.
@param to the event to store the decoded information into.
@return a pair containing the amount of bytes decoded and whether there was
an error or not. False if no error, true otherwise.
*/
std::pair<std::size_t, bool> decode(const unsigned char *from,
std::size_t size,
Binary_log_event &to) const override;

/**
This member function shall encode the contents of the event referenced and
store the result in the buffer provided. Note that the event referenced
needs to be of type HEARTBEAT_EVENT_V2.
@param from the event to encode.
@param to the buffer where to store the encoded event.
@param size the size of the buffer.
@return a pair containing the amount of bytes encoded and whether there was
an error or not.
*/
std::pair<std::size_t, bool> encode(const Binary_log_event &from,
unsigned char *to,
std::size_t size) const override;
};

} // namespace binary
} // namespace codecs
} // namespace binary_log
Expand Down
119 changes: 91 additions & 28 deletions libbinlogevents/include/control_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,26 +718,6 @@ class Transaction_payload_event : public Binary_log_event {
delete;
Transaction_payload_event(const Transaction_payload_event &) = delete;

public:
/**
The on-the-wire fields
*/
enum fields {
/** Marks the end of the payload header. */
OTW_PAYLOAD_HEADER_END_MARK = 0,

/** The payload field */
OTW_PAYLOAD_SIZE_FIELD = 1,

/** The compression type field */
OTW_PAYLOAD_COMPRESSION_TYPE_FIELD = 2,

/** The uncompressed size field */
OTW_PAYLOAD_UNCOMPRESSED_SIZE_FIELD = 3,

/** Other fields are appended here. */
};

protected:
/**
The raw bytes which are the data that this event contains.
Expand Down Expand Up @@ -776,7 +756,6 @@ class Transaction_payload_event : public Binary_log_event {
static const int MAX_DATA_LENGTH = COMPRESSION_TYPE_MAX_LENGTH +
PAYLOAD_SIZE_MAX_LENGTH +
UNCOMPRESSED_SIZE_MAX_LENGTH;

/**
Creates @c Transaction_payload_event with the given data which has the
given size.
Expand Down Expand Up @@ -1425,17 +1404,99 @@ class View_change_event : public Binary_log_event {
std::map<std::string, std::string> certification_info;
};

/**
@class Heartbeat_event_v2
Replication event to ensure to replica that source is alive.
The event is originated by source's dump thread and sent straight to
replica without being logged. Slave itself does not store it in relay log
but rather uses a data for immediate checks and throws away the event.
Two members of the class m_log_filename and m_log_position comprise
@see the rpl_event_coordinates instance. The coordinates that a heartbeat
instance carries correspond to the last event source has sent from
its binlog.
Also this event will be generated only for the source server with
version > 8.0.26
@section Heartbeat_event_v2_binary_format Binary Format
The Body has one component:
<table>
<caption>Body for Heartbeat_event</caption>
<tr>
<th>Name</th>
<th>Format</th>
<th>Description</th>
</tr>
<tr>
<td>m_log_filename</td>
<td>String variable to store the binlog name</td>
<td>Name of the current binlog being written to.</td>
</tr>
<tr>
<td>m_log_pos</td>
<td>8 byte unsigned integar</td>
<td>Name of the current binlog being written to.</td>
</tr>
</table>
*/

class Heartbeat_event_v2 : public Binary_log_event {
public:
/**
Sent by a source to a replica to let the replica know that the source is
still alive. Events of this type do not appear in the binary or relay logs.
They are generated on a source server by the thread that dumps events and
sent straight to the replica without ever being written to the binary log.
@param buf Contains the serialized event.
@param fde An FDE event (see Rotate_event constructor for more info).
*/
Heartbeat_event_v2(const char *buf, const Format_description_event *fde);

/**
Creates an empty heartbeat event.
*/
Heartbeat_event_v2();

virtual ~Heartbeat_event_v2() = default;

// Set the binlog filename
void set_log_filename(const std::string name);
// Set the position
void set_log_position(uint64_t position);
// Return the binlog filename
const std::string get_log_filename() const;
// Return the position
uint64_t get_log_position() const;

// Return the max length of an encoded packet.
static uint64_t max_encoding_length();
#ifndef HAVE_MYSYS
virtual void print_event_info(std::ostream &info) override;
virtual void print_long_info(std::ostream &info) override;
#endif
protected:
std::string m_log_filename{};
uint64_t m_log_position{0};
};

/**
@class Heartbeat_event
Replication event to ensure to slave that master is alive.
The event is originated by master's dump thread and sent straight to
slave without being logged. Slave itself does not store it in relay log
Replication event to ensure to replica that source is alive.
The event is originated by source's dump thread and sent straight to
replica without being logged. Slave itself does not store it in relay log
but rather uses a data for immediate checks and throws away the event.
Two members of the class log_ident and Binary_log_event::log_pos comprise
@see the rpl_event_coordinates instance. The coordinates that a heartbeat
instance carries correspond to the last event master has sent from
instance carries correspond to the last event source has sent from
its binlog.
@section Heartbeat_event_binary_format Binary Format
Expand All @@ -1462,17 +1523,19 @@ class View_change_event : public Binary_log_event {
class Heartbeat_event : public Binary_log_event {
public:
/**
Sent by a master to a slave to let the slave know that the master is
Sent by a source to a replica to let the replica know that the source is
still alive. Events of this type do not appear in the binary or relay logs.
They are generated on a master server by the thread that dumps events and
sent straight to the slave without ever being written to the binary log.
They are generated on a source server by the thread that dumps events and
sent straight to the replica without ever being written to the binary log.
@param buf Contains the serialized event.
@param fde An FDE event (see Rotate_event constructor for more info).
*/
Heartbeat_event(const char *buf, const Format_description_event *fde);

// Return the file name
const char *get_log_ident() { return log_ident; }
// Return the length of file name
unsigned int get_ident_len() { return ident_len; }

protected:
Expand Down
Loading

0 comments on commit 59e5907

Please sign in to comment.