~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/os/os0file.c

  • Committer: Brian Aker
  • Date: 2010-12-18 18:24:57 UTC
  • mfrom: (1999.6.3 trunk)
  • Revision ID: brian@tangent.org-20101218182457-yi1wd0so2hml1k1w
Merge in Lee's copyright header fix

Show diffs side-by-side

added added

removed removed

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