~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/srv/srv0start.cc

  • Committer: Brian Aker
  • Date: 2008-10-29 13:46:43 UTC
  • Revision ID: brian@tangent.org-20081029134643-z6jcwjvyruhk2vlu
Updates for ignore file.

Show diffs side-by-side

added added

removed removed

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