#Want to skip this test from daily Valgrind execution
--source include/no_valgrind_without_big.inc
# ==== Purpose ====
#
# Stress-test concurrent re-execution of transactions generated with
# GTID_MODE = ON.
#
# ==== Implementation ====
#
# 1. Generate a load on the master consisting of:
#     - transactions (INSERT/UPDATE/DELETE)
#     - DDL (ALTER and RENAME)
#     - FLUSH LOGS
#    Do not replicate anything.
#
# 2. Apply the binary logs on the slave (which is fresh).  The binary
#    logs are applied in N parallel connections.  In addition, for
#    increased concurrency, we open N concurrent connections that
#    repeatedly execute SHOW SLAVE STATUS, and N concurrent
#    connections that repeatedly read @@GLOBAL.GTID_EXECUTED and
#    @@GLOBAL.GTID_PURGED.
#
# 3. Check that master and slave have the same data.
#
# ==== References ====
#
# Implemented as part of WL#3584: Global Transaction Identifiers

--source include/big_test.inc
--source include/have_gtid.inc
--source include/master-slave.inc
--source include/not_windows.inc

--echo ==== Configure ====

--let $max_iterations= 10000
--let $max_seconds= 100
--let $n_forks= 8
--let $flush_probability= 0.05
--let $rename_probability= 0.1

--echo ==== Initialize ====

--enable_connect_log
--connection slave
--source include/stop_slave.inc

--delimiter |
CREATE PROCEDURE show_slave_status ()
BEGIN
  DECLARE name VARCHAR(100) DEFAULT('');
  WHILE name = '' DO
    SHOW SLAVE STATUS;
    SELECT TABLE_NAME INTO name
      FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 't_end';
  END WHILE;
END|

CREATE PROCEDURE read_gtid_executed ()
BEGIN
  DECLARE name VARCHAR(100) DEFAULT('');
  DECLARE temp VARCHAR(10000) DEFAULT('');
  WHILE name = '' DO
    SET temp = @@GLOBAL.GTID_EXECUTED;
    SET temp = @@GLOBAL.GTID_OWNED;
    SELECT TABLE_NAME INTO name
      FROM INFORMATION_SCHEMA.TABLES
      WHERE TABLE_NAME = 't_end';
  END WHILE;
END|
--delimiter ;

--connection master

--let $t= 1
eval CREATE TABLE t1_$t (a INT) ENGINE = InnoDB;
eval CREATE TABLE t2_$t (a INT) ENGINE = InnoDB;
eval INSERT INTO t1_$t VALUES (0);
eval INSERT INTO t2_$t VALUES (0);

--echo ==== Generate binary log ====

--let $iteration= 1
--let $start_time= `SELECT UNIX_TIMESTAMP()`
--let $done= 0
--disable_query_log
while (!$done)
{
  --let $rand_type= decide
  --let $rand_probability= $rename_probability
  --source include/rand.inc
  if ($rand)
  {
    --let $last_t= $t
    --inc $t
    eval ALTER TABLE t1_$last_t RENAME TO t1_$t;
    eval RENAME TABLE t2_$last_t TO t2_$t;
  }
  BEGIN;
  eval INSERT INTO t2_$t VALUES ($iteration);
  eval UPDATE t1_$t SET a = $iteration WHERE a = $iteration - 1;
  eval DELETE FROM t2_$t WHERE a = $iteration - 1;
  COMMIT;

  --let $rand_type= decide
  --let $rand_probability= $flush_probability
  --source include/rand.inc
  if ($rand)
  {
    FLUSH LOGS;
  }
  --inc $iteration

  if ($iteration >= $max_iterations)
  {
    --let $done= 1
  }
  if (`SELECT UNIX_TIMESTAMP() - $start_time > $max_seconds`)
  {
    --let $done= 1
  }
}
--enable_query_log
CREATE TABLE t_end (a INT);

--echo ==== Apply the generated binary logs ====

--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
--let $data_dir= `SELECT @@datadir`
--let _BINLOG_FILE= $data_dir/$binlog_file
--let _N_FORKS= $n_forks

perl;
  my $mysql_pipe= "| $ENV{MYSQL} --defaults-group-suffix=.2";
  my $file= $ENV{_BINLOG_FILE};
  $file=~ s/0*([1-9][0-9]*)$//;
  my $number= $1;
  my @mysqlbinlog_commands=
    map { sprintf("$ENV{MYSQL_BINLOG} %s%06d", $file, $_) } 1 .. $number;
  my $n_forks= $ENV{_N_FORKS};
  my $n= $n_forks;
  my @cmd_lists= ( [ 'echo "USE test; CALL show_slave_status();"' ],
                   [ 'echo "USE test; CALL read_gtid_executed();"' ],
                   \@mysqlbinlog_commands,
                   \@mysqlbinlog_commands );
  $n-- while $n && fork;
  my $cmd_list= $cmd_lists[$n % @cmd_lists];
  for my $cmd (@$cmd_list)
  {
    # discard stdout from $cmd (redirect to /dev/null is not portable)
    `$cmd $mysql_pipe`;
    $? == 0 or die "Error executing running $cmd (n=$n): $!";
  }
EOF

--echo ==== Wait for load to finish ====

--connection slave
--let $show_statement= SHOW TABLES;
--let $field= Tables_in_test
--let $condition= t_end
--source include/wait_show_condition.inc

--echo ==== Check result ====

--let $diff_tables= master:t1_$t, master:t2_$t, slave:t1_$t, slave:t2_$t
--let $diff_tables_silent= 1
--source include/diff_tables.inc

--echo ==== Clean up ====

--connection master
--disable_query_log
eval DROP TABLE t1_$t, t2_$t;
--enable_query_log
DROP TABLE t_end;

--connection slave
--disable_query_log
eval DROP TABLE t1_$t, t2_$t;
--enable_query_log
DROP TABLE t_end;
DROP PROCEDURE show_slave_status;
DROP PROCEDURE read_gtid_executed;
CHANGE MASTER TO MASTER_AUTO_POSITION= 0;
