From 1c27e6c717a7f627d2546369062232840ed7db73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@mariadb.com>
Date: Wed, 25 Jul 2018 10:34:49 +0300
Subject: [PATCH] MDEV-16791: Trace file operations during backup

backup_file_op(), log_file_op: Inform backup of file creation, deletion,
and deletion.

xtrabackup_backup_func(): Make log_file_op point to backup_file_op()
during the mariabackup --backup operation.

TODO: At the end of backup, add information to perform "delete" or "rename".
For "create", invoke fil_ibd_create() to create file stubs.
On "delete", stop copying that file, or remove it from the copying queue.

TODO: Remove the warning if xb_close_files is set.
---
 extra/mariabackup/backup_copy.cc    | 27 +++++++++++++++++++++++++++
 extra/mariabackup/backup_copy.h     | 10 ++++++++++
 extra/mariabackup/xtrabackup.cc     |  3 +++
 storage/innobase/include/log0recv.h | 13 ++++++++++++-
 storage/innobase/log/log0recv.cc    | 24 ++++++++++++++++++++++--
 5 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index 16a4042d66e..a2ad721df09 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -1361,6 +1361,33 @@ backup_files(const char *from, bool prep_mode)
 	return(ret);
 }
 
+/** Report an operation to create, delete, or rename a file during backup.
+@param[in]	space_id	tablespace identifier
+@param[in]	flags		tablespace flags (NULL if not create)
+@param[in]	name		file name (not NUL-terminated)
+@param[in]	len		length of name, in bytes
+@param[in]	new_name	new file name (NULL if not rename)
+@param[in]	new_len		length of new_name, in bytes (0 if NULL) */
+void backup_file_op(ulint space_id, const byte* flags,
+		    const byte* name, ulint len,
+		    const byte* new_name, ulint new_len)
+{
+	ut_ad(!flags || !new_name);
+	ut_ad(name);
+	ut_ad(len);
+	ut_ad(!new_name == !new_len);
+
+	if (flags) {
+		msg("create %zu \"%.*s\": %x\n",
+		    space_id, int(len), name, mach_read_from_4(flags));
+	} else if (new_name) {
+		msg("rename %zu \"%.*s\",\"%.*s\"\n",
+		    space_id, int(len), name, int(new_len), new_name);
+	} else {
+		msg("delete %zu \"%.*s\"\n", space_id, int(len), name);
+	}
+}
+
 /** Start --backup */
 bool backup_start()
 {
diff --git a/extra/mariabackup/backup_copy.h b/extra/mariabackup/backup_copy.h
index fbc09eaded3..75c26a671ad 100644
--- a/extra/mariabackup/backup_copy.h
+++ b/extra/mariabackup/backup_copy.h
@@ -31,6 +31,16 @@ copy_file(ds_ctxt_t *datasink,
 	  const char *dst_file_path,
 	  uint thread_n);
 
+/** Report an operation to create, delete, or rename a file during backup.
+@param[in]	space_id	tablespace identifier
+@param[in]	flags		tablespace flags (NULL if not create)
+@param[in]	name		file name (not NUL-terminated)
+@param[in]	len		length of name, in bytes
+@param[in]	new_name	new file name (NULL if not rename)
+@param[in]	new_len		length of new_name, in bytes (0 if NULL) */
+void backup_file_op(ulint space_id, const byte* flags,
+		    const byte* name, ulint len,
+		    const byte* new_name, ulint new_len);
 /** Start --backup */
 bool backup_start();
 /** Release resources after backup_start() */
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 390cdab52f2..fa6eebb3603 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -3817,6 +3817,7 @@ xtrabackup_backup_func()
 	srv_read_only_mode = TRUE;
 
 	srv_operation = SRV_OPERATION_BACKUP;
+	log_file_op = backup_file_op;
 	metadata_to_lsn = 0;
 
 	if (xb_close_files)
@@ -3830,6 +3831,7 @@ xtrabackup_backup_func()
 fail:
 		metadata_to_lsn = log_copying_running;
 		stop_backup_threads();
+		log_file_op = NULL;
 		if (dst_log_file) {
 			ds_close(dst_log_file);
 			dst_log_file = NULL;
@@ -4228,6 +4230,7 @@ xtrabackup_backup_func()
 	}
 
 	innodb_shutdown();
+	log_file_op = NULL;
 	return(true);
 }
 
diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h
index 6dcaaedd765..ca9b9e4473b 100644
--- a/storage/innobase/include/log0recv.h
+++ b/storage/innobase/include/log0recv.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, MariaDB Corporation.
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -157,6 +157,17 @@ void recv_sys_justify_left_parsing_buf();
 the skip table list given in the mariabackup option. */
 extern bool(*check_if_backup_includes)(ulint space_id);
 
+/** Report an operation to create, delete, or rename a file during backup.
+@param[in]	space_id	tablespace identifier
+@param[in]	flags		tablespace flags (NULL if not create)
+@param[in]	name		file name (not NUL-terminated)
+@param[in]	len		length of name, in bytes
+@param[in]	new_name	new file name (NULL if not rename)
+@param[in]	new_len		length of new_name, in bytes (0 if NULL) */
+extern void (*log_file_op)(ulint space_id, const byte* flags,
+			   const byte* name, ulint len,
+			   const byte* new_name, ulint new_len);
+
 /** Block of log record data */
 struct recv_data_t{
 	recv_data_t*	next;	/*!< pointer to the next block or NULL */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index c8976b193e2..c294b1b49b9 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -173,6 +173,17 @@ static recv_spaces_t	recv_spaces;
 the skip table list given in the mariabackup option. */
 bool(*check_if_backup_includes)(ulint space_id);
 
+/** Report an operation to create, delete, or rename a file during backup.
+@param[in]	space_id	tablespace identifier
+@param[in]	flags		tablespace flags (NULL if not create)
+@param[in]	name		file name (not NUL-terminated)
+@param[in]	len		length of name, in bytes
+@param[in]	new_name	new file name (NULL if not rename)
+@param[in]	new_len		length of new_name, in bytes (0 if NULL) */
+void (*log_file_op)(ulint space_id, const byte* flags,
+		    const byte* name, ulint len,
+		    const byte* new_name, ulint new_len);
+
 /** Process a file name from a MLOG_FILE_* record.
 @param[in,out]	name		file name
 @param[in]	len		length of the file name
@@ -381,9 +392,13 @@ fil_name_parse(
 
 		fil_name_process(
 			reinterpret_cast<char*>(ptr), len, space_id, true);
-
-		break;
+		/* fall through */
 	case MLOG_FILE_CREATE2:
+		if (log_file_op) {
+			log_file_op(space_id,
+				    type == MLOG_FILE_CREATE2 ? ptr - 4 : NULL,
+				    ptr, len, NULL, 0);
+		}
 		break;
 	case MLOG_FILE_RENAME2:
 		if (corrupt) {
@@ -424,6 +439,11 @@ fil_name_parse(
 			reinterpret_cast<char*>(new_name), new_len,
 			space_id, false);
 
+		if (log_file_op) {
+			log_file_op(space_id, NULL,
+				    ptr, len, new_name, new_len);
+		}
+
 		if (!apply) {
 			break;
 		}
-- 
2.18.0

