Drizzled Public API Documentation

srv0start.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
4 Copyright (C) 2008, Google Inc.
5 Copyright (C) 2009, Percona Inc.
6 
7 Portions of this file contain modifications contributed and copyrighted by
8 Google, Inc. Those modifications are gratefully acknowledged and are described
9 briefly in the InnoDB documentation. The contributions by Google are
10 incorporated with their permission, and subject to the conditions contained in
11 the file COPYING.Google.
12 
13 Portions of this file contain modifications contributed and copyrighted
14 by Percona Inc.. Those modifications are
15 gratefully acknowledged and are described briefly in the InnoDB
16 documentation. The contributions by Percona Inc. are incorporated with
17 their permission, and subject to the conditions contained in the file
18 COPYING.Percona.
19 
20 This program is free software; you can redistribute it and/or modify it under
21 the terms of the GNU General Public License as published by the Free Software
22 Foundation; version 2 of the License.
23 
24 This program is distributed in the hope that it will be useful, but WITHOUT
25 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
26 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
27 
28 You should have received a copy of the GNU General Public License along with
29 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
30 St, Fifth Floor, Boston, MA 02110-1301 USA
31 
32 *****************************************************************************/
33 
34 /********************************************************************/
41 #include "ut0mem.h"
42 #include "mem0mem.h"
43 #include "data0data.h"
44 #include "data0type.h"
45 #include "dict0dict.h"
46 #include "buf0buf.h"
47 #include "os0file.h"
48 #include "os0thread.h"
49 #include "fil0fil.h"
50 #include "fsp0fsp.h"
51 #include "rem0rec.h"
52 #include "mtr0mtr.h"
53 #include "log0log.h"
54 #include "log0recv.h"
55 #include "page0page.h"
56 #include "page0cur.h"
57 #include "trx0trx.h"
58 #include "trx0sys.h"
59 #include "btr0btr.h"
60 #include "btr0cur.h"
61 #include "rem0rec.h"
62 #include "ibuf0ibuf.h"
63 #include "srv0start.h"
64 #include "srv0srv.h"
65 #ifndef UNIV_HOTBACKUP
66 # include "os0proc.h"
67 # include "sync0sync.h"
68 # include "buf0flu.h"
69 # include "buf0rea.h"
70 # include "dict0boot.h"
71 # include "dict0load.h"
72 # include "que0que.h"
73 # include "usr0sess.h"
74 # include "lock0lock.h"
75 # include "trx0roll.h"
76 # include "trx0purge.h"
77 # include "lock0lock.h"
78 # include "pars0pars.h"
79 # include "btr0sea.h"
80 # include "rem0cmp.h"
81 # include "dict0crea.h"
82 # include "row0ins.h"
83 # include "row0sel.h"
84 # include "row0upd.h"
85 # include "row0row.h"
86 # include "row0mysql.h"
87 # include "btr0pcur.h"
88 # include "thr0loc.h"
89 # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */
90 # include "zlib.h" /* for ZLIB_VERSION */
91 #include "xtrabackup_api.h"
92 
93 #include <errno.h>
94 #include <unistd.h>
95 
96 #include <drizzled/gettext.h>
97 #include <drizzled/errmsg_print.h>
98 
100 UNIV_INTERN ib_uint64_t srv_start_lsn;
102 UNIV_INTERN ib_uint64_t srv_shutdown_lsn;
103 
104 #ifdef HAVE_DARWIN_THREADS
105 # include <sys/utsname.h>
107 UNIV_INTERN ibool srv_have_fullfsync = FALSE;
108 #endif
109 
111 UNIV_INTERN ibool srv_start_raw_disk_in_use = FALSE;
112 
117 UNIV_INTERN ibool srv_is_being_started = FALSE;
119 UNIV_INTERN ibool srv_was_started = FALSE;
121 static ibool srv_start_has_been_called = FALSE;
122 
126 
128 static os_file_t files[1000];
129 
131 static ulint n[SRV_MAX_N_IO_THREADS + 7];
133 static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 7];
134 
137 static os_fast_mutex_t srv_os_test_mutex;
138 
140 static char* srv_monitor_file_name;
141 #endif /* !UNIV_HOTBACKUP */
142 
144 #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
145 #define SRV_MAX_N_PENDING_SYNC_IOS 100
146 
147 #ifdef UNIV_PFS_THREAD
148 /* Keys to register InnoDB threads with performance schema */
149 UNIV_INTERN mysql_pfs_key_t io_handler_thread_key;
150 UNIV_INTERN mysql_pfs_key_t srv_lock_timeout_thread_key;
151 UNIV_INTERN mysql_pfs_key_t srv_error_monitor_thread_key;
152 UNIV_INTERN mysql_pfs_key_t srv_monitor_thread_key;
153 UNIV_INTERN mysql_pfs_key_t srv_master_thread_key;
154 #endif /* UNIV_PFS_THREAD */
155 
156 /*********************************************************************/
160 static
161 char*
162 srv_parse_megabytes(
163 /*================*/
164  char* str,
165  ulint* megs)
166 {
167  char* endp;
168  ulint size;
169 
170  size = strtoul(str, &endp, 10);
171 
172  str = endp;
173 
174  switch (*str) {
175  case 'G': case 'g':
176  size *= 1024;
177  /* fall through */
178  case 'M': case 'm':
179  str++;
180  break;
181  default:
182  size /= 1024 * 1024;
183  break;
184  }
185 
186  *megs = size;
187  return(str);
188 }
189 
190 /*********************************************************************/
194 UNIV_INTERN
195 ibool
197 /*================================*/
198  char* str)
199 {
200  char* input_str;
201  char* path;
202  ulint size;
203  ulint i = 0;
204 
205  srv_auto_extend_last_data_file = FALSE;
206  srv_last_file_size_max = 0;
207  srv_data_file_names = NULL;
208  srv_data_file_sizes = NULL;
209  srv_data_file_is_raw_partition = NULL;
210 
211  input_str = str;
212 
213  /* First calculate the number of data files and check syntax:
214  path:size[M | G];path:size[M | G]... . Note that a Windows path may
215  contain a drive name and a ':'. */
216 
217  while (*str != '\0') {
218  path = str;
219 
220  while ((*str != ':' && *str != '\0')
221  || (*str == ':'
222  && (*(str + 1) == '\\' || *(str + 1) == '/'
223  || *(str + 1) == ':'))) {
224  str++;
225  }
226 
227  if (*str == '\0') {
228  return(FALSE);
229  }
230 
231  str++;
232 
233  str = srv_parse_megabytes(str, &size);
234 
235  if (0 == strncmp(str, ":autoextend",
236  (sizeof ":autoextend") - 1)) {
237 
238  str += (sizeof ":autoextend") - 1;
239 
240  if (0 == strncmp(str, ":max:",
241  (sizeof ":max:") - 1)) {
242 
243  str += (sizeof ":max:") - 1;
244 
245  str = srv_parse_megabytes(str, &size);
246  }
247 
248  if (*str != '\0') {
249 
250  return(FALSE);
251  }
252  }
253 
254  if (strlen(str) >= 6
255  && *str == 'n'
256  && *(str + 1) == 'e'
257  && *(str + 2) == 'w') {
258  str += 3;
259  }
260 
261  if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
262  str += 3;
263  }
264 
265  if (size == 0) {
266  return(FALSE);
267  }
268 
269  i++;
270 
271  if (*str == ';') {
272  str++;
273  } else if (*str != '\0') {
274 
275  return(FALSE);
276  }
277  }
278 
279  if (i == 0) {
280  /* If innodb_data_file_path was defined it must contain
281  at least one data file definition */
282 
283  return(FALSE);
284  }
285 
286  srv_data_file_names = static_cast<char **>(malloc(i * sizeof *srv_data_file_names));
287  srv_data_file_sizes = static_cast<ulint *>(malloc(i * sizeof *srv_data_file_sizes));
288  srv_data_file_is_raw_partition = static_cast<ulint *>(malloc(
289  i * sizeof *srv_data_file_is_raw_partition));
290 
291  srv_n_data_files = i;
292 
293  /* Then store the actual values to our arrays */
294 
295  str = input_str;
296  i = 0;
297 
298  while (*str != '\0') {
299  path = str;
300 
301  /* Note that we must step over the ':' in a Windows path;
302  a Windows path normally looks like C:\ibdata\ibdata1:1G, but
303  a Windows raw partition may have a specification like
304  \\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */
305 
306  while ((*str != ':' && *str != '\0')
307  || (*str == ':'
308  && (*(str + 1) == '\\' || *(str + 1) == '/'
309  || *(str + 1) == ':'))) {
310  str++;
311  }
312 
313  if (*str == ':') {
314  /* Make path a null-terminated string */
315  *str = '\0';
316  str++;
317  }
318 
319  str = srv_parse_megabytes(str, &size);
320 
321  srv_data_file_names[i] = path;
322  srv_data_file_sizes[i] = size;
323 
324  if (0 == strncmp(str, ":autoextend",
325  (sizeof ":autoextend") - 1)) {
326 
327  srv_auto_extend_last_data_file = TRUE;
328 
329  str += (sizeof ":autoextend") - 1;
330 
331  if (0 == strncmp(str, ":max:",
332  (sizeof ":max:") - 1)) {
333 
334  str += (sizeof ":max:") - 1;
335 
336  str = srv_parse_megabytes(
337  str, &srv_last_file_size_max);
338  }
339 
340  if (*str != '\0') {
341 
342  return(FALSE);
343  }
344  }
345 
346  (srv_data_file_is_raw_partition)[i] = 0;
347 
348  if (strlen(str) >= 6
349  && *str == 'n'
350  && *(str + 1) == 'e'
351  && *(str + 2) == 'w') {
352  str += 3;
353  (srv_data_file_is_raw_partition)[i] = SRV_NEW_RAW;
354  }
355 
356  if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
357  str += 3;
358 
359  if ((srv_data_file_is_raw_partition)[i] == 0) {
360  (srv_data_file_is_raw_partition)[i] = SRV_OLD_RAW;
361  }
362  }
363 
364  i++;
365 
366  if (*str == ';') {
367  str++;
368  }
369  }
370 
371  return(TRUE);
372 }
373 
374 /*********************************************************************/
378 UNIV_INTERN
379 ibool
381 /*==========================*/
382  char* str)
383 {
384  char* input_str;
385  char* path;
386  ulint i = 0;
387 
388  srv_log_group_home_dirs = NULL;
389 
390  input_str = str;
391 
392  /* First calculate the number of directories and check syntax:
393  path;path;... */
394 
395  while (*str != '\0') {
396  path = str;
397 
398  while (*str != ';' && *str != '\0') {
399  str++;
400  }
401 
402  i++;
403 
404  if (*str == ';') {
405  str++;
406  } else if (*str != '\0') {
407 
408  return(FALSE);
409  }
410  }
411 
412  if (i != 1) {
413  /* If innodb_log_group_home_dir was defined it must
414  contain exactly one path definition under current MySQL */
415 
416  return(FALSE);
417  }
418 
419  srv_log_group_home_dirs = static_cast<char **>(malloc(i * sizeof *srv_log_group_home_dirs));
420 
421  /* Then store the actual values to our array */
422 
423  str = input_str;
424  i = 0;
425 
426  while (*str != '\0') {
427  path = str;
428 
429  while (*str != ';' && *str != '\0') {
430  str++;
431  }
432 
433  if (*str == ';') {
434  *str = '\0';
435  str++;
436  }
437 
438  srv_log_group_home_dirs[i] = path;
439 
440  i++;
441  }
442 
443  return(TRUE);
444 }
445 
446 /*********************************************************************/
449 UNIV_INTERN
450 void
452 /*==========================*/
453 {
454  free(srv_data_file_names);
455  srv_data_file_names = NULL;
456  free(srv_data_file_sizes);
457  srv_data_file_sizes = NULL;
458  free(srv_data_file_is_raw_partition);
459  srv_data_file_is_raw_partition = NULL;
460  free(srv_log_group_home_dirs);
461  srv_log_group_home_dirs = NULL;
462 }
463 
464 #ifndef UNIV_HOTBACKUP
465 /********************************************************************/
468 extern "C"
469 os_thread_ret_t
470 io_handler_thread(void* arg);
471 
472 extern "C"
473 os_thread_ret_t
474 io_handler_thread(
475 /*==============*/
476  void* arg)
478 {
479  ulint segment;
480 
481  segment = *((ulint*)arg);
482 
483 #ifdef UNIV_DEBUG_THREAD_CREATION
484  fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment,
486 #endif
487 
488 #ifdef UNIV_PFS_THREAD
489  pfs_register_thread(io_handler_thread_key);
490 #endif /* UNIV_PFS_THREAD */
491 
493  fil_aio_wait(segment);
494  }
495 
496  /* We count the number of threads in os_thread_exit(). A created
497  thread should always use that to exit and not use return() to exit.
498  The thread actually never comes here because it is exited in an
499  os_event_wait(). */
500  return 0;
501 }
502 #endif /* !UNIV_HOTBACKUP */
503 
504 #ifdef __WIN__
505 #define SRV_PATH_SEPARATOR '\\'
506 #else
507 #define SRV_PATH_SEPARATOR '/'
508 #endif
509 
510 /*********************************************************************/
512 UNIV_INTERN
513 void
515 /*=======================*/
516  char* /*str __attribute__((unused))*/)
518 {
519 #ifdef __WIN__
520  for (; *str; str++) {
521 
522  if (*str == '/') {
523  *str = '\\';
524  }
525  }
526 #endif
527 }
528 
529 #ifndef UNIV_HOTBACKUP
530 /*********************************************************************/
534 static
535 ulint
536 srv_calc_low32(
537 /*===========*/
538  ulint file_size)
539 {
540  return(0xFFFFFFFFUL & (file_size << UNIV_PAGE_SIZE_SHIFT));
541 }
542 
543 /*********************************************************************/
547 static
548 ulint
549 srv_calc_high32(
550 /*============*/
551  ulint file_size)
552 {
553  return(file_size >> (32 - UNIV_PAGE_SIZE_SHIFT));
554 }
555 
556 /*********************************************************************/
559 ulint
560 open_or_create_log_file(
561 /*====================*/
562  ibool create_new_db,
564  ibool* log_file_created,
566  ibool log_file_has_been_opened,
569  ulint k,
570  ulint i)
571 {
572  ibool ret;
573  ulint size;
574  ulint size_high;
575  char name[10000];
576  ulint dirnamelen;
577 
578  UT_NOT_USED(create_new_db);
579 
580  *log_file_created = FALSE;
581 
582  srv_normalize_path_for_win(srv_log_group_home_dirs[k]);
583 
584  dirnamelen = strlen(srv_log_group_home_dirs[k]);
585  ut_a(dirnamelen < (sizeof name) - 10 - sizeof "ib_logfile");
586  memcpy(name, srv_log_group_home_dirs[k], dirnamelen);
587 
588  /* Add a path separator if needed. */
589  if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
590  name[dirnamelen++] = SRV_PATH_SEPARATOR;
591  }
592 
593  sprintf(name + dirnamelen, "%s%lu", "ib_logfile", (ulong) i);
594 
595  files[i] = os_file_create(innodb_file_log_key, name,
596  OS_FILE_CREATE, OS_FILE_NORMAL,
597  OS_LOG_FILE, &ret);
598  if (ret == FALSE) {
599  if (os_file_get_last_error(FALSE) != OS_FILE_ALREADY_EXISTS
600 #ifdef UNIV_AIX
601  /* AIX 5.1 after security patch ML7 may have errno set
602  to 0 here, which causes our function to return 100;
603  work around that AIX problem */
604  && os_file_get_last_error(FALSE) != 100
605 #endif
606  ) {
607  drizzled::errmsg_printf(drizzled::error::ERROR,
608  "InnoDB: Error in creating or opening %s", name);
609 
610  return(DB_ERROR);
611  }
612 
613  files[i] = os_file_create(innodb_file_log_key, name,
614  OS_FILE_OPEN, OS_FILE_AIO,
615  OS_LOG_FILE, &ret);
616  if (!ret) {
617  drizzled::errmsg_printf(drizzled::error::ERROR,
618  "InnoDB: Error in opening %s.", name);
619 
620  return(DB_ERROR);
621  }
622 
623  ret = os_file_get_size(files[i], &size, &size_high);
624  ut_a(ret);
625 
626  if (size != srv_calc_low32(srv_log_file_size)
627  || size_high != srv_calc_high32(srv_log_file_size)) {
628 
629  drizzled::errmsg_printf(drizzled::error::ERROR,
630  "InnoDB: Error: log file %s is of different size %lu %lu bytes than specified in the .cnf"
631  " file %lu %lu bytes!",
632  name, (ulong) size_high, (ulong) size,
633  (ulong) srv_calc_high32(srv_log_file_size),
634  (ulong) srv_calc_low32(srv_log_file_size));
635 
636  return(DB_ERROR);
637  }
638  } else {
639  *log_file_created = TRUE;
640 
641  drizzled::errmsg_printf(drizzled::error::INFO,
642  "InnoDB: Log file %s did not exist: new to be created",
643  name);
644  if (log_file_has_been_opened) {
645 
646  return(DB_ERROR);
647  }
648 
649  drizzled::errmsg_printf(drizzled::error::INFO,
650  "InnoDB: Setting log file %s size to %lu MB",
651  name, (ulong) srv_log_file_size
652  >> (20 - UNIV_PAGE_SIZE_SHIFT));
653 
654  drizzled::errmsg_printf(drizzled::error::INFO,
655  "InnoDB: Database physically writes the file full: wait...\n");
656 
657  ret = os_file_set_size(name, files[i],
658  srv_calc_low32(srv_log_file_size),
659  srv_calc_high32(srv_log_file_size));
660  if (!ret) {
661  drizzled::errmsg_printf(drizzled::error::ERROR,
662  "InnoDB: Error in creating %s: probably out of disk space",
663  name);
664 
665  return(DB_ERROR);
666  }
667  }
668 
669  ret = os_file_close(files[i]);
670  ut_a(ret);
671 
672  if (i == 0) {
673  /* Create in memory the file space object
674  which is for this log group */
675 
676  fil_space_create(name,
677  2 * k + SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG);
678  }
679 
680  ut_a(fil_validate());
681 
682  fil_node_create(name, srv_log_file_size,
683  2 * k + SRV_LOG_SPACE_FIRST_ID, FALSE);
684 #ifdef UNIV_LOG_ARCHIVE
685  /* If this is the first log group, create the file space object
686  for archived logs.
687  Under MySQL, no archiving ever done. */
688 
689  if (k == 0 && i == 0) {
690  arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
691 
692  fil_space_create("arch_log_space", arch_space_id, 0, FIL_LOG);
693  } else {
694  arch_space_id = ULINT_UNDEFINED;
695  }
696 #endif /* UNIV_LOG_ARCHIVE */
697  if (i == 0) {
698  log_group_init(k, srv_n_log_files,
699  srv_log_file_size * UNIV_PAGE_SIZE,
700  2 * k + SRV_LOG_SPACE_FIRST_ID,
701  SRV_LOG_SPACE_FIRST_ID + 1); /* dummy arch
702  space id */
703  }
704 
705  return(DB_SUCCESS);
706 }
707 
708 /*********************************************************************/
711 ulint
712 open_or_create_data_files(
713 /*======================*/
714  ibool* create_new_db,
716 #ifdef UNIV_LOG_ARCHIVE
717  ulint* min_arch_log_no,
719  ulint* max_arch_log_no,
721 #endif /* UNIV_LOG_ARCHIVE */
722  ib_uint64_t* min_flushed_lsn,
724  ib_uint64_t* max_flushed_lsn,
726  ulint* sum_of_new_sizes)
728 {
729  ibool ret;
730  ulint i;
731  ibool one_opened = FALSE;
732  ibool one_created = FALSE;
733  ulint size;
734  ulint size_high;
735  ulint rounded_size_pages;
736  char name[10000];
737 
738  if (srv_n_data_files >= 1000) {
739  drizzled::errmsg_printf(drizzled::error::ERROR,
740  "InnoDB: can only have < 1000 data files you have defined %lu",
741  (ulong) srv_n_data_files);
742  return(DB_ERROR);
743  }
744 
745  *sum_of_new_sizes = 0;
746 
747  *create_new_db = FALSE;
748 
749  srv_normalize_path_for_win(srv_data_home);
750 
751  for (i = 0; i < srv_n_data_files; i++) {
752  ulint dirnamelen;
753 
754  srv_normalize_path_for_win(srv_data_file_names[i]);
755  dirnamelen = strlen(srv_data_home);
756 
757  ut_a(dirnamelen + strlen(srv_data_file_names[i])
758  < (sizeof name) - 1);
759  memcpy(name, srv_data_home, dirnamelen);
760  /* Add a path separator if needed. */
761  if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
762  name[dirnamelen++] = SRV_PATH_SEPARATOR;
763  }
764 
765  strcpy(name + dirnamelen, srv_data_file_names[i]);
766 
767  if (srv_data_file_is_raw_partition[i] == 0) {
768 
769  /* First we try to create the file: if it already
770  exists, ret will get value FALSE */
771 
772  files[i] = os_file_create(innodb_file_data_key,
773  name, OS_FILE_CREATE,
774  OS_FILE_NORMAL,
775  OS_DATA_FILE, &ret);
776 
777  if (ret == FALSE && os_file_get_last_error(FALSE)
778  != OS_FILE_ALREADY_EXISTS
779 #ifdef UNIV_AIX
780  /* AIX 5.1 after security patch ML7 may have
781  errno set to 0 here, which causes our function
782  to return 100; work around that AIX problem */
783  && os_file_get_last_error(FALSE) != 100
784 #endif
785  ) {
786  drizzled::errmsg_printf(drizzled::error::ERROR,
787  "InnoDB: Error in creating or opening %s",
788  name);
789 
790  return(DB_ERROR);
791  }
792  } else if (srv_data_file_is_raw_partition[i] == SRV_NEW_RAW) {
793  /* The partition is opened, not created; then it is
794  written over */
795 
797  srv_created_new_raw = TRUE;
798 
799  files[i] = os_file_create(innodb_file_data_key,
800  name, OS_FILE_OPEN_RAW,
801  OS_FILE_NORMAL,
802  OS_DATA_FILE, &ret);
803  if (!ret) {
804  drizzled::errmsg_printf(drizzled::error::ERROR,
805  "InnoDB: Error in opening %s", name);
806 
807  return(DB_ERROR);
808  }
809  } else if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
811 
812  ret = FALSE;
813  } else {
814  ut_a(0);
815  }
816 
817  if (ret == FALSE) {
818  /* We open the data file */
819 
820  if (one_created) {
821  drizzled::errmsg_printf(drizzled::error::ERROR,
822  "InnoDB: Error: data files can only be added at the end of a tablespace, but"
823  " data file %s existed beforehand.",
824  name);
825  return(DB_ERROR);
826  }
827 
828  if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
829  files[i] = os_file_create(
830  innodb_file_data_key,
831  name, OS_FILE_OPEN_RAW,
832  OS_FILE_NORMAL, OS_DATA_FILE, &ret);
833  } else if (i == 0) {
834  files[i] = os_file_create(
835  innodb_file_data_key,
836  name, OS_FILE_OPEN_RETRY,
837  OS_FILE_NORMAL, OS_DATA_FILE, &ret);
838  } else {
839  files[i] = os_file_create(
840  innodb_file_data_key,
841  name, OS_FILE_OPEN, OS_FILE_NORMAL,
842  OS_DATA_FILE, &ret);
843  }
844 
845  if (!ret) {
846  drizzled::errmsg_printf(drizzled::error::ERROR,
847  "InnoDB: Error in opening %s", name);
849 
850  return(DB_ERROR);
851  }
852 
853  if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
854 
855  goto skip_size_check;
856  }
857 
858  ret = os_file_get_size(files[i], &size, &size_high);
859  ut_a(ret);
860  /* Round size downward to megabytes */
861 
862  rounded_size_pages
863  = (size / (1024 * 1024) + 4096 * size_high)
864  << (20 - UNIV_PAGE_SIZE_SHIFT);
865 
866  if (i == srv_n_data_files - 1
867  && srv_auto_extend_last_data_file) {
868 
869  if (srv_data_file_sizes[i] > rounded_size_pages
870  || (srv_last_file_size_max > 0
871  && srv_last_file_size_max
872  < rounded_size_pages)) {
873 
874  drizzled::errmsg_printf(drizzled::error::ERROR,
875  "InnoDB: Error: auto-extending data file %s is of a different size. "
876  "%lu pages (rounded down to MB) than specified in the .cnf file: "
877  "initial %lu pages, max %lu (relevant if non-zero) pages!",
878  name,
879  (ulong) rounded_size_pages,
880  (ulong) srv_data_file_sizes[i],
881  (ulong)
882  srv_last_file_size_max);
883 
884  return(DB_ERROR);
885  }
886 
887  srv_data_file_sizes[i] = rounded_size_pages;
888  }
889 
890  if (rounded_size_pages != srv_data_file_sizes[i]) {
891 
892  drizzled::errmsg_printf(drizzled::error::ERROR,
893  "InnoDB: Error: data file %s is of a different size. "
894  "%lu pages (rounded down to MB). "
895  "Than specified in the .cnf file %lu pages!",
896  name,
897  (ulong) rounded_size_pages,
898  (ulong) srv_data_file_sizes[i]);
899 
900  return(DB_ERROR);
901  }
902 skip_size_check:
903  fil_read_flushed_lsn_and_arch_log_no(
904  files[i], one_opened,
905 #ifdef UNIV_LOG_ARCHIVE
906  min_arch_log_no, max_arch_log_no,
907 #endif /* UNIV_LOG_ARCHIVE */
908  min_flushed_lsn, max_flushed_lsn);
909  one_opened = TRUE;
910  } else {
911  /* We created the data file and now write it full of
912  zeros */
913 
914  one_created = TRUE;
915 
916  if (i > 0) {
917  drizzled::errmsg_printf(drizzled::error::INFO,
918  " InnoDB: Data file %s did not exist: new to be created",
919  name);
920  } else {
921  drizzled::errmsg_printf(drizzled::error::INFO,
922  "InnoDB: The first specified data file %s did not exist. A new database to be created!", name);
923  *create_new_db = TRUE;
924  }
925 
926  drizzled::errmsg_printf(drizzled::error::INFO,
927  " InnoDB: Setting file %s size to %lu MB",
928  name, (ulong) (srv_data_file_sizes[i]
929  >> (20 - UNIV_PAGE_SIZE_SHIFT)));
930 
931  drizzled::errmsg_printf(drizzled::error::INFO,
932  "InnoDB: Database physically writes the file full: wait...");
933 
934  ret = os_file_set_size(
935  name, files[i],
936  srv_calc_low32(srv_data_file_sizes[i]),
937  srv_calc_high32(srv_data_file_sizes[i]));
938 
939  if (!ret) {
940  drizzled::errmsg_printf(drizzled::error::ERROR,
941  "InnoDB: Error in creating %s: probably out of disk space", name);
942 
943  return(DB_ERROR);
944  }
945 
946  *sum_of_new_sizes = *sum_of_new_sizes
947  + srv_data_file_sizes[i];
948  }
949 
950  ret = os_file_close(files[i]);
951  ut_a(ret);
952 
953  if (i == 0) {
954  fil_space_create(name, 0, 0, FIL_TABLESPACE);
955  }
956 
957  ut_a(fil_validate());
958 
959  fil_node_create(name, srv_data_file_sizes[i], 0,
960  srv_data_file_is_raw_partition[i] != 0);
961  }
962 
963  return(DB_SUCCESS);
964 }
965 
966 /********************************************************************
967 Starts InnoDB and creates a new database if database files
968 are not found and the user wants.
969 @return DB_SUCCESS or error code */
970 UNIV_INTERN
971 int
973 /*====================================*/
974 {
975  ibool create_new_db;
976  ibool log_file_created;
977  ibool log_created = FALSE;
978  ibool log_opened = FALSE;
979  ib_uint64_t min_flushed_lsn;
980  ib_uint64_t max_flushed_lsn;
981 #ifdef UNIV_LOG_ARCHIVE
982  ulint min_arch_log_no;
983  ulint max_arch_log_no;
984 #endif /* UNIV_LOG_ARCHIVE */
985  ulint sum_of_new_sizes;
986  ulint sum_of_data_file_sizes;
987  ulint tablespace_size_in_header;
988  ulint err;
989  ulint i;
990  ulint io_limit;
991  my_bool srv_file_per_table_original_value
993  mtr_t mtr;
994 #ifdef HAVE_DARWIN_THREADS
995 # ifdef F_FULLFSYNC
996  /* This executable has been compiled on Mac OS X 10.3 or later.
997  Assume that F_FULLFSYNC is available at run-time. */
998  srv_have_fullfsync = TRUE;
999 # else /* F_FULLFSYNC */
1000  /* This executable has been compiled on Mac OS X 10.2
1001  or earlier. Determine if the executable is running
1002  on Mac OS X 10.3 or later. */
1003  struct utsname utsname;
1004  if (uname(&utsname)) {
1005  fputs(_("InnoDB: cannot determine Mac OS X version!\n"), stderr);
1006  } else {
1007  srv_have_fullfsync = strcmp(utsname.release, "7.") >= 0;
1008  }
1009  if (!srv_have_fullfsync) {
1010  fputs(_("InnoDB: On Mac OS X, fsync() may be"
1011  " broken on internal drives,\n"
1012  "InnoDB: making transactions unsafe!\n"), stderr);
1013  }
1014 # endif /* F_FULLFSYNC */
1015 #endif /* HAVE_DARWIN_THREADS */
1016 
1017  if (sizeof(ulint) != sizeof(void*)) {
1018  drizzled::errmsg_printf(drizzled::error::WARN,
1019  _("InnoDB: Error: size of InnoDB's ulint is %lu, but size of void* is %lu. "
1020  "The sizes should be the same so that on a 64-bit platform you can. Allocate more than 4 GB of memory."),
1021  (ulong)sizeof(ulint), (ulong)sizeof(void*));
1022  }
1023 
1024  /* System tables are created in tablespace 0. Thus, we must
1025  temporarily clear srv_file_per_table. This is ok, because the
1026  server will not accept connections (which could modify
1027  innodb_file_per_table) until this function has returned. */
1028  srv_file_per_table = FALSE;
1029 #ifdef UNIV_DEBUG
1030  drizzled::errmsg_printf(drizzled::error::INFO,
1031  _("InnoDB: !!!!!!!! UNIV_DEBUG switched on !!!!!!!!!\n"));
1032 #endif
1033 
1034 #ifdef UNIV_IBUF_DEBUG
1035  drizzled::errmsg_printf(drizzled::error::INFO,
1036  _("InnoDB: !!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!\n"
1037 # ifdef UNIV_IBUF_COUNT_DEBUG
1038  "InnoDB: !!!!!!!! UNIV_IBUF_COUNT_DEBUG switched on !!!!!!!!!\n"
1039  "InnoDB: Crash recovery will fail with UNIV_IBUF_COUNT_DEBUG\n"
1040 # endif
1041  ));
1042 #endif
1043 
1044 #ifdef UNIV_SYNC_DEBUG
1045  drizzled::errmsg_printf(drizzled::error::INFO,
1046  _("InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n"));
1047 #endif
1048 
1049 #ifdef UNIV_SEARCH_DEBUG
1050  drizzled::errmsg_printf(drizzled::error::INFO,
1051  _("InnoDB: !!!!!!!! UNIV_SEARCH_DEBUG switched on !!!!!!!!!\n"));
1052 #endif
1053 
1054 #ifdef UNIV_LOG_LSN_DEBUG
1055  drizzled::errmsg_printf(drizzled::error::INFO,
1056  _("InnoDB: !!!!!!!! UNIV_LOG_LSN_DEBUG switched on !!!!!!!!!\n"));
1057 #endif /* UNIV_LOG_LSN_DEBUG */
1058 #ifdef UNIV_MEM_DEBUG
1059  drizzled::errmsg_printf(drizzled::error::INFO,
1060  _("InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n"));
1061 #endif
1062 
1063  if (UNIV_LIKELY(srv_use_sys_malloc))
1064  {
1065  drizzled::errmsg_printf(drizzled::error::INFO, _("InnoDB: The InnoDB memory heap is disabled\n"));
1066  }
1067 
1068  drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: " IB_ATOMICS_STARTUP_MSG
1069  "\nInnoDB: Compressed tables use zlib " ZLIB_VERSION
1070 #ifdef UNIV_ZIP_DEBUG
1071  " with validation"
1072 #endif /* UNIV_ZIP_DEBUG */
1073 #ifdef UNIV_ZIP_COPY
1074  " and extra copying"
1075 #endif /* UNIV_ZIP_COPY */
1076  " ");
1077 
1078 
1079  /* Since InnoDB does not currently clean up all its internal data
1080  structures in MySQL Embedded Server Library server_end(), we
1081  print an error message if someone tries to start up InnoDB a
1082  second time during the process lifetime. */
1083 
1084  if (srv_start_has_been_called) {
1085  drizzled::errmsg_printf(drizzled::error::ERROR,
1086  "InnoDB: Error: startup called second time during the process lifetime.\n");
1087  }
1088 
1089  srv_start_has_been_called = TRUE;
1090 
1091 #ifdef UNIV_DEBUG
1092  log_do_write = TRUE;
1093 #endif /* UNIV_DEBUG */
1094  /* yydebug = TRUE; */
1095 
1096  srv_is_being_started = TRUE;
1098 
1099 #ifdef __WIN__
1100  switch (os_get_os_version()) {
1101  case OS_WIN95:
1102  case OS_WIN31:
1103  case OS_WINNT:
1104  /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
1105  and NT use simulated aio. In NT Windows provides async i/o,
1106  but when run in conjunction with InnoDB Hot Backup, it seemed
1107  to corrupt the data files. */
1108 
1109  srv_use_native_aio = FALSE;
1110  break;
1111 
1112  case OS_WIN2000:
1113  case OS_WINXP:
1114  /* On 2000 and XP, async IO is available. */
1115  srv_use_native_aio = TRUE;
1116  break;
1117 
1118  default:
1119  /* Vista and later have both async IO and condition variables */
1120  srv_use_native_aio = TRUE;
1121  srv_use_native_conditions = TRUE;
1122  break;
1123  }
1124 
1125 #elif defined(LINUX_NATIVE_AIO)
1126 
1127  if (srv_use_native_aio) {
1128  drizzled::errmsg_printf(drizzled::error::INFO,
1129  _("InnoDB: Using Linux native AIO"));
1130  }
1131 #else
1132  /* Currently native AIO is supported only on windows and linux
1133  and that also when the support is compiled in. In all other
1134  cases, we ignore the setting of innodb_use_native_aio. */
1135  srv_use_native_aio = FALSE;
1136 
1137 #endif
1138 
1139  if (srv_file_flush_method_str == NULL) {
1140  /* These are the default options */
1141 
1142  srv_unix_file_flush_method = SRV_UNIX_FSYNC;
1143 
1144  srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
1145 #ifndef __WIN__
1146  } else if (0 == ut_strcmp(srv_file_flush_method_str, "fsync")) {
1147  srv_unix_file_flush_method = SRV_UNIX_FSYNC;
1148 
1149  } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
1150  srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
1151 
1152  } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DIRECT")) {
1153  srv_unix_file_flush_method = SRV_UNIX_O_DIRECT;
1154 
1155  } else if (0 == ut_strcmp(srv_file_flush_method_str, "ALL_O_DIRECT")) {
1156  srv_unix_file_flush_method = SRV_UNIX_ALL_O_DIRECT;
1157 
1158  } else if (0 == ut_strcmp(srv_file_flush_method_str, "littlesync")) {
1159  srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
1160 
1161  } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
1162  srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
1163 #else
1164  } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
1165  srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
1166  srv_use_native_aio = FALSE;
1167 
1168  } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
1169  srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
1170  srv_use_native_aio = FALSE;
1171 
1172  } else if (0 == ut_strcmp(srv_file_flush_method_str,
1173  "async_unbuffered")) {
1174  srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
1175 #endif
1176  } else {
1177  drizzled::errmsg_printf(drizzled::error::ERROR,
1178  "InnoDB: Unrecognized value %s for innodb_flush_method",
1179  srv_file_flush_method_str);
1180  return(DB_ERROR);
1181  }
1182 
1183  /* Note that the call srv_boot() also changes the values of
1184  some variables to the units used by InnoDB internally */
1185 
1186  /* Set the maximum number of threads which can wait for a semaphore
1187  inside InnoDB: this is the 'sync wait array' size, as well as the
1188  maximum number of threads that can wait in the 'srv_conc array' for
1189  their time to enter InnoDB. */
1190 
1191  if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
1192  /* If buffer pool is less than 1000 MB,
1193  assume fewer threads. Also use only one
1194  buffer pool instance */
1195  srv_max_n_threads = 50000;
1196 
1197  } else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
1198 
1200  srv_max_n_threads = 10000;
1201  } else {
1203  srv_max_n_threads = 1000; /* saves several MB of memory,
1204  especially in 64-bit
1205  computers */
1206  }
1207 
1208  err = srv_boot();
1209 
1210  if (err != DB_SUCCESS) {
1211 
1212  return((int) err);
1213  }
1214 
1215  mutex_create(srv_monitor_file_mutex_key,
1216  &srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
1217 
1218  if (srv_innodb_status) {
1219  srv_monitor_file_name = static_cast<char *>(mem_alloc(
1220  strlen(fil_path_to_mysql_datadir)
1221  + 20 + sizeof "/innodb_status."));
1222  sprintf(srv_monitor_file_name, "%s/innodb_status.%lu",
1223  fil_path_to_mysql_datadir, os_proc_get_number());
1224  srv_monitor_file = fopen(srv_monitor_file_name, "w+");
1225  if (!srv_monitor_file) {
1226  drizzled::errmsg_printf(drizzled::error::ERROR,
1227  "InnoDB: unable to create %s: %s\n", srv_monitor_file_name, strerror(errno));
1228  return(DB_ERROR);
1229  }
1230  } else {
1231  srv_monitor_file_name = NULL;
1232  srv_monitor_file = os_file_create_tmpfile();
1233  if (!srv_monitor_file) {
1234  return(DB_ERROR);
1235  }
1236  }
1237 
1238  mutex_create(srv_dict_tmpfile_mutex_key,
1239  &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
1240 
1241  srv_dict_tmpfile = os_file_create_tmpfile();
1242  if (!srv_dict_tmpfile) {
1243  return(DB_ERROR);
1244  }
1245 
1246  mutex_create(srv_misc_tmpfile_mutex_key,
1247  &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
1248 
1249  srv_misc_tmpfile = os_file_create_tmpfile();
1250  if (!srv_misc_tmpfile) {
1251  return(DB_ERROR);
1252  }
1253 
1254  /* innodb_file_io_threads used to be user settable.
1255  It is now just a combination of read_io_threads and
1256  write_io_threads that is set by innodb internally. */
1257 
1258  /* Now overwrite the value on srv_n_file_io_threads */
1259  srv_n_file_io_threads = 2 + srv_n_read_io_threads
1260  + srv_n_write_io_threads;
1261 
1262  ut_a(srv_n_file_io_threads <= SRV_MAX_N_IO_THREADS);
1263 
1264  /* TODO: Investigate if SRV_N_PENDING_IOS_PER_THREAD (32) limit
1265  still applies to windows. */
1266  if (!srv_use_native_aio) {
1267  io_limit = 8 * SRV_N_PENDING_IOS_PER_THREAD;
1268  } else {
1269  io_limit = SRV_N_PENDING_IOS_PER_THREAD;
1270  }
1271 
1272  os_aio_init(io_limit,
1273  srv_n_read_io_threads,
1274  srv_n_write_io_threads,
1275  SRV_MAX_N_PENDING_SYNC_IOS);
1276 
1277  fil_init(srv_file_per_table ? 50000 : 5000,
1278  srv_max_n_open_files);
1279 
1280  /* Print time to initialize the buffer pool */
1281 
1282  if (srv_buf_pool_size >= 1024 * 1024 * 1024) {
1283  drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Initializing buffer pool, size = %.1fG",
1284  ((double) srv_buf_pool_size) / (1024 * 1024 * 1024));
1285  } else {
1286  drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Initializing buffer pool, size = %.1fM",
1287  ((double) srv_buf_pool_size) / (1024 * 1024));
1288  }
1289 
1290  err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
1291 
1292  drizzled::errmsg_printf(drizzled::error::INFO, "InnoDB: Completed initialization of buffer pool");
1293 
1294  if (err != DB_SUCCESS) {
1295  drizzled::errmsg_printf(drizzled::error::ERROR, "InnoDB: Fatal error: cannot allocate the memory for the buffer pool");
1296 
1297  return(DB_ERROR);
1298  }
1299 
1300 #ifdef UNIV_DEBUG
1301  /* We have observed deadlocks with a 5MB buffer pool but
1302  the actual lower limit could very well be a little higher. */
1303 
1304  if (srv_buf_pool_size <= 5 * 1024 * 1024) {
1305 
1306  drizzled::errmsg_printf(drizzled::error::WARN, "InnoDB: Warning: Small buffer pool size "
1307  "(%luM), the flst_validate() debug function "
1308  "can cause a deadlock if the buffer pool fills up.\n",
1309  srv_buf_pool_size / 1024 / 1024);
1310  }
1311 #endif
1312 
1313  fsp_init();
1314  log_init();
1315 
1316  lock_sys_create(srv_lock_table_size);
1317 
1318  /* Create i/o-handler threads: */
1319 
1320  for (i = 0; i < srv_n_file_io_threads; i++) {
1321  n[i] = i;
1322 
1323  os_thread_create(io_handler_thread, n + i, thread_ids + i);
1324  }
1325 
1326 #ifdef UNIV_LOG_ARCHIVE
1327  if (0 != ut_strcmp(srv_log_group_home_dirs[0], srv_arch_dir)) {
1328  drizzled::errmsg_printf(drizzled::error::ERROR,
1329  "InnoDB: Error: you must set the log group home dir in my.cnf the same as log arch dir.");
1330 
1331  return(DB_ERROR);
1332  }
1333 #endif /* UNIV_LOG_ARCHIVE */
1334 
1335  if (sizeof(ulint) == 4
1336  && srv_n_log_files * srv_log_file_size
1337  >= (1UL << (32 - UNIV_PAGE_SIZE_SHIFT))) {
1338  drizzled::errmsg_printf(drizzled::error::ERROR,
1339  "InnoDB: Error: combined size of log files must be < 4 GB on 32-bit systems\n");
1340 
1341  return(DB_ERROR);
1342  }
1343 
1344  sum_of_new_sizes = 0;
1345 
1346  for (i = 0; i < srv_n_data_files; i++) {
1347 #ifndef __WIN__
1348  if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= (1UL << (32 - UNIV_PAGE_SIZE_SHIFT))) {
1349  drizzled::errmsg_printf(drizzled::error::ERROR,
1350  "InnoDB: Error: file size must be < 4 GB with this MySQL binary and operating system combination,"
1351  " in some OS's < 2 GB\n");
1352 
1353  return(DB_ERROR);
1354  }
1355 #endif
1356  sum_of_new_sizes += srv_data_file_sizes[i];
1357  }
1358 
1359  if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) {
1360  drizzled::errmsg_printf(drizzled::error::ERROR, "InnoDB: Error: tablespace size must be at least 10 MB");
1361 
1362  return(DB_ERROR);
1363  }
1364 
1365  err = open_or_create_data_files(&create_new_db,
1366 #ifdef UNIV_LOG_ARCHIVE
1367  &min_arch_log_no, &max_arch_log_no,
1368 #endif /* UNIV_LOG_ARCHIVE */
1369  &min_flushed_lsn, &max_flushed_lsn,
1370  &sum_of_new_sizes);
1371  if (err != DB_SUCCESS) {
1372  drizzled::errmsg_printf(drizzled::error::ERROR,
1373  "InnoDB: Could not open or create data files.\n"
1374  "InnoDB: If you tried to add new data files, and it failed here,\n"
1375  "InnoDB: you should now edit innodb_data_file_path in my.cnf back\n"
1376  "InnoDB: to what it was, and remove the new ibdata files InnoDB created\n"
1377  "InnoDB: in this failed attempt. InnoDB only wrote those files full of\n"
1378  "InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n"
1379  "InnoDB: remove old data files which contain your precious data!\n");
1380 
1381  return((int) err);
1382  }
1383 
1384 #ifdef UNIV_LOG_ARCHIVE
1385  srv_normalize_path_for_win(srv_arch_dir);
1386  srv_arch_dir = srv_add_path_separator_if_needed(srv_arch_dir);
1387 #endif /* UNIV_LOG_ARCHIVE */
1388 
1389  for (i = 0; i < srv_n_log_files; i++) {
1390  err = open_or_create_log_file(create_new_db, &log_file_created,
1391  log_opened, 0, i);
1392  if (err != DB_SUCCESS) {
1393 
1394  return((int) err);
1395  }
1396 
1397  if (log_file_created) {
1398  log_created = TRUE;
1399  } else {
1400  log_opened = TRUE;
1401  }
1402  if ((log_opened && create_new_db)
1403  || (log_opened && log_created)) {
1404  drizzled::errmsg_printf(drizzled::error::ERROR,
1405  "InnoDB: Error: all log files must be created at the same time.\n"
1406  "InnoDB: All log files must be created also in database creation.\n"
1407  "InnoDB: If you want bigger or smaller log files, shut down the\n"
1408  "InnoDB: database and make sure there were no errors in shutdown.\n"
1409  "InnoDB: Then delete the existing log files. Edit the .cnf file\n"
1410  "InnoDB: and start the database again.\n");
1411 
1412  return(DB_ERROR);
1413  }
1414  }
1415 
1416  /* Open all log files and data files in the system tablespace: we
1417  keep them open until database shutdown */
1418 
1419  fil_open_log_and_system_tablespace_files();
1420 
1421  if (log_created && !create_new_db
1422 #ifdef UNIV_LOG_ARCHIVE
1423  && !srv_archive_recovery
1424 #endif /* UNIV_LOG_ARCHIVE */
1425  ) {
1426  if (max_flushed_lsn != min_flushed_lsn
1427 #ifdef UNIV_LOG_ARCHIVE
1428  || max_arch_log_no != min_arch_log_no
1429 #endif /* UNIV_LOG_ARCHIVE */
1430  ) {
1431  drizzled::errmsg_printf(drizzled::error::ERROR,
1432  "InnoDB: Cannot initialize created log files because\n"
1433  "InnoDB: data files were not in sync with each other\n"
1434  "InnoDB: or the data files are corrupt.\n");
1435 
1436  return(DB_ERROR);
1437  }
1438 
1439  if (max_flushed_lsn < (ib_uint64_t) 1000) {
1440  drizzled::errmsg_printf(drizzled::error::ERROR,
1441  "InnoDB: Cannot initialize created log files because\n"
1442  "InnoDB: data files are corrupt, or new data files were\n"
1443  "InnoDB: created when the database was started previous\n"
1444  "InnoDB: time but the database was not shut down\n"
1445  "InnoDB: normally after that.\n");
1446 
1447  return(DB_ERROR);
1448  }
1449 
1450  mutex_enter(&(log_sys->mutex));
1451 
1452 #ifdef UNIV_LOG_ARCHIVE
1453  /* Do not + 1 arch_log_no because we do not use log
1454  archiving */
1455  recv_reset_logs(max_flushed_lsn, max_arch_log_no, TRUE);
1456 #else
1457  recv_reset_logs(max_flushed_lsn, TRUE);
1458 #endif /* UNIV_LOG_ARCHIVE */
1459 
1460  mutex_exit(&(log_sys->mutex));
1461  }
1462 
1464 
1465  if (create_new_db) {
1466  mtr_start(&mtr);
1467 
1468  fsp_header_init(0, sum_of_new_sizes, &mtr);
1469 
1470  mtr_commit(&mtr);
1471 
1472  /* To maintain backward compatibility we create only
1473  the first rollback segment before the double write buffer.
1474  All the remaining rollback segments will be created later,
1475  after the double write buffer has been created. */
1476  trx_sys_create();
1477 
1478  dict_create();
1479 
1481 
1482 #ifdef UNIV_LOG_ARCHIVE
1483  } else if (srv_archive_recovery) {
1484  drizzled::errmsg_printf(drizzled::error::INFO,
1485  "InnoDB: Starting archive recovery from a backup...");
1486  err = recv_recovery_from_archive_start(
1487  min_flushed_lsn, srv_archive_recovery_limit_lsn,
1488  min_arch_log_no);
1489  if (err != DB_SUCCESS) {
1490 
1491  return(DB_ERROR);
1492  }
1493  /* Since ibuf init is in dict_boot, and ibuf is needed
1494  in any disk i/o, first call dict_boot */
1495 
1496  dict_boot();
1497 
1499 
1501 
1502  /* Initialize the fsp free limit global variable in the log
1503  system */
1504  fsp_header_get_free_limit();
1505 
1506  recv_recovery_from_archive_finish();
1507 #endif /* UNIV_LOG_ARCHIVE */
1508  } else {
1509 
1510  /* Check if we support the max format that is stamped
1511  on the system tablespace.
1512  Note: We are NOT allowed to make any modifications to
1513  the TRX_SYS_PAGE_NO page before recovery because this
1514  page also contains the max_trx_id etc. important system
1515  variables that are required for recovery. We need to
1516  ensure that we return the system to a state where normal
1517  recovery is guaranteed to work. We do this by
1518  invalidating the buffer cache, this will force the
1519  reread of the page and restoration to its last known
1520  consistent state, this is REQUIRED for the recovery
1521  process to work. */
1524 
1525  if (err != DB_SUCCESS) {
1526  return(err);
1527  }
1528 
1529  /* Invalidate the buffer pool to ensure that we reread
1530  the page that we read above, during recovery.
1531  Note that this is not as heavy weight as it seems. At
1532  this point there will be only ONE page in the buf_LRU
1533  and there must be no page in the buf_flush list. */
1534  buf_pool_invalidate();
1535 
1536  /* We always try to do a recovery, even if the database had
1537  been shut down normally: this is the normal startup path */
1538 
1539  err = recv_recovery_from_checkpoint_start(LOG_CHECKPOINT,
1540  IB_ULONGLONG_MAX,
1541  min_flushed_lsn,
1542  max_flushed_lsn);
1543  if (err != DB_SUCCESS) {
1544 
1545  return(DB_ERROR);
1546  }
1547 
1548  /* Since the insert buffer init is in dict_boot, and the
1549  insert buffer is needed in any disk i/o, first we call
1550  dict_boot(). Note that trx_sys_init_at_db_start() only needs
1551  to access space 0, and the insert buffer at this stage already
1552  works for space 0. */
1553 
1554  dict_boot();
1556 
1557  /* Initialize the fsp free limit global variable in the log
1558  system */
1559  fsp_header_get_free_limit();
1560 
1561  /* recv_recovery_from_checkpoint_finish needs trx lists which
1562  are initialized in trx_sys_init_at_db_start(). */
1563 
1565 
1566  if (srv_apply_log_only)
1567  goto skip_processes;
1568 
1569  if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) {
1570  /* The following call is necessary for the insert
1571  buffer to work with multiple tablespaces. We must
1572  know the mapping between space id's and .ibd file
1573  names.
1574 
1575  In a crash recovery, we check that the info in data
1576  dictionary is consistent with what we already know
1577  about space id's from the call of
1578  fil_load_single_table_tablespaces().
1579 
1580  In a normal startup, we create the space objects for
1581  every table in the InnoDB data dictionary that has
1582  an .ibd file.
1583 
1584  We also determine the maximum tablespace id used. */
1585 
1586  dict_check_tablespaces_and_store_max_id(
1588  }
1589 
1592 
1593  /* It is possible that file_format tag has never
1594  been set. In this case we initialize it to minimum
1595  value. Important to note that we can do it ONLY after
1596  we have finished the recovery process so that the
1597  image of TRX_SYS_PAGE_NO is not stale. */
1599  }
1600 
1601  if (!create_new_db && sum_of_new_sizes > 0) {
1602  /* New data file(s) were added */
1603  mtr_start(&mtr);
1604 
1605  fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
1606 
1607  mtr_commit(&mtr);
1608 
1609  /* Immediately write the log record about increased tablespace
1610  size to disk, so that it is durable even if mysqld would crash
1611  quickly */
1612 
1614  }
1615 
1616 #ifdef UNIV_LOG_ARCHIVE
1617  /* Archiving is always off under MySQL */
1618  if (!srv_log_archive_on) {
1619  ut_a(DB_SUCCESS == log_archive_noarchivelog());
1620  } else {
1621  mutex_enter(&(log_sys->mutex));
1622 
1623  start_archive = FALSE;
1624 
1625  if (log_sys->archiving_state == LOG_ARCH_OFF) {
1626  start_archive = TRUE;
1627  }
1628 
1629  mutex_exit(&(log_sys->mutex));
1630 
1631  if (start_archive) {
1632  ut_a(DB_SUCCESS == log_archive_archivelog());
1633  }
1634  }
1635 #endif /* UNIV_LOG_ARCHIVE */
1636 
1637  /* fprintf(stderr, "Max allowed record size %lu\n",
1638  page_get_free_space_of_empty() / 2); */
1639 
1640  if (trx_doublewrite == NULL) {
1641  /* Create the doublewrite buffer to a new tablespace */
1642 
1644  }
1645 
1646  /* Here the double write buffer has already been created and so
1647  any new rollback segments will be allocated after the double
1648  write buffer. The default segment should already exist.
1649  We create the new segments only if it's a new database or
1650  the database was shutdown cleanly. */
1651 
1652  /* Note: When creating the extra rollback segments during an upgrade
1653  we violate the latching order, even if the change buffer is empty.
1654  We make an exception in sync0sync.c and check srv_is_being_started
1655  for that violation. It cannot create a deadlock because we are still
1656  running in single threaded mode essentially. Only the IO threads
1657  should be running at this stage. */
1658 
1659  trx_sys_create_rsegs(TRX_SYS_N_RSEGS - 1);
1660 
1661  /* Create the thread which watches the timeouts for lock waits */
1663  thread_ids + 2 + SRV_MAX_N_IO_THREADS);
1664 
1665  /* Create the thread which warns of long semaphore waits */
1667  thread_ids + 3 + SRV_MAX_N_IO_THREADS);
1668 
1669  /* Create the thread which prints InnoDB monitor info */
1671  thread_ids + 4 + SRV_MAX_N_IO_THREADS);
1672 
1673  /* Create the thread which automaticaly dumps/restore buffer pool */
1675  thread_ids + 5 + SRV_MAX_N_IO_THREADS);
1676 
1677  srv_is_being_started = FALSE;
1678 
1679  err = dict_create_or_check_foreign_constraint_tables();
1680 
1681  if (err != DB_SUCCESS) {
1682  return((int)DB_ERROR);
1683  }
1684 
1685  /* Create the master thread which does purge and other utility
1686  operations */
1687 
1688  os_thread_create(&srv_master_thread, NULL, thread_ids
1689  + (1 + SRV_MAX_N_IO_THREADS));
1690 
1691  /* Currently we allow only a single purge thread. */
1692  ut_a(srv_n_purge_threads == 0 || srv_n_purge_threads == 1);
1693 
1694  /* If the user has requested a separate purge thread then
1695  start the purge thread. */
1696  if (srv_n_purge_threads == 1) {
1697  os_thread_create(&srv_purge_thread, NULL, NULL);
1698  }
1699 
1700 #ifdef UNIV_DEBUG
1701  /* buf_debug_prints = TRUE; */
1702 #endif /* UNIV_DEBUG */
1703  sum_of_data_file_sizes = 0;
1704 
1705  for (i = 0; i < srv_n_data_files; i++) {
1706  sum_of_data_file_sizes += srv_data_file_sizes[i];
1707  }
1708 
1709  tablespace_size_in_header = fsp_header_get_tablespace_size();
1710 
1711  if (!srv_auto_extend_last_data_file
1712  && sum_of_data_file_sizes != tablespace_size_in_header) {
1713 
1714  drizzled::errmsg_printf(drizzled::error::ERROR,
1715  "InnoDB: Error: tablespace size stored in header is %lu pages, but the sum of data file sizes is %lu pages.",
1716  (ulong) tablespace_size_in_header,
1717  (ulong) sum_of_data_file_sizes);
1718 
1719  if (srv_force_recovery == 0
1720  && sum_of_data_file_sizes < tablespace_size_in_header) {
1721  /* This is a fatal error, the tail of a tablespace is
1722  missing */
1723 
1724  drizzled::errmsg_printf(drizzled::error::ERROR,
1725  "InnoDB: Cannot start InnoDB. The tail of the system tablespace is "
1726  "missing. Have you edited innodb_data_file_path in my.cnf in an "
1727  "inappropriate way, removing ibdata files from there? "
1728  "You can set innodb_force_recovery=1 in my.cnf to force "
1729  "a startup if you are trying to recover a badly corrupt database.");
1730 
1731  return(DB_ERROR);
1732  }
1733  }
1734 
1735  if (srv_auto_extend_last_data_file
1736  && sum_of_data_file_sizes < tablespace_size_in_header) {
1737 
1738  drizzled::errmsg_printf(drizzled::error::ERROR,
1739  "InnoDB: Error: tablespace size stored in header is %lu pages, but the sum of data file sizes"
1740  " is only %lu pages\n",
1741  (ulong) tablespace_size_in_header,
1742  (ulong) sum_of_data_file_sizes);
1743 
1744  if (srv_force_recovery == 0) {
1745 
1746  drizzled::errmsg_printf(drizzled::error::ERROR,
1747  "InnoDB: Cannot start InnoDB. The tail of the system tablespace is "
1748  "missing. Have you edited innodb_data_file_path in my.cnf in an "
1749  "inappropriate way, removing ibdata files from there? "
1750  "You can set innodb_force_recovery=1 in my.cnf to force "
1751  "a startup if you are trying to recover a badly corrupt database.\n");
1752 
1753  return(DB_ERROR);
1754  }
1755  }
1756 
1757  /* Check that os_fast_mutexes work as expected */
1758  os_fast_mutex_init(&srv_os_test_mutex);
1759 
1760  if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
1761  drizzled::errmsg_printf(drizzled::error::ERROR,
1762  "InnoDB: Error: pthread_mutex_trylock returns an unexpected value on success! Cannot continue.\n");
1763  exit(1);
1764  }
1765 
1766  os_fast_mutex_unlock(&srv_os_test_mutex);
1767 
1768  os_fast_mutex_lock(&srv_os_test_mutex);
1769 
1770  os_fast_mutex_unlock(&srv_os_test_mutex);
1771 
1772  os_fast_mutex_free(&srv_os_test_mutex);
1773 
1774  if (srv_print_verbose_log) {
1775  drizzled::errmsg_printf(drizzled::error::INFO,
1776  "InnoDB %s started; log sequence number %"PRIu64"\n",
1777  INNODB_VERSION_STR, srv_start_lsn);
1778  }
1779 
1780  if (srv_force_recovery > 0) {
1781  drizzled::errmsg_printf(drizzled::error::ERROR,
1782  "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
1783  (ulong) srv_force_recovery);
1784  }
1785 
1787  /* Actually, we did not change the undo log format between
1788  4.0 and 4.1.1, and we would not need to run purge to
1789  completion. Note also that the purge algorithm in 4.1.1
1790  can process the the history list again even after a full
1791  purge, because our algorithm does not cut the end of the
1792  history list in all cases so that it would become empty
1793  after a full purge. That mean that we may purge 4.0 type
1794  undo log even after this phase.
1795 
1796  The insert buffer record format changed between 4.0 and
1797  4.1.1. It is essential that the insert buffer is emptied
1798  here! */
1799 
1800  drizzled::errmsg_printf(drizzled::error::INFO,
1801  "InnoDB: You are upgrading to an InnoDB version which allows multiple. "
1802  "tablespaces. Wait that purge and insert buffer merge run to completion...");
1803  for (;;) {
1804  os_thread_sleep(1000000);
1805 
1806  if (0 == strcmp(srv_main_thread_op_info,
1807  "waiting for server activity")) {
1808 
1809  ut_a(ibuf_is_empty());
1810 
1811  break;
1812  }
1813  }
1814  drizzled::errmsg_printf(drizzled::error::INFO,
1815  "InnoDB: Full purge and insert buffer merge completed.");
1816 
1818 
1819  drizzled::errmsg_printf(drizzled::error::INFO,
1820  "InnoDB: You have now successfully upgraded"
1821  " to the multiple tablespaces\n"
1822  "InnoDB: format. You should NOT DOWNGRADE"
1823  " to an earlier version of\n"
1824  "InnoDB: InnoDB! But if you absolutely need to"
1825  " downgrade, see\n"
1826  "InnoDB: " REFMAN "multiple-tablespaces.html\n"
1827  "InnoDB: for instructions.\n");
1828  }
1829 
1830  if (srv_force_recovery == 0) {
1831  /* In the insert buffer we may have even bigger tablespace
1832  id's, because we may have dropped those tablespaces, but
1833  insert buffer merge has not had time to clean the records from
1834  the ibuf tree. */
1835 
1836  ibuf_update_max_tablespace_id();
1837  }
1838 
1839 skip_processes:
1840  srv_file_per_table = srv_file_per_table_original_value;
1841 
1842  srv_was_started = TRUE;
1843 
1844  return((int) DB_SUCCESS);
1845 }
1846 
1847 /****************************************************************/
1850 UNIV_INTERN
1851 int
1853 /*=============================*/
1854 {
1855  ulint i;
1856  if (!srv_was_started) {
1857  if (srv_is_being_started) {
1858  drizzled::errmsg_printf(drizzled::error::ERROR,
1859  "InnoDB: Warning: shutting down a not properly started or created database!");
1860  }
1861 
1862  return(DB_SUCCESS);
1863  }
1864 
1865  /* 1. Flush the buffer pool to disk, write the current lsn to
1866  the tablespace header(s), and copy all log data to archive.
1867  The step 1 is the real InnoDB shutdown. The remaining steps 2 - ...
1868  just free data structures after the shutdown. */
1869 
1870 
1871  if (srv_fast_shutdown == 2) {
1872  drizzled::errmsg_printf(drizzled::error::INFO,
1873  "InnoDB: MySQL has requested a very fast shutdown without flushing "
1874  "the InnoDB buffer pool to data files. At the next mysqld startup "
1875  "InnoDB will do a crash recovery!");
1876  }
1877 
1879 
1880  if (srv_conc_n_threads != 0) {
1881  drizzled::errmsg_printf(drizzled::error::WARN,
1882  "InnoDB: Warning: query counter shows %ld queries still InnoDB: inside InnoDB at shutdown.",
1883  srv_conc_n_threads);
1884  }
1885 
1886  /* 2. Make all threads created by InnoDB to exit */
1887 
1889 
1890  /* In a 'very fast' shutdown, we do not need to wait for these threads
1891  to die; all which counts is that we flushed the log; a 'very fast'
1892  shutdown is essentially a crash. */
1893 
1894  if (srv_fast_shutdown == 2) {
1895  return(DB_SUCCESS);
1896  }
1897 
1898  /* All threads end up waiting for certain events. Put those events
1899  to the signaled state. Then the threads will exit themselves in
1900  os_thread_event_wait(). */
1901 
1902  for (i = 0; i < 1000; i++) {
1903  /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
1904  HERE OR EARLIER */
1905 
1906  /* a. Let the lock timeout thread exit */
1907  os_event_set(srv_lock_timeout_thread_event);
1908 
1909  /* b. srv error monitor thread exits automatically, no need
1910  to do anything here */
1911 
1912  /* c. We wake the master thread so that it exits */
1914 
1915  /* d. We wake the purge thread so that it exits */
1917 
1918  /* e. Exit the i/o threads */
1919 
1921 
1923 
1924  if (os_thread_count == 0) {
1925  /* All the threads have exited or are just exiting;
1926  NOTE that the threads may not have completed their
1927  exit yet. Should we use pthread_join() to make sure
1928  they have exited? If we did, we would have to
1929  remove the pthread_detach() from
1930  os_thread_exit(). Now we just sleep 0.1
1931  seconds and hope that is enough! */
1932 
1934 
1935  os_thread_sleep(100000);
1936 
1937  break;
1938  }
1939 
1941 
1942  os_thread_sleep(100000);
1943  }
1944 
1945  if (i == 1000) {
1946  drizzled::errmsg_printf(drizzled::error::WARN,
1947  "InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!",
1948  (ulong) os_thread_count);
1949  }
1950 
1951  if (srv_monitor_file) {
1952  fclose(srv_monitor_file);
1953  srv_monitor_file = 0;
1954  if (srv_monitor_file_name) {
1955  unlink(srv_monitor_file_name);
1956  mem_free(srv_monitor_file_name);
1957  }
1958  }
1959  if (srv_dict_tmpfile) {
1960  fclose(srv_dict_tmpfile);
1961  srv_dict_tmpfile = 0;
1962  }
1963 
1964  if (srv_misc_tmpfile) {
1965  fclose(srv_misc_tmpfile);
1966  srv_misc_tmpfile = 0;
1967  }
1968 
1969  /* This must be disabled before closing the buffer pool
1970  and closing the data dictionary. */
1971  btr_search_disable();
1972 
1973  ibuf_close();
1974  log_shutdown();
1975  lock_sys_close();
1976  thr_local_close();
1978  trx_sys_close();
1979 
1980  mutex_free(&srv_monitor_file_mutex);
1981  mutex_free(&srv_dict_tmpfile_mutex);
1982  mutex_free(&srv_misc_tmpfile_mutex);
1983  dict_close();
1984  btr_search_sys_free();
1985 
1986  /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
1987  them */
1988  os_aio_free();
1989  sync_close();
1990  srv_free();
1991  fil_close();
1992 
1993  /* 4. Free the os_conc_mutex and all os_events and os_mutexes */
1994 
1995  os_sync_free();
1996 
1997  /* 5. Free all allocated memory */
1998 
1999  pars_lexer_close();
2000  log_mem_free();
2001  buf_pool_free(srv_buf_pool_instances);
2002  mem_close();
2003 
2004  /* ut_free_all_mem() frees all allocated memory not freed yet
2005  in shutdown, and it will also free the ut_list_mutex, so it
2006  should be the last one for all operation */
2007  ut_free_all_mem();
2008 
2009  if (os_thread_count != 0
2010  || os_event_count != 0
2011  || os_mutex_count != 0
2012  || os_fast_mutex_count != 0) {
2013  drizzled::errmsg_printf(drizzled::error::WARN,
2014  "InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
2015  "InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
2016  (ulong) os_thread_count, (ulong) os_event_count,
2017  (ulong) os_mutex_count, (ulong) os_fast_mutex_count);
2018  }
2019 
2020  if (dict_foreign_err_file) {
2021  fclose(dict_foreign_err_file);
2022  }
2023  if (lock_latest_err_file) {
2024  fclose(lock_latest_err_file);
2025  }
2026 
2027  if (srv_print_verbose_log) {
2028  drizzled::errmsg_printf(drizzled::error::INFO,
2029  "InnoDB: Shutdown completed log sequence number %"PRIu64,
2031  }
2032 
2033  srv_was_started = FALSE;
2034  srv_start_has_been_called = FALSE;
2035 
2036  return((int) DB_SUCCESS);
2037 }
2038 #endif /* !UNIV_HOTBACKUP */