summaryrefslogtreecommitdiff
path: root/innobase/srv/srv0start.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/srv/srv0start.c')
-rw-r--r--innobase/srv/srv0start.c374
1 files changed, 351 insertions, 23 deletions
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index bbb48331811..fa4f4bc9419 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -84,6 +84,308 @@ we may get an assertion failure in os0file.c */
#define SRV_LOG_SPACE_FIRST_ID 1000000000
+/*************************************************************************
+Reads the data files and their sizes from a character string given in
+the .cnf file. */
+
+ibool
+srv_parse_data_file_paths_and_sizes(
+/*================================*/
+ /* out: TRUE if ok, FALSE if parsing
+ error */
+ char* str, /* in: the data file path string */
+ char*** data_file_names, /* out, own: array of data file
+ names */
+ ulint** data_file_sizes, /* out, own: array of data file sizes
+ in megabytes */
+ ulint** data_file_is_raw_partition,/* out, own: array of flags
+ showing which data files are raw
+ partitions */
+ ulint* n_data_files, /* out: number of data files */
+ ibool* is_auto_extending, /* out: TRUE if the last data file is
+ auto-extending */
+ ulint* max_auto_extend_size) /* out: max auto extend size for the
+ last file if specified, 0 if not */
+{
+ char* input_str;
+ char* endp;
+ char* path;
+ ulint size;
+ ulint i = 0;
+
+ *is_auto_extending = FALSE;
+ *max_auto_extend_size = 0;
+
+ 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++;
+ }
+
+ if (*str == '\0') {
+ return(FALSE);
+ }
+
+ str++;
+
+ size = strtoul(str, &endp, 10);
+
+ str = endp;
+
+ if (*str != 'M' && *str != 'G') {
+ size = size / (1024 * 1024);
+ } else if (*str == 'G') {
+ size = size * 1024;
+ str++;
+ } else {
+ str++;
+ }
+
+ if (strlen(str) >= ut_strlen(":autoextend")
+ && 0 == ut_memcmp(str, ":autoextend",
+ ut_strlen(":autoextend"))) {
+
+ str += ut_strlen(":autoextend");
+
+ if (strlen(str) >= ut_strlen(":max:")
+ && 0 == ut_memcmp(str, ":max:",
+ ut_strlen(":max:"))) {
+
+ str += ut_strlen(":max:");
+
+ size = strtoul(str, &endp, 10);
+
+ str = endp;
+
+ if (*str != 'M' && *str != 'G') {
+ size = size / (1024 * 1024);
+ } else if (*str == 'G') {
+ size = size * 1024;
+ str++;
+ } else {
+ str++;
+ }
+ }
+
+ if (*str != '\0') {
+
+ return(FALSE);
+ }
+ }
+
+ if (strlen(str) >= 6
+ && *str == 'n'
+ && *(str + 1) == 'e'
+ && *(str + 2) == 'w') {
+ str += 3;
+ }
+
+ if (strlen(str) >= 3
+ && *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);
+ }
+ }
+
+ *data_file_names = (char**)ut_malloc(i * sizeof(void*));
+ *data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
+ *data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));
+
+ *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 ignore the ':' in a Windows path */
+
+ while ((*str != ':' && *str != '\0')
+ || (*str == ':'
+ && (*(str + 1) == '\\' || *(str + 1) == '/'))) {
+ str++;
+ }
+
+ if (*str == ':') {
+ /* Make path a null-terminated string */
+ *str = '\0';
+ str++;
+ }
+
+ size = strtoul(str, &endp, 10);
+
+ str = endp;
+
+ if ((*str != 'M') && (*str != 'G')) {
+ size = size / (1024 * 1024);
+ } else if (*str == 'G') {
+ size = size * 1024;
+ str++;
+ } else {
+ str++;
+ }
+
+ (*data_file_names)[i] = path;
+ (*data_file_sizes)[i] = size;
+
+ if (strlen(str) >= ut_strlen(":autoextend")
+ && 0 == ut_memcmp(str, ":autoextend",
+ ut_strlen(":autoextend"))) {
+
+ *is_auto_extending = TRUE;
+
+ str += ut_strlen(":autoextend");
+
+ if (strlen(str) >= ut_strlen(":max:")
+ && 0 == ut_memcmp(str, ":max:",
+ ut_strlen(":max:"))) {
+
+ str += ut_strlen(":max:");
+
+ size = strtoul(str, &endp, 10);
+
+ str = endp;
+
+ if (*str != 'M' && *str != 'G') {
+ size = size / (1024 * 1024);
+ } else if (*str == 'G') {
+ size = size * 1024;
+ str++;
+ } else {
+ str++;
+ }
+
+ *max_auto_extend_size = size;
+ }
+
+ if (*str != '\0') {
+
+ return(FALSE);
+ }
+ }
+
+ (*data_file_is_raw_partition)[i] = 0;
+
+ if (strlen(str) >= 6
+ && *str == 'n'
+ && *(str + 1) == 'e'
+ && *(str + 2) == 'w') {
+ str += 3;
+ (*data_file_is_raw_partition)[i] = SRV_NEW_RAW;
+ }
+
+ if (strlen(str) >= 3
+ && *str == 'r'
+ && *(str + 1) == 'a'
+ && *(str + 2) == 'w') {
+ str += 3;
+
+ if ((*data_file_is_raw_partition)[i] == 0) {
+ (*data_file_is_raw_partition)[i] = SRV_OLD_RAW;
+ }
+ }
+
+ i++;
+
+ if (*str == ';') {
+ str++;
+ }
+ }
+
+ return(TRUE);
+}
+
+/*************************************************************************
+Reads log group home directories from a character string given in
+the .cnf file. */
+
+ibool
+srv_parse_log_group_home_dirs(
+/*==========================*/
+ /* out: TRUE if ok, FALSE if parsing
+ error */
+ char* str, /* in: character string */
+ char*** log_group_home_dirs) /* out, own: log group home dirs */
+{
+ char* input_str;
+ char* path;
+ ulint i = 0;
+
+ 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);
+ }
+ }
+
+ *log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));
+
+ /* 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++;
+ }
+
+ (*log_group_home_dirs)[i] = path;
+
+ i++;
+ }
+
+ return(TRUE);
+}
+
/************************************************************************
I/o-handler thread function. */
static
@@ -127,7 +429,7 @@ io_handler_thread(
/*************************************************************************
Normalizes a directory path for Windows: converts slashes to backslashes. */
-static
+
void
srv_normalize_path_for_win(
/*=======================*/
@@ -149,7 +451,7 @@ srv_normalize_path_for_win(
/*************************************************************************
Adds a slash or a backslash to the end of a string if it is missing
and the string is not empty. */
-static
+
char*
srv_add_path_separator_if_needed(
/*=============================*/
@@ -356,6 +658,7 @@ open_or_create_data_files(
ibool one_created = FALSE;
ulint size;
ulint size_high;
+ ulint rounded_size_pages;
char name[10000];
if (srv_n_data_files >= 1000) {
@@ -435,17 +738,35 @@ open_or_create_data_files(
ret = os_file_get_size(files[i], &size,
&size_high);
ut_a(ret);
+ /* Round size downward to megabytes */
- /* File sizes in srv_... are given in
- database pages */
-
- if (size != srv_calc_low32(
- srv_data_file_sizes[i])
- || size_high != srv_calc_high32(
- srv_data_file_sizes[i])) {
+ rounded_size_pages = (size / (1024 * 1024)
+ + 4096 * size_high)
+ << (20 - 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)) {
+
+ fprintf(stderr,
+ "InnoDB: Error: data file %s is of a different size\n"
+ "InnoDB: than specified in the .cnf file!\n", name);
+ }
+
+ srv_data_file_sizes[i] =
+ rounded_size_pages;
+ }
+
+ if (rounded_size_pages
+ != srv_data_file_sizes[i]) {
fprintf(stderr,
- "InnoDB: Error: data file %s is of different size\n"
+ "InnoDB: Error: data file %s is of a different size\n"
"InnoDB: than specified in the .cnf file!\n", name);
return(DB_ERROR);
@@ -479,7 +800,7 @@ open_or_create_data_files(
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
fprintf(stderr,
- "InnoDB: Database physically writes the file full: wait...\n");
+ "InnoDB: Database physically writes the file full: wait...\n");
ret = os_file_set_size(name, files[i],
srv_calc_low32(srv_data_file_sizes[i]),
@@ -681,6 +1002,8 @@ innobase_start_or_create_for_mysql(void)
os_aio_use_native_aio = TRUE;
}
#endif
+ os_aio_use_native_aio = FALSE;
+
if (!os_aio_use_native_aio) {
os_aio_init(4 * SRV_N_PENDING_IOS_PER_THREAD
* srv_n_file_io_threads,
@@ -727,12 +1050,10 @@ innobase_start_or_create_for_mysql(void)
return(DB_ERROR);
}
- if (sizeof(ulint) == 4
- && srv_n_log_files * srv_log_file_size >= 262144) {
+ if (srv_n_log_files * srv_log_file_size >= 262144) {
fprintf(stderr,
- "InnoDB: Error: combined size of log files must be < 4 GB\n"
- "InnoDB: on 32-bit computers\n");
+ "InnoDB: Error: combined size of log files must be < 4 GB\n");
return(DB_ERROR);
}
@@ -764,7 +1085,6 @@ innobase_start_or_create_for_mysql(void)
&max_flushed_lsn, &max_arch_log_no,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
-
fprintf(stderr, "InnoDB: Could not open data files\n");
return((int) err);
@@ -803,9 +1123,9 @@ innobase_start_or_create_for_mysql(void)
|| (log_opened && log_created)) {
fprintf(stderr,
"InnoDB: Error: all log files must be created at the same time.\n"
- "InnoDB: If you want bigger or smaller log files,\n"
- "InnoDB: shut down the database and make sure there\n"
- "InnoDB: were no errors in shutdown.\n"
+ "InnoDB: All log files must be created also in database creation.\n"
+ "InnoDB: If you want bigger or smaller log files, shut down the\n"
+ "InnoDB: database and make sure there were no errors in shutdown.\n"
"InnoDB: Then delete the existing log files. Edit the .cnf file\n"
"InnoDB: and start the database again.\n");
@@ -841,9 +1161,7 @@ innobase_start_or_create_for_mysql(void)
mutex_enter(&(log_sys->mutex));
- recv_reset_logs(ut_dulint_align_down(max_flushed_lsn,
- OS_FILE_LOG_BLOCK_SIZE),
- max_arch_log_no + 1, TRUE);
+ recv_reset_logs(max_flushed_lsn, max_arch_log_no + 1, TRUE);
mutex_exit(&(log_sys->mutex));
}
@@ -883,6 +1201,10 @@ innobase_start_or_create_for_mysql(void)
srv_startup_is_before_trx_rollback_phase = FALSE;
+ /* Initialize the fsp free limit global variable in the log
+ system */
+ fsp_header_get_free_limit(0);
+
recv_recovery_from_archive_finish();
} else {
/* We always try to do a recovery, even if the database had
@@ -899,6 +1221,7 @@ 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();
trx_sys_init_at_db_start();
@@ -906,6 +1229,11 @@ innobase_start_or_create_for_mysql(void)
trx_sys_init_at_db_start */
srv_startup_is_before_trx_rollback_phase = FALSE;
+
+ /* Initialize the fsp free limit global variable in the log
+ system */
+ fsp_header_get_free_limit(0);
+
recv_recovery_from_checkpoint_finish();
}
@@ -975,7 +1303,7 @@ innobase_start_or_create_for_mysql(void)
if (err != DB_SUCCESS) {
return((int)DB_ERROR);
}
-
+
/* Create the master thread which monitors the database
server, and does purge and other utility operations */