--source include/have_maria.inc
--source include/have_sequence.inc
--source include/not_embedded.inc

--echo #
--echo # MDEV-41708: Aria: one failed fdatasync() of aria_log silently makes the log
--echo # read-only; later writes fail with misleading errors, tables show corrupt, and
--echo # the changes of the failed statements show up after a restart.
--echo # Expected: a failed statement leaves no change that appears after a restart,
--echo # and a failed ALTER leaves no #sql-alter table. This test FAILS while the bug exists.
--echo # (local verification only: needs strace + passwordless sudo)
--echo #

# Skip unless strace and passwordless sudo are available
--perl
  my $ok = system("which strace >/dev/null 2>&1") == 0
        && system("sudo -n true >/dev/null 2>&1") == 0;
  open(F, ">$ENV{MYSQLTEST_VARDIR}/tmp/mdev41708_skip.inc") or die $!;
  print F ($ok ? "" : "--skip needs strace and passwordless sudo\n");
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41708_skip.inc

# The bug produces these on purpose-built failures; keep MTR's log scan quiet
call mtr.add_suppression("Can't sync file");
call mtr.add_suppression("marked as crashed");
call mtr.add_suppression("Got error '145");
call mtr.add_suppression("Recovering table");
call mtr.add_suppression("Checking table");
call mtr.add_suppression("Aria engine");
call mtr.add_suppression("Can't find record");
call mtr.add_suppression("when repairing");
call mtr.add_suppression("Found .* rows");
call mtr.add_suppression("checkpoint failed");

--let $failures= 0
--let $pid_file= `SELECT @@pid_file`
--let $helper= $MYSQL_TEST_DIR/std_data/strace_inject.sh
--let $trace= $MYSQLTEST_VARDIR/tmp/mdev41708.trace

# Name of the current Aria log file (aria_log.NNNNNNNN)
--perl
  opendir(D, "$ENV{MYSQLTEST_VARDIR}/mysqld.1/data") or die $!;
  my @f = sort grep { /^aria_log\.\d+$/ } readdir(D);
  open(F, ">$ENV{MYSQLTEST_VARDIR}/tmp/mdev41708_alog.inc") or die $!;
  print F "--let \$alog= $ENV{MYSQLTEST_VARDIR}/mysqld.1/data/$f[-1]\n";
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41708_alog.inc

CREATE TABLE t1 (id INT PRIMARY KEY, n INT) ENGINE=Aria TRANSACTIONAL=1;
CREATE TABLE t2 LIKE t1;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_1000;
INSERT INTO t2 SELECT seq, seq FROM seq_1_to_1000;

--echo # ---------------------------------------------------------------
--echo # Case 1: EIO on the next fdatasync of the Aria log, during INSERT INTO t1
--echo # ---------------------------------------------------------------
--exec INJECT_SYSCALLS=fdatasync INJECT_PATH=$alog sh $helper start $pid_file $trace
--disable_abort_on_error
INSERT INTO t1 VALUES (1001, 1001);
--let $e1= $mysql_errno
--exec sh $helper stop $pid_file $trace
--echo # injected fdatasync on the Aria log (must be 1):
--exec grep -c INJECTED $trace
--echo # INSERT INTO t1 errno: $e1 (27 = Can't sync file ...)

--echo # The Aria log is now read-only; every later write fails:
INSERT INTO t2 VALUES (1001, 1001);
--let $e2= $mysql_errno
--echo # INSERT INTO t2 errno: $e2 (1030 = Got error 122 "Internal (unspecified) error")
SELECT COUNT(*) AS rows_1001 FROM t2 WHERE id=1001;
CHECK TABLE t2;
CREATE USER u1@localhost;
--let $e3= $mysql_errno
--echo # CREATE USER errno: $e3 (1032 = Can't find record in 'global_priv')
CHECK TABLE mysql.global_priv;
--enable_abort_on_error

--echo # After a restart the failed statements must NOT show up:
--source include/restart_mysqld.inc
--let $row= `SELECT COUNT(*) FROM t2 WHERE id=1001`
--let $user= `SELECT COUNT(*) FROM mysql.global_priv WHERE user='u1'`
--echo # rows with id=1001 in t2 after the restart: $row
--echo # users u1 in mysql.global_priv after the restart: $user
--let $bad= `SELECT $e2 != 0 AND $row = 1`
if ($bad)
{
  --echo FAIL: INSERT INTO t2 failed (errno $e2) but its row exists after the restart
  --inc $failures
}
--let $bad= `SELECT $e3 != 0 AND $user = 1`
if ($bad)
{
  --echo FAIL: CREATE USER failed (errno $e3) but the user exists after the restart
  --inc $failures
}

--echo # ---------------------------------------------------------------
--echo # Case 2: EIO on the next fdatasync of the Aria log, during ALTER TABLE ... ADD INDEX
--echo # ---------------------------------------------------------------
--let $pid_file= `SELECT @@pid_file`
--perl
  opendir(D, "$ENV{MYSQLTEST_VARDIR}/mysqld.1/data") or die $!;
  my @f = sort grep { /^aria_log\.\d+$/ } readdir(D);
  open(F, ">$ENV{MYSQLTEST_VARDIR}/tmp/mdev41708_alog.inc") or die $!;
  print F "--let \$alog= $ENV{MYSQLTEST_VARDIR}/mysqld.1/data/$f[-1]\n";
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41708_alog.inc
--exec INJECT_SYSCALLS=fdatasync INJECT_PATH=$alog sh $helper start $pid_file $trace
--disable_abort_on_error
ALTER TABLE t1 ADD INDEX ix1_t1 (n);
--let $a1= $mysql_errno
--exec sh $helper stop $pid_file $trace
--echo # injected fdatasync on the Aria log (must be 1):
--exec grep -c INJECTED $trace
--echo # ALTER TABLE t1 ADD INDEX errno: $a1 (27 = Can't sync file ...)
ALTER TABLE t2 ADD INDEX ix3_t2 (n);
--let $a2= $mysql_errno
--echo # next ALTER TABLE t2 errno: $a2 (145 = Table was marked as crashed, on the #sql-alter table)
RENAME TABLE t1 TO t4;
--let $a3= $mysql_errno
--echo # RENAME TABLE t1 TO t4 errno: $a3 (1025 = Error on rename ... errno 1)
--enable_abort_on_error

--perl
  opendir(D, "$ENV{MYSQLTEST_VARDIR}/mysqld.1/data/test") or die $!;
  my @f = grep { /^#sql-alter/ } readdir(D);
  open(F, ">$ENV{MYSQLTEST_VARDIR}/tmp/mdev41708_leftover.inc") or die $!;
  print F "--let \$leftover= ".scalar(@f)."\n";
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41708_leftover.inc
--echo # #sql-alter-* files left in the database directory (expected: 0): $leftover
if ($leftover)
{
  --echo FAIL: $leftover #sql-alter-* file(s) left behind by the failed ALTER
  --inc $failures
}
--let $bad= `SELECT $a2 = 145`
if ($bad)
{
  --echo FAIL: the next ALTER on the connection fails with error 145 on the leftover #sql-alter table
  --inc $failures
}
--let $bad= `SELECT $a3 = 1025`
if ($bad)
{
  --echo FAIL: RENAME TABLE of the original table fails with 1025 (errno 1)
  --inc $failures
}

--echo # After a restart the leftover files must be gone:
--source include/restart_mysqld.inc
--perl
  opendir(D, "$ENV{MYSQLTEST_VARDIR}/mysqld.1/data/test") or die $!;
  my @f = grep { /^#sql-alter/ } readdir(D);
  open(F, ">$ENV{MYSQLTEST_VARDIR}/tmp/mdev41708_leftover.inc") or die $!;
  print F "--let \$leftover= ".scalar(@f)."\n";
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41708_leftover.inc
--echo # #sql-alter-* files after the restart: $leftover
if ($leftover)
{
  --echo FAIL: $leftover #sql-alter-* file(s) still there after the restart
  --inc $failures
}

--remove_file $trace
--disable_warnings
DROP USER IF EXISTS u1@localhost;
DROP TABLE IF EXISTS t1, t2, t4;
--enable_warnings

if ($failures)
{
  --die MDEV-41708 reproduced: $failures check(s) failed after one failed fdatasync of the Aria log
}
--echo # all checks passed
