summaryrefslogtreecommitdiff
path: root/extra
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-05-18 12:13:18 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-05-18 12:13:18 +0300
commit08b6fd93957280c1b3e12c30ead1b6b90a7dff26 (patch)
treeafe34161fbf79bac0d860b87ba7d541a2ee66386 /extra
parent4240704abc2d51a2e46fb85049b601fce5d5b24c (diff)
downloadmariadb-git-08b6fd93957280c1b3e12c30ead1b6b90a7dff26.tar.gz
MDEV-25710: Dead code os_file_opendir() in the server
The functions fil_file_readdir_next_file(), os_file_opendir(), os_file_closedir() became dead code in the server in MariaDB 10.4.0 with commit 09af00cbde1d62dfda574dee10e5c0fd240c3f7f (the removal of the crash recovery logic for the TRUNCATE TABLE implementation that was replaced in MDEV-13564). os_file_opendir(), os_file_closedir(): Define as macros.
Diffstat (limited to 'extra')
-rw-r--r--extra/mariabackup/backup_copy.cc25
-rw-r--r--extra/mariabackup/changed_page_bitmap.cc16
-rw-r--r--extra/mariabackup/xtrabackup.cc257
-rw-r--r--extra/mariabackup/xtrabackup.h49
4 files changed, 300 insertions, 47 deletions
diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc
index f52d288f42d..5eebd68f372 100644
--- a/extra/mariabackup/backup_copy.cc
+++ b/extra/mariabackup/backup_copy.cc
@@ -200,9 +200,9 @@ datadir_iter_new(const char *path, bool skip_first_level = true)
pthread_mutex_init(&it->mutex, NULL);
it->datadir_path = strdup(path);
- it->dir = os_file_opendir(it->datadir_path, TRUE);
+ it->dir = os_file_opendir(it->datadir_path);
- if (it->dir == NULL) {
+ if (it->dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr)) {
goto error;
}
@@ -233,11 +233,9 @@ bool
datadir_iter_next_database(datadir_iter_t *it)
{
if (it->dbdir != NULL) {
- if (os_file_closedir(it->dbdir) != 0) {
-
+ if (os_file_closedir_failed(it->dbdir)) {
msg("Warning: could not"
" close database directory %s", it->dbpath);
-
it->err = DB_ERROR;
}
@@ -283,10 +281,9 @@ datadir_iter_next_database(datadir_iter_t *it)
/* We want wrong directory permissions to be a fatal error for
XtraBackup. */
- it->dbdir = os_file_opendir(it->dbpath, TRUE);
-
- if (it->dbdir != NULL) {
+ it->dbdir = os_file_opendir(it->dbpath);
+ if (it->dir != IF_WIN(INVALID_HANDLE_VALUE, nullptr)) {
it->is_file = false;
return(true);
}
@@ -727,9 +724,9 @@ directory_exists(const char *dir, bool create)
}
/* could be symlink */
- os_dir = os_file_opendir(dir, FALSE);
+ os_dir = os_file_opendir(dir);
- if (os_dir == NULL) {
+ if (os_dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr)) {
my_strerror(errbuf, sizeof(errbuf), my_errno);
msg("Can not open directory %s: %s", dir,
errbuf);
@@ -757,9 +754,9 @@ directory_exists_and_empty(const char *dir, const char *comment)
return(false);
}
- os_dir = os_file_opendir(dir, FALSE);
+ os_dir = os_file_opendir(dir);
- if (os_dir == NULL) {
+ if (os_dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr)) {
msg("%s can not open directory %s", comment, dir);
return(false);
}
@@ -2179,7 +2176,9 @@ decrypt_decompress()
*/
static bool backup_files_from_datadir(const char *dir_path)
{
- os_file_dir_t dir = os_file_opendir(dir_path, TRUE);
+ os_file_dir_t dir = os_file_opendir(dir_path);
+ if (dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr)) return false;
+
os_file_stat_t info;
bool ret = true;
while (os_file_readdir_next_file(dir_path, dir, &info) == 0) {
diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc
index 5266bed800d..ac67bb9b924 100644
--- a/extra/mariabackup/changed_page_bitmap.cc
+++ b/extra/mariabackup/changed_page_bitmap.cc
@@ -279,9 +279,8 @@ log_online_setup_bitmap_file_range(
/* 1st pass: size the info array */
- bitmap_dir = os_file_opendir(srv_data_home, FALSE);
- if (UNIV_UNLIKELY(!bitmap_dir)) {
-
+ bitmap_dir = os_file_opendir(srv_data_home);
+ if (UNIV_UNLIKELY(bitmap_dir == IF_WIN(INVALID_HANDLE_VALUE, NULL))) {
msg("InnoDB: Error: failed to open bitmap directory \'%s\'",
srv_data_home);
return FALSE;
@@ -329,8 +328,7 @@ log_online_setup_bitmap_file_range(
}
}
- if (UNIV_UNLIKELY(os_file_closedir(bitmap_dir))) {
-
+ if (UNIV_UNLIKELY(os_file_closedir_failed(bitmap_dir))) {
os_file_get_last_error(TRUE);
msg("InnoDB: Error: cannot close \'%s\'",srv_data_home);
return FALSE;
@@ -346,9 +344,8 @@ log_online_setup_bitmap_file_range(
/* 2nd pass: get the file names in the file_seq_num order */
- bitmap_dir = os_file_opendir(srv_data_home, FALSE);
- if (UNIV_UNLIKELY(!bitmap_dir)) {
-
+ bitmap_dir = os_file_opendir(srv_data_home);
+ if (UNIV_UNLIKELY(bitmap_dir == IF_WIN(INVALID_HANDLE_VALUE, NULL))) {
msg("InnoDB: Error: failed to open bitmap directory \'%s\'",
srv_data_home);
return FALSE;
@@ -398,8 +395,7 @@ log_online_setup_bitmap_file_range(
}
}
- if (UNIV_UNLIKELY(os_file_closedir(bitmap_dir))) {
-
+ if (UNIV_UNLIKELY(os_file_closedir_failed(bitmap_dir))) {
os_file_get_last_error(TRUE);
msg("InnoDB: Error: cannot close \'%s\'", srv_data_home);
free(bitmap_files->files);
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index de4462bc01f..9cead18cdec 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -3502,6 +3502,222 @@ static void xb_load_single_table_tablespace(const std::string &space_name,
xb_load_single_table_tablespace(dbname, tablename, is_remote, set_size);
}
+#ifdef _WIN32
+/**
+The os_file_opendir() function opens a directory stream corresponding to the
+directory named by the dirname argument. The directory stream is positioned
+at the first entry. In both Unix and Windows we automatically skip the '.'
+and '..' items at the start of the directory listing.
+@param[in] dirname directory name; it must not contain a trailing
+ '\' or '/'
+@return directory stream, NULL if error */
+os_file_dir_t os_file_opendir(const char *dirname)
+{
+ char path[OS_FILE_MAX_PATH + 3];
+
+ ut_a(strlen(dirname) < OS_FILE_MAX_PATH);
+
+ strcpy(path, dirname);
+ strcpy(path + strlen(path), "\\*");
+
+ /* Note that in Windows opening the 'directory stream' also retrieves
+ the first entry in the directory. Since it is '.', that is no problem,
+ as we will skip over the '.' and '..' entries anyway. */
+
+ LPWIN32_FIND_DATA lpFindFileData= static_cast<LPWIN32_FIND_DATA>
+ (ut_malloc_nokey(sizeof(WIN32_FIND_DATA)));
+ os_file_dir_t dir= FindFirstFile((LPCTSTR) path, lpFindFileData);
+ ut_free(lpFindFileData);
+
+ return dir;
+}
+#endif
+
+/** This function returns information of the next file in the directory. We jump
+over the '.' and '..' entries in the directory.
+@param[in] dirname directory name or path
+@param[in] dir directory stream
+@param[out] info buffer where the info is returned
+@return 0 if ok, -1 if error, 1 if at the end of the directory */
+int
+os_file_readdir_next_file(
+ const char* dirname,
+ os_file_dir_t dir,
+ os_file_stat_t* info)
+{
+#ifdef _WIN32
+ BOOL ret;
+ int status;
+ WIN32_FIND_DATA find_data;
+
+next_file:
+ ret = FindNextFile(dir, &find_data);
+
+ if (ret > 0) {
+
+ const char* name;
+
+ name = static_cast<const char*>(find_data.cFileName);
+
+ ut_a(strlen(name) < OS_FILE_MAX_PATH);
+
+ if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+
+ goto next_file;
+ }
+
+ strcpy(info->name, name);
+
+ info->size = find_data.nFileSizeHigh;
+ info->size <<= 32;
+ info->size |= find_data.nFileSizeLow;
+
+ if (find_data.dwFileAttributes
+ & FILE_ATTRIBUTE_REPARSE_POINT) {
+
+ /* TODO: test Windows symlinks */
+ /* TODO: MySQL has apparently its own symlink
+ implementation in Windows, dbname.sym can
+ redirect a database directory:
+ REFMAN "windows-symbolic-links.html" */
+
+ info->type = OS_FILE_TYPE_LINK;
+
+ } else if (find_data.dwFileAttributes
+ & FILE_ATTRIBUTE_DIRECTORY) {
+
+ info->type = OS_FILE_TYPE_DIR;
+
+ } else {
+
+ /* It is probably safest to assume that all other
+ file types are normal. Better to check them rather
+ than blindly skip them. */
+
+ info->type = OS_FILE_TYPE_FILE;
+ }
+
+ status = 0;
+
+ } else {
+ DWORD err = GetLastError();
+ if (err == ERROR_NO_MORE_FILES) {
+ status = 1;
+ } else {
+ msg("readdir_next_file in %s returned %lu", dir, err);
+ status = -1;
+ }
+ }
+
+ return(status);
+#else
+ struct dirent* ent;
+ char* full_path;
+ int ret;
+ struct stat statinfo;
+
+next_file:
+
+ ent = readdir(dir);
+
+ if (ent == NULL) {
+
+ return(1);
+ }
+
+ ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH);
+
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
+
+ goto next_file;
+ }
+
+ strcpy(info->name, ent->d_name);
+
+ full_path = static_cast<char*>(
+ ut_malloc_nokey(strlen(dirname) + strlen(ent->d_name) + 10));
+
+ sprintf(full_path, "%s/%s", dirname, ent->d_name);
+
+ ret = stat(full_path, &statinfo);
+
+ if (ret) {
+
+ if (errno == ENOENT) {
+ /* readdir() returned a file that does not exist,
+ it must have been deleted in the meantime. Do what
+ would have happened if the file was deleted before
+ readdir() - ignore and go to the next entry.
+ If this is the last entry then info->name will still
+ contain the name of the deleted file when this
+ function returns, but this is not an issue since the
+ caller shouldn't be looking at info when end of
+ directory is returned. */
+
+ ut_free(full_path);
+
+ goto next_file;
+ }
+
+ msg("stat %s: Got error %d", full_path, errno);
+
+ ut_free(full_path);
+
+ return(-1);
+ }
+
+ info->size = statinfo.st_size;
+
+ if (S_ISDIR(statinfo.st_mode)) {
+ info->type = OS_FILE_TYPE_DIR;
+ } else if (S_ISLNK(statinfo.st_mode)) {
+ info->type = OS_FILE_TYPE_LINK;
+ } else if (S_ISREG(statinfo.st_mode)) {
+ info->type = OS_FILE_TYPE_FILE;
+ } else {
+ info->type = OS_FILE_TYPE_UNKNOWN;
+ }
+
+ ut_free(full_path);
+ return(0);
+#endif
+}
+
+/***********************************************************************//**
+A fault-tolerant function that tries to read the next file name in the
+directory. We retry 100 times if os_file_readdir_next_file() returns -1. The
+idea is to read as much good data as we can and jump over bad data.
+@return 0 if ok, -1 if error even after the retries, 1 if at the end
+of the directory */
+int
+fil_file_readdir_next_file(
+/*=======================*/
+ dberr_t* err, /*!< out: this is set to DB_ERROR if an error
+ was encountered, otherwise not changed */
+ const char* dirname,/*!< in: directory name or path */
+ os_file_dir_t dir, /*!< in: directory stream */
+ os_file_stat_t* info) /*!< in/out: buffer where the
+ info is returned */
+{
+ for (ulint i = 0; i < 100; i++) {
+ int ret = os_file_readdir_next_file(dirname, dir, info);
+
+ if (ret != -1) {
+
+ return(ret);
+ }
+
+ ib::error() << "os_file_readdir_next_file() returned -1 in"
+ " directory " << dirname
+ << ", crash recovery may have failed"
+ " for some .ibd files!";
+
+ *err = DB_ERROR;
+ }
+
+ return(-1);
+}
+
/** Scan the database directories under the MySQL datadir, looking for
.ibd files and determining the space id in each of them.
@return DB_SUCCESS or error number */
@@ -3520,10 +3736,10 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
/* The datadir of MySQL is always the default directory of mysqld */
- dir = os_file_opendir(fil_path_to_mysql_datadir, true);
-
- if (dir == NULL) {
+ dir = os_file_opendir(fil_path_to_mysql_datadir);
+ if (UNIV_UNLIKELY(dir == IF_WIN(INVALID_HANDLE_VALUE, nullptr))) {
+ msg("cannot open dir %s", fil_path_to_mysql_datadir);
return(DB_ERROR);
}
@@ -3576,12 +3792,9 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
goto next_datadir_item;
}
- /* We want wrong directory permissions to be a fatal error for
- XtraBackup. */
- dbdir = os_file_opendir(dbpath, true);
-
- if (dbdir != NULL) {
+ dbdir = os_file_opendir(dbpath);
+ if (UNIV_UNLIKELY(dbdir != IF_WIN(INVALID_HANDLE_VALUE,NULL))){
/* We found a database directory; loop through it,
looking for possible .ibd files in it */
@@ -3604,7 +3817,7 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
}
}
- if (0 != os_file_closedir(dbdir)) {
+ if (os_file_closedir_failed(dbdir)) {
fprintf(stderr, "InnoDB: Warning: could not"
" close database directory %s\n",
dbpath);
@@ -3613,7 +3826,7 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
}
} else {
-
+ msg("Can't open dir %s", dbpath);
err = DB_ERROR;
break;
@@ -3627,10 +3840,9 @@ next_datadir_item:
ut_free(dbpath);
- if (0 != os_file_closedir(dir)) {
+ if (os_file_closedir_failed(dir)) {
fprintf(stderr,
"InnoDB: Error: could not close MySQL datadir\n");
-
return(DB_ERROR);
}
@@ -5578,11 +5790,9 @@ static ibool xb_process_datadir(const char *path, const char *suffix,
suffix_len = strlen(suffix);
/* datafile */
- dbdir = os_file_opendir(path, FALSE);
-
- if (dbdir != NULL) {
- ret = fil_file_readdir_next_file(&err, path, dbdir,
- &fileinfo);
+ dbdir = os_file_opendir(path);
+ if (UNIV_UNLIKELY(dbdir != IF_WIN(INVALID_HANDLE_VALUE, nullptr))) {
+ ret = fil_file_readdir_next_file(&err, path, dbdir, &fileinfo);
while (ret == 0) {
if (fileinfo.type == OS_FILE_TYPE_DIR) {
goto next_file_item_1;
@@ -5612,14 +5822,14 @@ next_file_item_1:
}
/* single table tablespaces */
- dir = os_file_opendir(path, FALSE);
+ dir = os_file_opendir(path);
- if (dir == NULL) {
+ if (UNIV_UNLIKELY(dbdir == IF_WIN(INVALID_HANDLE_VALUE, nullptr))) {
msg("Can't open dir %s", path);
+ return TRUE;
}
- ret = fil_file_readdir_next_file(&err, path, dir,
- &dbinfo);
+ ret = fil_file_readdir_next_file(&err, path, dir, &dbinfo);
while (ret == 0) {
if (dbinfo.type == OS_FILE_TYPE_FILE
|| dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
@@ -5635,10 +5845,9 @@ next_file_item_1:
os_normalize_path(dbpath);
- dbdir = os_file_opendir(dbpath, FALSE);
-
- if (dbdir != NULL) {
+ dbdir = os_file_opendir(dbpath);
+ if (dbdir != IF_WIN(INVALID_HANDLE_VALUE, nullptr)) {
ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
&fileinfo);
while (ret == 0) {
diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h
index bf5313d35db..854456c3afd 100644
--- a/extra/mariabackup/xtrabackup.h
+++ b/extra/mariabackup/xtrabackup.h
@@ -235,4 +235,53 @@ typedef void (*insert_entry_func_t)(const char*);
void xb_load_list_string(char *list, const char *delimiters,
insert_entry_func_t ins);
void register_ignore_db_dirs_filter(const char *name);
+
+#ifdef _WIN32
+typedef HANDLE os_file_dir_t; /*!< directory stream */
+/** The os_file_opendir() function opens a directory stream corresponding to the
+directory named by the dirname argument. The directory stream is positioned
+at the first entry. In both Unix and Windows we automatically skip the '.'
+and '..' items at the start of the directory listing.
+
+@param[in] dirname directory name; it must not contain a trailing
+ '\' or '/'
+@return directory stream
+@retval INVALID_HANDLE_VALUE on error */
+HANDLE os_file_opendir(const char *dirname);
+# define os_file_closedir(dir) static_cast<void>(FindClose(dir))
+# define os_file_closedir_failed(dir) !FindClose(dir)
+#else
+typedef DIR* os_file_dir_t;
+# define os_file_opendir(dirname) opendir(dirname)
+# define os_file_closedir(dir) static_cast<void>(closedir(dir))
+# define os_file_closedir_failed(dir) closedir(dir)
+#endif
+
+/** This function returns information of the next file in the directory. We jump
+over the '.' and '..' entries in the directory.
+@param[in] dirname directory name or path
+@param[in] dir directory stream
+@param[out] info buffer where the info is returned
+@return 0 if ok, -1 if error, 1 if at the end of the directory */
+int
+os_file_readdir_next_file(
+ const char* dirname,
+ os_file_dir_t dir,
+ os_file_stat_t* info);
+
+/***********************************************************************//**
+A fault-tolerant function that tries to read the next file name in the
+directory. We retry 100 times if os_file_readdir_next_file() returns -1. The
+idea is to read as much good data as we can and jump over bad data.
+@return 0 if ok, -1 if error even after the retries, 1 if at the end
+of the directory */
+int
+fil_file_readdir_next_file(
+/*=======================*/
+ dberr_t* err, /*!< out: this is set to DB_ERROR if an error
+ was encountered, otherwise not changed */
+ const char* dirname,/*!< in: directory name or path */
+ os_file_dir_t dir, /*!< in: directory stream */
+ os_file_stat_t* info); /*!< in/out: buffer where the
+ info is returned */
#endif /* XB_XTRABACKUP_H */