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

--echo #
--echo # MDEV-41705: atomic DROP TABLE: the link to the DROP TABLE entry in
--echo # ddl_recovery.log (4-byte pwrite) is not synced before InnoDB commits the drop.
--echo # Expected: ddl_recovery.log has no unsynced write when InnoDB syncs its redo log.
--echo # 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/mdev41705_skip.inc") or die $!;
  print F ($ok ? "" : "--skip needs strace and passwordless sudo\n");
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41705_skip.inc

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

CREATE TABLE t8 (id INT PRIMARY KEY, k INT, n INT, v VARCHAR(1100)) ENGINE=InnoDB;
INSERT INTO t8 SELECT seq, seq, seq, REPEAT('x',100) FROM seq_1_to_100;

--echo # Record syscalls while DROP TABLE runs
--exec OBSERVE_SYSCALLS=pwrite64,pwritev,fsync,fdatasync,unlink,unlinkat sh $helper start $pid_file $trace
DROP TABLE t8;
--exec sh $helper stop $pid_file $trace

--perl
  my $t = "$ENV{MYSQLTEST_VARDIR}/tmp/mdev41705.trace";
  open(T, $t) or die "cannot open $t: $!";
  my ($dirty, $seen, $checked, $dirty_commit, $ddl_syncs, $link) = (0, 0, 0, 0, 0, 0);
  while (<T>) {
    if (m{\b(pwrite64|pwritev)\(\d+<[^>]*ddl_recovery\.log>}) {
      $dirty = 1; $seen = 1;
      $link++ if /, 4, \d+\) = 4/;                     # the 4-byte next_entry link
    } elsif (m{\b(fsync|fdatasync)\(\d+<[^>]*ddl_recovery\.log>}) {
      $dirty = 0; $ddl_syncs++;
    } elsif (m{\b(fsync|fdatasync)\(\d+<[^>]*ib_logfile\d*>}) {
      if ($seen && !$checked) { $checked = 1; $dirty_commit = $dirty; }   # InnoDB commits the drop
    }
  }
  close T;
  open(F, ">$ENV{MYSQLTEST_VARDIR}/tmp/mdev41705_counts.inc") or die $!;
  print F "--let \$ddl_syncs= $ddl_syncs\n--let \$link_written= $link\n--let \$commit_seen= $checked\n--let \$dirty_commit= $dirty_commit\n";
  close F;
EOF
--source $MYSQLTEST_VARDIR/tmp/mdev41705_counts.inc
--echo # fsync/fdatasync on ddl_recovery.log (control, expected >= 1): $ddl_syncs
--echo # 4-byte link writes to ddl_recovery.log:                     $link_written
--echo # InnoDB redo-log sync seen after the ddl log writes (1=yes):  $commit_seen
--echo # unsynced ddl_recovery.log writes at that redo-log sync (1=yes): $dirty_commit

# Sanity: without these the trace proves nothing
--let $no_sync= `SELECT $ddl_syncs = 0`
--let $no_link= `SELECT $link_written = 0`
--let $no_commit= `SELECT $commit_seen = 0`
if ($no_sync)
{
  --die INCONCLUSIVE: no fsync/fdatasync on ddl_recovery.log in the trace (is fsync disabled?)
}
if ($no_link)
{
  --die INCONCLUSIVE: no 4-byte link write to ddl_recovery.log in the trace (different log layout?)
}
if ($no_commit)
{
  --die INCONCLUSIVE: no redo-log sync (ib_logfile) seen after the ddl log writes
}

if ($dirty_commit)
{
  --echo FAIL: ddl_recovery.log has an unsynced write when InnoDB syncs its redo log (the drop is committed)
  --inc $failures
}

--remove_file $trace
if ($failures)
{
  --die MDEV-41705 reproduced: the DROP TABLE link in ddl_recovery.log is not synced before the InnoDB commit
}
--echo # all checks passed
