464 lines
14 KiB
Objective-C
464 lines
14 KiB
Objective-C
/* Copyright (c) 2018, 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 */
|
|
|
|
#ifndef CONSISTENCY_MANAGER_INCLUDED
|
|
#define CONSISTENCY_MANAGER_INCLUDED
|
|
|
|
#define CONSISTENCY_INFO_OUTCOME_OK 0
|
|
#define CONSISTENCY_INFO_OUTCOME_ERROR 1
|
|
#define CONSISTENCY_INFO_OUTCOME_COMMIT 2
|
|
|
|
#include <mysql/group_replication_priv.h>
|
|
#include <mysql/plugin_group_replication.h>
|
|
#include <atomic>
|
|
#include <list>
|
|
#include <map>
|
|
#include <utility>
|
|
|
|
#include "my_dbug.h"
|
|
#include "plugin/group_replication/include/member_info.h"
|
|
#include "plugin/group_replication/include/pipeline_interfaces.h"
|
|
#include "plugin/group_replication/include/plugin_observers/group_transaction_observation_manager.h"
|
|
#include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/gcs_member_identifier.h"
|
|
|
|
/**
|
|
@class Transaction_consistency_info
|
|
|
|
The consistency information of a transaction, including its
|
|
configuration and state.
|
|
*/
|
|
class Transaction_consistency_info {
|
|
public:
|
|
/**
|
|
Constructor
|
|
|
|
@param[in] thread_id the thread that is executing the transaction
|
|
@param[in] local_transaction true if this transaction did originate from
|
|
this server
|
|
@param[in] sid transaction sid
|
|
@param[in] sidno transaction sidno
|
|
@param[in] gno transaction gno
|
|
@param[in] consistency_level the transaction consistency
|
|
@param[in] members_that_must_prepare_the_transaction
|
|
list of the members that must prepare the
|
|
transaction before it is allowed to commit
|
|
*/
|
|
Transaction_consistency_info(
|
|
my_thread_id thread_id, bool local_transaction, const rpl_sid *sid,
|
|
rpl_sidno sidno, rpl_gno gno,
|
|
enum_group_replication_consistency_level consistency_level,
|
|
std::list<Gcs_member_identifier>
|
|
*members_that_must_prepare_the_transaction);
|
|
|
|
virtual ~Transaction_consistency_info();
|
|
|
|
/**
|
|
Get the thread id that is executing the transaction.
|
|
|
|
@return the thread id
|
|
*/
|
|
my_thread_id get_thread_id();
|
|
|
|
/**
|
|
Is the transaction from this server?
|
|
|
|
@return true yes
|
|
false otherwise
|
|
*/
|
|
bool is_local_transaction();
|
|
|
|
/**
|
|
Is the transaction prepared locally?
|
|
|
|
@return true yes
|
|
false otherwise
|
|
*/
|
|
bool is_transaction_prepared_locally();
|
|
|
|
/**
|
|
Get the transaction sidno.
|
|
|
|
@return the sidno
|
|
*/
|
|
rpl_sidno get_sidno();
|
|
|
|
/**
|
|
Get the transaction gno.
|
|
|
|
@return the gno
|
|
*/
|
|
rpl_gno get_gno();
|
|
|
|
/**
|
|
Get the transaction consistency.
|
|
|
|
@return the consistency
|
|
*/
|
|
enum_group_replication_consistency_level get_consistency_level();
|
|
|
|
/**
|
|
Is this transaction running on a single member group?
|
|
|
|
@return true yes
|
|
false otherwise
|
|
*/
|
|
bool is_a_single_member_group();
|
|
|
|
/**
|
|
Did all other ONLINE members already prepared the transaction?
|
|
|
|
@return true yes
|
|
false otherwise
|
|
*/
|
|
bool is_the_transaction_prepared_remotely();
|
|
|
|
/**
|
|
Call action after this transaction being prepared on this member
|
|
applier.
|
|
|
|
@param[in] thread_id the applier thread id
|
|
@param[in] member_status this member status
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int after_applier_prepare(
|
|
my_thread_id thread_id,
|
|
Group_member_info::Group_member_status member_status);
|
|
|
|
/**
|
|
Call action after this transaction being prepared by other member.
|
|
|
|
@param[in] gcs_member_id the member id
|
|
|
|
@return Operation status
|
|
@retval CONSISTENCY_INFO_OUTCOME_OK OK
|
|
@retval CONSISTENCY_INFO_OUTCOME_ERROR error
|
|
@retval CONSISTENCY_INFO_OUTCOME_COMMIT transaction must proceeded to
|
|
commit
|
|
*/
|
|
int handle_remote_prepare(const Gcs_member_identifier &gcs_member_id);
|
|
|
|
/**
|
|
Call action after members leave the group.
|
|
If any of these members are on the prepare wait list, they will
|
|
be removed. If the lists becomes empty, the transaction will proceed
|
|
to commit.
|
|
|
|
@param[in] leaving_members the members that left
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int handle_member_leave(
|
|
const std::vector<Gcs_member_identifier> &leaving_members);
|
|
|
|
private:
|
|
my_thread_id m_thread_id;
|
|
const bool m_local_transaction;
|
|
const bool m_sid_specified;
|
|
rpl_sid m_sid;
|
|
const rpl_sidno m_sidno;
|
|
const rpl_gno m_gno;
|
|
const enum_group_replication_consistency_level m_consistency_level;
|
|
std::list<Gcs_member_identifier> *m_members_that_must_prepare_the_transaction;
|
|
bool m_transaction_prepared_locally;
|
|
bool m_transaction_prepared_remotely;
|
|
};
|
|
|
|
typedef std::pair<rpl_sidno, rpl_gno> Transaction_consistency_manager_key;
|
|
typedef std::pair<Transaction_consistency_manager_key,
|
|
Transaction_consistency_info *>
|
|
Transaction_consistency_manager_pair;
|
|
typedef std::map<Transaction_consistency_manager_key,
|
|
Transaction_consistency_info *>
|
|
Transaction_consistency_manager_map;
|
|
|
|
/**
|
|
@class Transaction_consistency_manager
|
|
|
|
The consistency information of all ongoing transactions which have
|
|
consistency GROUP_REPLICATION_CONSISTENCY_BEFORE,
|
|
GROUP_REPLICATION_CONSISTENCY_AFTER or
|
|
GROUP_REPLICATION_CONSISTENCY_BEFORE_AND_AFTER.
|
|
*/
|
|
class Transaction_consistency_manager : public Group_transaction_listener {
|
|
public:
|
|
/**
|
|
Constructor.
|
|
*/
|
|
Transaction_consistency_manager();
|
|
|
|
virtual ~Transaction_consistency_manager();
|
|
|
|
/**
|
|
Clear all information.
|
|
*/
|
|
void clear();
|
|
|
|
/**
|
|
Call action after a transaction is certified.
|
|
The transaction coordination among the members will start on
|
|
this point.
|
|
|
|
@param[in] transaction_info the transaction info
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int after_certification(Transaction_consistency_info *transaction_info);
|
|
|
|
/**
|
|
Call action after a transaction being prepared on this member
|
|
applier.
|
|
|
|
@param[in] sidno the transaction sidno
|
|
@param[in] gno the transaction gno
|
|
@param[in] thread_id the applier thread id
|
|
@param[in] member_status this member status
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int after_applier_prepare(
|
|
rpl_sidno sidno, rpl_gno gno, my_thread_id thread_id,
|
|
Group_member_info::Group_member_status member_status);
|
|
|
|
/**
|
|
Call action after a transaction being prepared by other member.
|
|
|
|
If this sid is NULL that means this transaction sid is the group
|
|
name.
|
|
|
|
@param[in] sid the transaction sid
|
|
@param[in] gno the transaction gno
|
|
@param[in] gcs_member_id the member id
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int handle_remote_prepare(const rpl_sid *sid, rpl_gno gno,
|
|
const Gcs_member_identifier &gcs_member_id);
|
|
|
|
/**
|
|
Call action after members leave the group.
|
|
If any of these members are on the prepare wait lists, they will
|
|
be removed. If any those lists become empty, those transactions
|
|
proceed to commit.
|
|
|
|
@param[in] leaving_members the members that left
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int handle_member_leave(
|
|
const std::vector<Gcs_member_identifier> &leaving_members);
|
|
|
|
/**
|
|
Call action after commit a transaction on this member.
|
|
If new transactions are waiting for this prepared transaction
|
|
to be committed, they will be released.
|
|
|
|
@param[in] thread_id the transaction thread id
|
|
@param[in] sidno the transaction sidno
|
|
@param[in] gno the transaction gno
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
virtual int after_commit(my_thread_id thread_id, rpl_sidno sidno,
|
|
rpl_gno gno);
|
|
|
|
/**
|
|
Call action before a transaction starts.
|
|
It will handle transactions with
|
|
GROUP_REPLICATION_CONSISTENCY_BEFORE consistency and any others
|
|
that need to wait for preceding prepared transactions to
|
|
commit.
|
|
|
|
@param[in] thread_id the thread that is executing the
|
|
transaction
|
|
@param[in] gr_consistency_level the transaction consistency
|
|
@param[in] timeout maximum time to wait
|
|
@param[in] rpl_channel_type type of the channel that receives the
|
|
transaction
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
virtual int before_transaction_begin(my_thread_id thread_id,
|
|
ulong gr_consistency_level,
|
|
ulong timeout,
|
|
enum_rpl_channel_type rpl_channel_type);
|
|
|
|
/**
|
|
Call action once a Sync_before_execution_message is received,
|
|
this will allow fetch the group transactions set ordered with
|
|
the message order.
|
|
|
|
@param[in] thread_id the thread that is executing the
|
|
transaction
|
|
@param[in] gcs_member_id the member id
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int handle_sync_before_execution_message(
|
|
my_thread_id thread_id, const Gcs_member_identifier &gcs_member_id) const;
|
|
|
|
/**
|
|
Are there local prepared transactions waiting for prepare
|
|
acknowledge from other members?
|
|
|
|
@return true yes
|
|
false otherwise
|
|
*/
|
|
bool has_local_prepared_transactions();
|
|
|
|
/**
|
|
Schedule a View_change_log_event log into the relay to after
|
|
the local prepared transactions are complete, since those
|
|
transactions belong to the previous view and as such must be
|
|
logged before this view.
|
|
|
|
@param[in] pevent the pipeline event that contains
|
|
the View_change_log_event
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int schedule_view_change_event(Pipeline_event *pevent);
|
|
|
|
/**
|
|
Inform that plugin did start.
|
|
*/
|
|
void plugin_started();
|
|
|
|
/**
|
|
Inform that plugin is stopping.
|
|
New consistent transactions are not allowed to start.
|
|
On after_applier_prepare the transactions do not wait
|
|
for other prepares.
|
|
*/
|
|
void plugin_is_stopping();
|
|
|
|
/**
|
|
Register an observer for transactions
|
|
*/
|
|
void register_transaction_observer();
|
|
|
|
/**
|
|
Unregister the observer for transactions
|
|
*/
|
|
void unregister_transaction_observer();
|
|
|
|
virtual int before_commit(
|
|
my_thread_id thread_id,
|
|
Group_transaction_listener::enum_transaction_origin origin);
|
|
|
|
virtual int before_rollback(
|
|
my_thread_id thread_id,
|
|
Group_transaction_listener::enum_transaction_origin origin);
|
|
|
|
virtual int after_rollback(my_thread_id thread_id);
|
|
|
|
private:
|
|
/**
|
|
Help method called by transaction begin action that, for
|
|
transactions with consistency GROUP_REPLICATION_CONSISTENCY_BEFORE
|
|
or GROUP_REPLICATION_CONSISTENCY_BEFORE_AND_AFTER will:
|
|
1) send a message to all members;
|
|
2) when that message is received and processed in-order,
|
|
w.r.t. the message stream, will fetch the Group Replication
|
|
applier RECEIVED_TRANSACTION_SET, the set of remote
|
|
transactions that were allowed to commit;
|
|
3) wait until all the transactions on Group Replication applier
|
|
RECEIVED_TRANSACTION_SET are committed.
|
|
|
|
@param[in] thread_id the thread that is executing the
|
|
transaction
|
|
@param[in] consistency_level the transaction consistency
|
|
@param[in] timeout maximum time to wait
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int transaction_begin_sync_before_execution(
|
|
my_thread_id thread_id,
|
|
enum_group_replication_consistency_level consistency_level,
|
|
ulong timeout) const;
|
|
|
|
/**
|
|
Help method called by transaction begin action that, if there are
|
|
precedent prepared transactions with consistency
|
|
GROUP_REPLICATION_CONSISTENCY_AFTER or
|
|
GROUP_REPLICATION_CONSISTENCY_BEFORE_AND_AFTER, will hold the
|
|
this transaction until the prepared are committed.
|
|
|
|
@param[in] thread_id the thread that is executing the
|
|
transaction
|
|
@param[in] timeout maximum time to wait
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int transaction_begin_sync_prepared_transactions(my_thread_id thread_id,
|
|
ulong timeout);
|
|
|
|
/**
|
|
Help method that cleans prepared transactions and releases
|
|
transactions waiting on them.
|
|
|
|
@param[in] key the transaction key
|
|
|
|
@return Operation status
|
|
@retval 0 OK
|
|
@retval !=0 error
|
|
*/
|
|
int remove_prepared_transaction(Transaction_consistency_manager_key key);
|
|
|
|
Checkable_rwlock *m_map_lock;
|
|
Transaction_consistency_manager_map m_map;
|
|
|
|
Checkable_rwlock *m_prepared_transactions_on_my_applier_lock;
|
|
std::list<Transaction_consistency_manager_key>
|
|
m_prepared_transactions_on_my_applier;
|
|
std::list<my_thread_id> m_new_transactions_waiting;
|
|
std::list<Pipeline_event *> m_delayed_view_change_events;
|
|
|
|
std::atomic<bool> m_plugin_stopping;
|
|
};
|
|
|
|
#endif /* CONSISTENCY_MANAGER_INCLUDED */
|