~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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 drizzled 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 = static_cast<char* >(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: used in the diagnostic message */
1302
 
        const char*     operation_name)
1303
 
                                        /*!< 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 = static_cast<unsigned char *>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
1941
 
 
1942
 
        /* Align the buffer for possible raw i/o */
1943
 
        buf = static_cast<unsigned char *>(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
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2408
 
        no more than 32 bits. */
2409
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2410
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2411
 
 
2412
 
        os_n_file_reads++;
2413
 
        os_bytes_read_since_printout += n;
2414
 
 
2415
 
try_again:
2416
 
        ut_ad(file);
2417
 
        ut_ad(buf);
2418
 
        ut_ad(n > 0);
2419
 
 
2420
 
        low = (DWORD) offset;
2421
 
        high = (DWORD) offset_high;
2422
 
 
2423
 
        os_mutex_enter(os_file_count_mutex);
2424
 
        os_n_pending_reads++;
2425
 
        os_mutex_exit(os_file_count_mutex);
2426
 
 
2427
 
#ifndef UNIV_HOTBACKUP
2428
 
        /* Protect the seek / read operation with a mutex */
2429
 
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2430
 
 
2431
 
        os_mutex_enter(os_file_seek_mutexes[i]);
2432
 
#endif /* !UNIV_HOTBACKUP */
2433
 
 
2434
 
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2435
 
 
2436
 
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2437
 
 
2438
 
#ifndef UNIV_HOTBACKUP
2439
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2440
 
#endif /* !UNIV_HOTBACKUP */
2441
 
 
2442
 
                os_mutex_enter(os_file_count_mutex);
2443
 
                os_n_pending_reads--;
2444
 
                os_mutex_exit(os_file_count_mutex);
2445
 
 
2446
 
                goto error_handling;
2447
 
        }
2448
 
 
2449
 
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2450
 
 
2451
 
#ifndef UNIV_HOTBACKUP
2452
 
        os_mutex_exit(os_file_seek_mutexes[i]);
2453
 
#endif /* !UNIV_HOTBACKUP */
2454
 
 
2455
 
        os_mutex_enter(os_file_count_mutex);
2456
 
        os_n_pending_reads--;
2457
 
        os_mutex_exit(os_file_count_mutex);
2458
 
 
2459
 
        if (ret && len == n) {
2460
 
                return(TRUE);
2461
 
        }
2462
 
#else /* __WIN__ */
2463
 
        ibool   retry;
2464
 
        ssize_t ret;
2465
 
 
2466
 
        os_bytes_read_since_printout += n;
2467
 
 
2468
 
try_again:
2469
 
        ret = os_file_pread(file, buf, n, offset, offset_high);
2470
 
 
2471
 
        if ((ulint)ret == n) {
2472
 
 
2473
 
                return(TRUE);
2474
 
        }
2475
 
 
2476
 
        fprintf(stderr,
2477
 
                "InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n"
2478
 
                "InnoDB: Was only able to read %ld.\n",
2479
 
                (ulong)n, (ulong)offset_high,
2480
 
                (ulong)offset, (long)ret);
2481
 
#endif /* __WIN__ */
2482
 
#ifdef __WIN__
2483
 
error_handling:
2484
 
#endif
2485
 
        retry = os_file_handle_error(NULL, "read");
2486
 
 
2487
 
        if (retry) {
2488
 
                goto try_again;
2489
 
        }
2490
 
 
2491
 
        fprintf(stderr,
2492
 
                "InnoDB: Fatal error: cannot read from file."
2493
 
                " OS error number %lu.\n",
2494
 
#ifdef __WIN__
2495
 
                (ulong) GetLastError()
2496
 
#else
2497
 
                (ulong) errno
2498
 
#endif
2499
 
                );
2500
 
        fflush(stderr);
2501
 
 
2502
 
        ut_error;
2503
 
 
2504
 
        return(FALSE);
2505
 
}
2506
 
 
2507
 
/*******************************************************************//**
2508
 
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
2509
 
not directly this function!
2510
 
Requests a synchronous positioned read operation. This function does not do
2511
 
any error handling. In case of error it returns FALSE.
2512
 
@return TRUE if request was successful, FALSE if fail */
2513
 
UNIV_INTERN
2514
 
ibool
2515
 
os_file_read_no_error_handling_func(
2516
 
/*================================*/
2517
 
        os_file_t       file,   /*!< in: handle to a file */
2518
 
        void*           buf,    /*!< in: buffer where to read */
2519
 
        ulint           offset, /*!< in: least significant 32 bits of file
2520
 
                                offset where to read */
2521
 
        ulint           offset_high, /*!< in: most significant 32 bits of
2522
 
                                offset */
2523
 
        ulint           n)      /*!< in: number of bytes to read */
2524
 
{
2525
 
#ifdef __WIN__
2526
 
        BOOL            ret;
2527
 
        DWORD           len;
2528
 
        DWORD           ret2;
2529
 
        DWORD           low;
2530
 
        DWORD           high;
2531
 
        ibool           retry;
2532
 
#ifndef UNIV_HOTBACKUP
2533
 
        ulint           i;
2534
 
#endif /* !UNIV_HOTBACKUP */
2535
 
 
2536
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2537
 
        no more than 32 bits. */
2538
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2539
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2540
 
 
2541
 
        os_n_file_reads++;
2542
 
        os_bytes_read_since_printout += n;
2543
 
 
2544
 
try_again:
2545
 
        ut_ad(file);
2546
 
        ut_ad(buf);
2547
 
        ut_ad(n > 0);
2548
 
 
2549
 
        low = (DWORD) offset;
2550
 
        high = (DWORD) offset_high;
2551
 
 
2552
 
        os_mutex_enter(os_file_count_mutex);
2553
 
        os_n_pending_reads++;
2554
 
        os_mutex_exit(os_file_count_mutex);
2555
 
 
2556
 
#ifndef UNIV_HOTBACKUP
2557
 
        /* Protect the seek / read operation with a mutex */
2558
 
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2559
 
 
2560
 
        os_mutex_enter(os_file_seek_mutexes[i]);
2561
 
#endif /* !UNIV_HOTBACKUP */
2562
 
 
2563
 
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2564
 
 
2565
 
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2566
 
 
2567
 
#ifndef UNIV_HOTBACKUP
2568
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2569
 
#endif /* !UNIV_HOTBACKUP */
2570
 
 
2571
 
                os_mutex_enter(os_file_count_mutex);
2572
 
                os_n_pending_reads--;
2573
 
                os_mutex_exit(os_file_count_mutex);
2574
 
 
2575
 
                goto error_handling;
2576
 
        }
2577
 
 
2578
 
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2579
 
 
2580
 
#ifndef UNIV_HOTBACKUP
2581
 
        os_mutex_exit(os_file_seek_mutexes[i]);
2582
 
#endif /* !UNIV_HOTBACKUP */
2583
 
 
2584
 
        os_mutex_enter(os_file_count_mutex);
2585
 
        os_n_pending_reads--;
2586
 
        os_mutex_exit(os_file_count_mutex);
2587
 
 
2588
 
        if (ret && len == n) {
2589
 
                return(TRUE);
2590
 
        }
2591
 
#else /* __WIN__ */
2592
 
        ibool   retry;
2593
 
        ssize_t ret;
2594
 
 
2595
 
        os_bytes_read_since_printout += n;
2596
 
 
2597
 
try_again:
2598
 
        ret = os_file_pread(file, buf, n, offset, offset_high);
2599
 
 
2600
 
        if ((ulint)ret == n) {
2601
 
 
2602
 
                return(TRUE);
2603
 
        }
2604
 
#endif /* __WIN__ */
2605
 
#ifdef __WIN__
2606
 
error_handling:
2607
 
#endif
2608
 
        retry = os_file_handle_error_no_exit(NULL, "read");
2609
 
 
2610
 
        if (retry) {
2611
 
                goto try_again;
2612
 
        }
2613
 
 
2614
 
        return(FALSE);
2615
 
}
2616
 
 
2617
 
/*******************************************************************//**
2618
 
Rewind file to its start, read at most size - 1 bytes from it to str, and
2619
 
NUL-terminate str. All errors are silently ignored. This function is
2620
 
mostly meant to be used with temporary files. */
2621
 
UNIV_INTERN
2622
 
void
2623
 
os_file_read_string(
2624
 
/*================*/
2625
 
        FILE*   file,   /*!< in: file to read from */
2626
 
        char*   str,    /*!< in: buffer where to read */
2627
 
        ulint   size)   /*!< in: size of buffer */
2628
 
{
2629
 
        size_t  flen;
2630
 
 
2631
 
        if (size == 0) {
2632
 
                return;
2633
 
        }
2634
 
 
2635
 
        rewind(file);
2636
 
        flen = fread(str, 1, size - 1, file);
2637
 
        str[flen] = '\0';
2638
 
}
2639
 
 
2640
 
/*******************************************************************//**
2641
 
NOTE! Use the corresponding macro os_file_write(), not directly
2642
 
this function!
2643
 
Requests a synchronous write operation.
2644
 
@return TRUE if request was successful, FALSE if fail */
2645
 
UNIV_INTERN
2646
 
ibool
2647
 
os_file_write_func(
2648
 
/*===============*/
2649
 
        const char*     name,   /*!< in: name of the file or path as a
2650
 
                                null-terminated string */
2651
 
        os_file_t       file,   /*!< in: handle to a file */
2652
 
        const void*     buf,    /*!< in: buffer from which to write */
2653
 
        ulint           offset, /*!< in: least significant 32 bits of file
2654
 
                                offset where to write */
2655
 
        ulint           offset_high, /*!< in: most significant 32 bits of
2656
 
                                offset */
2657
 
        ulint           n)      /*!< in: number of bytes to write */
2658
 
{
2659
 
#ifdef __WIN__
2660
 
        BOOL            ret;
2661
 
        DWORD           len;
2662
 
        DWORD           ret2;
2663
 
        DWORD           low;
2664
 
        DWORD           high;
2665
 
        ulint           n_retries       = 0;
2666
 
        ulint           err;
2667
 
#ifndef UNIV_HOTBACKUP
2668
 
        ulint           i;
2669
 
#endif /* !UNIV_HOTBACKUP */
2670
 
 
2671
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2672
 
        no more than 32 bits. */
2673
 
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2674
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2675
 
 
2676
 
        os_n_file_writes++;
2677
 
 
2678
 
        ut_ad(file);
2679
 
        ut_ad(buf);
2680
 
        ut_ad(n > 0);
2681
 
retry:
2682
 
        low = (DWORD) offset;
2683
 
        high = (DWORD) offset_high;
2684
 
 
2685
 
        os_mutex_enter(os_file_count_mutex);
2686
 
        os_n_pending_writes++;
2687
 
        os_mutex_exit(os_file_count_mutex);
2688
 
 
2689
 
#ifndef UNIV_HOTBACKUP
2690
 
        /* Protect the seek / write operation with a mutex */
2691
 
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2692
 
 
2693
 
        os_mutex_enter(os_file_seek_mutexes[i]);
2694
 
#endif /* !UNIV_HOTBACKUP */
2695
 
 
2696
 
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2697
 
 
2698
 
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2699
 
 
2700
 
#ifndef UNIV_HOTBACKUP
2701
 
                os_mutex_exit(os_file_seek_mutexes[i]);
2702
 
#endif /* !UNIV_HOTBACKUP */
2703
 
 
2704
 
                os_mutex_enter(os_file_count_mutex);
2705
 
                os_n_pending_writes--;
2706
 
                os_mutex_exit(os_file_count_mutex);
2707
 
 
2708
 
                ut_print_timestamp(stderr);
2709
 
 
2710
 
                fprintf(stderr,
2711
 
                        "  InnoDB: Error: File pointer positioning to"
2712
 
                        " file %s failed at\n"
2713
 
                        "InnoDB: offset %lu %lu. Operating system"
2714
 
                        " error number %lu.\n"
2715
 
                        "InnoDB: Some operating system error numbers"
2716
 
                        " are described at\n"
2717
 
                        "InnoDB: "
2718
 
                        REFMAN "operating-system-error-codes.html\n",
2719
 
                        name, (ulong) offset_high, (ulong) offset,
2720
 
                        (ulong) GetLastError());
2721
 
 
2722
 
                return(FALSE);
2723
 
        }
2724
 
 
2725
 
        ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
2726
 
 
2727
 
        /* Always do fsync to reduce the probability that when the OS crashes,
2728
 
        a database page is only partially physically written to disk. */
2729
 
 
2730
 
# ifdef UNIV_DO_FLUSH
2731
 
        if (!os_do_not_call_flush_at_each_write) {
2732
 
                ut_a(TRUE == os_file_flush(file));
2733
 
        }
2734
 
# endif /* UNIV_DO_FLUSH */
2735
 
 
2736
 
#ifndef UNIV_HOTBACKUP
2737
 
        os_mutex_exit(os_file_seek_mutexes[i]);
2738
 
#endif /* !UNIV_HOTBACKUP */
2739
 
 
2740
 
        os_mutex_enter(os_file_count_mutex);
2741
 
        os_n_pending_writes--;
2742
 
        os_mutex_exit(os_file_count_mutex);
2743
 
 
2744
 
        if (ret && len == n) {
2745
 
 
2746
 
                return(TRUE);
2747
 
        }
2748
 
 
2749
 
        /* If some background file system backup tool is running, then, at
2750
 
        least in Windows 2000, we may get here a specific error. Let us
2751
 
        retry the operation 100 times, with 1 second waits. */
2752
 
 
2753
 
        if (GetLastError() == ERROR_LOCK_VIOLATION && n_retries < 100) {
2754
 
 
2755
 
                os_thread_sleep(1000000);
2756
 
 
2757
 
                n_retries++;
2758
 
 
2759
 
                goto retry;
2760
 
        }
2761
 
 
2762
 
        if (!os_has_said_disk_full) {
2763
 
 
2764
 
                err = (ulint)GetLastError();
2765
 
 
2766
 
                ut_print_timestamp(stderr);
2767
 
 
2768
 
                fprintf(stderr,
2769
 
                        "  InnoDB: Error: Write to file %s failed"
2770
 
                        " at offset %lu %lu.\n"
2771
 
                        "InnoDB: %lu bytes should have been written,"
2772
 
                        " only %lu were written.\n"
2773
 
                        "InnoDB: Operating system error number %lu.\n"
2774
 
                        "InnoDB: Check that your OS and file system"
2775
 
                        " support files of this size.\n"
2776
 
                        "InnoDB: Check also that the disk is not full"
2777
 
                        " or a disk quota exceeded.\n",
2778
 
                        name, (ulong) offset_high, (ulong) offset,
2779
 
                        (ulong) n, (ulong) len, (ulong) err);
2780
 
 
2781
 
                if (strerror((int)err) != NULL) {
2782
 
                        fprintf(stderr,
2783
 
                                "InnoDB: Error number %lu means '%s'.\n",
2784
 
                                (ulong) err, strerror((int)err));
2785
 
                }
2786
 
 
2787
 
                fprintf(stderr,
2788
 
                        "InnoDB: Some operating system error numbers"
2789
 
                        " are described at\n"
2790
 
                        "InnoDB: "
2791
 
                        REFMAN "operating-system-error-codes.html\n");
2792
 
 
2793
 
                os_has_said_disk_full = TRUE;
2794
 
        }
2795
 
 
2796
 
        return(FALSE);
2797
 
#else
2798
 
        ssize_t ret;
2799
 
 
2800
 
        ret = os_file_pwrite(file, buf, n, offset, offset_high);
2801
 
 
2802
 
        if ((ulint)ret == n) {
2803
 
 
2804
 
                return(TRUE);
2805
 
        }
2806
 
 
2807
 
        if (!os_has_said_disk_full) {
2808
 
 
2809
 
                ut_print_timestamp(stderr);
2810
 
 
2811
 
                fprintf(stderr,
2812
 
                        "  InnoDB: Error: Write to file %s failed"
2813
 
                        " at offset %lu %lu.\n"
2814
 
                        "InnoDB: %lu bytes should have been written,"
2815
 
                        " only %ld were written.\n"
2816
 
                        "InnoDB: Operating system error number %lu.\n"
2817
 
                        "InnoDB: Check that your OS and file system"
2818
 
                        " support files of this size.\n"
2819
 
                        "InnoDB: Check also that the disk is not full"
2820
 
                        " or a disk quota exceeded.\n",
2821
 
                        name, offset_high, offset, n, (long int)ret,
2822
 
                        (ulint)errno);
2823
 
                if (strerror(errno) != NULL) {
2824
 
                        fprintf(stderr,
2825
 
                                "InnoDB: Error number %lu means '%s'.\n",
2826
 
                                (ulint)errno, strerror(errno));
2827
 
                }
2828
 
 
2829
 
                fprintf(stderr,
2830
 
                        "InnoDB: Some operating system error numbers"
2831
 
                        " are described at\n"
2832
 
                        "InnoDB: "
2833
 
                        REFMAN "operating-system-error-codes.html\n");
2834
 
 
2835
 
                os_has_said_disk_full = TRUE;
2836
 
        }
2837
 
 
2838
 
        return(FALSE);
2839
 
#endif
2840
 
}
2841
 
 
2842
 
/*******************************************************************//**
2843
 
Check the existence and type of the given file.
2844
 
@return TRUE if call succeeded */
2845
 
UNIV_INTERN
2846
 
ibool
2847
 
os_file_status(
2848
 
/*===========*/
2849
 
        const char*     path,   /*!< in:        pathname of the file */
2850
 
        ibool*          exists, /*!< out: TRUE if file exists */
2851
 
        os_file_type_t* type)   /*!< out: type of the file (if it exists) */
2852
 
{
2853
 
#ifdef __WIN__
2854
 
        int             ret;
2855
 
        struct _stat    statinfo;
2856
 
 
2857
 
        ret = _stat(path, &statinfo);
2858
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2859
 
                /* file does not exist */
2860
 
                *exists = FALSE;
2861
 
                return(TRUE);
2862
 
        } else if (ret) {
2863
 
                /* file exists, but stat call failed */
2864
 
 
2865
 
                os_file_handle_error_no_exit(path, "stat");
2866
 
 
2867
 
                return(FALSE);
2868
 
        }
2869
 
 
2870
 
        if (_S_IFDIR & statinfo.st_mode) {
2871
 
                *type = OS_FILE_TYPE_DIR;
2872
 
        } else if (_S_IFREG & statinfo.st_mode) {
2873
 
                *type = OS_FILE_TYPE_FILE;
2874
 
        } else {
2875
 
                *type = OS_FILE_TYPE_UNKNOWN;
2876
 
        }
2877
 
 
2878
 
        *exists = TRUE;
2879
 
 
2880
 
        return(TRUE);
2881
 
#else
2882
 
        int             ret;
2883
 
        struct stat     statinfo;
2884
 
 
2885
 
        ret = stat(path, &statinfo);
2886
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2887
 
                /* file does not exist */
2888
 
                *exists = FALSE;
2889
 
                return(TRUE);
2890
 
        } else if (ret) {
2891
 
                /* file exists, but stat call failed */
2892
 
 
2893
 
                os_file_handle_error_no_exit(path, "stat");
2894
 
 
2895
 
                return(FALSE);
2896
 
        }
2897
 
 
2898
 
        if (S_ISDIR(statinfo.st_mode)) {
2899
 
                *type = OS_FILE_TYPE_DIR;
2900
 
        } else if (S_ISLNK(statinfo.st_mode)) {
2901
 
                *type = OS_FILE_TYPE_LINK;
2902
 
        } else if (S_ISREG(statinfo.st_mode)) {
2903
 
                *type = OS_FILE_TYPE_FILE;
2904
 
        } else {
2905
 
                *type = OS_FILE_TYPE_UNKNOWN;
2906
 
        }
2907
 
 
2908
 
        *exists = TRUE;
2909
 
 
2910
 
        return(TRUE);
2911
 
#endif
2912
 
}
2913
 
 
2914
 
/*******************************************************************//**
2915
 
This function returns information about the specified file
2916
 
@return TRUE if stat information found */
2917
 
UNIV_INTERN
2918
 
ibool
2919
 
os_file_get_status(
2920
 
/*===============*/
2921
 
        const char*     path,           /*!< in:        pathname of the file */
2922
 
        os_file_stat_t* stat_info)      /*!< information of a file in a
2923
 
                                        directory */
2924
 
{
2925
 
#ifdef __WIN__
2926
 
        int             ret;
2927
 
        struct _stat    statinfo;
2928
 
 
2929
 
        ret = _stat(path, &statinfo);
2930
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2931
 
                /* file does not exist */
2932
 
 
2933
 
                return(FALSE);
2934
 
        } else if (ret) {
2935
 
                /* file exists, but stat call failed */
2936
 
 
2937
 
                os_file_handle_error_no_exit(path, "stat");
2938
 
 
2939
 
                return(FALSE);
2940
 
        }
2941
 
        if (_S_IFDIR & statinfo.st_mode) {
2942
 
                stat_info->type = OS_FILE_TYPE_DIR;
2943
 
        } else if (_S_IFREG & statinfo.st_mode) {
2944
 
                stat_info->type = OS_FILE_TYPE_FILE;
2945
 
        } else {
2946
 
                stat_info->type = OS_FILE_TYPE_UNKNOWN;
2947
 
        }
2948
 
 
2949
 
        stat_info->ctime = statinfo.st_ctime;
2950
 
        stat_info->atime = statinfo.st_atime;
2951
 
        stat_info->mtime = statinfo.st_mtime;
2952
 
        stat_info->size  = statinfo.st_size;
2953
 
 
2954
 
        return(TRUE);
2955
 
#else
2956
 
        int             ret;
2957
 
        struct stat     statinfo;
2958
 
 
2959
 
        ret = stat(path, &statinfo);
2960
 
 
2961
 
        if (ret && (errno == ENOENT || errno == ENOTDIR)) {
2962
 
                /* file does not exist */
2963
 
 
2964
 
                return(FALSE);
2965
 
        } else if (ret) {
2966
 
                /* file exists, but stat call failed */
2967
 
 
2968
 
                os_file_handle_error_no_exit(path, "stat");
2969
 
 
2970
 
                return(FALSE);
2971
 
        }
2972
 
 
2973
 
        if (S_ISDIR(statinfo.st_mode)) {
2974
 
                stat_info->type = OS_FILE_TYPE_DIR;
2975
 
        } else if (S_ISLNK(statinfo.st_mode)) {
2976
 
                stat_info->type = OS_FILE_TYPE_LINK;
2977
 
        } else if (S_ISREG(statinfo.st_mode)) {
2978
 
                stat_info->type = OS_FILE_TYPE_FILE;
2979
 
        } else {
2980
 
                stat_info->type = OS_FILE_TYPE_UNKNOWN;
2981
 
        }
2982
 
 
2983
 
        stat_info->ctime = statinfo.st_ctime;
2984
 
        stat_info->atime = statinfo.st_atime;
2985
 
        stat_info->mtime = statinfo.st_mtime;
2986
 
        stat_info->size  = statinfo.st_size;
2987
 
 
2988
 
        return(TRUE);
2989
 
#endif
2990
 
}
2991
 
 
2992
 
/* path name separator character */
2993
 
#ifdef __WIN__
2994
 
#  define OS_FILE_PATH_SEPARATOR        '\\'
2995
 
#else
2996
 
#  define OS_FILE_PATH_SEPARATOR        '/'
2997
 
#endif
2998
 
 
2999
 
/****************************************************************//**
3000
 
The function os_file_dirname returns a directory component of a
3001
 
null-terminated pathname string.  In the usual case, dirname returns
3002
 
the string up to, but not including, the final '/', and basename
3003
 
is the component following the final '/'.  Trailing '/' charac�
3004
 
ters are not counted as part of the pathname.
3005
 
 
3006
 
If path does not contain a slash, dirname returns the string ".".
3007
 
 
3008
 
Concatenating the string returned by dirname, a "/", and the basename
3009
 
yields a complete pathname.
3010
 
 
3011
 
The return value is  a copy of the directory component of the pathname.
3012
 
The copy is allocated from heap. It is the caller responsibility
3013
 
to free it after it is no longer needed.
3014
 
 
3015
 
The following list of examples (taken from SUSv2) shows the strings
3016
 
returned by dirname and basename for different paths:
3017
 
 
3018
 
       path           dirname        basename
3019
 
       "/usr/lib"     "/usr"         "lib"
3020
 
       "/usr/"        "/"            "usr"
3021
 
       "usr"          "."            "usr"
3022
 
       "/"            "/"            "/"
3023
 
       "."            "."            "."
3024
 
       ".."           "."            ".."
3025
 
 
3026
 
@return own: directory component of the pathname */
3027
 
UNIV_INTERN
3028
 
char*
3029
 
os_file_dirname(
3030
 
/*============*/
3031
 
        const char*     path)   /*!< in: pathname */
3032
 
{
3033
 
        /* Find the offset of the last slash */
3034
 
        const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR);
3035
 
        if (!last_slash) {
3036
 
                /* No slash in the path, return "." */
3037
 
 
3038
 
                return(mem_strdup("."));
3039
 
        }
3040
 
 
3041
 
        /* Ok, there is a slash */
3042
 
 
3043
 
        if (last_slash == path) {
3044
 
                /* last slash is the first char of the path */
3045
 
 
3046
 
                return(mem_strdup("/"));
3047
 
        }
3048
 
 
3049
 
        /* Non-trivial directory component */
3050
 
 
3051
 
        return(mem_strdupl(path, last_slash - path));
3052
 
}
3053
 
 
3054
 
/****************************************************************//**
3055
 
Creates all missing subdirectories along the given path.
3056
 
@return TRUE if call succeeded FALSE otherwise */
3057
 
UNIV_INTERN
3058
 
ibool
3059
 
os_file_create_subdirs_if_needed(
3060
 
/*=============================*/
3061
 
        const char*     path)   /*!< in: path name */
3062
 
{
3063
 
        char*           subdir;
3064
 
        ibool           success, subdir_exists;
3065
 
        os_file_type_t  type;
3066
 
 
3067
 
        subdir = os_file_dirname(path);
3068
 
        if (strlen(subdir) == 1
3069
 
            && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) {
3070
 
                /* subdir is root or cwd, nothing to do */
3071
 
                mem_free(subdir);
3072
 
 
3073
 
                return(TRUE);
3074
 
        }
3075
 
 
3076
 
        /* Test if subdir exists */
3077
 
        success = os_file_status(subdir, &subdir_exists, &type);
3078
 
        if (success && !subdir_exists) {
3079
 
                /* subdir does not exist, create it */
3080
 
                success = os_file_create_subdirs_if_needed(subdir);
3081
 
                if (!success) {
3082
 
                        mem_free(subdir);
3083
 
 
3084
 
                        return(FALSE);
3085
 
                }
3086
 
                success = os_file_create_directory(subdir, FALSE);
3087
 
        }
3088
 
 
3089
 
        mem_free(subdir);
3090
 
 
3091
 
        return(success);
3092
 
}
3093
 
 
3094
 
#ifndef UNIV_HOTBACKUP
3095
 
/****************************************************************//**
3096
 
Returns a pointer to the nth slot in the aio array.
3097
 
@return pointer to slot */
3098
 
static
3099
 
os_aio_slot_t*
3100
 
os_aio_array_get_nth_slot(
3101
 
/*======================*/
3102
 
        os_aio_array_t*         array,  /*!< in: aio array */
3103
 
        ulint                   index)  /*!< in: index of the slot */
3104
 
{
3105
 
        ut_a(index < array->n_slots);
3106
 
 
3107
 
        return((array->slots) + index);
3108
 
}
3109
 
 
3110
 
#if defined(LINUX_NATIVE_AIO)
3111
 
/******************************************************************//**
3112
 
Creates an io_context for native linux AIO.
3113
 
@return TRUE on success. */
3114
 
static
3115
 
ibool
3116
 
os_aio_linux_create_io_ctx(
3117
 
/*=======================*/
3118
 
        ulint           max_events,     /*!< in: number of events. */
3119
 
        io_context_t*   io_ctx)         /*!< out: io_ctx to initialize. */
3120
 
{
3121
 
        int     ret;
3122
 
        ulint   retries = 0;
3123
 
 
3124
 
retry:
3125
 
        memset(io_ctx, 0x0, sizeof(*io_ctx));
3126
 
 
3127
 
        /* Initialize the io_ctx. Tell it how many pending
3128
 
        IO requests this context will handle. */
3129
 
 
3130
 
        ret = io_setup(max_events, io_ctx);
3131
 
        if (ret == 0) {
3132
 
#if defined(UNIV_AIO_DEBUG)
3133
 
                fprintf(stderr,
3134
 
                        "InnoDB: Linux native AIO:"
3135
 
                        " initialized io_ctx for segment\n");
3136
 
#endif
3137
 
                /* Success. Return now. */
3138
 
                return(TRUE);
3139
 
        }
3140
 
 
3141
 
        /* If we hit EAGAIN we'll make a few attempts before failing. */
3142
 
 
3143
 
        switch (ret) {
3144
 
        case -EAGAIN:
3145
 
                if (retries == 0) {
3146
 
                        /* First time around. */
3147
 
                        ut_print_timestamp(stderr);
3148
 
                        fprintf(stderr,
3149
 
                                "  InnoDB: Warning: io_setup() failed"
3150
 
                                " with EAGAIN. Will make %d attempts"
3151
 
                                " before giving up.\n",
3152
 
                                OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
3153
 
                }
3154
 
 
3155
 
                if (retries < OS_AIO_IO_SETUP_RETRY_ATTEMPTS) {
3156
 
                        ++retries;
3157
 
                        fprintf(stderr,
3158
 
                                "InnoDB: Warning: io_setup() attempt"
3159
 
                                " %lu failed.\n",
3160
 
                                retries);
3161
 
                        os_thread_sleep(OS_AIO_IO_SETUP_RETRY_SLEEP);
3162
 
                        goto retry;
3163
 
                }
3164
 
 
3165
 
                /* Have tried enough. Better call it a day. */
3166
 
                ut_print_timestamp(stderr);
3167
 
                fprintf(stderr,
3168
 
                        "  InnoDB: Error: io_setup() failed"
3169
 
                        " with EAGAIN after %d attempts.\n",
3170
 
                        OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
3171
 
                break;
3172
 
 
3173
 
        case -ENOSYS:
3174
 
                ut_print_timestamp(stderr);
3175
 
                fprintf(stderr,
3176
 
                        "  InnoDB: Error: Linux Native AIO interface"
3177
 
                        " is not supported on this platform. Please"
3178
 
                        " check your OS documentation and install"
3179
 
                        " appropriate binary of InnoDB.\n");
3180
 
 
3181
 
                break;
3182
 
 
3183
 
        default:
3184
 
                ut_print_timestamp(stderr);
3185
 
                fprintf(stderr,
3186
 
                        "  InnoDB: Error: Linux Native AIO setup"
3187
 
                        " returned following error[%d]\n", -ret);
3188
 
                break;
3189
 
        }
3190
 
 
3191
 
        fprintf(stderr,
3192
 
                "InnoDB: You can disable Linux Native AIO by"
3193
 
                " setting innodb_native_aio = off in my.cnf\n");
3194
 
        return(FALSE);
3195
 
}
3196
 
#endif /* LINUX_NATIVE_AIO */
3197
 
 
3198
 
/******************************************************************//**
3199
 
Creates an aio wait array. Note that we return NULL in case of failure.
3200
 
We don't care about freeing memory here because we assume that a
3201
 
failure will result in server refusing to start up.
3202
 
@return own: aio array, NULL on failure */
3203
 
static
3204
 
os_aio_array_t*
3205
 
os_aio_array_create(
3206
 
/*================*/
3207
 
        ulint   n,              /*!< in: maximum number of pending aio
3208
 
                                operations allowed; n must be
3209
 
                                divisible by n_segments */
3210
 
        ulint   n_segments)     /*!< in: number of segments in the aio array */
3211
 
{
3212
 
        os_aio_array_t* array;
3213
 
        ulint           i;
3214
 
        os_aio_slot_t*  slot;
3215
 
#ifdef WIN_ASYNC_IO
3216
 
        OVERLAPPED*     over;
3217
 
#elif defined(LINUX_NATIVE_AIO)
3218
 
        struct io_event*        aio_event = NULL;
3219
 
#endif
3220
 
        ut_a(n > 0);
3221
 
        ut_a(n_segments > 0);
3222
 
 
3223
 
        array = static_cast<os_aio_array_t *>(ut_malloc(sizeof(os_aio_array_t)));
3224
 
 
3225
 
        array->mutex            = os_mutex_create();
3226
 
        array->not_full         = os_event_create(NULL);
3227
 
        array->is_empty         = os_event_create(NULL);
3228
 
 
3229
 
        os_event_set(array->is_empty);
3230
 
 
3231
 
        array->n_slots          = n;
3232
 
        array->n_segments       = n_segments;
3233
 
        array->n_reserved       = 0;
3234
 
        array->cur_seg          = 0;
3235
 
        array->slots            = static_cast<os_aio_slot_t *>(ut_malloc(n * sizeof(os_aio_slot_t)));
3236
 
#ifdef __WIN__
3237
 
        array->handles          = ut_malloc(n * sizeof(HANDLE));
3238
 
#endif
3239
 
 
3240
 
#if defined(LINUX_NATIVE_AIO)
3241
 
        array->aio_ctx = NULL;
3242
 
        array->aio_events = NULL;
3243
 
 
3244
 
        /* If we are not using native aio interface then skip this
3245
 
        part of initialization. */
3246
 
        if (!srv_use_native_aio) {
3247
 
                goto skip_native_aio;
3248
 
        }
3249
 
 
3250
 
        /* Initialize the io_context array. One io_context
3251
 
        per segment in the array. */
3252
 
 
3253
 
        array->aio_ctx = (io_context**) ut_malloc(n_segments *
3254
 
                                   sizeof(*array->aio_ctx));
3255
 
        for (i = 0; i < n_segments; ++i) {
3256
 
                if (!os_aio_linux_create_io_ctx(n/n_segments,
3257
 
                                           &array->aio_ctx[i])) {
3258
 
                        /* If something bad happened during aio setup
3259
 
                        we should call it a day and return right away.
3260
 
                        We don't care about any leaks because a failure
3261
 
                        to initialize the io subsystem means that the
3262
 
                        server (or atleast the innodb storage engine)
3263
 
                        is not going to startup. */
3264
 
                        return(NULL);
3265
 
                }
3266
 
        }
3267
 
 
3268
 
        /* Initialize the event array. One event per slot. */
3269
 
        aio_event = (io_event*) ut_malloc(n * sizeof(io_event));
3270
 
        memset(aio_event, 0x0, sizeof(io_event) * n);
3271
 
        array->aio_events = aio_event;
3272
 
 
3273
 
skip_native_aio:
3274
 
#endif /* LINUX_NATIVE_AIO */
3275
 
        for (i = 0; i < n; i++) {
3276
 
                slot = os_aio_array_get_nth_slot(array, i);
3277
 
 
3278
 
                slot->pos = i;
3279
 
                slot->reserved = FALSE;
3280
 
#ifdef WIN_ASYNC_IO
3281
 
                slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
3282
 
 
3283
 
                over = &(slot->control);
3284
 
 
3285
 
                over->hEvent = slot->handle;
3286
 
 
3287
 
                *((array->handles) + i) = over->hEvent;
3288
 
 
3289
 
#elif defined(LINUX_NATIVE_AIO)
3290
 
 
3291
 
                memset(&slot->control, 0x0, sizeof(slot->control));
3292
 
                slot->n_bytes = 0;
3293
 
                slot->ret = 0;
3294
 
#endif
3295
 
        }
3296
 
 
3297
 
        return(array);
3298
 
}
3299
 
 
3300
 
/************************************************************************//**
3301
 
Frees an aio wait array. */
3302
 
static
3303
 
void
3304
 
os_aio_array_free(
3305
 
/*==============*/
3306
 
        os_aio_array_t* array)  /*!< in, own: array to free */
3307
 
{
3308
 
#ifdef WIN_ASYNC_IO
3309
 
        ulint   i;
3310
 
 
3311
 
        for (i = 0; i < array->n_slots; i++) {
3312
 
                os_aio_slot_t*  slot = os_aio_array_get_nth_slot(array, i);
3313
 
                CloseHandle(slot->handle);
3314
 
        }
3315
 
#endif /* WIN_ASYNC_IO */
3316
 
 
3317
 
#ifdef __WIN__
3318
 
        ut_free(array->handles);
3319
 
#endif /* __WIN__ */
3320
 
        os_mutex_free(array->mutex);
3321
 
        os_event_free(array->not_full);
3322
 
        os_event_free(array->is_empty);
3323
 
 
3324
 
#if defined(LINUX_NATIVE_AIO)
3325
 
        if (srv_use_native_aio) {
3326
 
                ut_free(array->aio_events);
3327
 
                ut_free(array->aio_ctx);
3328
 
        }
3329
 
#endif /* LINUX_NATIVE_AIO */
3330
 
 
3331
 
        ut_free(array->slots);
3332
 
        ut_free(array);
3333
 
}
3334
 
 
3335
 
/***********************************************************************
3336
 
Initializes the asynchronous io system. Creates one array each for ibuf
3337
 
and log i/o. Also creates one array each for read and write where each
3338
 
array is divided logically into n_read_segs and n_write_segs
3339
 
respectively. The caller must create an i/o handler thread for each
3340
 
segment in these arrays. This function also creates the sync array.
3341
 
No i/o handler thread needs to be created for that */
3342
 
UNIV_INTERN
3343
 
ibool
3344
 
os_aio_init(
3345
 
/*========*/
3346
 
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3347
 
                                operations allowed per segment */
3348
 
        ulint   n_read_segs,    /*<! in: number of reader threads */
3349
 
        ulint   n_write_segs,   /*<! in: number of writer threads */
3350
 
        ulint   n_slots_sync)   /*<! in: number of slots in the sync aio
3351
 
                                array */
3352
 
{
3353
 
        ulint   i;
3354
 
        ulint   n_segments = 2 + n_read_segs + n_write_segs;
3355
 
 
3356
 
        ut_ad(n_segments >= 4);
3357
 
 
3358
 
        os_io_init_simple();
3359
 
 
3360
 
        for (i = 0; i < n_segments; i++) {
3361
 
                srv_set_io_thread_op_info(i, "not started yet");
3362
 
        }
3363
 
 
3364
 
 
3365
 
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3366
 
 
3367
 
        os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
3368
 
        if (os_aio_ibuf_array == NULL) {
3369
 
                goto err_exit;
3370
 
        }
3371
 
 
3372
 
        srv_io_thread_function[0] = "insert buffer thread";
3373
 
 
3374
 
        os_aio_log_array = os_aio_array_create(n_per_seg, 1);
3375
 
        if (os_aio_log_array == NULL) {
3376
 
                goto err_exit;
3377
 
        }
3378
 
 
3379
 
        srv_io_thread_function[1] = "log thread";
3380
 
 
3381
 
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3382
 
                                                n_read_segs);
3383
 
        if (os_aio_read_array == NULL) {
3384
 
                goto err_exit;
3385
 
        }
3386
 
 
3387
 
        for (i = 2; i < 2 + n_read_segs; i++) {
3388
 
                ut_a(i < SRV_MAX_N_IO_THREADS);
3389
 
                srv_io_thread_function[i] = "read thread";
3390
 
        }
3391
 
 
3392
 
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3393
 
                                                 n_write_segs);
3394
 
        if (os_aio_write_array == NULL) {
3395
 
                goto err_exit;
3396
 
        }
3397
 
 
3398
 
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3399
 
                ut_a(i < SRV_MAX_N_IO_THREADS);
3400
 
                srv_io_thread_function[i] = "write thread";
3401
 
        }
3402
 
 
3403
 
        os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
3404
 
        if (os_aio_sync_array == NULL) {
3405
 
                goto err_exit;
3406
 
        }
3407
 
 
3408
 
 
3409
 
        os_aio_n_segments = n_segments;
3410
 
 
3411
 
        os_aio_validate();
3412
 
 
3413
 
        os_aio_segment_wait_events = static_cast<os_event_t *>(ut_malloc(n_segments * sizeof(void*)));
3414
 
 
3415
 
        for (i = 0; i < n_segments; i++) {
3416
 
                os_aio_segment_wait_events[i] = os_event_create(NULL);
3417
 
        }
3418
 
 
3419
 
        os_last_printout = time(NULL);
3420
 
 
3421
 
        return(TRUE);
3422
 
 
3423
 
err_exit:
3424
 
        return(FALSE);
3425
 
 
3426
 
}
3427
 
 
3428
 
/***********************************************************************
3429
 
Frees the asynchronous io system. */
3430
 
UNIV_INTERN
3431
 
void
3432
 
os_aio_free(void)
3433
 
/*=============*/
3434
 
{
3435
 
        ulint   i;
3436
 
 
3437
 
        os_aio_array_free(os_aio_ibuf_array);
3438
 
        os_aio_ibuf_array = NULL;
3439
 
        os_aio_array_free(os_aio_log_array);
3440
 
        os_aio_log_array = NULL;
3441
 
        os_aio_array_free(os_aio_read_array);
3442
 
        os_aio_read_array = NULL;
3443
 
        os_aio_array_free(os_aio_write_array);
3444
 
        os_aio_write_array = NULL;
3445
 
        os_aio_array_free(os_aio_sync_array);
3446
 
        os_aio_sync_array = NULL;
3447
 
 
3448
 
        for (i = 0; i < os_aio_n_segments; i++) {
3449
 
                os_event_free(os_aio_segment_wait_events[i]);
3450
 
        }
3451
 
 
3452
 
        ut_free(os_aio_segment_wait_events);
3453
 
        os_aio_segment_wait_events = 0;
3454
 
        os_aio_n_segments = 0;
3455
 
}
3456
 
 
3457
 
#ifdef WIN_ASYNC_IO
3458
 
/************************************************************************//**
3459
 
Wakes up all async i/o threads in the array in Windows async i/o at
3460
 
shutdown. */
3461
 
static
3462
 
void
3463
 
os_aio_array_wake_win_aio_at_shutdown(
3464
 
/*==================================*/
3465
 
        os_aio_array_t* array)  /*!< in: aio array */
3466
 
{
3467
 
        ulint   i;
3468
 
 
3469
 
        for (i = 0; i < array->n_slots; i++) {
3470
 
 
3471
 
                SetEvent((array->slots + i)->handle);
3472
 
        }
3473
 
}
3474
 
#endif
3475
 
 
3476
 
/************************************************************************//**
3477
 
Wakes up all async i/o threads so that they know to exit themselves in
3478
 
shutdown. */
3479
 
UNIV_INTERN
3480
 
void
3481
 
os_aio_wake_all_threads_at_shutdown(void)
3482
 
/*=====================================*/
3483
 
{
3484
 
        ulint   i;
3485
 
 
3486
 
#ifdef WIN_ASYNC_IO
3487
 
        /* This code wakes up all ai/o threads in Windows native aio */
3488
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
3489
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3490
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3491
 
        os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
3492
 
 
3493
 
#elif defined(LINUX_NATIVE_AIO)
3494
 
 
3495
 
        /* When using native AIO interface the io helper threads
3496
 
        wait on io_getevents with a timeout value of 500ms. At
3497
 
        each wake up these threads check the server status.
3498
 
        No need to do anything to wake them up. */
3499
 
 
3500
 
        if (srv_use_native_aio) {
3501
 
                return;
3502
 
        }
3503
 
        /* Fall through to simulated AIO handler wakeup if we are
3504
 
        not using native AIO. */
3505
 
#endif
3506
 
        /* This loop wakes up all simulated ai/o threads */
3507
 
 
3508
 
        for (i = 0; i < os_aio_n_segments; i++) {
3509
 
 
3510
 
                os_event_set(os_aio_segment_wait_events[i]);
3511
 
        }
3512
 
}
3513
 
 
3514
 
/************************************************************************//**
3515
 
Waits until there are no pending writes in os_aio_write_array. There can
3516
 
be other, synchronous, pending writes. */
3517
 
UNIV_INTERN
3518
 
void
3519
 
os_aio_wait_until_no_pending_writes(void)
3520
 
/*=====================================*/
3521
 
{
3522
 
        os_event_wait(os_aio_write_array->is_empty);
3523
 
}
3524
 
 
3525
 
/**********************************************************************//**
3526
 
Calculates segment number for a slot.
3527
 
@return segment number (which is the number used by, for example,
3528
 
i/o-handler threads) */
3529
 
static
3530
 
ulint
3531
 
os_aio_get_segment_no_from_slot(
3532
 
/*============================*/
3533
 
        os_aio_array_t* array,  /*!< in: aio wait array */
3534
 
        os_aio_slot_t*  slot)   /*!< in: slot in this array */
3535
 
{
3536
 
        ulint   segment;
3537
 
        ulint   seg_len;
3538
 
 
3539
 
        if (array == os_aio_ibuf_array) {
3540
 
                segment = 0;
3541
 
 
3542
 
        } else if (array == os_aio_log_array) {
3543
 
                segment = 1;
3544
 
 
3545
 
        } else if (array == os_aio_read_array) {
3546
 
                seg_len = os_aio_read_array->n_slots
3547
 
                        / os_aio_read_array->n_segments;
3548
 
 
3549
 
                segment = 2 + slot->pos / seg_len;
3550
 
        } else {
3551
 
                ut_a(array == os_aio_write_array);
3552
 
                seg_len = os_aio_write_array->n_slots
3553
 
                        / os_aio_write_array->n_segments;
3554
 
 
3555
 
                segment = os_aio_read_array->n_segments + 2
3556
 
                        + slot->pos / seg_len;
3557
 
        }
3558
 
 
3559
 
        return(segment);
3560
 
}
3561
 
 
3562
 
/**********************************************************************//**
3563
 
Calculates local segment number and aio array from global segment number.
3564
 
@return local segment number within the aio array */
3565
 
static
3566
 
ulint
3567
 
os_aio_get_array_and_local_segment(
3568
 
/*===============================*/
3569
 
        os_aio_array_t** array,         /*!< out: aio wait array */
3570
 
        ulint            global_segment)/*!< in: global segment number */
3571
 
{
3572
 
        ulint   segment;
3573
 
 
3574
 
        ut_a(global_segment < os_aio_n_segments);
3575
 
 
3576
 
        if (global_segment == 0) {
3577
 
                *array = os_aio_ibuf_array;
3578
 
                segment = 0;
3579
 
 
3580
 
        } else if (global_segment == 1) {
3581
 
                *array = os_aio_log_array;
3582
 
                segment = 0;
3583
 
 
3584
 
        } else if (global_segment < os_aio_read_array->n_segments + 2) {
3585
 
                *array = os_aio_read_array;
3586
 
 
3587
 
                segment = global_segment - 2;
3588
 
        } else {
3589
 
                *array = os_aio_write_array;
3590
 
 
3591
 
                segment = global_segment - (os_aio_read_array->n_segments + 2);
3592
 
        }
3593
 
 
3594
 
        return(segment);
3595
 
}
3596
 
 
3597
 
/*******************************************************************//**
3598
 
Requests for a slot in the aio array. If no slot is available, waits until
3599
 
not_full-event becomes signaled.
3600
 
@return pointer to slot */
3601
 
static
3602
 
os_aio_slot_t*
3603
 
os_aio_array_reserve_slot(
3604
 
/*======================*/
3605
 
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3606
 
        os_aio_array_t* array,  /*!< in: aio array */
3607
 
        fil_node_t*     message1,/*!< in: message to be passed along with
3608
 
                                the aio operation */
3609
 
        void*           message2,/*!< in: message to be passed along with
3610
 
                                the aio operation */
3611
 
        os_file_t       file,   /*!< in: file handle */
3612
 
        const char*     name,   /*!< in: name of the file or path as a
3613
 
                                null-terminated string */
3614
 
        void*           buf,    /*!< in: buffer where to read or from which
3615
 
                                to write */
3616
 
        ulint           offset, /*!< in: least significant 32 bits of file
3617
 
                                offset */
3618
 
        ulint           offset_high, /*!< in: most significant 32 bits of
3619
 
                                offset */
3620
 
        ulint           len)    /*!< in: length of the block to read or write */
3621
 
{
3622
 
        os_aio_slot_t*  slot = NULL;
3623
 
#ifdef WIN_ASYNC_IO
3624
 
        OVERLAPPED*     control;
3625
 
 
3626
 
#elif defined(LINUX_NATIVE_AIO)
3627
 
 
3628
 
        struct iocb*    iocb;
3629
 
        off_t           aio_offset;
3630
 
 
3631
 
#endif
3632
 
        ulint           i;
3633
 
        ulint           counter;
3634
 
        ulint           slots_per_seg;
3635
 
        ulint           local_seg;
3636
 
 
3637
 
#ifdef WIN_ASYNC_IO
3638
 
        ut_a((len & 0xFFFFFFFFUL) == len);
3639
 
#endif
3640
 
 
3641
 
        /* No need of a mutex. Only reading constant fields */
3642
 
        slots_per_seg = array->n_slots / array->n_segments;
3643
 
 
3644
 
        /* We attempt to keep adjacent blocks in the same local
3645
 
        segment. This can help in merging IO requests when we are
3646
 
        doing simulated AIO */
3647
 
        local_seg = (offset >> (UNIV_PAGE_SIZE_SHIFT + 6))
3648
 
                    % array->n_segments;
3649
 
 
3650
 
loop:
3651
 
        os_mutex_enter(array->mutex);
3652
 
 
3653
 
        if (array->n_reserved == array->n_slots) {
3654
 
                os_mutex_exit(array->mutex);
3655
 
 
3656
 
                if (!srv_use_native_aio) {
3657
 
                        /* If the handler threads are suspended, wake them
3658
 
                        so that we get more slots */
3659
 
 
3660
 
                        os_aio_simulated_wake_handler_threads();
3661
 
                }
3662
 
 
3663
 
                os_event_wait(array->not_full);
3664
 
 
3665
 
                goto loop;
3666
 
        }
3667
 
 
3668
 
        /* We start our search for an available slot from our preferred
3669
 
        local segment and do a full scan of the array. We are
3670
 
        guaranteed to find a slot in full scan. */
3671
 
        for (i = local_seg * slots_per_seg, counter = 0;
3672
 
             counter < array->n_slots; i++, counter++) {
3673
 
 
3674
 
                i %= array->n_slots;
3675
 
                slot = os_aio_array_get_nth_slot(array, i);
3676
 
 
3677
 
                if (slot->reserved == FALSE) {
3678
 
                        goto found;
3679
 
                }
3680
 
        }
3681
 
 
3682
 
        /* We MUST always be able to get hold of a reserved slot. */
3683
 
        ut_error;
3684
 
 
3685
 
found:
3686
 
        ut_a(slot->reserved == FALSE);
3687
 
        array->n_reserved++;
3688
 
 
3689
 
        if (array->n_reserved == 1) {
3690
 
                os_event_reset(array->is_empty);
3691
 
        }
3692
 
 
3693
 
        if (array->n_reserved == array->n_slots) {
3694
 
                os_event_reset(array->not_full);
3695
 
        }
3696
 
 
3697
 
        slot->reserved = TRUE;
3698
 
        slot->reservation_time = time(NULL);
3699
 
        slot->message1 = message1;
3700
 
        slot->message2 = message2;
3701
 
        slot->file     = file;
3702
 
        slot->name     = name;
3703
 
        slot->len      = len;
3704
 
        slot->type     = type;
3705
 
        slot->buf      = static_cast<unsigned char *>(buf);
3706
 
        slot->offset   = offset;
3707
 
        slot->offset_high = offset_high;
3708
 
        slot->io_already_done = FALSE;
3709
 
 
3710
 
#ifdef WIN_ASYNC_IO
3711
 
        control = &(slot->control);
3712
 
        control->Offset = (DWORD)offset;
3713
 
        control->OffsetHigh = (DWORD)offset_high;
3714
 
        ResetEvent(slot->handle);
3715
 
 
3716
 
#elif defined(LINUX_NATIVE_AIO)
3717
 
 
3718
 
        /* If we are not using native AIO skip this part. */
3719
 
        if (!srv_use_native_aio) {
3720
 
                goto skip_native_aio;
3721
 
        }
3722
 
 
3723
 
        /* Check if we are dealing with 64 bit arch.
3724
 
        If not then make sure that offset fits in 32 bits. */
3725
 
        if (sizeof(aio_offset) == 8) {
3726
 
                aio_offset = offset_high;
3727
 
                aio_offset <<= 32;
3728
 
                aio_offset += offset;
3729
 
        } else {
3730
 
                ut_a(offset_high == 0);
3731
 
                aio_offset = offset;
3732
 
        }
3733
 
 
3734
 
        iocb = &slot->control;
3735
 
 
3736
 
        if (type == OS_FILE_READ) {
3737
 
                io_prep_pread(iocb, file, buf, len, aio_offset);
3738
 
        } else {
3739
 
                ut_a(type == OS_FILE_WRITE);
3740
 
                io_prep_pwrite(iocb, file, buf, len, aio_offset);
3741
 
        }
3742
 
 
3743
 
        iocb->data = (void*)slot;
3744
 
        slot->n_bytes = 0;
3745
 
        slot->ret = 0;
3746
 
        /*fprintf(stderr, "Filled up Linux native iocb.\n");*/
3747
 
        
3748
 
 
3749
 
skip_native_aio:
3750
 
#endif /* LINUX_NATIVE_AIO */
3751
 
        os_mutex_exit(array->mutex);
3752
 
 
3753
 
        return(slot);
3754
 
}
3755
 
 
3756
 
/*******************************************************************//**
3757
 
Frees a slot in the aio array. */
3758
 
static
3759
 
void
3760
 
os_aio_array_free_slot(
3761
 
/*===================*/
3762
 
        os_aio_array_t* array,  /*!< in: aio array */
3763
 
        os_aio_slot_t*  slot)   /*!< in: pointer to slot */
3764
 
{
3765
 
        ut_ad(array);
3766
 
        ut_ad(slot);
3767
 
 
3768
 
        os_mutex_enter(array->mutex);
3769
 
 
3770
 
        ut_ad(slot->reserved);
3771
 
 
3772
 
        slot->reserved = FALSE;
3773
 
 
3774
 
        array->n_reserved--;
3775
 
 
3776
 
        if (array->n_reserved == array->n_slots - 1) {
3777
 
                os_event_set(array->not_full);
3778
 
        }
3779
 
 
3780
 
        if (array->n_reserved == 0) {
3781
 
                os_event_set(array->is_empty);
3782
 
        }
3783
 
 
3784
 
#ifdef WIN_ASYNC_IO
3785
 
 
3786
 
        ResetEvent(slot->handle);
3787
 
 
3788
 
#elif defined(LINUX_NATIVE_AIO)
3789
 
 
3790
 
        if (srv_use_native_aio) {
3791
 
                memset(&slot->control, 0x0, sizeof(slot->control));
3792
 
                slot->n_bytes = 0;
3793
 
                slot->ret = 0;
3794
 
                /*fprintf(stderr, "Freed up Linux native slot.\n");*/
3795
 
        } else {
3796
 
                /* These fields should not be used if we are not
3797
 
                using native AIO. */
3798
 
                ut_ad(slot->n_bytes == 0);
3799
 
                ut_ad(slot->ret == 0);
3800
 
        }
3801
 
 
3802
 
#endif
3803
 
        os_mutex_exit(array->mutex);
3804
 
}
3805
 
 
3806
 
/**********************************************************************//**
3807
 
Wakes up a simulated aio i/o-handler thread if it has something to do. */
3808
 
static
3809
 
void
3810
 
os_aio_simulated_wake_handler_thread(
3811
 
/*=================================*/
3812
 
        ulint   global_segment) /*!< in: the number of the segment in the aio
3813
 
                                arrays */
3814
 
{
3815
 
        os_aio_array_t* array;
3816
 
        os_aio_slot_t*  slot;
3817
 
        ulint           segment;
3818
 
        ulint           n;
3819
 
        ulint           i;
3820
 
 
3821
 
        ut_ad(!srv_use_native_aio);
3822
 
 
3823
 
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3824
 
 
3825
 
        n = array->n_slots / array->n_segments;
3826
 
 
3827
 
        /* Look through n slots after the segment * n'th slot */
3828
 
 
3829
 
        os_mutex_enter(array->mutex);
3830
 
 
3831
 
        for (i = 0; i < n; i++) {
3832
 
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
3833
 
 
3834
 
                if (slot->reserved) {
3835
 
                        /* Found an i/o request */
3836
 
 
3837
 
                        break;
3838
 
                }
3839
 
        }
3840
 
 
3841
 
        os_mutex_exit(array->mutex);
3842
 
 
3843
 
        if (i < n) {
3844
 
                os_event_set(os_aio_segment_wait_events[global_segment]);
3845
 
        }
3846
 
}
3847
 
 
3848
 
/**********************************************************************//**
3849
 
Wakes up simulated aio i/o-handler threads if they have something to do. */
3850
 
UNIV_INTERN
3851
 
void
3852
 
os_aio_simulated_wake_handler_threads(void)
3853
 
/*=======================================*/
3854
 
{
3855
 
        ulint   i;
3856
 
 
3857
 
        if (srv_use_native_aio) {
3858
 
                /* We do not use simulated aio: do nothing */
3859
 
 
3860
 
                return;
3861
 
        }
3862
 
 
3863
 
        os_aio_recommend_sleep_for_read_threads = FALSE;
3864
 
 
3865
 
        for (i = 0; i < os_aio_n_segments; i++) {
3866
 
                os_aio_simulated_wake_handler_thread(i);
3867
 
        }
3868
 
}
3869
 
 
3870
 
/**********************************************************************//**
3871
 
This function can be called if one wants to post a batch of reads and
3872
 
prefers an i/o-handler thread to handle them all at once later. You must
3873
 
call os_aio_simulated_wake_handler_threads later to ensure the threads
3874
 
are not left sleeping! */
3875
 
UNIV_INTERN
3876
 
void
3877
 
os_aio_simulated_put_read_threads_to_sleep(void)
3878
 
/*============================================*/
3879
 
{
3880
 
 
3881
 
/* The idea of putting background IO threads to sleep is only for
3882
 
Windows when using simulated AIO. Windows XP seems to schedule
3883
 
background threads too eagerly to allow for coalescing during
3884
 
readahead requests. */
3885
 
#ifdef __WIN__
3886
 
        os_aio_array_t* array;
3887
 
        ulint           g;
3888
 
 
3889
 
        if (srv_use_native_aio) {
3890
 
                /* We do not use simulated aio: do nothing */
3891
 
 
3892
 
                return;
3893
 
        }
3894
 
 
3895
 
        os_aio_recommend_sleep_for_read_threads = TRUE;
3896
 
 
3897
 
        for (g = 0; g < os_aio_n_segments; g++) {
3898
 
                os_aio_get_array_and_local_segment(&array, g);
3899
 
 
3900
 
                if (array == os_aio_read_array) {
3901
 
 
3902
 
                        os_event_reset(os_aio_segment_wait_events[g]);
3903
 
                }
3904
 
        }
3905
 
#endif /* __WIN__ */
3906
 
}
3907
 
 
3908
 
#if defined(LINUX_NATIVE_AIO)
3909
 
/*******************************************************************//**
3910
 
Dispatch an AIO request to the kernel.
3911
 
@return TRUE on success. */
3912
 
static
3913
 
ibool
3914
 
os_aio_linux_dispatch(
3915
 
/*==================*/
3916
 
        os_aio_array_t* array,  /*!< in: io request array. */
3917
 
        os_aio_slot_t*  slot)   /*!< in: an already reserved slot. */
3918
 
{
3919
 
        int             ret;
3920
 
        ulint           io_ctx_index;
3921
 
        struct iocb*    iocb;
3922
 
 
3923
 
        ut_ad(slot != NULL);
3924
 
        ut_ad(array);
3925
 
 
3926
 
        ut_a(slot->reserved);
3927
 
 
3928
 
        /* Find out what we are going to work with.
3929
 
        The iocb struct is directly in the slot.
3930
 
        The io_context is one per segment. */
3931
 
 
3932
 
        iocb = &slot->control;
3933
 
        io_ctx_index = (slot->pos * array->n_segments) / array->n_slots;
3934
 
 
3935
 
        ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb);
3936
 
 
3937
 
#if defined(UNIV_AIO_DEBUG)
3938
 
        fprintf(stderr,
3939
 
                "io_submit[%c] ret[%d]: slot[%p] ctx[%p] seg[%lu]\n",
3940
 
                (slot->type == OS_FILE_WRITE) ? 'w' : 'r', ret, slot,
3941
 
                array->aio_ctx[io_ctx_index], (ulong)io_ctx_index);
3942
 
#endif
3943
 
 
3944
 
        /* io_submit returns number of successfully
3945
 
        queued requests or -errno. */
3946
 
        if (UNIV_UNLIKELY(ret != 1)) {
3947
 
                errno = -ret;
3948
 
                return(FALSE);
3949
 
        }
3950
 
 
3951
 
        return(TRUE);
3952
 
}
3953
 
#endif /* LINUX_NATIVE_AIO */
3954
 
 
3955
 
 
3956
 
/*******************************************************************//**
3957
 
NOTE! Use the corresponding macro os_aio(), not directly this function!
3958
 
Requests an asynchronous i/o operation.
3959
 
@return TRUE if request was queued successfully, FALSE if fail */
3960
 
UNIV_INTERN
3961
 
ibool
3962
 
os_aio_func(
3963
 
/*========*/
3964
 
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3965
 
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3966
 
                                to OS_AIO_SIMULATED_WAKE_LATER: the
3967
 
                                last flag advises this function not to wake
3968
 
                                i/o-handler threads, but the caller will
3969
 
                                do the waking explicitly later, in this
3970
 
                                way the caller can post several requests in
3971
 
                                a batch; NOTE that the batch must not be
3972
 
                                so big that it exhausts the slots in aio
3973
 
                                arrays! NOTE that a simulated batch
3974
 
                                may introduce hidden chances of deadlocks,
3975
 
                                because i/os are not actually handled until
3976
 
                                all have been posted: use with great
3977
 
                                caution! */
3978
 
        const char*     name,   /*!< in: name of the file or path as a
3979
 
                                null-terminated string */
3980
 
        os_file_t       file,   /*!< in: handle to a file */
3981
 
        void*           buf,    /*!< in: buffer where to read or from which
3982
 
                                to write */
3983
 
        ulint           offset, /*!< in: least significant 32 bits of file
3984
 
                                offset where to read or write */
3985
 
        ulint           offset_high, /*!< in: most significant 32 bits of
3986
 
                                offset */
3987
 
        ulint           n,      /*!< in: number of bytes to read or write */
3988
 
        fil_node_t*     message1,/*!< in: message for the aio handler
3989
 
                                (can be used to identify a completed
3990
 
                                aio operation); ignored if mode is
3991
 
                                OS_AIO_SYNC */
3992
 
        void*           message2)/*!< in: message for the aio handler
3993
 
                                (can be used to identify a completed
3994
 
                                aio operation); ignored if mode is
3995
 
                                OS_AIO_SYNC */
3996
 
{
3997
 
        os_aio_array_t* array;
3998
 
        os_aio_slot_t*  slot;
3999
 
#ifdef WIN_ASYNC_IO
4000
 
        ibool           retval;
4001
 
        BOOL            ret             = TRUE;
4002
 
        DWORD           len             = (DWORD) n;
4003
 
        struct fil_node_struct * dummy_mess1;
4004
 
        void*           dummy_mess2;
4005
 
        ulint           dummy_type;
4006
 
#endif /* WIN_ASYNC_IO */
4007
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4008
 
        ibool           retry;
4009
 
#endif
4010
 
        ulint           wake_later;
4011
 
 
4012
 
        ut_ad(file);
4013
 
        ut_ad(buf);
4014
 
        ut_ad(n > 0);
4015
 
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
4016
 
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
4017
 
        ut_ad(os_aio_validate());
4018
 
#ifdef WIN_ASYNC_IO
4019
 
        ut_ad((n & 0xFFFFFFFFUL) == n);
4020
 
#endif
4021
 
 
4022
 
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
4023
 
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
4024
 
 
4025
 
        if (mode == OS_AIO_SYNC
4026
 
#ifdef WIN_ASYNC_IO
4027
 
            && !srv_use_native_aio
4028
 
#endif /* WIN_ASYNC_IO */
4029
 
            ) {
4030
 
                /* This is actually an ordinary synchronous read or write:
4031
 
                no need to use an i/o-handler thread. NOTE that if we use
4032
 
                Windows async i/o, Windows does not allow us to use
4033
 
                ordinary synchronous os_file_read etc. on the same file,
4034
 
                therefore we have built a special mechanism for synchronous
4035
 
                wait in the Windows case. */
4036
 
 
4037
 
                if (type == OS_FILE_READ) {
4038
 
                        return(os_file_read(file, buf, offset,
4039
 
                                            offset_high, n));
4040
 
                }
4041
 
 
4042
 
                ut_a(type == OS_FILE_WRITE);
4043
 
 
4044
 
                return(os_file_write(name, file, buf, offset, offset_high, n));
4045
 
        }
4046
 
 
4047
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4048
 
try_again:
4049
 
#endif
4050
 
        if (mode == OS_AIO_NORMAL) {
4051
 
                if (type == OS_FILE_READ) {
4052
 
                        array = os_aio_read_array;
4053
 
                } else {
4054
 
                        array = os_aio_write_array;
4055
 
                }
4056
 
        } else if (mode == OS_AIO_IBUF) {
4057
 
                ut_ad(type == OS_FILE_READ);
4058
 
                /* Reduce probability of deadlock bugs in connection with ibuf:
4059
 
                do not let the ibuf i/o handler sleep */
4060
 
 
4061
 
                wake_later = FALSE;
4062
 
 
4063
 
                array = os_aio_ibuf_array;
4064
 
        } else if (mode == OS_AIO_LOG) {
4065
 
 
4066
 
                array = os_aio_log_array;
4067
 
        } else if (mode == OS_AIO_SYNC) {
4068
 
                array = os_aio_sync_array;
4069
 
 
4070
 
#if defined(LINUX_NATIVE_AIO)
4071
 
                /* In Linux native AIO we don't use sync IO array. */
4072
 
                ut_a(!srv_use_native_aio);
4073
 
#endif /* LINUX_NATIVE_AIO */
4074
 
        } else {
4075
 
                array = NULL; /* Eliminate compiler warning */
4076
 
                ut_error;
4077
 
        }
4078
 
 
4079
 
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
4080
 
                                         name, buf, offset, offset_high, n);
4081
 
        if (type == OS_FILE_READ) {
4082
 
                if (srv_use_native_aio) {
4083
 
                        os_n_file_reads++;
4084
 
                        os_bytes_read_since_printout += n;
4085
 
#ifdef WIN_ASYNC_IO
4086
 
                        ret = ReadFile(file, buf, (DWORD)n, &len,
4087
 
                                       &(slot->control));
4088
 
 
4089
 
#elif defined(LINUX_NATIVE_AIO)
4090
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4091
 
                                goto err_exit;
4092
 
                        }
4093
 
#endif
4094
 
                } else {
4095
 
                        if (!wake_later) {
4096
 
                                os_aio_simulated_wake_handler_thread(
4097
 
                                        os_aio_get_segment_no_from_slot(
4098
 
                                                array, slot));
4099
 
                        }
4100
 
                }
4101
 
        } else if (type == OS_FILE_WRITE) {
4102
 
                if (srv_use_native_aio) {
4103
 
                        os_n_file_writes++;
4104
 
#ifdef WIN_ASYNC_IO
4105
 
                        ret = WriteFile(file, buf, (DWORD)n, &len,
4106
 
                                        &(slot->control));
4107
 
 
4108
 
#elif defined(LINUX_NATIVE_AIO)
4109
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4110
 
                                goto err_exit;
4111
 
                        }
4112
 
#endif
4113
 
                } else {
4114
 
                        if (!wake_later) {
4115
 
                                os_aio_simulated_wake_handler_thread(
4116
 
                                        os_aio_get_segment_no_from_slot(
4117
 
                                                array, slot));
4118
 
                        }
4119
 
                }
4120
 
        } else {
4121
 
                ut_error;
4122
 
        }
4123
 
 
4124
 
#ifdef WIN_ASYNC_IO
4125
 
        if (srv_use_native_aio) {
4126
 
                if ((ret && len == n)
4127
 
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
4128
 
                        /* aio was queued successfully! */
4129
 
 
4130
 
                        if (mode == OS_AIO_SYNC) {
4131
 
                                /* We want a synchronous i/o operation on a
4132
 
                                file where we also use async i/o: in Windows
4133
 
                                we must use the same wait mechanism as for
4134
 
                                async i/o */
4135
 
 
4136
 
                                retval = os_aio_windows_handle(ULINT_UNDEFINED,
4137
 
                                                               slot->pos,
4138
 
                                                               &dummy_mess1,
4139
 
                                                               &dummy_mess2,
4140
 
                                                               &dummy_type);
4141
 
 
4142
 
                                return(retval);
4143
 
                        }
4144
 
 
4145
 
                        return(TRUE);
4146
 
                }
4147
 
 
4148
 
                goto err_exit;
4149
 
        }
4150
 
#endif /* WIN_ASYNC_IO */
4151
 
        /* aio was queued successfully! */
4152
 
        return(TRUE);
4153
 
 
4154
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4155
 
err_exit:
4156
 
        os_aio_array_free_slot(array, slot);
4157
 
 
4158
 
        retry = os_file_handle_error(name,
4159
 
                                     type == OS_FILE_READ
4160
 
                                     ? "aio read" : "aio write");
4161
 
        if (retry) {
4162
 
 
4163
 
                goto try_again;
4164
 
        }
4165
 
 
4166
 
        return(FALSE);
4167
 
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
4168
 
}
4169
 
 
4170
 
#ifdef WIN_ASYNC_IO
4171
 
/**********************************************************************//**
4172
 
This function is only used in Windows asynchronous i/o.
4173
 
Waits for an aio operation to complete. This function is used to wait the
4174
 
for completed requests. The aio array of pending requests is divided
4175
 
into segments. The thread specifies which segment or slot it wants to wait
4176
 
for. NOTE: this function will also take care of freeing the aio slot,
4177
 
therefore no other thread is allowed to do the freeing!
4178
 
@return TRUE if the aio operation succeeded */
4179
 
UNIV_INTERN
4180
 
ibool
4181
 
os_aio_windows_handle(
4182
 
/*==================*/
4183
 
        ulint   segment,        /*!< in: the number of the segment in the aio
4184
 
                                arrays to wait for; segment 0 is the ibuf
4185
 
                                i/o thread, segment 1 the log i/o thread,
4186
 
                                then follow the non-ibuf read threads, and as
4187
 
                                the last are the non-ibuf write threads; if
4188
 
                                this is ULINT_UNDEFINED, then it means that
4189
 
                                sync aio is used, and this parameter is
4190
 
                                ignored */
4191
 
        ulint   pos,            /*!< this parameter is used only in sync aio:
4192
 
                                wait for the aio slot at this position */
4193
 
        fil_node_t**message1,   /*!< out: the messages passed with the aio
4194
 
                                request; note that also in the case where
4195
 
                                the aio operation failed, these output
4196
 
                                parameters are valid and can be used to
4197
 
                                restart the operation, for example */
4198
 
        void**  message2,
4199
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
4200
 
{
4201
 
        ulint           orig_seg        = segment;
4202
 
        os_aio_array_t* array;
4203
 
        os_aio_slot_t*  slot;
4204
 
        ulint           n;
4205
 
        ulint           i;
4206
 
        ibool           ret_val;
4207
 
        BOOL            ret;
4208
 
        DWORD           len;
4209
 
        BOOL            retry           = FALSE;
4210
 
 
4211
 
        if (segment == ULINT_UNDEFINED) {
4212
 
                array = os_aio_sync_array;
4213
 
                segment = 0;
4214
 
        } else {
4215
 
                segment = os_aio_get_array_and_local_segment(&array, segment);
4216
 
        }
4217
 
 
4218
 
        /* NOTE! We only access constant fields in os_aio_array. Therefore
4219
 
        we do not have to acquire the protecting mutex yet */
4220
 
 
4221
 
        ut_ad(os_aio_validate());
4222
 
        ut_ad(segment < array->n_segments);
4223
 
 
4224
 
        n = array->n_slots / array->n_segments;
4225
 
 
4226
 
        if (array == os_aio_sync_array) {
4227
 
                WaitForSingleObject(
4228
 
                        os_aio_array_get_nth_slot(array, pos)->handle,
4229
 
                        INFINITE);
4230
 
                i = pos;
4231
 
        } else {
4232
 
                srv_set_io_thread_op_info(orig_seg, "wait Windows aio");
4233
 
                i = WaitForMultipleObjects((DWORD) n,
4234
 
                                           array->handles + segment * n,
4235
 
                                           FALSE,
4236
 
                                           INFINITE);
4237
 
        }
4238
 
 
4239
 
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
4240
 
                os_thread_exit(NULL);
4241
 
        }
4242
 
 
4243
 
        os_mutex_enter(array->mutex);
4244
 
 
4245
 
        slot = os_aio_array_get_nth_slot(array, i + segment * n);
4246
 
 
4247
 
        ut_a(slot->reserved);
4248
 
 
4249
 
        if (orig_seg != ULINT_UNDEFINED) {
4250
 
                srv_set_io_thread_op_info(orig_seg,
4251
 
                                          "get windows aio return value");
4252
 
        }
4253
 
 
4254
 
        ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
4255
 
 
4256
 
        *message1 = slot->message1;
4257
 
        *message2 = slot->message2;
4258
 
 
4259
 
        *type = slot->type;
4260
 
 
4261
 
        if (ret && len == slot->len) {
4262
 
                ret_val = TRUE;
4263
 
 
4264
 
#ifdef UNIV_DO_FLUSH
4265
 
                if (slot->type == OS_FILE_WRITE
4266
 
                    && !os_do_not_call_flush_at_each_write) {
4267
 
                        if (!os_file_flush(slot->file)) {
4268
 
                                ut_error;
4269
 
                        }
4270
 
                }
4271
 
#endif /* UNIV_DO_FLUSH */
4272
 
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
4273
 
 
4274
 
                retry = TRUE;
4275
 
        } else {
4276
 
 
4277
 
                ret_val = FALSE;
4278
 
        }
4279
 
 
4280
 
        os_mutex_exit(array->mutex);
4281
 
 
4282
 
        if (retry) {
4283
 
                /* retry failed read/write operation synchronously.
4284
 
                No need to hold array->mutex. */
4285
 
 
4286
 
#ifdef UNIV_PFS_IO
4287
 
                /* This read/write does not go through os_file_read
4288
 
                and os_file_write APIs, need to register with
4289
 
                performance schema explicitly here. */
4290
 
                struct PSI_file_locker* locker = NULL;
4291
 
                register_pfs_file_io_begin(locker, slot->file, slot->len,
4292
 
                                           (slot->type == OS_FILE_WRITE)
4293
 
                                                ? PSI_FILE_WRITE
4294
 
                                                : PSI_FILE_READ,
4295
 
                                            __FILE__, __LINE__);
4296
 
#endif
4297
 
 
4298
 
                ut_a((slot->len & 0xFFFFFFFFUL) == slot->len);
4299
 
 
4300
 
                switch (slot->type) {
4301
 
                case OS_FILE_WRITE:
4302
 
                        ret = WriteFile(slot->file, slot->buf,
4303
 
                                        (DWORD) slot->len, &len,
4304
 
                                        &(slot->control));
4305
 
 
4306
 
                        break;
4307
 
                case OS_FILE_READ:
4308
 
                        ret = ReadFile(slot->file, slot->buf,
4309
 
                                       (DWORD) slot->len, &len,
4310
 
                                       &(slot->control));
4311
 
 
4312
 
                        break;
4313
 
                default:
4314
 
                        ut_error;
4315
 
                }
4316
 
 
4317
 
#ifdef UNIV_PFS_IO
4318
 
                register_pfs_file_io_end(locker, len);
4319
 
#endif
4320
 
 
4321
 
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
4322
 
                        /* aio was queued successfully!
4323
 
                        We want a synchronous i/o operation on a
4324
 
                        file where we also use async i/o: in Windows
4325
 
                        we must use the same wait mechanism as for
4326
 
                        async i/o */
4327
 
 
4328
 
                        ret = GetOverlappedResult(slot->file,
4329
 
                                                  &(slot->control),
4330
 
                                                  &len, TRUE);
4331
 
                }
4332
 
 
4333
 
                ret_val = ret && len == slot->len;
4334
 
        }
4335
 
 
4336
 
        os_aio_array_free_slot(array, slot);
4337
 
 
4338
 
        return(ret_val);
4339
 
}
4340
 
#endif
4341
 
 
4342
 
#if defined(LINUX_NATIVE_AIO)
4343
 
/******************************************************************//**
4344
 
This function is only used in Linux native asynchronous i/o. This is
4345
 
called from within the io-thread. If there are no completed IO requests
4346
 
in the slot array, the thread calls this function to collect more
4347
 
requests from the kernel.
4348
 
The io-thread waits on io_getevents(), which is a blocking call, with
4349
 
a timeout value. Unless the system is very heavy loaded, keeping the
4350
 
io-thread very busy, the io-thread will spend most of its time waiting
4351
 
in this function.
4352
 
The io-thread also exits in this function. It checks server status at
4353
 
each wakeup and that is why we use timed wait in io_getevents(). */
4354
 
static
4355
 
void
4356
 
os_aio_linux_collect(
4357
 
/*=================*/
4358
 
        os_aio_array_t* array,          /*!< in/out: slot array. */
4359
 
        ulint           segment,        /*!< in: local segment no. */
4360
 
        ulint           seg_size)       /*!< in: segment size. */
4361
 
{
4362
 
        int                     i;
4363
 
        int                     ret;
4364
 
        ulint                   start_pos;
4365
 
        ulint                   end_pos;
4366
 
        struct timespec         timeout;
4367
 
        struct io_event*        events;
4368
 
        struct io_context*      io_ctx;
4369
 
 
4370
 
        /* sanity checks. */
4371
 
        ut_ad(array != NULL);
4372
 
        ut_ad(seg_size > 0);
4373
 
        ut_ad(segment < array->n_segments);
4374
 
 
4375
 
        /* Which part of event array we are going to work on. */
4376
 
        events = &array->aio_events[segment * seg_size];
4377
 
 
4378
 
        /* Which io_context we are going to use. */
4379
 
        io_ctx = array->aio_ctx[segment];
4380
 
 
4381
 
        /* Starting point of the segment we will be working on. */
4382
 
        start_pos = segment * seg_size;
4383
 
 
4384
 
        /* End point. */
4385
 
        end_pos = start_pos + seg_size;
4386
 
 
4387
 
retry:
4388
 
 
4389
 
        /* Go down if we are in shutdown mode.
4390
 
        In case of srv_fast_shutdown == 2, there may be pending
4391
 
        IO requests but that should be OK as we essentially treat
4392
 
        that as a crash of InnoDB. */
4393
 
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
4394
 
                os_thread_exit(NULL);
4395
 
        }
4396
 
 
4397
 
        /* Initialize the events. The timeout value is arbitrary.
4398
 
        We probably need to experiment with it a little. */
4399
 
        memset(events, 0, sizeof(*events) * seg_size);
4400
 
        timeout.tv_sec = 0;
4401
 
        timeout.tv_nsec = OS_AIO_REAP_TIMEOUT;
4402
 
 
4403
 
        ret = io_getevents(io_ctx, 1, seg_size, events, &timeout);
4404
 
 
4405
 
        /* This error handling is for any error in collecting the
4406
 
        IO requests. The errors, if any, for any particular IO
4407
 
        request are simply passed on to the calling routine. */
4408
 
 
4409
 
        /* Not enough resources! Try again. */
4410
 
        if (ret == -EAGAIN) {
4411
 
                goto retry;
4412
 
        }
4413
 
 
4414
 
        /* Interrupted! I have tested the behaviour in case of an
4415
 
        interrupt. If we have some completed IOs available then
4416
 
        the return code will be the number of IOs. We get EINTR only
4417
 
        if there are no completed IOs and we have been interrupted. */
4418
 
        if (ret == -EINTR) {
4419
 
                goto retry;
4420
 
        }
4421
 
 
4422
 
        /* No pending request! Go back and check again. */
4423
 
        if (ret == 0) {
4424
 
                goto retry;
4425
 
        }
4426
 
 
4427
 
        /* All other errors! should cause a trap for now. */
4428
 
        if (UNIV_UNLIKELY(ret < 0)) {
4429
 
                ut_print_timestamp(stderr);
4430
 
                fprintf(stderr,
4431
 
                        "  InnoDB: unexpected ret_code[%d] from"
4432
 
                        " io_getevents()!\n", ret);
4433
 
                ut_error;
4434
 
        }
4435
 
 
4436
 
        ut_a(ret > 0);
4437
 
 
4438
 
        for (i = 0; i < ret; i++) {
4439
 
                os_aio_slot_t*  slot;
4440
 
                struct iocb*    control;
4441
 
 
4442
 
                control = (struct iocb *)events[i].obj;
4443
 
                ut_a(control != NULL);
4444
 
 
4445
 
                slot = (os_aio_slot_t *) control->data;
4446
 
 
4447
 
                /* Some sanity checks. */
4448
 
                ut_a(slot != NULL);
4449
 
                ut_a(slot->reserved);
4450
 
 
4451
 
#if defined(UNIV_AIO_DEBUG)
4452
 
                fprintf(stderr,
4453
 
                        "io_getevents[%c]: slot[%p] ctx[%p]"
4454
 
                        " seg[%lu]\n",
4455
 
                        (slot->type == OS_FILE_WRITE) ? 'w' : 'r',
4456
 
                        slot, io_ctx, segment);
4457
 
#endif
4458
 
 
4459
 
                /* We are not scribbling previous segment. */
4460
 
                ut_a(slot->pos >= start_pos);
4461
 
 
4462
 
                /* We have not overstepped to next segment. */
4463
 
                ut_a(slot->pos < end_pos);
4464
 
 
4465
 
                /* Mark this request as completed. The error handling
4466
 
                will be done in the calling function. */
4467
 
                os_mutex_enter(array->mutex);
4468
 
                slot->n_bytes = events[i].res;
4469
 
                slot->ret = events[i].res2;
4470
 
                slot->io_already_done = TRUE;
4471
 
                os_mutex_exit(array->mutex);
4472
 
        }
4473
 
 
4474
 
        return;
4475
 
}
4476
 
 
4477
 
/**********************************************************************//**
4478
 
This function is only used in Linux native asynchronous i/o.
4479
 
Waits for an aio operation to complete. This function is used to wait for
4480
 
the completed requests. The aio array of pending requests is divided
4481
 
into segments. The thread specifies which segment or slot it wants to wait
4482
 
for. NOTE: this function will also take care of freeing the aio slot,
4483
 
therefore no other thread is allowed to do the freeing!
4484
 
@return TRUE if the IO was successful */
4485
 
UNIV_INTERN
4486
 
ibool
4487
 
os_aio_linux_handle(
4488
 
/*================*/
4489
 
        ulint   global_seg,     /*!< in: segment number in the aio array
4490
 
                                to wait for; segment 0 is the ibuf
4491
 
                                i/o thread, segment 1 is log i/o thread,
4492
 
                                then follow the non-ibuf read threads,
4493
 
                                and the last are the non-ibuf write
4494
 
                                threads. */
4495
 
        fil_node_t**message1,   /*!< out: the messages passed with the */
4496
 
        void**  message2,       /*!< aio request; note that in case the
4497
 
                                aio operation failed, these output
4498
 
                                parameters are valid and can be used to
4499
 
                                restart the operation. */
4500
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
4501
 
{
4502
 
        ulint           segment;
4503
 
        os_aio_array_t* array;
4504
 
        os_aio_slot_t*  slot;
4505
 
        ulint           n;
4506
 
        ulint           i;
4507
 
        ibool           ret = FALSE;
4508
 
 
4509
 
        /* Should never be doing Sync IO here. */
4510
 
        ut_a(global_seg != ULINT_UNDEFINED);
4511
 
 
4512
 
        /* Find the array and the local segment. */
4513
 
        segment = os_aio_get_array_and_local_segment(&array, global_seg);
4514
 
        n = array->n_slots / array->n_segments;
4515
 
 
4516
 
        /* Loop until we have found a completed request. */
4517
 
        for (;;) {
4518
 
                os_mutex_enter(array->mutex);
4519
 
                for (i = 0; i < n; ++i) {
4520
 
                        slot = os_aio_array_get_nth_slot(
4521
 
                                        array, i + segment * n);
4522
 
                        if (slot->reserved && slot->io_already_done) {
4523
 
                                /* Something for us to work on. */
4524
 
                                goto found;
4525
 
                        }
4526
 
                }
4527
 
 
4528
 
                os_mutex_exit(array->mutex);
4529
 
 
4530
 
                /* We don't have any completed request.
4531
 
                Wait for some request. Note that we return
4532
 
                from wait iff we have found a request. */
4533
 
 
4534
 
                srv_set_io_thread_op_info(global_seg,
4535
 
                        "waiting for completed aio requests");
4536
 
                os_aio_linux_collect(array, segment, n);
4537
 
        }
4538
 
 
4539
 
found:
4540
 
        /* Note that it may be that there are more then one completed
4541
 
        IO requests. We process them one at a time. We may have a case
4542
 
        here to improve the performance slightly by dealing with all
4543
 
        requests in one sweep. */
4544
 
        srv_set_io_thread_op_info(global_seg,
4545
 
                                "processing completed aio requests");
4546
 
 
4547
 
        /* Ensure that we are scribbling only our segment. */
4548
 
        ut_a(i < n);
4549
 
 
4550
 
        ut_ad(slot != NULL);
4551
 
        ut_ad(slot->reserved);
4552
 
        ut_ad(slot->io_already_done);
4553
 
 
4554
 
        *message1 = slot->message1;
4555
 
        *message2 = slot->message2;
4556
 
 
4557
 
        *type = slot->type;
4558
 
 
4559
 
        if ((slot->ret == 0) && (slot->n_bytes == (long)slot->len)) {
4560
 
                ret = TRUE;
4561
 
 
4562
 
#ifdef UNIV_DO_FLUSH
4563
 
                if (slot->type == OS_FILE_WRITE
4564
 
                    && !os_do_not_call_flush_at_each_write)
4565
 
                    && !os_file_flush(slot->file) {
4566
 
                        ut_error;
4567
 
                }
4568
 
#endif /* UNIV_DO_FLUSH */
4569
 
        } else {
4570
 
                errno = -slot->ret;
4571
 
 
4572
 
                /* os_file_handle_error does tell us if we should retry
4573
 
                this IO. As it stands now, we don't do this retry when
4574
 
                reaping requests from a different context than
4575
 
                the dispatcher. This non-retry logic is the same for
4576
 
                windows and linux native AIO.
4577
 
                We should probably look into this to transparently
4578
 
                re-submit the IO. */
4579
 
                os_file_handle_error(slot->name, "Linux aio");
4580
 
 
4581
 
                ret = FALSE;
4582
 
        }
4583
 
 
4584
 
        os_mutex_exit(array->mutex);
4585
 
 
4586
 
        os_aio_array_free_slot(array, slot);
4587
 
 
4588
 
        return(ret);
4589
 
}
4590
 
#endif /* LINUX_NATIVE_AIO */
4591
 
 
4592
 
/**********************************************************************//**
4593
 
Does simulated aio. This function should be called by an i/o-handler
4594
 
thread.
4595
 
@return TRUE if the aio operation succeeded */
4596
 
UNIV_INTERN
4597
 
ibool
4598
 
os_aio_simulated_handle(
4599
 
/*====================*/
4600
 
        ulint   global_segment, /*!< in: the number of the segment in the aio
4601
 
                                arrays to wait for; segment 0 is the ibuf
4602
 
                                i/o thread, segment 1 the log i/o thread,
4603
 
                                then follow the non-ibuf read threads, and as
4604
 
                                the last are the non-ibuf write threads */
4605
 
        fil_node_t**message1,   /*!< out: the messages passed with the aio
4606
 
                                request; note that also in the case where
4607
 
                                the aio operation failed, these output
4608
 
                                parameters are valid and can be used to
4609
 
                                restart the operation, for example */
4610
 
        void**  message2,
4611
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
4612
 
{
4613
 
        os_aio_array_t* array;
4614
 
        ulint           segment;
4615
 
        os_aio_slot_t*  slot;
4616
 
        os_aio_slot_t*  slot2;
4617
 
        os_aio_slot_t*  consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
4618
 
        ulint           n_consecutive;
4619
 
        ulint           total_len;
4620
 
        ulint           offs;
4621
 
        ulint           lowest_offset;
4622
 
        ulint           biggest_age;
4623
 
        ulint           age;
4624
 
        byte*           combined_buf;
4625
 
        byte*           combined_buf2;
4626
 
        ibool           ret;
4627
 
        ulint           n;
4628
 
        ulint           i;
4629
 
 
4630
 
        /* Fix compiler warning */
4631
 
        *consecutive_ios = NULL;
4632
 
 
4633
 
        memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
4634
 
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
4635
 
 
4636
 
restart:
4637
 
        /* NOTE! We only access constant fields in os_aio_array. Therefore
4638
 
        we do not have to acquire the protecting mutex yet */
4639
 
 
4640
 
        srv_set_io_thread_op_info(global_segment,
4641
 
                                  "looking for i/o requests (a)");
4642
 
        ut_ad(os_aio_validate());
4643
 
        ut_ad(segment < array->n_segments);
4644
 
 
4645
 
        n = array->n_slots / array->n_segments;
4646
 
 
4647
 
        /* Look through n slots after the segment * n'th slot */
4648
 
 
4649
 
        if (array == os_aio_read_array
4650
 
            && os_aio_recommend_sleep_for_read_threads) {
4651
 
 
4652
 
                /* Give other threads chance to add several i/os to the array
4653
 
                at once. */
4654
 
 
4655
 
                goto recommended_sleep;
4656
 
        }
4657
 
 
4658
 
        os_mutex_enter(array->mutex);
4659
 
 
4660
 
        srv_set_io_thread_op_info(global_segment,
4661
 
                                  "looking for i/o requests (b)");
4662
 
 
4663
 
        /* Check if there is a slot for which the i/o has already been
4664
 
        done */
4665
 
 
4666
 
        for (i = 0; i < n; i++) {
4667
 
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
4668
 
 
4669
 
                if (slot->reserved && slot->io_already_done) {
4670
 
 
4671
 
                        if (os_aio_print_debug) {
4672
 
                                fprintf(stderr,
4673
 
                                        "InnoDB: i/o for slot %lu"
4674
 
                                        " already done, returning\n",
4675
 
                                        (ulong) i);
4676
 
                        }
4677
 
 
4678
 
                        ret = TRUE;
4679
 
 
4680
 
                        goto slot_io_done;
4681
 
                }
4682
 
        }
4683
 
 
4684
 
        n_consecutive = 0;
4685
 
 
4686
 
        /* If there are at least 2 seconds old requests, then pick the oldest
4687
 
        one to prevent starvation. If several requests have the same age,
4688
 
        then pick the one at the lowest offset. */
4689
 
 
4690
 
        biggest_age = 0;
4691
 
        lowest_offset = ULINT_MAX;
4692
 
 
4693
 
        for (i = 0; i < n; i++) {
4694
 
                slot = os_aio_array_get_nth_slot(array, i + segment * n);
4695
 
 
4696
 
                if (slot->reserved) {
4697
 
                        age = (ulint)difftime(time(NULL),
4698
 
                                              slot->reservation_time);
4699
 
 
4700
 
                        if ((age >= 2 && age > biggest_age)
4701
 
                            || (age >= 2 && age == biggest_age
4702
 
                                && slot->offset < lowest_offset)) {
4703
 
 
4704
 
                                /* Found an i/o request */
4705
 
                                consecutive_ios[0] = slot;
4706
 
 
4707
 
                                n_consecutive = 1;
4708
 
 
4709
 
                                biggest_age = age;
4710
 
                                lowest_offset = slot->offset;
4711
 
                        }
4712
 
                }
4713
 
        }
4714
 
 
4715
 
        if (n_consecutive == 0) {
4716
 
                /* There were no old requests. Look for an i/o request at the
4717
 
                lowest offset in the array (we ignore the high 32 bits of the
4718
 
                offset in these heuristics) */
4719
 
 
4720
 
                lowest_offset = ULINT_MAX;
4721
 
 
4722
 
                for (i = 0; i < n; i++) {
4723
 
                        slot = os_aio_array_get_nth_slot(array,
4724
 
                                                         i + segment * n);
4725
 
 
4726
 
                        if (slot->reserved && slot->offset < lowest_offset) {
4727
 
 
4728
 
                                /* Found an i/o request */
4729
 
                                consecutive_ios[0] = slot;
4730
 
 
4731
 
                                n_consecutive = 1;
4732
 
 
4733
 
                                lowest_offset = slot->offset;
4734
 
                        }
4735
 
                }
4736
 
        }
4737
 
 
4738
 
        if (n_consecutive == 0) {
4739
 
 
4740
 
                /* No i/o requested at the moment */
4741
 
 
4742
 
                goto wait_for_io;
4743
 
        }
4744
 
 
4745
 
        /* if n_consecutive != 0, then we have assigned
4746
 
        something valid to consecutive_ios[0] */
4747
 
        ut_ad(n_consecutive != 0);
4748
 
        ut_ad(consecutive_ios[0] != NULL);
4749
 
 
4750
 
        slot = consecutive_ios[0];
4751
 
 
4752
 
        /* Check if there are several consecutive blocks to read or write */
4753
 
 
4754
 
consecutive_loop:
4755
 
        for (i = 0; i < n; i++) {
4756
 
                slot2 = os_aio_array_get_nth_slot(array, i + segment * n);
4757
 
 
4758
 
                if (slot2->reserved && slot2 != slot
4759
 
                    && slot2->offset == slot->offset + slot->len
4760
 
                    /* check that sum does not wrap over */
4761
 
                    && slot->offset + slot->len > slot->offset
4762
 
                    && slot2->offset_high == slot->offset_high
4763
 
                    && slot2->type == slot->type
4764
 
                    && slot2->file == slot->file) {
4765
 
 
4766
 
                        /* Found a consecutive i/o request */
4767
 
 
4768
 
                        consecutive_ios[n_consecutive] = slot2;
4769
 
                        n_consecutive++;
4770
 
 
4771
 
                        slot = slot2;
4772
 
 
4773
 
                        if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) {
4774
 
 
4775
 
                                goto consecutive_loop;
4776
 
                        } else {
4777
 
                                break;
4778
 
                        }
4779
 
                }
4780
 
        }
4781
 
 
4782
 
        srv_set_io_thread_op_info(global_segment, "consecutive i/o requests");
4783
 
 
4784
 
        /* We have now collected n_consecutive i/o requests in the array;
4785
 
        allocate a single buffer which can hold all data, and perform the
4786
 
        i/o */
4787
 
 
4788
 
        total_len = 0;
4789
 
        slot = consecutive_ios[0];
4790
 
 
4791
 
        for (i = 0; i < n_consecutive; i++) {
4792
 
                total_len += consecutive_ios[i]->len;
4793
 
        }
4794
 
 
4795
 
        if (n_consecutive == 1) {
4796
 
                /* We can use the buffer of the i/o request */
4797
 
                combined_buf = slot->buf;
4798
 
                combined_buf2 = NULL;
4799
 
        } else {
4800
 
                combined_buf2 = static_cast<unsigned char *>(ut_malloc(total_len + UNIV_PAGE_SIZE));
4801
 
 
4802
 
                ut_a(combined_buf2);
4803
 
 
4804
 
                combined_buf = static_cast<unsigned char *>(ut_align(combined_buf2, UNIV_PAGE_SIZE));
4805
 
        }
4806
 
 
4807
 
        /* We release the array mutex for the time of the i/o: NOTE that
4808
 
        this assumes that there is just one i/o-handler thread serving
4809
 
        a single segment of slots! */
4810
 
 
4811
 
        os_mutex_exit(array->mutex);
4812
 
 
4813
 
        if (slot->type == OS_FILE_WRITE && n_consecutive > 1) {
4814
 
                /* Copy the buffers to the combined buffer */
4815
 
                offs = 0;
4816
 
 
4817
 
                for (i = 0; i < n_consecutive; i++) {
4818
 
 
4819
 
                        ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf,
4820
 
                                  consecutive_ios[i]->len);
4821
 
                        offs += consecutive_ios[i]->len;
4822
 
                }
4823
 
        }
4824
 
 
4825
 
        srv_set_io_thread_op_info(global_segment, "doing file i/o");
4826
 
 
4827
 
        if (os_aio_print_debug) {
4828
 
                fprintf(stderr,
4829
 
                        "InnoDB: doing i/o of type %lu at offset %lu %lu,"
4830
 
                        " length %lu\n",
4831
 
                        (ulong) slot->type, (ulong) slot->offset_high,
4832
 
                        (ulong) slot->offset, (ulong) total_len);
4833
 
        }
4834
 
 
4835
 
        /* Do the i/o with ordinary, synchronous i/o functions: */
4836
 
        if (slot->type == OS_FILE_WRITE) {
4837
 
                ret = os_file_write(slot->name, slot->file, combined_buf,
4838
 
                                    slot->offset, slot->offset_high,
4839
 
                                    total_len);
4840
 
        } else {
4841
 
                ret = os_file_read(slot->file, combined_buf,
4842
 
                                   slot->offset, slot->offset_high, total_len);
4843
 
        }
4844
 
 
4845
 
        ut_a(ret);
4846
 
        srv_set_io_thread_op_info(global_segment, "file i/o done");
4847
 
 
4848
 
#if 0
4849
 
        fprintf(stderr,
4850
 
                "aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
4851
 
                n_consecutive, global_segment, slot->offset / UNIV_PAGE_SIZE);
4852
 
#endif
4853
 
 
4854
 
        if (slot->type == OS_FILE_READ && n_consecutive > 1) {
4855
 
                /* Copy the combined buffer to individual buffers */
4856
 
                offs = 0;
4857
 
 
4858
 
                for (i = 0; i < n_consecutive; i++) {
4859
 
 
4860
 
                        ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs,
4861
 
                                  consecutive_ios[i]->len);
4862
 
                        offs += consecutive_ios[i]->len;
4863
 
                }
4864
 
        }
4865
 
 
4866
 
        if (combined_buf2) {
4867
 
                ut_free(combined_buf2);
4868
 
        }
4869
 
 
4870
 
        os_mutex_enter(array->mutex);
4871
 
 
4872
 
        /* Mark the i/os done in slots */
4873
 
 
4874
 
        for (i = 0; i < n_consecutive; i++) {
4875
 
                consecutive_ios[i]->io_already_done = TRUE;
4876
 
        }
4877
 
 
4878
 
        /* We return the messages for the first slot now, and if there were
4879
 
        several slots, the messages will be returned with subsequent calls
4880
 
        of this function */
4881
 
 
4882
 
slot_io_done:
4883
 
 
4884
 
        ut_a(slot->reserved);
4885
 
 
4886
 
        *message1 = slot->message1;
4887
 
        *message2 = slot->message2;
4888
 
 
4889
 
        *type = slot->type;
4890
 
 
4891
 
        os_mutex_exit(array->mutex);
4892
 
 
4893
 
        os_aio_array_free_slot(array, slot);
4894
 
 
4895
 
        return(ret);
4896
 
 
4897
 
wait_for_io:
4898
 
        srv_set_io_thread_op_info(global_segment, "resetting wait event");
4899
 
 
4900
 
        /* We wait here until there again can be i/os in the segment
4901
 
        of this thread */
4902
 
 
4903
 
        os_event_reset(os_aio_segment_wait_events[global_segment]);
4904
 
 
4905
 
        os_mutex_exit(array->mutex);
4906
 
 
4907
 
recommended_sleep:
4908
 
        srv_set_io_thread_op_info(global_segment, "waiting for i/o request");
4909
 
 
4910
 
        os_event_wait(os_aio_segment_wait_events[global_segment]);
4911
 
 
4912
 
        if (os_aio_print_debug) {
4913
 
                fprintf(stderr,
4914
 
                        "InnoDB: i/o handler thread for i/o"
4915
 
                        " segment %lu wakes up\n",
4916
 
                        (ulong) global_segment);
4917
 
        }
4918
 
 
4919
 
        goto restart;
4920
 
}
4921
 
 
4922
 
/**********************************************************************//**
4923
 
Validates the consistency of an aio array.
4924
 
@return TRUE if ok */
4925
 
static
4926
 
ibool
4927
 
os_aio_array_validate(
4928
 
/*==================*/
4929
 
        os_aio_array_t* array)  /*!< in: aio wait array */
4930
 
{
4931
 
        os_aio_slot_t*  slot;
4932
 
        ulint           n_reserved      = 0;
4933
 
        ulint           i;
4934
 
 
4935
 
        ut_a(array);
4936
 
 
4937
 
        os_mutex_enter(array->mutex);
4938
 
 
4939
 
        ut_a(array->n_slots > 0);
4940
 
        ut_a(array->n_segments > 0);
4941
 
 
4942
 
        for (i = 0; i < array->n_slots; i++) {
4943
 
                slot = os_aio_array_get_nth_slot(array, i);
4944
 
 
4945
 
                if (slot->reserved) {
4946
 
                        n_reserved++;
4947
 
                        ut_a(slot->len > 0);
4948
 
                }
4949
 
        }
4950
 
 
4951
 
        ut_a(array->n_reserved == n_reserved);
4952
 
 
4953
 
        os_mutex_exit(array->mutex);
4954
 
 
4955
 
        return(TRUE);
4956
 
}
4957
 
 
4958
 
/**********************************************************************//**
4959
 
Validates the consistency the aio system.
4960
 
@return TRUE if ok */
4961
 
UNIV_INTERN
4962
 
ibool
4963
 
os_aio_validate(void)
4964
 
/*=================*/
4965
 
{
4966
 
        os_aio_array_validate(os_aio_read_array);
4967
 
        os_aio_array_validate(os_aio_write_array);
4968
 
        os_aio_array_validate(os_aio_ibuf_array);
4969
 
        os_aio_array_validate(os_aio_log_array);
4970
 
        os_aio_array_validate(os_aio_sync_array);
4971
 
 
4972
 
        return(TRUE);
4973
 
}
4974
 
 
4975
 
/**********************************************************************//**
4976
 
Prints pending IO requests per segment of an aio array.
4977
 
We probably don't need per segment statistics but they can help us
4978
 
during development phase to see if the IO requests are being
4979
 
distributed as expected. */
4980
 
static
4981
 
void
4982
 
os_aio_print_segment_info(
4983
 
/*======================*/
4984
 
        FILE*           file,   /*!< in: file where to print */
4985
 
        ulint*          n_seg,  /*!< in: pending IO array */
4986
 
        os_aio_array_t* array)  /*!< in: array to process */
4987
 
{
4988
 
        ulint   i;
4989
 
 
4990
 
        ut_ad(array);
4991
 
        ut_ad(n_seg);
4992
 
        ut_ad(array->n_segments > 0);
4993
 
 
4994
 
        if (array->n_segments == 1) {
4995
 
                return;
4996
 
        }
4997
 
 
4998
 
        fprintf(file, " [");
4999
 
        for (i = 0; i < array->n_segments; i++) {
5000
 
                if (i != 0) {
5001
 
                        fprintf(file, ", ");
5002
 
                }
5003
 
 
5004
 
                fprintf(file, "%lu", n_seg[i]);
5005
 
        }
5006
 
        fprintf(file, "] ");
5007
 
}
5008
 
 
5009
 
/**********************************************************************//**
5010
 
Prints info of the aio arrays. */
5011
 
UNIV_INTERN
5012
 
void
5013
 
os_aio_print(
5014
 
/*=========*/
5015
 
        FILE*   file)   /*!< in: file where to print */
5016
 
{
5017
 
        os_aio_array_t* array;
5018
 
        os_aio_slot_t*  slot;
5019
 
        ulint           n_reserved;
5020
 
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
5021
 
        time_t          current_time;
5022
 
        double          time_elapsed;
5023
 
        double          avg_bytes_read;
5024
 
        ulint           i;
5025
 
 
5026
 
        for (i = 0; i < srv_n_file_io_threads; i++) {
5027
 
                fprintf(file, "I/O thread %lu state: %s (%s)", (ulong) i,
5028
 
                        srv_io_thread_op_info[i],
5029
 
                        srv_io_thread_function[i]);
5030
 
 
5031
 
#ifndef __WIN__
5032
 
                if (os_aio_segment_wait_events[i]->is_set) {
5033
 
                        fprintf(file, " ev set");
5034
 
                }
5035
 
#endif
5036
 
 
5037
 
                fprintf(file, "\n");
5038
 
        }
5039
 
 
5040
 
        fputs("Pending normal aio reads:", file);
5041
 
 
5042
 
        array = os_aio_read_array;
5043
 
loop:
5044
 
        ut_a(array);
5045
 
 
5046
 
        os_mutex_enter(array->mutex);
5047
 
 
5048
 
        ut_a(array->n_slots > 0);
5049
 
        ut_a(array->n_segments > 0);
5050
 
 
5051
 
        n_reserved = 0;
5052
 
 
5053
 
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
5054
 
 
5055
 
        for (i = 0; i < array->n_slots; i++) {
5056
 
                ulint   seg_no;
5057
 
 
5058
 
                slot = os_aio_array_get_nth_slot(array, i);
5059
 
 
5060
 
                seg_no = (i * array->n_segments) / array->n_slots;
5061
 
                if (slot->reserved) {
5062
 
                        n_reserved++;
5063
 
                        n_res_seg[seg_no]++;
5064
 
#if 0
5065
 
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
5066
 
                                (void*) slot->message1,
5067
 
                                (void*) slot->message2);
5068
 
#endif
5069
 
                        ut_a(slot->len > 0);
5070
 
                }
5071
 
        }
5072
 
 
5073
 
        ut_a(array->n_reserved == n_reserved);
5074
 
 
5075
 
        fprintf(file, " %lu", (ulong) n_reserved);
5076
 
 
5077
 
        os_aio_print_segment_info(file, n_res_seg, array);
5078
 
 
5079
 
        os_mutex_exit(array->mutex);
5080
 
 
5081
 
        if (array == os_aio_read_array) {
5082
 
                fputs(", aio writes:", file);
5083
 
 
5084
 
                array = os_aio_write_array;
5085
 
 
5086
 
                goto loop;
5087
 
        }
5088
 
 
5089
 
        if (array == os_aio_write_array) {
5090
 
                fputs(",\n ibuf aio reads:", file);
5091
 
                array = os_aio_ibuf_array;
5092
 
 
5093
 
                goto loop;
5094
 
        }
5095
 
 
5096
 
        if (array == os_aio_ibuf_array) {
5097
 
                fputs(", log i/o's:", file);
5098
 
                array = os_aio_log_array;
5099
 
 
5100
 
                goto loop;
5101
 
        }
5102
 
 
5103
 
        if (array == os_aio_log_array) {
5104
 
                fputs(", sync i/o's:", file);
5105
 
                array = os_aio_sync_array;
5106
 
 
5107
 
                goto loop;
5108
 
        }
5109
 
 
5110
 
        putc('\n', file);
5111
 
        current_time = time(NULL);
5112
 
        time_elapsed = 0.001 + difftime(current_time, os_last_printout);
5113
 
 
5114
 
        fprintf(file,
5115
 
                "Pending flushes (fsync) log: %lu; buffer pool: %lu\n"
5116
 
                "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
5117
 
                (ulong) fil_n_pending_log_flushes,
5118
 
                (ulong) fil_n_pending_tablespace_flushes,
5119
 
                (ulong) os_n_file_reads, (ulong) os_n_file_writes,
5120
 
                (ulong) os_n_fsyncs);
5121
 
 
5122
 
        if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) {
5123
 
                fprintf(file,
5124
 
                        "%lu pending preads, %lu pending pwrites\n",
5125
 
                        (ulong) os_file_n_pending_preads,
5126
 
                        (ulong) os_file_n_pending_pwrites);
5127
 
        }
5128
 
 
5129
 
        if (os_n_file_reads == os_n_file_reads_old) {
5130
 
                avg_bytes_read = 0.0;
5131
 
        } else {
5132
 
                avg_bytes_read = (double) os_bytes_read_since_printout
5133
 
                        / (os_n_file_reads - os_n_file_reads_old);
5134
 
        }
5135
 
 
5136
 
        fprintf(file,
5137
 
                "%.2f reads/s, %lu avg bytes/read,"
5138
 
                " %.2f writes/s, %.2f fsyncs/s\n",
5139
 
                (os_n_file_reads - os_n_file_reads_old)
5140
 
                / time_elapsed,
5141
 
                (ulong)avg_bytes_read,
5142
 
                (os_n_file_writes - os_n_file_writes_old)
5143
 
                / time_elapsed,
5144
 
                (os_n_fsyncs - os_n_fsyncs_old)
5145
 
                / time_elapsed);
5146
 
 
5147
 
        os_n_file_reads_old = os_n_file_reads;
5148
 
        os_n_file_writes_old = os_n_file_writes;
5149
 
        os_n_fsyncs_old = os_n_fsyncs;
5150
 
        os_bytes_read_since_printout = 0;
5151
 
 
5152
 
        os_last_printout = current_time;
5153
 
}
5154
 
 
5155
 
/**********************************************************************//**
5156
 
Refreshes the statistics used to print per-second averages. */
5157
 
UNIV_INTERN
5158
 
void
5159
 
os_aio_refresh_stats(void)
5160
 
/*======================*/
5161
 
{
5162
 
        os_n_file_reads_old = os_n_file_reads;
5163
 
        os_n_file_writes_old = os_n_file_writes;
5164
 
        os_n_fsyncs_old = os_n_fsyncs;
5165
 
        os_bytes_read_since_printout = 0;
5166
 
 
5167
 
        os_last_printout = time(NULL);
5168
 
}
5169
 
 
5170
 
#ifdef UNIV_DEBUG
5171
 
/**********************************************************************//**
5172
 
Checks that all slots in the system have been freed, that is, there are
5173
 
no pending io operations.
5174
 
@return TRUE if all free */
5175
 
UNIV_INTERN
5176
 
ibool
5177
 
os_aio_all_slots_free(void)
5178
 
/*=======================*/
5179
 
{
5180
 
        os_aio_array_t* array;
5181
 
        ulint           n_res   = 0;
5182
 
 
5183
 
        array = os_aio_read_array;
5184
 
 
5185
 
        os_mutex_enter(array->mutex);
5186
 
 
5187
 
        n_res += array->n_reserved;
5188
 
 
5189
 
        os_mutex_exit(array->mutex);
5190
 
 
5191
 
        array = os_aio_write_array;
5192
 
 
5193
 
        os_mutex_enter(array->mutex);
5194
 
 
5195
 
        n_res += array->n_reserved;
5196
 
 
5197
 
        os_mutex_exit(array->mutex);
5198
 
 
5199
 
        array = os_aio_ibuf_array;
5200
 
 
5201
 
        os_mutex_enter(array->mutex);
5202
 
 
5203
 
        n_res += array->n_reserved;
5204
 
 
5205
 
        os_mutex_exit(array->mutex);
5206
 
 
5207
 
        array = os_aio_log_array;
5208
 
 
5209
 
        os_mutex_enter(array->mutex);
5210
 
 
5211
 
        n_res += array->n_reserved;
5212
 
 
5213
 
        os_mutex_exit(array->mutex);
5214
 
 
5215
 
        array = os_aio_sync_array;
5216
 
 
5217
 
        os_mutex_enter(array->mutex);
5218
 
 
5219
 
        n_res += array->n_reserved;
5220
 
 
5221
 
        os_mutex_exit(array->mutex);
5222
 
 
5223
 
        if (n_res == 0) {
5224
 
 
5225
 
                return(TRUE);
5226
 
        }
5227
 
 
5228
 
        return(FALSE);
5229
 
}
5230
 
#endif /* UNIV_DEBUG */
5231
 
 
5232
 
#endif /* !UNIV_HOTBACKUP */