~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/os/os0file.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
5
This program is free software; you can redistribute it and/or modify it under
 
6
the terms of the GNU General Public License as published by the Free Software
 
7
Foundation; version 2 of the License.
 
8
 
 
9
This program is distributed in the hope that it will be useful, but WITHOUT
 
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
12
 
 
13
You should have received a copy of the GNU General Public License along with
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
 
16
 
 
17
*****************************************************************************/
 
18
/***********************************************************************
 
19
 
 
20
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
21
Copyright (c) 2009, Percona Inc.
 
22
 
 
23
Portions of this file contain modifications contributed and copyrighted
 
24
by Percona Inc.. Those modifications are
 
25
gratefully acknowledged and are described briefly in the InnoDB
 
26
documentation. The contributions by Percona Inc. are incorporated with
 
27
their permission, and subject to the conditions contained in the file
 
28
COPYING.Percona.
 
29
 
 
30
This program is free software; you can redistribute it and/or modify it
 
31
under the terms of the GNU General Public License as published by the
 
32
Free Software Foundation; version 2 of the License.
 
33
 
 
34
This program is distributed in the hope that it will be useful, but
 
35
WITHOUT ANY WARRANTY; without even the implied warranty of
 
36
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 
37
Public License for more details.
 
38
 
 
39
You should have received a copy of the GNU General Public License along
 
40
with this program; if not, write to the Free Software Foundation, Inc.,
 
41
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
42
 
 
43
***********************************************************************/
 
44
 
 
45
/**************************************************//**
 
46
@file os/os0file.c
 
47
The interface to the operating system file i/o primitives
 
48
 
 
49
Created 10/21/1995 Heikki Tuuri
 
50
*******************************************************/
 
51
 
 
52
#include "os0file.h"
 
53
#include "ut0mem.h"
 
54
#include "srv0srv.h"
 
55
#include "srv0start.h"
 
56
#include "fil0fil.h"
 
57
#include "buf0buf.h"
 
58
#ifndef UNIV_HOTBACKUP
 
59
# include "os0sync.h"
 
60
# include "os0thread.h"
 
61
#else /* !UNIV_HOTBACKUP */
 
62
# ifdef __WIN__
 
63
/* Add includes for the _stat() call to compile on Windows */
 
64
#  include <sys/types.h>
 
65
#  include <sys/stat.h>
 
66
#  include <errno.h>
 
67
# endif /* __WIN__ */
 
68
#endif /* !UNIV_HOTBACKUP */
 
69
 
 
70
/* This specifies the file permissions InnoDB uses when it creates files in
 
71
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
 
72
my_umask */
 
73
 
 
74
#ifndef __WIN__
 
75
/** Umask for creating files */
 
76
UNIV_INTERN ulint       os_innodb_umask
 
77
                        = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
 
78
#else
 
79
/** Umask for creating files */
 
80
UNIV_INTERN ulint       os_innodb_umask         = 0;
 
81
#endif
 
82
 
 
83
#ifdef UNIV_DO_FLUSH
 
84
/* If the following is set to TRUE, we do not call os_file_flush in every
 
85
os_file_write. We can set this TRUE when the doublewrite buffer is used. */
 
86
UNIV_INTERN ibool       os_do_not_call_flush_at_each_write      = FALSE;
 
87
#else
 
88
/* We do not call os_file_flush in every os_file_write. */
 
89
#endif /* UNIV_DO_FLUSH */
 
90
 
 
91
#ifdef UNIV_HOTBACKUP
 
92
# define os_aio_use_native_aio  FALSE
 
93
#else /* UNIV_HOTBACKUP */
 
94
/* We use these mutexes to protect lseek + file i/o operation, if the
 
95
OS does not provide an atomic pread or pwrite, or similar */
 
96
#define OS_FILE_N_SEEK_MUTEXES  16
 
97
UNIV_INTERN os_mutex_t  os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES];
 
98
 
 
99
/* In simulated aio, merge at most this many consecutive i/os */
 
100
#define OS_AIO_MERGE_N_CONSECUTIVE      64
 
101
 
 
102
/** If this flag is TRUE, then we will use the native aio of the
 
103
OS (provided we compiled Innobase with it in), otherwise we will
 
104
use simulated aio we build below with threads */
 
105
 
 
106
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
 
107
 
 
108
/** Flag: enable debug printout for asynchronous i/o */
 
109
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
 
110
 
 
111
/** The asynchronous i/o array slot structure */
 
112
typedef struct os_aio_slot_struct       os_aio_slot_t;
 
113
 
 
114
/** The asynchronous i/o array slot structure */
 
115
struct os_aio_slot_struct{
 
116
        ibool           is_read;        /*!< TRUE if a read operation */
 
117
        ulint           pos;            /*!< index of the slot in the aio
 
118
                                        array */
 
119
        ibool           reserved;       /*!< TRUE if this slot is reserved */
 
120
        time_t          reservation_time;/*!< time when reserved */
 
121
        ulint           len;            /*!< length of the block to read or
 
122
                                        write */
 
123
        byte*           buf;            /*!< buffer used in i/o */
 
124
        ulint           type;           /*!< OS_FILE_READ or OS_FILE_WRITE */
 
125
        ulint           offset;         /*!< 32 low bits of file offset in
 
126
                                        bytes */
 
127
        ulint           offset_high;    /*!< 32 high bits of file offset */
 
128
        os_file_t       file;           /*!< file where to read or write */
 
129
        const char*     name;           /*!< file name or path */
 
130
        ibool           io_already_done;/*!< used only in simulated aio:
 
131
                                        TRUE if the physical i/o already
 
132
                                        made and only the slot message
 
133
                                        needs to be passed to the caller
 
134
                                        of os_aio_simulated_handle */
 
135
        fil_node_t*     message1;       /*!< message which is given by the */
 
136
        void*           message2;       /*!< the requester of an aio operation
 
137
                                        and which can be used to identify
 
138
                                        which pending aio operation was
 
139
                                        completed */
 
140
#ifdef WIN_ASYNC_IO
 
141
        os_event_t      event;          /*!< event object we need in the
 
142
                                        OVERLAPPED struct */
 
143
        OVERLAPPED      control;        /*!< Windows control block for the
 
144
                                        aio request */
 
145
#endif
 
146
};
 
147
 
 
148
/** The asynchronous i/o array structure */
 
149
typedef struct os_aio_array_struct      os_aio_array_t;
 
150
 
 
151
/** The asynchronous i/o array structure */
 
152
struct os_aio_array_struct{
 
153
        os_mutex_t      mutex;  /*!< the mutex protecting the aio array */
 
154
        os_event_t      not_full;
 
155
                                /*!< The event which is set to the
 
156
                                signaled state when there is space in
 
157
                                the aio outside the ibuf segment */
 
158
        os_event_t      is_empty;
 
159
                                /*!< The event which is set to the
 
160
                                signaled state when there are no
 
161
                                pending i/os in this array */
 
162
        ulint           n_slots;/*!< Total number of slots in the aio
 
163
                                array.  This must be divisible by
 
164
                                n_threads. */
 
165
        ulint           n_segments;
 
166
                                /*!< Number of segments in the aio
 
167
                                array of pending aio requests. A
 
168
                                thread can wait separately for any one
 
169
                                of the segments. */
 
170
        ulint           n_reserved;
 
171
                                /*!< Number of reserved slots in the
 
172
                                aio array outside the ibuf segment */
 
173
        os_aio_slot_t*  slots;  /*!< Pointer to the slots in the array */
 
174
#ifdef __WIN__
 
175
        os_native_event_t* native_events;
 
176
                                /*!< Pointer to an array of OS native
 
177
                                event handles where we copied the
 
178
                                handles from slots, in the same
 
179
                                order. This can be used in
 
180
                                WaitForMultipleObjects; used only in
 
181
                                Windows */
 
182
#endif
 
183
};
 
184
 
 
185
/** Array of events used in simulated aio */
 
186
static os_event_t*      os_aio_segment_wait_events      = NULL;
 
187
 
 
188
/** The aio arrays for non-ibuf i/o and ibuf i/o, as well as sync aio. These
 
189
are NULL when the module has not yet been initialized. @{ */
 
190
static os_aio_array_t*  os_aio_read_array       = NULL; /*!< Reads */
 
191
static os_aio_array_t*  os_aio_write_array      = NULL; /*!< Writes */
 
192
static os_aio_array_t*  os_aio_ibuf_array       = NULL; /*!< Insert buffer */
 
193
static os_aio_array_t*  os_aio_log_array        = NULL; /*!< Redo log */
 
194
static os_aio_array_t*  os_aio_sync_array       = NULL; /*!< Synchronous I/O */
 
195
/* @} */
 
196
 
 
197
/** Number of asynchronous I/O segments.  Set by os_aio_init(). */
 
198
static ulint    os_aio_n_segments       = ULINT_UNDEFINED;
 
199
 
 
200
/** If the following is TRUE, read i/o handler threads try to
 
201
wait until a batch of new read requests have been posted */
 
202
static ibool    os_aio_recommend_sleep_for_read_threads = FALSE;
 
203
#endif /* UNIV_HOTBACKUP */
 
204
 
 
205
UNIV_INTERN ulint       os_n_file_reads         = 0;
 
206
UNIV_INTERN ulint       os_bytes_read_since_printout = 0;
 
207
UNIV_INTERN ulint       os_n_file_writes        = 0;
 
208
UNIV_INTERN ulint       os_n_fsyncs             = 0;
 
209
UNIV_INTERN ulint       os_n_file_reads_old     = 0;
 
210
UNIV_INTERN ulint       os_n_file_writes_old    = 0;
 
211
UNIV_INTERN ulint       os_n_fsyncs_old         = 0;
 
212
UNIV_INTERN time_t      os_last_printout;
 
213
 
 
214
UNIV_INTERN ibool       os_has_said_disk_full   = FALSE;
 
215
 
 
216
#ifndef UNIV_HOTBACKUP
 
217
/** The mutex protecting the following counts of pending I/O operations */
 
218
static os_mutex_t       os_file_count_mutex;
 
219
#endif /* !UNIV_HOTBACKUP */
 
220
/** Number of pending os_file_pread() operations */
 
221
UNIV_INTERN ulint       os_file_n_pending_preads  = 0;
 
222
/** Number of pending os_file_pwrite() operations */
 
223
UNIV_INTERN ulint       os_file_n_pending_pwrites = 0;
 
224
/** Number of pending write operations */
 
225
UNIV_INTERN ulint       os_n_pending_writes = 0;
 
226
/** Number of pending read operations */
 
227
UNIV_INTERN ulint       os_n_pending_reads = 0;
 
228
 
 
229
/***********************************************************************//**
 
230
Gets the operating system version. Currently works only on Windows.
 
231
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
 
232
UNIV_INTERN
 
233
ulint
 
234
os_get_os_version(void)
 
235
/*===================*/
 
236
{
 
237
#ifdef __WIN__
 
238
        OSVERSIONINFO     os_info;
 
239
 
 
240
        os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
241
 
 
242
        ut_a(GetVersionEx(&os_info));
 
243
 
 
244
        if (os_info.dwPlatformId == VER_PLATFORM_WIN32s) {
 
245
                return(OS_WIN31);
 
246
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
 
247
                return(OS_WIN95);
 
248
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
 
249
                if (os_info.dwMajorVersion <= 4) {
 
250
                        return(OS_WINNT);
 
251
                } else {
 
252
                        return(OS_WIN2000);
 
253
                }
 
254
        } else {
 
255
                ut_error;
 
256
                return(0);
 
257
        }
 
258
#else
 
259
        ut_error;
 
260
 
 
261
        return(0);
 
262
#endif
 
263
}
 
264
 
 
265
/***********************************************************************//**
 
266
Retrieves the last error number if an error occurs in a file io function.
 
267
The number should be retrieved before any other OS calls (because they may
 
268
overwrite the error number). If the number is not known to this program,
 
269
the OS error number + 100 is returned.
 
270
@return error number, or OS error number + 100 */
 
271
UNIV_INTERN
 
272
ulint
 
273
os_file_get_last_error(
 
274
/*===================*/
 
275
        ibool   report_all_errors)      /*!< in: TRUE if we want an error message
 
276
                                        printed of all errors */
 
277
{
 
278
        ulint   err;
 
279
 
 
280
#ifdef __WIN__
 
281
 
 
282
        err = (ulint) GetLastError();
 
283
 
 
284
        if (report_all_errors
 
285
            || (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS)) {
 
286
 
 
287
                ut_print_timestamp(stderr);
 
288
                fprintf(stderr,
 
289
                        "  InnoDB: Operating system error number %lu"
 
290
                        " in a file operation.\n", (ulong) err);
 
291
 
 
292
                if (err == ERROR_PATH_NOT_FOUND) {
 
293
                        fprintf(stderr,
 
294
                                "InnoDB: The error means the system"
 
295
                                " cannot find the path specified.\n");
 
296
 
 
297
                        if (srv_is_being_started) {
 
298
                                fprintf(stderr,
 
299
                                        "InnoDB: If you are installing InnoDB,"
 
300
                                        " remember that you must create\n"
 
301
                                        "InnoDB: directories yourself, InnoDB"
 
302
                                        " does not create them.\n");
 
303
                        }
 
304
                } else if (err == ERROR_ACCESS_DENIED) {
 
305
                        fprintf(stderr,
 
306
                                "InnoDB: The error means mysqld does not have"
 
307
                                " the access rights to\n"
 
308
                                "InnoDB: the directory. It may also be"
 
309
                                " you have created a subdirectory\n"
 
310
                                "InnoDB: of the same name as a data file.\n");
 
311
                } else if (err == ERROR_SHARING_VIOLATION
 
312
                           || err == ERROR_LOCK_VIOLATION) {
 
313
                        fprintf(stderr,
 
314
                                "InnoDB: The error means that another program"
 
315
                                " is using InnoDB's files.\n"
 
316
                                "InnoDB: This might be a backup or antivirus"
 
317
                                " software or another instance\n"
 
318
                                "InnoDB: of MySQL."
 
319
                                " Please close it to get rid of this error.\n");
 
320
                } else if (err == ERROR_WORKING_SET_QUOTA
 
321
                           || err == ERROR_NO_SYSTEM_RESOURCES) {
 
322
                        fprintf(stderr,
 
323
                                "InnoDB: The error means that there are no"
 
324
                                " sufficient system resources or quota to"
 
325
                                " complete the operation.\n");
 
326
                } else if (err == ERROR_OPERATION_ABORTED) {
 
327
                        fprintf(stderr,
 
328
                                "InnoDB: The error means that the I/O"
 
329
                                " operation has been aborted\n"
 
330
                                "InnoDB: because of either a thread exit"
 
331
                                " or an application request.\n"
 
332
                                "InnoDB: Retry attempt is made.\n");
 
333
                } else {
 
334
                        fprintf(stderr,
 
335
                                "InnoDB: Some operating system error numbers"
 
336
                                " are described at\n"
 
337
                                "InnoDB: "
 
338
                                REFMAN
 
339
                                "operating-system-error-codes.html\n");
 
340
                }
 
341
        }
 
342
 
 
343
        fflush(stderr);
 
344
 
 
345
        if (err == ERROR_FILE_NOT_FOUND) {
 
346
                return(OS_FILE_NOT_FOUND);
 
347
        } else if (err == ERROR_DISK_FULL) {
 
348
                return(OS_FILE_DISK_FULL);
 
349
        } else if (err == ERROR_FILE_EXISTS) {
 
350
                return(OS_FILE_ALREADY_EXISTS);
 
351
        } else if (err == ERROR_SHARING_VIOLATION
 
352
                   || err == ERROR_LOCK_VIOLATION) {
 
353
                return(OS_FILE_SHARING_VIOLATION);
 
354
        } else if (err == ERROR_WORKING_SET_QUOTA
 
355
                   || err == ERROR_NO_SYSTEM_RESOURCES) {
 
356
                return(OS_FILE_INSUFFICIENT_RESOURCE);
 
357
        } else if (err == ERROR_OPERATION_ABORTED) {
 
358
                return(OS_FILE_OPERATION_ABORTED);
 
359
        } else {
 
360
                return(100 + err);
 
361
        }
 
362
#else
 
363
        err = (ulint) errno;
 
364
 
 
365
        if (report_all_errors
 
366
            || (err != ENOSPC && err != EEXIST)) {
 
367
 
 
368
                ut_print_timestamp(stderr);
 
369
                fprintf(stderr,
 
370
                        "  InnoDB: Operating system error number %lu"
 
371
                        " in a file operation.\n", (ulong) err);
 
372
 
 
373
                if (err == ENOENT) {
 
374
                        fprintf(stderr,
 
375
                                "InnoDB: The error means the system"
 
376
                                " cannot find the path specified.\n");
 
377
 
 
378
                        if (srv_is_being_started) {
 
379
                                fprintf(stderr,
 
380
                                        "InnoDB: If you are installing InnoDB,"
 
381
                                        " remember that you must create\n"
 
382
                                        "InnoDB: directories yourself, InnoDB"
 
383
                                        " does not create them.\n");
 
384
                        }
 
385
                } else if (err == EACCES) {
 
386
                        fprintf(stderr,
 
387
                                "InnoDB: The error means mysqld does not have"
 
388
                                " the access rights to\n"
 
389
                                "InnoDB: the directory.\n");
 
390
                } else {
 
391
                        if (strerror((int)err) != NULL) {
 
392
                                fprintf(stderr,
 
393
                                        "InnoDB: Error number %lu"
 
394
                                        " means '%s'.\n",
 
395
                                        err, strerror((int)err));
 
396
                        }
 
397
 
 
398
                        fprintf(stderr,
 
399
                                "InnoDB: Some operating system"
 
400
                                " error numbers are described at\n"
 
401
                                "InnoDB: "
 
402
                                REFMAN
 
403
                                "operating-system-error-codes.html\n");
 
404
                }
 
405
        }
 
406
 
 
407
        fflush(stderr);
 
408
 
 
409
        if (err == ENOSPC) {
 
410
                return(OS_FILE_DISK_FULL);
 
411
        } else if (err == ENOENT) {
 
412
                return(OS_FILE_NOT_FOUND);
 
413
        } else if (err == EEXIST) {
 
414
                return(OS_FILE_ALREADY_EXISTS);
 
415
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
 
416
                return(OS_FILE_PATH_ERROR);
 
417
        } else {
 
418
                return(100 + err);
 
419
        }
 
420
#endif
 
421
}
 
422
 
 
423
/****************************************************************//**
 
424
Does error handling when a file operation fails.
 
425
Conditionally exits (calling exit(3)) based on should_exit value and the
 
426
error type
 
427
@return TRUE if we should retry the operation */
 
428
static
 
429
ibool
 
430
os_file_handle_error_cond_exit(
 
431
/*===========================*/
 
432
        const char*     name,           /*!< in: name of a file or NULL */
 
433
        const char*     operation,      /*!< in: operation */
 
434
        ibool           should_exit)    /*!< in: call exit(3) if unknown error
 
435
                                        and this parameter is TRUE */
 
436
{
 
437
        ulint   err;
 
438
 
 
439
        err = os_file_get_last_error(FALSE);
 
440
 
 
441
        if (err == OS_FILE_DISK_FULL) {
 
442
                /* We only print a warning about disk full once */
 
443
 
 
444
                if (os_has_said_disk_full) {
 
445
 
 
446
                        return(FALSE);
 
447
                }
 
448
 
 
449
                if (name) {
 
450
                        ut_print_timestamp(stderr);
 
451
                        fprintf(stderr,
 
452
                                "  InnoDB: Encountered a problem with"
 
453
                                " file %s\n", name);
 
454
                }
 
455
 
 
456
                ut_print_timestamp(stderr);
 
457
                fprintf(stderr,
 
458
                        "  InnoDB: Disk is full. Try to clean the disk"
 
459
                        " to free space.\n");
 
460
 
 
461
                os_has_said_disk_full = TRUE;
 
462
 
 
463
                fflush(stderr);
 
464
 
 
465
                return(FALSE);
 
466
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
 
467
 
 
468
                return(TRUE);
 
469
        } else if (err == OS_FILE_ALREADY_EXISTS
 
470
                   || err == OS_FILE_PATH_ERROR) {
 
471
 
 
472
                return(FALSE);
 
473
        } else if (err == OS_FILE_SHARING_VIOLATION) {
 
474
 
 
475
                os_thread_sleep(10000000);  /* 10 sec */
 
476
                return(TRUE);
 
477
        } else if (err == OS_FILE_INSUFFICIENT_RESOURCE) {
 
478
 
 
479
                os_thread_sleep(100000);        /* 100 ms */
 
480
                return(TRUE);
 
481
        } else if (err == OS_FILE_OPERATION_ABORTED) {
 
482
 
 
483
                os_thread_sleep(100000);        /* 100 ms */
 
484
                return(TRUE);
 
485
        } else {
 
486
                if (name) {
 
487
                        fprintf(stderr, "InnoDB: File name %s\n", name);
 
488
                }
 
489
 
 
490
                fprintf(stderr, "InnoDB: File operation call: '%s'.\n",
 
491
                        operation);
 
492
 
 
493
                if (should_exit) {
 
494
                        fprintf(stderr, "InnoDB: Cannot continue operation.\n");
 
495
 
 
496
                        fflush(stderr);
 
497
 
 
498
                        exit(1);
 
499
                }
 
500
        }
 
501
 
 
502
        return(FALSE);
 
503
}
 
504
 
 
505
/****************************************************************//**
 
506
Does error handling when a file operation fails.
 
507
@return TRUE if we should retry the operation */
 
508
static
 
509
ibool
 
510
os_file_handle_error(
 
511
/*=================*/
 
512
        const char*     name,   /*!< in: name of a file or NULL */
 
513
        const char*     operation)/*!< in: operation */
 
514
{
 
515
        /* exit in case of unknown error */
 
516
        return(os_file_handle_error_cond_exit(name, operation, TRUE));
 
517
}
 
518
 
 
519
/****************************************************************//**
 
520
Does error handling when a file operation fails.
 
521
@return TRUE if we should retry the operation */
 
522
static
 
523
ibool
 
524
os_file_handle_error_no_exit(
 
525
/*=========================*/
 
526
        const char*     name,   /*!< in: name of a file or NULL */
 
527
        const char*     operation)/*!< in: operation */
 
528
{
 
529
        /* don't exit in case of unknown error */
 
530
        return(os_file_handle_error_cond_exit(name, operation, FALSE));
 
531
}
 
532
 
 
533
#undef USE_FILE_LOCK
 
534
#define USE_FILE_LOCK
 
535
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
 
536
/* InnoDB Hot Backup does not lock the data files.
 
537
 * On Windows, mandatory locking is used.
 
538
 */
 
539
# undef USE_FILE_LOCK
 
540
#endif
 
541
#ifdef USE_FILE_LOCK
 
542
/****************************************************************//**
 
543
Obtain an exclusive lock on a file.
 
544
@return 0 on success */
 
545
static
 
546
int
 
547
os_file_lock(
 
548
/*=========*/
 
549
        int             fd,     /*!< in: file descriptor */
 
550
        const char*     name)   /*!< in: file name */
 
551
{
 
552
        struct flock lk;
 
553
        lk.l_type = F_WRLCK;
 
554
        lk.l_whence = SEEK_SET;
 
555
        lk.l_start = lk.l_len = 0;
 
556
        if (fcntl(fd, F_SETLK, &lk) == -1) {
 
557
                fprintf(stderr,
 
558
                        "InnoDB: Unable to lock %s, error: %d\n", name, errno);
 
559
 
 
560
                if (errno == EAGAIN || errno == EACCES) {
 
561
                        fprintf(stderr,
 
562
                                "InnoDB: Check that you do not already have"
 
563
                                " another mysqld process\n"
 
564
                                "InnoDB: using the same InnoDB data"
 
565
                                " or log files.\n");
 
566
                }
 
567
 
 
568
                return(-1);
 
569
        }
 
570
 
 
571
        return(0);
 
572
}
 
573
#endif /* USE_FILE_LOCK */
 
574
 
 
575
#ifndef UNIV_HOTBACKUP
 
576
/****************************************************************//**
 
577
Creates the seek mutexes used in positioned reads and writes. */
 
578
UNIV_INTERN
 
579
void
 
580
os_io_init_simple(void)
 
581
/*===================*/
 
582
{
 
583
        ulint   i;
 
584
 
 
585
        os_file_count_mutex = os_mutex_create(NULL);
 
586
 
 
587
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
 
588
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
 
589
        }
 
590
}
 
591
 
 
592
/***********************************************************************//**
 
593
Creates a temporary file.  This function is like tmpfile(3), but
 
594
the temporary file is created in the MySQL temporary directory.
 
595
On Netware, this function is like tmpfile(3), because the C run-time
 
596
library of Netware does not expose the delete-on-close flag.
 
597
@return temporary file handle, or NULL on error */
 
598
UNIV_INTERN
 
599
FILE*
 
600
os_file_create_tmpfile(void)
 
601
/*========================*/
 
602
{
 
603
#ifdef __NETWARE__
 
604
        FILE*   file    = tmpfile();
 
605
#else /* __NETWARE__ */
 
606
        FILE*   file    = NULL;
 
607
        int     fd      = innobase_mysql_tmpfile();
 
608
 
 
609
        if (fd >= 0) {
 
610
                file = fdopen(fd, "w+b");
 
611
        }
 
612
#endif /* __NETWARE__ */
 
613
 
 
614
        if (!file) {
 
615
                ut_print_timestamp(stderr);
 
616
                fprintf(stderr,
 
617
                        "  InnoDB: Error: unable to create temporary file;"
 
618
                        " errno: %d\n", errno);
 
619
#ifndef __NETWARE__
 
620
                if (fd >= 0) {
 
621
                        close(fd);
 
622
                }
 
623
#endif /* !__NETWARE__ */
 
624
        }
 
625
 
 
626
        return(file);
 
627
}
 
628
#endif /* !UNIV_HOTBACKUP */
 
629
 
 
630
/***********************************************************************//**
 
631
The os_file_opendir() function opens a directory stream corresponding to the
 
632
directory named by the dirname argument. The directory stream is positioned
 
633
at the first entry. In both Unix and Windows we automatically skip the '.'
 
634
and '..' items at the start of the directory listing.
 
635
@return directory stream, NULL if error */
 
636
UNIV_INTERN
 
637
os_file_dir_t
 
638
os_file_opendir(
 
639
/*============*/
 
640
        const char*     dirname,        /*!< in: directory name; it must not
 
641
                                        contain a trailing '\' or '/' */
 
642
        ibool           error_is_fatal) /*!< in: TRUE if we should treat an
 
643
                                        error as a fatal error; if we try to
 
644
                                        open symlinks then we do not wish a
 
645
                                        fatal error if it happens not to be
 
646
                                        a directory */
 
647
{
 
648
        os_file_dir_t           dir;
 
649
#ifdef __WIN__
 
650
        LPWIN32_FIND_DATA       lpFindFileData;
 
651
        char                    path[OS_FILE_MAX_PATH + 3];
 
652
 
 
653
        ut_a(strlen(dirname) < OS_FILE_MAX_PATH);
 
654
 
 
655
        strcpy(path, dirname);
 
656
        strcpy(path + strlen(path), "\\*");
 
657
 
 
658
        /* Note that in Windows opening the 'directory stream' also retrieves
 
659
        the first entry in the directory. Since it is '.', that is no problem,
 
660
        as we will skip over the '.' and '..' entries anyway. */
 
661
 
 
662
        lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
 
663
 
 
664
        dir = FindFirstFile((LPCTSTR) path, lpFindFileData);
 
665
 
 
666
        ut_free(lpFindFileData);
 
667
 
 
668
        if (dir == INVALID_HANDLE_VALUE) {
 
669
 
 
670
                if (error_is_fatal) {
 
671
                        os_file_handle_error(dirname, "opendir");
 
672
                }
 
673
 
 
674
                return(NULL);
 
675
        }
 
676
 
 
677
        return(dir);
 
678
#else
 
679
        dir = opendir(dirname);
 
680
 
 
681
        if (dir == NULL && error_is_fatal) {
 
682
                os_file_handle_error(dirname, "opendir");
 
683
        }
 
684
 
 
685
        return(dir);
 
686
#endif
 
687
}
 
688
 
 
689
/***********************************************************************//**
 
690
Closes a directory stream.
 
691
@return 0 if success, -1 if failure */
 
692
UNIV_INTERN
 
693
int
 
694
os_file_closedir(
 
695
/*=============*/
 
696
        os_file_dir_t   dir)    /*!< in: directory stream */
 
697
{
 
698
#ifdef __WIN__
 
699
        BOOL            ret;
 
700
 
 
701
        ret = FindClose(dir);
 
702
 
 
703
        if (!ret) {
 
704
                os_file_handle_error_no_exit(NULL, "closedir");
 
705
 
 
706
                return(-1);
 
707
        }
 
708
 
 
709
        return(0);
 
710
#else
 
711
        int     ret;
 
712
 
 
713
        ret = closedir(dir);
 
714
 
 
715
        if (ret) {
 
716
                os_file_handle_error_no_exit(NULL, "closedir");
 
717
        }
 
718
 
 
719
        return(ret);
 
720
#endif
 
721
}
 
722
 
 
723
/***********************************************************************//**
 
724
This function returns information of the next file in the directory. We jump
 
725
over the '.' and '..' entries in the directory.
 
726
@return 0 if ok, -1 if error, 1 if at the end of the directory */
 
727
UNIV_INTERN
 
728
int
 
729
os_file_readdir_next_file(
 
730
/*======================*/
 
731
        const char*     dirname,/*!< in: directory name or path */
 
732
        os_file_dir_t   dir,    /*!< in: directory stream */
 
733
        os_file_stat_t* info)   /*!< in/out: buffer where the info is returned */
 
734
{
 
735
#ifdef __WIN__
 
736
        LPWIN32_FIND_DATA       lpFindFileData;
 
737
        BOOL                    ret;
 
738
 
 
739
        lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
 
740
next_file:
 
741
        ret = FindNextFile(dir, lpFindFileData);
 
742
 
 
743
        if (ret) {
 
744
                ut_a(strlen((char *) lpFindFileData->cFileName)
 
745
                     < OS_FILE_MAX_PATH);
 
746
 
 
747
                if (strcmp((char *) lpFindFileData->cFileName, ".") == 0
 
748
                    || strcmp((char *) lpFindFileData->cFileName, "..") == 0) {
 
749
 
 
750
                        goto next_file;
 
751
                }
 
752
 
 
753
                strcpy(info->name, (char *) lpFindFileData->cFileName);
 
754
 
 
755
                info->size = (ib_int64_t)(lpFindFileData->nFileSizeLow)
 
756
                        + (((ib_int64_t)(lpFindFileData->nFileSizeHigh))
 
757
                           << 32);
 
758
 
 
759
                if (lpFindFileData->dwFileAttributes
 
760
                    & FILE_ATTRIBUTE_REPARSE_POINT) {
 
761
                        /* TODO: test Windows symlinks */
 
762
                        /* TODO: MySQL has apparently its own symlink
 
763
                        implementation in Windows, dbname.sym can
 
764
                        redirect a database directory:
 
765
                        REFMAN "windows-symbolic-links.html" */
 
766
                        info->type = OS_FILE_TYPE_LINK;
 
767
                } else if (lpFindFileData->dwFileAttributes
 
768
                           & FILE_ATTRIBUTE_DIRECTORY) {
 
769
                        info->type = OS_FILE_TYPE_DIR;
 
770
                } else {
 
771
                        /* It is probably safest to assume that all other
 
772
                        file types are normal. Better to check them rather
 
773
                        than blindly skip them. */
 
774
 
 
775
                        info->type = OS_FILE_TYPE_FILE;
 
776
                }
 
777
        }
 
778
 
 
779
        ut_free(lpFindFileData);
 
780
 
 
781
        if (ret) {
 
782
                return(0);
 
783
        } else if (GetLastError() == ERROR_NO_MORE_FILES) {
 
784
 
 
785
                return(1);
 
786
        } else {
 
787
                os_file_handle_error_no_exit(dirname,
 
788
                                             "readdir_next_file");
 
789
                return(-1);
 
790
        }
 
791
#else
 
792
        struct dirent*  ent;
 
793
        char*           full_path;
 
794
        int             ret;
 
795
        struct stat     statinfo;
 
796
#ifdef HAVE_READDIR_R
 
797
        char            dirent_buf[sizeof(struct dirent)
 
798
                                   + _POSIX_PATH_MAX + 100];
 
799
        /* In /mysys/my_lib.c, _POSIX_PATH_MAX + 1 is used as
 
800
        the max file name len; but in most standards, the
 
801
        length is NAME_MAX; we add 100 to be even safer */
 
802
#endif
 
803
 
 
804
next_file:
 
805
 
 
806
#ifdef HAVE_READDIR_R
 
807
        ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
 
808
 
 
809
        if (ret != 0) {
 
810
                fprintf(stderr,
 
811
                        "InnoDB: cannot read directory %s, error %lu\n",
 
812
                        dirname, (ulong)ret);
 
813
 
 
814
                return(-1);
 
815
        }
 
816
 
 
817
        if (ent == NULL) {
 
818
                /* End of directory */
 
819
 
 
820
                return(1);
 
821
        }
 
822
 
 
823
        ut_a(strlen(ent->d_name) < _POSIX_PATH_MAX + 100 - 1);
 
824
#else
 
825
        ent = readdir(dir);
 
826
 
 
827
        if (ent == NULL) {
 
828
 
 
829
                return(1);
 
830
        }
 
831
#endif
 
832
        ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH);
 
833
 
 
834
        if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
 
835
 
 
836
                goto next_file;
 
837
        }
 
838
 
 
839
        strcpy(info->name, ent->d_name);
 
840
 
 
841
        full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10);
 
842
 
 
843
        sprintf(full_path, "%s/%s", dirname, ent->d_name);
 
844
 
 
845
        ret = stat(full_path, &statinfo);
 
846
 
 
847
        if (ret) {
 
848
 
 
849
                if (errno == ENOENT) {
 
850
                        /* readdir() returned a file that does not exist,
 
851
                        it must have been deleted in the meantime. Do what
 
852
                        would have happened if the file was deleted before
 
853
                        readdir() - ignore and go to the next entry.
 
854
                        If this is the last entry then info->name will still
 
855
                        contain the name of the deleted file when this
 
856
                        function returns, but this is not an issue since the
 
857
                        caller shouldn't be looking at info when end of
 
858
                        directory is returned. */
 
859
 
 
860
                        ut_free(full_path);
 
861
 
 
862
                        goto next_file;
 
863
                }
 
864
 
 
865
                os_file_handle_error_no_exit(full_path, "stat");
 
866
 
 
867
                ut_free(full_path);
 
868
 
 
869
                return(-1);
 
870
        }
 
871
 
 
872
        info->size = (ib_int64_t)statinfo.st_size;
 
873
 
 
874
        if (S_ISDIR(statinfo.st_mode)) {
 
875
                info->type = OS_FILE_TYPE_DIR;
 
876
        } else if (S_ISLNK(statinfo.st_mode)) {
 
877
                info->type = OS_FILE_TYPE_LINK;
 
878
        } else if (S_ISREG(statinfo.st_mode)) {
 
879
                info->type = OS_FILE_TYPE_FILE;
 
880
        } else {
 
881
                info->type = OS_FILE_TYPE_UNKNOWN;
 
882
        }
 
883
 
 
884
        ut_free(full_path);
 
885
 
 
886
        return(0);
 
887
#endif
 
888
}
 
889
 
 
890
/*****************************************************************//**
 
891
This function attempts to create a directory named pathname. The new directory
 
892
gets default permissions. On Unix the permissions are (0770 & ~umask). If the
 
893
directory exists already, nothing is done and the call succeeds, unless the
 
894
fail_if_exists arguments is true.
 
895
@return TRUE if call succeeds, FALSE on error */
 
896
UNIV_INTERN
 
897
ibool
 
898
os_file_create_directory(
 
899
/*=====================*/
 
900
        const char*     pathname,       /*!< in: directory name as
 
901
                                        null-terminated string */
 
902
        ibool           fail_if_exists) /*!< in: if TRUE, pre-existing directory
 
903
                                        is treated as an error. */
 
904
{
 
905
#ifdef __WIN__
 
906
        BOOL    rcode;
 
907
 
 
908
        rcode = CreateDirectory((LPCTSTR) pathname, NULL);
 
909
        if (!(rcode != 0
 
910
              || (GetLastError() == ERROR_ALREADY_EXISTS
 
911
                  && !fail_if_exists))) {
 
912
                /* failure */
 
913
                os_file_handle_error(pathname, "CreateDirectory");
 
914
 
 
915
                return(FALSE);
 
916
        }
 
917
 
 
918
        return (TRUE);
 
919
#else
 
920
        int     rcode;
 
921
 
 
922
        rcode = mkdir(pathname, 0770);
 
923
 
 
924
        if (!(rcode == 0 || (errno == EEXIST && !fail_if_exists))) {
 
925
                /* failure */
 
926
                os_file_handle_error(pathname, "mkdir");
 
927
 
 
928
                return(FALSE);
 
929
        }
 
930
 
 
931
        return (TRUE);
 
932
#endif
 
933
}
 
934
 
 
935
/****************************************************************//**
 
936
A simple function to open or create a file.
 
937
@return own: handle to the file, not defined if error, error number
 
938
can be retrieved with os_file_get_last_error */
 
939
UNIV_INTERN
 
940
os_file_t
 
941
os_file_create_simple(
 
942
/*==================*/
 
943
        const char*     name,   /*!< in: name of the file or path as a
 
944
                                null-terminated string */
 
945
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
 
946
                                opened (if does not exist, error), or
 
947
                                OS_FILE_CREATE if a new file is created
 
948
                                (if exists, error), or
 
949
                                OS_FILE_CREATE_PATH if new file
 
950
                                (if exists, error) and subdirectories along
 
951
                                its path are created (if needed)*/
 
952
        ulint           access_type,/*!< in: OS_FILE_READ_ONLY or
 
953
                                OS_FILE_READ_WRITE */
 
954
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
 
955
{
 
956
#ifdef __WIN__
 
957
        os_file_t       file;
 
958
        DWORD           create_flag;
 
959
        DWORD           access;
 
960
        DWORD           attributes      = 0;
 
961
        ibool           retry;
 
962
 
 
963
try_again:
 
964
        ut_a(name);
 
965
 
 
966
        if (create_mode == OS_FILE_OPEN) {
 
967
                create_flag = OPEN_EXISTING;
 
968
        } else if (create_mode == OS_FILE_CREATE) {
 
969
                create_flag = CREATE_NEW;
 
970
        } else if (create_mode == OS_FILE_CREATE_PATH) {
 
971
                /* create subdirs along the path if needed  */
 
972
                *success = os_file_create_subdirs_if_needed(name);
 
973
                if (!*success) {
 
974
                        ut_error;
 
975
                }
 
976
                create_flag = CREATE_NEW;
 
977
                create_mode = OS_FILE_CREATE;
 
978
        } else {
 
979
                create_flag = 0;
 
980
                ut_error;
 
981
        }
 
982
 
 
983
        if (access_type == OS_FILE_READ_ONLY) {
 
984
                access = GENERIC_READ;
 
985
        } else if (access_type == OS_FILE_READ_WRITE) {
 
986
                access = GENERIC_READ | GENERIC_WRITE;
 
987
        } else {
 
988
                access = 0;
 
989
                ut_error;
 
990
        }
 
991
 
 
992
        file = CreateFile((LPCTSTR) name,
 
993
                          access,
 
994
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
 
995
                          /* file can be read and written also
 
996
                          by other processes */
 
997
                          NULL, /* default security attributes */
 
998
                          create_flag,
 
999
                          attributes,
 
1000
                          NULL);        /*!< no template file */
 
1001
 
 
1002
        if (file == INVALID_HANDLE_VALUE) {
 
1003
                *success = FALSE;
 
1004
 
 
1005
                retry = os_file_handle_error(name,
 
1006
                                             create_mode == OS_FILE_OPEN ?
 
1007
                                             "open" : "create");
 
1008
                if (retry) {
 
1009
                        goto try_again;
 
1010
                }
 
1011
        } else {
 
1012
                *success = TRUE;
 
1013
        }
 
1014
 
 
1015
        return(file);
 
1016
#else /* __WIN__ */
 
1017
        os_file_t       file;
 
1018
        int             create_flag;
 
1019
        ibool           retry;
 
1020
 
 
1021
try_again:
 
1022
        ut_a(name);
 
1023
 
 
1024
        if (create_mode == OS_FILE_OPEN) {
 
1025
                if (access_type == OS_FILE_READ_ONLY) {
 
1026
                        create_flag = O_RDONLY;
 
1027
                } else {
 
1028
                        create_flag = O_RDWR;
 
1029
                }
 
1030
        } else if (create_mode == OS_FILE_CREATE) {
 
1031
                create_flag = O_RDWR | O_CREAT | O_EXCL;
 
1032
        } else if (create_mode == OS_FILE_CREATE_PATH) {
 
1033
                /* create subdirs along the path if needed  */
 
1034
                *success = os_file_create_subdirs_if_needed(name);
 
1035
                if (!*success) {
 
1036
                        return (-1);
 
1037
                }
 
1038
                create_flag = O_RDWR | O_CREAT | O_EXCL;
 
1039
                create_mode = OS_FILE_CREATE;
 
1040
        } else {
 
1041
                create_flag = 0;
 
1042
                ut_error;
 
1043
        }
 
1044
 
 
1045
        if (create_mode == OS_FILE_CREATE) {
 
1046
                file = open(name, create_flag, S_IRUSR | S_IWUSR
 
1047
                            | S_IRGRP | S_IWGRP);
 
1048
        } else {
 
1049
                file = open(name, create_flag);
 
1050
        }
 
1051
 
 
1052
        if (file == -1) {
 
1053
                *success = FALSE;
 
1054
 
 
1055
                retry = os_file_handle_error(name,
 
1056
                                             create_mode == OS_FILE_OPEN ?
 
1057
                                             "open" : "create");
 
1058
                if (retry) {
 
1059
                        goto try_again;
 
1060
                }
 
1061
#ifdef USE_FILE_LOCK
 
1062
        } else if (access_type == OS_FILE_READ_WRITE
 
1063
                   && os_file_lock(file, name)) {
 
1064
                *success = FALSE;
 
1065
                close(file);
 
1066
                file = -1;
 
1067
#endif
 
1068
        } else {
 
1069
                *success = TRUE;
 
1070
        }
 
1071
 
 
1072
        return(file);
 
1073
#endif /* __WIN__ */
 
1074
}
 
1075
 
 
1076
/****************************************************************//**
 
1077
A simple function to open or create a file.
 
1078
@return own: handle to the file, not defined if error, error number
 
1079
can be retrieved with os_file_get_last_error */
 
1080
UNIV_INTERN
 
1081
os_file_t
 
1082
os_file_create_simple_no_error_handling(
 
1083
/*====================================*/
 
1084
        const char*     name,   /*!< in: name of the file or path as a
 
1085
                                null-terminated string */
 
1086
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
 
1087
                                is opened (if does not exist, error), or
 
1088
                                OS_FILE_CREATE if a new file is created
 
1089
                                (if exists, error) */
 
1090
        ulint           access_type,/*!< in: OS_FILE_READ_ONLY,
 
1091
                                OS_FILE_READ_WRITE, or
 
1092
                                OS_FILE_READ_ALLOW_DELETE; the last option is
 
1093
                                used by a backup program reading the file */
 
1094
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
 
1095
{
 
1096
#ifdef __WIN__
 
1097
        os_file_t       file;
 
1098
        DWORD           create_flag;
 
1099
        DWORD           access;
 
1100
        DWORD           attributes      = 0;
 
1101
        DWORD           share_mode      = FILE_SHARE_READ | FILE_SHARE_WRITE;
 
1102
 
 
1103
        ut_a(name);
 
1104
 
 
1105
        if (create_mode == OS_FILE_OPEN) {
 
1106
                create_flag = OPEN_EXISTING;
 
1107
        } else if (create_mode == OS_FILE_CREATE) {
 
1108
                create_flag = CREATE_NEW;
 
1109
        } else {
 
1110
                create_flag = 0;
 
1111
                ut_error;
 
1112
        }
 
1113
 
 
1114
        if (access_type == OS_FILE_READ_ONLY) {
 
1115
                access = GENERIC_READ;
 
1116
        } else if (access_type == OS_FILE_READ_WRITE) {
 
1117
                access = GENERIC_READ | GENERIC_WRITE;
 
1118
        } else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
 
1119
                access = GENERIC_READ;
 
1120
                share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ
 
1121
                        | FILE_SHARE_WRITE;     /*!< A backup program has to give
 
1122
                                                mysqld the maximum freedom to
 
1123
                                                do what it likes with the
 
1124
                                                file */
 
1125
        } else {
 
1126
                access = 0;
 
1127
                ut_error;
 
1128
        }
 
1129
 
 
1130
        file = CreateFile((LPCTSTR) name,
 
1131
                          access,
 
1132
                          share_mode,
 
1133
                          NULL, /* default security attributes */
 
1134
                          create_flag,
 
1135
                          attributes,
 
1136
                          NULL);        /*!< no template file */
 
1137
 
 
1138
        if (file == INVALID_HANDLE_VALUE) {
 
1139
                *success = FALSE;
 
1140
        } else {
 
1141
                *success = TRUE;
 
1142
        }
 
1143
 
 
1144
        return(file);
 
1145
#else /* __WIN__ */
 
1146
        os_file_t       file;
 
1147
        int             create_flag;
 
1148
 
 
1149
        ut_a(name);
 
1150
 
 
1151
        if (create_mode == OS_FILE_OPEN) {
 
1152
                if (access_type == OS_FILE_READ_ONLY) {
 
1153
                        create_flag = O_RDONLY;
 
1154
                } else {
 
1155
                        create_flag = O_RDWR;
 
1156
                }
 
1157
        } else if (create_mode == OS_FILE_CREATE) {
 
1158
                create_flag = O_RDWR | O_CREAT | O_EXCL;
 
1159
        } else {
 
1160
                create_flag = 0;
 
1161
                ut_error;
 
1162
        }
 
1163
 
 
1164
        if (create_mode == OS_FILE_CREATE) {
 
1165
                file = open(name, create_flag, S_IRUSR | S_IWUSR
 
1166
                            | S_IRGRP | S_IWGRP);
 
1167
        } else {
 
1168
                file = open(name, create_flag);
 
1169
        }
 
1170
 
 
1171
        if (file == -1) {
 
1172
                *success = FALSE;
 
1173
#ifdef USE_FILE_LOCK
 
1174
        } else if (access_type == OS_FILE_READ_WRITE
 
1175
                   && os_file_lock(file, name)) {
 
1176
                *success = FALSE;
 
1177
                close(file);
 
1178
                file = -1;
 
1179
#endif
 
1180
        } else {
 
1181
                *success = TRUE;
 
1182
        }
 
1183
 
 
1184
        return(file);
 
1185
#endif /* __WIN__ */
 
1186
}
 
1187
 
 
1188
/****************************************************************//**
 
1189
Tries to disable OS caching on an opened file descriptor. */
 
1190
UNIV_INTERN
 
1191
void
 
1192
os_file_set_nocache(
 
1193
/*================*/
 
1194
        int             fd,             /*!< in: file descriptor to alter */
 
1195
        const char*     file_name,      /*!< in: file name, used in the
 
1196
                                        diagnostic message */
 
1197
        const char*     operation_name) /*!< in: "open" or "create"; used in the
 
1198
                                        diagnostic message */
 
1199
{
 
1200
        /* some versions of Solaris may not have DIRECTIO_ON */
 
1201
#if defined(UNIV_SOLARIS) && defined(DIRECTIO_ON)
 
1202
        if (directio(fd, DIRECTIO_ON) == -1) {
 
1203
                int     errno_save;
 
1204
                errno_save = (int)errno;
 
1205
                ut_print_timestamp(stderr);
 
1206
                fprintf(stderr,
 
1207
                        "  InnoDB: Failed to set DIRECTIO_ON "
 
1208
                        "on file %s: %s: %s, continuing anyway\n",
 
1209
                        file_name, operation_name, strerror(errno_save));
 
1210
        }
 
1211
#elif defined(O_DIRECT)
 
1212
        if (fcntl(fd, F_SETFL, O_DIRECT) == -1) {
 
1213
                int     errno_save;
 
1214
                errno_save = (int)errno;
 
1215
                ut_print_timestamp(stderr);
 
1216
                fprintf(stderr,
 
1217
                        "  InnoDB: Failed to set O_DIRECT "
 
1218
                        "on file %s: %s: %s, continuing anyway\n",
 
1219
                        file_name, operation_name, strerror(errno_save));
 
1220
                if (errno_save == EINVAL) {
 
1221
                        ut_print_timestamp(stderr);
 
1222
                        fprintf(stderr,
 
1223
                                "  InnoDB: O_DIRECT is known to result in "
 
1224
                                "'Invalid argument' on Linux on tmpfs, "
 
1225
                                "see MySQL Bug#26662\n");
 
1226
                }
 
1227
        }
 
1228
#endif
 
1229
}
 
1230
 
 
1231
/****************************************************************//**
 
1232
Opens an existing file or creates a new.
 
1233
@return own: handle to the file, not defined if error, error number
 
1234
can be retrieved with os_file_get_last_error */
 
1235
UNIV_INTERN
 
1236
os_file_t
 
1237
os_file_create(
 
1238
/*===========*/
 
1239
        const char*     name,   /*!< in: name of the file or path as a
 
1240
                                null-terminated string */
 
1241
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
 
1242
                                is opened (if does not exist, error), or
 
1243
                                OS_FILE_CREATE if a new file is created
 
1244
                                (if exists, error),
 
1245
                                OS_FILE_OVERWRITE if a new file is created
 
1246
                                or an old overwritten;
 
1247
                                OS_FILE_OPEN_RAW, if a raw device or disk
 
1248
                                partition should be opened */
 
1249
        ulint           purpose,/*!< in: OS_FILE_AIO, if asynchronous,
 
1250
                                non-buffered i/o is desired,
 
1251
                                OS_FILE_NORMAL, if any normal file;
 
1252
                                NOTE that it also depends on type, os_aio_..
 
1253
                                and srv_.. variables whether we really use
 
1254
                                async i/o or unbuffered i/o: look in the
 
1255
                                function source code for the exact rules */
 
1256
        ulint           type,   /*!< in: OS_DATA_FILE or OS_LOG_FILE */
 
1257
        ibool*          success)/*!< out: TRUE if succeed, FALSE if error */
 
1258
{
 
1259
#ifdef __WIN__
 
1260
        os_file_t       file;
 
1261
        DWORD           share_mode      = FILE_SHARE_READ;
 
1262
        DWORD           create_flag;
 
1263
        DWORD           attributes;
 
1264
        ibool           retry;
 
1265
try_again:
 
1266
        ut_a(name);
 
1267
 
 
1268
        if (create_mode == OS_FILE_OPEN_RAW) {
 
1269
                create_flag = OPEN_EXISTING;
 
1270
                share_mode = FILE_SHARE_WRITE;
 
1271
        } else if (create_mode == OS_FILE_OPEN
 
1272
                   || create_mode == OS_FILE_OPEN_RETRY) {
 
1273
                create_flag = OPEN_EXISTING;
 
1274
        } else if (create_mode == OS_FILE_CREATE) {
 
1275
                create_flag = CREATE_NEW;
 
1276
        } else if (create_mode == OS_FILE_OVERWRITE) {
 
1277
                create_flag = CREATE_ALWAYS;
 
1278
        } else {
 
1279
                create_flag = 0;
 
1280
                ut_error;
 
1281
        }
 
1282
 
 
1283
        if (purpose == OS_FILE_AIO) {
 
1284
                /* If specified, use asynchronous (overlapped) io and no
 
1285
                buffering of writes in the OS */
 
1286
                attributes = 0;
 
1287
#ifdef WIN_ASYNC_IO
 
1288
                if (os_aio_use_native_aio) {
 
1289
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
 
1290
                }
 
1291
#endif
 
1292
#ifdef UNIV_NON_BUFFERED_IO
 
1293
# ifndef UNIV_HOTBACKUP
 
1294
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
 
1295
                        /* Do not use unbuffered i/o to log files because
 
1296
                        value 2 denotes that we do not flush the log at every
 
1297
                        commit, but only once per second */
 
1298
                } else if (srv_win_file_flush_method
 
1299
                           == SRV_WIN_IO_UNBUFFERED) {
 
1300
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
 
1301
                }
 
1302
# else /* !UNIV_HOTBACKUP */
 
1303
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
 
1304
# endif /* !UNIV_HOTBACKUP */
 
1305
#endif /* UNIV_NON_BUFFERED_IO */
 
1306
        } else if (purpose == OS_FILE_NORMAL) {
 
1307
                attributes = 0;
 
1308
#ifdef UNIV_NON_BUFFERED_IO
 
1309
# ifndef UNIV_HOTBACKUP
 
1310
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
 
1311
                        /* Do not use unbuffered i/o to log files because
 
1312
                        value 2 denotes that we do not flush the log at every
 
1313
                        commit, but only once per second */
 
1314
                } else if (srv_win_file_flush_method
 
1315
                           == SRV_WIN_IO_UNBUFFERED) {
 
1316
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
 
1317
                }
 
1318
# else /* !UNIV_HOTBACKUP */
 
1319
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
 
1320
# endif /* !UNIV_HOTBACKUP */
 
1321
#endif /* UNIV_NON_BUFFERED_IO */
 
1322
        } else {
 
1323
                attributes = 0;
 
1324
                ut_error;
 
1325
        }
 
1326
 
 
1327
        file = CreateFile((LPCTSTR) name,
 
1328
                          GENERIC_READ | GENERIC_WRITE, /* read and write
 
1329
                                                        access */
 
1330
                          share_mode,   /* File can be read also by other
 
1331
                                        processes; we must give the read
 
1332
                                        permission because of ibbackup. We do
 
1333
                                        not give the write permission to
 
1334
                                        others because if one would succeed to
 
1335
                                        start 2 instances of mysqld on the
 
1336
                                        SAME files, that could cause severe
 
1337
                                        database corruption! When opening
 
1338
                                        raw disk partitions, Microsoft manuals
 
1339
                                        say that we must give also the write
 
1340
                                        permission. */
 
1341
                          NULL, /* default security attributes */
 
1342
                          create_flag,
 
1343
                          attributes,
 
1344
                          NULL);        /*!< no template file */
 
1345
 
 
1346
        if (file == INVALID_HANDLE_VALUE) {
 
1347
                *success = FALSE;
 
1348
 
 
1349
                /* When srv_file_per_table is on, file creation failure may not
 
1350
                be critical to the whole instance. Do not crash the server in
 
1351
                case of unknown errors. */
 
1352
                if (srv_file_per_table) {
 
1353
                        retry = os_file_handle_error_no_exit(name,
 
1354
                                                create_mode == OS_FILE_CREATE ?
 
1355
                                                "create" : "open");
 
1356
                } else {
 
1357
                        retry = os_file_handle_error(name,
 
1358
                                                create_mode == OS_FILE_CREATE ?
 
1359
                                                "create" : "open");
 
1360
                }
 
1361
 
 
1362
                if (retry) {
 
1363
                        goto try_again;
 
1364
                }
 
1365
        } else {
 
1366
                *success = TRUE;
 
1367
        }
 
1368
 
 
1369
        return(file);
 
1370
#else /* __WIN__ */
 
1371
        os_file_t       file;
 
1372
        int             create_flag;
 
1373
        ibool           retry;
 
1374
        const char*     mode_str        = NULL;
 
1375
        const char*     type_str        = NULL;
 
1376
        const char*     purpose_str     = NULL;
 
1377
 
 
1378
try_again:
 
1379
        ut_a(name);
 
1380
 
 
1381
        if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW
 
1382
            || create_mode == OS_FILE_OPEN_RETRY) {
 
1383
                mode_str = "OPEN";
 
1384
                create_flag = O_RDWR;
 
1385
        } else if (create_mode == OS_FILE_CREATE) {
 
1386
                mode_str = "CREATE";
 
1387
                create_flag = O_RDWR | O_CREAT | O_EXCL;
 
1388
        } else if (create_mode == OS_FILE_OVERWRITE) {
 
1389
                mode_str = "OVERWRITE";
 
1390
                create_flag = O_RDWR | O_CREAT | O_TRUNC;
 
1391
        } else {
 
1392
                create_flag = 0;
 
1393
                ut_error;
 
1394
        }
 
1395
 
 
1396
        if (type == OS_LOG_FILE) {
 
1397
                type_str = "LOG";
 
1398
        } else if (type == OS_DATA_FILE) {
 
1399
                type_str = "DATA";
 
1400
        } else {
 
1401
                ut_error;
 
1402
        }
 
1403
 
 
1404
        if (purpose == OS_FILE_AIO) {
 
1405
                purpose_str = "AIO";
 
1406
        } else if (purpose == OS_FILE_NORMAL) {
 
1407
                purpose_str = "NORMAL";
 
1408
        } else {
 
1409
                ut_error;
 
1410
        }
 
1411
 
 
1412
#if 0
 
1413
        fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n",
 
1414
                name, mode_str, type_str, purpose_str);
 
1415
#endif
 
1416
#ifdef O_SYNC
 
1417
        /* We let O_SYNC only affect log files; note that we map O_DSYNC to
 
1418
        O_SYNC because the datasync options seemed to corrupt files in 2001
 
1419
        in both Linux and Solaris */
 
1420
        if (type == OS_LOG_FILE
 
1421
            && srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
 
1422
 
 
1423
# if 0
 
1424
                fprintf(stderr, "Using O_SYNC for file %s\n", name);
 
1425
# endif
 
1426
 
 
1427
                create_flag = create_flag | O_SYNC;
 
1428
        }
 
1429
#endif /* O_SYNC */
 
1430
 
 
1431
        file = open(name, create_flag, os_innodb_umask);
 
1432
 
 
1433
        if (file == -1) {
 
1434
                *success = FALSE;
 
1435
 
 
1436
                /* When srv_file_per_table is on, file creation failure may not
 
1437
                be critical to the whole instance. Do not crash the server in
 
1438
                case of unknown errors. */
 
1439
                if (srv_file_per_table) {
 
1440
                        retry = os_file_handle_error_no_exit(name,
 
1441
                                                create_mode == OS_FILE_CREATE ?
 
1442
                                                "create" : "open");
 
1443
                } else {
 
1444
                        retry = os_file_handle_error(name,
 
1445
                                                create_mode == OS_FILE_CREATE ?
 
1446
                                                "create" : "open");
 
1447
                }
 
1448
 
 
1449
                if (retry) {
 
1450
                        goto try_again;
 
1451
                } else {
 
1452
                        return(file /* -1 */);
 
1453
                }
 
1454
        }
 
1455
        /* else */
 
1456
 
 
1457
        *success = TRUE;
 
1458
 
 
1459
        /* We disable OS caching (O_DIRECT) only on data files */
 
1460
        if (type != OS_LOG_FILE
 
1461
            && srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
 
1462
                
 
1463
                os_file_set_nocache(file, name, mode_str);
 
1464
        }
 
1465
 
 
1466
#ifdef USE_FILE_LOCK
 
1467
        if (create_mode != OS_FILE_OPEN_RAW && os_file_lock(file, name)) {
 
1468
 
 
1469
                if (create_mode == OS_FILE_OPEN_RETRY) {
 
1470
                        int i;
 
1471
                        ut_print_timestamp(stderr);
 
1472
                        fputs("  InnoDB: Retrying to lock"
 
1473
                              " the first data file\n",
 
1474
                              stderr);
 
1475
                        for (i = 0; i < 100; i++) {
 
1476
                                os_thread_sleep(1000000);
 
1477
                                if (!os_file_lock(file, name)) {
 
1478
                                        *success = TRUE;
 
1479
                                        return(file);
 
1480
                                }
 
1481
                        }
 
1482
                        ut_print_timestamp(stderr);
 
1483
                        fputs("  InnoDB: Unable to open the first data file\n",
 
1484
                              stderr);
 
1485
                }
 
1486
 
 
1487
                *success = FALSE;
 
1488
                close(file);
 
1489
                file = -1;
 
1490
        }
 
1491
#endif /* USE_FILE_LOCK */
 
1492
 
 
1493
        return(file);
 
1494
#endif /* __WIN__ */
 
1495
}
 
1496
 
 
1497
/***********************************************************************//**
 
1498
Deletes a file if it exists. The file has to be closed before calling this.
 
1499
@return TRUE if success */
 
1500
UNIV_INTERN
 
1501
ibool
 
1502
os_file_delete_if_exists(
 
1503
/*=====================*/
 
1504
        const char*     name)   /*!< in: file path as a null-terminated string */
 
1505
{
 
1506
#ifdef __WIN__
 
1507
        BOOL    ret;
 
1508
        ulint   count   = 0;
 
1509
loop:
 
1510
        /* In Windows, deleting an .ibd file may fail if ibbackup is copying
 
1511
        it */
 
1512
 
 
1513
        ret = DeleteFile((LPCTSTR)name);
 
1514
 
 
1515
        if (ret) {
 
1516
                return(TRUE);
 
1517
        }
 
1518
 
 
1519
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
 
1520
                /* the file does not exist, this not an error */
 
1521
 
 
1522
                return(TRUE);
 
1523
        }
 
1524
 
 
1525
        count++;
 
1526
 
 
1527
        if (count > 100 && 0 == (count % 10)) {
 
1528
                fprintf(stderr,
 
1529
                        "InnoDB: Warning: cannot delete file %s\n"
 
1530
                        "InnoDB: Are you running ibbackup"
 
1531
                        " to back up the file?\n", name);
 
1532
 
 
1533
                os_file_get_last_error(TRUE); /* print error information */
 
1534
        }
 
1535
 
 
1536
        os_thread_sleep(1000000);       /* sleep for a second */
 
1537
 
 
1538
        if (count > 2000) {
 
1539
 
 
1540
                return(FALSE);
 
1541
        }
 
1542
 
 
1543
        goto loop;
 
1544
#else
 
1545
        int     ret;
 
1546
 
 
1547
        ret = unlink(name);
 
1548
 
 
1549
        if (ret != 0 && errno != ENOENT) {
 
1550
                os_file_handle_error_no_exit(name, "delete");
 
1551
 
 
1552
                return(FALSE);
 
1553
        }
 
1554
 
 
1555
        return(TRUE);
 
1556
#endif
 
1557
}
 
1558
 
 
1559
/***********************************************************************//**
 
1560
Deletes a file. The file has to be closed before calling this.
 
1561
@return TRUE if success */
 
1562
UNIV_INTERN
 
1563
ibool
 
1564
os_file_delete(
 
1565
/*===========*/
 
1566
        const char*     name)   /*!< in: file path as a null-terminated string */
 
1567
{
 
1568
#ifdef __WIN__
 
1569
        BOOL    ret;
 
1570
        ulint   count   = 0;
 
1571
loop:
 
1572
        /* In Windows, deleting an .ibd file may fail if ibbackup is copying
 
1573
        it */
 
1574
 
 
1575
        ret = DeleteFile((LPCTSTR)name);
 
1576
 
 
1577
        if (ret) {
 
1578
                return(TRUE);
 
1579
        }
 
1580
 
 
1581
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
 
1582
                /* If the file does not exist, we classify this as a 'mild'
 
1583
                error and return */
 
1584
 
 
1585
                return(FALSE);
 
1586
        }
 
1587
 
 
1588
        count++;
 
1589
 
 
1590
        if (count > 100 && 0 == (count % 10)) {
 
1591
                fprintf(stderr,
 
1592
                        "InnoDB: Warning: cannot delete file %s\n"
 
1593
                        "InnoDB: Are you running ibbackup"
 
1594
                        " to back up the file?\n", name);
 
1595
 
 
1596
                os_file_get_last_error(TRUE); /* print error information */
 
1597
        }
 
1598
 
 
1599
        os_thread_sleep(1000000);       /* sleep for a second */
 
1600
 
 
1601
        if (count > 2000) {
 
1602
 
 
1603
                return(FALSE);
 
1604
        }
 
1605
 
 
1606
        goto loop;
 
1607
#else
 
1608
        int     ret;
 
1609
 
 
1610
        ret = unlink(name);
 
1611
 
 
1612
        if (ret != 0) {
 
1613
                os_file_handle_error_no_exit(name, "delete");
 
1614
 
 
1615
                return(FALSE);
 
1616
        }
 
1617
 
 
1618
        return(TRUE);
 
1619
#endif
 
1620
}
 
1621
 
 
1622
/***********************************************************************//**
 
1623
Renames a file (can also move it to another directory). It is safest that the
 
1624
file is closed before calling this function.
 
1625
@return TRUE if success */
 
1626
UNIV_INTERN
 
1627
ibool
 
1628
os_file_rename(
 
1629
/*===========*/
 
1630
        const char*     oldpath,/*!< in: old file path as a null-terminated
 
1631
                                string */
 
1632
        const char*     newpath)/*!< in: new file path */
 
1633
{
 
1634
#ifdef __WIN__
 
1635
        BOOL    ret;
 
1636
 
 
1637
        ret = MoveFile((LPCTSTR)oldpath, (LPCTSTR)newpath);
 
1638
 
 
1639
        if (ret) {
 
1640
                return(TRUE);
 
1641
        }
 
1642
 
 
1643
        os_file_handle_error_no_exit(oldpath, "rename");
 
1644
 
 
1645
        return(FALSE);
 
1646
#else
 
1647
        int     ret;
 
1648
 
 
1649
        ret = rename(oldpath, newpath);
 
1650
 
 
1651
        if (ret != 0) {
 
1652
                os_file_handle_error_no_exit(oldpath, "rename");
 
1653
 
 
1654
                return(FALSE);
 
1655
        }
 
1656
 
 
1657
        return(TRUE);
 
1658
#endif
 
1659
}
 
1660
 
 
1661
/***********************************************************************//**
 
1662
Closes a file handle. In case of error, error number can be retrieved with
 
1663
os_file_get_last_error.
 
1664
@return TRUE if success */
 
1665
UNIV_INTERN
 
1666
ibool
 
1667
os_file_close(
 
1668
/*==========*/
 
1669
        os_file_t       file)   /*!< in, own: handle to a file */
 
1670
{
 
1671
#ifdef __WIN__
 
1672
        BOOL    ret;
 
1673
 
 
1674
        ut_a(file);
 
1675
 
 
1676
        ret = CloseHandle(file);
 
1677
 
 
1678
        if (ret) {
 
1679
                return(TRUE);
 
1680
        }
 
1681
 
 
1682
        os_file_handle_error(NULL, "close");
 
1683
 
 
1684
        return(FALSE);
 
1685
#else
 
1686
        int     ret;
 
1687
 
 
1688
        ret = close(file);
 
1689
 
 
1690
        if (ret == -1) {
 
1691
                os_file_handle_error(NULL, "close");
 
1692
 
 
1693
                return(FALSE);
 
1694
        }
 
1695
 
 
1696
        return(TRUE);
 
1697
#endif
 
1698
}
 
1699
 
 
1700
#ifdef UNIV_HOTBACKUP
 
1701
/***********************************************************************//**
 
1702
Closes a file handle.
 
1703
@return TRUE if success */
 
1704
UNIV_INTERN
 
1705
ibool
 
1706
os_file_close_no_error_handling(
 
1707
/*============================*/
 
1708
        os_file_t       file)   /*!< in, own: handle to a file */
 
1709
{
 
1710
#ifdef __WIN__
 
1711
        BOOL    ret;
 
1712
 
 
1713
        ut_a(file);
 
1714
 
 
1715
        ret = CloseHandle(file);
 
1716
 
 
1717
        if (ret) {
 
1718
                return(TRUE);
 
1719
        }
 
1720
 
 
1721
        return(FALSE);
 
1722
#else
 
1723
        int     ret;
 
1724
 
 
1725
        ret = close(file);
 
1726
 
 
1727
        if (ret == -1) {
 
1728
 
 
1729
                return(FALSE);
 
1730
        }
 
1731
 
 
1732
        return(TRUE);
 
1733
#endif
 
1734
}
 
1735
#endif /* UNIV_HOTBACKUP */
 
1736
 
 
1737
/***********************************************************************//**
 
1738
Gets a file size.
 
1739
@return TRUE if success */
 
1740
UNIV_INTERN
 
1741
ibool
 
1742
os_file_get_size(
 
1743
/*=============*/
 
1744
        os_file_t       file,   /*!< in: handle to a file */
 
1745
        ulint*          size,   /*!< out: least significant 32 bits of file
 
1746
                                size */
 
1747
        ulint*          size_high)/*!< out: most significant 32 bits of size */
 
1748
{
 
1749
#ifdef __WIN__
 
1750
        DWORD   high;
 
1751
        DWORD   low;
 
1752
 
 
1753
        low = GetFileSize(file, &high);
 
1754
 
 
1755
        if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
 
1756
                return(FALSE);
 
1757
        }
 
1758
 
 
1759
        *size = low;
 
1760
        *size_high = high;
 
1761
 
 
1762
        return(TRUE);
 
1763
#else
 
1764
        off_t   offs;
 
1765
 
 
1766
        offs = lseek(file, 0, SEEK_END);
 
1767
 
 
1768
        if (offs == ((off_t)-1)) {
 
1769
 
 
1770
                return(FALSE);
 
1771
        }
 
1772
 
 
1773
        if (sizeof(off_t) > 4) {
 
1774
                *size = (ulint)(offs & 0xFFFFFFFFUL);
 
1775
                *size_high = (ulint)(offs >> 32);
 
1776
        } else {
 
1777
                *size = (ulint) offs;
 
1778
                *size_high = 0;
 
1779
        }
 
1780
 
 
1781
        return(TRUE);
 
1782
#endif
 
1783
}
 
1784
 
 
1785
/***********************************************************************//**
 
1786
Gets file size as a 64-bit integer ib_int64_t.
 
1787
@return size in bytes, -1 if error */
 
1788
UNIV_INTERN
 
1789
ib_int64_t
 
1790
os_file_get_size_as_iblonglong(
 
1791
/*===========================*/
 
1792
        os_file_t       file)   /*!< in: handle to a file */
 
1793
{
 
1794
        ulint   size;
 
1795
        ulint   size_high;
 
1796
        ibool   success;
 
1797
 
 
1798
        success = os_file_get_size(file, &size, &size_high);
 
1799
 
 
1800
        if (!success) {
 
1801
 
 
1802
                return(-1);
 
1803
        }
 
1804
 
 
1805
        return((((ib_int64_t)size_high) << 32) + (ib_int64_t)size);
 
1806
}
 
1807
 
 
1808
/***********************************************************************//**
 
1809
Write the specified number of zeros to a newly created file.
 
1810
@return TRUE if success */
 
1811
UNIV_INTERN
 
1812
ibool
 
1813
os_file_set_size(
 
1814
/*=============*/
 
1815
        const char*     name,   /*!< in: name of the file or path as a
 
1816
                                null-terminated string */
 
1817
        os_file_t       file,   /*!< in: handle to a file */
 
1818
        ulint           size,   /*!< in: least significant 32 bits of file
 
1819
                                size */
 
1820
        ulint           size_high)/*!< in: most significant 32 bits of size */
 
1821
{
 
1822
        ib_int64_t      current_size;
 
1823
        ib_int64_t      desired_size;
 
1824
        ibool           ret;
 
1825
        byte*           buf;
 
1826
        byte*           buf2;
 
1827
        ulint           buf_size;
 
1828
 
 
1829
        ut_a(size == (size & 0xFFFFFFFF));
 
1830
 
 
1831
        current_size = 0;
 
1832
        desired_size = (ib_int64_t)size + (((ib_int64_t)size_high) << 32);
 
1833
 
 
1834
        /* Write up to 1 megabyte at a time. */
 
1835
        buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
 
1836
                * UNIV_PAGE_SIZE;
 
1837
        buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
 
1838
 
 
1839
        /* Align the buffer for possible raw i/o */
 
1840
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
 
1841
 
 
1842
        /* Write buffer full of zeros */
 
1843
        memset(buf, 0, buf_size);
 
1844
 
 
1845
        if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) {
 
1846
 
 
1847
                fprintf(stderr, "InnoDB: Progress in MB:");
 
1848
        }
 
1849
 
 
1850
        while (current_size < desired_size) {
 
1851
                ulint   n_bytes;
 
1852
 
 
1853
                if (desired_size - current_size < (ib_int64_t) buf_size) {
 
1854
                        n_bytes = (ulint) (desired_size - current_size);
 
1855
                } else {
 
1856
                        n_bytes = buf_size;
 
1857
                }
 
1858
 
 
1859
                ret = os_file_write(name, file, buf,
 
1860
                                    (ulint)(current_size & 0xFFFFFFFF),
 
1861
                                    (ulint)(current_size >> 32),
 
1862
                                    n_bytes);
 
1863
                if (!ret) {
 
1864
                        ut_free(buf2);
 
1865
                        goto error_handling;
 
1866
                }
 
1867
 
 
1868
                /* Print about progress for each 100 MB written */
 
1869
                if ((ib_int64_t) (current_size + n_bytes) / (ib_int64_t)(100 * 1024 * 1024)
 
1870
                    != current_size / (ib_int64_t)(100 * 1024 * 1024)) {
 
1871
 
 
1872
                        fprintf(stderr, " %lu00",
 
1873
                                (ulong) ((current_size + n_bytes)
 
1874
                                         / (ib_int64_t)(100 * 1024 * 1024)));
 
1875
                }
 
1876
 
 
1877
                current_size += n_bytes;
 
1878
        }
 
1879
 
 
1880
        if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) {
 
1881
 
 
1882
                fprintf(stderr, "\n");
 
1883
        }
 
1884
 
 
1885
        ut_free(buf2);
 
1886
 
 
1887
        ret = os_file_flush(file);
 
1888
 
 
1889
        if (ret) {
 
1890
                return(TRUE);
 
1891
        }
 
1892
 
 
1893
error_handling:
 
1894
        return(FALSE);
 
1895
}
 
1896
 
 
1897
/***********************************************************************//**
 
1898
Truncates a file at its current position.
 
1899
@return TRUE if success */
 
1900
UNIV_INTERN
 
1901
ibool
 
1902
os_file_set_eof(
 
1903
/*============*/
 
1904
        FILE*           file)   /*!< in: file to be truncated */
 
1905
{
 
1906
#ifdef __WIN__
 
1907
        HANDLE h = (HANDLE) _get_osfhandle(fileno(file));
 
1908
        return(SetEndOfFile(h));
 
1909
#else /* __WIN__ */
 
1910
        return(!ftruncate(fileno(file), ftell(file)));
 
1911
#endif /* __WIN__ */
 
1912
}
 
1913
 
 
1914
#ifndef __WIN__
 
1915
/***********************************************************************//**
 
1916
Wrapper to fsync(2) that retries the call on some errors.
 
1917
Returns the value 0 if successful; otherwise the value -1 is returned and
 
1918
the global variable errno is set to indicate the error.
 
1919
@return 0 if success, -1 otherwise */
 
1920
 
 
1921
static
 
1922
int
 
1923
os_file_fsync(
 
1924
/*==========*/
 
1925
        os_file_t       file)   /*!< in: handle to a file */
 
1926
{
 
1927
        int     ret;
 
1928
        int     failures;
 
1929
        ibool   retry;
 
1930
 
 
1931
        failures = 0;
 
1932
 
 
1933
        do {
 
1934
                ret = fsync(file);
 
1935
 
 
1936
                os_n_fsyncs++;
 
1937
 
 
1938
                if (ret == -1 && errno == ENOLCK) {
 
1939
 
 
1940
                        if (failures % 100 == 0) {
 
1941
 
 
1942
                                ut_print_timestamp(stderr);
 
1943
                                fprintf(stderr,
 
1944
                                        "  InnoDB: fsync(): "
 
1945
                                        "No locks available; retrying\n");
 
1946
                        }
 
1947
 
 
1948
                        os_thread_sleep(200000 /* 0.2 sec */);
 
1949
 
 
1950
                        failures++;
 
1951
 
 
1952
                        retry = TRUE;
 
1953
                } else {
 
1954
 
 
1955
                        retry = FALSE;
 
1956
                }
 
1957
        } while (retry);
 
1958
 
 
1959
        return(ret);
 
1960
}
 
1961
#endif /* !__WIN__ */
 
1962
 
 
1963
/***********************************************************************//**
 
1964
Flushes the write buffers of a given file to the disk.
 
1965
@return TRUE if success */
 
1966
UNIV_INTERN
 
1967
ibool
 
1968
os_file_flush(
 
1969
/*==========*/
 
1970
        os_file_t       file)   /*!< in, own: handle to a file */
 
1971
{
 
1972
#ifdef __WIN__
 
1973
        BOOL    ret;
 
1974
 
 
1975
        ut_a(file);
 
1976
 
 
1977
        os_n_fsyncs++;
 
1978
 
 
1979
        ret = FlushFileBuffers(file);
 
1980
 
 
1981
        if (ret) {
 
1982
                return(TRUE);
 
1983
        }
 
1984
 
 
1985
        /* Since Windows returns ERROR_INVALID_FUNCTION if the 'file' is
 
1986
        actually a raw device, we choose to ignore that error if we are using
 
1987
        raw disks */
 
1988
 
 
1989
        if (srv_start_raw_disk_in_use && GetLastError()
 
1990
            == ERROR_INVALID_FUNCTION) {
 
1991
                return(TRUE);
 
1992
        }
 
1993
 
 
1994
        os_file_handle_error(NULL, "flush");
 
1995
 
 
1996
        /* It is a fatal error if a file flush does not succeed, because then
 
1997
        the database can get corrupt on disk */
 
1998
        ut_error;
 
1999
 
 
2000
        return(FALSE);
 
2001
#else
 
2002
        int     ret;
 
2003
 
 
2004
#if defined(HAVE_DARWIN_THREADS)
 
2005
# ifndef F_FULLFSYNC
 
2006
        /* The following definition is from the Mac OS X 10.3 <sys/fcntl.h> */
 
2007
#  define F_FULLFSYNC 51 /* fsync + ask the drive to flush to the media */
 
2008
# elif F_FULLFSYNC != 51
 
2009
#  error "F_FULLFSYNC != 51: ABI incompatibility with Mac OS X 10.3"
 
2010
# endif
 
2011
        /* Apple has disabled fsync() for internal disk drives in OS X. That
 
2012
        caused corruption for a user when he tested a power outage. Let us in
 
2013
        OS X use a nonstandard flush method recommended by an Apple
 
2014
        engineer. */
 
2015
 
 
2016
        if (!srv_have_fullfsync) {
 
2017
                /* If we are not on an operating system that supports this,
 
2018
                then fall back to a plain fsync. */
 
2019
 
 
2020
                ret = os_file_fsync(file);
 
2021
        } else {
 
2022
                ret = fcntl(file, F_FULLFSYNC, NULL);
 
2023
 
 
2024
                if (ret) {
 
2025
                        /* If we are not on a file system that supports this,
 
2026
                        then fall back to a plain fsync. */
 
2027
                        ret = os_file_fsync(file);
 
2028
                }
 
2029
        }
 
2030
#else
 
2031
        ret = os_file_fsync(file);
 
2032
#endif
 
2033
 
 
2034
        if (ret == 0) {
 
2035
                return(TRUE);
 
2036
        }
 
2037
 
 
2038
        /* Since Linux returns EINVAL if the 'file' is actually a raw device,
 
2039
        we choose to ignore that error if we are using raw disks */
 
2040
 
 
2041
        if (srv_start_raw_disk_in_use && errno == EINVAL) {
 
2042
 
 
2043
                return(TRUE);
 
2044
        }
 
2045
 
 
2046
        ut_print_timestamp(stderr);
 
2047
 
 
2048
        fprintf(stderr,
 
2049
                "  InnoDB: Error: the OS said file flush did not succeed\n");
 
2050
 
 
2051
        os_file_handle_error(NULL, "flush");
 
2052
 
 
2053
        /* It is a fatal error if a file flush does not succeed, because then
 
2054
        the database can get corrupt on disk */
 
2055
        ut_error;
 
2056
 
 
2057
        return(FALSE);
 
2058
#endif
 
2059
}
 
2060
 
 
2061
#ifndef __WIN__
 
2062
/*******************************************************************//**
 
2063
Does a synchronous read operation in Posix.
 
2064
@return number of bytes read, -1 if error */
 
2065
static
 
2066
ssize_t
 
2067
os_file_pread(
 
2068
/*==========*/
 
2069
        os_file_t       file,   /*!< in: handle to a file */
 
2070
        void*           buf,    /*!< in: buffer where to read */
 
2071
        ulint           n,      /*!< in: number of bytes to read */
 
2072
        ulint           offset, /*!< in: least significant 32 bits of file
 
2073
                                offset from where to read */
 
2074
        ulint           offset_high) /*!< in: most significant 32 bits of
 
2075
                                offset */
 
2076
{
 
2077
        off_t   offs;
 
2078
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
 
2079
        ssize_t n_bytes;
 
2080
#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
 
2081
 
 
2082
        ut_a((offset & 0xFFFFFFFFUL) == offset);
 
2083
 
 
2084
        /* If off_t is > 4 bytes in size, then we assume we can pass a
 
2085
        64-bit address */
 
2086
 
 
2087
        if (sizeof(off_t) > 4) {
 
2088
                offs = (off_t)offset + (((off_t)offset_high) << 32);
 
2089
 
 
2090
        } else {
 
2091
                offs = (off_t)offset;
 
2092
 
 
2093
                if (offset_high > 0) {
 
2094
                        fprintf(stderr,
 
2095
                                "InnoDB: Error: file read at offset > 4 GB\n");
 
2096
                }
 
2097
        }
 
2098
 
 
2099
        os_n_file_reads++;
 
2100
 
 
2101
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
 
2102
        os_mutex_enter(os_file_count_mutex);
 
2103
        os_file_n_pending_preads++;
 
2104
        os_n_pending_reads++;
 
2105
        os_mutex_exit(os_file_count_mutex);
 
2106
 
 
2107
        n_bytes = pread(file, buf, (ssize_t)n, offs);
 
2108
 
 
2109
        os_mutex_enter(os_file_count_mutex);
 
2110
        os_file_n_pending_preads--;
 
2111
        os_n_pending_reads--;
 
2112
        os_mutex_exit(os_file_count_mutex);
 
2113
 
 
2114
        return(n_bytes);
 
2115
#else
 
2116
        {
 
2117
                off_t   ret_offset;
 
2118
                ssize_t ret;
 
2119
#ifndef UNIV_HOTBACKUP
 
2120
                ulint   i;
 
2121
#endif /* !UNIV_HOTBACKUP */
 
2122
 
 
2123
                os_mutex_enter(os_file_count_mutex);
 
2124
                os_n_pending_reads++;
 
2125
                os_mutex_exit(os_file_count_mutex);
 
2126
 
 
2127
#ifndef UNIV_HOTBACKUP
 
2128
                /* Protect the seek / read operation with a mutex */
 
2129
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
2130
 
 
2131
                os_mutex_enter(os_file_seek_mutexes[i]);
 
2132
#endif /* !UNIV_HOTBACKUP */
 
2133
 
 
2134
                ret_offset = lseek(file, offs, SEEK_SET);
 
2135
 
 
2136
                if (ret_offset < 0) {
 
2137
                        ret = -1;
 
2138
                } else {
 
2139
                        ret = read(file, buf, (ssize_t)n);
 
2140
                }
 
2141
 
 
2142
#ifndef UNIV_HOTBACKUP
 
2143
                os_mutex_exit(os_file_seek_mutexes[i]);
 
2144
#endif /* !UNIV_HOTBACKUP */
 
2145
 
 
2146
                os_mutex_enter(os_file_count_mutex);
 
2147
                os_n_pending_reads--;
 
2148
                os_mutex_exit(os_file_count_mutex);
 
2149
 
 
2150
                return(ret);
 
2151
        }
 
2152
#endif
 
2153
}
 
2154
 
 
2155
/*******************************************************************//**
 
2156
Does a synchronous write operation in Posix.
 
2157
@return number of bytes written, -1 if error */
 
2158
static
 
2159
ssize_t
 
2160
os_file_pwrite(
 
2161
/*===========*/
 
2162
        os_file_t       file,   /*!< in: handle to a file */
 
2163
        const void*     buf,    /*!< in: buffer from where to write */
 
2164
        ulint           n,      /*!< in: number of bytes to write */
 
2165
        ulint           offset, /*!< in: least significant 32 bits of file
 
2166
                                offset where to write */
 
2167
        ulint           offset_high) /*!< in: most significant 32 bits of
 
2168
                                offset */
 
2169
{
 
2170
        ssize_t ret;
 
2171
        off_t   offs;
 
2172
 
 
2173
        ut_a((offset & 0xFFFFFFFFUL) == offset);
 
2174
 
 
2175
        /* If off_t is > 4 bytes in size, then we assume we can pass a
 
2176
        64-bit address */
 
2177
 
 
2178
        if (sizeof(off_t) > 4) {
 
2179
                offs = (off_t)offset + (((off_t)offset_high) << 32);
 
2180
        } else {
 
2181
                offs = (off_t)offset;
 
2182
 
 
2183
                if (offset_high > 0) {
 
2184
                        fprintf(stderr,
 
2185
                                "InnoDB: Error: file write"
 
2186
                                " at offset > 4 GB\n");
 
2187
                }
 
2188
        }
 
2189
 
 
2190
        os_n_file_writes++;
 
2191
 
 
2192
#if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
 
2193
        os_mutex_enter(os_file_count_mutex);
 
2194
        os_file_n_pending_pwrites++;
 
2195
        os_n_pending_writes++;
 
2196
        os_mutex_exit(os_file_count_mutex);
 
2197
 
 
2198
        ret = pwrite(file, buf, (ssize_t)n, offs);
 
2199
 
 
2200
        os_mutex_enter(os_file_count_mutex);
 
2201
        os_file_n_pending_pwrites--;
 
2202
        os_n_pending_writes--;
 
2203
        os_mutex_exit(os_file_count_mutex);
 
2204
 
 
2205
# ifdef UNIV_DO_FLUSH
 
2206
        if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
 
2207
            && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
 
2208
            && !os_do_not_call_flush_at_each_write) {
 
2209
 
 
2210
                /* Always do fsync to reduce the probability that when
 
2211
                the OS crashes, a database page is only partially
 
2212
                physically written to disk. */
 
2213
 
 
2214
                ut_a(TRUE == os_file_flush(file));
 
2215
        }
 
2216
# endif /* UNIV_DO_FLUSH */
 
2217
 
 
2218
        return(ret);
 
2219
#else
 
2220
        {
 
2221
                off_t   ret_offset;
 
2222
# ifndef UNIV_HOTBACKUP
 
2223
                ulint   i;
 
2224
# endif /* !UNIV_HOTBACKUP */
 
2225
 
 
2226
                os_mutex_enter(os_file_count_mutex);
 
2227
                os_n_pending_writes++;
 
2228
                os_mutex_exit(os_file_count_mutex);
 
2229
 
 
2230
# ifndef UNIV_HOTBACKUP
 
2231
                /* Protect the seek / write operation with a mutex */
 
2232
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
2233
 
 
2234
                os_mutex_enter(os_file_seek_mutexes[i]);
 
2235
# endif /* UNIV_HOTBACKUP */
 
2236
 
 
2237
                ret_offset = lseek(file, offs, SEEK_SET);
 
2238
 
 
2239
                if (ret_offset < 0) {
 
2240
                        ret = -1;
 
2241
 
 
2242
                        goto func_exit;
 
2243
                }
 
2244
 
 
2245
                ret = write(file, buf, (ssize_t)n);
 
2246
 
 
2247
# ifdef UNIV_DO_FLUSH
 
2248
                if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
 
2249
                    && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
 
2250
                    && !os_do_not_call_flush_at_each_write) {
 
2251
 
 
2252
                        /* Always do fsync to reduce the probability that when
 
2253
                        the OS crashes, a database page is only partially
 
2254
                        physically written to disk. */
 
2255
 
 
2256
                        ut_a(TRUE == os_file_flush(file));
 
2257
                }
 
2258
# endif /* UNIV_DO_FLUSH */
 
2259
 
 
2260
func_exit:
 
2261
# ifndef UNIV_HOTBACKUP
 
2262
                os_mutex_exit(os_file_seek_mutexes[i]);
 
2263
# endif /* !UNIV_HOTBACKUP */
 
2264
 
 
2265
                os_mutex_enter(os_file_count_mutex);
 
2266
                os_n_pending_writes--;
 
2267
                os_mutex_exit(os_file_count_mutex);
 
2268
 
 
2269
                return(ret);
 
2270
        }
 
2271
#endif
 
2272
}
 
2273
#endif
 
2274
 
 
2275
/*******************************************************************//**
 
2276
Requests a synchronous positioned read operation.
 
2277
@return TRUE if request was successful, FALSE if fail */
 
2278
UNIV_INTERN
 
2279
ibool
 
2280
os_file_read(
 
2281
/*=========*/
 
2282
        os_file_t       file,   /*!< in: handle to a file */
 
2283
        void*           buf,    /*!< in: buffer where to read */
 
2284
        ulint           offset, /*!< in: least significant 32 bits of file
 
2285
                                offset where to read */
 
2286
        ulint           offset_high, /*!< in: most significant 32 bits of
 
2287
                                offset */
 
2288
        ulint           n)      /*!< in: number of bytes to read */
 
2289
{
 
2290
#ifdef __WIN__
 
2291
        BOOL            ret;
 
2292
        DWORD           len;
 
2293
        DWORD           ret2;
 
2294
        DWORD           low;
 
2295
        DWORD           high;
 
2296
        ibool           retry;
 
2297
#ifndef UNIV_HOTBACKUP
 
2298
        ulint           i;
 
2299
#endif /* !UNIV_HOTBACKUP */
 
2300
 
 
2301
        ut_a((offset & 0xFFFFFFFFUL) == offset);
 
2302
 
 
2303
        os_n_file_reads++;
 
2304
        os_bytes_read_since_printout += n;
 
2305
 
 
2306
try_again:
 
2307
        ut_ad(file);
 
2308
        ut_ad(buf);
 
2309
        ut_ad(n > 0);
 
2310
 
 
2311
        low = (DWORD) offset;
 
2312
        high = (DWORD) offset_high;
 
2313
 
 
2314
        os_mutex_enter(os_file_count_mutex);
 
2315
        os_n_pending_reads++;
 
2316
        os_mutex_exit(os_file_count_mutex);
 
2317
 
 
2318
#ifndef UNIV_HOTBACKUP
 
2319
        /* Protect the seek / read operation with a mutex */
 
2320
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
2321
 
 
2322
        os_mutex_enter(os_file_seek_mutexes[i]);
 
2323
#endif /* !UNIV_HOTBACKUP */
 
2324
 
 
2325
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
 
2326
 
 
2327
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
 
2328
 
 
2329
#ifndef UNIV_HOTBACKUP
 
2330
                os_mutex_exit(os_file_seek_mutexes[i]);
 
2331
#endif /* !UNIV_HOTBACKUP */
 
2332
 
 
2333
                os_mutex_enter(os_file_count_mutex);
 
2334
                os_n_pending_reads--;
 
2335
                os_mutex_exit(os_file_count_mutex);
 
2336
 
 
2337
                goto error_handling;
 
2338
        }
 
2339
 
 
2340
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
 
2341
 
 
2342
#ifndef UNIV_HOTBACKUP
 
2343
        os_mutex_exit(os_file_seek_mutexes[i]);
 
2344
#endif /* !UNIV_HOTBACKUP */
 
2345
 
 
2346
        os_mutex_enter(os_file_count_mutex);
 
2347
        os_n_pending_reads--;
 
2348
        os_mutex_exit(os_file_count_mutex);
 
2349
 
 
2350
        if (ret && len == n) {
 
2351
                return(TRUE);
 
2352
        }
 
2353
#else /* __WIN__ */
 
2354
        ibool   retry;
 
2355
        ssize_t ret;
 
2356
 
 
2357
        os_bytes_read_since_printout += n;
 
2358
 
 
2359
try_again:
 
2360
        ret = os_file_pread(file, buf, n, offset, offset_high);
 
2361
 
 
2362
        if ((ulint)ret == n) {
 
2363
 
 
2364
                return(TRUE);
 
2365
        }
 
2366
 
 
2367
        fprintf(stderr,
 
2368
                "InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n"
 
2369
                "InnoDB: Was only able to read %ld.\n",
 
2370
                (ulong)n, (ulong)offset_high,
 
2371
                (ulong)offset, (long)ret);
 
2372
#endif /* __WIN__ */
 
2373
#ifdef __WIN__
 
2374
error_handling:
 
2375
#endif
 
2376
        retry = os_file_handle_error(NULL, "read");
 
2377
 
 
2378
        if (retry) {
 
2379
                goto try_again;
 
2380
        }
 
2381
 
 
2382
        fprintf(stderr,
 
2383
                "InnoDB: Fatal error: cannot read from file."
 
2384
                " OS error number %lu.\n",
 
2385
#ifdef __WIN__
 
2386
                (ulong) GetLastError()
 
2387
#else
 
2388
                (ulong) errno
 
2389
#endif
 
2390
                );
 
2391
        fflush(stderr);
 
2392
 
 
2393
        ut_error;
 
2394
 
 
2395
        return(FALSE);
 
2396
}
 
2397
 
 
2398
/*******************************************************************//**
 
2399
Requests a synchronous positioned read operation. This function does not do
 
2400
any error handling. In case of error it returns FALSE.
 
2401
@return TRUE if request was successful, FALSE if fail */
 
2402
UNIV_INTERN
 
2403
ibool
 
2404
os_file_read_no_error_handling(
 
2405
/*===========================*/
 
2406
        os_file_t       file,   /*!< in: handle to a file */
 
2407
        void*           buf,    /*!< in: buffer where to read */
 
2408
        ulint           offset, /*!< in: least significant 32 bits of file
 
2409
                                offset where to read */
 
2410
        ulint           offset_high, /*!< in: most significant 32 bits of
 
2411
                                offset */
 
2412
        ulint           n)      /*!< in: number of bytes to read */
 
2413
{
 
2414
#ifdef __WIN__
 
2415
        BOOL            ret;
 
2416
        DWORD           len;
 
2417
        DWORD           ret2;
 
2418
        DWORD           low;
 
2419
        DWORD           high;
 
2420
        ibool           retry;
 
2421
#ifndef UNIV_HOTBACKUP
 
2422
        ulint           i;
 
2423
#endif /* !UNIV_HOTBACKUP */
 
2424
 
 
2425
        ut_a((offset & 0xFFFFFFFFUL) == offset);
 
2426
 
 
2427
        os_n_file_reads++;
 
2428
        os_bytes_read_since_printout += n;
 
2429
 
 
2430
try_again:
 
2431
        ut_ad(file);
 
2432
        ut_ad(buf);
 
2433
        ut_ad(n > 0);
 
2434
 
 
2435
        low = (DWORD) offset;
 
2436
        high = (DWORD) offset_high;
 
2437
 
 
2438
        os_mutex_enter(os_file_count_mutex);
 
2439
        os_n_pending_reads++;
 
2440
        os_mutex_exit(os_file_count_mutex);
 
2441
 
 
2442
#ifndef UNIV_HOTBACKUP
 
2443
        /* Protect the seek / read operation with a mutex */
 
2444
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
2445
 
 
2446
        os_mutex_enter(os_file_seek_mutexes[i]);
 
2447
#endif /* !UNIV_HOTBACKUP */
 
2448
 
 
2449
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
 
2450
 
 
2451
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
 
2452
 
 
2453
#ifndef UNIV_HOTBACKUP
 
2454
                os_mutex_exit(os_file_seek_mutexes[i]);
 
2455
#endif /* !UNIV_HOTBACKUP */
 
2456
 
 
2457
                os_mutex_enter(os_file_count_mutex);
 
2458
                os_n_pending_reads--;
 
2459
                os_mutex_exit(os_file_count_mutex);
 
2460
 
 
2461
                goto error_handling;
 
2462
        }
 
2463
 
 
2464
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
 
2465
 
 
2466
#ifndef UNIV_HOTBACKUP
 
2467
        os_mutex_exit(os_file_seek_mutexes[i]);
 
2468
#endif /* !UNIV_HOTBACKUP */
 
2469
 
 
2470
        os_mutex_enter(os_file_count_mutex);
 
2471
        os_n_pending_reads--;
 
2472
        os_mutex_exit(os_file_count_mutex);
 
2473
 
 
2474
        if (ret && len == n) {
 
2475
                return(TRUE);
 
2476
        }
 
2477
#else /* __WIN__ */
 
2478
        ibool   retry;
 
2479
        ssize_t ret;
 
2480
 
 
2481
        os_bytes_read_since_printout += n;
 
2482
 
 
2483
try_again:
 
2484
        ret = os_file_pread(file, buf, n, offset, offset_high);
 
2485
 
 
2486
        if ((ulint)ret == n) {
 
2487
 
 
2488
                return(TRUE);
 
2489
        }
 
2490
#endif /* __WIN__ */
 
2491
#ifdef __WIN__
 
2492
error_handling:
 
2493
#endif
 
2494
        retry = os_file_handle_error_no_exit(NULL, "read");
 
2495
 
 
2496
        if (retry) {
 
2497
                goto try_again;
 
2498
        }
 
2499
 
 
2500
        return(FALSE);
 
2501
}
 
2502
 
 
2503
/*******************************************************************//**
 
2504
Rewind file to its start, read at most size - 1 bytes from it to str, and
 
2505
NUL-terminate str. All errors are silently ignored. This function is
 
2506
mostly meant to be used with temporary files. */
 
2507
UNIV_INTERN
 
2508
void
 
2509
os_file_read_string(
 
2510
/*================*/
 
2511
        FILE*   file,   /*!< in: file to read from */
 
2512
        char*   str,    /*!< in: buffer where to read */
 
2513
        ulint   size)   /*!< in: size of buffer */
 
2514
{
 
2515
        size_t  flen;
 
2516
 
 
2517
        if (size == 0) {
 
2518
                return;
 
2519
        }
 
2520
 
 
2521
        rewind(file);
 
2522
        flen = fread(str, 1, size - 1, file);
 
2523
        str[flen] = '\0';
 
2524
}
 
2525
 
 
2526
/*******************************************************************//**
 
2527
Requests a synchronous write operation.
 
2528
@return TRUE if request was successful, FALSE if fail */
 
2529
UNIV_INTERN
 
2530
ibool
 
2531
os_file_write(
 
2532
/*==========*/
 
2533
        const char*     name,   /*!< in: name of the file or path as a
 
2534
                                null-terminated string */
 
2535
        os_file_t       file,   /*!< in: handle to a file */
 
2536
        const void*     buf,    /*!< in: buffer from which to write */
 
2537
        ulint           offset, /*!< in: least significant 32 bits of file
 
2538
                                offset where to write */
 
2539
        ulint           offset_high, /*!< in: most significant 32 bits of
 
2540
                                offset */
 
2541
        ulint           n)      /*!< in: number of bytes to write */
 
2542
{
 
2543
#ifdef __WIN__
 
2544
        BOOL            ret;
 
2545
        DWORD           len;
 
2546
        DWORD           ret2;
 
2547
        DWORD           low;
 
2548
        DWORD           high;
 
2549
        ulint           n_retries       = 0;
 
2550
        ulint           err;
 
2551
#ifndef UNIV_HOTBACKUP
 
2552
        ulint           i;
 
2553
#endif /* !UNIV_HOTBACKUP */
 
2554
 
 
2555
        ut_a((offset & 0xFFFFFFFF) == offset);
 
2556
 
 
2557
        os_n_file_writes++;
 
2558
 
 
2559
        ut_ad(file);
 
2560
        ut_ad(buf);
 
2561
        ut_ad(n > 0);
 
2562
retry:
 
2563
        low = (DWORD) offset;
 
2564
        high = (DWORD) offset_high;
 
2565
 
 
2566
        os_mutex_enter(os_file_count_mutex);
 
2567
        os_n_pending_writes++;
 
2568
        os_mutex_exit(os_file_count_mutex);
 
2569
 
 
2570
#ifndef UNIV_HOTBACKUP
 
2571
        /* Protect the seek / write operation with a mutex */
 
2572
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
 
2573
 
 
2574
        os_mutex_enter(os_file_seek_mutexes[i]);
 
2575
#endif /* !UNIV_HOTBACKUP */
 
2576
 
 
2577
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
 
2578
 
 
2579
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
 
2580
 
 
2581
#ifndef UNIV_HOTBACKUP
 
2582
                os_mutex_exit(os_file_seek_mutexes[i]);
 
2583
#endif /* !UNIV_HOTBACKUP */
 
2584
 
 
2585
                os_mutex_enter(os_file_count_mutex);
 
2586
                os_n_pending_writes--;
 
2587
                os_mutex_exit(os_file_count_mutex);
 
2588
 
 
2589
                ut_print_timestamp(stderr);
 
2590
 
 
2591
                fprintf(stderr,
 
2592
                        "  InnoDB: Error: File pointer positioning to"
 
2593
                        " file %s failed at\n"
 
2594
                        "InnoDB: offset %lu %lu. Operating system"
 
2595
                        " error number %lu.\n"
 
2596
                        "InnoDB: Some operating system error numbers"
 
2597
                        " are described at\n"
 
2598
                        "InnoDB: "
 
2599
                        REFMAN "operating-system-error-codes.html\n",
 
2600
                        name, (ulong) offset_high, (ulong) offset,
 
2601
                        (ulong) GetLastError());
 
2602
 
 
2603
                return(FALSE);
 
2604
        }
 
2605
 
 
2606
        ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
 
2607
 
 
2608
        /* Always do fsync to reduce the probability that when the OS crashes,
 
2609
        a database page is only partially physically written to disk. */
 
2610
 
 
2611
# ifdef UNIV_DO_FLUSH
 
2612
        if (!os_do_not_call_flush_at_each_write) {
 
2613
                ut_a(TRUE == os_file_flush(file));
 
2614
        }
 
2615
# endif /* UNIV_DO_FLUSH */
 
2616
 
 
2617
#ifndef UNIV_HOTBACKUP
 
2618
        os_mutex_exit(os_file_seek_mutexes[i]);
 
2619
#endif /* !UNIV_HOTBACKUP */
 
2620
 
 
2621
        os_mutex_enter(os_file_count_mutex);
 
2622
        os_n_pending_writes--;
 
2623
        os_mutex_exit(os_file_count_mutex);
 
2624
 
 
2625
        if (ret && len == n) {
 
2626
 
 
2627
                return(TRUE);
 
2628
        }
 
2629
 
 
2630
        /* If some background file system backup tool is running, then, at
 
2631
        least in Windows 2000, we may get here a specific error. Let us
 
2632
        retry the operation 100 times, with 1 second waits. */
 
2633
 
 
2634
        if (GetLastError() == ERROR_LOCK_VIOLATION && n_retries < 100) {
 
2635
 
 
2636
                os_thread_sleep(1000000);
 
2637
 
 
2638
                n_retries++;
 
2639
 
 
2640
                goto retry;
 
2641
        }
 
2642
 
 
2643
        if (!os_has_said_disk_full) {
 
2644
 
 
2645
                err = (ulint)GetLastError();
 
2646
 
 
2647
                ut_print_timestamp(stderr);
 
2648
 
 
2649
                fprintf(stderr,
 
2650
                        "  InnoDB: Error: Write to file %s failed"
 
2651
                        " at offset %lu %lu.\n"
 
2652
                        "InnoDB: %lu bytes should have been written,"
 
2653
                        " only %lu were written.\n"
 
2654
                        "InnoDB: Operating system error number %lu.\n"
 
2655
                        "InnoDB: Check that your OS and file system"
 
2656
                        " support files of this size.\n"
 
2657
                        "InnoDB: Check also that the disk is not full"
 
2658
                        " or a disk quota exceeded.\n",
 
2659
                        name, (ulong) offset_high, (ulong) offset,
 
2660
                        (ulong) n, (ulong) len, (ulong) err);
 
2661
 
 
2662
                if (strerror((int)err) != NULL) {
 
2663
                        fprintf(stderr,
 
2664
                                "InnoDB: Error number %lu means '%s'.\n",
 
2665
                                (ulong) err, strerror((int)err));
 
2666
                }
 
2667
 
 
2668
                fprintf(stderr,
 
2669
                        "InnoDB: Some operating system error numbers"
 
2670
                        " are described at\n"
 
2671
                        "InnoDB: "
 
2672
                        REFMAN "operating-system-error-codes.html\n");
 
2673
 
 
2674
                os_has_said_disk_full = TRUE;
 
2675
        }
 
2676
 
 
2677
        return(FALSE);
 
2678
#else
 
2679
        ssize_t ret;
 
2680
 
 
2681
        ret = os_file_pwrite(file, buf, n, offset, offset_high);
 
2682
 
 
2683
        if ((ulint)ret == n) {
 
2684
 
 
2685
                return(TRUE);
 
2686
        }
 
2687
 
 
2688
        if (!os_has_said_disk_full) {
 
2689
 
 
2690
                ut_print_timestamp(stderr);
 
2691
 
 
2692
                fprintf(stderr,
 
2693
                        "  InnoDB: Error: Write to file %s failed"
 
2694
                        " at offset %lu %lu.\n"
 
2695
                        "InnoDB: %lu bytes should have been written,"
 
2696
                        " only %ld were written.\n"
 
2697
                        "InnoDB: Operating system error number %lu.\n"
 
2698
                        "InnoDB: Check that your OS and file system"
 
2699
                        " support files of this size.\n"
 
2700
                        "InnoDB: Check also that the disk is not full"
 
2701
                        " or a disk quota exceeded.\n",
 
2702
                        name, offset_high, offset, n, (long int)ret,
 
2703
                        (ulint)errno);
 
2704
                if (strerror(errno) != NULL) {
 
2705
                        fprintf(stderr,
 
2706
                                "InnoDB: Error number %lu means '%s'.\n",
 
2707
                                (ulint)errno, strerror(errno));
 
2708
                }
 
2709
 
 
2710
                fprintf(stderr,
 
2711
                        "InnoDB: Some operating system error numbers"
 
2712
                        " are described at\n"
 
2713
                        "InnoDB: "
 
2714
                        REFMAN "operating-system-error-codes.html\n");
 
2715
 
 
2716
                os_has_said_disk_full = TRUE;
 
2717
        }
 
2718
 
 
2719
        return(FALSE);
 
2720
#endif
 
2721
}
 
2722
 
 
2723
/*******************************************************************//**
 
2724
Check the existence and type of the given file.
 
2725
@return TRUE if call succeeded */
 
2726
UNIV_INTERN
 
2727
ibool
 
2728
os_file_status(
 
2729
/*===========*/
 
2730
        const char*     path,   /*!< in:        pathname of the file */
 
2731
        ibool*          exists, /*!< out: TRUE if file exists */
 
2732
        os_file_type_t* type)   /*!< out: type of the file (if it exists) */
 
2733
{
 
2734
#ifdef __WIN__
 
2735
        int             ret;
 
2736
        struct _stat    statinfo;
 
2737
 
 
2738
        ret = _stat(path, &statinfo);
 
2739
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
 
2740
                /* file does not exist */
 
2741
                *exists = FALSE;
 
2742
                return(TRUE);
 
2743
        } else if (ret) {
 
2744
                /* file exists, but stat call failed */
 
2745
 
 
2746
                os_file_handle_error_no_exit(path, "stat");
 
2747
 
 
2748
                return(FALSE);
 
2749
        }
 
2750
 
 
2751
        if (_S_IFDIR & statinfo.st_mode) {
 
2752
                *type = OS_FILE_TYPE_DIR;
 
2753
        } else if (_S_IFREG & statinfo.st_mode) {
 
2754
                *type = OS_FILE_TYPE_FILE;
 
2755
        } else {
 
2756
                *type = OS_FILE_TYPE_UNKNOWN;
 
2757
        }
 
2758
 
 
2759
        *exists = TRUE;
 
2760
 
 
2761
        return(TRUE);
 
2762
#else
 
2763
        int             ret;
 
2764
        struct stat     statinfo;
 
2765
 
 
2766
        ret = stat(path, &statinfo);
 
2767
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
 
2768
                /* file does not exist */
 
2769
                *exists = FALSE;
 
2770
                return(TRUE);
 
2771
        } else if (ret) {
 
2772
                /* file exists, but stat call failed */
 
2773
 
 
2774
                os_file_handle_error_no_exit(path, "stat");
 
2775
 
 
2776
                return(FALSE);
 
2777
        }
 
2778
 
 
2779
        if (S_ISDIR(statinfo.st_mode)) {
 
2780
                *type = OS_FILE_TYPE_DIR;
 
2781
        } else if (S_ISLNK(statinfo.st_mode)) {
 
2782
                *type = OS_FILE_TYPE_LINK;
 
2783
        } else if (S_ISREG(statinfo.st_mode)) {
 
2784
                *type = OS_FILE_TYPE_FILE;
 
2785
        } else {
 
2786
                *type = OS_FILE_TYPE_UNKNOWN;
 
2787
        }
 
2788
 
 
2789
        *exists = TRUE;
 
2790
 
 
2791
        return(TRUE);
 
2792
#endif
 
2793
}
 
2794
 
 
2795
/*******************************************************************//**
 
2796
This function returns information about the specified file
 
2797
@return TRUE if stat information found */
 
2798
UNIV_INTERN
 
2799
ibool
 
2800
os_file_get_status(
 
2801
/*===============*/
 
2802
        const char*     path,           /*!< in:        pathname of the file */
 
2803
        os_file_stat_t* stat_info)      /*!< information of a file in a
 
2804
                                        directory */
 
2805
{
 
2806
#ifdef __WIN__
 
2807
        int             ret;
 
2808
        struct _stat    statinfo;
 
2809
 
 
2810
        ret = _stat(path, &statinfo);
 
2811
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
 
2812
                /* file does not exist */
 
2813
 
 
2814
                return(FALSE);
 
2815
        } else if (ret) {
 
2816
                /* file exists, but stat call failed */
 
2817
 
 
2818
                os_file_handle_error_no_exit(path, "stat");
 
2819
 
 
2820
                return(FALSE);
 
2821
        }
 
2822
        if (_S_IFDIR & statinfo.st_mode) {
 
2823
                stat_info->type = OS_FILE_TYPE_DIR;
 
2824
        } else if (_S_IFREG & statinfo.st_mode) {
 
2825
                stat_info->type = OS_FILE_TYPE_FILE;
 
2826
        } else {
 
2827
                stat_info->type = OS_FILE_TYPE_UNKNOWN;
 
2828
        }
 
2829
 
 
2830
        stat_info->ctime = statinfo.st_ctime;
 
2831
        stat_info->atime = statinfo.st_atime;
 
2832
        stat_info->mtime = statinfo.st_mtime;
 
2833
        stat_info->size  = statinfo.st_size;
 
2834
 
 
2835
        return(TRUE);
 
2836
#else
 
2837
        int             ret;
 
2838
        struct stat     statinfo;
 
2839
 
 
2840
        ret = stat(path, &statinfo);
 
2841
 
 
2842
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
 
2843
                /* file does not exist */
 
2844
 
 
2845
                return(FALSE);
 
2846
        } else if (ret) {
 
2847
                /* file exists, but stat call failed */
 
2848
 
 
2849
                os_file_handle_error_no_exit(path, "stat");
 
2850
 
 
2851
                return(FALSE);
 
2852
        }
 
2853
 
 
2854
        if (S_ISDIR(statinfo.st_mode)) {
 
2855
                stat_info->type = OS_FILE_TYPE_DIR;
 
2856
        } else if (S_ISLNK(statinfo.st_mode)) {
 
2857
                stat_info->type = OS_FILE_TYPE_LINK;
 
2858
        } else if (S_ISREG(statinfo.st_mode)) {
 
2859
                stat_info->type = OS_FILE_TYPE_FILE;
 
2860
        } else {
 
2861
                stat_info->type = OS_FILE_TYPE_UNKNOWN;
 
2862
        }
 
2863
 
 
2864
        stat_info->ctime = statinfo.st_ctime;
 
2865
        stat_info->atime = statinfo.st_atime;
 
2866
        stat_info->mtime = statinfo.st_mtime;
 
2867
        stat_info->size  = statinfo.st_size;
 
2868
 
 
2869
        return(TRUE);
 
2870
#endif
 
2871
}
 
2872
 
 
2873
/* path name separator character */
 
2874
#ifdef __WIN__
 
2875
#  define OS_FILE_PATH_SEPARATOR        '\\'
 
2876
#else
 
2877
#  define OS_FILE_PATH_SEPARATOR        '/'
 
2878
#endif
 
2879
 
 
2880
/****************************************************************//**
 
2881
The function os_file_dirname returns a directory component of a
 
2882
null-terminated pathname string.  In the usual case, dirname returns
 
2883
the string up to, but not including, the final '/', and basename
 
2884
is the component following the final '/'.  Trailing '/' characļæ½
 
2885
ters are not counted as part of the pathname.
 
2886
 
 
2887
If path does not contain a slash, dirname returns the string ".".
 
2888
 
 
2889
Concatenating the string returned by dirname, a "/", and the basename
 
2890
yields a complete pathname.
 
2891
 
 
2892
The return value is  a copy of the directory component of the pathname.
 
2893
The copy is allocated from heap. It is the caller responsibility
 
2894
to free it after it is no longer needed.
 
2895
 
 
2896
The following list of examples (taken from SUSv2) shows the strings
 
2897
returned by dirname and basename for different paths:
 
2898
 
 
2899
       path           dirname        basename
 
2900
       "/usr/lib"     "/usr"         "lib"
 
2901
       "/usr/"        "/"            "usr"
 
2902
       "usr"          "."            "usr"
 
2903
       "/"            "/"            "/"
 
2904
       "."            "."            "."
 
2905
       ".."           "."            ".."
 
2906
 
 
2907
@return own: directory component of the pathname */
 
2908
UNIV_INTERN
 
2909
char*
 
2910
os_file_dirname(
 
2911
/*============*/
 
2912
        const char*     path)   /*!< in: pathname */
 
2913
{
 
2914
        /* Find the offset of the last slash */
 
2915
        const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR);
 
2916
        if (!last_slash) {
 
2917
                /* No slash in the path, return "." */
 
2918
 
 
2919
                return(mem_strdup("."));
 
2920
        }
 
2921
 
 
2922
        /* Ok, there is a slash */
 
2923
 
 
2924
        if (last_slash == path) {
 
2925
                /* last slash is the first char of the path */
 
2926
 
 
2927
                return(mem_strdup("/"));
 
2928
        }
 
2929
 
 
2930
        /* Non-trivial directory component */
 
2931
 
 
2932
        return(mem_strdupl(path, last_slash - path));
 
2933
}
 
2934
 
 
2935
/****************************************************************//**
 
2936
Creates all missing subdirectories along the given path.
 
2937
@return TRUE if call succeeded FALSE otherwise */
 
2938
UNIV_INTERN
 
2939
ibool
 
2940
os_file_create_subdirs_if_needed(
 
2941
/*=============================*/
 
2942
        const char*     path)   /*!< in: path name */
 
2943
{
 
2944
        char*           subdir;
 
2945
        ibool           success, subdir_exists;
 
2946
        os_file_type_t  type;
 
2947
 
 
2948
        subdir = os_file_dirname(path);
 
2949
        if (strlen(subdir) == 1
 
2950
            && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) {
 
2951
                /* subdir is root or cwd, nothing to do */
 
2952
                mem_free(subdir);
 
2953
 
 
2954
                return(TRUE);
 
2955
        }
 
2956
 
 
2957
        /* Test if subdir exists */
 
2958
        success = os_file_status(subdir, &subdir_exists, &type);
 
2959
        if (success && !subdir_exists) {
 
2960
                /* subdir does not exist, create it */
 
2961
                success = os_file_create_subdirs_if_needed(subdir);
 
2962
                if (!success) {
 
2963
                        mem_free(subdir);
 
2964
 
 
2965
                        return(FALSE);
 
2966
                }
 
2967
                success = os_file_create_directory(subdir, FALSE);
 
2968
        }
 
2969
 
 
2970
        mem_free(subdir);
 
2971
 
 
2972
        return(success);
 
2973
}
 
2974
 
 
2975
#ifndef UNIV_HOTBACKUP
 
2976
/****************************************************************//**
 
2977
Returns a pointer to the nth slot in the aio array.
 
2978
@return pointer to slot */
 
2979
static
 
2980
os_aio_slot_t*
 
2981
os_aio_array_get_nth_slot(
 
2982
/*======================*/
 
2983
        os_aio_array_t*         array,  /*!< in: aio array */
 
2984
        ulint                   index)  /*!< in: index of the slot */
 
2985
{
 
2986
        ut_a(index < array->n_slots);
 
2987
 
 
2988
        return((array->slots) + index);
 
2989
}
 
2990
 
 
2991
/************************************************************************//**
 
2992
Creates an aio wait array.
 
2993
@return own: aio array */
 
2994
static
 
2995
os_aio_array_t*
 
2996
os_aio_array_create(
 
2997
/*================*/
 
2998
        ulint   n,              /*!< in: maximum number of pending aio operations
 
2999
                                allowed; n must be divisible by n_segments */
 
3000
        ulint   n_segments)     /*!< in: number of segments in the aio array */
 
3001
{
 
3002
        os_aio_array_t* array;
 
3003
        ulint           i;
 
3004
        os_aio_slot_t*  slot;
 
3005
#ifdef WIN_ASYNC_IO
 
3006
        OVERLAPPED*     over;
 
3007
#endif
 
3008
        ut_a(n > 0);
 
3009
        ut_a(n_segments > 0);
 
3010
 
 
3011
        array = ut_malloc(sizeof(os_aio_array_t));
 
3012
 
 
3013
        array->mutex            = os_mutex_create(NULL);
 
3014
        array->not_full         = os_event_create(NULL);
 
3015
        array->is_empty         = os_event_create(NULL);
 
3016
 
 
3017
        os_event_set(array->is_empty);
 
3018
 
 
3019
        array->n_slots          = n;
 
3020
        array->n_segments       = n_segments;
 
3021
        array->n_reserved       = 0;
 
3022
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
 
3023
#ifdef __WIN__
 
3024
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
 
3025
#endif
 
3026
        for (i = 0; i < n; i++) {
 
3027
                slot = os_aio_array_get_nth_slot(array, i);
 
3028
 
 
3029
                slot->pos = i;
 
3030
                slot->reserved = FALSE;
 
3031
#ifdef WIN_ASYNC_IO
 
3032
                slot->event = os_event_create(NULL);
 
3033
 
 
3034
                over = &(slot->control);
 
3035
 
 
3036
                over->hEvent = slot->event->handle;
 
3037
 
 
3038
                *((array->native_events) + i) = over->hEvent;
 
3039
#endif
 
3040
        }
 
3041
 
 
3042
        return(array);
 
3043
}
 
3044
 
 
3045
/************************************************************************//**
 
3046
Frees an aio wait array. */
 
3047
static
 
3048
void
 
3049
os_aio_array_free(
 
3050
/*==============*/
 
3051
        os_aio_array_t* array)  /*!< in, own: array to free */
 
3052
{
 
3053
#ifdef WIN_ASYNC_IO
 
3054
        ulint   i;
 
3055
 
 
3056
        for (i = 0; i < array->n_slots; i++) {
 
3057
                os_aio_slot_t*  slot = os_aio_array_get_nth_slot(array, i);
 
3058
                os_event_free(slot->event);
 
3059
        }
 
3060
#endif /* WIN_ASYNC_IO */
 
3061
 
 
3062
#ifdef __WIN__
 
3063
        ut_free(array->native_events);
 
3064
#endif /* __WIN__ */
 
3065
        os_mutex_free(array->mutex);
 
3066
        os_event_free(array->not_full);
 
3067
        os_event_free(array->is_empty);
 
3068
 
 
3069
        ut_free(array->slots);
 
3070
        ut_free(array);
 
3071
}
 
3072
 
 
3073
/***********************************************************************
 
3074
Initializes the asynchronous io system. Creates one array each for ibuf
 
3075
and log i/o. Also creates one array each for read and write where each
 
3076
array is divided logically into n_read_segs and n_write_segs
 
3077
respectively. The caller must create an i/o handler thread for each
 
3078
segment in these arrays. This function also creates the sync array.
 
3079
No i/o handler thread needs to be created for that */
 
3080
UNIV_INTERN
 
3081
void
 
3082
os_aio_init(
 
3083
/*========*/
 
3084
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
 
3085
                                operations allowed per segment */
 
3086
        ulint   n_read_segs,    /*<! in: number of reader threads */
 
3087
        ulint   n_write_segs,   /*<! in: number of writer threads */
 
3088
        ulint   n_slots_sync)   /*<! in: number of slots in the sync aio
 
3089
                                array */
 
3090
{
 
3091
        ulint   i;
 
3092
        ulint   n_segments = 2 + n_read_segs + n_write_segs;
 
3093
 
 
3094
        ut_ad(n_segments >= 4);
 
3095
 
 
3096
        os_io_init_simple();
 
3097
 
 
3098
        for (i = 0; i < n_segments; i++) {
 
3099
                srv_set_io_thread_op_info(i, "not started yet");
 
3100
        }
 
3101
 
 
3102
 
 
3103
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
 
3104
 
 
3105
        os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
 
3106
 
 
3107
        srv_io_thread_function[0] = "insert buffer thread";
 
3108
 
 
3109
        os_aio_log_array = os_aio_array_create(n_per_seg, 1);
 
3110
 
 
3111
        srv_io_thread_function[1] = "log thread";
 
3112
 
 
3113
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
 
3114
                                                n_read_segs);
 
3115
        for (i = 2; i < 2 + n_read_segs; i++) {
 
3116
                ut_a(i < SRV_MAX_N_IO_THREADS);
 
3117
                srv_io_thread_function[i] = "read thread";
 
3118
        }
 
3119
 
 
3120
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
 
3121
                                                 n_write_segs);
 
3122
        for (i = 2 + n_read_segs; i < n_segments; i++) {
 
3123
                ut_a(i < SRV_MAX_N_IO_THREADS);
 
3124
                srv_io_thread_function[i] = "write thread";
 
3125
        }
 
3126
 
 
3127
        os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
 
3128
 
 
3129
        os_aio_n_segments = n_segments;
 
3130
 
 
3131
        os_aio_validate();
 
3132
 
 
3133
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
 
3134
 
 
3135
        for (i = 0; i < n_segments; i++) {
 
3136
                os_aio_segment_wait_events[i] = os_event_create(NULL);
 
3137
        }
 
3138
 
 
3139
        os_last_printout = time(NULL);
 
3140
 
 
3141
}
 
3142
 
 
3143
/***********************************************************************
 
3144
Frees the asynchronous io system. */
 
3145
UNIV_INTERN
 
3146
void
 
3147
os_aio_free(void)
 
3148
/*=============*/
 
3149
{
 
3150
        ulint   i;
 
3151
 
 
3152
        os_aio_array_free(os_aio_ibuf_array);
 
3153
        os_aio_ibuf_array = NULL;
 
3154
        os_aio_array_free(os_aio_log_array);
 
3155
        os_aio_log_array = NULL;
 
3156
        os_aio_array_free(os_aio_read_array);
 
3157
        os_aio_read_array = NULL;
 
3158
        os_aio_array_free(os_aio_write_array);
 
3159
        os_aio_write_array = NULL;
 
3160
        os_aio_array_free(os_aio_sync_array);
 
3161
        os_aio_sync_array = NULL;
 
3162
 
 
3163
        for (i = 0; i < os_aio_n_segments; i++) {
 
3164
                os_event_free(os_aio_segment_wait_events[i]);
 
3165
        }
 
3166
 
 
3167
        ut_free(os_aio_segment_wait_events);
 
3168
        os_aio_segment_wait_events = 0;
 
3169
        os_aio_n_segments = 0;
 
3170
}
 
3171
 
 
3172
#ifdef WIN_ASYNC_IO
 
3173
/************************************************************************//**
 
3174
Wakes up all async i/o threads in the array in Windows async i/o at
 
3175
shutdown. */
 
3176
static
 
3177
void
 
3178
os_aio_array_wake_win_aio_at_shutdown(
 
3179
/*==================================*/
 
3180
        os_aio_array_t* array)  /*!< in: aio array */
 
3181
{
 
3182
        ulint   i;
 
3183
 
 
3184
        for (i = 0; i < array->n_slots; i++) {
 
3185
 
 
3186
                os_event_set((array->slots + i)->event);
 
3187
        }
 
3188
}
 
3189
#endif
 
3190
 
 
3191
/************************************************************************//**
 
3192
Wakes up all async i/o threads so that they know to exit themselves in
 
3193
shutdown. */
 
3194
UNIV_INTERN
 
3195
void
 
3196
os_aio_wake_all_threads_at_shutdown(void)
 
3197
/*=====================================*/
 
3198
{
 
3199
        ulint   i;
 
3200
 
 
3201
#ifdef WIN_ASYNC_IO
 
3202
        /* This code wakes up all ai/o threads in Windows native aio */
 
3203
        os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
 
3204
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
 
3205
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
 
3206
        os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
 
3207
#endif
 
3208
        /* This loop wakes up all simulated ai/o threads */
 
3209
 
 
3210
        for (i = 0; i < os_aio_n_segments; i++) {
 
3211
 
 
3212
                os_event_set(os_aio_segment_wait_events[i]);
 
3213
        }
 
3214
}
 
3215
 
 
3216
/************************************************************************//**
 
3217
Waits until there are no pending writes in os_aio_write_array. There can
 
3218
be other, synchronous, pending writes. */
 
3219
UNIV_INTERN
 
3220
void
 
3221
os_aio_wait_until_no_pending_writes(void)
 
3222
/*=====================================*/
 
3223
{
 
3224
        os_event_wait(os_aio_write_array->is_empty);
 
3225
}
 
3226
 
 
3227
/**********************************************************************//**
 
3228
Calculates segment number for a slot.
 
3229
@return segment number (which is the number used by, for example,
 
3230
i/o-handler threads) */
 
3231
static
 
3232
ulint
 
3233
os_aio_get_segment_no_from_slot(
 
3234
/*============================*/
 
3235
        os_aio_array_t* array,  /*!< in: aio wait array */
 
3236
        os_aio_slot_t*  slot)   /*!< in: slot in this array */
 
3237
{
 
3238
        ulint   segment;
 
3239
        ulint   seg_len;
 
3240
 
 
3241
        if (array == os_aio_ibuf_array) {
 
3242
                segment = 0;
 
3243
 
 
3244
        } else if (array == os_aio_log_array) {
 
3245
                segment = 1;
 
3246
 
 
3247
        } else if (array == os_aio_read_array) {
 
3248
                seg_len = os_aio_read_array->n_slots
 
3249
                        / os_aio_read_array->n_segments;
 
3250
 
 
3251
                segment = 2 + slot->pos / seg_len;
 
3252
        } else {
 
3253
                ut_a(array == os_aio_write_array);
 
3254
                seg_len = os_aio_write_array->n_slots
 
3255
                        / os_aio_write_array->n_segments;
 
3256
 
 
3257
                segment = os_aio_read_array->n_segments + 2
 
3258
                        + slot->pos / seg_len;
 
3259
        }
 
3260
 
 
3261
        return(segment);
 
3262
}
 
3263
 
 
3264
/**********************************************************************//**
 
3265
Calculates local segment number and aio array from global segment number.
 
3266
@return local segment number within the aio array */
 
3267
static
 
3268
ulint
 
3269
os_aio_get_array_and_local_segment(
 
3270
/*===============================*/
 
3271
        os_aio_array_t** array,         /*!< out: aio wait array */
 
3272
        ulint            global_segment)/*!< in: global segment number */
 
3273
{
 
3274
        ulint   segment;
 
3275
 
 
3276
        ut_a(global_segment < os_aio_n_segments);
 
3277
 
 
3278
        if (global_segment == 0) {
 
3279
                *array = os_aio_ibuf_array;
 
3280
                segment = 0;
 
3281
 
 
3282
        } else if (global_segment == 1) {
 
3283
                *array = os_aio_log_array;
 
3284
                segment = 0;
 
3285
 
 
3286
        } else if (global_segment < os_aio_read_array->n_segments + 2) {
 
3287
                *array = os_aio_read_array;
 
3288
 
 
3289
                segment = global_segment - 2;
 
3290
        } else {
 
3291
                *array = os_aio_write_array;
 
3292
 
 
3293
                segment = global_segment - (os_aio_read_array->n_segments + 2);
 
3294
        }
 
3295
 
 
3296
        return(segment);
 
3297
}
 
3298
 
 
3299
/*******************************************************************//**
 
3300
Requests for a slot in the aio array. If no slot is available, waits until
 
3301
not_full-event becomes signaled.
 
3302
@return pointer to slot */
 
3303
static
 
3304
os_aio_slot_t*
 
3305
os_aio_array_reserve_slot(
 
3306
/*======================*/
 
3307
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
 
3308
        os_aio_array_t* array,  /*!< in: aio array */
 
3309
        fil_node_t*     message1,/*!< in: message to be passed along with
 
3310
                                the aio operation */
 
3311
        void*           message2,/*!< in: message to be passed along with
 
3312
                                the aio operation */
 
3313
        os_file_t       file,   /*!< in: file handle */
 
3314
        const char*     name,   /*!< in: name of the file or path as a
 
3315
                                null-terminated string */
 
3316
        void*           buf,    /*!< in: buffer where to read or from which
 
3317
                                to write */
 
3318
        ulint           offset, /*!< in: least significant 32 bits of file
 
3319
                                offset */
 
3320
        ulint           offset_high, /*!< in: most significant 32 bits of
 
3321
                                offset */
 
3322
        ulint           len)    /*!< in: length of the block to read or write */
 
3323
{
 
3324
        os_aio_slot_t*  slot;
 
3325
#ifdef WIN_ASYNC_IO
 
3326
        OVERLAPPED*     control;
 
3327
#endif
 
3328
        ulint           i;
 
3329
        ulint           slots_per_seg;
 
3330
        ulint           local_seg;
 
3331
 
 
3332
        /* No need of a mutex. Only reading constant fields */
 
3333
        slots_per_seg = array->n_slots / array->n_segments;
 
3334
 
 
3335
        /* We attempt to keep adjacent blocks in the same local
 
3336
        segment. This can help in merging IO requests when we are
 
3337
        doing simulated AIO */
 
3338
        local_seg = (offset >> (UNIV_PAGE_SIZE_SHIFT + 6))
 
3339
                    % array->n_segments;
 
3340
 
 
3341
loop:
 
3342
        os_mutex_enter(array->mutex);
 
3343
 
 
3344
        if (array->n_reserved == array->n_slots) {
 
3345
                os_mutex_exit(array->mutex);
 
3346
 
 
3347
                if (!os_aio_use_native_aio) {
 
3348
                        /* If the handler threads are suspended, wake them
 
3349
                        so that we get more slots */
 
3350
 
 
3351
                        os_aio_simulated_wake_handler_threads();
 
3352
                }
 
3353
 
 
3354
                os_event_wait(array->not_full);
 
3355
 
 
3356
                goto loop;
 
3357
        }
 
3358
 
 
3359
        /* First try to find a slot in the preferred local segment */
 
3360
        for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
 
3361
                slot = os_aio_array_get_nth_slot(array, i);
 
3362
 
 
3363
                if (slot->reserved == FALSE) {
 
3364
                        goto found;
 
3365
                }
 
3366
        }
 
3367
 
 
3368
        /* Fall back to a full scan. We are guaranteed to find a slot */
 
3369
        for (i = 0;; i++) {
 
3370
                slot = os_aio_array_get_nth_slot(array, i);
 
3371
 
 
3372
                if (slot->reserved == FALSE) {
 
3373
                        goto found;
 
3374
                }
 
3375
        }
 
3376
 
 
3377
found:
 
3378
        ut_a(slot->reserved == FALSE);
 
3379
        array->n_reserved++;
 
3380
 
 
3381
        if (array->n_reserved == 1) {
 
3382
                os_event_reset(array->is_empty);
 
3383
        }
 
3384
 
 
3385
        if (array->n_reserved == array->n_slots) {
 
3386
                os_event_reset(array->not_full);
 
3387
        }
 
3388
 
 
3389
        slot->reserved = TRUE;
 
3390
        slot->reservation_time = time(NULL);
 
3391
        slot->message1 = message1;
 
3392
        slot->message2 = message2;
 
3393
        slot->file     = file;
 
3394
        slot->name     = name;
 
3395
        slot->len      = len;
 
3396
        slot->type     = type;
 
3397
        slot->buf      = buf;
 
3398
        slot->offset   = offset;
 
3399
        slot->offset_high = offset_high;
 
3400
        slot->io_already_done = FALSE;
 
3401
 
 
3402
#ifdef WIN_ASYNC_IO
 
3403
        control = &(slot->control);
 
3404
        control->Offset = (DWORD)offset;
 
3405
        control->OffsetHigh = (DWORD)offset_high;
 
3406
        os_event_reset(slot->event);
 
3407
#endif
 
3408
 
 
3409
        os_mutex_exit(array->mutex);
 
3410
 
 
3411
        return(slot);
 
3412
}
 
3413
 
 
3414
/*******************************************************************//**
 
3415
Frees a slot in the aio array. */
 
3416
static
 
3417
void
 
3418
os_aio_array_free_slot(
 
3419
/*===================*/
 
3420
        os_aio_array_t* array,  /*!< in: aio array */
 
3421
        os_aio_slot_t*  slot)   /*!< in: pointer to slot */
 
3422
{
 
3423
        ut_ad(array);
 
3424
        ut_ad(slot);
 
3425
 
 
3426
        os_mutex_enter(array->mutex);
 
3427
 
 
3428
        ut_ad(slot->reserved);
 
3429
 
 
3430
        slot->reserved = FALSE;
 
3431
 
 
3432
        array->n_reserved--;
 
3433
 
 
3434
        if (array->n_reserved == array->n_slots - 1) {
 
3435
                os_event_set(array->not_full);
 
3436
        }
 
3437
 
 
3438
        if (array->n_reserved == 0) {
 
3439
                os_event_set(array->is_empty);
 
3440
        }
 
3441
 
 
3442
#ifdef WIN_ASYNC_IO
 
3443
        os_event_reset(slot->event);
 
3444
#endif
 
3445
        os_mutex_exit(array->mutex);
 
3446
}
 
3447
 
 
3448
/**********************************************************************//**
 
3449
Wakes up a simulated aio i/o-handler thread if it has something to do. */
 
3450
static
 
3451
void
 
3452
os_aio_simulated_wake_handler_thread(
 
3453
/*=================================*/
 
3454
        ulint   global_segment) /*!< in: the number of the segment in the aio
 
3455
                                arrays */
 
3456
{
 
3457
        os_aio_array_t* array;
 
3458
        os_aio_slot_t*  slot;
 
3459
        ulint           segment;
 
3460
        ulint           n;
 
3461
        ulint           i;
 
3462
 
 
3463
        ut_ad(!os_aio_use_native_aio);
 
3464
 
 
3465
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
 
3466
 
 
3467
        n = array->n_slots / array->n_segments;
 
3468
 
 
3469
        /* Look through n slots after the segment * n'th slot */
 
3470
 
 
3471
        os_mutex_enter(array->mutex);
 
3472
 
 
3473
        for (i = 0; i < n; i++) {
 
3474
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
3475
 
 
3476
                if (slot->reserved) {
 
3477
                        /* Found an i/o request */
 
3478
 
 
3479
                        break;
 
3480
                }
 
3481
        }
 
3482
 
 
3483
        os_mutex_exit(array->mutex);
 
3484
 
 
3485
        if (i < n) {
 
3486
                os_event_set(os_aio_segment_wait_events[global_segment]);
 
3487
        }
 
3488
}
 
3489
 
 
3490
/**********************************************************************//**
 
3491
Wakes up simulated aio i/o-handler threads if they have something to do. */
 
3492
UNIV_INTERN
 
3493
void
 
3494
os_aio_simulated_wake_handler_threads(void)
 
3495
/*=======================================*/
 
3496
{
 
3497
        ulint   i;
 
3498
 
 
3499
        if (os_aio_use_native_aio) {
 
3500
                /* We do not use simulated aio: do nothing */
 
3501
 
 
3502
                return;
 
3503
        }
 
3504
 
 
3505
        os_aio_recommend_sleep_for_read_threads = FALSE;
 
3506
 
 
3507
        for (i = 0; i < os_aio_n_segments; i++) {
 
3508
                os_aio_simulated_wake_handler_thread(i);
 
3509
        }
 
3510
}
 
3511
 
 
3512
/**********************************************************************//**
 
3513
This function can be called if one wants to post a batch of reads and
 
3514
prefers an i/o-handler thread to handle them all at once later. You must
 
3515
call os_aio_simulated_wake_handler_threads later to ensure the threads
 
3516
are not left sleeping! */
 
3517
UNIV_INTERN
 
3518
void
 
3519
os_aio_simulated_put_read_threads_to_sleep(void)
 
3520
/*============================================*/
 
3521
{
 
3522
 
 
3523
/* The idea of putting background IO threads to sleep is only for
 
3524
Windows when using simulated AIO. Windows XP seems to schedule
 
3525
background threads too eagerly to allow for coalescing during
 
3526
readahead requests. */
 
3527
#ifdef __WIN__
 
3528
        os_aio_array_t* array;
 
3529
        ulint           g;
 
3530
 
 
3531
        if (os_aio_use_native_aio) {
 
3532
                /* We do not use simulated aio: do nothing */
 
3533
 
 
3534
                return;
 
3535
        }
 
3536
 
 
3537
        os_aio_recommend_sleep_for_read_threads = TRUE;
 
3538
 
 
3539
        for (g = 0; g < os_aio_n_segments; g++) {
 
3540
                os_aio_get_array_and_local_segment(&array, g);
 
3541
 
 
3542
                if (array == os_aio_read_array) {
 
3543
 
 
3544
                        os_event_reset(os_aio_segment_wait_events[g]);
 
3545
                }
 
3546
        }
 
3547
#endif /* __WIN__ */
 
3548
}
 
3549
 
 
3550
/*******************************************************************//**
 
3551
Requests an asynchronous i/o operation.
 
3552
@return TRUE if request was queued successfully, FALSE if fail */
 
3553
UNIV_INTERN
 
3554
ibool
 
3555
os_aio(
 
3556
/*===*/
 
3557
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
 
3558
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
 
3559
                                to OS_AIO_SIMULATED_WAKE_LATER: the
 
3560
                                last flag advises this function not to wake
 
3561
                                i/o-handler threads, but the caller will
 
3562
                                do the waking explicitly later, in this
 
3563
                                way the caller can post several requests in
 
3564
                                a batch; NOTE that the batch must not be
 
3565
                                so big that it exhausts the slots in aio
 
3566
                                arrays! NOTE that a simulated batch
 
3567
                                may introduce hidden chances of deadlocks,
 
3568
                                because i/os are not actually handled until
 
3569
                                all have been posted: use with great
 
3570
                                caution! */
 
3571
        const char*     name,   /*!< in: name of the file or path as a
 
3572
                                null-terminated string */
 
3573
        os_file_t       file,   /*!< in: handle to a file */
 
3574
        void*           buf,    /*!< in: buffer where to read or from which
 
3575
                                to write */
 
3576
        ulint           offset, /*!< in: least significant 32 bits of file
 
3577
                                offset where to read or write */
 
3578
        ulint           offset_high, /*!< in: most significant 32 bits of
 
3579
                                offset */
 
3580
        ulint           n,      /*!< in: number of bytes to read or write */
 
3581
        fil_node_t*     message1,/*!< in: message for the aio handler
 
3582
                                (can be used to identify a completed
 
3583
                                aio operation); ignored if mode is
 
3584
                                OS_AIO_SYNC */
 
3585
        void*           message2)/*!< in: message for the aio handler
 
3586
                                (can be used to identify a completed
 
3587
                                aio operation); ignored if mode is
 
3588
                                OS_AIO_SYNC */
 
3589
{
 
3590
        os_aio_array_t* array;
 
3591
        os_aio_slot_t*  slot;
 
3592
#ifdef WIN_ASYNC_IO
 
3593
        ibool           retval;
 
3594
        BOOL            ret             = TRUE;
 
3595
        DWORD           len             = (DWORD) n;
 
3596
        struct fil_node_struct * dummy_mess1;
 
3597
        void*           dummy_mess2;
 
3598
        ulint           dummy_type;
 
3599
#endif
 
3600
        ulint           err             = 0;
 
3601
        ibool           retry;
 
3602
        ulint           wake_later;
 
3603
 
 
3604
        ut_ad(file);
 
3605
        ut_ad(buf);
 
3606
        ut_ad(n > 0);
 
3607
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
 
3608
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
 
3609
        ut_ad(os_aio_validate());
 
3610
 
 
3611
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
 
3612
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
 
3613
 
 
3614
        if (mode == OS_AIO_SYNC
 
3615
#ifdef WIN_ASYNC_IO
 
3616
            && !os_aio_use_native_aio
 
3617
#endif
 
3618
            ) {
 
3619
                /* This is actually an ordinary synchronous read or write:
 
3620
                no need to use an i/o-handler thread. NOTE that if we use
 
3621
                Windows async i/o, Windows does not allow us to use
 
3622
                ordinary synchronous os_file_read etc. on the same file,
 
3623
                therefore we have built a special mechanism for synchronous
 
3624
                wait in the Windows case. */
 
3625
 
 
3626
                if (type == OS_FILE_READ) {
 
3627
                        return(os_file_read(file, buf, offset,
 
3628
                                            offset_high, n));
 
3629
                }
 
3630
 
 
3631
                ut_a(type == OS_FILE_WRITE);
 
3632
 
 
3633
                return(os_file_write(name, file, buf, offset, offset_high, n));
 
3634
        }
 
3635
 
 
3636
try_again:
 
3637
        if (mode == OS_AIO_NORMAL) {
 
3638
                if (type == OS_FILE_READ) {
 
3639
                        array = os_aio_read_array;
 
3640
                } else {
 
3641
                        array = os_aio_write_array;
 
3642
                }
 
3643
        } else if (mode == OS_AIO_IBUF) {
 
3644
                ut_ad(type == OS_FILE_READ);
 
3645
                /* Reduce probability of deadlock bugs in connection with ibuf:
 
3646
                do not let the ibuf i/o handler sleep */
 
3647
 
 
3648
                wake_later = FALSE;
 
3649
 
 
3650
                array = os_aio_ibuf_array;
 
3651
        } else if (mode == OS_AIO_LOG) {
 
3652
 
 
3653
                array = os_aio_log_array;
 
3654
        } else if (mode == OS_AIO_SYNC) {
 
3655
                array = os_aio_sync_array;
 
3656
        } else {
 
3657
                array = NULL; /* Eliminate compiler warning */
 
3658
                ut_error;
 
3659
        }
 
3660
 
 
3661
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
 
3662
                                         name, buf, offset, offset_high, n);
 
3663
        if (type == OS_FILE_READ) {
 
3664
                if (os_aio_use_native_aio) {
 
3665
#ifdef WIN_ASYNC_IO
 
3666
                        os_n_file_reads++;
 
3667
                        os_bytes_read_since_printout += len;
 
3668
 
 
3669
                        ret = ReadFile(file, buf, (DWORD)n, &len,
 
3670
                                       &(slot->control));
 
3671
#endif
 
3672
                } else {
 
3673
                        if (!wake_later) {
 
3674
                                os_aio_simulated_wake_handler_thread(
 
3675
                                        os_aio_get_segment_no_from_slot(
 
3676
                                                array, slot));
 
3677
                        }
 
3678
                }
 
3679
        } else if (type == OS_FILE_WRITE) {
 
3680
                if (os_aio_use_native_aio) {
 
3681
#ifdef WIN_ASYNC_IO
 
3682
                        os_n_file_writes++;
 
3683
                        ret = WriteFile(file, buf, (DWORD)n, &len,
 
3684
                                        &(slot->control));
 
3685
#endif
 
3686
                } else {
 
3687
                        if (!wake_later) {
 
3688
                                os_aio_simulated_wake_handler_thread(
 
3689
                                        os_aio_get_segment_no_from_slot(
 
3690
                                                array, slot));
 
3691
                        }
 
3692
                }
 
3693
        } else {
 
3694
                ut_error;
 
3695
        }
 
3696
 
 
3697
#ifdef WIN_ASYNC_IO
 
3698
        if (os_aio_use_native_aio) {
 
3699
                if ((ret && len == n)
 
3700
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
 
3701
                        /* aio was queued successfully! */
 
3702
 
 
3703
                        if (mode == OS_AIO_SYNC) {
 
3704
                                /* We want a synchronous i/o operation on a
 
3705
                                file where we also use async i/o: in Windows
 
3706
                                we must use the same wait mechanism as for
 
3707
                                async i/o */
 
3708
 
 
3709
                                retval = os_aio_windows_handle(ULINT_UNDEFINED,
 
3710
                                                               slot->pos,
 
3711
                                                               &dummy_mess1,
 
3712
                                                               &dummy_mess2,
 
3713
                                                               &dummy_type);
 
3714
 
 
3715
                                return(retval);
 
3716
                        }
 
3717
 
 
3718
                        return(TRUE);
 
3719
                }
 
3720
 
 
3721
                err = 1; /* Fall through the next if */
 
3722
        }
 
3723
#endif
 
3724
        if (err == 0) {
 
3725
                /* aio was queued successfully! */
 
3726
 
 
3727
                return(TRUE);
 
3728
        }
 
3729
 
 
3730
        os_aio_array_free_slot(array, slot);
 
3731
 
 
3732
        retry = os_file_handle_error(name,
 
3733
                                     type == OS_FILE_READ
 
3734
                                     ? "aio read" : "aio write");
 
3735
        if (retry) {
 
3736
 
 
3737
                goto try_again;
 
3738
        }
 
3739
 
 
3740
        return(FALSE);
 
3741
}
 
3742
 
 
3743
#ifdef WIN_ASYNC_IO
 
3744
/**********************************************************************//**
 
3745
This function is only used in Windows asynchronous i/o.
 
3746
Waits for an aio operation to complete. This function is used to wait the
 
3747
for completed requests. The aio array of pending requests is divided
 
3748
into segments. The thread specifies which segment or slot it wants to wait
 
3749
for. NOTE: this function will also take care of freeing the aio slot,
 
3750
therefore no other thread is allowed to do the freeing!
 
3751
@return TRUE if the aio operation succeeded */
 
3752
UNIV_INTERN
 
3753
ibool
 
3754
os_aio_windows_handle(
 
3755
/*==================*/
 
3756
        ulint   segment,        /*!< in: the number of the segment in the aio
 
3757
                                arrays to wait for; segment 0 is the ibuf
 
3758
                                i/o thread, segment 1 the log i/o thread,
 
3759
                                then follow the non-ibuf read threads, and as
 
3760
                                the last are the non-ibuf write threads; if
 
3761
                                this is ULINT_UNDEFINED, then it means that
 
3762
                                sync aio is used, and this parameter is
 
3763
                                ignored */
 
3764
        ulint   pos,            /*!< this parameter is used only in sync aio:
 
3765
                                wait for the aio slot at this position */
 
3766
        fil_node_t**message1,   /*!< out: the messages passed with the aio
 
3767
                                request; note that also in the case where
 
3768
                                the aio operation failed, these output
 
3769
                                parameters are valid and can be used to
 
3770
                                restart the operation, for example */
 
3771
        void**  message2,
 
3772
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
 
3773
{
 
3774
        ulint           orig_seg        = segment;
 
3775
        os_aio_array_t* array;
 
3776
        os_aio_slot_t*  slot;
 
3777
        ulint           n;
 
3778
        ulint           i;
 
3779
        ibool           ret_val;
 
3780
        BOOL            ret;
 
3781
        DWORD           len;
 
3782
        BOOL            retry           = FALSE;
 
3783
 
 
3784
        if (segment == ULINT_UNDEFINED) {
 
3785
                array = os_aio_sync_array;
 
3786
                segment = 0;
 
3787
        } else {
 
3788
                segment = os_aio_get_array_and_local_segment(&array, segment);
 
3789
        }
 
3790
 
 
3791
        /* NOTE! We only access constant fields in os_aio_array. Therefore
 
3792
        we do not have to acquire the protecting mutex yet */
 
3793
 
 
3794
        ut_ad(os_aio_validate());
 
3795
        ut_ad(segment < array->n_segments);
 
3796
 
 
3797
        n = array->n_slots / array->n_segments;
 
3798
 
 
3799
        if (array == os_aio_sync_array) {
 
3800
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
 
3801
                i = pos;
 
3802
        } else {
 
3803
                srv_set_io_thread_op_info(orig_seg, "wait Windows aio");
 
3804
                i = os_event_wait_multiple(n,
 
3805
                                           (array->native_events)
 
3806
                                           + segment * n);
 
3807
        }
 
3808
 
 
3809
        os_mutex_enter(array->mutex);
 
3810
 
 
3811
        slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
3812
 
 
3813
        ut_a(slot->reserved);
 
3814
 
 
3815
        if (orig_seg != ULINT_UNDEFINED) {
 
3816
                srv_set_io_thread_op_info(orig_seg,
 
3817
                                          "get windows aio return value");
 
3818
        }
 
3819
 
 
3820
        ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
 
3821
 
 
3822
        *message1 = slot->message1;
 
3823
        *message2 = slot->message2;
 
3824
 
 
3825
        *type = slot->type;
 
3826
 
 
3827
        if (ret && len == slot->len) {
 
3828
                ret_val = TRUE;
 
3829
 
 
3830
#ifdef UNIV_DO_FLUSH
 
3831
                if (slot->type == OS_FILE_WRITE
 
3832
                    && !os_do_not_call_flush_at_each_write) {
 
3833
                        ut_a(TRUE == os_file_flush(slot->file));
 
3834
                }
 
3835
#endif /* UNIV_DO_FLUSH */
 
3836
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
 
3837
 
 
3838
                retry = TRUE;
 
3839
        } else {
 
3840
 
 
3841
                ret_val = FALSE;
 
3842
        }
 
3843
 
 
3844
        os_mutex_exit(array->mutex);
 
3845
 
 
3846
        if (retry) {
 
3847
                /* retry failed read/write operation synchronously.
 
3848
                No need to hold array->mutex. */
 
3849
 
 
3850
                switch (slot->type) {
 
3851
                case OS_FILE_WRITE:
 
3852
                        ret = WriteFile(slot->file, slot->buf,
 
3853
                                        slot->len, &len,
 
3854
                                        &(slot->control));
 
3855
 
 
3856
                        break;
 
3857
                case OS_FILE_READ:
 
3858
                        ret = ReadFile(slot->file, slot->buf,
 
3859
                                       slot->len, &len,
 
3860
                                       &(slot->control));
 
3861
 
 
3862
                        break;
 
3863
                default:
 
3864
                        ut_error;
 
3865
                }
 
3866
 
 
3867
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
 
3868
                        /* aio was queued successfully!
 
3869
                        We want a synchronous i/o operation on a
 
3870
                        file where we also use async i/o: in Windows
 
3871
                        we must use the same wait mechanism as for
 
3872
                        async i/o */
 
3873
 
 
3874
                        ret = GetOverlappedResult(slot->file,
 
3875
                                                  &(slot->control),
 
3876
                                                  &len, TRUE);
 
3877
                }
 
3878
 
 
3879
                ret_val = ret && len == slot->len;
 
3880
        }
 
3881
 
 
3882
        os_aio_array_free_slot(array, slot);
 
3883
 
 
3884
        return(ret_val);
 
3885
}
 
3886
#endif
 
3887
 
 
3888
/**********************************************************************//**
 
3889
Does simulated aio. This function should be called by an i/o-handler
 
3890
thread.
 
3891
@return TRUE if the aio operation succeeded */
 
3892
UNIV_INTERN
 
3893
ibool
 
3894
os_aio_simulated_handle(
 
3895
/*====================*/
 
3896
        ulint   global_segment, /*!< in: the number of the segment in the aio
 
3897
                                arrays to wait for; segment 0 is the ibuf
 
3898
                                i/o thread, segment 1 the log i/o thread,
 
3899
                                then follow the non-ibuf read threads, and as
 
3900
                                the last are the non-ibuf write threads */
 
3901
        fil_node_t**message1,   /*!< out: the messages passed with the aio
 
3902
                                request; note that also in the case where
 
3903
                                the aio operation failed, these output
 
3904
                                parameters are valid and can be used to
 
3905
                                restart the operation, for example */
 
3906
        void**  message2,
 
3907
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
 
3908
{
 
3909
        os_aio_array_t* array;
 
3910
        ulint           segment;
 
3911
        os_aio_slot_t*  slot;
 
3912
        os_aio_slot_t*  slot2;
 
3913
        os_aio_slot_t*  consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
 
3914
        ulint           n_consecutive;
 
3915
        ulint           total_len;
 
3916
        ulint           offs;
 
3917
        ulint           lowest_offset;
 
3918
        ulint           biggest_age;
 
3919
        ulint           age;
 
3920
        byte*           combined_buf;
 
3921
        byte*           combined_buf2;
 
3922
        ibool           ret;
 
3923
        ulint           n;
 
3924
        ulint           i;
 
3925
 
 
3926
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
 
3927
 
 
3928
restart:
 
3929
        /* NOTE! We only access constant fields in os_aio_array. Therefore
 
3930
        we do not have to acquire the protecting mutex yet */
 
3931
 
 
3932
        srv_set_io_thread_op_info(global_segment,
 
3933
                                  "looking for i/o requests (a)");
 
3934
        ut_ad(os_aio_validate());
 
3935
        ut_ad(segment < array->n_segments);
 
3936
 
 
3937
        n = array->n_slots / array->n_segments;
 
3938
 
 
3939
        /* Look through n slots after the segment * n'th slot */
 
3940
 
 
3941
        if (array == os_aio_read_array
 
3942
            && os_aio_recommend_sleep_for_read_threads) {
 
3943
 
 
3944
                /* Give other threads chance to add several i/os to the array
 
3945
                at once. */
 
3946
 
 
3947
                goto recommended_sleep;
 
3948
        }
 
3949
 
 
3950
        os_mutex_enter(array->mutex);
 
3951
 
 
3952
        srv_set_io_thread_op_info(global_segment,
 
3953
                                  "looking for i/o requests (b)");
 
3954
 
 
3955
        /* Check if there is a slot for which the i/o has already been
 
3956
        done */
 
3957
 
 
3958
        for (i = 0; i < n; i++) {
 
3959
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
3960
 
 
3961
                if (slot->reserved && slot->io_already_done) {
 
3962
 
 
3963
                        if (os_aio_print_debug) {
 
3964
                                fprintf(stderr,
 
3965
                                        "InnoDB: i/o for slot %lu"
 
3966
                                        " already done, returning\n",
 
3967
                                        (ulong) i);
 
3968
                        }
 
3969
 
 
3970
                        ret = TRUE;
 
3971
 
 
3972
                        goto slot_io_done;
 
3973
                }
 
3974
        }
 
3975
 
 
3976
        n_consecutive = 0;
 
3977
 
 
3978
        /* If there are at least 2 seconds old requests, then pick the oldest
 
3979
        one to prevent starvation. If several requests have the same age,
 
3980
        then pick the one at the lowest offset. */
 
3981
 
 
3982
        biggest_age = 0;
 
3983
        lowest_offset = ULINT_MAX;
 
3984
 
 
3985
        for (i = 0; i < n; i++) {
 
3986
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
 
3987
 
 
3988
                if (slot->reserved) {
 
3989
                        age = (ulint)difftime(time(NULL),
 
3990
                                              slot->reservation_time);
 
3991
 
 
3992
                        if ((age >= 2 && age > biggest_age)
 
3993
                            || (age >= 2 && age == biggest_age
 
3994
                                && slot->offset < lowest_offset)) {
 
3995
 
 
3996
                                /* Found an i/o request */
 
3997
                                consecutive_ios[0] = slot;
 
3998
 
 
3999
                                n_consecutive = 1;
 
4000
 
 
4001
                                biggest_age = age;
 
4002
                                lowest_offset = slot->offset;
 
4003
                        }
 
4004
                }
 
4005
        }
 
4006
 
 
4007
        if (n_consecutive == 0) {
 
4008
                /* There were no old requests. Look for an i/o request at the
 
4009
                lowest offset in the array (we ignore the high 32 bits of the
 
4010
                offset in these heuristics) */
 
4011
 
 
4012
                lowest_offset = ULINT_MAX;
 
4013
 
 
4014
                for (i = 0; i < n; i++) {
 
4015
                        slot = os_aio_array_get_nth_slot(array,
 
4016
                                                         i + segment * n);
 
4017
 
 
4018
                        if (slot->reserved && slot->offset < lowest_offset) {
 
4019
 
 
4020
                                /* Found an i/o request */
 
4021
                                consecutive_ios[0] = slot;
 
4022
 
 
4023
                                n_consecutive = 1;
 
4024
 
 
4025
                                lowest_offset = slot->offset;
 
4026
                        }
 
4027
                }
 
4028
        }
 
4029
 
 
4030
        if (n_consecutive == 0) {
 
4031
 
 
4032
                /* No i/o requested at the moment */
 
4033
 
 
4034
                goto wait_for_io;
 
4035
        }
 
4036
 
 
4037
        slot = consecutive_ios[0];
 
4038
 
 
4039
        /* Check if there are several consecutive blocks to read or write */
 
4040
 
 
4041
consecutive_loop:
 
4042
        for (i = 0; i < n; i++) {
 
4043
                slot2 = os_aio_array_get_nth_slot(array, i + segment * n);
 
4044
 
 
4045
                if (slot2->reserved && slot2 != slot
 
4046
                    && slot2->offset == slot->offset + slot->len
 
4047
                    /* check that sum does not wrap over */
 
4048
                    && slot->offset + slot->len > slot->offset
 
4049
                    && slot2->offset_high == slot->offset_high
 
4050
                    && slot2->type == slot->type
 
4051
                    && slot2->file == slot->file) {
 
4052
 
 
4053
                        /* Found a consecutive i/o request */
 
4054
 
 
4055
                        consecutive_ios[n_consecutive] = slot2;
 
4056
                        n_consecutive++;
 
4057
 
 
4058
                        slot = slot2;
 
4059
 
 
4060
                        if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) {
 
4061
 
 
4062
                                goto consecutive_loop;
 
4063
                        } else {
 
4064
                                break;
 
4065
                        }
 
4066
                }
 
4067
        }
 
4068
 
 
4069
        srv_set_io_thread_op_info(global_segment, "consecutive i/o requests");
 
4070
 
 
4071
        /* We have now collected n_consecutive i/o requests in the array;
 
4072
        allocate a single buffer which can hold all data, and perform the
 
4073
        i/o */
 
4074
 
 
4075
        total_len = 0;
 
4076
        slot = consecutive_ios[0];
 
4077
 
 
4078
        for (i = 0; i < n_consecutive; i++) {
 
4079
                total_len += consecutive_ios[i]->len;
 
4080
        }
 
4081
 
 
4082
        if (n_consecutive == 1) {
 
4083
                /* We can use the buffer of the i/o request */
 
4084
                combined_buf = slot->buf;
 
4085
                combined_buf2 = NULL;
 
4086
        } else {
 
4087
                combined_buf2 = ut_malloc(total_len + UNIV_PAGE_SIZE);
 
4088
 
 
4089
                ut_a(combined_buf2);
 
4090
 
 
4091
                combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE);
 
4092
        }
 
4093
 
 
4094
        /* We release the array mutex for the time of the i/o: NOTE that
 
4095
        this assumes that there is just one i/o-handler thread serving
 
4096
        a single segment of slots! */
 
4097
 
 
4098
        os_mutex_exit(array->mutex);
 
4099
 
 
4100
        if (slot->type == OS_FILE_WRITE && n_consecutive > 1) {
 
4101
                /* Copy the buffers to the combined buffer */
 
4102
                offs = 0;
 
4103
 
 
4104
                for (i = 0; i < n_consecutive; i++) {
 
4105
 
 
4106
                        ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf,
 
4107
                                  consecutive_ios[i]->len);
 
4108
                        offs += consecutive_ios[i]->len;
 
4109
                }
 
4110
        }
 
4111
 
 
4112
        srv_set_io_thread_op_info(global_segment, "doing file i/o");
 
4113
 
 
4114
        if (os_aio_print_debug) {
 
4115
                fprintf(stderr,
 
4116
                        "InnoDB: doing i/o of type %lu at offset %lu %lu,"
 
4117
                        " length %lu\n",
 
4118
                        (ulong) slot->type, (ulong) slot->offset_high,
 
4119
                        (ulong) slot->offset, (ulong) total_len);
 
4120
        }
 
4121
 
 
4122
        /* Do the i/o with ordinary, synchronous i/o functions: */
 
4123
        if (slot->type == OS_FILE_WRITE) {
 
4124
                ret = os_file_write(slot->name, slot->file, combined_buf,
 
4125
                                    slot->offset, slot->offset_high,
 
4126
                                    total_len);
 
4127
        } else {
 
4128
                ret = os_file_read(slot->file, combined_buf,
 
4129
                                   slot->offset, slot->offset_high, total_len);
 
4130
        }
 
4131
 
 
4132
        ut_a(ret);
 
4133
        srv_set_io_thread_op_info(global_segment, "file i/o done");
 
4134
 
 
4135
#if 0
 
4136
        fprintf(stderr,
 
4137
                "aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
 
4138
                n_consecutive, global_segment, slot->offset / UNIV_PAGE_SIZE);
 
4139
#endif
 
4140
 
 
4141
        if (slot->type == OS_FILE_READ && n_consecutive > 1) {
 
4142
                /* Copy the combined buffer to individual buffers */
 
4143
                offs = 0;
 
4144
 
 
4145
                for (i = 0; i < n_consecutive; i++) {
 
4146
 
 
4147
                        ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs,
 
4148
                                  consecutive_ios[i]->len);
 
4149
                        offs += consecutive_ios[i]->len;
 
4150
                }
 
4151
        }
 
4152
 
 
4153
        if (combined_buf2) {
 
4154
                ut_free(combined_buf2);
 
4155
        }
 
4156
 
 
4157
        os_mutex_enter(array->mutex);
 
4158
 
 
4159
        /* Mark the i/os done in slots */
 
4160
 
 
4161
        for (i = 0; i < n_consecutive; i++) {
 
4162
                consecutive_ios[i]->io_already_done = TRUE;
 
4163
        }
 
4164
 
 
4165
        /* We return the messages for the first slot now, and if there were
 
4166
        several slots, the messages will be returned with subsequent calls
 
4167
        of this function */
 
4168
 
 
4169
slot_io_done:
 
4170
 
 
4171
        ut_a(slot->reserved);
 
4172
 
 
4173
        *message1 = slot->message1;
 
4174
        *message2 = slot->message2;
 
4175
 
 
4176
        *type = slot->type;
 
4177
 
 
4178
        os_mutex_exit(array->mutex);
 
4179
 
 
4180
        os_aio_array_free_slot(array, slot);
 
4181
 
 
4182
        return(ret);
 
4183
 
 
4184
wait_for_io:
 
4185
        srv_set_io_thread_op_info(global_segment, "resetting wait event");
 
4186
 
 
4187
        /* We wait here until there again can be i/os in the segment
 
4188
        of this thread */
 
4189
 
 
4190
        os_event_reset(os_aio_segment_wait_events[global_segment]);
 
4191
 
 
4192
        os_mutex_exit(array->mutex);
 
4193
 
 
4194
recommended_sleep:
 
4195
        srv_set_io_thread_op_info(global_segment, "waiting for i/o request");
 
4196
 
 
4197
        os_event_wait(os_aio_segment_wait_events[global_segment]);
 
4198
 
 
4199
        if (os_aio_print_debug) {
 
4200
                fprintf(stderr,
 
4201
                        "InnoDB: i/o handler thread for i/o"
 
4202
                        " segment %lu wakes up\n",
 
4203
                        (ulong) global_segment);
 
4204
        }
 
4205
 
 
4206
        goto restart;
 
4207
}
 
4208
 
 
4209
/**********************************************************************//**
 
4210
Validates the consistency of an aio array.
 
4211
@return TRUE if ok */
 
4212
static
 
4213
ibool
 
4214
os_aio_array_validate(
 
4215
/*==================*/
 
4216
        os_aio_array_t* array)  /*!< in: aio wait array */
 
4217
{
 
4218
        os_aio_slot_t*  slot;
 
4219
        ulint           n_reserved      = 0;
 
4220
        ulint           i;
 
4221
 
 
4222
        ut_a(array);
 
4223
 
 
4224
        os_mutex_enter(array->mutex);
 
4225
 
 
4226
        ut_a(array->n_slots > 0);
 
4227
        ut_a(array->n_segments > 0);
 
4228
 
 
4229
        for (i = 0; i < array->n_slots; i++) {
 
4230
                slot = os_aio_array_get_nth_slot(array, i);
 
4231
 
 
4232
                if (slot->reserved) {
 
4233
                        n_reserved++;
 
4234
                        ut_a(slot->len > 0);
 
4235
                }
 
4236
        }
 
4237
 
 
4238
        ut_a(array->n_reserved == n_reserved);
 
4239
 
 
4240
        os_mutex_exit(array->mutex);
 
4241
 
 
4242
        return(TRUE);
 
4243
}
 
4244
 
 
4245
/**********************************************************************//**
 
4246
Validates the consistency the aio system.
 
4247
@return TRUE if ok */
 
4248
UNIV_INTERN
 
4249
ibool
 
4250
os_aio_validate(void)
 
4251
/*=================*/
 
4252
{
 
4253
        os_aio_array_validate(os_aio_read_array);
 
4254
        os_aio_array_validate(os_aio_write_array);
 
4255
        os_aio_array_validate(os_aio_ibuf_array);
 
4256
        os_aio_array_validate(os_aio_log_array);
 
4257
        os_aio_array_validate(os_aio_sync_array);
 
4258
 
 
4259
        return(TRUE);
 
4260
}
 
4261
 
 
4262
/**********************************************************************//**
 
4263
Prints info of the aio arrays. */
 
4264
UNIV_INTERN
 
4265
void
 
4266
os_aio_print(
 
4267
/*=========*/
 
4268
        FILE*   file)   /*!< in: file where to print */
 
4269
{
 
4270
        os_aio_array_t* array;
 
4271
        os_aio_slot_t*  slot;
 
4272
        ulint           n_reserved;
 
4273
        time_t          current_time;
 
4274
        double          time_elapsed;
 
4275
        double          avg_bytes_read;
 
4276
        ulint           i;
 
4277
 
 
4278
        for (i = 0; i < srv_n_file_io_threads; i++) {
 
4279
                fprintf(file, "I/O thread %lu state: %s (%s)", (ulong) i,
 
4280
                        srv_io_thread_op_info[i],
 
4281
                        srv_io_thread_function[i]);
 
4282
 
 
4283
#ifndef __WIN__
 
4284
                if (os_aio_segment_wait_events[i]->is_set) {
 
4285
                        fprintf(file, " ev set");
 
4286
                }
 
4287
#endif
 
4288
 
 
4289
                fprintf(file, "\n");
 
4290
        }
 
4291
 
 
4292
        fputs("Pending normal aio reads:", file);
 
4293
 
 
4294
        array = os_aio_read_array;
 
4295
loop:
 
4296
        ut_a(array);
 
4297
 
 
4298
        os_mutex_enter(array->mutex);
 
4299
 
 
4300
        ut_a(array->n_slots > 0);
 
4301
        ut_a(array->n_segments > 0);
 
4302
 
 
4303
        n_reserved = 0;
 
4304
 
 
4305
        for (i = 0; i < array->n_slots; i++) {
 
4306
                slot = os_aio_array_get_nth_slot(array, i);
 
4307
 
 
4308
                if (slot->reserved) {
 
4309
                        n_reserved++;
 
4310
#if 0
 
4311
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
 
4312
                                (void*) slot->message1,
 
4313
                                (void*) slot->message2);
 
4314
#endif
 
4315
                        ut_a(slot->len > 0);
 
4316
                }
 
4317
        }
 
4318
 
 
4319
        ut_a(array->n_reserved == n_reserved);
 
4320
 
 
4321
        fprintf(file, " %lu", (ulong) n_reserved);
 
4322
 
 
4323
        os_mutex_exit(array->mutex);
 
4324
 
 
4325
        if (array == os_aio_read_array) {
 
4326
                fputs(", aio writes:", file);
 
4327
 
 
4328
                array = os_aio_write_array;
 
4329
 
 
4330
                goto loop;
 
4331
        }
 
4332
 
 
4333
        if (array == os_aio_write_array) {
 
4334
                fputs(",\n ibuf aio reads:", file);
 
4335
                array = os_aio_ibuf_array;
 
4336
 
 
4337
                goto loop;
 
4338
        }
 
4339
 
 
4340
        if (array == os_aio_ibuf_array) {
 
4341
                fputs(", log i/o's:", file);
 
4342
                array = os_aio_log_array;
 
4343
 
 
4344
                goto loop;
 
4345
        }
 
4346
 
 
4347
        if (array == os_aio_log_array) {
 
4348
                fputs(", sync i/o's:", file);
 
4349
                array = os_aio_sync_array;
 
4350
 
 
4351
                goto loop;
 
4352
        }
 
4353
 
 
4354
        putc('\n', file);
 
4355
        current_time = time(NULL);
 
4356
        time_elapsed = 0.001 + difftime(current_time, os_last_printout);
 
4357
 
 
4358
        fprintf(file,
 
4359
                "Pending flushes (fsync) log: %lu; buffer pool: %lu\n"
 
4360
                "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
 
4361
                (ulong) fil_n_pending_log_flushes,
 
4362
                (ulong) fil_n_pending_tablespace_flushes,
 
4363
                (ulong) os_n_file_reads, (ulong) os_n_file_writes,
 
4364
                (ulong) os_n_fsyncs);
 
4365
 
 
4366
        if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) {
 
4367
                fprintf(file,
 
4368
                        "%lu pending preads, %lu pending pwrites\n",
 
4369
                        (ulong) os_file_n_pending_preads,
 
4370
                        (ulong) os_file_n_pending_pwrites);
 
4371
        }
 
4372
 
 
4373
        if (os_n_file_reads == os_n_file_reads_old) {
 
4374
                avg_bytes_read = 0.0;
 
4375
        } else {
 
4376
                avg_bytes_read = (double) os_bytes_read_since_printout
 
4377
                        / (os_n_file_reads - os_n_file_reads_old);
 
4378
        }
 
4379
 
 
4380
        fprintf(file,
 
4381
                "%.2f reads/s, %lu avg bytes/read,"
 
4382
                " %.2f writes/s, %.2f fsyncs/s\n",
 
4383
                (os_n_file_reads - os_n_file_reads_old)
 
4384
                / time_elapsed,
 
4385
                (ulong)avg_bytes_read,
 
4386
                (os_n_file_writes - os_n_file_writes_old)
 
4387
                / time_elapsed,
 
4388
                (os_n_fsyncs - os_n_fsyncs_old)
 
4389
                / time_elapsed);
 
4390
 
 
4391
        os_n_file_reads_old = os_n_file_reads;
 
4392
        os_n_file_writes_old = os_n_file_writes;
 
4393
        os_n_fsyncs_old = os_n_fsyncs;
 
4394
        os_bytes_read_since_printout = 0;
 
4395
 
 
4396
        os_last_printout = current_time;
 
4397
}
 
4398
 
 
4399
/**********************************************************************//**
 
4400
Refreshes the statistics used to print per-second averages. */
 
4401
UNIV_INTERN
 
4402
void
 
4403
os_aio_refresh_stats(void)
 
4404
/*======================*/
 
4405
{
 
4406
        os_n_file_reads_old = os_n_file_reads;
 
4407
        os_n_file_writes_old = os_n_file_writes;
 
4408
        os_n_fsyncs_old = os_n_fsyncs;
 
4409
        os_bytes_read_since_printout = 0;
 
4410
 
 
4411
        os_last_printout = time(NULL);
 
4412
}
 
4413
 
 
4414
#ifdef UNIV_DEBUG
 
4415
/**********************************************************************//**
 
4416
Checks that all slots in the system have been freed, that is, there are
 
4417
no pending io operations.
 
4418
@return TRUE if all free */
 
4419
UNIV_INTERN
 
4420
ibool
 
4421
os_aio_all_slots_free(void)
 
4422
/*=======================*/
 
4423
{
 
4424
        os_aio_array_t* array;
 
4425
        ulint           n_res   = 0;
 
4426
 
 
4427
        array = os_aio_read_array;
 
4428
 
 
4429
        os_mutex_enter(array->mutex);
 
4430
 
 
4431
        n_res += array->n_reserved;
 
4432
 
 
4433
        os_mutex_exit(array->mutex);
 
4434
 
 
4435
        array = os_aio_write_array;
 
4436
 
 
4437
        os_mutex_enter(array->mutex);
 
4438
 
 
4439
        n_res += array->n_reserved;
 
4440
 
 
4441
        os_mutex_exit(array->mutex);
 
4442
 
 
4443
        array = os_aio_ibuf_array;
 
4444
 
 
4445
        os_mutex_enter(array->mutex);
 
4446
 
 
4447
        n_res += array->n_reserved;
 
4448
 
 
4449
        os_mutex_exit(array->mutex);
 
4450
 
 
4451
        array = os_aio_log_array;
 
4452
 
 
4453
        os_mutex_enter(array->mutex);
 
4454
 
 
4455
        n_res += array->n_reserved;
 
4456
 
 
4457
        os_mutex_exit(array->mutex);
 
4458
 
 
4459
        array = os_aio_sync_array;
 
4460
 
 
4461
        os_mutex_enter(array->mutex);
 
4462
 
 
4463
        n_res += array->n_reserved;
 
4464
 
 
4465
        os_mutex_exit(array->mutex);
 
4466
 
 
4467
        if (n_res == 0) {
 
4468
 
 
4469
                return(TRUE);
 
4470
        }
 
4471
 
 
4472
        return(FALSE);
 
4473
}
 
4474
#endif /* UNIV_DEBUG */
 
4475
 
 
4476
#endif /* !UNIV_HOTBACKUP */