227 lines
7.3 KiB
Objective-C
227 lines
7.3 KiB
Objective-C
/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
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, version 2.0, 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 St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
/**
|
|
@addtogroup Replication
|
|
@{
|
|
|
|
@file
|
|
|
|
@brief Transaction boundary parser definitions. This includes code for
|
|
parsing a stream of events identifying the transaction boundaries (like
|
|
if the event is starting a transaction, is in the middle of a transaction
|
|
or if the event is ending a transaction).
|
|
*/
|
|
|
|
#ifndef RPL_TRX_BOUNDARY_PARSER_H
|
|
#define RPL_TRX_BOUNDARY_PARSER_H
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "libbinlogevents/include/control_events.h"
|
|
#include "my_dbug.h"
|
|
|
|
/**
|
|
@class Transaction_boundary_parser
|
|
|
|
This is the base class for verifying transaction boundaries in a replication
|
|
event stream.
|
|
*/
|
|
class Transaction_boundary_parser {
|
|
public:
|
|
/**
|
|
Constructor.
|
|
*/
|
|
Transaction_boundary_parser()
|
|
: current_parser_state(EVENT_PARSER_NONE),
|
|
last_parser_state(EVENT_PARSER_NONE) {
|
|
DBUG_TRACE;
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Reset the transaction boundary parser state.
|
|
*/
|
|
void reset();
|
|
|
|
/*
|
|
In an event stream, an event is considered safe to be separated from the
|
|
next if it is not inside a transaction.
|
|
We need to know this in order to evaluate if we will let the relay log
|
|
to be rotated or not.
|
|
*/
|
|
|
|
/**
|
|
State if the transaction boundary parser is inside a transaction.
|
|
This "inside a transaction" means that the parser was fed with at least
|
|
one event of a transaction, but the transaction wasn't completely fed yet.
|
|
This also means that the last event fed depends on following event(s) to
|
|
be correctly applied.
|
|
|
|
@return false if the boundary parser is not inside a transaction.
|
|
true if the boundary parser is inside a transaction.
|
|
*/
|
|
inline bool is_inside_transaction() {
|
|
return (current_parser_state != EVENT_PARSER_ERROR &&
|
|
current_parser_state != EVENT_PARSER_NONE);
|
|
}
|
|
|
|
/**
|
|
State if the transaction boundary parser is not inside a transaction.
|
|
This "not inside a transaction" means that the parser was fed with an
|
|
event that doesn't depend on following events.
|
|
|
|
@return false if the boundary parser is inside a transaction.
|
|
true if the boundary parser is not inside a transaction.
|
|
*/
|
|
inline bool is_not_inside_transaction() {
|
|
return (current_parser_state == EVENT_PARSER_NONE);
|
|
}
|
|
|
|
/**
|
|
State if the transaction boundary parser was fed with a sequence of events
|
|
that the parser wasn't able to parse correctly.
|
|
|
|
@return false if the boundary parser is not in the error state.
|
|
true if the boundary parser is in the error state.
|
|
*/
|
|
inline bool is_error() {
|
|
return (current_parser_state == EVENT_PARSER_ERROR);
|
|
}
|
|
|
|
/**
|
|
Feed the transaction boundary parser with a Log_event of any type,
|
|
serialized into a char* buffer.
|
|
|
|
@param buf Pointer to the event buffer.
|
|
@param length The size of the event buffer.
|
|
@param fd_event The description event of the master which logged
|
|
the event.
|
|
@param throw_warnings If the function should throw warning messages while
|
|
updating the boundary parser state.
|
|
While initializing the Relay_log_info the
|
|
relay log is scanned backwards and this could
|
|
generate false errors. So, in this case, we
|
|
don't want to throw warnings.
|
|
|
|
@return false if the transaction boundary parser accepted the event.
|
|
true if the transaction boundary parser didn't accepted the event.
|
|
*/
|
|
bool feed_event(const char *buf, size_t length,
|
|
const binary_log::Format_description_event *fd_event,
|
|
bool throw_warnings);
|
|
|
|
/**
|
|
Rolls back to the last parser state.
|
|
|
|
This should be called in the case of a failed queued event.
|
|
*/
|
|
void rollback() { current_parser_state = last_parser_state; }
|
|
|
|
private:
|
|
enum enum_event_boundary_type {
|
|
EVENT_BOUNDARY_TYPE_ERROR = -1,
|
|
/* Gtid_log_event */
|
|
EVENT_BOUNDARY_TYPE_GTID = 0,
|
|
/* Query_log_event(BEGIN), Query_log_event(XA START) */
|
|
EVENT_BOUNDARY_TYPE_BEGIN_TRX = 1,
|
|
/* Xid, Query_log_event(COMMIT), Query_log_event(ROLLBACK),
|
|
XA_Prepare_log_event */
|
|
EVENT_BOUNDARY_TYPE_END_TRX = 2,
|
|
/* Query_log_event(XA ROLLBACK) */
|
|
EVENT_BOUNDARY_TYPE_END_XA_TRX = 3,
|
|
/* User_var, Intvar and Rand */
|
|
EVENT_BOUNDARY_TYPE_PRE_STATEMENT = 4,
|
|
/*
|
|
All other Query_log_events and all other DML events
|
|
(Rows, Load_data, etc.)
|
|
*/
|
|
EVENT_BOUNDARY_TYPE_STATEMENT = 5,
|
|
/* Incident */
|
|
EVENT_BOUNDARY_TYPE_INCIDENT = 6,
|
|
/*
|
|
All non DDL/DML events: Format_desc, Rotate,
|
|
Previous_gtids, Stop, etc.
|
|
*/
|
|
EVENT_BOUNDARY_TYPE_IGNORE = 7
|
|
};
|
|
|
|
/*
|
|
Internal states for parsing a stream of events.
|
|
|
|
DDL has the format:
|
|
DDL-1: [GTID]
|
|
DDL-2: [User] [Intvar] [Rand]
|
|
DDL-3: Query
|
|
|
|
DML has the format:
|
|
DML-1: [GTID]
|
|
DML-2: Query(BEGIN)
|
|
DML-3: Statements
|
|
DML-4: (Query(COMMIT) | Query([XA] ROLLBACK) | Xid | Xa_prepare)
|
|
*/
|
|
enum enum_event_parser_state {
|
|
/* NONE is set after DDL-3 or DML-4 */
|
|
EVENT_PARSER_NONE,
|
|
/* GTID is set after DDL-1 or DML-1 */
|
|
EVENT_PARSER_GTID,
|
|
/* DDL is set after DDL-2 */
|
|
EVENT_PARSER_DDL,
|
|
/* DML is set after DML-2 */
|
|
EVENT_PARSER_DML,
|
|
/* ERROR is set whenever the above pattern is not followed */
|
|
EVENT_PARSER_ERROR
|
|
};
|
|
|
|
/**
|
|
Current internal state of the event parser.
|
|
*/
|
|
enum_event_parser_state current_parser_state;
|
|
|
|
/**
|
|
Last internal state of the event parser.
|
|
|
|
This should be used if we had to roll back the last parsed event.
|
|
*/
|
|
enum_event_parser_state last_parser_state;
|
|
|
|
/**
|
|
Parses an event based on the event parser logic.
|
|
*/
|
|
static enum_event_boundary_type get_event_boundary_type(
|
|
const char *buf, size_t length,
|
|
const binary_log::Format_description_event *fd_event,
|
|
bool throw_warnings);
|
|
|
|
/**
|
|
Set the boundary parser state based on the event parser logic.
|
|
*/
|
|
bool update_state(enum_event_boundary_type event_boundary_type,
|
|
bool throw_warnings);
|
|
};
|
|
|
|
/**
|
|
@} (End of group Replication)
|
|
*/
|
|
|
|
#endif /* RPL_TRX_BOUNDARY_PARSER_H */
|