Drizzled Public API Documentation

srv0start.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
00004 Copyright (C) 2008, Google Inc.
00005 Copyright (C) 2009, Percona Inc.
00006 
00007 Portions of this file contain modifications contributed and copyrighted by
00008 Google, Inc. Those modifications are gratefully acknowledged and are described
00009 briefly in the InnoDB documentation. The contributions by Google are
00010 incorporated with their permission, and subject to the conditions contained in
00011 the file COPYING.Google.
00012 
00013 Portions of this file contain modifications contributed and copyrighted
00014 by Percona Inc.. Those modifications are
00015 gratefully acknowledged and are described briefly in the InnoDB
00016 documentation. The contributions by Percona Inc. are incorporated with
00017 their permission, and subject to the conditions contained in the file
00018 COPYING.Percona.
00019 
00020 This program is free software; you can redistribute it and/or modify it under
00021 the terms of the GNU General Public License as published by the Free Software
00022 Foundation; version 2 of the License.
00023 
00024 This program is distributed in the hope that it will be useful, but WITHOUT
00025 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00026 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00027 
00028 You should have received a copy of the GNU General Public License along with
00029 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00030 St, Fifth Floor, Boston, MA 02110-1301 USA
00031 
00032 *****************************************************************************/
00033 
00034 /********************************************************************/
00041 #include "ut0mem.h"
00042 #include "mem0mem.h"
00043 #include "data0data.h"
00044 #include "data0type.h"
00045 #include "dict0dict.h"
00046 #include "buf0buf.h"
00047 #include "os0file.h"
00048 #include "os0thread.h"
00049 #include "fil0fil.h"
00050 #include "fsp0fsp.h"
00051 #include "rem0rec.h"
00052 #include "mtr0mtr.h"
00053 #include "log0log.h"
00054 #include "log0recv.h"
00055 #include "page0page.h"
00056 #include "page0cur.h"
00057 #include "trx0trx.h"
00058 #include "trx0sys.h"
00059 #include "btr0btr.h"
00060 #include "btr0cur.h"
00061 #include "rem0rec.h"
00062 #include "ibuf0ibuf.h"
00063 #include "srv0start.h"
00064 #include "srv0srv.h"
00065 #ifndef UNIV_HOTBACKUP
00066 # include "os0proc.h"
00067 # include "sync0sync.h"
00068 # include "buf0flu.h"
00069 # include "buf0rea.h"
00070 # include "dict0boot.h"
00071 # include "dict0load.h"
00072 # include "que0que.h"
00073 # include "usr0sess.h"
00074 # include "lock0lock.h"
00075 # include "trx0roll.h"
00076 # include "trx0purge.h"
00077 # include "lock0lock.h"
00078 # include "pars0pars.h"
00079 # include "btr0sea.h"
00080 # include "rem0cmp.h"
00081 # include "dict0crea.h"
00082 # include "row0ins.h"
00083 # include "row0sel.h"
00084 # include "row0upd.h"
00085 # include "row0row.h"
00086 # include "row0mysql.h"
00087 # include "btr0pcur.h"
00088 # include "thr0loc.h"
00089 # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
00090 # include "zlib.h" /* for ZLIB_VERSION */
00091 #include "xtrabackup_api.h"
00092 
00093 #include <errno.h>
00094 #include <unistd.h>
00095 
00096 #include <drizzled/gettext.h> 
00097 #include <drizzled/errmsg_print.h>
00098 
00100 UNIV_INTERN ib_uint64_t srv_start_lsn;
00102 UNIV_INTERN ib_uint64_t srv_shutdown_lsn;
00103 
00104 #ifdef HAVE_DARWIN_THREADS
00105 # include <sys/utsname.h>
00107 UNIV_INTERN ibool srv_have_fullfsync = FALSE;
00108 #endif
00109 
00111 UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE;
00112 
00115 UNIV_INTERN ibool srv_startup_is_before_trx_rollback_phase = FALSE;
00117 UNIV_INTERN ibool srv_is_being_started = FALSE;
00119 UNIV_INTERN ibool srv_was_started = FALSE;
00121 static ibool  srv_start_has_been_called = FALSE;
00122 
00125 UNIV_INTERN enum srv_shutdown_state srv_shutdown_state = SRV_SHUTDOWN_NONE;
00126 
00128 static os_file_t  files[1000];
00129 
00131 static ulint    n[SRV_MAX_N_IO_THREADS + 7];
00133 static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7];
00134 
00137 static os_fast_mutex_t  srv_os_test_mutex;
00138 
00140 static char*  srv_monitor_file_name;
00141 #endif /* !UNIV_HOTBACKUP */
00142 
00144 #define SRV_N_PENDING_IOS_PER_THREAD  OS_AIO_N_PENDING_IOS_PER_THREAD
00145 #define SRV_MAX_N_PENDING_SYNC_IOS  100
00146 
00147 #ifdef UNIV_PFS_THREAD
00148 /* Keys to register InnoDB threads with performance schema */
00149 UNIV_INTERN mysql_pfs_key_t io_handler_thread_key;
00150 UNIV_INTERN mysql_pfs_key_t srv_lock_timeout_thread_key;
00151 UNIV_INTERN mysql_pfs_key_t srv_error_monitor_thread_key;
00152 UNIV_INTERN mysql_pfs_key_t srv_monitor_thread_key;
00153 UNIV_INTERN mysql_pfs_key_t srv_master_thread_key;
00154 #endif /* UNIV_PFS_THREAD */
00155 
00156 /*********************************************************************/
00160 static
00161 char*
00162 srv_parse_megabytes(
00163 /*================*/
00164   char* str,  
00165   ulint*  megs) 
00166 {
00167   char* endp;
00168   ulint size;
00169 
00170   size = strtoul(str, &endp, 10);
00171 
00172   str = endp;
00173 
00174   switch (*str) {
00175   case 'G': case 'g':
00176     size *= 1024;
00177     /* fall through */
00178   case 'M': case 'm':
00179     str++;
00180     break;
00181   default:
00182     size /= 1024 * 1024;
00183     break;
00184   }
00185 
00186   *megs = size;
00187   return(str);
00188 }
00189 
00190 /*********************************************************************/
00194 UNIV_INTERN
00195 ibool
00196 srv_parse_data_file_paths_and_sizes(
00197 /*================================*/
00198   char* str)  
00199 {
00200   char* input_str;
00201   char* path;
00202   ulint size;
00203   ulint i = 0;
00204 
00205   srv_auto_extend_last_data_file = FALSE;
00206   srv_last_file_size_max = 0;
00207   srv_data_file_names = NULL;
00208   srv_data_file_sizes = NULL;
00209   srv_data_file_is_raw_partition = NULL;
00210 
00211   input_str = str;
00212 
00213   /* First calculate the number of data files and check syntax:
00214   path:size[M | G];path:size[M | G]... . Note that a Windows path may
00215   contain a drive name and a ':'. */
00216 
00217   while (*str != '\0') {
00218     path = str;
00219 
00220     while ((*str != ':' && *str != '\0')
00221            || (*str == ':'
00222          && (*(str + 1) == '\\' || *(str + 1) == '/'
00223              || *(str + 1) == ':'))) {
00224       str++;
00225     }
00226 
00227     if (*str == '\0') {
00228       return(FALSE);
00229     }
00230 
00231     str++;
00232 
00233     str = srv_parse_megabytes(str, &size);
00234 
00235     if (0 == strncmp(str, ":autoextend",
00236          (sizeof ":autoextend") - 1)) {
00237 
00238       str += (sizeof ":autoextend") - 1;
00239 
00240       if (0 == strncmp(str, ":max:",
00241            (sizeof ":max:") - 1)) {
00242 
00243         str += (sizeof ":max:") - 1;
00244 
00245         str = srv_parse_megabytes(str, &size);
00246       }
00247 
00248       if (*str != '\0') {
00249 
00250         return(FALSE);
00251       }
00252     }
00253 
00254     if (strlen(str) >= 6
00255         && *str == 'n'
00256         && *(str + 1) == 'e'
00257         && *(str + 2) == 'w') {
00258       str += 3;
00259     }
00260 
00261     if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
00262       str += 3;
00263     }
00264 
00265     if (size == 0) {
00266       return(FALSE);
00267     }
00268 
00269     i++;
00270 
00271     if (*str == ';') {
00272       str++;
00273     } else if (*str != '\0') {
00274 
00275       return(FALSE);
00276     }
00277   }
00278 
00279   if (i == 0) {
00280     /* If innodb_data_file_path was defined it must contain
00281     at least one data file definition */
00282 
00283     return(FALSE);
00284   }
00285 
00286         srv_data_file_names = static_cast<char **>(malloc(i * sizeof *srv_data_file_names));
00287         srv_data_file_sizes = static_cast<ulint *>(malloc(i * sizeof *srv_data_file_sizes));
00288         srv_data_file_is_raw_partition = static_cast<ulint *>(malloc(
00289                                                                      i * sizeof *srv_data_file_is_raw_partition));
00290 
00291   srv_n_data_files = i;
00292 
00293   /* Then store the actual values to our arrays */
00294 
00295   str = input_str;
00296   i = 0;
00297 
00298   while (*str != '\0') {
00299     path = str;
00300 
00301     /* Note that we must step over the ':' in a Windows path;
00302     a Windows path normally looks like C:\ibdata\ibdata1:1G, but
00303     a Windows raw partition may have a specification like
00304     \\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */
00305 
00306     while ((*str != ':' && *str != '\0')
00307            || (*str == ':'
00308          && (*(str + 1) == '\\' || *(str + 1) == '/'
00309              || *(str + 1) == ':'))) {
00310       str++;
00311     }
00312 
00313     if (*str == ':') {
00314       /* Make path a null-terminated string */
00315       *str = '\0';
00316       str++;
00317     }
00318 
00319     str = srv_parse_megabytes(str, &size);
00320 
00321     srv_data_file_names[i] = path;
00322     srv_data_file_sizes[i] = size;
00323 
00324     if (0 == strncmp(str, ":autoextend",
00325          (sizeof ":autoextend") - 1)) {
00326 
00327       srv_auto_extend_last_data_file = TRUE;
00328 
00329       str += (sizeof ":autoextend") - 1;
00330 
00331       if (0 == strncmp(str, ":max:",
00332            (sizeof ":max:") - 1)) {
00333 
00334         str += (sizeof ":max:") - 1;
00335 
00336         str = srv_parse_megabytes(
00337           str, &srv_last_file_size_max);
00338       }
00339 
00340       if (*str != '\0') {
00341 
00342         return(FALSE);
00343       }
00344     }
00345 
00346     (srv_data_file_is_raw_partition)[i] = 0;
00347 
00348     if (strlen(str) >= 6
00349         && *str == 'n'
00350         && *(str + 1) == 'e'
00351         && *(str + 2) == 'w') {
00352       str += 3;
00353       (srv_data_file_is_raw_partition)[i] = SRV_NEW_RAW;
00354     }
00355 
00356     if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
00357       str += 3;
00358 
00359       if ((srv_data_file_is_raw_partition)[i] == 0) {
00360         (srv_data_file_is_raw_partition)[i] = SRV_OLD_RAW;
00361       }
00362     }
00363 
00364     i++;
00365 
00366     if (*str == ';') {
00367       str++;
00368     }
00369   }
00370 
00371   return(TRUE);
00372 }
00373 
00374 /*********************************************************************/
00378 UNIV_INTERN
00379 ibool
00380 srv_parse_log_group_home_dirs(
00381 /*==========================*/
00382   char* str)  
00383 {
00384   char* input_str;
00385   char* path;
00386   ulint i = 0;
00387 
00388   srv_log_group_home_dirs = NULL;
00389 
00390   input_str = str;
00391 
00392   /* First calculate the number of directories and check syntax:
00393   path;path;... */
00394 
00395   while (*str != '\0') {
00396     path = str;
00397 
00398     while (*str != ';' && *str != '\0') {
00399       str++;
00400     }
00401 
00402     i++;
00403 
00404     if (*str == ';') {
00405       str++;
00406     } else if (*str != '\0') {
00407 
00408       return(FALSE);
00409     }
00410   }
00411 
00412   if (i != 1) {
00413     /* If innodb_log_group_home_dir was defined it must
00414     contain exactly one path definition under current MySQL */
00415 
00416     return(FALSE);
00417   }
00418 
00419         srv_log_group_home_dirs = static_cast<char **>(malloc(i * sizeof *srv_log_group_home_dirs));
00420 
00421   /* Then store the actual values to our array */
00422 
00423   str = input_str;
00424   i = 0;
00425 
00426   while (*str != '\0') {
00427     path = str;
00428 
00429     while (*str != ';' && *str != '\0') {
00430       str++;
00431     }
00432 
00433     if (*str == ';') {
00434       *str = '\0';
00435       str++;
00436     }
00437 
00438     srv_log_group_home_dirs[i] = path;
00439 
00440     i++;
00441   }
00442 
00443   return(TRUE);
00444 }
00445 
00446 /*********************************************************************/
00449 UNIV_INTERN
00450 void
00451 srv_free_paths_and_sizes(void)
00452 /*==========================*/
00453 {
00454   free(srv_data_file_names);
00455   srv_data_file_names = NULL;
00456   free(srv_data_file_sizes);
00457   srv_data_file_sizes = NULL;
00458   free(srv_data_file_is_raw_partition);
00459   srv_data_file_is_raw_partition = NULL;
00460   free(srv_log_group_home_dirs);
00461   srv_log_group_home_dirs = NULL;
00462 }
00463 
00464 #ifndef UNIV_HOTBACKUP
00465 /********************************************************************/
00468 extern "C"
00469 os_thread_ret_t
00470 io_handler_thread(void* arg);
00471 
00472 extern "C"
00473 os_thread_ret_t
00474 io_handler_thread(
00475 /*==============*/
00476   void* arg)  
00478 {
00479   ulint segment;
00480 
00481   segment = *((ulint*)arg);
00482 
00483 #ifdef UNIV_DEBUG_THREAD_CREATION
00484   fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment,
00485     os_thread_pf(os_thread_get_curr_id()));
00486 #endif
00487 
00488 #ifdef UNIV_PFS_THREAD
00489   pfs_register_thread(io_handler_thread_key);
00490 #endif /* UNIV_PFS_THREAD */
00491 
00492   while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
00493     fil_aio_wait(segment);
00494   }
00495 
00496   /* We count the number of threads in os_thread_exit(). A created
00497   thread should always use that to exit and not use return() to exit.
00498   The thread actually never comes here because it is exited in an
00499   os_event_wait(). */
00500   return 0;
00501 }
00502 #endif /* !UNIV_HOTBACKUP */
00503 
00504 #ifdef __WIN__
00505 #define SRV_PATH_SEPARATOR  '\\'
00506 #else
00507 #define SRV_PATH_SEPARATOR  '/'
00508 #endif
00509 
00510 /*********************************************************************/
00512 UNIV_INTERN
00513 void
00514 srv_normalize_path_for_win(
00515 /*=======================*/
00516   char* /*str __attribute__((unused))*/)  
00518 {
00519 #ifdef __WIN__
00520   for (; *str; str++) {
00521 
00522     if (*str == '/') {
00523       *str = '\\';
00524     }
00525   }
00526 #endif
00527 }
00528 
00529 #ifndef UNIV_HOTBACKUP
00530 /*********************************************************************/
00534 static
00535 ulint
00536 srv_calc_low32(
00537 /*===========*/
00538   ulint file_size)  
00539 {
00540   return(0xFFFFFFFFUL & (file_size << UNIV_PAGE_SIZE_SHIFT));
00541 }
00542 
00543 /*********************************************************************/
00547 static
00548 ulint
00549 srv_calc_high32(
00550 /*============*/
00551   ulint file_size)  
00552 {
00553   return(file_size >> (32 - UNIV_PAGE_SIZE_SHIFT));
00554 }
00555 
00556 /*********************************************************************/
00559 ulint
00560 open_or_create_log_file(
00561 /*====================*/
00562   ibool create_new_db,    
00564   ibool*  log_file_created, 
00566   ibool log_file_has_been_opened,
00569   ulint k,      
00570   ulint i)      
00571 {
00572   ibool ret;
00573   ulint size;
00574   ulint size_high;
00575   char  name[10000];
00576   ulint dirnamelen;
00577 
00578   UT_NOT_USED(create_new_db);
00579 
00580   *log_file_created = FALSE;
00581 
00582   srv_normalize_path_for_win(srv_log_group_home_dirs[k]);
00583 
00584   dirnamelen = strlen(srv_log_group_home_dirs[k]);
00585   ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile");
00586   memcpy(name, srv_log_group_home_dirs[k], dirnamelen);
00587 
00588   /* Add a path separator if needed. */
00589   if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
00590     name[dirnamelen++] = SRV_PATH_SEPARATOR;
00591   }
00592 
00593   sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i);
00594 
00595   files[i] = os_file_create(innodb_file_log_key, name,
00596           OS_FILE_CREATE, OS_FILE_NORMAL,
00597           OS_LOG_FILE, &ret);
00598   if (ret == FALSE) {
00599     if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS
00600 #ifdef UNIV_AIX
00601         /* AIX 5.1 after security patch ML7 may have errno set
00602         to 0 here, which causes our function to return 100;
00603         work around that AIX problem */
00604         && os_file_get_last_error(FALSE) != 100
00605 #endif
00606         ) {
00607                   drizzled::errmsg_printf(drizzled::error::ERROR,
00608                                           "InnoDB: Error in creating or opening %s", name);
00609 
00610                   return(DB_ERROR);
00611     }
00612 
00613     files[i] = os_file_create(innodb_file_log_key, name,
00614             OS_FILE_OPEN, OS_FILE_AIO,
00615             OS_LOG_FILE, &ret);
00616     if (!ret) {
00617                   drizzled::errmsg_printf(drizzled::error::ERROR,
00618                                           "InnoDB: Error in opening %s.", name);
00619 
00620       return(DB_ERROR);
00621     }
00622 
00623     ret = os_file_get_size(files[i], &size, &size_high);
00624     ut_a(ret);
00625 
00626     if (size != srv_calc_low32(srv_log_file_size)
00627         || size_high != srv_calc_high32(srv_log_file_size)) {
00628 
00629                   drizzled::errmsg_printf(drizzled::error::ERROR,
00630                                           "InnoDB: Error: log file %s is of different size %lu %lu bytes than specified in the .cnf"
00631                                           " file %lu %lu bytes!",
00632                                           name, (ulong) size_high, (ulong) size,
00633                                           (ulong) srv_calc_high32(srv_log_file_size),
00634                                           (ulong) srv_calc_low32(srv_log_file_size));
00635 
00636       return(DB_ERROR);
00637     }
00638   } else {
00639     *log_file_created = TRUE;
00640 
00641                 drizzled::errmsg_printf(drizzled::error::INFO,
00642                                         "InnoDB: Log file %s did not exist: new to be created",
00643                                         name);
00644     if (log_file_has_been_opened) {
00645 
00646       return(DB_ERROR);
00647     }
00648 
00649                 drizzled::errmsg_printf(drizzled::error::INFO,
00650                                         "InnoDB: Setting log file %s size to %lu MB",
00651                                         name, (ulong) srv_log_file_size
00652                                         >> (20 - UNIV_PAGE_SIZE_SHIFT));
00653 
00654                 drizzled::errmsg_printf(drizzled::error::INFO,
00655                                         "InnoDB: Database physically writes the file full: wait...\n");
00656 
00657     ret = os_file_set_size(name, files[i],
00658                srv_calc_low32(srv_log_file_size),
00659                srv_calc_high32(srv_log_file_size));
00660     if (!ret) {
00661                   drizzled::errmsg_printf(drizzled::error::ERROR,
00662                                           "InnoDB: Error in creating %s: probably out of disk space",
00663                                           name);
00664 
00665       return(DB_ERROR);
00666     }
00667   }
00668 
00669   ret = os_file_close(files[i]);
00670   ut_a(ret);
00671 
00672   if (i == 0) {
00673     /* Create in memory the file space object
00674     which is for this log group */
00675 
00676     fil_space_create(name,
00677          2 * k + SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG);
00678   }
00679 
00680   ut_a(fil_validate());
00681 
00682   fil_node_create(name, srv_log_file_size,
00683       2 * k + SRV_LOG_SPACE_FIRST_ID, FALSE);
00684 #ifdef UNIV_LOG_ARCHIVE
00685   /* If this is the first log group, create the file space object
00686   for archived logs.
00687   Under MySQL, no archiving ever done. */
00688 
00689   if (k == 0 && i == 0) {
00690     arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
00691 
00692     fil_space_create("arch_log_space", arch_space_id, 0, FIL_LOG);
00693   } else {
00694     arch_space_id = ULINT_UNDEFINED;
00695   }
00696 #endif /* UNIV_LOG_ARCHIVE */
00697   if (i == 0) {
00698     log_group_init(k, srv_n_log_files,
00699              srv_log_file_size * UNIV_PAGE_SIZE,
00700              2 * k + SRV_LOG_SPACE_FIRST_ID,
00701              SRV_LOG_SPACE_FIRST_ID + 1); /* dummy arch
00702                   space id */
00703   }
00704 
00705   return(DB_SUCCESS);
00706 }
00707 
00708 /*********************************************************************/
00711 ulint
00712 open_or_create_data_files(
00713 /*======================*/
00714   ibool*    create_new_db,  
00716 #ifdef UNIV_LOG_ARCHIVE
00717   ulint*    min_arch_log_no,
00719   ulint*    max_arch_log_no,
00721 #endif /* UNIV_LOG_ARCHIVE */
00722   ib_uint64_t*  min_flushed_lsn,
00724   ib_uint64_t*  max_flushed_lsn,
00726   ulint*    sum_of_new_sizes)
00728 {
00729   ibool ret;
00730   ulint i;
00731   ibool one_opened  = FALSE;
00732   ibool one_created = FALSE;
00733   ulint size;
00734   ulint size_high;
00735   ulint rounded_size_pages;
00736   char  name[10000];
00737 
00738   if (srv_n_data_files >= 1000) {
00739           drizzled::errmsg_printf(drizzled::error::ERROR,
00740                                   "InnoDB: can only have < 1000 data files you have defined %lu",
00741                                   (ulong) srv_n_data_files);
00742     return(DB_ERROR);
00743   }
00744 
00745   *sum_of_new_sizes = 0;
00746 
00747   *create_new_db = FALSE;
00748 
00749   srv_normalize_path_for_win(srv_data_home);
00750 
00751   for (i = 0; i < srv_n_data_files; i++) {
00752     ulint dirnamelen;
00753 
00754     srv_normalize_path_for_win(srv_data_file_names[i]);
00755     dirnamelen = strlen(srv_data_home);
00756 
00757     ut_a(dirnamelen + strlen(srv_data_file_names[i])
00758          < (sizeof name) - 1);
00759     memcpy(name, srv_data_home, dirnamelen);
00760     /* Add a path separator if needed. */
00761     if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
00762       name[dirnamelen++] = SRV_PATH_SEPARATOR;
00763     }
00764 
00765     strcpy(name + dirnamelen, srv_data_file_names[i]);
00766 
00767     if (srv_data_file_is_raw_partition[i] == 0) {
00768 
00769       /* First we try to create the file: if it already
00770       exists, ret will get value FALSE */
00771 
00772       files[i] = os_file_create(innodb_file_data_key,
00773               name, OS_FILE_CREATE,
00774               OS_FILE_NORMAL,
00775               OS_DATA_FILE, &ret);
00776 
00777       if (ret == FALSE && os_file_get_last_error(FALSE)
00778           != OS_FILE_ALREADY_EXISTS
00779 #ifdef UNIV_AIX
00780           /* AIX 5.1 after security patch ML7 may have
00781           errno set to 0 here, which causes our function
00782           to return 100; work around that AIX problem */
00783           && os_file_get_last_error(FALSE) != 100
00784 #endif
00785           ) {
00786                           drizzled::errmsg_printf(drizzled::error::ERROR,
00787                                                   "InnoDB: Error in creating or opening %s",
00788                                                   name);
00789 
00790         return(DB_ERROR);
00791       }
00792     } else if (srv_data_file_is_raw_partition[i] == SRV_NEW_RAW) {
00793       /* The partition is opened, not created; then it is
00794       written over */
00795 
00796       srv_start_raw_disk_in_use = TRUE;
00797       srv_created_new_raw = TRUE;
00798 
00799       files[i] = os_file_create(innodb_file_data_key,
00800               name, OS_FILE_OPEN_RAW,
00801               OS_FILE_NORMAL,
00802               OS_DATA_FILE, &ret);
00803       if (!ret) {
00804                           drizzled::errmsg_printf(drizzled::error::ERROR,
00805                                                   "InnoDB: Error in opening %s", name);
00806 
00807         return(DB_ERROR);
00808       }
00809     } else if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
00810       srv_start_raw_disk_in_use = TRUE;
00811 
00812       ret = FALSE;
00813     } else {
00814       ut_a(0);
00815     }
00816 
00817     if (ret == FALSE) {
00818       /* We open the data file */
00819 
00820       if (one_created) {
00821                           drizzled::errmsg_printf(drizzled::error::ERROR,
00822           "InnoDB: Error: data files can only be added at the end of a tablespace, but"
00823                                         " data file %s existed beforehand.",
00824                                         name);
00825         return(DB_ERROR);
00826       }
00827 
00828       if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
00829         files[i] = os_file_create(
00830           innodb_file_data_key,
00831           name, OS_FILE_OPEN_RAW,
00832           OS_FILE_NORMAL, OS_DATA_FILE, &ret);
00833       } else if (i == 0) {
00834         files[i] = os_file_create(
00835           innodb_file_data_key,
00836           name, OS_FILE_OPEN_RETRY,
00837           OS_FILE_NORMAL, OS_DATA_FILE, &ret);
00838       } else {
00839         files[i] = os_file_create(
00840           innodb_file_data_key,
00841           name, OS_FILE_OPEN, OS_FILE_NORMAL,
00842           OS_DATA_FILE, &ret);
00843       }
00844 
00845       if (!ret) {
00846                           drizzled::errmsg_printf(drizzled::error::ERROR,
00847                                                   "InnoDB: Error in opening %s", name);
00848         os_file_get_last_error(TRUE);
00849 
00850         return(DB_ERROR);
00851       }
00852 
00853       if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
00854 
00855         goto skip_size_check;
00856       }
00857 
00858       ret = os_file_get_size(files[i], &size, &size_high);
00859       ut_a(ret);
00860       /* Round size downward to megabytes */
00861 
00862       rounded_size_pages
00863         = (size / (1024 * 1024) + 4096 * size_high)
00864           << (20 - UNIV_PAGE_SIZE_SHIFT);
00865 
00866       if (i == srv_n_data_files - 1
00867           && srv_auto_extend_last_data_file) {
00868 
00869         if (srv_data_file_sizes[i] > rounded_size_pages
00870             || (srv_last_file_size_max > 0
00871           && srv_last_file_size_max
00872           < rounded_size_pages)) {
00873 
00874                                   drizzled::errmsg_printf(drizzled::error::ERROR,
00875                                                           "InnoDB: Error: auto-extending data file %s is of a different size. "
00876                                                           "%lu pages (rounded down to MB) than specified in the .cnf file: "
00877                                                           "initial %lu pages, max %lu (relevant if non-zero) pages!",
00878                                                           name,
00879                                                           (ulong) rounded_size_pages,
00880                                                           (ulong) srv_data_file_sizes[i],
00881                                                           (ulong)
00882                                                           srv_last_file_size_max);
00883 
00884           return(DB_ERROR);
00885         }
00886 
00887         srv_data_file_sizes[i] = rounded_size_pages;
00888       }
00889 
00890       if (rounded_size_pages != srv_data_file_sizes[i]) {
00891 
00892                           drizzled::errmsg_printf(drizzled::error::ERROR,
00893           "InnoDB: Error: data file %s is of a different size. "
00894           "%lu pages (rounded down to MB). "
00895           "Than specified in the .cnf file %lu pages!",
00896           name,
00897           (ulong) rounded_size_pages,
00898           (ulong) srv_data_file_sizes[i]);
00899 
00900         return(DB_ERROR);
00901       }
00902 skip_size_check:
00903       fil_read_flushed_lsn_and_arch_log_no(
00904         files[i], one_opened,
00905 #ifdef UNIV_LOG_ARCHIVE
00906         min_arch_log_no, max_arch_log_no,
00907 #endif /* UNIV_LOG_ARCHIVE */
00908         min_flushed_lsn, max_flushed_lsn);
00909       one_opened = TRUE;
00910     } else {
00911       /* We created the data file and now write it full of
00912       zeros */
00913 
00914       one_created = TRUE;
00915 
00916       if (i > 0) {
00917                                 drizzled::errmsg_printf(drizzled::error::INFO,
00918           "  InnoDB: Data file %s did not exist: new to be created",
00919           name);
00920       } else {
00921                           drizzled::errmsg_printf(drizzled::error::INFO,
00922           "InnoDB: The first specified data file %s did not exist. A new database to be created!", name);
00923         *create_new_db = TRUE;
00924       }
00925 
00926                         drizzled::errmsg_printf(drizzled::error::INFO,
00927                                                 "  InnoDB: Setting file %s size to %lu MB",
00928                                                 name, (ulong) (srv_data_file_sizes[i]
00929                                                          >> (20 - UNIV_PAGE_SIZE_SHIFT)));
00930 
00931                         drizzled::errmsg_printf(drizzled::error::INFO,
00932         "InnoDB: Database physically writes the file full: wait...");
00933 
00934       ret = os_file_set_size(
00935         name, files[i],
00936         srv_calc_low32(srv_data_file_sizes[i]),
00937         srv_calc_high32(srv_data_file_sizes[i]));
00938 
00939       if (!ret) {
00940                           drizzled::errmsg_printf(drizzled::error::ERROR,
00941                                                   "InnoDB: Error in creating %s: probably out of disk space", name);
00942 
00943         return(DB_ERROR);
00944       }
00945 
00946       *sum_of_new_sizes = *sum_of_new_sizes
00947         + srv_data_file_sizes[i];
00948     }
00949 
00950     ret = os_file_close(files[i]);
00951     ut_a(ret);
00952 
00953     if (i == 0) {
00954       fil_space_create(name, 0, 0, FIL_TABLESPACE);
00955     }
00956 
00957     ut_a(fil_validate());
00958 
00959     fil_node_create(name, srv_data_file_sizes[i], 0,
00960         srv_data_file_is_raw_partition[i] != 0);
00961   }
00962 
00963   return(DB_SUCCESS);
00964 }
00965 
00966 /********************************************************************
00967 Starts InnoDB and creates a new database if database files
00968 are not found and the user wants.
00969 @return DB_SUCCESS or error code */
00970 UNIV_INTERN
00971 int
00972 innobase_start_or_create_for_mysql(void)
00973 /*====================================*/
00974 {
00975   ibool   create_new_db;
00976   ibool   log_file_created;
00977   ibool   log_created = FALSE;
00978   ibool   log_opened  = FALSE;
00979   ib_uint64_t min_flushed_lsn;
00980   ib_uint64_t max_flushed_lsn;
00981 #ifdef UNIV_LOG_ARCHIVE
00982   ulint   min_arch_log_no;
00983   ulint   max_arch_log_no;
00984 #endif /* UNIV_LOG_ARCHIVE */
00985   ulint   sum_of_new_sizes;
00986   ulint   sum_of_data_file_sizes;
00987   ulint   tablespace_size_in_header;
00988   ulint   err;
00989   ulint   i;
00990   ulint   io_limit;
00991   my_bool   srv_file_per_table_original_value
00992     = srv_file_per_table;
00993   mtr_t   mtr;
00994 #ifdef HAVE_DARWIN_THREADS
00995 # ifdef F_FULLFSYNC
00996   /* This executable has been compiled on Mac OS X 10.3 or later.
00997   Assume that F_FULLFSYNC is available at run-time. */
00998   srv_have_fullfsync = TRUE;
00999 # else /* F_FULLFSYNC */
01000   /* This executable has been compiled on Mac OS X 10.2
01001   or earlier.  Determine if the executable is running
01002   on Mac OS X 10.3 or later. */
01003   struct utsname utsname;
01004   if (uname(&utsname)) {
01005     fputs(_("InnoDB: cannot determine Mac OS X version!\n"), stderr);
01006   } else {
01007     srv_have_fullfsync = strcmp(utsname.release, "7.") >= 0;
01008   }
01009   if (!srv_have_fullfsync) {
01010     fputs(_("InnoDB: On Mac OS X, fsync() may be"
01011                         " broken on internal drives,\n"
01012                         "InnoDB: making transactions unsafe!\n"), stderr);
01013   }
01014 # endif /* F_FULLFSYNC */
01015 #endif /* HAVE_DARWIN_THREADS */
01016 
01017   if (sizeof(ulint) != sizeof(void*)) {
01018           drizzled::errmsg_printf(drizzled::error::WARN,
01019       _("InnoDB: Error: size of InnoDB's ulint is %lu, but size of void* is %lu. "
01020                           "The sizes should be the same so that on a 64-bit platform you can. Allocate more than 4 GB of memory."),
01021       (ulong)sizeof(ulint), (ulong)sizeof(void*));
01022   }
01023 
01024   /* System tables are created in tablespace 0.  Thus, we must
01025   temporarily clear srv_file_per_table.  This is ok, because the
01026   server will not accept connections (which could modify
01027   innodb_file_per_table) until this function has returned. */
01028   srv_file_per_table = FALSE;
01029 #ifdef UNIV_DEBUG
01030         drizzled::errmsg_printf(drizzled::error::INFO,
01031                                 _("InnoDB: !!!!!!!! UNIV_DEBUG switched on !!!!!!!!!\n"));
01032 #endif
01033 
01034 #ifdef UNIV_IBUF_DEBUG
01035         drizzled::errmsg_printf(drizzled::error::INFO,
01036     _("InnoDB: !!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!\n"
01037 # ifdef UNIV_IBUF_COUNT_DEBUG
01038                   "InnoDB: !!!!!!!! UNIV_IBUF_COUNT_DEBUG switched on !!!!!!!!!\n"
01039                   "InnoDB: Crash recovery will fail with UNIV_IBUF_COUNT_DEBUG\n"
01040 # endif
01041     ));
01042 #endif
01043 
01044 #ifdef UNIV_SYNC_DEBUG
01045         drizzled::errmsg_printf(drizzled::error::INFO,
01046                                 _("InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n"));
01047 #endif
01048 
01049 #ifdef UNIV_SEARCH_DEBUG
01050         drizzled::errmsg_printf(drizzled::error::INFO,
01051                                 _("InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!\n"));
01052 #endif
01053 
01054 #ifdef UNIV_LOG_LSN_DEBUG
01055         drizzled::errmsg_printf(drizzled::error::INFO,
01056                                 _("InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!\n"));
01057 #endif /* UNIV_LOG_LSN_DEBUG */
01058 #ifdef UNIV_MEM_DEBUG
01059         drizzled::errmsg_printf(drizzled::error::INFO,
01060                                 _("InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n"));
01061 #endif
01062 
01063   if (UNIV_LIKELY(srv_use_sys_malloc))
01064         {
01065           drizzled::errmsg_printf(drizzled::error::INFO, _("InnoDB: The InnoDB memory heap is disabled\n"));
01066   }
01067 
01068         drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: " IB_ATOMICS_STARTUP_MSG
01069                 "\nInnoDB: Compressed tables use zlib " ZLIB_VERSION
01070 #ifdef UNIV_ZIP_DEBUG
01071         " with validation"
01072 #endif /* UNIV_ZIP_DEBUG */
01073 #ifdef UNIV_ZIP_COPY
01074         " and extra copying"
01075 #endif /* UNIV_ZIP_COPY */
01076         " ");
01077 
01078 
01079   /* Since InnoDB does not currently clean up all its internal data
01080   structures in MySQL Embedded Server Library server_end(), we
01081   print an error message if someone tries to start up InnoDB a
01082   second time during the process lifetime. */
01083 
01084   if (srv_start_has_been_called) {
01085           drizzled::errmsg_printf(drizzled::error::ERROR,
01086       "InnoDB: Error: startup called second time during the process lifetime.\n");
01087   }
01088 
01089   srv_start_has_been_called = TRUE;
01090 
01091 #ifdef UNIV_DEBUG
01092   log_do_write = TRUE;
01093 #endif /* UNIV_DEBUG */
01094   /*  yydebug = TRUE; */
01095 
01096   srv_is_being_started = TRUE;
01097   srv_startup_is_before_trx_rollback_phase = TRUE;
01098 
01099 #ifdef __WIN__
01100   switch (os_get_os_version()) {
01101   case OS_WIN95:
01102   case OS_WIN31:
01103   case OS_WINNT:
01104     /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
01105     and NT use simulated aio. In NT Windows provides async i/o,
01106     but when run in conjunction with InnoDB Hot Backup, it seemed
01107     to corrupt the data files. */
01108 
01109     srv_use_native_aio = FALSE;
01110     break;
01111 
01112   case OS_WIN2000:
01113   case OS_WINXP:
01114     /* On 2000 and XP, async IO is available. */
01115     srv_use_native_aio = TRUE;
01116     break;
01117 
01118   default:
01119     /* Vista and later have both async IO and condition variables */
01120     srv_use_native_aio = TRUE;
01121     srv_use_native_conditions = TRUE;
01122     break;
01123   }
01124 
01125 #elif defined(LINUX_NATIVE_AIO)
01126 
01127   if (srv_use_native_aio) {
01128                 drizzled::errmsg_printf(drizzled::error::INFO,
01129                                         _("InnoDB: Using Linux native AIO"));
01130   }
01131 #else
01132   /* Currently native AIO is supported only on windows and linux
01133   and that also when the support is compiled in. In all other
01134   cases, we ignore the setting of innodb_use_native_aio. */
01135   srv_use_native_aio = FALSE;
01136 
01137 #endif
01138 
01139   if (srv_file_flush_method_str == NULL) {
01140     /* These are the default options */
01141 
01142     srv_unix_file_flush_method = SRV_UNIX_FSYNC;
01143 
01144     srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
01145 #ifndef __WIN__
01146   } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
01147     srv_unix_file_flush_method = SRV_UNIX_FSYNC;
01148 
01149   } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
01150     srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
01151 
01152   } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
01153     srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
01154 
01155   } else if (0 == ut_strcmp(srv_file_flush_method_str, "ALL_O_DIRECT")) {
01156     srv_unix_file_flush_method = SRV_UNIX_ALL_O_DIRECT;
01157 
01158   } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
01159     srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
01160 
01161   } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
01162     srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
01163 #else
01164   } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
01165     srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
01166     srv_use_native_aio = FALSE;
01167 
01168   } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
01169     srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
01170     srv_use_native_aio = FALSE;
01171 
01172   } else if (0 == ut_strcmp(srv_file_flush_method_str,
01173           "async_unbuffered")) {
01174     srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
01175 #endif
01176   } else {
01177           drizzled::errmsg_printf(drizzled::error::ERROR,
01178                                   "InnoDB: Unrecognized value %s for innodb_flush_method",
01179                                   srv_file_flush_method_str);
01180     return(DB_ERROR);
01181   }
01182 
01183   /* Note that the call srv_boot() also changes the values of
01184   some variables to the units used by InnoDB internally */
01185 
01186   /* Set the maximum number of threads which can wait for a semaphore
01187   inside InnoDB: this is the 'sync wait array' size, as well as the
01188   maximum number of threads that can wait in the 'srv_conc array' for
01189   their time to enter InnoDB. */
01190 
01191   if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
01192     /* If buffer pool is less than 1000 MB,
01193     assume fewer threads. Also use only one
01194     buffer pool instance */
01195     srv_max_n_threads = 50000;
01196 
01197   } else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
01198 
01199     srv_buf_pool_instances = 1;
01200     srv_max_n_threads = 10000;
01201   } else {
01202     srv_buf_pool_instances = 1;
01203     srv_max_n_threads = 1000; /* saves several MB of memory,
01204             especially in 64-bit
01205             computers */
01206   }
01207 
01208   err = srv_boot();
01209 
01210   if (err != DB_SUCCESS) {
01211 
01212     return((int) err);
01213   }
01214 
01215   mutex_create(srv_monitor_file_mutex_key,
01216          &srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
01217 
01218   if (srv_innodb_status) {
01219           srv_monitor_file_name = static_cast<char *>(mem_alloc(
01220       strlen(fil_path_to_mysql_datadir)
01221                         + 20 + sizeof "/innodb_status."));
01222     sprintf(srv_monitor_file_name, "%s/innodb_status.%lu",
01223       fil_path_to_mysql_datadir, os_proc_get_number());
01224     srv_monitor_file = fopen(srv_monitor_file_name, "w+");
01225     if (!srv_monitor_file) {
01226                   drizzled::errmsg_printf(drizzled::error::ERROR,
01227                                           "InnoDB: unable to create %s: %s\n", srv_monitor_file_name, strerror(errno));
01228       return(DB_ERROR);
01229     }
01230   } else {
01231     srv_monitor_file_name = NULL;
01232     srv_monitor_file = os_file_create_tmpfile();
01233     if (!srv_monitor_file) {
01234       return(DB_ERROR);
01235     }
01236   }
01237 
01238   mutex_create(srv_dict_tmpfile_mutex_key,
01239          &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
01240 
01241   srv_dict_tmpfile = os_file_create_tmpfile();
01242   if (!srv_dict_tmpfile) {
01243     return(DB_ERROR);
01244   }
01245 
01246   mutex_create(srv_misc_tmpfile_mutex_key,
01247          &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
01248 
01249   srv_misc_tmpfile = os_file_create_tmpfile();
01250   if (!srv_misc_tmpfile) {
01251     return(DB_ERROR);
01252   }
01253 
01254   /* innodb_file_io_threads used to be user settable.
01255            It is now just a combination of read_io_threads and
01256            write_io_threads that is set by innodb internally. */
01257 
01258   /* Now overwrite the value on srv_n_file_io_threads */
01259   srv_n_file_io_threads = 2 + srv_n_read_io_threads
01260         + srv_n_write_io_threads;
01261 
01262   ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS);
01263 
01264   /* TODO: Investigate if SRV_N_PENDING_IOS_PER_THREAD (32) limit
01265   still applies to windows. */
01266   if (!srv_use_native_aio) {
01267     io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD;
01268   } else {
01269     io_limit = SRV_N_PENDING_IOS_PER_THREAD;
01270   }
01271 
01272   os_aio_init(io_limit,
01273         srv_n_read_io_threads,
01274         srv_n_write_io_threads,
01275         SRV_MAX_N_PENDING_SYNC_IOS);
01276 
01277   fil_init(srv_file_per_table ? 50000 : 5000,
01278      srv_max_n_open_files);
01279 
01280   /* Print time to initialize the buffer pool */
01281 
01282   if (srv_buf_pool_size >= 1024 * 1024 * 1024) {
01283           drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Initializing buffer pool, size = %.1fG",
01284                                   ((double) srv_buf_pool_size) / (1024 * 1024 * 1024));
01285   } else {
01286           drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Initializing buffer pool, size = %.1fM",
01287                                   ((double) srv_buf_pool_size) / (1024 * 1024));
01288   }
01289 
01290   err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
01291 
01292         drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Completed initialization of buffer pool");
01293 
01294   if (err != DB_SUCCESS) {
01295           drizzled::errmsg_printf(drizzled::error::ERROR, "InnoDB: Fatal error: cannot allocate the memory for the buffer pool");
01296 
01297           return(DB_ERROR);
01298   }
01299 
01300 #ifdef UNIV_DEBUG
01301   /* We have observed deadlocks with a 5MB buffer pool but
01302   the actual lower limit could very well be a little higher. */
01303 
01304   if (srv_buf_pool_size <= 5 * 1024 * 1024) {
01305 
01306           drizzled::errmsg_printf(drizzled::error::WARN, "InnoDB: Warning: Small buffer pool size "
01307                                   "(%luM), the flst_validate() debug function "
01308                                   "can cause a deadlock if the buffer pool fills up.\n",
01309                                   srv_buf_pool_size / 1024 / 1024);
01310   }
01311 #endif
01312 
01313   fsp_init();
01314   log_init();
01315 
01316   lock_sys_create(srv_lock_table_size);
01317 
01318   /* Create i/o-handler threads: */
01319 
01320   for (i = 0; i < srv_n_file_io_threads; i++) {
01321     n[i] = i;
01322 
01323     os_thread_create(io_handler_thread, n + i, thread_ids + i);
01324   }
01325 
01326 #ifdef UNIV_LOG_ARCHIVE
01327   if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) {
01328           drizzled::errmsg_printf(drizzled::error::ERROR,
01329                                   "InnoDB: Error: you must set the log group home dir in my.cnf the same as log arch dir.");
01330 
01331     return(DB_ERROR);
01332   }
01333 #endif /* UNIV_LOG_ARCHIVE */
01334 
01335   if (sizeof(ulint) == 4
01336       && srv_n_log_files * srv_log_file_size
01337       >= (1UL << (32 - UNIV_PAGE_SIZE_SHIFT))) {
01338     drizzled::errmsg_printf(drizzled::error::ERROR,
01339           "InnoDB: Error: combined size of log files must be < 4 GB on 32-bit systems\n");
01340 
01341     return(DB_ERROR);
01342   }
01343 
01344   sum_of_new_sizes = 0;
01345 
01346   for (i = 0; i < srv_n_data_files; i++) {
01347 #ifndef __WIN__
01348     if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= (1UL << (32 - UNIV_PAGE_SIZE_SHIFT))) {
01349                   drizzled::errmsg_printf(drizzled::error::ERROR,
01350                                           "InnoDB: Error: file size must be < 4 GB with this MySQL binary and operating system combination,"
01351                                           " in some OS's < 2 GB\n");
01352 
01353       return(DB_ERROR);
01354     }
01355 #endif
01356     sum_of_new_sizes += srv_data_file_sizes[i];
01357   }
01358 
01359   if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) {
01360           drizzled::errmsg_printf(drizzled::error::ERROR, "InnoDB: Error: tablespace size must be at least 10 MB");
01361 
01362     return(DB_ERROR);
01363   }
01364 
01365   err = open_or_create_data_files(&create_new_db,
01366 #ifdef UNIV_LOG_ARCHIVE
01367           &min_arch_log_no, &max_arch_log_no,
01368 #endif /* UNIV_LOG_ARCHIVE */
01369           &min_flushed_lsn, &max_flushed_lsn,
01370           &sum_of_new_sizes);
01371   if (err != DB_SUCCESS) {
01372           drizzled::errmsg_printf(drizzled::error::ERROR,
01373                                   "InnoDB: Could not open or create data files.\n"
01374                                   "InnoDB: If you tried to add new data files, and it failed here,\n"
01375                                   "InnoDB: you should now edit innodb_data_file_path in my.cnf back\n"
01376                                   "InnoDB: to what it was, and remove the new ibdata files InnoDB created\n"
01377                                   "InnoDB: in this failed attempt. InnoDB only wrote those files full of\n"
01378                                   "InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n"
01379                                   "InnoDB: remove old data files which contain your precious data!\n");
01380 
01381     return((int) err);
01382   }
01383 
01384 #ifdef UNIV_LOG_ARCHIVE
01385   srv_normalize_path_for_win(srv_arch_dir);
01386   srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir);
01387 #endif /* UNIV_LOG_ARCHIVE */
01388 
01389   for (i = 0; i < srv_n_log_files; i++) {
01390     err = open_or_create_log_file(create_new_db, &log_file_created,
01391                 log_opened, 0, i);
01392     if (err != DB_SUCCESS) {
01393 
01394       return((int) err);
01395     }
01396 
01397     if (log_file_created) {
01398       log_created = TRUE;
01399     } else {
01400       log_opened = TRUE;
01401     }
01402     if ((log_opened && create_new_db)
01403         || (log_opened && log_created)) {
01404                   drizzled::errmsg_printf(drizzled::error::ERROR,
01405         "InnoDB: Error: all log files must be created at the same time.\n"
01406         "InnoDB: All log files must be created also in database creation.\n"
01407         "InnoDB: If you want bigger or smaller log files, shut down the\n"
01408         "InnoDB: database and make sure there were no errors in shutdown.\n"
01409         "InnoDB: Then delete the existing log files. Edit the .cnf file\n"
01410         "InnoDB: and start the database again.\n");
01411 
01412       return(DB_ERROR);
01413     }
01414   }
01415 
01416   /* Open all log files and data files in the system tablespace: we
01417   keep them open until database shutdown */
01418 
01419   fil_open_log_and_system_tablespace_files();
01420 
01421   if (log_created && !create_new_db
01422 #ifdef UNIV_LOG_ARCHIVE
01423       && !srv_archive_recovery
01424 #endif /* UNIV_LOG_ARCHIVE */
01425       ) {
01426     if (max_flushed_lsn != min_flushed_lsn
01427 #ifdef UNIV_LOG_ARCHIVE
01428         || max_arch_log_no != min_arch_log_no
01429 #endif /* UNIV_LOG_ARCHIVE */
01430         ) {
01431                   drizzled::errmsg_printf(drizzled::error::ERROR,
01432         "InnoDB: Cannot initialize created log files because\n"
01433         "InnoDB: data files were not in sync with each other\n"
01434         "InnoDB: or the data files are corrupt.\n");
01435 
01436       return(DB_ERROR);
01437     }
01438 
01439     if (max_flushed_lsn < (ib_uint64_t) 1000) {
01440                   drizzled::errmsg_printf(drizzled::error::ERROR,
01441         "InnoDB: Cannot initialize created log files because\n"
01442         "InnoDB: data files are corrupt, or new data files were\n"
01443         "InnoDB: created when the database was started previous\n"
01444         "InnoDB: time but the database was not shut down\n"
01445                                 "InnoDB: normally after that.\n");
01446 
01447       return(DB_ERROR);
01448     }
01449 
01450     mutex_enter(&(log_sys->mutex));
01451 
01452 #ifdef UNIV_LOG_ARCHIVE
01453     /* Do not + 1 arch_log_no because we do not use log
01454     archiving */
01455     recv_reset_logs(max_flushed_lsn, max_arch_log_no, TRUE);
01456 #else
01457     recv_reset_logs(max_flushed_lsn, TRUE);
01458 #endif /* UNIV_LOG_ARCHIVE */
01459 
01460     mutex_exit(&(log_sys->mutex));
01461   }
01462 
01463   trx_sys_file_format_init();
01464 
01465   if (create_new_db) {
01466     mtr_start(&mtr);
01467 
01468     fsp_header_init(0, sum_of_new_sizes, &mtr);
01469 
01470     mtr_commit(&mtr);
01471 
01472     /* To maintain backward compatibility we create only
01473     the first rollback segment before the double write buffer.
01474     All the remaining rollback segments will be created later,
01475     after the double write buffer has been created. */
01476     trx_sys_create();
01477 
01478     dict_create();
01479 
01480     srv_startup_is_before_trx_rollback_phase = FALSE;
01481 
01482 #ifdef UNIV_LOG_ARCHIVE
01483   } else if (srv_archive_recovery) {
01484           drizzled::errmsg_printf(drizzled::error::INFO,
01485                                   "InnoDB: Starting archive recovery from a backup...");
01486     err = recv_recovery_from_archive_start(
01487       min_flushed_lsn, srv_archive_recovery_limit_lsn,
01488       min_arch_log_no);
01489     if (err != DB_SUCCESS) {
01490 
01491       return(DB_ERROR);
01492     }
01493     /* Since ibuf init is in dict_boot, and ibuf is needed
01494     in any disk i/o, first call dict_boot */
01495 
01496     dict_boot();
01497 
01498     trx_sys_init_at_db_start();
01499 
01500     srv_startup_is_before_trx_rollback_phase = FALSE;
01501 
01502     /* Initialize the fsp free limit global variable in the log
01503     system */
01504     fsp_header_get_free_limit();
01505 
01506     recv_recovery_from_archive_finish();
01507 #endif /* UNIV_LOG_ARCHIVE */
01508   } else {
01509 
01510     /* Check if we support the max format that is stamped
01511     on the system tablespace. 
01512     Note:  We are NOT allowed to make any modifications to
01513     the TRX_SYS_PAGE_NO page before recovery  because this
01514     page also contains the max_trx_id etc. important system
01515     variables that are required for recovery.  We need to
01516     ensure that we return the system to a state where normal
01517     recovery is guaranteed to work. We do this by
01518     invalidating the buffer cache, this will force the
01519     reread of the page and restoration to its last known
01520     consistent state, this is REQUIRED for the recovery
01521     process to work. */
01522     err = trx_sys_file_format_max_check(
01523       srv_max_file_format_at_startup);
01524 
01525     if (err != DB_SUCCESS) {
01526       return(err);
01527     }
01528 
01529     /* Invalidate the buffer pool to ensure that we reread
01530     the page that we read above, during recovery.
01531     Note that this is not as heavy weight as it seems. At
01532     this point there will be only ONE page in the buf_LRU
01533     and there must be no page in the buf_flush list. */
01534     buf_pool_invalidate();
01535 
01536     /* We always try to do a recovery, even if the database had
01537     been shut down normally: this is the normal startup path */
01538 
01539     err = recv_recovery_from_checkpoint_start(LOG_CHECKPOINT,
01540                 IB_ULONGLONG_MAX,
01541                 min_flushed_lsn,
01542                 max_flushed_lsn);
01543     if (err != DB_SUCCESS) {
01544 
01545       return(DB_ERROR);
01546     }
01547 
01548     /* Since the insert buffer init is in dict_boot, and the
01549     insert buffer is needed in any disk i/o, first we call
01550     dict_boot(). Note that trx_sys_init_at_db_start() only needs
01551     to access space 0, and the insert buffer at this stage already
01552     works for space 0. */
01553 
01554     dict_boot();
01555     trx_sys_init_at_db_start();
01556 
01557     /* Initialize the fsp free limit global variable in the log
01558     system */
01559     fsp_header_get_free_limit();
01560 
01561     /* recv_recovery_from_checkpoint_finish needs trx lists which
01562     are initialized in trx_sys_init_at_db_start(). */
01563 
01564     recv_recovery_from_checkpoint_finish();
01565 
01566                 if (srv_apply_log_only)
01567                   goto skip_processes;
01568 
01569     if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) {
01570       /* The following call is necessary for the insert
01571       buffer to work with multiple tablespaces. We must
01572       know the mapping between space id's and .ibd file
01573       names.
01574 
01575       In a crash recovery, we check that the info in data
01576       dictionary is consistent with what we already know
01577       about space id's from the call of
01578       fil_load_single_table_tablespaces().
01579 
01580       In a normal startup, we create the space objects for
01581       every table in the InnoDB data dictionary that has
01582       an .ibd file.
01583 
01584       We also determine the maximum tablespace id used. */
01585 
01586       dict_check_tablespaces_and_store_max_id(
01587         recv_needed_recovery);
01588     }
01589 
01590     srv_startup_is_before_trx_rollback_phase = FALSE;
01591     recv_recovery_rollback_active();
01592 
01593     /* It is possible that file_format tag has never
01594     been set. In this case we initialize it to minimum
01595     value.  Important to note that we can do it ONLY after
01596     we have finished the recovery process so that the
01597     image of TRX_SYS_PAGE_NO is not stale. */
01598     trx_sys_file_format_tag_init();
01599   }
01600 
01601   if (!create_new_db && sum_of_new_sizes > 0) {
01602     /* New data file(s) were added */
01603     mtr_start(&mtr);
01604 
01605     fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
01606 
01607     mtr_commit(&mtr);
01608 
01609     /* Immediately write the log record about increased tablespace
01610     size to disk, so that it is durable even if mysqld would crash
01611     quickly */
01612 
01613     log_buffer_flush_to_disk();
01614   }
01615 
01616 #ifdef UNIV_LOG_ARCHIVE
01617   /* Archiving is always off under MySQL */
01618   if (!srv_log_archive_on) {
01619     ut_a(DB_SUCCESS == log_archive_noarchivelog());
01620   } else {
01621     mutex_enter(&(log_sys->mutex));
01622 
01623     start_archive = FALSE;
01624 
01625     if (log_sys->archiving_state == LOG_ARCH_OFF) {
01626       start_archive = TRUE;
01627     }
01628 
01629     mutex_exit(&(log_sys->mutex));
01630 
01631     if (start_archive) {
01632       ut_a(DB_SUCCESS == log_archive_archivelog());
01633     }
01634   }
01635 #endif /* UNIV_LOG_ARCHIVE */
01636 
01637   /* fprintf(stderr, "Max allowed record size %lu\n",
01638   page_get_free_space_of_empty() / 2); */
01639 
01640   if (trx_doublewrite == NULL) {
01641     /* Create the doublewrite buffer to a new tablespace */
01642 
01643     trx_sys_create_doublewrite_buf();
01644   }
01645 
01646   /* Here the double write buffer has already been created and so
01647   any new rollback segments will be allocated after the double
01648   write buffer. The default segment should already exist.
01649   We create the new segments only if it's a new database or
01650   the database was shutdown cleanly. */
01651 
01652   /* Note: When creating the extra rollback segments during an upgrade
01653   we violate the latching order, even if the change buffer is empty.
01654   We make an exception in sync0sync.c and check srv_is_being_started
01655   for that violation. It cannot create a deadlock because we are still
01656   running in single threaded mode essentially. Only the IO threads
01657   should be running at this stage. */
01658 
01659   trx_sys_create_rsegs(TRX_SYS_N_RSEGS - 1);
01660 
01661   /* Create the thread which watches the timeouts for lock waits */
01662   os_thread_create(&srv_lock_timeout_thread, NULL,
01663        thread_ids + 2 + SRV_MAX_N_IO_THREADS);
01664 
01665   /* Create the thread which warns of long semaphore waits */
01666   os_thread_create(&srv_error_monitor_thread, NULL,
01667        thread_ids + 3 + SRV_MAX_N_IO_THREADS);
01668 
01669   /* Create the thread which prints InnoDB monitor info */
01670   os_thread_create(&srv_monitor_thread, NULL,
01671        thread_ids + 4 + SRV_MAX_N_IO_THREADS);
01672 
01673   /* Create the thread which automaticaly dumps/restore buffer pool */
01674   os_thread_create(&srv_LRU_dump_restore_thread, NULL,
01675        thread_ids + 5 + SRV_MAX_N_IO_THREADS);
01676 
01677   srv_is_being_started = FALSE;
01678 
01679   err = dict_create_or_check_foreign_constraint_tables();
01680 
01681   if (err != DB_SUCCESS) {
01682     return((int)DB_ERROR);
01683   }
01684 
01685   /* Create the master thread which does purge and other utility
01686   operations */
01687 
01688   os_thread_create(&srv_master_thread, NULL, thread_ids
01689        + (1 + SRV_MAX_N_IO_THREADS));
01690 
01691   /* Currently we allow only a single purge thread. */
01692   ut_a(srv_n_purge_threads == 0 || srv_n_purge_threads == 1);
01693 
01694   /* If the user has requested a separate purge thread then
01695   start the purge thread. */
01696   if (srv_n_purge_threads == 1) {
01697     os_thread_create(&srv_purge_thread, NULL, NULL);
01698   }
01699 
01700 #ifdef UNIV_DEBUG
01701   /* buf_debug_prints = TRUE; */
01702 #endif /* UNIV_DEBUG */
01703   sum_of_data_file_sizes = 0;
01704 
01705   for (i = 0; i < srv_n_data_files; i++) {
01706     sum_of_data_file_sizes += srv_data_file_sizes[i];
01707   }
01708 
01709   tablespace_size_in_header = fsp_header_get_tablespace_size();
01710 
01711   if (!srv_auto_extend_last_data_file
01712       && sum_of_data_file_sizes != tablespace_size_in_header) {
01713 
01714           drizzled::errmsg_printf(drizzled::error::ERROR,
01715                                   "InnoDB: Error: tablespace size stored in header is %lu pages, but the sum of data file sizes is %lu pages.",
01716                                   (ulong) tablespace_size_in_header,
01717                                   (ulong) sum_of_data_file_sizes);
01718 
01719     if (srv_force_recovery == 0
01720         && sum_of_data_file_sizes < tablespace_size_in_header) {
01721       /* This is a fatal error, the tail of a tablespace is
01722       missing */
01723 
01724                   drizzled::errmsg_printf(drizzled::error::ERROR,
01725                                           "InnoDB: Cannot start InnoDB. The tail of the system tablespace is "
01726                                           "missing. Have you edited innodb_data_file_path in my.cnf in an "
01727                                           "inappropriate way, removing ibdata files from there? "
01728                                           "You can set innodb_force_recovery=1 in my.cnf to force "
01729                                           "a startup if you are trying to recover a badly corrupt database.");
01730 
01731       return(DB_ERROR);
01732     }
01733   }
01734 
01735   if (srv_auto_extend_last_data_file
01736       && sum_of_data_file_sizes < tablespace_size_in_header) {
01737 
01738           drizzled::errmsg_printf(drizzled::error::ERROR,
01739                                   "InnoDB: Error: tablespace size stored in header is %lu pages, but the sum of data file sizes"
01740                                   " is only %lu pages\n",
01741                                   (ulong) tablespace_size_in_header,
01742                                   (ulong) sum_of_data_file_sizes);
01743 
01744     if (srv_force_recovery == 0) {
01745 
01746                   drizzled::errmsg_printf(drizzled::error::ERROR,
01747         "InnoDB: Cannot start InnoDB. The tail of the system tablespace is "
01748         "missing. Have you edited innodb_data_file_path in my.cnf in an "
01749         "inappropriate way, removing ibdata files from there? "
01750         "You can set innodb_force_recovery=1 in my.cnf to force "
01751         "a startup if you are trying to recover a badly corrupt database.\n");
01752 
01753       return(DB_ERROR);
01754     }
01755   }
01756 
01757   /* Check that os_fast_mutexes work as expected */
01758   os_fast_mutex_init(&srv_os_test_mutex);
01759 
01760   if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
01761           drizzled::errmsg_printf(drizzled::error::ERROR,
01762       "InnoDB: Error: pthread_mutex_trylock returns an unexpected value on success! Cannot continue.\n");
01763     exit(1);
01764   }
01765 
01766   os_fast_mutex_unlock(&srv_os_test_mutex);
01767 
01768   os_fast_mutex_lock(&srv_os_test_mutex);
01769 
01770   os_fast_mutex_unlock(&srv_os_test_mutex);
01771 
01772   os_fast_mutex_free(&srv_os_test_mutex);
01773 
01774   if (srv_print_verbose_log) {
01775                 drizzled::errmsg_printf(drizzled::error::INFO,
01776                                         "InnoDB %s started; log sequence number %"PRIu64"\n",
01777                                         INNODB_VERSION_STR, srv_start_lsn);
01778   }
01779 
01780   if (srv_force_recovery > 0) {
01781           drizzled::errmsg_printf(drizzled::error::ERROR,
01782                                   "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
01783                                   (ulong) srv_force_recovery);
01784   }
01785 
01786   if (trx_doublewrite_must_reset_space_ids) {
01787     /* Actually, we did not change the undo log format between
01788     4.0 and 4.1.1, and we would not need to run purge to
01789     completion. Note also that the purge algorithm in 4.1.1
01790     can process the the history list again even after a full
01791     purge, because our algorithm does not cut the end of the
01792     history list in all cases so that it would become empty
01793     after a full purge. That mean that we may purge 4.0 type
01794     undo log even after this phase.
01795 
01796     The insert buffer record format changed between 4.0 and
01797     4.1.1. It is essential that the insert buffer is emptied
01798     here! */
01799 
01800           drizzled::errmsg_printf(drizzled::error::INFO,
01801                                   "InnoDB: You are upgrading to an InnoDB version which allows multiple. "
01802                                   "tablespaces. Wait that purge and insert buffer merge run to completion...");
01803     for (;;) {
01804       os_thread_sleep(1000000);
01805 
01806       if (0 == strcmp(srv_main_thread_op_info,
01807           "waiting for server activity")) {
01808 
01809         ut_a(ibuf_is_empty());
01810 
01811         break;
01812       }
01813     }
01814                 drizzled::errmsg_printf(drizzled::error::INFO,
01815                                         "InnoDB: Full purge and insert buffer merge completed.");
01816 
01817     trx_sys_mark_upgraded_to_multiple_tablespaces();
01818 
01819                 drizzled::errmsg_printf(drizzled::error::INFO,
01820                                         "InnoDB: You have now successfully upgraded"
01821                                         " to the multiple tablespaces\n"
01822                                         "InnoDB: format. You should NOT DOWNGRADE"
01823                                         " to an earlier version of\n"
01824                                         "InnoDB: InnoDB! But if you absolutely need to"
01825                                         " downgrade, see\n"
01826                                         "InnoDB: " REFMAN "multiple-tablespaces.html\n"
01827                                         "InnoDB: for instructions.\n");
01828   }
01829 
01830   if (srv_force_recovery == 0) {
01831     /* In the insert buffer we may have even bigger tablespace
01832     id's, because we may have dropped those tablespaces, but
01833     insert buffer merge has not had time to clean the records from
01834     the ibuf tree. */
01835 
01836     ibuf_update_max_tablespace_id();
01837   }
01838 
01839 skip_processes:
01840   srv_file_per_table = srv_file_per_table_original_value;
01841 
01842   srv_was_started = TRUE;
01843 
01844   return((int) DB_SUCCESS);
01845 }
01846 
01847 /****************************************************************/
01850 UNIV_INTERN
01851 int
01852 innobase_shutdown_for_mysql(void)
01853 /*=============================*/
01854 {
01855   ulint i;
01856   if (!srv_was_started) {
01857     if (srv_is_being_started) {
01858                   drizzled::errmsg_printf(drizzled::error::ERROR,
01859         "InnoDB: Warning: shutting down a not properly started or created database!");
01860     }
01861 
01862     return(DB_SUCCESS);
01863   }
01864 
01865   /* 1. Flush the buffer pool to disk, write the current lsn to
01866   the tablespace header(s), and copy all log data to archive.
01867   The step 1 is the real InnoDB shutdown. The remaining steps 2 - ...
01868   just free data structures after the shutdown. */
01869 
01870 
01871   if (srv_fast_shutdown == 2) {
01872                 drizzled::errmsg_printf(drizzled::error::INFO,
01873                                         "InnoDB: MySQL has requested a very fast shutdown without flushing "
01874                                         "the InnoDB buffer pool to data files. At the next mysqld startup "
01875                                         "InnoDB will do a crash recovery!");
01876   }
01877 
01878   logs_empty_and_mark_files_at_shutdown();
01879 
01880   if (srv_conc_n_threads != 0) {
01881           drizzled::errmsg_printf(drizzled::error::WARN,
01882                                   "InnoDB: Warning: query counter shows %ld queries still InnoDB: inside InnoDB at shutdown.",
01883                                   srv_conc_n_threads);
01884   }
01885 
01886   /* 2. Make all threads created by InnoDB to exit */
01887 
01888   srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
01889 
01890   /* In a 'very fast' shutdown, we do not need to wait for these threads
01891   to die; all which counts is that we flushed the log; a 'very fast'
01892   shutdown is essentially a crash. */
01893 
01894   if (srv_fast_shutdown == 2) {
01895     return(DB_SUCCESS);
01896   }
01897 
01898   /* All threads end up waiting for certain events. Put those events
01899   to the signaled state. Then the threads will exit themselves in
01900   os_thread_event_wait(). */
01901 
01902   for (i = 0; i < 1000; i++) {
01903     /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
01904     HERE OR EARLIER */
01905 
01906     /* a. Let the lock timeout thread exit */
01907     os_event_set(srv_lock_timeout_thread_event);
01908 
01909     /* b. srv error monitor thread exits automatically, no need
01910     to do anything here */
01911 
01912     /* c. We wake the master thread so that it exits */
01913     srv_wake_master_thread();
01914 
01915     /* d. We wake the purge thread so that it exits */
01916     srv_wake_purge_thread();
01917 
01918     /* e. Exit the i/o threads */
01919 
01920     os_aio_wake_all_threads_at_shutdown();
01921 
01922     os_mutex_enter(os_sync_mutex);
01923 
01924     if (os_thread_count == 0) {
01925       /* All the threads have exited or are just exiting;
01926       NOTE that the threads may not have completed their
01927       exit yet. Should we use pthread_join() to make sure
01928       they have exited? If we did, we would have to
01929       remove the pthread_detach() from
01930       os_thread_exit().  Now we just sleep 0.1
01931       seconds and hope that is enough! */
01932 
01933       os_mutex_exit(os_sync_mutex);
01934 
01935       os_thread_sleep(100000);
01936 
01937       break;
01938     }
01939 
01940     os_mutex_exit(os_sync_mutex);
01941 
01942     os_thread_sleep(100000);
01943   }
01944 
01945   if (i == 1000) {
01946           drizzled::errmsg_printf(drizzled::error::WARN,
01947       "InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!",
01948       (ulong) os_thread_count);
01949   }
01950 
01951   if (srv_monitor_file) {
01952     fclose(srv_monitor_file);
01953     srv_monitor_file = 0;
01954     if (srv_monitor_file_name) {
01955       unlink(srv_monitor_file_name);
01956       mem_free(srv_monitor_file_name);
01957     }
01958   }
01959   if (srv_dict_tmpfile) {
01960     fclose(srv_dict_tmpfile);
01961     srv_dict_tmpfile = 0;
01962   }
01963 
01964   if (srv_misc_tmpfile) {
01965     fclose(srv_misc_tmpfile);
01966     srv_misc_tmpfile = 0;
01967   }
01968 
01969   /* This must be disabled before closing the buffer pool
01970   and closing the data dictionary.  */
01971   btr_search_disable();
01972 
01973   ibuf_close();
01974   log_shutdown();
01975   lock_sys_close();
01976   thr_local_close();
01977   trx_sys_file_format_close();
01978   trx_sys_close();
01979 
01980   mutex_free(&srv_monitor_file_mutex);
01981   mutex_free(&srv_dict_tmpfile_mutex);
01982   mutex_free(&srv_misc_tmpfile_mutex);
01983   dict_close();
01984   btr_search_sys_free();
01985 
01986   /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
01987   them */
01988   os_aio_free();
01989   sync_close();
01990   srv_free();
01991   fil_close();
01992 
01993   /* 4. Free the os_conc_mutex and all os_events and os_mutexes */
01994 
01995   os_sync_free();
01996 
01997   /* 5. Free all allocated memory */
01998 
01999   pars_lexer_close();
02000   log_mem_free();
02001   buf_pool_free(srv_buf_pool_instances);
02002   mem_close();
02003 
02004   /* ut_free_all_mem() frees all allocated memory not freed yet
02005   in shutdown, and it will also free the ut_list_mutex, so it
02006   should be the last one for all operation */
02007   ut_free_all_mem();
02008 
02009   if (os_thread_count != 0
02010       || os_event_count != 0
02011       || os_mutex_count != 0
02012       || os_fast_mutex_count != 0) {
02013           drizzled::errmsg_printf(drizzled::error::WARN,
02014                                   "InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
02015                                   "InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
02016                                   (ulong) os_thread_count, (ulong) os_event_count,
02017                                   (ulong) os_mutex_count, (ulong) os_fast_mutex_count);
02018   }
02019 
02020   if (dict_foreign_err_file) {
02021     fclose(dict_foreign_err_file);
02022   }
02023   if (lock_latest_err_file) {
02024     fclose(lock_latest_err_file);
02025   }
02026 
02027   if (srv_print_verbose_log) {
02028                 drizzled::errmsg_printf(drizzled::error::INFO,
02029                                         "InnoDB: Shutdown completed log sequence number %"PRIu64,
02030                                         srv_shutdown_lsn);
02031   }
02032 
02033   srv_was_started = FALSE;
02034   srv_start_has_been_called = FALSE;
02035 
02036   return((int) DB_SUCCESS);
02037 }
02038 #endif /* !UNIV_HOTBACKUP */