###############################################################################
#
# When primary member is proposed
# - 1: A new election shall happen in all members appointing the
#   proposed member as the new primary
# - 2: While all updates from the old primary previous to the
#   election are not applied, the new primary must stay in read mode.
# - 3: While updates from the old and new primaries are in the
#   group, any transactional conflict between them must abort.
#
# Test:
#   0. This test requires two servers in single primary mode
#   1. Bootstrap the group with server1 and create table test.t1 and test.t2
#   2. Start server2 and lock writes to table t1
#   3. Insert values on table t1 on server 1
#   4. Set server2 as primary
#   5. Consult stages to guarantee that server2 is waiting on the execution
#      of server 1 transactions.
#      Server2 must be in read mode
#   6. Send a transaction to table2 on server1. Block it on sending.
#   7. Unlock the table1 on server2. The member shall unset the read mode
#      The member shall now wait for server1 to be in read mode
#   8. Send a transaction to table2 on server2. Block it on sending.
#   9. Unblock the transaction on server1
#   10. Check the status of server2 transaction. It should have failed
#   11. The group_replication_set_as_primary will succeed
#   12. Server2 is the new primary
#   13. Cleanup
#
###############################################################################

--source include/have_debug_sync.inc
--source include/have_group_replication_plugin.inc
--let $rpl_skip_group_replication_start= 1
--let $rpl_group_replication_single_primary_mode=1
--source include/group_replication.inc

--echo
--echo # 1. Bootstrap the group with server1 and create table test.t1 and test.t2

--source include/start_and_bootstrap_group_replication.inc

CREATE TABLE test.t1 (a INT PRIMARY KEY);
CREATE TABLE test.t2 (a INT PRIMARY KEY);

--echo
--echo # 2. Start server2 and lock writes to table t1

--let $rpl_connection_name= server2
--source include/rpl_connection.inc
--source include/start_group_replication.inc

--let $server2_uuid= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)

LOCK TABLE t1 READ;

--echo
--echo # 3. Insert values on table t1 on server 1

--let $rpl_connection_name= server1
--source include/rpl_connection.inc

INSERT INTO t1 VALUES (1);
INSERT INTO t1 VALUES (2);

--echo
--echo # 4. Set server2 as primary

--replace_result $server2_uuid MEMBER2_UUID
--send_eval SELECT group_replication_set_as_primary("$server2_uuid")

--let $rpl_connection_name= server_1
--source include/rpl_connection.inc

--let $assert_text= The super_read_only mode should be 0 here.
--let $assert_cond= "[SELECT @@GLOBAL.super_read_only]" = 0;
--source include/assert.inc

--echo
--echo # 5. Consult stages to guarantee that server2 is
--echo #    waiting on the execution of serve 1 transactions.
--echo #    Server2 must be in read mode

--let $rpl_connection_name= server2
--source include/rpl_connection.inc

--let $wait_condition=SELECT COUNT(*)=1 FROM performance_schema.events_stages_current WHERE event_name LIKE "%Primary Election: applying buffered transactions%"
--source include/wait_condition.inc

--let $stage_name= `SELECT event_name FROM performance_schema.events_stages_current WHERE event_name LIKE "%stage/group_rpl/Primary Election%";`
--let $assert_text= stage/group_rpl/Primary Election: applying buffered transactions
--let $assert_cond= "$stage_name" = "stage/group_rpl/Primary Election: applying buffered transactions"
--source include/assert.inc

--let $received_transaction_set= query_get_value(SELECT received_transaction_set FROM performance_schema.replication_connection_status WHERE channel_name="group_replication_applier", received_transaction_set, 1)
--let $assert_text= The value of received_transaction_set must contain the 2 creates and 2 inserts
--let $assert_cond= "$received_transaction_set" = "$group_replication_group_name:4-6"
--source include/assert.inc

--let $assert_text= The super_read_only mode should be 1 here.
--let $assert_cond= "[SELECT @@GLOBAL.super_read_only]" = 1;
--source include/assert.inc

--echo
--echo # 6. Send a transaction to table2 on server1.
--echo #    Block it on sending

--let $rpl_connection_name= server_1
--source include/rpl_connection.inc

SET @@GLOBAL.DEBUG='+d,group_replication_before_message_broadcast';

--let $rpl_connection_name= server_1_1
--source include/rpl_connection.inc

--send INSERT INTO t2 VALUES (1)

--let $rpl_connection_name= server_1
--source include/rpl_connection.inc

--let $wait_condition=SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'debug sync point: now'
--source include/wait_condition.inc

--echo
--echo # 7. Unlock the table1 on server2
--echo #    The member shall unset the read mode
--echo #    The member shall now wait for server1 to be in read mode

--let $rpl_connection_name= server2
--source include/rpl_connection.inc

UNLOCK TABLES;

--let $wait_condition=SELECT COUNT(*)=1 FROM performance_schema.events_stages_current WHERE event_name LIKE "%super_read_only%"
--source include/wait_condition.inc

--let $stage_name= `SELECT event_name FROM performance_schema.events_stages_current WHERE event_name LIKE "%stage/group_rpl/Primary Election%";`
--let $assert_text= stage/group_rpl/Primary Election: waiting for members to enable super_read_only
--let $assert_cond= "$stage_name" = "stage/group_rpl/Primary Election: waiting for members to enable super_read_only"
--source include/assert.inc

--let $assert_text= The super_read_only mode should be 0 here.
--let $assert_cond= "[SELECT @@GLOBAL.super_read_only]" = 0;
--source include/assert.inc

--echo
--echo # 8. Send a transaction to table2 on server2.
--echo #    Block it on sending

--let $rpl_connection_name= server_2
--source include/rpl_connection.inc

SET @@GLOBAL.DEBUG='+d,group_replication_before_message_broadcast';

--let $rpl_connection_name= server_2_1
--source include/rpl_connection.inc

--send INSERT INTO t2 VALUES (1)

--let $rpl_connection_name= server_2
--source include/rpl_connection.inc

--let $wait_condition=SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'debug sync point: now'
--source include/wait_condition.inc

--echo
--echo # 9. Unblock the transaction on server1

--let $rpl_connection_name= server_1
--source include/rpl_connection.inc

SET DEBUG_SYNC='now SIGNAL waiting';
SET @@GLOBAL.DEBUG='-d,group_replication_before_message_broadcast';

--let $rpl_connection_name= server_1_1
--source include/rpl_connection.inc

--reap

--echo
--echo # 10. Check the status of server2 transaction.
--echo #     It should have failed

--let $rpl_connection_name= server_2
--source include/rpl_connection.inc

SET DEBUG_SYNC='now SIGNAL waiting';
SET @@GLOBAL.DEBUG='-d,group_replication_before_message_broadcast';

--let $rpl_connection_name= server_2_1
--source include/rpl_connection.inc

--error ER_TRANSACTION_ROLLBACK_DURING_COMMIT
--reap

--echo
--echo # 11. The group_replication_set_as_primary will succeed

--let $rpl_connection_name= server1
--source include/rpl_connection.inc

--replace_result $server2_uuid MEMBER2_UUID
--reap

--echo
--echo # 12. Server2 is the new primary

--let $rpl_connection_name= server2
--source include/rpl_connection.inc

--source include/gr_assert_primary_member.inc

--let $rpl_connection_name= server1
--source include/rpl_connection.inc

--source include/gr_assert_secondary_member.inc

--echo
--echo # 13. Cleanup

--let $rpl_connection_name= server2
--source include/rpl_connection.inc

DROP TABLE t1;
DROP TABLE t2;

--let $rpl_group_replication_reset_persistent_vars=1
--source include/group_replication_end.inc
