summaryrefslogtreecommitdiff
path: root/storage/innobase/srv/srv0start.cc
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2013-03-26 00:03:13 +0200
committerMichael Widenius <monty@askmonty.org>2013-03-26 00:03:13 +0200
commit068c61978e3a81836d52b8caf11e044290159ad1 (patch)
tree2cbca861ab2cebe3bd99379ca9668bb483ca0d2a /storage/innobase/srv/srv0start.cc
parent35bc8f9f4353b64da215e52ff6f1612a8ce66f43 (diff)
downloadmariadb-git-068c61978e3a81836d52b8caf11e044290159ad1.tar.gz
Temporary commit of 10.0-merge
Diffstat (limited to 'storage/innobase/srv/srv0start.cc')
-rw-r--r--storage/innobase/srv/srv0start.cc1765
1 files changed, 1071 insertions, 694 deletions
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 9d1600cff23..efe9f094c0d 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -71,6 +71,7 @@ Created 2/16/1996 Heikki Tuuri
# include "buf0rea.h"
# include "dict0boot.h"
# include "dict0load.h"
+# include "dict0stats_bg.h"
# include "que0que.h"
# include "usr0sess.h"
# include "lock0lock.h"
@@ -87,9 +88,9 @@ Created 2/16/1996 Heikki Tuuri
# include "row0row.h"
# include "row0mysql.h"
# include "btr0pcur.h"
-# include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
-# include "zlib.h" /* for ZLIB_VERSION */
-# include "buf0dblwr.h"
+# include "os0sync.h"
+# include "zlib.h"
+# include "ut0crc32.h"
/** Log sequence number immediately after startup */
UNIV_INTERN lsn_t srv_start_lsn;
@@ -188,6 +189,63 @@ srv_parse_megabytes(
}
/*********************************************************************//**
+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",
+ srv_read_only_mode
+ ? "read-write" : "read",
+ name);
+
+ 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 */
@@ -376,79 +434,6 @@ srv_parse_data_file_paths_and_sizes(
}
/*********************************************************************//**
-Reads log group home directories from a character string given in
-the .cnf file.
-@return TRUE if ok, FALSE on parse error */
-UNIV_INTERN
-ibool
-srv_parse_log_group_home_dirs(
-/*==========================*/
- char* str) /*!< in/out: character string */
-{
- char* input_str;
- char* path;
- ulint i = 0;
-
- srv_log_group_home_dirs = NULL;
-
- input_str = str;
-
- /* First calculate the number of directories and check syntax:
- path;path;... */
-
- while (*str != '\0') {
- path = str;
-
- while (*str != ';' && *str != '\0') {
- str++;
- }
-
- i++;
-
- if (*str == ';') {
- str++;
- } else if (*str != '\0') {
-
- return(FALSE);
- }
- }
-
- if (i != 1) {
- /* If innodb_log_group_home_dir was defined it must
- contain exactly one path definition under current MySQL */
-
- return(FALSE);
- }
-
- srv_log_group_home_dirs = static_cast<char**>(
- malloc(i * sizeof *srv_log_group_home_dirs));
-
- /* Then store the actual values to our array */
-
- str = input_str;
- i = 0;
-
- while (*str != '\0') {
- path = str;
-
- while (*str != ';' && *str != '\0') {
- str++;
- }
-
- if (*str == ';') {
- *str = '\0';
- str++;
- }
-
- srv_log_group_home_dirs[i] = path;
-
- i++;
- }
-
- return(TRUE);
-}
-
-/*********************************************************************//**
Frees the memory allocated by srv_parse_data_file_paths_and_sizes()
and srv_parse_log_group_home_dirs(). */
UNIV_INTERN
@@ -462,8 +447,6 @@ srv_free_paths_and_sizes(void)
srv_data_file_sizes = NULL;
free(srv_data_file_is_raw_partition);
srv_data_file_is_raw_partition = NULL;
- free(srv_log_group_home_dirs);
- srv_log_group_home_dirs = NULL;
}
#ifndef UNIV_HOTBACKUP
@@ -526,175 +509,230 @@ srv_normalize_path_for_win(
#ifndef UNIV_HOTBACKUP
/*********************************************************************//**
-Creates or opens the log files and closes them.
+Creates a log file.
@return DB_SUCCESS or error code */
-static
-ulint
-open_or_create_log_file(
-/*====================*/
- ibool create_new_db, /*!< in: TRUE if we should create a
- new database */
- ibool* log_file_created, /*!< out: TRUE if new log file
- created */
- ibool log_file_has_been_opened,/*!< in: TRUE if a log file has been
- opened before: then it is an error
- to try to create another log file */
- ulint k, /*!< in: log group number */
- ulint i) /*!< in: log file number in group */
+static __attribute__((nonnull, warn_unused_result))
+dberr_t
+create_log_file(
+/*============*/
+ os_file_t* file, /*!< out: file handle */
+ const char* name) /*!< in: log file name */
{
ibool ret;
- os_offset_t size;
- char name[10000];
- ulint dirnamelen;
- UT_NOT_USED(create_new_db);
+ *file = os_file_create(
+ innodb_file_log_key, name,
+ OS_FILE_CREATE, OS_FILE_NORMAL, OS_LOG_FILE, &ret);
- *log_file_created = FALSE;
+ 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));
- srv_normalize_path_for_win(srv_log_group_home_dirs[k]);
+ 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, "Error in creating %s", name);
+ return(DB_ERROR);
+ }
- dirnamelen = strlen(srv_log_group_home_dirs[k]);
- ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile");
- memcpy(name, srv_log_group_home_dirs[k], dirnamelen);
+ ret = os_file_close(*file);
+ ut_a(ret);
- /* Add a path separator if needed. */
- if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
- name[dirnamelen++] = SRV_PATH_SEPARATOR;
+ return(DB_SUCCESS);
+}
+
+/** Initial number of the first redo log file */
+#define INIT_LOG_FILE0 (SRV_N_LOG_FILES_MAX + 1)
+
+#ifdef DBUG_OFF
+# define RECOVERY_CRASH(x) do {} while(0)
+#else
+# define RECOVERY_CRASH(x) do { \
+ if (srv_force_recovery_crash == x) { \
+ fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \
+ srv_force_recovery_crash); \
+ fflush(stderr); \
+ exit(3); \
+ } \
+} while (0)
+#endif
+
+/*********************************************************************//**
+Creates all log files.
+@return DB_SUCCESS or error code */
+static
+dberr_t
+create_log_files(
+/*=============*/
+ 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);
}
- sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i);
+ /* Remove any old log files. */
+ for (unsigned i = 0; i <= INIT_LOG_FILE0; i++) {
+ sprintf(logfilename + dirnamelen, "ib_logfile%u", i);
- files[i] = os_file_create(innodb_file_log_key, name,
- OS_FILE_CREATE, OS_FILE_NORMAL,
- OS_LOG_FILE, &ret);
- 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
+ /* 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
- ) {
- fprintf(stderr,
- "InnoDB: Error in creating"
- " or opening %s\n", name);
+ /* 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. */
+ RECOVERY_CRASH(6);
+ }
- return(DB_ERROR);
- }
+ ut_ad(!buf_pool_check_no_pending_io());
- files[i] = os_file_create(innodb_file_log_key, name,
- OS_FILE_OPEN, OS_FILE_AIO,
- OS_LOG_FILE, &ret);
- if (!ret) {
- fprintf(stderr,
- "InnoDB: Error in opening %s\n", name);
+ RECOVERY_CRASH(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);
}
+ }
- size = os_file_get_size(files[i]);
- ut_a(size != (os_offset_t) -1);
+ RECOVERY_CRASH(8);
- if (UNIV_UNLIKELY(size != (os_offset_t) srv_log_file_size
- << UNIV_PAGE_SIZE_SHIFT)) {
+ /* 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);
- fprintf(stderr,
- "InnoDB: Error: log file %s is"
- " of different size "UINT64PF" bytes\n"
- "InnoDB: than specified in the .cnf"
- " file "UINT64PF" bytes!\n",
- name, size,
- (os_offset_t) srv_log_file_size
- << UNIV_PAGE_SIZE_SHIFT);
+ fil_space_create(
+ logfilename, SRV_LOG_SPACE_FIRST_ID,
+ fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
+ FIL_LOG);
+ ut_a(fil_validate());
- return(DB_ERROR);
+ 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;
}
- } else {
- *log_file_created = TRUE;
+ }
- ut_print_timestamp(stderr);
+ 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);
- fprintf(stderr,
- " InnoDB: Log file %s did not exist:"
- " new to be created\n",
- name);
- if (log_file_has_been_opened) {
+ fil_open_log_and_system_tablespace_files();
- return(DB_ERROR);
- }
+ /* Create a log checkpoint. */
+ mutex_enter(&log_sys->mutex);
+ ut_d(recv_no_log_write = FALSE);
+ recv_reset_logs(lsn);
+ mutex_exit(&log_sys->mutex);
- fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n",
- name, (ulong) srv_log_file_size
- >> (20 - UNIV_PAGE_SIZE_SHIFT));
+ return(DB_SUCCESS);
+}
- fprintf(stderr,
- "InnoDB: Database physically writes the file"
- " full: wait...\n");
+/*********************************************************************//**
+Renames the first log file. */
+static
+void
+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);
+ /* Close the log files, so that we can rename
+ the first one. */
+ fil_close_log_files(false);
- ret = os_file_set_size(name, files[i],
- (os_offset_t) srv_log_file_size
- << UNIV_PAGE_SIZE_SHIFT);
- if (!ret) {
- fprintf(stderr,
- "InnoDB: Error in creating %s:"
- " probably out of disk space\n",
- name);
+ /* Rename the first log file, now that a log
+ checkpoint has been created. */
+ sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
- return(DB_ERROR);
- }
- }
+ RECOVERY_CRASH(9);
- ret = os_file_close(files[i]);
- ut_a(ret);
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Renaming log file %s to %s", logfile0, logfilename);
- if (i == 0) {
- /* Create in memory the file space object
- which is for this log group */
+ mutex_enter(&log_sys->mutex);
+ ut_ad(strlen(logfile0) == 2 + strlen(logfilename));
+ ibool success = os_file_rename(
+ innodb_file_log_key, logfile0, logfilename);
+ ut_a(success);
- fil_space_create(name,
- 2 * k + SRV_LOG_SPACE_FIRST_ID,
- fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
- FIL_LOG);
- }
+ RECOVERY_CRASH(10);
- ut_a(fil_validate());
+ /* Replace the first file with ib_logfile0. */
+ strcpy(logfile0, logfilename);
+ mutex_exit(&log_sys->mutex);
- /* 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);
+ fil_open_log_and_system_tablespace_files();
- fil_node_create(name, (ulint) srv_log_file_size,
- 2 * k + SRV_LOG_SPACE_FIRST_ID, FALSE);
-#ifdef UNIV_LOG_ARCHIVE
- /* If this is the first log group, create the file space object
- for archived logs.
- Under MySQL, no archiving ever done. */
+ ib_logf(IB_LOG_LEVEL_WARN, "New log files created, LSN=" LSN_PF, lsn);
+}
- if (k == 0 && i == 0) {
- arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
+/*********************************************************************//**
+Opens a log file.
+@return DB_SUCCESS or error code */
+static __attribute__((nonnull, warn_unused_result))
+dberr_t
+open_log_file(
+/*==========*/
+ os_file_t* file, /*!< out: file handle */
+ const char* name, /*!< in: log file name */
+ os_offset_t* size) /*!< out: file size */
+{
+ ibool ret;
- fil_space_create("arch_log_space", arch_space_id, 0, FIL_LOG);
- } else {
- arch_space_id = ULINT_UNDEFINED;
- }
-#endif /* UNIV_LOG_ARCHIVE */
- if (i == 0) {
- log_group_init(k, srv_n_log_files,
- srv_log_file_size * UNIV_PAGE_SIZE,
- 2 * k + SRV_LOG_SPACE_FIRST_ID,
- SRV_LOG_SPACE_FIRST_ID + 1); /* dummy arch
- space id */
+ *file = os_file_create(innodb_file_log_key, name,
+ OS_FILE_OPEN, OS_FILE_AIO,
+ OS_LOG_FILE, &ret);
+ 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.
@return DB_SUCCESS or error code */
-static
-ulint
+static __attribute__((nonnull, warn_unused_result))
+dberr_t
open_or_create_data_files(
/*======================*/
ibool* create_new_db, /*!< out: TRUE if new database should be
@@ -718,13 +756,16 @@ open_or_create_data_files(
ibool one_created = FALSE;
os_offset_t size;
ulint flags;
+ ulint space;
ulint rounded_size_pages;
char name[10000];
if (srv_n_data_files >= 1000) {
- fprintf(stderr, "InnoDB: can only have < 1000 data files\n"
- "InnoDB: you have defined %lu\n",
- (ulong) srv_n_data_files);
+
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Can only have < 1000 data files, you have "
+ "defined %lu", (ulong) srv_n_data_files);
+
return(DB_ERROR);
}
@@ -742,7 +783,9 @@ open_or_create_data_files(
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;
@@ -750,46 +793,67 @@ open_or_create_data_files(
strcpy(name + dirnamelen, srv_data_file_names[i]);
- if (srv_data_file_is_raw_partition[i] == 0) {
+ /* 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);
+ files[i] = os_file_create(
+ innodb_file_data_key, name, OS_FILE_CREATE,
+ OS_FILE_NORMAL, OS_DATA_FILE, &ret);
+
+ if (srv_read_only_mode) {
+
+ if (ret) {
+ goto size_check;
+ }
- if (ret == FALSE && os_file_get_last_error(FALSE)
- != OS_FILE_ALREADY_EXISTS
+ 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
+ /* 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 */
) {
- fprintf(stderr,
- "InnoDB: Error in creating"
- " or opening %s\n",
+ 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);
+ files[i] = os_file_create(
+ innodb_file_data_key, name, OS_FILE_OPEN_RAW,
+ OS_FILE_NORMAL, OS_DATA_FILE, &ret);
+
if (!ret) {
- fprintf(stderr,
- "InnoDB: Error in opening %s\n", name);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Error in opening %s", name);
return(DB_ERROR);
}
@@ -805,17 +869,15 @@ open_or_create_data_files(
/* We open the data file */
if (one_created) {
- fprintf(stderr,
- "InnoDB: Error: data files can only"
- " be added at the end\n");
- fprintf(stderr,
- "InnoDB: of a tablespace, but"
- " data file %s existed beforehand.\n",
+ 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,
@@ -833,9 +895,11 @@ open_or_create_data_files(
}
if (!ret) {
- fprintf(stderr,
- "InnoDB: Error in opening %s\n", name);
- os_file_get_last_error(TRUE);
+
+ os_file_get_last_error(true);
+
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Can't open '%s'", name);
return(DB_ERROR);
}
@@ -845,6 +909,7 @@ open_or_create_data_files(
goto skip_size_check;
}
+size_check:
size = os_file_get_size(files[i]);
ut_a(size != (os_offset_t) -1);
/* Round size downward to megabytes */
@@ -860,16 +925,16 @@ open_or_create_data_files(
&& srv_last_file_size_max
< rounded_size_pages)) {
- fprintf(stderr,
- "InnoDB: Error: auto-extending"
- " data file %s is"
- " of a different size\n"
- "InnoDB: %lu pages (rounded"
- " down to MB) than specified"
- " in the .cnf file:\n"
- "InnoDB: initial %lu pages,"
- " max %lu (relevant if"
- " non-zero) pages!\n",
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "auto-extending "
+ "data file %s is "
+ "of a different size "
+ "%lu pages (rounded "
+ "down to MB) than specified "
+ "in the .cnf file: "
+ "initial %lu pages, "
+ "max %lu (relevant if "
+ "non-zero) pages!",
name,
(ulong) rounded_size_pages,
(ulong) srv_data_file_sizes[i],
@@ -884,13 +949,11 @@ open_or_create_data_files(
if (rounded_size_pages != srv_data_file_sizes[i]) {
- fprintf(stderr,
- "InnoDB: Error: data file %s"
- " is of a different size\n"
- "InnoDB: %lu pages"
- " (rounded down to MB)\n"
- "InnoDB: than specified"
- " in the .cnf file %lu pages!\n",
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Data file %s is of a different "
+ "size %lu pages (rounded down to MB) "
+ "than specified in the .cnf file "
+ "%lu pages!",
name,
(ulong) rounded_size_pages,
(ulong) srv_data_file_sizes[i]);
@@ -899,63 +962,65 @@ open_or_create_data_files(
}
skip_size_check:
fil_read_first_page(
- files[i], one_opened, &flags,
+ files[i], one_opened, &flags, &space,
#ifdef UNIV_LOG_ARCHIVE
min_arch_log_no, max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
min_flushed_lsn, max_flushed_lsn);
+ /* 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)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: data file %s"
- " uses page size %lu,\n",
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Data file \"%s\" uses page size %lu,"
+ "but the start-up parameter "
+ "is --innodb-page-size=%lu",
name,
- fsp_flags_get_page_size(flags));
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: but the start-up parameter"
- " is innodb-page-size=%lu\n",
+ fsp_flags_get_page_size(flags),
UNIV_PAGE_SIZE);
return(DB_ERROR);
}
one_opened = TRUE;
- } else {
+ } else if (!srv_read_only_mode) {
/* We created the data file and now write it full of
zeros */
one_created = TRUE;
if (i > 0) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Data file %s did not"
- " exist: new to be created\n",
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Data file %s did not"
+ " exist: new to be created",
name);
} else {
- fprintf(stderr,
- "InnoDB: The first specified"
- " data file %s did not exist:\n"
- "InnoDB: a new database"
- " to be created!\n", name);
+ 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;
}
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Setting file %s size to %lu MB\n",
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Setting file %s size to %lu MB",
name,
(ulong) (srv_data_file_sizes[i]
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
- fprintf(stderr,
- "InnoDB: Database physically writes the"
- " file full: wait...\n");
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Database physically writes the"
+ " file full: wait...");
ret = os_file_set_size(
name, files[i],
@@ -963,9 +1028,10 @@ skip_size_check:
<< UNIV_PAGE_SIZE_SHIFT);
if (!ret) {
- fprintf(stderr,
- "InnoDB: Error in creating %s:"
- " probably out of disk space\n", name);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Error in creating %s: "
+ "probably out of disk space",
+ name);
return(DB_ERROR);
}
@@ -983,8 +1049,10 @@ skip_size_check:
ut_a(fil_validate());
- fil_node_create(name, srv_data_file_sizes[i], 0,
- srv_data_file_is_raw_partition[i] != 0);
+ 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);
@@ -994,7 +1062,7 @@ skip_size_check:
Create undo tablespace.
@return DB_SUCCESS or error code */
static
-enum db_err
+dberr_t
srv_undo_tablespace_create(
/*=======================*/
const char* name, /*!< in: tablespace name */
@@ -1002,48 +1070,55 @@ srv_undo_tablespace_create(
{
os_file_t fh;
ibool ret;
- enum db_err err = DB_SUCCESS;
+ dberr_t err = DB_SUCCESS;
os_file_create_subdirs_if_needed(name);
fh = os_file_create(
- innodb_file_data_key, name, 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);
- if (ret == FALSE
- && os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS
+ if (srv_read_only_mode && ret) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "%s opened in read-only mode", name);
+ } else if (ret == FALSE
+ && 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
+ /* 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 */
) {
- fprintf(stderr, "InnoDB: Error in creating %s\n", name);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Can't create UNDO tablespace %s", name);
err = DB_ERROR;
} else {
+ ut_a(!srv_read_only_mode);
+
/* We created the data file and now write it full of zeros */
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Data file %s did not"
- " exist: new to be created\n", name);
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Data file %s did not exist: new to be created",
+ name);
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Setting file %s size to %lu MB\n",
- name, size >> (20 - UNIV_PAGE_SIZE_SHIFT));
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Setting file %s size to %lu MB",
+ name, size >> (20 - UNIV_PAGE_SIZE_SHIFT));
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Database physically writes the"
- " file full: wait...\n");
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Database physically writes the file full: wait...");
ret = os_file_set_size(name, fh, size << UNIV_PAGE_SIZE_SHIFT);
if (!ret) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Error in creating %s:"
- " probably out of disk space\n", name);
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Error in creating %s: probably out of "
+ "disk space", name);
err = DB_ERROR;
}
@@ -1058,17 +1133,25 @@ srv_undo_tablespace_create(
Open an undo tablespace.
@return DB_SUCCESS or error code */
static
-enum db_err
+dberr_t
srv_undo_tablespace_open(
/*=====================*/
const char* name, /*!< in: tablespace name */
ulint space) /*!< in: tablespace id */
{
os_file_t fh;
- enum db_err err;
+ 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
@@ -1082,7 +1165,6 @@ srv_undo_tablespace_open(
if (ret) {
os_offset_t size;
- os_offset_t n_pages;
size = os_file_get_size(fh);
ut_a(size != (os_offset_t) -1);
@@ -1105,17 +1187,15 @@ srv_undo_tablespace_open(
ut_a(fil_validate());
- n_pages = size / UNIV_PAGE_SIZE;
+ 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. */
- fil_node_create(name, (ulint) n_pages, space, FALSE);
-
- err = DB_SUCCESS;
- } else {
- err = DB_ERROR;
+ if (fil_node_create(name, (ulint) n_pages, space, FALSE)) {
+ err = DB_SUCCESS;
+ }
}
return(err);
@@ -1125,20 +1205,25 @@ srv_undo_tablespace_open(
Opens the configured number of undo tablespaces.
@return DB_SUCCESS or error code */
static
-enum db_err
+dberr_t
srv_undo_tablespaces_init(
/*======================*/
ibool create_new_db, /*!< in: TRUE if new db being
created */
- const ulint n_conf_tablespaces) /*!< in: configured undo
+ const ulint n_conf_tablespaces, /*!< in: configured undo
tablespaces */
+ ulint* n_opened) /*!< out: number of UNDO
+ tablespaces successfully
+ discovered and opened */
{
ulint i;
- enum db_err err = DB_SUCCESS;
+ 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));
@@ -1164,10 +1249,10 @@ srv_undo_tablespaces_init(
name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
if (err != DB_SUCCESS) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Could not create "
- "undo tablespace '%s'.\n", name);
+
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Could not create undo tablespace '%s'.",
+ name);
return(err);
}
@@ -1217,15 +1302,16 @@ srv_undo_tablespaces_init(
err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]);
if (err != DB_SUCCESS) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error opening undo "
- "tablespace %s.\n", name);
+
+ 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.
@@ -1248,6 +1334,8 @@ srv_undo_tablespaces_init(
}
++n_undo_tablespaces;
+
+ ++*n_opened;
}
/* If the user says that there are fewer than what we find we
@@ -1275,13 +1363,17 @@ srv_undo_tablespaces_init(
"value is %lu\n", n_undo_tablespaces);
return(err != DB_SUCCESS ? err : DB_ERROR);
- }
- if (n_undo_tablespaces > 0) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Opened %lu undo tablespaces\n",
- n_conf_tablespaces);
+ } 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) {
@@ -1303,18 +1395,51 @@ srv_undo_tablespaces_init(
}
/********************************************************************
+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;
+ }
+ }
+}
+
+/********************************************************************
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
-int
+dberr_t
innobase_start_or_create_for_mysql(void)
/*====================================*/
{
ibool create_new_db;
- ibool log_file_created;
- ibool log_created = FALSE;
- ibool log_opened = FALSE;
lsn_t min_flushed_lsn;
lsn_t max_flushed_lsn;
#ifdef UNIV_LOG_ARCHIVE
@@ -1324,11 +1449,19 @@ innobase_start_or_create_for_mysql(void)
ulint sum_of_new_sizes;
ulint sum_of_data_file_sizes;
ulint tablespace_size_in_header;
- ulint err;
- ulint i;
+ 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;
+ char logfilename[10000];
+ char* logfile0 = NULL;
+ size_t dirnamelen;
+
+ if (srv_read_only_mode) {
+ ib_logf(IB_LOG_LEVEL_INFO, "Started in read only mode");
+ }
#ifdef HAVE_DARWIN_THREADS
# ifdef F_FULLFSYNC
@@ -1422,31 +1555,34 @@ innobase_start_or_create_for_mysql(void)
" InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n");
#endif
- if (UNIV_LIKELY(srv_use_sys_malloc)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: The InnoDB memory heap is disabled\n");
+ if (srv_use_sys_malloc) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "The InnoDB memory heap is disabled");
}
#if defined(COMPILER_HINTS_ENABLED)
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Compiler hints enabled.\n");
+ ib_logf(IB_LOG_LEVEL_INFO,
+ " InnoDB: Compiler hints enabled.");
#endif /* defined(COMPILER_HINTS_ENABLED) */
- ut_print_timestamp(stderr);
- fputs(" InnoDB: " IB_ATOMICS_STARTUP_MSG "\n", stderr);
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "" IB_ATOMICS_STARTUP_MSG "");
- ut_print_timestamp(stderr);
- fputs(" InnoDB: Compressed tables use zlib " ZLIB_VERSION
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Compressed tables use zlib " ZLIB_VERSION
#ifdef UNIV_ZIP_DEBUG
" with validation"
#endif /* UNIV_ZIP_DEBUG */
- "\n" , stderr);
+ );
#ifdef UNIV_ZIP_COPY
- ut_print_timestamp(stderr);
- fputs(" InnoDB: and extra copying\n", stderr);
+ ib_logf(IB_LOG_LEVEL_INFO, "and extra copying");
#endif /* UNIV_ZIP_COPY */
+
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "CPU %s crc32 instructions",
+ ut_crc32_sse2_enabled ? "supports" : "does not support");
+
/* 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
@@ -1505,17 +1641,14 @@ innobase_start_or_create_for_mysql(void)
#elif defined(LINUX_NATIVE_AIO)
if (srv_use_native_aio) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Using Linux native AIO\n");
+ 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
+#endif /* __WIN__ */
if (srv_file_flush_method_str == NULL) {
/* These are the default options */
@@ -1533,6 +1666,9 @@ innobase_start_or_create_for_mysql(void)
} 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, "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;
@@ -1550,12 +1686,10 @@ innobase_start_or_create_for_mysql(void)
} else if (0 == ut_strcmp(srv_file_flush_method_str,
"async_unbuffered")) {
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
-#endif
+#endif /* __WIN__ */
} else {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Unrecognized value %s for"
- " innodb_flush_method\n",
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Unrecognized value %s for innodb_flush_method",
srv_file_flush_method_str);
return(DB_ERROR);
}
@@ -1580,74 +1714,93 @@ innobase_start_or_create_for_mysql(void)
srv_max_n_threads = 10000;
} else {
srv_buf_pool_instances = 1;
- srv_max_n_threads = 1000; /* saves several MB of memory,
- especially in 64-bit
- computers */
+
+ /* Saves several MB of memory, especially in
+ 64-bit computers */
+
+ srv_max_n_threads = 1000;
}
- err = srv_boot();
+ srv_boot();
- if (err != DB_SUCCESS) {
+ if (!srv_read_only_mode) {
- return((int) err);
- }
+ mutex_create(srv_monitor_file_mutex_key,
+ &srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
- mutex_create(srv_monitor_file_mutex_key,
- &srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
+ if (srv_innodb_status) {
- if (srv_innodb_status) {
+ srv_monitor_file_name = static_cast<char*>(
+ mem_alloc(
+ strlen(fil_path_to_mysql_datadir)
+ + 20 + sizeof "/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());
- 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) {
- fprintf(stderr, "InnoDB: unable to create %s: %s\n",
- srv_monitor_file_name, strerror(errno));
- return(DB_ERROR);
+ 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();
+
+ if (!srv_monitor_file) {
+ return(DB_ERROR);
+ }
}
- } else {
- srv_monitor_file_name = NULL;
- srv_monitor_file = os_file_create_tmpfile();
- if (!srv_monitor_file) {
+
+ mutex_create(srv_dict_tmpfile_mutex_key,
+ &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
+
+ srv_dict_tmpfile = os_file_create_tmpfile();
+
+ if (!srv_dict_tmpfile) {
return(DB_ERROR);
}
- }
- mutex_create(srv_dict_tmpfile_mutex_key,
- &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
+ mutex_create(srv_misc_tmpfile_mutex_key,
+ &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
- srv_dict_tmpfile = os_file_create_tmpfile();
- if (!srv_dict_tmpfile) {
- return(DB_ERROR);
- }
+ srv_misc_tmpfile = os_file_create_tmpfile();
- mutex_create(srv_misc_tmpfile_mutex_key,
- &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
-
- srv_misc_tmpfile = os_file_create_tmpfile();
- if (!srv_misc_tmpfile) {
- return(DB_ERROR);
+ 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) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Warning:"
- " innodb_file_io_threads is deprecated."
- " Please use innodb_read_io_threads and"
- " innodb_write_io_threads instead\n");
+ 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 = 2 + srv_n_read_io_threads
- + srv_n_write_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);
@@ -1662,56 +1815,59 @@ innobase_start_or_create_for_mysql(void)
}
# endif /* __WIN__ */
- os_aio_init(io_limit,
- srv_n_read_io_threads,
- srv_n_write_io_threads,
- SRV_MAX_N_PENDING_SYNC_IOS);
+ 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");
+
+ return(DB_ERROR);
+ }
fil_init(srv_file_per_table ? 50000 : 5000, srv_max_n_open_files);
- /* Print time to initialize the buffer pool */
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Initializing buffer pool, size =");
+ double size;
+ char unit;
if (srv_buf_pool_size >= 1024 * 1024 * 1024) {
- fprintf(stderr,
- " %.1fG\n",
- ((double) srv_buf_pool_size) / (1024 * 1024 * 1024));
+ size = ((double) srv_buf_pool_size) / (1024 * 1024 * 1024);
+ unit = 'G';
} else {
- fprintf(stderr,
- " %.1fM\n",
- ((double) srv_buf_pool_size) / (1024 * 1024));
+ size = ((double) srv_buf_pool_size) / (1024 * 1024);
+ unit = 'M';
}
- err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
+ /* Print time to initialize the buffer pool */
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Initializing buffer pool, size = %.1f%c", size, unit);
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Completed initialization of buffer pool\n");
+ err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
if (err != DB_SUCCESS) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Fatal error: cannot allocate memory"
- " for the buffer pool\n");
+ 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) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Warning: Small buffer pool size "
- "(%luM), the flst_validate() debug function "
- "can cause a deadlock if the buffer pool fills up.\n",
+ 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
+#endif /* UNIV_DEBUG */
fsp_init();
log_init();
@@ -1720,14 +1876,15 @@ innobase_start_or_create_for_mysql(void)
/* Create i/o-handler threads: */
- for (i = 0; i < srv_n_file_io_threads; i++) {
+ for (ulint i = 0; i < srv_n_file_io_threads; ++i) {
+
n[i] = i;
os_thread_create(io_handler_thread, n + i, thread_ids + i);
}
#ifdef UNIV_LOG_ARCHIVE
- if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) {
+ if (0 != ut_strcmp(srv_log_group_home_dir, srv_arch_dir)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error: you must set the log group home dir in my.cnf\n");
ut_print_timestamp(stderr);
@@ -1738,16 +1895,14 @@ innobase_start_or_create_for_mysql(void)
#endif /* UNIV_LOG_ARCHIVE */
if (srv_n_log_files * srv_log_file_size * UNIV_PAGE_SIZE
- >= 549755813888ULL /* 512G */) {
+ >= 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. */
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: combined size of log files"
- " must be < 512 GB\n");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Combined size of log files must be < 512 GB");
return(DB_ERROR);
}
@@ -1759,7 +1914,6 @@ innobase_start_or_create_for_mysql(void)
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. */
- ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: combined size of log files"
" must be < %lu GB\n",
@@ -1791,10 +1945,8 @@ innobase_start_or_create_for_mysql(void)
}
if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: tablespace size must be"
- " at least 10 MB\n");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tablespace size must be at least 10 MB");
return(DB_ERROR);
}
@@ -1805,36 +1957,27 @@ innobase_start_or_create_for_mysql(void)
#endif /* UNIV_LOG_ARCHIVE */
&min_flushed_lsn, &max_flushed_lsn,
&sum_of_new_sizes);
- if (err != DB_SUCCESS) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Could not open or create data files.\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: If you tried to add new data files,"
- " and it failed here,\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: you should now edit innodb_data_file_path"
- " in my.cnf back\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: to what it was, and remove the"
- " new ibdata files InnoDB created\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: in this failed attempt. InnoDB only wrote"
- " those files full of\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: zeros, but did not yet use them in any way."
- " But be careful: do not\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: remove old data files"
- " which contain your precious data!\n");
+ if (err == DB_FAIL) {
+
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "The system tablespace must be writable!");
+
+ return(DB_ERROR);
- return((int) err);
+ } 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
@@ -1842,125 +1985,199 @@ innobase_start_or_create_for_mysql(void)
srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir);
#endif /* UNIV_LOG_ARCHIVE */
- for (i = 0; i < srv_n_log_files; i++) {
- err = open_or_create_log_file(create_new_db, &log_file_created,
- log_opened, 0, i);
- if (err != DB_SUCCESS) {
+ dirnamelen = strlen(srv_log_group_home_dir);
+ ut_a(dirnamelen < (sizeof logfilename) - 10 - sizeof "ib_logfile");
+ memcpy(logfilename, srv_log_group_home_dir, dirnamelen);
- return((int) err);
- }
+ /* Add a path separator if needed. */
+ if (dirnamelen && logfilename[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
+ logfilename[dirnamelen++] = SRV_PATH_SEPARATOR;
+ }
- if (log_file_created) {
- log_created = TRUE;
- } else {
- log_opened = TRUE;
+ 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);
+
+ min_flushed_lsn = max_flushed_lsn = log_get_lsn();
+
+ buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
+
+ err = create_log_files(logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
+
+ if (err != DB_SUCCESS) {
+ return(err);
}
- if ((log_opened && create_new_db)
- || (log_opened && log_created)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: all log files must be"
- " created at the same time.\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: All log files must be"
- " created also in database creation.\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: If you want bigger or smaller"
- " log files, shut down the\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: database and make sure there"
- " were no errors in shutdown.\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Then delete the existing log files."
- " Edit the .cnf file\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: and start the database again.\n");
+ } else {
+ 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 (max_flushed_lsn
+ != min_flushed_lsn) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Cannot create"
+ " log files because"
+ " data files are"
+ " corrupt or"
+ " not in sync"
+ " with each other");
+ return(DB_ERROR);
+ }
+
+ if (max_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(
+ logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
+
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
+
+ create_log_files_rename(
+ logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
+
+ /* Suppress the message about
+ crash recovery. */
+ max_flushed_lsn = min_flushed_lsn
+ = log_get_lsn();
+ goto files_checked;
+ } else if (i < 2) {
+ /* must have at least 2 log files */
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Only one log file found.");
+ return(err);
+ }
- return(DB_ERROR);
+ /* opened all files */
+ 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);
+ }
}
- }
- /* Open all log files and data files in the system tablespace: we
- keep them open until database shutdown */
+ srv_n_log_files_found = i;
- fil_open_log_and_system_tablespace_files();
+ /* Create the in-memory file space objects. */
- err = srv_undo_tablespaces_init(create_new_db, srv_undo_tablespaces);
+ sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
- /* If the force recovery is set very high then we carry on regardless
- of all errors. Basically this is fingers crossed mode. */
+ fil_space_create(logfilename,
+ SRV_LOG_SPACE_FIRST_ID,
+ fsp_flags_set_page_size(0, UNIV_PAGE_SIZE),
+ FIL_LOG);
- if (err != DB_SUCCESS
- && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) {
+ ut_a(fil_validate());
- return((int) err);
- }
+ /* 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);
+ }
+ }
- if (log_created && !create_new_db
-#ifdef UNIV_LOG_ARCHIVE
- && !srv_archive_recovery
-#endif /* UNIV_LOG_ARCHIVE */
- ) {
- if (max_flushed_lsn != min_flushed_lsn
#ifdef UNIV_LOG_ARCHIVE
- || max_arch_log_no != min_arch_log_no
+ /* 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);
#endif /* UNIV_LOG_ARCHIVE */
- ) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Cannot initialize created"
- " log files because\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: data files were not in sync"
- " with each other\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: or the data files are corrupt.\n");
+ log_group_init(0, i, srv_log_file_size * UNIV_PAGE_SIZE,
+ SRV_LOG_SPACE_FIRST_ID,
+ SRV_LOG_SPACE_FIRST_ID + 1);
+ }
- return(DB_ERROR);
- }
+files_checked:
+ /* Open all log files and data files in the system
+ tablespace: we keep them open until database
+ shutdown */
- if (max_flushed_lsn < (lsn_t) 1000) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Cannot initialize created"
- " log files because\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: data files are corrupt,"
- " or new data files were\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: created when the database"
- " was started previous\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: time but the database"
- " was not shut down\n");
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: normally after that.\n");
+ fil_open_log_and_system_tablespace_files();
- return(DB_ERROR);
- }
+ err = srv_undo_tablespaces_init(
+ create_new_db,
+ srv_undo_tablespaces,
+ &srv_undo_tablespaces_open);
- mutex_enter(&(log_sys->mutex));
+ /* If the force recovery is set very high then we carry on regardless
+ of all errors. Basically this is fingers crossed mode. */
-#ifdef UNIV_LOG_ARCHIVE
- /* Do not + 1 arch_log_no because we do not use log
- archiving */
- recv_reset_logs(max_flushed_lsn, max_arch_log_no, TRUE);
-#else
- recv_reset_logs(max_flushed_lsn, TRUE);
-#endif /* UNIV_LOG_ARCHIVE */
+ if (err != DB_SUCCESS
+ && srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) {
- mutex_exit(&(log_sys->mutex));
+ 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();
@@ -1968,6 +2185,9 @@ innobase_start_or_create_for_mysql(void)
trx_sys_create();
if (create_new_db) {
+
+ ut_a(!srv_read_only_mode);
+
mtr_start(&mtr);
fsp_header_init(0, sum_of_new_sizes, &mtr);
@@ -1987,16 +2207,34 @@ innobase_start_or_create_for_mysql(void)
trx_purge_sys_create(srv_n_purge_threads, ib_bh);
- dict_create();
+ 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);
+
+ min_flushed_lsn = max_flushed_lsn = log_get_lsn();
+
+ buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
+
+ /* Stamp the LSN to the data files. */
+ fil_write_flushed_lsn_to_data_files(max_flushed_lsn, 0);
+
+ fil_flush_file_spaces(FIL_TABLESPACE);
+
+ create_log_files_rename(logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
#ifdef UNIV_LOG_ARCHIVE
} else if (srv_archive_recovery) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Starting archive"
- " recovery from a backup...\n");
+
+ ib_logf(IB_LOG_LEVEL_INFO,
+ " Starting archive recovery from a backup...");
+
err = recv_recovery_from_archive_start(
min_flushed_lsn, srv_archive_recovery_limit_lsn,
min_arch_log_no);
@@ -2007,7 +2245,11 @@ innobase_start_or_create_for_mysql(void)
/* Since ibuf init is in dict_boot, and ibuf is needed
in any disk i/o, first call dict_boot */
- dict_boot();
+ err = dict_boot();
+
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
ib_bh = trx_sys_init_at_db_start();
@@ -2051,10 +2293,10 @@ innobase_start_or_create_for_mysql(void)
/* 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,
- IB_ULONGLONG_MAX,
- min_flushed_lsn,
- max_flushed_lsn);
+ err = recv_recovery_from_checkpoint_start(
+ LOG_CHECKPOINT, IB_ULONGLONG_MAX,
+ min_flushed_lsn, max_flushed_lsn);
+
if (err != DB_SUCCESS) {
return(DB_ERROR);
@@ -2066,7 +2308,11 @@ innobase_start_or_create_for_mysql(void)
to access space 0, and the insert buffer at this stage already
works for space 0. */
- dict_boot();
+ err = dict_boot();
+
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
ib_bh = trx_sys_init_at_db_start();
@@ -2079,6 +2325,7 @@ innobase_start_or_create_for_mysql(void)
are initialized in trx_sys_init_at_db_start(). */
recv_recovery_from_checkpoint_finish();
+
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
@@ -2100,6 +2347,90 @@ innobase_start_or_create_for_mysql(void)
recv_needed_recovery);
}
+ 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);
+
+ RECOVERY_CRASH(1);
+
+ min_flushed_lsn = max_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,
+ max_flushed_lsn);
+
+ buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
+
+ RECOVERY_CRASH(2);
+
+ /* 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(max_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());
+
+ RECOVERY_CRASH(3);
+
+ /* Stamp the LSN to the data files. */
+ fil_write_flushed_lsn_to_data_files(
+ max_flushed_lsn, 0);
+
+ fil_flush_file_spaces(FIL_TABLESPACE);
+
+ RECOVERY_CRASH(4);
+
+ /* Close and free the redo log files, so that
+ we can replace them. */
+ fil_close_log_files(true);
+
+ RECOVERY_CRASH(5);
+
+ /* 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(logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
+
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
+
+ create_log_files_rename(logfilename, dirnamelen,
+ max_flushed_lsn, logfile0);
+ }
+
srv_startup_is_before_trx_rollback_phase = FALSE;
recv_recovery_rollback_active();
@@ -2181,31 +2512,39 @@ innobase_start_or_create_for_mysql(void)
if (srv_available_undo_logs == ULINT_UNDEFINED) {
/* Can only happen if force recovery is set. */
- ut_a(srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
+ ut_a(srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO
+ || srv_read_only_mode);
srv_undo_logs = ULONG_UNDEFINED;
}
- /* Create the thread which watches the timeouts for lock waits */
- os_thread_create(
- lock_wait_timeout_thread,
- NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS);
-
- /* Create the thread which warns of long semaphore waits */
- os_thread_create(
- srv_error_monitor_thread,
- NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS);
+ if (!srv_read_only_mode) {
+ /* Create the thread which watches the timeouts
+ for lock waits */
+ os_thread_create(
+ lock_wait_timeout_thread,
+ NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS);
- /* Create the thread which prints InnoDB monitor info */
- os_thread_create(
- srv_monitor_thread,
- NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
+ /* Create the thread which warns of long semaphore waits */
+ os_thread_create(
+ srv_error_monitor_thread,
+ NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS);
- srv_is_being_started = FALSE;
+ /* Create the thread which prints InnoDB monitor info */
+ os_thread_create(
+ srv_monitor_thread,
+ NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS);
+ }
/* Create the SYS_FOREIGN and SYS_FOREIGN_COLS system tables */
err = dict_create_or_check_foreign_constraint_tables();
if (err != DB_SUCCESS) {
- return((int)DB_ERROR);
+ return(err);
+ }
+
+ /* Create the SYS_TABLESPACES system table */
+ err = dict_create_or_check_sys_tablespace();
+ if (err != DB_SUCCESS) {
+ return(err);
}
srv_is_being_started = FALSE;
@@ -2215,11 +2554,15 @@ innobase_start_or_create_for_mysql(void)
/* Create the master thread which does purge and other utility
operations */
- os_thread_create(
- srv_master_thread,
- NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
+ if (!srv_read_only_mode) {
+
+ os_thread_create(
+ srv_master_thread,
+ NULL, thread_ids + (1 + SRV_MAX_N_IO_THREADS));
+ }
- if (srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
+ if (!srv_read_only_mode
+ && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {
os_thread_create(
srv_purge_coordinator_thread,
@@ -2234,35 +2577,15 @@ innobase_start_or_create_for_mysql(void)
srv_worker_thread, NULL,
thread_ids + 5 + i + SRV_MAX_N_IO_THREADS);
}
- }
-
- os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL);
-
- /* Wait for the purge coordinator and master thread to startup. */
-
- purge_state_t state = trx_purge_state();
- 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:
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: "
- "Waiting for the background threads to "
- "start\n");
+ srv_start_wait_for_purge_to_start();
- os_thread_sleep(50000);
- break;
+ } else {
+ purge_sys->state = PURGE_STATE_DISABLED;
+ }
- case PURGE_STATE_EXIT:
- ut_error;
- }
+ if (!srv_read_only_mode) {
+ os_thread_create(buf_flush_page_cleaner_thread, NULL, NULL);
}
#ifdef UNIV_DEBUG
@@ -2276,7 +2599,8 @@ innobase_start_or_create_for_mysql(void)
tablespace_size_in_header = fsp_header_get_tablespace_size();
- if (!srv_auto_extend_last_data_file
+ if (!srv_read_only_mode
+ && !srv_auto_extend_last_data_file
&& sum_of_data_file_sizes != tablespace_size_in_header) {
ut_print_timestamp(stderr);
@@ -2319,7 +2643,8 @@ innobase_start_or_create_for_mysql(void)
}
}
- if (srv_auto_extend_last_data_file
+ if (!srv_read_only_mode
+ && srv_auto_extend_last_data_file
&& sum_of_data_file_sizes < tablespace_size_in_header) {
ut_print_timestamp(stderr);
@@ -2383,23 +2708,17 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_free(&srv_os_test_mutex);
if (srv_print_verbose_log) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: %s started; "
- "log sequence number " LSN_PF "\n",
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "%s started; log sequence number " LSN_PF "",
INNODB_VERSION_STR, srv_start_lsn);
}
if (srv_force_recovery > 0) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: !!! innodb_force_recovery"
- " is set to %lu !!!\n",
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "!!! innodb_force_recovery is set to %lu !!!",
(ulong) srv_force_recovery);
}
- fflush(stderr);
-
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
@@ -2409,16 +2728,20 @@ innobase_start_or_create_for_mysql(void)
ibuf_update_max_tablespace_id();
}
- /* Create the buffer pool dump/load thread */
- os_thread_create(buf_dump_thread, NULL, NULL);
+ if (!srv_read_only_mode) {
+ /* Create the buffer pool dump/load thread */
+ os_thread_create(buf_dump_thread, NULL, NULL);
- srv_was_started = TRUE;
+ /* Create the dict stats gathering thread */
+ os_thread_create(dict_stats_thread, NULL, NULL);
- /* Create the thread that will optimize the FTS sub-system
- in a separate background thread. */
- fts_optimize_init();
+ /* Create the thread that will optimize the FTS sub-system. */
+ fts_optimize_init();
+ }
- return((int) DB_SUCCESS);
+ srv_was_started = TRUE;
+
+ return(DB_SUCCESS);
}
#if 0
@@ -2455,27 +2778,28 @@ srv_fts_close(void)
Shuts down the InnoDB database.
@return DB_SUCCESS or error code */
UNIV_INTERN
-int
+dberr_t
innobase_shutdown_for_mysql(void)
/*=============================*/
{
ulint i;
+
if (!srv_was_started) {
if (srv_is_being_started) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Warning: shutting down"
- " a not properly started\n"
- "InnoDB: or created database!\n");
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Shutting down an improperly started, "
+ "or created database!");
}
return(DB_SUCCESS);
}
- /* Shutdown the FTS optimize sub system. */
- fts_optimize_start_shutdown();
+ if (!srv_read_only_mode) {
+ /* Shutdown the FTS optimize sub system. */
+ fts_optimize_start_shutdown();
- fts_optimize_end();
+ fts_optimize_end();
+ }
/* 1. Flush the buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive.
@@ -2485,18 +2809,12 @@ innobase_shutdown_for_mysql(void)
logs_empty_and_mark_files_at_shutdown();
if (srv_conc_get_active_threads() != 0) {
- fprintf(stderr,
- "InnoDB: Warning: query counter shows %ld queries"
- " still\n"
- "InnoDB: inside InnoDB at shutdown\n",
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Query counter shows %ld queries still "
+ "inside InnoDB at shutdown",
srv_conc_get_active_threads());
}
- /* This functionality will be used by WL#5522. */
- ut_a(trx_purge_state() == PURGE_STATE_RUN
- || trx_purge_state() == PURGE_STATE_EXIT
- || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND);
-
/* 2. Make all threads created by InnoDB to exit */
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
@@ -2509,22 +2827,28 @@ innobase_shutdown_for_mysql(void)
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
HERE OR EARLIER */
- /* a. Let the lock timeout thread exit */
- os_event_set(srv_timeout_event);
+ 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 */
+ /* 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();
+ /* c. We wake the master thread so that it exits */
+ srv_wake_master_thread();
- /* d. Wakeup purge threads. */
- srv_purge_wakeup();
+ /* 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. */
+
os_mutex_enter(os_sync_mutex);
if (os_thread_count == 0) {
@@ -2549,9 +2873,9 @@ innobase_shutdown_for_mysql(void)
}
if (i == 1000) {
- fprintf(stderr,
- "InnoDB: Warning: %lu threads created by InnoDB"
- " had not exited at shutdown!\n",
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "%lu threads created by InnoDB"
+ " had not exited at shutdown!",
(ulong) os_thread_count);
}
@@ -2563,6 +2887,7 @@ innobase_shutdown_for_mysql(void)
mem_free(srv_monitor_file_name);
}
}
+
if (srv_dict_tmpfile) {
fclose(srv_dict_tmpfile);
srv_dict_tmpfile = 0;
@@ -2573,6 +2898,10 @@ innobase_shutdown_for_mysql(void)
srv_misc_tmpfile = 0;
}
+ if (!srv_read_only_mode) {
+ dict_stats_thread_deinit();
+ }
+
/* This must be disabled before closing the buffer pool
and closing the data dictionary. */
btr_search_disable();
@@ -2583,9 +2912,14 @@ innobase_shutdown_for_mysql(void)
trx_sys_file_format_close();
trx_sys_close();
- mutex_free(&srv_monitor_file_mutex);
- mutex_free(&srv_dict_tmpfile_mutex);
- mutex_free(&srv_misc_tmpfile_mutex);
+ /* 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();
@@ -2594,6 +2928,7 @@ innobase_shutdown_for_mysql(void)
os_aio_free();
que_close();
row_mysql_close();
+ srv_mon_free();
sync_close();
srv_free();
fil_close();
@@ -2618,11 +2953,10 @@ innobase_shutdown_for_mysql(void)
|| os_event_count != 0
|| os_mutex_count != 0
|| os_fast_mutex_count != 0) {
- fprintf(stderr,
- "InnoDB: Warning: some resources were not"
- " cleaned up in shutdown:\n"
- "InnoDB: threads %lu, events %lu,"
- " os_mutexes %lu, os_fast_mutexes %lu\n",
+ 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);
}
@@ -2632,17 +2966,15 @@ innobase_shutdown_for_mysql(void)
}
if (srv_print_verbose_log) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Shutdown completed;"
- " log sequence number " LSN_PF "\n",
+ 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;
- return((int) DB_SUCCESS);
+ return(DB_SUCCESS);
}
#endif /* !UNIV_HOTBACKUP */
@@ -2650,7 +2982,7 @@ innobase_shutdown_for_mysql(void)
/********************************************************************
Signal all per-table background threads to shutdown, and wait for them to do
so. */
-
+UNIV_INTERN
void
srv_shutdown_table_bg_threads(void)
/*===============================*/
@@ -2723,3 +3055,48 @@ srv_shutdown_table_bg_threads(void)
table = next;
}
}
+
+/*****************************************************************//**
+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(strncmp(suffix, ".ibd", suffix_len) == 0);
+
+ strncpy(filename, path, len - suffix_len);
+ suffix = filename + (len - suffix_len);
+ strcpy(suffix, ".cfg");
+ }
+
+ mem_free(path);
+
+ srv_normalize_path_for_win(filename);
+}