diff options
Diffstat (limited to 'storage/xtradb/srv/srv0start.cc')
-rw-r--r-- | storage/xtradb/srv/srv0start.cc | 3457 |
1 files changed, 0 insertions, 3457 deletions
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc deleted file mode 100644 index 62bf4c758b7..00000000000 --- a/storage/xtradb/srv/srv0start.cc +++ /dev/null @@ -1,3457 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. -Copyright (c) 2008, Google Inc. -Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2019, MariaDB Corporation. - -Portions of this file contain modifications contributed and copyrighted by -Google, Inc. Those modifications are gratefully acknowledged and are described -briefly in the InnoDB documentation. The contributions by Google are -incorporated with their permission, and subject to the conditions contained in -the file COPYING.Google. - -Portions of this file contain modifications contributed and copyrighted -by Percona Inc.. Those modifications are -gratefully acknowledged and are described briefly in the InnoDB -documentation. The contributions by Percona Inc. are incorporated with -their permission, and subject to the conditions contained in the file -COPYING.Percona. - -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 -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/********************************************************************//** -@file srv/srv0start.cc -Starts the InnoDB database server - -Created 2/16/1996 Heikki Tuuri -*************************************************************************/ - -#include "mysqld.h" -#include "pars0pars.h" -#include "row0ftsort.h" -#include "ut0mem.h" -#include "mem0mem.h" -#include "data0data.h" -#include "data0type.h" -#include "dict0dict.h" -#include "buf0buf.h" -#include "buf0dump.h" -#include "os0file.h" -#include "os0thread.h" -#include "fil0fil.h" -#include "fil0crypt.h" -#include "fsp0fsp.h" -#include "rem0rec.h" -#include "mtr0mtr.h" -#include "log0log.h" -#include "log0online.h" -#include "log0recv.h" -#include "page0page.h" -#include "page0cur.h" -#include "trx0trx.h" -#include "trx0sys.h" -#include "btr0btr.h" -#include "btr0cur.h" -#include "rem0rec.h" -#include "ibuf0ibuf.h" -#include "srv0start.h" -#include "srv0srv.h" -#include "buf0flu.h" -#include "btr0defragment.h" -#include "ut0timer.h" -#include "btr0scrub.h" -#include "mysql/service_wsrep.h" /* wsrep_recovery */ - -#ifndef UNIV_HOTBACKUP -# include "trx0rseg.h" -# include "os0proc.h" -# include "sync0sync.h" -# include "buf0flu.h" -# include "buf0mtflu.h" -# include "buf0rea.h" -# include "dict0boot.h" -# include "dict0load.h" -# include "dict0stats_bg.h" -# include "que0que.h" -# include "usr0sess.h" -# include "lock0lock.h" -# include "trx0roll.h" -# include "trx0purge.h" -# include "lock0lock.h" -# include "pars0pars.h" -# include "btr0sea.h" -# include "rem0cmp.h" -# include "dict0crea.h" -# include "row0ins.h" -# include "row0sel.h" -# include "row0upd.h" -# include "row0row.h" -# include "row0mysql.h" -# include "btr0pcur.h" -# include "os0sync.h" -# include "zlib.h" -# include "ut0crc32.h" -# include "os0stacktrace.h" - -/** Log sequence number immediately after startup */ -UNIV_INTERN lsn_t srv_start_lsn; -/** Log sequence number at shutdown */ -UNIV_INTERN lsn_t srv_shutdown_lsn; - -#ifdef HAVE_DARWIN_THREADS -# include <sys/utsname.h> -/** TRUE if the F_FULLFSYNC option is available */ -UNIV_INTERN ibool srv_have_fullfsync = FALSE; -#endif - -/** TRUE if a raw partition is in use */ -UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE; - -/** UNDO tablespaces starts with space id. */ -ulint srv_undo_space_id_start; - -/** TRUE if the server is being started, before rolling back any -incomplete transactions */ -UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE; -/** TRUE if the server is being started */ -UNIV_INTERN ibool srv_is_being_started = FALSE; -/** TRUE if the server was successfully started */ -UNIV_INTERN ibool srv_was_started = FALSE; -/** TRUE if innobase_start_or_create_for_mysql() has been called */ -static ibool srv_start_has_been_called; - -/** Whether any undo log records can be generated */ -UNIV_INTERN bool srv_undo_sources; - -#ifdef UNIV_DEBUG -/** InnoDB system tablespace to set during recovery */ -UNIV_INTERN uint srv_sys_space_size_debug; -#endif /* UNIV_DEBUG */ - -/** At a shutdown this value climbs from SRV_SHUTDOWN_NONE to -SRV_SHUTDOWN_CLEANUP and then to SRV_SHUTDOWN_LAST_PHASE, and so on */ -UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE; - -/** Files comprising the system tablespace. Also used by Mariabackup. */ -UNIV_INTERN pfs_os_file_t files[1000]; - -/** io_handler_thread parameters for thread identification */ -static ulint n[SRV_MAX_N_IO_THREADS]; -/** io_handler_thread identifiers, 32 is the maximum number of purge threads. -The extra elements at the end are allocated as follows: -SRV_MAX_N_IO_THREADS + 1: srv_master_thread -SRV_MAX_N_IO_THREADS + 2: lock_wait_timeout_thread -SRV_MAX_N_IO_THREADS + 3: srv_error_monitor_thread -SRV_MAX_N_IO_THREADS + 4: srv_monitor_thread -SRV_MAX_N_IO_THREADS + 5: srv_redo_log_follow_thread -SRV_MAX_N_IO_THREADS + 6: srv_purge_coordinator_thread -SRV_MAX_N_IO_THREADS + 7: srv_worker_thread -... -SRV_MAX_N_IO_THREADS + 7 + srv_n_purge_threads - 1: srv_worker_thread */ -static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7 - + SRV_MAX_N_PURGE_THREADS - + MTFLUSH_MAX_WORKER]; -/* Thread contex data for multi-threaded flush */ -void *mtflush_ctx=NULL; - -/** Thead handles */ -static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 7 + SRV_MAX_N_PURGE_THREADS]; -static os_thread_t buf_flush_page_cleaner_thread_handle; -static os_thread_t buf_dump_thread_handle; -static os_thread_t dict_stats_thread_handle; -static os_thread_t buf_flush_lru_manager_thread_handle; -static os_thread_t srv_redo_log_follow_thread_handle; -/** Status variables, is thread started ?*/ -static bool thread_started[SRV_MAX_N_IO_THREADS + 7 + SRV_MAX_N_PURGE_THREADS] = {false}; -static bool buf_flush_page_cleaner_thread_started = false; -static bool buf_dump_thread_started = false; -static bool dict_stats_thread_started = false; -static bool buf_flush_lru_manager_thread_started = false; -static bool srv_redo_log_follow_thread_started = false; - -/** We use this mutex to test the return value of pthread_mutex_trylock - on successful locking. HP-UX does NOT return 0, though Linux et al do. */ -static os_fast_mutex_t srv_os_test_mutex; - -/** Name of srv_monitor_file */ -static char* srv_monitor_file_name; -#endif /* !UNIV_HOTBACKUP */ - -/** Default undo tablespace size in UNIV_PAGEs count (10MB). */ -static const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES = - ((1024 * 1024) * 10) / UNIV_PAGE_SIZE_DEF; - -/** */ -#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD -#define SRV_MAX_N_PENDING_SYNC_IOS 100 - -#ifdef UNIV_PFS_THREAD -/* Keys to register InnoDB threads with performance schema */ -UNIV_INTERN mysql_pfs_key_t io_handler_thread_key; -UNIV_INTERN mysql_pfs_key_t srv_lock_timeout_thread_key; -UNIV_INTERN mysql_pfs_key_t srv_error_monitor_thread_key; -UNIV_INTERN mysql_pfs_key_t srv_monitor_thread_key; -UNIV_INTERN mysql_pfs_key_t srv_master_thread_key; -UNIV_INTERN mysql_pfs_key_t srv_purge_thread_key; -UNIV_INTERN mysql_pfs_key_t srv_log_tracking_thread_key; -#endif /* UNIV_PFS_THREAD */ - -/** Innobase start-up aborted. Perform cleanup actions. -@param[in] create_new_db TRUE if new db is being created -@param[in] file File name -@param[in] line Line number -@param[in] err Reason for aborting InnoDB startup -@return DB_SUCCESS or error code. */ -static -dberr_t -srv_init_abort( - bool create_new_db, - const char* file, - ulint line, - dberr_t err) -{ - if (create_new_db) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Database creation was aborted" - " at %s [" ULINTPF "]" - " with error %s. You may need" - " to delete the ibdata1 file before trying to start" - " up again.", - file, line, ut_strerr(err)); - } else { - ib_logf(IB_LOG_LEVEL_ERROR, - "Plugin initialization aborted" - " at %s [" ULINTPF "]" - " with error %s.", - file, line, ut_strerr(err)); - } - - return(err); -} - -/*********************************************************************//** -Convert a numeric string that optionally ends in G or M or K, to a number -containing megabytes. -@return next character in string */ -static -char* -srv_parse_megabytes( -/*================*/ - char* str, /*!< in: string containing a quantity in bytes */ - ulint* megs) /*!< out: the number in megabytes */ -{ - char* endp; - ulint size; - - size = strtoul(str, &endp, 10); - - str = endp; - - switch (*str) { - case 'G': case 'g': - size *= 1024; - /* fall through */ - case 'M': case 'm': - str++; - break; - case 'K': case 'k': - size /= 1024; - str++; - break; - default: - size /= 1024 * 1024; - break; - } - - *megs = size; - return(str); -} - -/*********************************************************************//** -Check if a file can be opened in read-write mode. -@return true if it doesn't exist or can be opened in rw mode. */ -static -bool -srv_file_check_mode( -/*================*/ - const char* name) /*!< in: filename to check */ -{ - os_file_stat_t stat; - - memset(&stat, 0x0, sizeof(stat)); - - dberr_t err = os_file_get_status(name, &stat, true); - - if (err == DB_FAIL) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "os_file_get_status() failed on '%s'. Can't determine " - "file permissions", name); - - return(false); - - } else if (err == DB_SUCCESS) { - - /* Note: stat.rw_perm is only valid of files */ - - if (stat.type == OS_FILE_TYPE_FILE) { - - if (!stat.rw_perm) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "%s can't be opened in %s mode", - name, - srv_read_only_mode - ? "read" : "read-write"); - - return(false); - } - } else { - /* Not a regular file, bail out. */ - - ib_logf(IB_LOG_LEVEL_ERROR, - "'%s' not a regular file.", name); - - return(false); - } - } else { - - /* This is OK. If the file create fails on RO media, there - is nothing we can do. */ - - ut_a(err == DB_NOT_FOUND); - } - - return(true); -} - -/*********************************************************************//** -Reads the data files and their sizes from a character string given in -the .cnf file. -@return TRUE if ok, FALSE on parse error */ -UNIV_INTERN -ibool -srv_parse_data_file_paths_and_sizes( -/*================================*/ - char* str) /*!< in/out: the data file path string */ -{ - char* input_str; - char* path; - ulint size; - ulint i = 0; - - srv_auto_extend_last_data_file = FALSE; - srv_last_file_size_max = 0; - srv_data_file_names = NULL; - srv_data_file_sizes = NULL; - srv_data_file_is_raw_partition = NULL; - - input_str = str; - - /* First calculate the number of data files and check syntax: - path:size[M | G];path:size[M | G]... . Note that a Windows path may - contain a drive name and a ':'. */ - - while (*str != '\0') { - path = str; - - while ((*str != ':' && *str != '\0') - || (*str == ':' - && (*(str + 1) == '\\' || *(str + 1) == '/' - || *(str + 1) == ':'))) { - str++; - } - - if (*str == '\0') { - return(FALSE); - } - - str++; - - str = srv_parse_megabytes(str, &size); - - if (0 == strncmp(str, ":autoextend", - (sizeof ":autoextend") - 1)) { - - str += (sizeof ":autoextend") - 1; - - if (0 == strncmp(str, ":max:", - (sizeof ":max:") - 1)) { - - str += (sizeof ":max:") - 1; - - str = srv_parse_megabytes(str, &size); - } - - if (*str != '\0') { - - return(FALSE); - } - } - - if (strlen(str) >= 6 - && *str == 'n' - && *(str + 1) == 'e' - && *(str + 2) == 'w') { - str += 3; - } - - if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { - str += 3; - } - - if (size == 0) { - return(FALSE); - } - - i++; - - if (*str == ';') { - str++; - } else if (*str != '\0') { - - return(FALSE); - } - } - - if (i == 0) { - /* If innodb_data_file_path was defined it must contain - at least one data file definition */ - - return(FALSE); - } - - srv_data_file_names = static_cast<char**>( - malloc(i * sizeof *srv_data_file_names)); - - srv_data_file_sizes = static_cast<ulint*>( - malloc(i * sizeof *srv_data_file_sizes)); - - srv_data_file_is_raw_partition = static_cast<ulint*>( - malloc(i * sizeof *srv_data_file_is_raw_partition)); - - srv_n_data_files = i; - - /* Then store the actual values to our arrays */ - - str = input_str; - i = 0; - - while (*str != '\0') { - path = str; - - /* Note that we must step over the ':' in a Windows path; - a Windows path normally looks like C:\ibdata\ibdata1:1G, but - a Windows raw partition may have a specification like - \\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */ - - while ((*str != ':' && *str != '\0') - || (*str == ':' - && (*(str + 1) == '\\' || *(str + 1) == '/' - || *(str + 1) == ':'))) { - str++; - } - - if (*str == ':') { - /* Make path a null-terminated string */ - *str = '\0'; - str++; - } - - str = srv_parse_megabytes(str, &size); - - srv_data_file_names[i] = path; - srv_data_file_sizes[i] = size; - - if (0 == strncmp(str, ":autoextend", - (sizeof ":autoextend") - 1)) { - - srv_auto_extend_last_data_file = TRUE; - - str += (sizeof ":autoextend") - 1; - - if (0 == strncmp(str, ":max:", - (sizeof ":max:") - 1)) { - - str += (sizeof ":max:") - 1; - - str = srv_parse_megabytes( - str, &srv_last_file_size_max); - } - - if (*str != '\0') { - - return(FALSE); - } - } - - (srv_data_file_is_raw_partition)[i] = 0; - - if (strlen(str) >= 6 - && *str == 'n' - && *(str + 1) == 'e' - && *(str + 2) == 'w') { - str += 3; - /* Initialize new raw device only during bootstrap */ - (srv_data_file_is_raw_partition)[i] = - opt_bootstrap ? SRV_NEW_RAW : SRV_OLD_RAW; - } - - if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { - str += 3; - - /* Initialize new raw device only during bootstrap */ - if ((srv_data_file_is_raw_partition)[i] == 0) { - (srv_data_file_is_raw_partition)[i] = - opt_bootstrap ? SRV_NEW_RAW : SRV_OLD_RAW; - } - } - - i++; - - if (*str == ';') { - str++; - } - } - - return(TRUE); -} - -/*********************************************************************//** -Frees the memory allocated by srv_parse_data_file_paths_and_sizes() -and srv_parse_log_group_home_dirs(). */ -UNIV_INTERN -void -srv_free_paths_and_sizes(void) -/*==========================*/ -{ - free(srv_data_file_names); - srv_data_file_names = NULL; - free(srv_data_file_sizes); - srv_data_file_sizes = NULL; - free(srv_data_file_is_raw_partition); - srv_data_file_is_raw_partition = NULL; -} - -#ifndef UNIV_HOTBACKUP - -static ulint io_tid_i = 0; - -/********************************************************************//** -I/o-handler thread function. -@return OS_THREAD_DUMMY_RETURN */ -extern "C" UNIV_INTERN -os_thread_ret_t -DECLARE_THREAD(io_handler_thread)( -/*==============================*/ - void* arg) /*!< in: pointer to the number of the segment in - the aio array */ -{ - ulint segment; - ulint tid_i = os_atomic_increment_ulint(&io_tid_i, 1) - 1; - - ut_ad(tid_i < srv_n_file_io_threads); - - segment = *((ulint*) arg); - - srv_io_tids[tid_i] = os_thread_get_tid(); - os_thread_set_priority(srv_io_tids[tid_i], srv_sched_priority_io); - -#ifdef UNIV_DEBUG_THREAD_CREATION - ib_logf(IB_LOG_LEVEL_INFO, - "Io handler thread %lu starts, id %lu\n", segment, - os_thread_pf(os_thread_get_curr_id())); -#endif - -#ifdef UNIV_PFS_THREAD - pfs_register_thread(io_handler_thread_key); -#endif /* UNIV_PFS_THREAD */ - - while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) { - srv_current_thread_priority = srv_io_thread_priority; - fil_aio_wait(segment); - } - - /* We count the number of threads in os_thread_exit(). A created - thread should always use that to exit and not use return() to exit. - The thread actually never comes here because it is exited in an - os_event_wait(). */ - - os_thread_exit(NULL); - - OS_THREAD_DUMMY_RETURN; -} -#endif /* !UNIV_HOTBACKUP */ - -/*********************************************************************//** -Normalizes a directory path for Windows: converts slashes to backslashes. */ -UNIV_INTERN -void -srv_normalize_path_for_win( -/*=======================*/ - char* str MY_ATTRIBUTE((unused))) /*!< in/out: null-terminated - character string */ -{ -#ifdef __WIN__ - for (; *str; str++) { - - if (*str == '/') { - *str = '\\'; - } - } -#endif -} - -#ifndef UNIV_HOTBACKUP -/*********************************************************************//** -Creates a log file. -@return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -create_log_file( -/*============*/ - pfs_os_file_t* file, /*!< out: file handle */ - const char* name) /*!< in: log file name */ -{ - ibool ret; - - *file = os_file_create( - innodb_file_log_key, name, - OS_FILE_CREATE|OS_FILE_ON_ERROR_NO_EXIT, OS_FILE_NORMAL, - OS_LOG_FILE, &ret, FALSE); - - if (!ret) { - ib_logf(IB_LOG_LEVEL_ERROR, "Cannot create %s", name); - return(DB_ERROR); - } - - ib_logf(IB_LOG_LEVEL_INFO, - "Setting log file %s size to %lu MB", - name, (ulong) srv_log_file_size - >> (20 - UNIV_PAGE_SIZE_SHIFT)); - - ret = os_file_set_size(name, *file, - (os_offset_t) srv_log_file_size - << UNIV_PAGE_SIZE_SHIFT); - if (!ret) { - ib_logf(IB_LOG_LEVEL_ERROR, "Cannot set log file" - " %s to size %lu MB", name, (ulong) srv_log_file_size - >> (20 - UNIV_PAGE_SIZE_SHIFT)); - return(DB_ERROR); - } - - ret = os_file_close(*file); - ut_a(ret); - - return(DB_SUCCESS); -} - -/** Initial number of the first redo log file */ -#define INIT_LOG_FILE0 (SRV_N_LOG_FILES_MAX + 1) - -/*********************************************************************//** -Creates all log files. -@return DB_SUCCESS or error code */ -static -dberr_t -create_log_files( -/*=============*/ - bool create_new_db, /*!< in: TRUE if new database is being - created */ - char* logfilename, /*!< in/out: buffer for log file name */ - size_t dirnamelen, /*!< in: length of the directory path */ - lsn_t lsn, /*!< in: FIL_PAGE_FILE_FLUSH_LSN value */ - char*& logfile0) /*!< out: name of the first log file */ -{ - if (srv_read_only_mode) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Cannot create log files in read-only mode"); - return(DB_READ_ONLY); - } - - /* We prevent system tablespace creation with existing files in - data directory. So we do not delete log files when creating new system - tablespace */ - if (!create_new_db) { - /* Remove any old log files. */ - for (unsigned i = 0; i <= INIT_LOG_FILE0; i++) { - sprintf(logfilename + dirnamelen, "ib_logfile%u", i); - - /* Ignore errors about non-existent files or files - that cannot be removed. The create_log_file() will - return an error when the file exists. */ -#ifdef __WIN__ - DeleteFile((LPCTSTR) logfilename); -#else - unlink(logfilename); -#endif - /* Crashing after deleting the first - file should be recoverable. The buffer - pool was clean, and we can simply create - all log files from the scratch. */ - DBUG_EXECUTE_IF("innodb_log_abort_6", - return(DB_ERROR);); - } - } - - ut_ad(!buf_pool_check_no_pending_io()); - - DBUG_EXECUTE_IF("innodb_log_abort_7", return(DB_ERROR);); - - for (unsigned i = 0; i < srv_n_log_files; i++) { - sprintf(logfilename + dirnamelen, - "ib_logfile%u", i ? i : INIT_LOG_FILE0); - - dberr_t err = create_log_file(&files[i], logfilename); - - if (err != DB_SUCCESS) { - return(err); - } - } - - DBUG_EXECUTE_IF("innodb_log_abort_8", return(DB_ERROR);); - - /* We did not create the first log file initially as - ib_logfile0, so that crash recovery cannot find it until it - has been completed and renamed. */ - sprintf(logfilename + dirnamelen, "ib_logfile%u", INIT_LOG_FILE0); - - fil_space_create( - logfilename, SRV_LOG_SPACE_FIRST_ID, 0, - FIL_LOG, - NULL /* no encryption yet */, - true /* this is create */); - - ut_a(fil_validate()); - - logfile0 = fil_node_create( - logfilename, (ulint) srv_log_file_size, - SRV_LOG_SPACE_FIRST_ID, FALSE); - ut_a(logfile0); - - for (unsigned i = 1; i < srv_n_log_files; i++) { - sprintf(logfilename + dirnamelen, "ib_logfile%u", i); - - if (!fil_node_create( - logfilename, - (ulint) srv_log_file_size, - SRV_LOG_SPACE_FIRST_ID, FALSE)) { - ut_error; - } - } - -#ifdef UNIV_LOG_ARCHIVE - /* Create the file space object for archived logs. */ - fil_space_create("arch_log_space", SRV_LOG_SPACE_FIRST_ID + 1, - 0, FIL_LOG, NULL /* no encryption yet */, true /* create */); -#endif - log_group_init(0, srv_n_log_files, - srv_log_file_size * UNIV_PAGE_SIZE, - SRV_LOG_SPACE_FIRST_ID, - SRV_LOG_SPACE_FIRST_ID + 1); - - fil_open_log_and_system_tablespace_files(); - - /* Create a log checkpoint. */ - mutex_enter(&log_sys->mutex); - ut_d(recv_no_log_write = srv_apply_log_only); - recv_reset_logs( -#ifdef UNIV_LOG_ARCHIVE - UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no, - TRUE, -#endif - lsn); - mutex_exit(&log_sys->mutex); - - return(DB_SUCCESS); -} - -/** Rename the first redo log file. -@param[in,out] logfilename buffer for the log file name -@param[in] dirnamelen length of the directory path -@param[in] lsn FIL_PAGE_FILE_FLUSH_LSN value -@param[in,out] logfile0 name of the first log file -@return error code -@retval DB_SUCCESS on successful operation */ -MY_ATTRIBUTE((warn_unused_result, nonnull)) -static -dberr_t -create_log_files_rename( -/*====================*/ - char* logfilename, /*!< in/out: buffer for log file name */ - size_t dirnamelen, /*!< in: length of the directory path */ - lsn_t lsn, /*!< in: FIL_PAGE_FILE_FLUSH_LSN value */ - char* logfile0) /*!< in/out: name of the first log file */ -{ - /* If innodb_flush_method=O_DSYNC, - we need to explicitly flush the log buffers. */ - fil_flush(SRV_LOG_SPACE_FIRST_ID); - - DBUG_EXECUTE_IF("innodb_log_abort_9", return(DB_ERROR);); - - /* Close the log files, so that we can rename - the first one. */ - fil_close_log_files(false); - - /* Rename the first log file, now that a log - checkpoint has been created. */ - sprintf(logfilename + dirnamelen, "ib_logfile%u", 0); - - ib_logf(IB_LOG_LEVEL_INFO, - "Renaming log file %s to %s", logfile0, logfilename); - - mutex_enter(&log_sys->mutex); - ut_ad(strlen(logfile0) == 2 + strlen(logfilename)); - dberr_t err = os_file_rename( - innodb_file_log_key, logfile0, logfilename) - ? DB_SUCCESS : DB_ERROR; - - /* Replace the first file with ib_logfile0. */ - strcpy(logfile0, logfilename); - mutex_exit(&log_sys->mutex); - - DBUG_EXECUTE_IF("innodb_log_abort_10", err = DB_ERROR;); - - if (err == DB_SUCCESS) { - fil_open_log_and_system_tablespace_files(); - ib_logf(IB_LOG_LEVEL_WARN, - "New log files created, LSN=" LSN_PF, lsn); - } - - return(err); -} - -/*********************************************************************//** -Opens a log file. -@return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -open_log_file( -/*==========*/ - pfs_os_file_t* file, /*!< out: file handle */ - const char* name, /*!< in: log file name */ - os_offset_t* size) /*!< out: file size */ -{ - ibool ret; - - *file = os_file_create(innodb_file_log_key, name, - OS_FILE_OPEN, OS_FILE_AIO, - OS_LOG_FILE, &ret, FALSE); - if (!ret) { - ib_logf(IB_LOG_LEVEL_ERROR, "Unable to open '%s'", name); - return(DB_ERROR); - } - - *size = os_file_get_size(*file); - - ret = os_file_close(*file); - ut_a(ret); - return(DB_SUCCESS); -} - - -/** Creates or opens database data files and closes them. -@param[out] create_new_db true = create new database -@param[out] min_arch_log_no min of archived log numbers in - data files -@param[out] max_arch_log_no max of archived log numbers in - data files -@param[out] flushed_lsn flushed lsn in fist datafile -@param[out] sum_of_new_sizes sum of sizes of the new files - added -@return DB_SUCCESS or error code */ -MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -open_or_create_data_files( - bool* create_new_db, -#ifdef UNIV_LOG_ARCHIVE - lsn_t* min_arch_log_no, - lsn_t* max_arch_log_no, -#endif /* UNIV_LOG_ARCHIVE */ - lsn_t* flushed_lsn, - ulint* sum_of_new_sizes) -{ - ibool ret; - ulint i; - bool one_opened = false; - bool one_created = false; - os_offset_t size; - ulint flags; - ulint space = 0; - ulint rounded_size_pages; - char name[10000]; - fil_space_crypt_t* crypt_data=NULL; - - if (srv_n_data_files >= 1000) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Can only have < 1000 data files, you have " - "defined %lu", (ulong) srv_n_data_files); - - return(DB_ERROR); - } - - *sum_of_new_sizes = 0; - - *create_new_db = false; - - srv_normalize_path_for_win(srv_data_home); - - for (i = 0; i < srv_n_data_files; i++) { - ulint dirnamelen; - - srv_normalize_path_for_win(srv_data_file_names[i]); - dirnamelen = strlen(srv_data_home); - - ut_a(dirnamelen + strlen(srv_data_file_names[i]) - < (sizeof name) - 1); - - memcpy(name, srv_data_home, dirnamelen); - - /* Add a path separator if needed. */ - if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) { - name[dirnamelen++] = SRV_PATH_SEPARATOR; - } - - strcpy(name + dirnamelen, srv_data_file_names[i]); - - /* Note: It will return true if the file doesn' exist. */ - - if (!srv_file_check_mode(name)) { - - return(DB_FAIL); - - } else if (srv_data_file_is_raw_partition[i] == 0) { - - /* First we try to create the file: if it already - exists, ret will get value FALSE */ - - files[i] = os_file_create( - innodb_file_data_key, name, OS_FILE_CREATE, - OS_FILE_NORMAL, OS_DATA_FILE, &ret, FALSE); - - if (srv_read_only_mode) { - - if (ret) { - goto size_check; - } - - ib_logf(IB_LOG_LEVEL_ERROR, - "Opening %s failed!", name); - - return(DB_ERROR); - - } else if (!ret - && os_file_get_last_error(false) - != OS_FILE_ALREADY_EXISTS -#ifdef UNIV_AIX - /* AIX 5.1 after security patch ML7 may have - errno set to 0 here, which causes our - function to return 100; work around that - AIX problem */ - && os_file_get_last_error(false) != 100 -#endif /* UNIV_AIX */ - ) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Creating or opening %s failed!", - name); - - return(DB_ERROR); - } - - } else if (srv_data_file_is_raw_partition[i] == SRV_NEW_RAW) { - - ut_a(!srv_read_only_mode); - - /* The partition is opened, not created; then it is - written over */ - - srv_start_raw_disk_in_use = TRUE; - srv_created_new_raw = TRUE; - - files[i] = os_file_create( - innodb_file_data_key, name, OS_FILE_OPEN_RAW, - OS_FILE_NORMAL, OS_DATA_FILE, &ret, FALSE); - - if (!ret) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Error in opening %s", name); - - return(DB_ERROR); - } - - const char* check_msg; - - check_msg = fil_read_first_page( - files[i], FALSE, &flags, &space, - flushed_lsn, NULL); - - /* If first page is valid, don't overwrite DB. - It prevents overwriting DB when mysql_install_db - starts mysqld multiple times during bootstrap. */ - if (check_msg == NULL) { - - srv_created_new_raw = FALSE; - ret = FALSE; - } - - } else if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { - srv_start_raw_disk_in_use = TRUE; - - ret = FALSE; - } else { - ut_a(0); - } - - if (ret == FALSE) { - const char* check_msg; - /* We open the data file */ - - if (one_created) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Data files can only be added at " - "the end of a tablespace, but " - "data file %s existed beforehand.", - name); - return(DB_ERROR); - } - - if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { - ut_a(!srv_read_only_mode); - files[i] = os_file_create( - innodb_file_data_key, - name, OS_FILE_OPEN_RAW, - OS_FILE_NORMAL, OS_DATA_FILE, &ret, FALSE); - } else if (i == 0) { - files[i] = os_file_create( - innodb_file_data_key, - name, OS_FILE_OPEN_RETRY, - OS_FILE_NORMAL, OS_DATA_FILE, &ret, FALSE); - } else { - files[i] = os_file_create( - innodb_file_data_key, - name, OS_FILE_OPEN, OS_FILE_NORMAL, - OS_DATA_FILE, &ret, FALSE); - } - - if (!ret) { - os_file_get_last_error(true); - - ib_logf(IB_LOG_LEVEL_ERROR, - "Can't open '%s'", name); - - return(DB_ERROR); - } - - if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) { - goto skip_size_check; - } - -size_check: - size = os_file_get_size(files[i]); - ut_a(size != (os_offset_t) -1); - - /* If InnoDB encountered an error or was killed - while extending the data file, the last page - could be incomplete. */ - - rounded_size_pages = static_cast<ulint>( - size >> UNIV_PAGE_SIZE_SHIFT); - - if (i == srv_n_data_files - 1 - && srv_auto_extend_last_data_file) { - - if (srv_data_file_sizes[i] > rounded_size_pages - || (srv_last_file_size_max > 0 - && srv_last_file_size_max - < rounded_size_pages)) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "auto-extending " - "data file %s is " - "of a different size " - ULINTPF " pages (rounded " - "down to MB) than specified " - "in the .cnf file: " - "initial " ULINTPF " pages, " - "max " ULINTPF " (relevant if " - "non-zero) pages!", - name, - rounded_size_pages, - srv_data_file_sizes[i], - srv_last_file_size_max); - - return(DB_ERROR); - } - - srv_data_file_sizes[i] = rounded_size_pages; - } - - if (rounded_size_pages != srv_data_file_sizes[i]) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Data file %s is of a different " - "size " ULINTPF " pages (rounded down to MB) " - "than specified in the .cnf file " - ULINTPF " pages!", - name, - rounded_size_pages, - srv_data_file_sizes[i]); - - return(DB_ERROR); - } -skip_size_check: - - /* This is the earliest location where we can load - the double write buffer. */ - if (i == 0) { - /* XtraBackup never loads corrupted pages from - the doublewrite buffer */ - buf_dblwr_init_or_load_pages( - files[i], srv_data_file_names[i], !IS_XTRABACKUP()); - } - - bool retry = true; -check_first_page: - check_msg = fil_read_first_page( - files[i], one_opened, &flags, &space, - flushed_lsn, &crypt_data); - - if (check_msg) { - - if (retry) { - fsp_open_info fsp; - const ulint page_no = 0; - - retry = false; - fsp.id = 0; - fsp.filepath = srv_data_file_names[i]; - fsp.file = files[i]; - - if (fil_user_tablespace_restore_page( - &fsp, page_no)) { - goto check_first_page; - } - } - - ib_logf(IB_LOG_LEVEL_ERROR, - "%s in data file %s", - check_msg, name); - return(DB_ERROR); - } - - /* The first file of the system tablespace must - have space ID = TRX_SYS_SPACE. The FSP_SPACE_ID - field in files greater than ibdata1 are unreliable. */ - ut_a(one_opened || space == TRX_SYS_SPACE); - - /* Check the flags for the first system tablespace - file only. */ - if (!one_opened - && UNIV_PAGE_SIZE - != fsp_flags_get_page_size(flags)) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Data file \"%s\" uses page size " ULINTPF " ," - "but the start-up parameter " - "is --innodb-page-size=" ULINTPF " .", - name, - fsp_flags_get_page_size(flags), - UNIV_PAGE_SIZE); - - return(DB_ERROR); - } - - one_opened = TRUE; - } else if (!srv_read_only_mode) { - /* We created the data file and now write it full of - zeros */ - - one_created = TRUE; - - if (i > 0) { - ib_logf(IB_LOG_LEVEL_INFO, - "Data file %s did not" - " exist: new to be created", - name); - } else { - ib_logf(IB_LOG_LEVEL_INFO, - "The first specified " - "data file %s did not exist: " - "a new database to be created!", - name); - - *create_new_db = TRUE; - } - - ib_logf(IB_LOG_LEVEL_INFO, - "Setting file %s size to " ULINTPF " MB", - name, - (srv_data_file_sizes[i] - >> (20 - UNIV_PAGE_SIZE_SHIFT))); - - ret = os_file_set_size( - name, files[i], - (os_offset_t) srv_data_file_sizes[i] - << UNIV_PAGE_SIZE_SHIFT - /* TODO: enable page_compression on the - system tablespace and add - , FSP_FLAGS_HAS_PAGE_COMPRESSION(flags)*/); - - if (!ret) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Error in creating %s: " - "probably out of disk space", - name); - - return(DB_ERROR); - } - - *sum_of_new_sizes += srv_data_file_sizes[i]; - } - - ret = os_file_close(files[i]); - ut_a(ret); - - if (i == 0) { - flags = FSP_FLAGS_PAGE_SSIZE(); - - fil_space_create(name, 0, flags, FIL_TABLESPACE, - crypt_data, (*create_new_db) == true); - } - - ut_a(fil_validate()); - - if (!fil_node_create(name, srv_data_file_sizes[i], 0, - srv_data_file_is_raw_partition[i] != 0)) { - return(DB_ERROR); - } - } - - return(DB_SUCCESS); -} - -/*********************************************************************//** -Create undo tablespace. -@return DB_SUCCESS or error code */ -static -dberr_t -srv_undo_tablespace_create( -/*=======================*/ - const char* name, /*!< in: tablespace name */ - ulint size) /*!< in: tablespace size in pages */ -{ - pfs_os_file_t fh; - ibool ret; - dberr_t err = DB_SUCCESS; - - os_file_create_subdirs_if_needed(name); - - fh = os_file_create( - innodb_file_data_key, - name, - srv_read_only_mode ? OS_FILE_OPEN : OS_FILE_CREATE, - OS_FILE_NORMAL, OS_DATA_FILE, &ret, FALSE); - - if (srv_read_only_mode && ret) { - ib_logf(IB_LOG_LEVEL_INFO, - "%s opened in read-only mode", name); - } else if (ret == FALSE) { - if (os_file_get_last_error(false) != OS_FILE_ALREADY_EXISTS -#ifdef UNIV_AIX - /* AIX 5.1 after security patch ML7 may have - errno set to 0 here, which causes our function - to return 100; work around that AIX problem */ - && os_file_get_last_error(false) != 100 -#endif /* UNIV_AIX */ - ) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Can't create UNDO tablespace %s", name); - } else { - ib_logf(IB_LOG_LEVEL_ERROR, - "Creating system tablespace with" - " existing undo tablespaces is not" - " supported. Please delete all undo" - " tablespaces before creating new" - " system tablespace."); - } - err = DB_ERROR; - } else { - ut_a(!srv_read_only_mode); - - /* We created the data file and now write it full of zeros */ - - ib_logf(IB_LOG_LEVEL_INFO, - "Data file %s did not exist: new to be created", - name); - - ib_logf(IB_LOG_LEVEL_INFO, - "Setting file %s size to %lu MB", - name, size >> (20 - UNIV_PAGE_SIZE_SHIFT)); - - ret = os_file_set_size(name, fh, size << UNIV_PAGE_SIZE_SHIFT - /* TODO: enable page_compression on the - system tablespace and add - FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) - */); - - if (!ret) { - ib_logf(IB_LOG_LEVEL_INFO, - "Error in creating %s: probably out of " - "disk space", name); - - err = DB_ERROR; - } - - os_file_close(fh); - } - - return(err); -} - -/*********************************************************************//** -Open an undo tablespace. -@return DB_SUCCESS or error code */ -static -dberr_t -srv_undo_tablespace_open( -/*=====================*/ - const char* name, /*!< in: tablespace name */ - ulint space) /*!< in: tablespace id */ -{ - pfs_os_file_t fh; - dberr_t err = DB_ERROR; - ibool ret; - ulint flags; - - if (!srv_file_check_mode(name)) { - ib_logf(IB_LOG_LEVEL_ERROR, - "UNDO tablespaces must be %s!", - srv_read_only_mode ? "writable" : "readable"); - - return(DB_ERROR); - } - - fh = os_file_create( - innodb_file_data_key, name, - OS_FILE_OPEN_RETRY - | OS_FILE_ON_ERROR_NO_EXIT - | OS_FILE_ON_ERROR_SILENT, - OS_FILE_NORMAL, - OS_DATA_FILE, - &ret, - FALSE); - - /* If the file open was successful then load the tablespace. */ - - if (ret) { - os_offset_t size; - - size = os_file_get_size(fh); - ut_a(size != (os_offset_t) -1); - - /* Load the tablespace into InnoDB's internal - data structures. */ - - const char* check_msg; - fil_space_crypt_t* crypt_data = NULL; - - /* Set the compressed page size to 0 (non-compressed) */ - flags = FSP_FLAGS_PAGE_SSIZE(); - - /* Read first page to find out does the crypt_info - exists on undo tablespace. */ - check_msg = fil_read_first_page( - fh, FALSE, &flags, &space, - NULL, &crypt_data, false); - - ret = os_file_close(fh); - ut_a(ret); - - if (check_msg) { - ib_logf(IB_LOG_LEVEL_ERROR, - "%s in data file %s", - check_msg, name); - return (err); - } - - /* We set the biggest space id to the undo tablespace - because InnoDB hasn't opened any other tablespace apart - from the system tablespace. */ - - fil_set_max_space_id_if_bigger(space); - - fil_space_create(name, space, flags, FIL_TABLESPACE, - crypt_data, - true /* create */); - - ut_a(fil_validate()); - - os_offset_t n_pages = size / UNIV_PAGE_SIZE; - - /* On 64 bit Windows ulint can be 32 bit and os_offset_t - is 64 bit. It is OK to cast the n_pages to ulint because - the unit has been scaled to pages and they are always - 32 bit. */ - if (fil_node_create(name, (ulint) n_pages, space, FALSE)) { - err = DB_SUCCESS; - } - } - - return(err); -} - -/******************************************************************** -Opens the configured number of undo tablespaces. -@return DB_SUCCESS or error code */ -dberr_t -srv_undo_tablespaces_init( -/*======================*/ - ibool create_new_db, /*!< in: TRUE if new db being - created */ - ibool backup_mode, /*!< in: TRUE disables reading - the system tablespace (used in - XtraBackup), FALSE is passed on - recovery. */ - const ulint n_conf_tablespaces, /*!< in: configured undo - tablespaces */ - ulint* n_opened) /*!< out: number of UNDO - tablespaces successfully - discovered and opened */ -{ - ulint i; - dberr_t err = DB_SUCCESS; - ulint prev_space_id = 0; - ulint n_undo_tablespaces; - ulint undo_tablespace_ids[TRX_SYS_N_RSEGS + 1]; - - *n_opened = 0; - - ut_a(n_conf_tablespaces <= TRX_SYS_N_RSEGS); - - memset(undo_tablespace_ids, 0x0, sizeof(undo_tablespace_ids)); - - /* Create the undo spaces only if we are creating a new - instance. We don't allow creating of new undo tablespaces - in an existing instance (yet). This restriction exists because - we check in several places for SYSTEM tablespaces to be less than - the min of user defined tablespace ids. Once we implement saving - the location of the undo tablespaces and their space ids this - restriction will/should be lifted. */ - - for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) { - char name[OS_FILE_MAX_PATH]; - ulint space_id = i + 1; - - DBUG_EXECUTE_IF("innodb_undo_upgrade", - space_id = i + 3;); - - ut_snprintf( - name, sizeof(name), - "%s%cundo%03lu", - srv_undo_dir, SRV_PATH_SEPARATOR, space_id); - - if (i == 0) { - srv_undo_space_id_start = space_id; - prev_space_id = srv_undo_space_id_start - 1; - } - - undo_tablespace_ids[i] = space_id; - - err = srv_undo_tablespace_create( - name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES); - - if (err != DB_SUCCESS) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Could not create undo tablespace '%s'.", - name); - - return(err); - } - } - - /* Get the tablespace ids of all the undo segments excluding - the system tablespace (0). If we are creating a new instance then - we build the undo_tablespace_ids ourselves since they don't - already exist. */ - - if (!create_new_db && !backup_mode) { - n_undo_tablespaces = trx_rseg_get_n_undo_tablespaces( - undo_tablespace_ids); - - if (n_undo_tablespaces != 0) { - srv_undo_space_id_start = undo_tablespace_ids[0]; - prev_space_id = srv_undo_space_id_start - 1; - } - - } else { - n_undo_tablespaces = n_conf_tablespaces; - - undo_tablespace_ids[n_conf_tablespaces] = ULINT_UNDEFINED; - - if (backup_mode) { - ut_ad(!create_new_db); - for (i = 0; i < n_undo_tablespaces; i++) { - undo_tablespace_ids[i] - = i + srv_undo_space_id_start; - } - - prev_space_id = srv_undo_space_id_start - 1; - } - } - - /* Open all the undo tablespaces that are currently in use. If we - fail to open any of these it is a fatal error. The tablespace ids - should be contiguous. It is a fatal error because they are required - for recovery and are referenced by the UNDO logs (a.k.a RBS). */ - - for (i = 0; i < n_undo_tablespaces; ++i) { - char name[OS_FILE_MAX_PATH]; - - ut_snprintf( - name, sizeof(name), - "%s%cundo%03lu", - srv_undo_dir, SRV_PATH_SEPARATOR, - undo_tablespace_ids[i]); - - /* Should be no gaps in undo tablespace ids. */ - ut_a(prev_space_id + 1 == undo_tablespace_ids[i]); - - /* The system space id should not be in this array. */ - ut_a(undo_tablespace_ids[i] != 0); - ut_a(undo_tablespace_ids[i] != ULINT_UNDEFINED); - - err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); - - if (err != DB_SUCCESS) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Unable to open undo tablespace '%s'.", name); - - return(err); - } - - prev_space_id = undo_tablespace_ids[i]; - - ++*n_opened; - } - - /* Open any extra unused undo tablespaces. These must be contiguous. - We stop at the first failure. These are undo tablespaces that are - not in use and therefore not required by recovery. We only check - that there are no gaps. */ - - for (i = prev_space_id + 1; i < TRX_SYS_N_RSEGS; ++i) { - char name[OS_FILE_MAX_PATH]; - - ut_snprintf( - name, sizeof(name), - "%s%cundo%03lu", srv_undo_dir, SRV_PATH_SEPARATOR, i); - - /* Undo space ids start from 1. */ - err = srv_undo_tablespace_open(name, i); - - if (err != DB_SUCCESS) { - break; - } - - /** Note the first undo tablespace id in case of - no active undo tablespace. */ - if (n_undo_tablespaces == 0) { - srv_undo_space_id_start = i; - } - - ++n_undo_tablespaces; - - ++*n_opened; - } - - /** Explictly specify the srv_undo_space_id_start - as zero when there are no undo tablespaces. */ - if (n_undo_tablespaces == 0) { - srv_undo_space_id_start = 0; - } - - /* If the user says that there are fewer than what we find we - tolerate that discrepancy but not the inverse. Because there could - be unused undo tablespaces for future use. */ - - if (n_conf_tablespaces > n_undo_tablespaces) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Expected to open %lu undo " - "tablespaces but was able\n", - n_conf_tablespaces); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: to find only %lu undo " - "tablespaces.\n", n_undo_tablespaces); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Set the " - "innodb_undo_tablespaces parameter to " - "the\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: correct value and retry. Suggested " - "value is %lu\n", n_undo_tablespaces); - - return(err != DB_SUCCESS ? err : DB_ERROR); - - } else if (n_undo_tablespaces > 0) { - - ib_logf(IB_LOG_LEVEL_INFO, "Opened %lu undo tablespaces", - n_undo_tablespaces); - - if (n_conf_tablespaces == 0) { - ib_logf(IB_LOG_LEVEL_WARN, - "Using the system tablespace for all UNDO " - "logging because innodb_undo_tablespaces=0"); - } - } - - if (create_new_db) { - mtr_t mtr; - - mtr_start(&mtr); - - /* The undo log tablespace */ - for (i = 0; i < n_undo_tablespaces; ++i) { - - fsp_header_init( - undo_tablespace_ids[i], - SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr); - } - - mtr_commit(&mtr); - } - - return(DB_SUCCESS); -} - -/******************************************************************** -Wait for the purge thread(s) to start up. */ -static -void -srv_start_wait_for_purge_to_start() -/*===============================*/ -{ - /* Wait for the purge coordinator and master thread to startup. */ - - purge_state_t state = trx_purge_state(); - - ut_a(state != PURGE_STATE_DISABLED); - - while (srv_shutdown_state == SRV_SHUTDOWN_NONE - && srv_force_recovery < SRV_FORCE_NO_BACKGROUND - && state == PURGE_STATE_INIT) { - - switch (state = trx_purge_state()) { - case PURGE_STATE_RUN: - case PURGE_STATE_STOP: - break; - - case PURGE_STATE_INIT: - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for purge to start"); - - os_thread_sleep(50000); - break; - - case PURGE_STATE_EXIT: - case PURGE_STATE_DISABLED: - ut_error; - } - } -} - -/*********************************************************************//** -Initializes the log tracking subsystem and starts its thread. */ -static -void -init_log_online(void) -/*=================*/ -{ - if (UNIV_UNLIKELY(srv_force_recovery > 0 || srv_read_only_mode)) { - srv_track_changed_pages = FALSE; - return; - } - - if (srv_track_changed_pages) { - - log_online_read_init(); - - /* Create the thread that follows the redo log to output the - changed page bitmap */ - srv_redo_log_follow_thread_handle = os_thread_create(&srv_redo_log_follow_thread, NULL, - thread_ids + 5 + SRV_MAX_N_IO_THREADS); - srv_redo_log_follow_thread_started = true; - } -} - -/******************************************************************** -Starts InnoDB and creates a new database if database files -are not found and the user wants. -@return DB_SUCCESS or error code */ -UNIV_INTERN -dberr_t -innobase_start_or_create_for_mysql() -{ - bool create_new_db; - lsn_t flushed_lsn; -#ifdef UNIV_LOG_ARCHIVE - lsn_t min_arch_log_no = LSN_MAX; - lsn_t max_arch_log_no = LSN_MAX; -#endif /* UNIV_LOG_ARCHIVE */ - ulint sum_of_new_sizes; - dberr_t err; - unsigned i; - ulint srv_n_log_files_found = srv_n_log_files; - ulint io_limit; - mtr_t mtr; - ib_bh_t* ib_bh; - ulint n_recovered_trx; - char logfilename[10000]; - char* logfile0 = NULL; - size_t dirnamelen; - bool sys_datafiles_created = false; - - /* Check that os_fast_mutexes work as expected */ - os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex); - - ut_a(0 == os_fast_mutex_trylock(&srv_os_test_mutex)); - - os_fast_mutex_unlock(&srv_os_test_mutex); - - os_fast_mutex_lock(&srv_os_test_mutex); - - os_fast_mutex_unlock(&srv_os_test_mutex); - - os_fast_mutex_free(&srv_os_test_mutex); - - /* This should be initialized early */ - ut_init_timer(); - - if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { - srv_read_only_mode = 1; - } - - high_level_read_only = srv_read_only_mode - || srv_force_recovery > SRV_FORCE_NO_TRX_UNDO; - - if (srv_read_only_mode) { - ib_logf(IB_LOG_LEVEL_INFO, "Started in read only mode"); - } - -#ifdef HAVE_DARWIN_THREADS -# ifdef F_FULLFSYNC - /* This executable has been compiled on Mac OS X 10.3 or later. - Assume that F_FULLFSYNC is available at run-time. */ - srv_have_fullfsync = TRUE; -# else /* F_FULLFSYNC */ - /* This executable has been compiled on Mac OS X 10.2 - or earlier. Determine if the executable is running - on Mac OS X 10.3 or later. */ - struct utsname utsname; - if (uname(&utsname)) { - ut_print_timestamp(stderr); - fputs(" InnoDB: cannot determine Mac OS X version!\n", stderr); - } else { - srv_have_fullfsync = strcmp(utsname.release, "7.") >= 0; - } - if (!srv_have_fullfsync) { - ut_print_timestamp(stderr); - fputs(" InnoDB: On Mac OS X, fsync() may be " - "broken on internal drives,\n", stderr); - ut_print_timestamp(stderr); - fputs(" InnoDB: making transactions unsafe!\n", stderr); - } -# endif /* F_FULLFSYNC */ -#endif /* HAVE_DARWIN_THREADS */ - - ib_logf(IB_LOG_LEVEL_INFO, - "Using %s to ref count buffer pool pages", -#ifdef PAGE_ATOMIC_REF_COUNT - "atomics" -#else - "mutexes" -#endif /* PAGE_ATOMIC_REF_COUNT */ - ); - - compile_time_assert(sizeof(ulint) == sizeof(void*)); - - /* If stacktrace is used we set up signal handler for SIGUSR2 signal - here. If signal handler set fails we report that and disable - stacktrace feature. */ - - if (srv_use_stacktrace) { -#if defined (__linux__) && HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS - struct sigaction sigact; - - sigact.sa_sigaction = os_stacktrace_print; - sigact.sa_flags = SA_RESTART | SA_SIGINFO; - - if (sigaction(SIGUSR2, &sigact, (struct sigaction *)NULL) != 0) - { - fprintf(stderr, " InnoDB:error setting signal handler for %d (%s)\n", - SIGUSR2, strsignal(SIGUSR2)); - srv_use_stacktrace = FALSE; - - } -#endif /* defined (__linux__) && HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS */ - } - -#ifdef UNIV_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_DEBUG switched on !!!!!!!!!"); -#endif - -#ifdef UNIV_IBUF_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!"); -# ifdef UNIV_IBUF_COUNT_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_IBUF_COUNT_DEBUG switched on " - "!!!!!!!!!"); - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: Crash recovery will fail with UNIV_IBUF_COUNT_DEBUG"); -# endif -#endif - -#ifdef UNIV_BLOB_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - "InnoDB: !!!!!!!! UNIV_BLOB_DEBUG switched on !!!!!!!!!\n" - "InnoDB: Server restart may fail with UNIV_BLOB_DEBUG"); -#endif /* UNIV_BLOB_DEBUG */ - -#ifdef UNIV_SYNC_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!"); -#endif - -#ifdef UNIV_SEARCH_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!"); -#endif - -#ifdef UNIV_LOG_LSN_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!"); -#endif /* UNIV_LOG_LSN_DEBUG */ -#ifdef UNIV_MEM_DEBUG - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!"); -#endif - - if (srv_use_sys_malloc) { - ib_logf(IB_LOG_LEVEL_INFO, - "The InnoDB memory heap is disabled"); - } - -#if defined(COMPILER_HINTS_ENABLED) - ib_logf(IB_LOG_LEVEL_INFO, - " InnoDB: Compiler hints enabled."); -#endif /* defined(COMPILER_HINTS_ENABLED) */ - - ib_logf(IB_LOG_LEVEL_INFO, - "" IB_ATOMICS_STARTUP_MSG ""); - - ib_logf(IB_LOG_LEVEL_INFO, - "" IB_MEMORY_BARRIER_STARTUP_MSG ""); - -#ifndef HAVE_MEMORY_BARRIER -#if defined __i386__ || defined __x86_64__ || defined _M_IX86 || defined _M_X64 || defined __WIN__ -#else - ib_logf(IB_LOG_LEVEL_WARN, - "MySQL was built without a memory barrier capability on this" - " architecture, which might allow a mutex/rw_lock violation" - " under high thread concurrency. This may cause a hang."); -#endif /* IA32 or AMD64 */ -#endif /* HAVE_MEMORY_BARRIER */ - - ib_logf(IB_LOG_LEVEL_INFO, - "Compressed tables use zlib " ZLIB_VERSION -#ifdef UNIV_ZIP_DEBUG - " with validation" -#endif /* UNIV_ZIP_DEBUG */ - ); -#ifdef UNIV_ZIP_COPY - ib_logf(IB_LOG_LEVEL_INFO, "and extra copying"); -#endif /* UNIV_ZIP_COPY */ - - - /* Since InnoDB does not currently clean up all its internal data - structures in MySQL Embedded Server Library server_end(), we - print an error message if someone tries to start up InnoDB a - second time during the process lifetime. */ - - if (srv_start_has_been_called) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error: startup called second time " - "during the process\n"); - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: lifetime. In the MySQL Embedded " - "Server Library you\n"); - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: cannot call server_init() more " - "than once during the\n"); - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: process lifetime.\n"); - } - - srv_start_has_been_called = TRUE; - -#ifdef UNIV_DEBUG - log_do_write = TRUE; -#endif /* UNIV_DEBUG */ - /* yydebug = TRUE; */ - - srv_is_being_started = TRUE; - srv_startup_is_before_trx_rollback_phase = TRUE; - -#ifdef __WIN__ - srv_use_native_aio = TRUE; - -#elif defined(LINUX_NATIVE_AIO) - - if (srv_use_native_aio) { - ib_logf(IB_LOG_LEVEL_INFO, "Using Linux native AIO"); - } -#else - /* Currently native AIO is supported only on windows and linux - and that also when the support is compiled in. In all other - cases, we ignore the setting of innodb_use_native_aio. */ - srv_use_native_aio = FALSE; -#endif /* __WIN__ */ - - if (srv_file_flush_method_str == NULL) { - /* These are the default options */ - - srv_unix_file_flush_method = SRV_UNIX_FSYNC; - - srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; - } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) { - srv_unix_file_flush_method = SRV_UNIX_FSYNC; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) { - srv_unix_file_flush_method = SRV_UNIX_O_DSYNC; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) { - srv_unix_file_flush_method = SRV_UNIX_O_DIRECT; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "ALL_O_DIRECT")) { - srv_unix_file_flush_method = SRV_UNIX_ALL_O_DIRECT; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT_NO_FSYNC")) { - srv_unix_file_flush_method = SRV_UNIX_O_DIRECT_NO_FSYNC; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) { - srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) { - srv_unix_file_flush_method = SRV_UNIX_NOSYNC; -#ifdef _WIN32 - } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) { - srv_win_file_flush_method = SRV_WIN_IO_NORMAL; - srv_use_native_aio = FALSE; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) { - srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; - srv_use_native_aio = FALSE; - - } else if (0 == ut_strcmp(srv_file_flush_method_str, - "async_unbuffered")) { - srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; - srv_use_native_aio = TRUE; -#endif /* __WIN__ */ - } else { - ib_logf(IB_LOG_LEVEL_ERROR, - "Unrecognized value %s for innodb_flush_method", - srv_file_flush_method_str); - return(DB_ERROR); - } - - /* Note that the call srv_boot() also changes the values of - some variables to the units used by InnoDB internally */ - - /* Set the maximum number of threads which can wait for a semaphore - inside InnoDB: this is the 'sync wait array' size, as well as the - maximum number of threads that can wait in the 'srv_conc array' for - their time to enter InnoDB. */ - -#define BUF_POOL_SIZE_THRESHOLD (1024 * 1024 * 1024) - srv_max_n_threads = 1 /* io_ibuf_thread */ - + 1 /* io_log_thread */ - + 1 /* lock_wait_timeout_thread */ - + 1 /* srv_error_monitor_thread */ - + 1 /* srv_monitor_thread */ - + 1 /* srv_master_thread */ - + 1 /* srv_redo_log_follow_thread */ - + 1 /* srv_purge_coordinator_thread */ - + 1 /* buf_dump_thread */ - + 1 /* dict_stats_thread */ - + 1 /* fts_optimize_thread */ - + 1 /* recv_writer_thread */ - + 1 /* buf_flush_page_cleaner_thread */ - + 1 /* trx_rollback_or_clean_all_recovered */ - + 128 /* added as margin, for use of - InnoDB Memcached etc. */ - + max_connections - + srv_n_read_io_threads - + srv_n_write_io_threads - + srv_n_purge_threads - /* FTS Parallel Sort */ - + fts_sort_pll_degree * FTS_NUM_AUX_INDEX - * max_connections; - - if (srv_buf_pool_size < BUF_POOL_SIZE_THRESHOLD) { - /* If buffer pool is less than 1 GB, - use only one buffer pool instance */ - srv_buf_pool_instances = 1; - } - - srv_boot(); - - ib_logf(IB_LOG_LEVEL_INFO, ut_crc32_implementation); - - if (!srv_read_only_mode) { - - mutex_create(srv_monitor_file_mutex_key, - &srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK); - - if (srv_innodb_status) { - - srv_monitor_file_name = static_cast<char*>( - mem_alloc( - strlen(fil_path_to_mysql_datadir) - + 20 + sizeof "/innodb_status.")); - - sprintf(srv_monitor_file_name, "%s/innodb_status.%lu", - fil_path_to_mysql_datadir, - os_proc_get_number()); - - srv_monitor_file = fopen(srv_monitor_file_name, "w+"); - - if (!srv_monitor_file) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Unable to create %s: %s", - srv_monitor_file_name, - strerror(errno)); - - return(DB_ERROR); - } - } else { - srv_monitor_file_name = NULL; - srv_monitor_file = os_file_create_tmpfile(NULL); - - if (!srv_monitor_file) { - return(DB_ERROR); - } - } - - mutex_create(srv_dict_tmpfile_mutex_key, - &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); - - srv_dict_tmpfile = os_file_create_tmpfile(NULL); - - if (!srv_dict_tmpfile) { - return(DB_ERROR); - } - - mutex_create(srv_misc_tmpfile_mutex_key, - &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); - - srv_misc_tmpfile = os_file_create_tmpfile(NULL); - - if (!srv_misc_tmpfile) { - return(DB_ERROR); - } - } - - /* If user has set the value of innodb_file_io_threads then - we'll emit a message telling the user that this parameter - is now deprecated. */ - if (srv_n_file_io_threads != 4) { - ib_logf(IB_LOG_LEVEL_WARN, - "innodb_file_io_threads is deprecated. Please use " - "innodb_read_io_threads and innodb_write_io_threads " - "instead"); - } - - /* Now overwrite the value on srv_n_file_io_threads */ - srv_n_file_io_threads = srv_n_read_io_threads; - - if (!srv_read_only_mode) { - /* Add the log and ibuf IO threads. */ - srv_n_file_io_threads += 2; - srv_n_file_io_threads += srv_n_write_io_threads; - } else { - ib_logf(IB_LOG_LEVEL_INFO, - "Disabling background IO write threads."); - - srv_n_write_io_threads = 0; - } - - ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS); - - io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD; - - /* On Windows when using native aio the number of aio requests - that a thread can handle at a given time is limited to 32 - i.e.: SRV_N_PENDING_IOS_PER_THREAD */ -# ifdef __WIN__ - if (srv_use_native_aio) { - io_limit = SRV_N_PENDING_IOS_PER_THREAD; - } -# endif /* __WIN__ */ - - if (!os_aio_init(io_limit, - srv_n_read_io_threads, - srv_n_write_io_threads, - SRV_MAX_N_PENDING_SYNC_IOS)) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Fatal : Cannot initialize AIO sub-system"); -#if defined(LINUX_NATIVE_AIO) - ib_logf(IB_LOG_LEVEL_INFO, - "You can try increasing system fs.aio-max-nr to 1048576 " - "or larger or setting innodb_use_native_aio = 0 in my.cnf"); -#endif - - return(DB_ERROR); - } - - fil_init(srv_file_per_table ? 50000 : 5000, srv_max_n_open_files); - - double size; - char unit; - - if (srv_buf_pool_size >= 1024 * 1024 * 1024) { - size = ((double) srv_buf_pool_size) / (1024 * 1024 * 1024); - unit = 'G'; - } else { - size = ((double) srv_buf_pool_size) / (1024 * 1024); - unit = 'M'; - } - - /* Print time to initialize the buffer pool */ - ib_logf(IB_LOG_LEVEL_INFO, - "Initializing buffer pool, size = %.1f%c", size, unit); - - err = buf_pool_init(srv_buf_pool_size, static_cast<bool>(srv_numa_interleave), - srv_buf_pool_instances); - - if (err != DB_SUCCESS) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Cannot allocate memory for the buffer pool"); - - return(DB_ERROR); - } - - ib_logf(IB_LOG_LEVEL_INFO, - "Completed initialization of buffer pool"); - -#ifdef UNIV_DEBUG - /* We have observed deadlocks with a 5MB buffer pool but - the actual lower limit could very well be a little higher. */ - - if (srv_buf_pool_size <= 5 * 1024 * 1024) { - - ib_logf(IB_LOG_LEVEL_INFO, - "Small buffer pool size (%luM), the flst_validate() " - "debug function can cause a deadlock if the " - "buffer pool fills up.", - srv_buf_pool_size / 1024 / 1024); - } -#endif /* UNIV_DEBUG */ - - fsp_init(); - log_init(); - log_online_init(); - - lock_sys_create(srv_lock_table_size); - - /* Create i/o-handler threads: */ - - for (i = 0; i < srv_n_file_io_threads; ++i) { - - n[i] = i; - - thread_handles[i] = os_thread_create(io_handler_thread, n + i, thread_ids + i); - thread_started[i] = true; - } - - if (srv_n_log_files * srv_log_file_size * UNIV_PAGE_SIZE - >= 512ULL * 1024ULL * 1024ULL * 1024ULL) { - /* log_block_convert_lsn_to_no() limits the returned block - number to 1G and given that OS_FILE_LOG_BLOCK_SIZE is 512 - bytes, then we have a limit of 512 GB. If that limit is to - be raised, then log_block_convert_lsn_to_no() must be - modified. */ - ib_logf(IB_LOG_LEVEL_ERROR, - "Combined size of log files must be < 512 GB"); - - return(DB_ERROR); - } - - if (srv_n_log_files * srv_log_file_size >= ULINT_MAX) { - /* fil_io() takes ulint as an argument and we are passing - (next_offset / UNIV_PAGE_SIZE) to it in log_group_write_buf(). - So (next_offset / UNIV_PAGE_SIZE) must be less than ULINT_MAX. - So next_offset must be < ULINT_MAX * UNIV_PAGE_SIZE. This - means that we are limited to ULINT_MAX * UNIV_PAGE_SIZE which - is 64 TB on 32 bit systems. */ - fprintf(stderr, - " InnoDB: Error: combined size of log files" - " must be < %lu GB\n", - ULINT_MAX / 1073741824 * UNIV_PAGE_SIZE); - - return(DB_ERROR); - } - - sum_of_new_sizes = 0; - - for (i = 0; i < srv_n_data_files; i++) { -#ifndef __WIN__ - if (sizeof(off_t) < 5 - && srv_data_file_sizes[i] - >= (ulint) (1 << (32 - UNIV_PAGE_SIZE_SHIFT))) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: file size must be < 4 GB" - " with this MySQL binary\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: and operating system combination," - " in some OS's < 2 GB\n"); - - return(DB_ERROR); - } -#endif - sum_of_new_sizes += srv_data_file_sizes[i]; - } - - if (!srv_auto_extend_last_data_file && sum_of_new_sizes < 640) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Combined size in innodb_data_file_path" - " must be at least %u MiB", - 640 >> (20 - UNIV_PAGE_SIZE_SHIFT)); - - return(DB_ERROR); - } - - recv_sys_create(); - recv_sys_init(buf_pool_get_curr_size()); - - err = open_or_create_data_files(&create_new_db, -#ifdef UNIV_LOG_ARCHIVE - &min_arch_log_no, &max_arch_log_no, -#endif /* UNIV_LOG_ARCHIVE */ - &flushed_lsn, - &sum_of_new_sizes); - if (err == DB_FAIL) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "The system tablespace must be writable!"); - - return(DB_ERROR); - - } else if (err != DB_SUCCESS) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Could not open or create the system tablespace. If " - "you tried to add new data files to the system " - "tablespace, and it failed here, you should now " - "edit innodb_data_file_path in my.cnf back to what " - "it was, and remove the new ibdata files InnoDB " - "created in this failed attempt. InnoDB only wrote " - "those files full of zeros, but did not yet use " - "them in any way. But be careful: do not remove " - "old data files which contain your precious data!"); - - return(err); - } - -#ifdef UNIV_LOG_ARCHIVE - srv_normalize_path_for_win(srv_arch_dir); -#endif /* UNIV_LOG_ARCHIVE */ - - dirnamelen = strlen(srv_log_group_home_dir); - ut_a(dirnamelen < (sizeof logfilename) - 10 - sizeof "ib_logfile"); - memcpy(logfilename, srv_log_group_home_dir, dirnamelen); - - /* Add a path separator if needed. */ - if (dirnamelen && logfilename[dirnamelen - 1] != SRV_PATH_SEPARATOR) { - logfilename[dirnamelen++] = SRV_PATH_SEPARATOR; - } - - srv_log_file_size_requested = srv_log_file_size; - - if (create_new_db) { - bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL); - ut_a(success); - - flushed_lsn = log_get_lsn(); - - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); - - err = create_log_files(create_new_db, logfilename, dirnamelen, - flushed_lsn, logfile0); - - if (err != DB_SUCCESS) { - return(err); - } - } else { - ut_d(fil_space_get(0)->recv_size = srv_sys_space_size_debug); - - for (i = 0; i < SRV_N_LOG_FILES_MAX; i++) { - os_offset_t size; - os_file_stat_t stat_info; - - sprintf(logfilename + dirnamelen, - "ib_logfile%u", i); - - err = os_file_get_status( - logfilename, &stat_info, false); - - if (err == DB_NOT_FOUND) { - if (i == 0) { - - if (flushed_lsn < (lsn_t) 1000) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Cannot create" - " log files because" - " data files are" - " corrupt or the" - " database was not" - " shut down cleanly" - " after creating" - " the data files."); - return(DB_ERROR); - } - - err = create_log_files( - create_new_db, logfilename, - dirnamelen, flushed_lsn, - logfile0); - - if (err == DB_SUCCESS) { - err = create_log_files_rename( - logfilename, - dirnamelen, - flushed_lsn, - logfile0); - } - - if (err != DB_SUCCESS) { - return(err); - } - - /* Suppress the message about - crash recovery. */ - flushed_lsn = log_get_lsn(); - goto files_checked; - } else if (i < 2 && !IS_XTRABACKUP()) { - /* must have at least 2 log files */ - ib_logf(IB_LOG_LEVEL_ERROR, - "Only one log file found."); - return(err); - } - - /* opened all files */ - break; - } - - if (stat_info.type != OS_FILE_TYPE_FILE) { - break; - } - if (!srv_file_check_mode(logfilename)) { - return(DB_ERROR); - } - - err = open_log_file(&files[i], logfilename, &size); - - if (err != DB_SUCCESS) { - return(err); - } - - ut_a(size != (os_offset_t) -1); - - if (size & ((1 << UNIV_PAGE_SIZE_SHIFT) - 1)) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Log file %s size " - UINT64PF " is not a multiple of" - " innodb_page_size", - logfilename, size); - return(DB_ERROR); - } - - size >>= UNIV_PAGE_SIZE_SHIFT; - - if (i == 0) { - srv_log_file_size = size; - } else if (size != srv_log_file_size) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Log file %s is" - " of different size " UINT64PF " bytes" - " than other log" - " files " UINT64PF " bytes!", - logfilename, - size << UNIV_PAGE_SIZE_SHIFT, - (os_offset_t) srv_log_file_size - << UNIV_PAGE_SIZE_SHIFT); - return(DB_ERROR); - } - } - - srv_n_log_files_found = i; - - /* Create the in-memory file space objects. */ - - sprintf(logfilename + dirnamelen, "ib_logfile%u", 0); - - fil_space_create(logfilename, - SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG, - NULL /* no encryption yet */, - true /* create */); - - ut_a(fil_validate()); - - /* srv_log_file_size is measured in pages; if page size is 16KB, - then we have a limit of 64TB on 32 bit systems */ - ut_a(srv_log_file_size <= ULINT_MAX); - - for (unsigned j = 0; j < i; j++) { - sprintf(logfilename + dirnamelen, "ib_logfile%u", j); - - if (!fil_node_create(logfilename, - (ulint) srv_log_file_size, - SRV_LOG_SPACE_FIRST_ID, FALSE)) { - return(DB_ERROR); - } - } - -#ifdef UNIV_LOG_ARCHIVE - /* Create the file space object for archived logs. Under - MySQL, no archiving ever done. */ - fil_space_create("arch_log_space", SRV_LOG_SPACE_FIRST_ID + 1, - 0, FIL_LOG, NULL /* no encryption yet */, - true /* create */); -#endif /* UNIV_LOG_ARCHIVE */ - log_group_init(0, i, srv_log_file_size * UNIV_PAGE_SIZE, - SRV_LOG_SPACE_FIRST_ID, - SRV_LOG_SPACE_FIRST_ID + 1); - } - -files_checked: - /* Open all log files and data files in the system - tablespace: we keep them open until database - shutdown */ - - fil_open_log_and_system_tablespace_files(); - - err = srv_undo_tablespaces_init( - create_new_db, - FALSE, - srv_undo_tablespaces, - &srv_undo_tablespaces_open); - - /* If the force recovery is set very high then we carry on regardless - of all errors. Basically this is fingers crossed mode. */ - - if (err != DB_SUCCESS - && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) { - - return(err); - } - - /* Initialize objects used by dict stats gathering thread, which - can also be used by recovery if it tries to drop some table */ - if (!srv_read_only_mode) { - dict_stats_thread_init(); - } - - trx_sys_file_format_init(); - - trx_sys_create(); - - if (create_new_db) { - ut_a(!srv_read_only_mode); - init_log_online(); - - mtr_start(&mtr); - - fsp_header_init(0, sum_of_new_sizes, &mtr); - compile_time_assert(TRX_SYS_SPACE == 0); - compile_time_assert(IBUF_SPACE_ID == 0); - - ulint ibuf_root = btr_create( - DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, - 0, 0, DICT_IBUF_ID_MIN, - dict_ind_redundant, &mtr); - - mtr_commit(&mtr); - - if (ibuf_root == FIL_NULL) { - return(srv_init_abort(true, __FILE__, __LINE__, - DB_ERROR)); - } - - ut_ad(ibuf_root == IBUF_TREE_ROOT_PAGE_NO); - - /* To maintain backward compatibility we create only - the first rollback segment before the double write buffer. - All the remaining rollback segments will be created later, - after the double write buffer has been created. */ - trx_sys_create_sys_pages(); - - ib_bh = trx_sys_init_at_db_start(); - n_recovered_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); - - /* The purge system needs to create the purge view and - therefore requires that the trx_sys is inited. */ - - trx_purge_sys_create(srv_n_purge_threads, ib_bh); - - err = dict_create(); - - if (err != DB_SUCCESS) { - return(err); - } - - srv_startup_is_before_trx_rollback_phase = FALSE; - - bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL); - ut_a(success); - - flushed_lsn = log_get_lsn(); - - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); - - /* Stamp the LSN to the data files. */ - err = fil_write_flushed_lsn(flushed_lsn); - - if (err != DB_SUCCESS) { - return(err); - } - - err = create_log_files_rename(logfilename, dirnamelen, - flushed_lsn, logfile0); - - if (err != DB_SUCCESS) { - return(err); - } - } else { - - /* Check if we support the max format that is stamped - on the system tablespace. - Note: We are NOT allowed to make any modifications to - the TRX_SYS_PAGE_NO page before recovery because this - page also contains the max_trx_id etc. important system - variables that are required for recovery. We need to - ensure that we return the system to a state where normal - recovery is guaranteed to work. We do this by - invalidating the buffer cache, this will force the - reread of the page and restoration to its last known - consistent state, this is REQUIRED for the recovery - process to work. */ - err = trx_sys_file_format_max_check( - srv_max_file_format_at_startup); - - if (err != DB_SUCCESS) { - return(err); - } - - /* Invalidate the buffer pool to ensure that we reread - the page that we read above, during recovery. - Note that this is not as heavy weight as it seems. At - this point there will be only ONE page in the buf_LRU - and there must be no page in the buf_flush list. */ - buf_pool_invalidate(); - - /* Start monitor thread early enough so that e.g. crash - recovery failing to find free pages in the buffer pool is - diagnosed. */ - if (!srv_read_only_mode) - { - /* Create the thread which prints InnoDB monitor - info */ - srv_monitor_active = true; - thread_handles[4 + SRV_MAX_N_IO_THREADS] = - os_thread_create( - srv_monitor_thread, - NULL, - thread_ids + 4 + SRV_MAX_N_IO_THREADS); - - thread_started[4 + SRV_MAX_N_IO_THREADS] = true; - } - - /* We always try to do a recovery, even if the database had - been shut down normally: this is the normal startup path */ - - err = recv_recovery_from_checkpoint_start( - LOG_CHECKPOINT, LSN_MAX, - flushed_lsn); - - if (err != DB_SUCCESS) { - return(err); - } - - init_log_online(); - - /* Initialize the change buffer. */ - err = dict_boot(); - - if (err != DB_SUCCESS) { - return(err); - } - - /* This must precede recv_apply_hashed_log_recs(true). */ - ib_bh = trx_sys_init_at_db_start(); - - if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { - /* Apply the hashed log records to the - respective file pages, for the last batch of - recv_group_scan_log_recs(). */ - - recv_apply_hashed_log_recs(true); - - if (recv_sys->found_corrupt_log) { - return (DB_CORRUPTION); - } - - DBUG_PRINT("ib_log", ("apply completed")); - } - - if (!srv_read_only_mode) { - const ulint flags = FSP_FLAGS_PAGE_SSIZE(); - for (ulint id = 0; id <= srv_undo_tablespaces; id++) { - if (fil_space_get(id)) { - fsp_flags_try_adjust(id, flags); - } - } - - if (sum_of_new_sizes > 0) { - /* New data file(s) were added */ - mtr_start(&mtr); - fsp_header_inc_size(0, sum_of_new_sizes, &mtr); - mtr_commit(&mtr); - /* Immediately write the log record about - increased tablespace size to disk, so that it - is durable even if mysqld would crash - quickly */ - log_buffer_flush_to_disk(); - } - } - - const ulint tablespace_size_in_header - = fsp_header_get_tablespace_size(); - -#ifdef UNIV_DEBUG - /* buf_debug_prints = TRUE; */ -#endif /* UNIV_DEBUG */ - ulint sum_of_data_file_sizes = 0; - - for (ulint d = 0; d < srv_n_data_files; d++) { - sum_of_data_file_sizes += srv_data_file_sizes[d]; - } - - /* Compare the system tablespace file size to what is - stored in FSP_SIZE. In open_or_create_data_files() - we already checked that the file sizes match the - innodb_data_file_path specification. */ - if (srv_read_only_mode - || sum_of_data_file_sizes == tablespace_size_in_header) { - /* Do not complain about the size. */ - } else if (!srv_auto_extend_last_data_file - || sum_of_data_file_sizes - < tablespace_size_in_header) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Tablespace size stored in header is " ULINTPF - " pages, but the sum of data file sizes is " - ULINTPF " pages", - tablespace_size_in_header, - sum_of_data_file_sizes); - - if (srv_force_recovery == 0 - && sum_of_data_file_sizes - < tablespace_size_in_header) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Cannot start InnoDB. The tail of" - " the system tablespace is" - " missing. Have you edited" - " innodb_data_file_path in my.cnf" - " in an inappropriate way, removing" - " data files from there?" - " You can set innodb_force_recovery=1" - " in my.cnf to force" - " a startup if you are trying to" - " recover a badly corrupt database."); - - return(DB_ERROR); - } - } - - n_recovered_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); - - /* The purge system needs to create the purge view and - therefore requires that the trx_sys is inited. */ - - trx_purge_sys_create(srv_n_purge_threads, ib_bh); - - /* recv_recovery_from_checkpoint_finish needs trx lists which - are initialized in trx_sys_init_at_db_start(). */ - - recv_recovery_from_checkpoint_finish(); - - if (srv_apply_log_only) { - ut_ad(IS_XTRABACKUP()); - goto skip_processes; - } - - if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) { - /* The following call is necessary for the insert - buffer to work with multiple tablespaces. We must - know the mapping between space id's and .ibd file - names. - - In a crash recovery, we check that the info in data - dictionary is consistent with what we already know - about space id's from the call of - fil_load_single_table_tablespaces(). - - In a normal startup, we create the space objects for - every table in the InnoDB data dictionary that has - an .ibd file. - - We also determine the maximum tablespace id used. */ - dict_check_t dict_check; - - if (recv_needed_recovery) { - dict_check = DICT_CHECK_ALL_LOADED; - } else if (n_recovered_trx) { - dict_check = DICT_CHECK_SOME_LOADED; - } else { - dict_check = DICT_CHECK_NONE_LOADED; - } - - /* Create the SYS_TABLESPACES and SYS_DATAFILES system table */ - err = dict_create_or_check_sys_tablespace(); - if (err != DB_SUCCESS) { - return(err); - } - - sys_datafiles_created = true; - - /* This function assumes that SYS_DATAFILES exists */ - dict_check_tablespaces_and_store_max_id(dict_check); - } - - if (IS_XTRABACKUP() - && !srv_backup_mode - && srv_read_only_mode - && srv_log_file_size_requested != srv_log_file_size) { - - ib_logf(IB_LOG_LEVEL_WARN, - "Log files size mismatch, ignored in readonly mode"); - srv_log_file_size_requested = srv_log_file_size; - } - - - if (!srv_force_recovery - && !recv_sys->found_corrupt_log - && (srv_log_file_size_requested != srv_log_file_size - || srv_n_log_files_found != srv_n_log_files)) { - /* Prepare to replace the redo log files. */ - - if (srv_read_only_mode) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Cannot resize log files " - "in read-only mode."); - return(DB_READ_ONLY); - } - - /* Clean the buffer pool. */ - bool success = buf_flush_list( - ULINT_MAX, LSN_MAX, NULL); - ut_a(success); - - DBUG_EXECUTE_IF("innodb_log_abort_1", - return(DB_ERROR);); - - flushed_lsn = log_get_lsn(); - - ib_logf(IB_LOG_LEVEL_WARN, - "Resizing redo log from %u*%u to %u*%u pages" - ", LSN=" LSN_PF, - (unsigned) i, - (unsigned) srv_log_file_size, - (unsigned) srv_n_log_files, - (unsigned) srv_log_file_size_requested, - flushed_lsn); - - buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST); - - /* Flush the old log files. */ - log_buffer_flush_to_disk(); - /* If innodb_flush_method=O_DSYNC, - we need to explicitly flush the log buffers. */ - fil_flush(SRV_LOG_SPACE_FIRST_ID); - - ut_ad(flushed_lsn == log_get_lsn()); - - /* Prohibit redo log writes from any other - threads until creating a log checkpoint at the - end of create_log_files(). */ - ut_d(recv_no_log_write = TRUE); - ut_ad(!buf_pool_check_no_pending_io()); - - DBUG_EXECUTE_IF("innodb_log_abort_3", - return(DB_ERROR);); - - /* Stamp the LSN to the data files. */ - err = fil_write_flushed_lsn(flushed_lsn); - - DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;); - - if (err != DB_SUCCESS) { - return(err); - } - - /* Close and free the redo log files, so that - we can replace them. */ - fil_close_log_files(true); - - DBUG_EXECUTE_IF("innodb_log_abort_5", - return(DB_ERROR);); - - /* Free the old log file space. */ - log_group_close_all(); - - ib_logf(IB_LOG_LEVEL_WARN, - "Starting to delete and rewrite log files."); - - srv_log_file_size = srv_log_file_size_requested; - - err = create_log_files(create_new_db, logfilename, - dirnamelen, flushed_lsn, - logfile0); - - if (err != DB_SUCCESS) { - return(err); - } - - err = create_log_files_rename(logfilename, dirnamelen, - log_get_lsn(), logfile0); - - if (err != DB_SUCCESS) { - return(err); - } - } - - recv_recovery_rollback_active(); - srv_startup_is_before_trx_rollback_phase = FALSE; - - /* It is possible that file_format tag has never - been set. In this case we initialize it to minimum - value. Important to note that we can do it ONLY after - we have finished the recovery process so that the - image of TRX_SYS_PAGE_NO is not stale. */ - trx_sys_file_format_tag_init(); - } - - ut_ad(err == DB_SUCCESS); - ut_a(sum_of_new_sizes != ULINT_UNDEFINED); - -#ifdef UNIV_LOG_ARCHIVE - if (!srv_read_only_mode) { - if (!srv_log_archive_on) { - ut_a(DB_SUCCESS == log_archive_noarchivelog()); - } else { - bool start_archive; - - mutex_enter(&(log_sys->mutex)); - - start_archive = false; - - if (log_sys->archiving_state == LOG_ARCH_OFF) { - start_archive = true; - } - - mutex_exit(&(log_sys->mutex)); - - if (start_archive) { - ut_a(DB_SUCCESS == log_archive_archivelog()); - } - } - } -#endif /* UNIV_LOG_ARCHIVE */ - - /* fprintf(stderr, "Max allowed record size %lu\n", - page_get_free_space_of_empty() / 2); */ - - if (!buf_dblwr_create()) { - return(srv_init_abort(create_new_db, __FILE__, __LINE__, - DB_ERROR)); - } - - /* Here the double write buffer has already been created and so - any new rollback segments will be allocated after the double - write buffer. The default segment should already exist. - We create the new segments only if it's a new database or - the database was shutdown cleanly. */ - - /* Note: When creating the extra rollback segments during an upgrade - we violate the latching order, even if the change buffer is empty. - We make an exception in sync0sync.cc and check srv_is_being_started - for that violation. It cannot create a deadlock because we are still - running in single threaded mode essentially. Only the IO threads - should be running at this stage. */ - - ut_a(srv_undo_logs > 0); - ut_a(srv_undo_logs <= TRX_SYS_N_RSEGS); - - /* The number of rsegs that exist in InnoDB is given by status - variable srv_available_undo_logs. The number of rsegs to use can - be set using the dynamic global variable srv_undo_logs. */ - - srv_available_undo_logs = trx_sys_create_rsegs( - srv_undo_tablespaces, srv_undo_logs); - - if (srv_available_undo_logs == ULINT_UNDEFINED) { - /* Can only happen if server is read only. */ - ut_a(srv_read_only_mode); - srv_undo_logs = ULONG_UNDEFINED; - } else if (srv_available_undo_logs < srv_undo_logs) { - /* Should due to out of file space. */ - return (srv_init_abort(create_new_db, __FILE__, __LINE__, DB_ERROR)); - } - - if (!srv_read_only_mode) { - /* Create the thread which watches the timeouts - for lock waits */ - thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create( - lock_wait_timeout_thread, - NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); - thread_started[2 + SRV_MAX_N_IO_THREADS] = true; - lock_sys->timeout_thread_active = true; - - /* Create the thread which warns of long semaphore waits */ - srv_error_monitor_active = true; - thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create( - srv_error_monitor_thread, - NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); - thread_started[3 + SRV_MAX_N_IO_THREADS] = true; - - /* Create the thread which prints InnoDB monitor info */ - if (!thread_started[4 + SRV_MAX_N_IO_THREADS]) { - /* srv_monitor_thread not yet started */ - srv_monitor_active = true; - thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create( - srv_monitor_thread, - NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); - thread_started[4 + SRV_MAX_N_IO_THREADS] = true; - } - } - - /* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */ - err = dict_create_or_check_foreign_constraint_tables(); - if (err != DB_SUCCESS) { - return(err); - } - - /* Create the SYS_TABLESPACES and SYS_DATAFILES system tables if we - have not done that already on crash recovery. */ - if (sys_datafiles_created == false) { - err = dict_create_or_check_sys_tablespace(); - if (err != DB_SUCCESS) { - return(err); - } - } - - srv_is_being_started = FALSE; - - ut_a(trx_purge_state() == PURGE_STATE_INIT); - - /* Create the master thread which does purge and other utility - operations */ - - if (!srv_read_only_mode) { - - thread_handles[1 + SRV_MAX_N_IO_THREADS] = os_thread_create( - srv_master_thread, - NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS)); - thread_started[1 + SRV_MAX_N_IO_THREADS] = true; - - srv_undo_sources = true; - /* Create the dict stats gathering thread */ - srv_dict_stats_thread_active = true; - dict_stats_thread_handle = os_thread_create( - dict_stats_thread, NULL, NULL); - dict_stats_thread_started = true; - - /* Create the thread that will optimize the FTS sub-system. */ - fts_optimize_init(); - } - - if (!srv_read_only_mode - && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) { - - thread_handles[6 + SRV_MAX_N_IO_THREADS] = os_thread_create( - srv_purge_coordinator_thread, - NULL, thread_ids + 6 + SRV_MAX_N_IO_THREADS); - - thread_started[6 + SRV_MAX_N_IO_THREADS] = true; - - ut_a(UT_ARR_SIZE(thread_ids) - > 6 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS); - - /* We've already created the purge coordinator thread above. */ - for (i = 1; i < srv_n_purge_threads; ++i) { - thread_handles[6 + i + SRV_MAX_N_IO_THREADS] = os_thread_create( - srv_worker_thread, NULL, - thread_ids + 6 + i + SRV_MAX_N_IO_THREADS); - thread_started[6 + i + SRV_MAX_N_IO_THREADS] = true; - } - - srv_start_wait_for_purge_to_start(); - - } else { - purge_sys->state = PURGE_STATE_DISABLED; - } - - if (!srv_read_only_mode) { - - if (srv_use_mtflush) { - /* Start multi-threaded flush threads */ - mtflush_ctx = buf_mtflu_handler_init( - srv_mtflush_threads, - srv_buf_pool_instances); - - /* Set up the thread ids */ - buf_mtflu_set_thread_ids( - srv_mtflush_threads, - mtflush_ctx, - (thread_ids + 6 + SRV_MAX_N_PURGE_THREADS)); - } - - - buf_page_cleaner_is_active = true; - buf_flush_page_cleaner_thread_handle = os_thread_create( - buf_flush_page_cleaner_thread, NULL, NULL); - buf_flush_page_cleaner_thread_started = true; - - buf_lru_manager_is_active = true; - buf_flush_lru_manager_thread_handle = os_thread_create( - buf_flush_lru_manager_thread, NULL, NULL); - buf_flush_lru_manager_thread_started = true; - } - - if (!srv_file_per_table && srv_pass_corrupt_table) { - fprintf(stderr, "InnoDB: Warning:" - " The option innodb_file_per_table is disabled," - " so using the option innodb_pass_corrupt_table doesn't make sense.\n"); - } - - if (srv_print_verbose_log) { - ib_logf(IB_LOG_LEVEL_INFO, - " Percona XtraDB (http://www.percona.com) %s started; " - "log sequence number " LSN_PF "", - INNODB_VERSION_STR, srv_start_lsn); - } - - if (srv_force_recovery > 0) { - ib_logf(IB_LOG_LEVEL_INFO, - "!!! innodb_force_recovery is set to %lu !!!", - (ulong) srv_force_recovery); - } - - if (!srv_read_only_mode) { - /* - Create a checkpoint before logging anything new, so that - the current encryption key in use is definitely logged - before any log blocks encrypted with that key. - */ - log_make_checkpoint_at(LSN_MAX, TRUE); - } - - if (srv_force_recovery == 0) { - /* In the insert buffer we may have even bigger tablespace - id's, because we may have dropped those tablespaces, but - insert buffer merge has not had time to clean the records from - the ibuf tree. */ - - ibuf_update_max_tablespace_id(); - } - - if (!srv_read_only_mode) { -#ifdef WITH_WSREP - /* - Create the dump/load thread only when not running with - --wsrep-recover. - */ - if (!wsrep_recovery) { -#endif /* WITH_WSREP */ - /* Create the buffer pool dump/load thread */ - srv_buf_dump_thread_active = true; - buf_dump_thread_handle= - os_thread_create(buf_dump_thread, NULL, NULL); - - buf_dump_thread_started = true; -#ifdef WITH_WSREP - } else { - ib_logf(IB_LOG_LEVEL_WARN, - "Skipping buffer pool dump/restore during " - "wsrep recovery."); - } -#endif /* WITH_WSREP */ - /* Create thread(s) that handles key rotation */ - fil_system_enter(); - btr_scrub_init(); - fil_crypt_threads_init(); - fil_system_exit(); - - /* Initialize online defragmentation. */ - btr_defragment_init(); - btr_defragment_thread_active = true; - os_thread_create(btr_defragment_thread, NULL, NULL); - } - -skip_processes: - srv_was_started = TRUE; - - return(DB_SUCCESS); -} - -#if 0 -/******************************************************************** -Sync all FTS cache before shutdown */ -static -void -srv_fts_close(void) -/*===============*/ -{ - dict_table_t* table; - - for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); - table; table = UT_LIST_GET_NEXT(table_LRU, table)) { - fts_t* fts = table->fts; - - if (fts != NULL) { - fts_sync_table(table); - } - } - - for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU); - table; table = UT_LIST_GET_NEXT(table_LRU, table)) { - fts_t* fts = table->fts; - - if (fts != NULL) { - fts_sync_table(table); - } - } -} -#endif - -/** Shut down InnoDB. */ -UNIV_INTERN -void -innodb_shutdown() -{ - ulint i; - - if (!srv_was_started) { - if (srv_is_being_started) { - ib_logf(IB_LOG_LEVEL_WARN, - "Shutting down an improperly started, " - "or created database!"); - } - } - - if (srv_undo_sources) { - ut_ad(!srv_read_only_mode); - /* Shutdown the FTS optimize sub system. */ - fts_optimize_start_shutdown(); - - fts_optimize_end(); - dict_stats_shutdown(); - while (row_get_background_drop_list_len_low()) { - srv_wake_master_thread(); - os_thread_yield(); - } - srv_undo_sources = false; - } - - /* 1. Flush the buffer pool to disk, write the current lsn to - the tablespace header(s), and copy all log data to archive. - The step 1 is the real InnoDB shutdown. The remaining steps 2 - ... - just free data structures after the shutdown. */ - - logs_empty_and_mark_files_at_shutdown(); - - if (srv_conc_get_active_threads() != 0) { - ib_logf(IB_LOG_LEVEL_WARN, - "Query counter shows %ld queries still " - "inside InnoDB at shutdown", - srv_conc_get_active_threads()); - } - - /* 2. Make all threads created by InnoDB to exit */ - - srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS; - - /* All threads end up waiting for certain events. Put those events - to the signaled state. Then the threads will exit themselves after - os_event_wait(). */ - - for (i = 0; i < 1000; i++) { - /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM - HERE OR EARLIER */ - - if (!srv_read_only_mode) { - /* a. Let the lock timeout thread exit */ - os_event_set(lock_sys->timeout_event); - - /* b. srv error monitor thread exits automatically, - no need to do anything here */ - - /* c. We wake the master thread so that it exits */ - srv_wake_master_thread(); - - /* d. Wakeup purge threads. */ - srv_purge_wakeup(); - } - - /* e. Exit the i/o threads */ - - os_aio_wake_all_threads_at_shutdown(); - - /* f. dict_stats_thread is signaled from - logs_empty_and_mark_files_at_shutdown() and should have - already quit or is quitting right now. */ - - if (srv_use_mtflush) { - /* g. Exit the multi threaded flush threads */ - - buf_mtflu_io_thread_exit(); - } - - os_rmb; - if (os_thread_count == 0) { - /* All the threads have exited or are just exiting; - NOTE that the threads may not have completed their - exit yet. Should we use pthread_join() to make sure - they have exited? If we did, we would have to - remove the pthread_detach() from - os_thread_exit(). Now we just sleep 0.1 - seconds and hope that is enough! */ - - os_thread_sleep(100000); - - break; - } - - os_thread_sleep(100000); - } - - if (i == 1000) { - ib_logf(IB_LOG_LEVEL_WARN, - "%lu threads created by InnoDB" - " had not exited at shutdown!", - (ulong) os_thread_count); - } - - if (srv_monitor_file) { - fclose(srv_monitor_file); - srv_monitor_file = 0; - if (srv_monitor_file_name) { - unlink(srv_monitor_file_name); - mem_free(srv_monitor_file_name); - } - } - - if (srv_dict_tmpfile) { - fclose(srv_dict_tmpfile); - srv_dict_tmpfile = 0; - } - - if (srv_misc_tmpfile) { - fclose(srv_misc_tmpfile); - srv_misc_tmpfile = 0; - } - - if (!srv_read_only_mode && !srv_apply_log_only) { - dict_stats_thread_deinit(); - fil_crypt_threads_cleanup(); - btr_scrub_cleanup(); - btr_defragment_shutdown(); - } - -#ifdef __WIN__ - /* MDEV-361: ha_innodb.dll leaks handles on Windows - MDEV-7403: should not pass recv_writer_thread_handle to - CloseHandle(). - - On Windows we should call CloseHandle() for all - open thread handles. */ - if (os_thread_count == 0) { - for (i = 0; i < SRV_MAX_N_IO_THREADS + 6 + 32; ++i) { - if (thread_started[i]) { - CloseHandle(thread_handles[i]); - } - } - - if (buf_flush_page_cleaner_thread_started) { - CloseHandle(buf_flush_page_cleaner_thread_handle); - } - - if (buf_dump_thread_started) { - CloseHandle(buf_dump_thread_handle); - } - - if (dict_stats_thread_started) { - CloseHandle(dict_stats_thread_handle); - } - - if (buf_flush_lru_manager_thread_started) { - CloseHandle(buf_flush_lru_manager_thread_handle); - } - - if (srv_redo_log_follow_thread_started) { - CloseHandle(srv_redo_log_follow_thread_handle); - } - } -#endif /* __WIN __ */ - - /* This must be disabled before closing the buffer pool - and closing the data dictionary. */ - btr_search_disable(); - - ibuf_close(); - log_online_shutdown(); - log_shutdown(); - trx_sys_file_format_close(); - trx_sys_close(); - lock_sys_close(); - - /* We don't create these mutexes in RO mode because we don't create - the temp files that the cover. */ - if (!srv_read_only_mode) { - mutex_free(&srv_monitor_file_mutex); - mutex_free(&srv_dict_tmpfile_mutex); - mutex_free(&srv_misc_tmpfile_mutex); - } - - dict_close(); - btr_search_sys_free(); - - /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside - them */ - os_aio_free(); - que_close(); - row_mysql_close(); - srv_mon_free(); - srv_free(); - fil_close(); - - /* 4. Free all allocated memory */ - - pars_lexer_close(); - log_mem_free(); - buf_pool_free(srv_buf_pool_instances); - mem_close(); - sync_close(); - - /* ut_free_all_mem() frees all allocated memory not freed yet - in shutdown, and it will also free the ut_list_mutex, so it - should be the last one for all operation */ - ut_free_all_mem(); - - os_rmb; - if (os_thread_count != 0 - || os_event_count != 0 - || os_mutex_count != 0 - || os_fast_mutex_count != 0) { - ib_logf(IB_LOG_LEVEL_WARN, - "Some resources were not cleaned up in shutdown: " - "threads %lu, events %lu, os_mutexes %lu, " - "os_fast_mutexes %lu", - (ulong) os_thread_count, (ulong) os_event_count, - (ulong) os_mutex_count, (ulong) os_fast_mutex_count); - } - - if (dict_foreign_err_file) { - fclose(dict_foreign_err_file); - } - - if (srv_print_verbose_log) { - ib_logf(IB_LOG_LEVEL_INFO, - "Shutdown completed; log sequence number " LSN_PF "", - srv_shutdown_lsn); - } - - srv_was_started = FALSE; - srv_start_has_been_called = FALSE; - /* reset io_tid_i, in case current process does second innodb start (xtrabackup might do that).*/ - io_tid_i = 0; -} -#endif /* !UNIV_HOTBACKUP */ - -/*****************************************************************//** -Get the meta-data filename from the table name. */ -UNIV_INTERN -void -srv_get_meta_data_filename( -/*=======================*/ - dict_table_t* table, /*!< in: table */ - char* filename, /*!< out: filename */ - ulint max_len) /*!< in: filename max length */ -{ - ulint len; - char* path; - char* suffix; - static const ulint suffix_len = strlen(".cfg"); - - if (DICT_TF_HAS_DATA_DIR(table->flags)) { - dict_get_and_save_data_dir_path(table, false); - ut_a(table->data_dir_path); - - path = os_file_make_remote_pathname( - table->data_dir_path, table->name, "cfg"); - } else { - path = fil_make_ibd_name(table->name, false); - } - - ut_a(path); - len = ut_strlen(path); - ut_a(max_len >= len); - - suffix = path + (len - suffix_len); - if (strncmp(suffix, ".cfg", suffix_len) == 0) { - strcpy(filename, path); - } else { - ut_ad(!strcmp(suffix, ".ibd")); - memcpy(filename, path, len - suffix_len); - suffix = filename + (len - suffix_len); - strcpy(suffix, ".cfg"); - } - - mem_free(path); - - srv_normalize_path_for_win(filename); -} |