From 389c33b746e9dcd525ec43a81b08453e7a0efa75 Mon Sep 17 00:00:00 2001 From: osku Date: Thu, 8 Dec 2005 14:27:09 +0000 Subject: [PATCH] Port r87 from branches/5.0: Work around Bug #12071: Do not call os_file_create_tmpfile() at runtime. Instead, create all tempfiles at startup and guard access to them with mutexes. --- handler/ha_innodb.cc | 123 +++++++++++++++++++++---------------------- include/os0file.h | 2 +- include/srv0srv.h | 12 +++++ row/row0ins.c | 19 +++---- srv/srv0srv.c | 12 +++++ srv/srv0start.c | 27 +++++++++- 6 files changed, 118 insertions(+), 77 deletions(-) diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index fc4908c7ac0..9d5bd62e845 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -5768,6 +5768,7 @@ ha_innobase::update_table_comment( uint length = (uint) strlen(comment); char* str; row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; + long flen; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -5787,43 +5788,43 @@ ha_innobase::update_table_comment( trx_search_latch_release_if_reserved(prebuilt->trx); str = NULL; - if (FILE* file = os_file_create_tmpfile()) { - long flen; + /* output the data to a temporary file */ - /* output the data to a temporary file */ - fprintf(file, "InnoDB free: %lu kB", + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); + + fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB", (ulong) fsp_get_available_space_in_free_extents( prebuilt->table->space)); - dict_print_info_on_foreign_keys(FALSE, file, + dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (length + flen + 3 > 64000) { - flen = 64000 - 3 - length; - } - - /* allocate buffer for the full string, and - read the contents of the temporary file */ - - str = my_malloc(length + flen + 3, MYF(0)); - - if (str) { - char* pos = str + length; - if (length) { - memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - rewind(file); - flen = (uint) fread(pos, 1, flen, file); - pos[flen] = 0; - } - - fclose(file); + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { + flen = 64000 - 3 - length; } + /* allocate buffer for the full string, and + read the contents of the temporary file */ + + str = my_malloc(length + flen + 3, MYF(0)); + + if (str) { + char* pos = str + length; + if (length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; + } + rewind(srv_dict_tmpfile); + flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile); + pos[flen] = 0; + } + + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + prebuilt->trx->op_info = (char*)""; return(str ? str : (char*) comment); @@ -5841,6 +5842,7 @@ ha_innobase::get_foreign_key_create_info(void) { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; char* str = 0; + long flen; ut_a(prebuilt != NULL); @@ -5850,47 +5852,42 @@ ha_innobase::get_foreign_key_create_info(void) update_thd(current_thd); - if (FILE* file = os_file_create_tmpfile()) { - long flen; + prebuilt->trx->op_info = (char*)"getting info on foreign keys"; - prebuilt->trx->op_info = (char*)"getting info on foreign keys"; + /* In case MySQL calls this in the middle of a SELECT query, + release possible adaptive hash latch to avoid + deadlocks of threads */ - /* In case MySQL calls this in the middle of a SELECT query, - release possible adaptive hash latch to avoid - deadlocks of threads */ + trx_search_latch_release_if_reserved(prebuilt->trx); - trx_search_latch_release_if_reserved(prebuilt->trx); + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); - /* output the data to a temporary file */ - dict_print_info_on_foreign_keys(TRUE, file, + /* output the data to a temporary file */ + dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - prebuilt->trx->op_info = (char*)""; + prebuilt->trx->op_info = (char*)""; - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; - } - - /* allocate buffer for the string, and - read the contents of the temporary file */ - - str = my_malloc(flen + 1, MYF(0)); - - if (str) { - rewind(file); - flen = (uint) fread(str, 1, flen, file); - str[flen] = 0; - } - - fclose(file); - } else { - /* unable to create temporary file */ - str = my_strdup( -"/* Error: cannot display foreign key constraints */", MYF(0)); + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (flen > 64000 - 1) { + flen = 64000 - 1; } + /* allocate buffer for the string, and + read the contents of the temporary file */ + + str = my_malloc(flen + 1, MYF(0)); + + if (str) { + rewind(srv_dict_tmpfile); + flen = (uint) fread(str, 1, flen, srv_dict_tmpfile); + str[flen] = 0; + } + + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + return(str); } diff --git a/include/os0file.h b/include/os0file.h index 224fd59a76b..02a38dd49ef 100644 --- a/include/os0file.h +++ b/include/os0file.h @@ -187,7 +187,7 @@ Creates a temporary file. */ FILE* os_file_create_tmpfile(void); /*========================*/ - /* out: temporary file handle (never NULL) */ + /* out: temporary file handle, or NULL on error */ /*************************************************************************** The os_file_opendir() function opens a directory stream corresponding to the directory named by the dirname argument. The directory stream is positioned diff --git a/include/srv0srv.h b/include/srv0srv.h index 11347f430d4..99ea4f2de27 100644 --- a/include/srv0srv.h +++ b/include/srv0srv.h @@ -34,6 +34,18 @@ extern ibool srv_lower_case_table_names; extern mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ extern FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +extern mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +extern FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +extern mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +extern FILE* srv_misc_tmpfile; /* Server parameters which are read from the initfile */ diff --git a/row/row0ins.c b/row/row0ins.c index 5e833372299..6be22b75420 100644 --- a/row/row0ins.c +++ b/row/row0ins.c @@ -588,20 +588,15 @@ row_ins_set_detailed( trx_t* trx, /* in: transaction */ dict_foreign_t* foreign) /* in: foreign key constraint */ { - - FILE* tf = os_file_create_tmpfile(); + mutex_enter(&srv_misc_tmpfile_mutex); + rewind(srv_misc_tmpfile); - if (tf) { - ut_print_name(tf, trx, foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format(tf, trx, - foreign, FALSE); + ut_print_name(srv_misc_tmpfile, trx, foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format(srv_misc_tmpfile, + trx, foreign, FALSE); + trx_set_detailed_error_from_file(trx, srv_misc_tmpfile); - trx_set_detailed_error_from_file(trx, tf); - - fclose(tf); - } else { - trx_set_detailed_error(trx, "temp file creation failed"); - } + mutex_exit(&srv_misc_tmpfile_mutex); } /************************************************************************* diff --git a/srv/srv0srv.c b/srv/srv0srv.c index c585536baee..6e0b9b23266 100644 --- a/srv/srv0srv.c +++ b/srv/srv0srv.c @@ -397,6 +397,18 @@ mutex_t srv_innodb_monitor_mutex; mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +FILE* srv_misc_tmpfile; ulint srv_main_thread_process_no = 0; ulint srv_main_thread_id = 0; diff --git a/srv/srv0start.c b/srv/srv0start.c index e5151ebf631..4f99f340e1c 100644 --- a/srv/srv0start.c +++ b/srv/srv0start.c @@ -1180,6 +1180,20 @@ NetWare. */ } } + mutex_create(&srv_dict_tmpfile_mutex); + mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); + srv_dict_tmpfile = os_file_create_tmpfile(); + if (!srv_dict_tmpfile) { + return(DB_ERROR); + } + + mutex_create(&srv_misc_tmpfile_mutex); + mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); + srv_misc_tmpfile = os_file_create_tmpfile(); + if (!srv_misc_tmpfile) { + return(DB_ERROR); + } + /* Restrict the maximum number of file i/o threads */ if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) { @@ -1822,8 +1836,19 @@ innobase_shutdown_for_mysql(void) 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; + } + mutex_free(&srv_monitor_file_mutex); + mutex_free(&srv_dict_tmpfile_mutex); + mutex_free(&srv_misc_tmpfile_mutex); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */