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