diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-05-18 12:13:18 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-05-18 12:13:18 +0300 |
commit | 08b6fd93957280c1b3e12c30ead1b6b90a7dff26 (patch) | |
tree | afe34161fbf79bac0d860b87ba7d541a2ee66386 /extra | |
parent | 4240704abc2d51a2e46fb85049b601fce5d5b24c (diff) | |
download | mariadb-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.cc | 25 | ||||
-rw-r--r-- | extra/mariabackup/changed_page_bitmap.cc | 16 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 257 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.h | 49 |
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 */ |