polardbxengine/sql/rpl_trx_boundary_parser.h

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 */