~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-09-15 20:24:31 UTC
  • mto: (1766.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1767.
  • Revision ID: brian@tangent.org-20100915202431-wbrrl4vg6rzjvdiu
Adding opt for optional schedulers and making them --plugin-add only.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
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.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
12
4
 
13
5
This program is free software; you can redistribute it and/or modify it under
14
6
the terms of the GNU General Public License as published by the Free Software
19
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
12
 
21
13
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
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
24
16
 
25
17
*****************************************************************************/
 
18
/***********************************************************************
 
19
 
 
20
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
21
Copyright (c) 2009, Percona Inc.
 
22
 
 
23
Portions of this file contain modifications contributed and copyrighted
 
24
by Percona Inc.. Those modifications are
 
25
gratefully acknowledged and are described briefly in the InnoDB
 
26
documentation. The contributions by Percona Inc. are incorporated with
 
27
their permission, and subject to the conditions contained in the file
 
28
COPYING.Percona.
 
29
 
 
30
This program is free software; you can redistribute it and/or modify it
 
31
under the terms of the GNU General Public License as published by the
 
32
Free Software Foundation; version 2 of the License.
 
33
 
 
34
This program is distributed in the hope that it will be useful, but
 
35
WITHOUT ANY WARRANTY; without even the implied warranty of
 
36
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 
37
Public License for more details.
 
38
 
 
39
You should have received a copy of the GNU General Public License along
 
40
with this program; if not, write to the Free Software Foundation, Inc.,
 
41
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
42
 
 
43
***********************************************************************/
26
44
 
27
45
/**************************************************//**
28
46
@file os/os0file.c
32
50
*******************************************************/
33
51
 
34
52
#include "os0file.h"
35
 
 
36
 
#ifdef UNIV_NONINL
37
 
#include "os0file.ic"
38
 
#endif
39
 
 
40
53
#include "ut0mem.h"
41
54
#include "srv0srv.h"
42
55
#include "srv0start.h"
57
70
# endif /* __WIN__ */
58
71
#endif /* !UNIV_HOTBACKUP */
59
72
 
60
 
#if defined(LINUX_NATIVE_AIO)
61
 
#include <libaio.h>
62
 
#endif
63
 
 
64
73
/* This specifies the file permissions InnoDB uses when it creates files in
65
74
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
66
75
my_umask */
91
100
/* In simulated aio, merge at most this many consecutive i/os */
92
101
#define OS_AIO_MERGE_N_CONSECUTIVE      64
93
102
 
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
 
**********************************************************************/
 
103
/** If this flag is TRUE, then we will use the native aio of the
 
104
OS (provided we compiled Innobase with it in), otherwise we will
 
105
use simulated aio we build below with threads */
 
106
 
 
107
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
147
108
 
148
109
/** Flag: enable debug printout for asynchronous i/o */
149
110
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
150
111
 
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
112
/** The asynchronous i/o array slot structure */
159
113
typedef struct os_aio_slot_struct       os_aio_slot_t;
160
114
 
185
139
                                        which pending aio operation was
186
140
                                        completed */
187
141
#ifdef WIN_ASYNC_IO
188
 
        HANDLE          handle;         /*!< handle object we need in the
 
142
        os_event_t      event;          /*!< event object we need in the
189
143
                                        OVERLAPPED struct */
190
144
        OVERLAPPED      control;        /*!< Windows control block for the
191
145
                                        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
146
#endif
197
147
};
198
148
 
218
168
                                array of pending aio requests. A
219
169
                                thread can wait separately for any one
220
170
                                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
171
        ulint           n_reserved;
226
172
                                /*!< Number of reserved slots in the
227
173
                                aio array outside the ibuf segment */
228
174
        os_aio_slot_t*  slots;  /*!< Pointer to the slots in the array */
229
175
#ifdef __WIN__
230
 
        HANDLE*         handles;
 
176
        os_native_event_t* native_events;
231
177
                                /*!< Pointer to an array of OS native
232
178
                                event handles where we copied the
233
179
                                handles from slots, in the same
235
181
                                WaitForMultipleObjects; used only in
236
182
                                Windows */
237
183
#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
184
};
251
185
 
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
186
/** Array of events used in simulated aio */
264
187
static os_event_t*      os_aio_segment_wait_events      = NULL;
265
188
 
306
229
 
307
230
/***********************************************************************//**
308
231
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. */
 
232
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
311
233
UNIV_INTERN
312
234
ulint
313
235
os_get_os_version(void)
325
247
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
326
248
                return(OS_WIN95);
327
249
        } 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;
 
250
                if (os_info.dwMajorVersion <= 4) {
 
251
                        return(OS_WINNT);
 
252
                } else {
 
253
                        return(OS_WIN2000);
340
254
                }
341
255
        } else {
342
256
                ut_error;
404
318
                                " software or another instance\n"
405
319
                                "InnoDB: of MySQL."
406
320
                                " 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
321
                } else {
421
322
                        fprintf(stderr,
422
323
                                "InnoDB: Some operating system error numbers"
438
339
        } else if (err == ERROR_SHARING_VIOLATION
439
340
                   || err == ERROR_LOCK_VIOLATION) {
440
341
                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
342
        } else {
447
343
                return(100 + err);
448
344
        }
493
389
 
494
390
        fflush(stderr);
495
391
 
496
 
        switch (err) {
497
 
        case ENOSPC:
 
392
        if (err == ENOSPC) {
498
393
                return(OS_FILE_DISK_FULL);
499
 
        case ENOENT:
 
394
        } else if (err == ENOENT) {
500
395
                return(OS_FILE_NOT_FOUND);
501
 
        case EEXIST:
 
396
        } else if (err == EEXIST) {
502
397
                return(OS_FILE_ALREADY_EXISTS);
503
 
        case EXDEV:
504
 
        case ENOTDIR:
505
 
        case EISDIR:
 
398
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
506
399
                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;
 
400
        } else {
 
401
                return(100 + err);
517
402
        }
518
 
        return(100 + err);
519
403
#endif
520
404
}
521
405
 
565
449
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
566
450
 
567
451
                return(TRUE);
568
 
        } else if (err == OS_FILE_AIO_INTERRUPTED) {
569
 
 
570
 
                return(TRUE);
571
452
        } else if (err == OS_FILE_ALREADY_EXISTS
572
453
                   || err == OS_FILE_PATH_ERROR) {
573
454
 
576
457
 
577
458
                os_thread_sleep(10000000);  /* 10 sec */
578
459
                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
460
        } else {
588
461
                if (name) {
589
462
                        fprintf(stderr, "InnoDB: File name %s\n", name);
634
507
 
635
508
#undef USE_FILE_LOCK
636
509
#define USE_FILE_LOCK
637
 
#if defined(UNIV_HOTBACKUP) || defined(__WIN__)
 
510
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
638
511
/* InnoDB Hot Backup does not lock the data files.
639
512
 * On Windows, mandatory locking is used.
640
513
 */
684
557
{
685
558
        ulint   i;
686
559
 
687
 
        os_file_count_mutex = os_mutex_create();
 
560
        os_file_count_mutex = os_mutex_create(NULL);
688
561
 
689
562
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
690
 
                os_file_seek_mutexes[i] = os_mutex_create();
 
563
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
691
564
        }
692
565
}
693
566
 
694
567
/***********************************************************************//**
695
568
Creates a temporary file.  This function is like tmpfile(3), but
696
569
the temporary file is created in the MySQL temporary directory.
 
570
On Netware, this function is like tmpfile(3), because the C run-time
 
571
library of Netware does not expose the delete-on-close flag.
697
572
@return temporary file handle, or NULL on error */
698
573
UNIV_INTERN
699
574
FILE*
700
575
os_file_create_tmpfile(void)
701
576
/*========================*/
702
577
{
 
578
#ifdef __NETWARE__
 
579
        FILE*   file    = tmpfile();
 
580
#else /* __NETWARE__ */
703
581
        FILE*   file    = NULL;
704
582
        int     fd      = innobase_mysql_tmpfile();
705
583
 
706
584
        if (fd >= 0) {
707
585
                file = fdopen(fd, "w+b");
708
586
        }
 
587
#endif /* __NETWARE__ */
709
588
 
710
589
        if (!file) {
711
590
                ut_print_timestamp(stderr);
712
591
                fprintf(stderr,
713
592
                        "  InnoDB: Error: unable to create temporary file;"
714
593
                        " errno: %d\n", errno);
 
594
#ifndef __NETWARE__
715
595
                if (fd >= 0) {
716
596
                        close(fd);
717
597
                }
 
598
#endif /* !__NETWARE__ */
718
599
        }
719
600
 
720
601
        return(file);
900
781
#ifdef HAVE_READDIR_R
901
782
        ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
902
783
 
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
 
           ) {
 
784
        if (ret != 0) {
912
785
                fprintf(stderr,
913
786
                        "InnoDB: cannot read directory %s, error %lu\n",
914
787
                        dirname, (ulong)ret);
947
820
        ret = stat(full_path, &statinfo);
948
821
 
949
822
        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
823
                os_file_handle_error_no_exit(full_path, "stat");
968
824
 
969
825
                ut_free(full_path);
1035
891
}
1036
892
 
1037
893
/****************************************************************//**
1038
 
NOTE! Use the corresponding macro os_file_create_simple(), not directly
1039
 
this function!
1040
894
A simple function to open or create a file.
1041
895
@return own: handle to the file, not defined if error, error number
1042
896
can be retrieved with os_file_get_last_error */
1043
897
UNIV_INTERN
1044
898
os_file_t
1045
 
os_file_create_simple_func(
1046
 
/*=======================*/
 
899
os_file_create_simple(
 
900
/*==================*/
1047
901
        const char*     name,   /*!< in: name of the file or path as a
1048
902
                                null-terminated string */
1049
903
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
1178
1032
}
1179
1033
 
1180
1034
/****************************************************************//**
1181
 
NOTE! Use the corresponding macro
1182
 
os_file_create_simple_no_error_handling(), not directly this function!
1183
1035
A simple function to open or create a file.
1184
1036
@return own: handle to the file, not defined if error, error number
1185
1037
can be retrieved with os_file_get_last_error */
1186
1038
UNIV_INTERN
1187
1039
os_file_t
1188
 
os_file_create_simple_no_error_handling_func(
1189
 
/*=========================================*/
 
1040
os_file_create_simple_no_error_handling(
 
1041
/*====================================*/
1190
1042
        const char*     name,   /*!< in: name of the file or path as a
1191
1043
                                null-terminated string */
1192
1044
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1339
1191
}
1340
1192
 
1341
1193
/****************************************************************//**
1342
 
NOTE! Use the corresponding macro os_file_create(), not directly
1343
 
this function!
1344
1194
Opens an existing file or creates a new.
1345
1195
@return own: handle to the file, not defined if error, error number
1346
1196
can be retrieved with os_file_get_last_error */
1347
1197
UNIV_INTERN
1348
1198
os_file_t
1349
 
os_file_create_func(
1350
 
/*================*/
 
1199
os_file_create(
 
1200
/*===========*/
1351
1201
        const char*     name,   /*!< in: name of the file or path as a
1352
1202
                                null-terminated string */
1353
1203
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1397
1247
                buffering of writes in the OS */
1398
1248
                attributes = 0;
1399
1249
#ifdef WIN_ASYNC_IO
1400
 
                if (srv_use_native_aio) {
 
1250
                if (os_aio_use_native_aio) {
1401
1251
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
1402
1252
                }
1403
1253
#endif
1404
1254
#ifdef UNIV_NON_BUFFERED_IO
1405
 
# ifndef UNIV_HOTBACKUP
1406
1255
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
1407
1256
                        /* Do not use unbuffered i/o to log files because
1408
1257
                        value 2 denotes that we do not flush the log at every
1411
1260
                           == SRV_WIN_IO_UNBUFFERED) {
1412
1261
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
1413
1262
                }
1414
 
# else /* !UNIV_HOTBACKUP */
1415
 
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
1416
 
# endif /* !UNIV_HOTBACKUP */
1417
 
#endif /* UNIV_NON_BUFFERED_IO */
 
1263
#endif
1418
1264
        } else if (purpose == OS_FILE_NORMAL) {
1419
1265
                attributes = 0;
1420
1266
#ifdef UNIV_NON_BUFFERED_IO
1421
 
# ifndef UNIV_HOTBACKUP
1422
1267
                if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
1423
1268
                        /* Do not use unbuffered i/o to log files because
1424
1269
                        value 2 denotes that we do not flush the log at every
1427
1272
                           == SRV_WIN_IO_UNBUFFERED) {
1428
1273
                        attributes = attributes | FILE_FLAG_NO_BUFFERING;
1429
1274
                }
1430
 
# else /* !UNIV_HOTBACKUP */
1431
 
                attributes = attributes | FILE_FLAG_NO_BUFFERING;
1432
 
# endif /* !UNIV_HOTBACKUP */
1433
 
#endif /* UNIV_NON_BUFFERED_IO */
 
1275
#endif
1434
1276
        } else {
1435
1277
                attributes = 0;
1436
1278
                ut_error;
1460
1302
 
1461
1303
                /* When srv_file_per_table is on, file creation failure may not
1462
1304
                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 */
 
1305
                case of unknown errors. */
1468
1306
                if (srv_file_per_table) {
1469
1307
                        retry = os_file_handle_error_no_exit(name,
1470
1308
                                                create_mode == OS_FILE_CREATE ?
1488
1326
        int             create_flag;
1489
1327
        ibool           retry;
1490
1328
        const char*     mode_str        = NULL;
 
1329
        const char*     type_str        = NULL;
 
1330
        const char*     purpose_str     = NULL;
1491
1331
 
1492
1332
try_again:
1493
1333
        ut_a(name);
1507
1347
                ut_error;
1508
1348
        }
1509
1349
 
1510
 
        ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
1511
 
        ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL);
1512
 
 
 
1350
        if (type == OS_LOG_FILE) {
 
1351
                type_str = "LOG";
 
1352
        } else if (type == OS_DATA_FILE) {
 
1353
                type_str = "DATA";
 
1354
        } else {
 
1355
                ut_error;
 
1356
        }
 
1357
 
 
1358
        if (purpose == OS_FILE_AIO) {
 
1359
                purpose_str = "AIO";
 
1360
        } else if (purpose == OS_FILE_NORMAL) {
 
1361
                purpose_str = "NORMAL";
 
1362
        } else {
 
1363
                ut_error;
 
1364
        }
 
1365
 
 
1366
#if 0
 
1367
        fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n",
 
1368
                name, mode_str, type_str, purpose_str);
 
1369
#endif
1513
1370
#ifdef O_SYNC
1514
1371
        /* We let O_SYNC only affect log files; note that we map O_DSYNC to
1515
1372
        O_SYNC because the datasync options seemed to corrupt files in 2001
1532
1389
 
1533
1390
                /* When srv_file_per_table is on, file creation failure may not
1534
1391
                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 */
 
1392
                case of unknown errors. */
1540
1393
                if (srv_file_per_table) {
1541
1394
                        retry = os_file_handle_error_no_exit(name,
1542
1395
                                                create_mode == OS_FILE_CREATE ?
1721
1574
}
1722
1575
 
1723
1576
/***********************************************************************//**
1724
 
NOTE! Use the corresponding macro os_file_rename(), not directly this function!
1725
1577
Renames a file (can also move it to another directory). It is safest that the
1726
1578
file is closed before calling this function.
1727
1579
@return TRUE if success */
1728
1580
UNIV_INTERN
1729
1581
ibool
1730
 
os_file_rename_func(
1731
 
/*================*/
 
1582
os_file_rename(
 
1583
/*===========*/
1732
1584
        const char*     oldpath,/*!< in: old file path as a null-terminated
1733
1585
                                string */
1734
1586
        const char*     newpath)/*!< in: new file path */
1761
1613
}
1762
1614
 
1763
1615
/***********************************************************************//**
1764
 
NOTE! Use the corresponding macro os_file_close(), not directly this function!
1765
1616
Closes a file handle. In case of error, error number can be retrieved with
1766
1617
os_file_get_last_error.
1767
1618
@return TRUE if success */
1768
1619
UNIV_INTERN
1769
1620
ibool
1770
 
os_file_close_func(
1771
 
/*===============*/
 
1621
os_file_close(
 
1622
/*==========*/
1772
1623
        os_file_t       file)   /*!< in, own: handle to a file */
1773
1624
{
1774
1625
#ifdef __WIN__
2064
1915
#endif /* !__WIN__ */
2065
1916
 
2066
1917
/***********************************************************************//**
2067
 
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
2068
1918
Flushes the write buffers of a given file to the disk.
2069
1919
@return TRUE if success */
2070
1920
UNIV_INTERN
2071
1921
ibool
2072
 
os_file_flush_func(
2073
 
/*===============*/
 
1922
os_file_flush(
 
1923
/*==========*/
2074
1924
        os_file_t       file)   /*!< in, own: handle to a file */
2075
1925
{
2076
1926
#ifdef __WIN__
2179
2029
                                offset */
2180
2030
{
2181
2031
        off_t   offs;
2182
 
#if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
2183
2032
        ssize_t n_bytes;
2184
 
#endif /* HAVE_PREAD && !HAVE_BROKEN_PREAD */
2185
2033
 
2186
2034
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2187
2035
 
2220
2068
        {
2221
2069
                off_t   ret_offset;
2222
2070
                ssize_t ret;
2223
 
#ifndef UNIV_HOTBACKUP
2224
2071
                ulint   i;
2225
 
#endif /* !UNIV_HOTBACKUP */
2226
2072
 
2227
2073
                os_mutex_enter(os_file_count_mutex);
2228
2074
                os_n_pending_reads++;
2229
2075
                os_mutex_exit(os_file_count_mutex);
2230
2076
 
2231
 
#ifndef UNIV_HOTBACKUP
2232
2077
                /* Protect the seek / read operation with a mutex */
2233
2078
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2234
2079
 
2235
2080
                os_mutex_enter(os_file_seek_mutexes[i]);
2236
 
#endif /* !UNIV_HOTBACKUP */
2237
2081
 
2238
2082
                ret_offset = lseek(file, offs, SEEK_SET);
2239
2083
 
2243
2087
                        ret = read(file, buf, (ssize_t)n);
2244
2088
                }
2245
2089
 
2246
 
#ifndef UNIV_HOTBACKUP
2247
2090
                os_mutex_exit(os_file_seek_mutexes[i]);
2248
 
#endif /* !UNIV_HOTBACKUP */
2249
2091
 
2250
2092
                os_mutex_enter(os_file_count_mutex);
2251
2093
                os_n_pending_reads--;
2323
2165
#else
2324
2166
        {
2325
2167
                off_t   ret_offset;
2326
 
# ifndef UNIV_HOTBACKUP
2327
2168
                ulint   i;
2328
 
# endif /* !UNIV_HOTBACKUP */
2329
2169
 
2330
2170
                os_mutex_enter(os_file_count_mutex);
2331
2171
                os_n_pending_writes++;
2332
2172
                os_mutex_exit(os_file_count_mutex);
2333
2173
 
2334
 
# ifndef UNIV_HOTBACKUP
2335
2174
                /* Protect the seek / write operation with a mutex */
2336
2175
                i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2337
2176
 
2338
2177
                os_mutex_enter(os_file_seek_mutexes[i]);
2339
 
# endif /* UNIV_HOTBACKUP */
2340
2178
 
2341
2179
                ret_offset = lseek(file, offs, SEEK_SET);
2342
2180
 
2362
2200
# endif /* UNIV_DO_FLUSH */
2363
2201
 
2364
2202
func_exit:
2365
 
# ifndef UNIV_HOTBACKUP
2366
2203
                os_mutex_exit(os_file_seek_mutexes[i]);
2367
 
# endif /* !UNIV_HOTBACKUP */
2368
2204
 
2369
2205
                os_mutex_enter(os_file_count_mutex);
2370
2206
                os_n_pending_writes--;
2377
2213
#endif
2378
2214
 
2379
2215
/*******************************************************************//**
2380
 
NOTE! Use the corresponding macro os_file_read(), not directly this
2381
 
function!
2382
2216
Requests a synchronous positioned read operation.
2383
2217
@return TRUE if request was successful, FALSE if fail */
2384
2218
UNIV_INTERN
2385
2219
ibool
2386
 
os_file_read_func(
2387
 
/*==============*/
 
2220
os_file_read(
 
2221
/*=========*/
2388
2222
        os_file_t       file,   /*!< in: handle to a file */
2389
2223
        void*           buf,    /*!< in: buffer where to read */
2390
2224
        ulint           offset, /*!< in: least significant 32 bits of file
2400
2234
        DWORD           low;
2401
2235
        DWORD           high;
2402
2236
        ibool           retry;
2403
 
#ifndef UNIV_HOTBACKUP
2404
2237
        ulint           i;
2405
 
#endif /* !UNIV_HOTBACKUP */
2406
2238
 
2407
2239
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2408
2240
 
2421
2253
        os_n_pending_reads++;
2422
2254
        os_mutex_exit(os_file_count_mutex);
2423
2255
 
2424
 
#ifndef UNIV_HOTBACKUP
2425
2256
        /* Protect the seek / read operation with a mutex */
2426
2257
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2427
2258
 
2428
2259
        os_mutex_enter(os_file_seek_mutexes[i]);
2429
 
#endif /* !UNIV_HOTBACKUP */
2430
2260
 
2431
2261
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2432
2262
 
2433
2263
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2434
2264
 
2435
 
#ifndef UNIV_HOTBACKUP
2436
2265
                os_mutex_exit(os_file_seek_mutexes[i]);
2437
 
#endif /* !UNIV_HOTBACKUP */
2438
2266
 
2439
2267
                os_mutex_enter(os_file_count_mutex);
2440
2268
                os_n_pending_reads--;
2445
2273
 
2446
2274
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2447
2275
 
2448
 
#ifndef UNIV_HOTBACKUP
2449
2276
        os_mutex_exit(os_file_seek_mutexes[i]);
2450
 
#endif /* !UNIV_HOTBACKUP */
2451
2277
 
2452
2278
        os_mutex_enter(os_file_count_mutex);
2453
2279
        os_n_pending_reads--;
2456
2282
        if (ret && len == n) {
2457
2283
                return(TRUE);
2458
2284
        }
2459
 
#else /* __WIN__ */
 
2285
#else
2460
2286
        ibool   retry;
2461
2287
        ssize_t ret;
2462
2288
 
2475
2301
                "InnoDB: Was only able to read %ld.\n",
2476
2302
                (ulong)n, (ulong)offset_high,
2477
2303
                (ulong)offset, (long)ret);
2478
 
#endif /* __WIN__ */
 
2304
#endif
2479
2305
#ifdef __WIN__
2480
2306
error_handling:
2481
2307
#endif
2502
2328
}
2503
2329
 
2504
2330
/*******************************************************************//**
2505
 
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
2506
 
not directly this function!
2507
2331
Requests a synchronous positioned read operation. This function does not do
2508
2332
any error handling. In case of error it returns FALSE.
2509
2333
@return TRUE if request was successful, FALSE if fail */
2510
2334
UNIV_INTERN
2511
2335
ibool
2512
 
os_file_read_no_error_handling_func(
2513
 
/*================================*/
 
2336
os_file_read_no_error_handling(
 
2337
/*===========================*/
2514
2338
        os_file_t       file,   /*!< in: handle to a file */
2515
2339
        void*           buf,    /*!< in: buffer where to read */
2516
2340
        ulint           offset, /*!< in: least significant 32 bits of file
2526
2350
        DWORD           low;
2527
2351
        DWORD           high;
2528
2352
        ibool           retry;
2529
 
#ifndef UNIV_HOTBACKUP
2530
2353
        ulint           i;
2531
 
#endif /* !UNIV_HOTBACKUP */
2532
2354
 
2533
2355
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2534
2356
 
2547
2369
        os_n_pending_reads++;
2548
2370
        os_mutex_exit(os_file_count_mutex);
2549
2371
 
2550
 
#ifndef UNIV_HOTBACKUP
2551
2372
        /* Protect the seek / read operation with a mutex */
2552
2373
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2553
2374
 
2554
2375
        os_mutex_enter(os_file_seek_mutexes[i]);
2555
 
#endif /* !UNIV_HOTBACKUP */
2556
2376
 
2557
2377
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2558
2378
 
2559
2379
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2560
2380
 
2561
 
#ifndef UNIV_HOTBACKUP
2562
2381
                os_mutex_exit(os_file_seek_mutexes[i]);
2563
 
#endif /* !UNIV_HOTBACKUP */
2564
2382
 
2565
2383
                os_mutex_enter(os_file_count_mutex);
2566
2384
                os_n_pending_reads--;
2571
2389
 
2572
2390
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2573
2391
 
2574
 
#ifndef UNIV_HOTBACKUP
2575
2392
        os_mutex_exit(os_file_seek_mutexes[i]);
2576
 
#endif /* !UNIV_HOTBACKUP */
2577
2393
 
2578
2394
        os_mutex_enter(os_file_count_mutex);
2579
2395
        os_n_pending_reads--;
2582
2398
        if (ret && len == n) {
2583
2399
                return(TRUE);
2584
2400
        }
2585
 
#else /* __WIN__ */
 
2401
#else
2586
2402
        ibool   retry;
2587
2403
        ssize_t ret;
2588
2404
 
2595
2411
 
2596
2412
                return(TRUE);
2597
2413
        }
2598
 
#endif /* __WIN__ */
 
2414
#endif
2599
2415
#ifdef __WIN__
2600
2416
error_handling:
2601
2417
#endif
2632
2448
}
2633
2449
 
2634
2450
/*******************************************************************//**
2635
 
NOTE! Use the corresponding macro os_file_write(), not directly
2636
 
this function!
2637
2451
Requests a synchronous write operation.
2638
2452
@return TRUE if request was successful, FALSE if fail */
2639
2453
UNIV_INTERN
2640
2454
ibool
2641
 
os_file_write_func(
2642
 
/*===============*/
 
2455
os_file_write(
 
2456
/*==========*/
2643
2457
        const char*     name,   /*!< in: name of the file or path as a
2644
2458
                                null-terminated string */
2645
2459
        os_file_t       file,   /*!< in: handle to a file */
2656
2470
        DWORD           ret2;
2657
2471
        DWORD           low;
2658
2472
        DWORD           high;
 
2473
        ulint           i;
2659
2474
        ulint           n_retries       = 0;
2660
2475
        ulint           err;
2661
 
#ifndef UNIV_HOTBACKUP
2662
 
        ulint           i;
2663
 
#endif /* !UNIV_HOTBACKUP */
2664
2476
 
2665
2477
        ut_a((offset & 0xFFFFFFFF) == offset);
2666
2478
 
2677
2489
        os_n_pending_writes++;
2678
2490
        os_mutex_exit(os_file_count_mutex);
2679
2491
 
2680
 
#ifndef UNIV_HOTBACKUP
2681
2492
        /* Protect the seek / write operation with a mutex */
2682
2493
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2683
2494
 
2684
2495
        os_mutex_enter(os_file_seek_mutexes[i]);
2685
 
#endif /* !UNIV_HOTBACKUP */
2686
2496
 
2687
2497
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2688
2498
 
2689
2499
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2690
2500
 
2691
 
#ifndef UNIV_HOTBACKUP
2692
2501
                os_mutex_exit(os_file_seek_mutexes[i]);
2693
 
#endif /* !UNIV_HOTBACKUP */
2694
2502
 
2695
2503
                os_mutex_enter(os_file_count_mutex);
2696
2504
                os_n_pending_writes--;
2724
2532
        }
2725
2533
# endif /* UNIV_DO_FLUSH */
2726
2534
 
2727
 
#ifndef UNIV_HOTBACKUP
2728
2535
        os_mutex_exit(os_file_seek_mutexes[i]);
2729
 
#endif /* !UNIV_HOTBACKUP */
2730
2536
 
2731
2537
        os_mutex_enter(os_file_count_mutex);
2732
2538
        os_n_pending_writes--;
3098
2904
        return((array->slots) + index);
3099
2905
}
3100
2906
 
3101
 
#if defined(LINUX_NATIVE_AIO)
3102
 
/******************************************************************//**
3103
 
Creates an io_context for native linux AIO.
3104
 
@return TRUE on success. */
3105
 
static
3106
 
ibool
3107
 
os_aio_linux_create_io_ctx(
3108
 
/*=======================*/
3109
 
        ulint           max_events,     /*!< in: number of events. */
3110
 
        io_context_t*   io_ctx)         /*!< out: io_ctx to initialize. */
3111
 
{
3112
 
        int     ret;
3113
 
        ulint   retries = 0;
3114
 
 
3115
 
retry:
3116
 
        memset(io_ctx, 0x0, sizeof(*io_ctx));
3117
 
 
3118
 
        /* Initialize the io_ctx. Tell it how many pending
3119
 
        IO requests this context will handle. */
3120
 
 
3121
 
        ret = io_setup(max_events, io_ctx);
3122
 
        if (ret == 0) {
3123
 
#if defined(UNIV_AIO_DEBUG)
3124
 
                fprintf(stderr,
3125
 
                        "InnoDB: Linux native AIO:"
3126
 
                        " initialized io_ctx for segment\n");
3127
 
#endif
3128
 
                /* Success. Return now. */
3129
 
                return(TRUE);
3130
 
        }
3131
 
 
3132
 
        /* If we hit EAGAIN we'll make a few attempts before failing. */
3133
 
 
3134
 
        switch (ret) {
3135
 
        case -EAGAIN:
3136
 
                if (retries == 0) {
3137
 
                        /* First time around. */
3138
 
                        ut_print_timestamp(stderr);
3139
 
                        fprintf(stderr,
3140
 
                                "  InnoDB: Warning: io_setup() failed"
3141
 
                                " with EAGAIN. Will make %d attempts"
3142
 
                                " before giving up.\n",
3143
 
                                OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
3144
 
                }
3145
 
 
3146
 
                if (retries < OS_AIO_IO_SETUP_RETRY_ATTEMPTS) {
3147
 
                        ++retries;
3148
 
                        fprintf(stderr,
3149
 
                                "InnoDB: Warning: io_setup() attempt"
3150
 
                                " %lu failed.\n",
3151
 
                                retries);
3152
 
                        os_thread_sleep(OS_AIO_IO_SETUP_RETRY_SLEEP);
3153
 
                        goto retry;
3154
 
                }
3155
 
 
3156
 
                /* Have tried enough. Better call it a day. */
3157
 
                ut_print_timestamp(stderr);
3158
 
                fprintf(stderr,
3159
 
                        "  InnoDB: Error: io_setup() failed"
3160
 
                        " with EAGAIN after %d attempts.\n",
3161
 
                        OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
3162
 
                break;
3163
 
 
3164
 
        case -ENOSYS:
3165
 
                ut_print_timestamp(stderr);
3166
 
                fprintf(stderr,
3167
 
                        "  InnoDB: Error: Linux Native AIO interface"
3168
 
                        " is not supported on this platform. Please"
3169
 
                        " check your OS documentation and install"
3170
 
                        " appropriate binary of InnoDB.\n");
3171
 
 
3172
 
                break;
3173
 
 
3174
 
        default:
3175
 
                ut_print_timestamp(stderr);
3176
 
                fprintf(stderr,
3177
 
                        "  InnoDB: Error: Linux Native AIO setup"
3178
 
                        " returned following error[%d]\n", -ret);
3179
 
                break;
3180
 
        }
3181
 
 
3182
 
        fprintf(stderr,
3183
 
                "InnoDB: You can disable Linux Native AIO by"
3184
 
                " setting innodb_native_aio = off in my.cnf\n");
3185
 
        return(FALSE);
3186
 
}
3187
 
#endif /* LINUX_NATIVE_AIO */
3188
 
 
3189
 
/******************************************************************//**
3190
 
Creates an aio wait array. Note that we return NULL in case of failure.
3191
 
We don't care about freeing memory here because we assume that a
3192
 
failure will result in server refusing to start up.
3193
 
@return own: aio array, NULL on failure */
 
2907
/************************************************************************//**
 
2908
Creates an aio wait array.
 
2909
@return own: aio array */
3194
2910
static
3195
2911
os_aio_array_t*
3196
2912
os_aio_array_create(
3197
2913
/*================*/
3198
 
        ulint   n,              /*!< in: maximum number of pending aio
3199
 
                                operations allowed; n must be
3200
 
                                divisible by n_segments */
 
2914
        ulint   n,              /*!< in: maximum number of pending aio operations
 
2915
                                allowed; n must be divisible by n_segments */
3201
2916
        ulint   n_segments)     /*!< in: number of segments in the aio array */
3202
2917
{
3203
2918
        os_aio_array_t* array;
3205
2920
        os_aio_slot_t*  slot;
3206
2921
#ifdef WIN_ASYNC_IO
3207
2922
        OVERLAPPED*     over;
3208
 
#elif defined(LINUX_NATIVE_AIO)
3209
 
        struct io_event*        io_event = NULL;
3210
2923
#endif
3211
2924
        ut_a(n > 0);
3212
2925
        ut_a(n_segments > 0);
3213
2926
 
3214
2927
        array = ut_malloc(sizeof(os_aio_array_t));
3215
2928
 
3216
 
        array->mutex            = os_mutex_create();
 
2929
        array->mutex            = os_mutex_create(NULL);
3217
2930
        array->not_full         = os_event_create(NULL);
3218
2931
        array->is_empty         = os_event_create(NULL);
3219
2932
 
3222
2935
        array->n_slots          = n;
3223
2936
        array->n_segments       = n_segments;
3224
2937
        array->n_reserved       = 0;
3225
 
        array->cur_seg          = 0;
3226
2938
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
3227
2939
#ifdef __WIN__
3228
 
        array->handles          = ut_malloc(n * sizeof(HANDLE));
 
2940
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
3229
2941
#endif
3230
 
 
3231
 
#if defined(LINUX_NATIVE_AIO)
3232
 
        array->aio_ctx = NULL;
3233
 
        array->aio_events = NULL;
3234
 
 
3235
 
        /* If we are not using native aio interface then skip this
3236
 
        part of initialization. */
3237
 
        if (!srv_use_native_aio) {
3238
 
                goto skip_native_aio;
3239
 
        }
3240
 
 
3241
 
        /* Initialize the io_context array. One io_context
3242
 
        per segment in the array. */
3243
 
 
3244
 
        array->aio_ctx = ut_malloc(n_segments *
3245
 
                                   sizeof(*array->aio_ctx));
3246
 
        for (i = 0; i < n_segments; ++i) {
3247
 
                if (!os_aio_linux_create_io_ctx(n/n_segments,
3248
 
                                           &array->aio_ctx[i])) {
3249
 
                        /* If something bad happened during aio setup
3250
 
                        we should call it a day and return right away.
3251
 
                        We don't care about any leaks because a failure
3252
 
                        to initialize the io subsystem means that the
3253
 
                        server (or atleast the innodb storage engine)
3254
 
                        is not going to startup. */
3255
 
                        return(NULL);
3256
 
                }
3257
 
        }
3258
 
 
3259
 
        /* Initialize the event array. One event per slot. */
3260
 
        io_event = ut_malloc(n * sizeof(*io_event));
3261
 
        memset(io_event, 0x0, sizeof(*io_event) * n);
3262
 
        array->aio_events = io_event;
3263
 
 
3264
 
skip_native_aio:
3265
 
#endif /* LINUX_NATIVE_AIO */
3266
2942
        for (i = 0; i < n; i++) {
3267
2943
                slot = os_aio_array_get_nth_slot(array, i);
3268
2944
 
3269
2945
                slot->pos = i;
3270
2946
                slot->reserved = FALSE;
3271
2947
#ifdef WIN_ASYNC_IO
3272
 
                slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
 
2948
                slot->event = os_event_create(NULL);
3273
2949
 
3274
2950
                over = &(slot->control);
3275
2951
 
3276
 
                over->hEvent = slot->handle;
3277
 
 
3278
 
                *((array->handles) + i) = over->hEvent;
3279
 
 
3280
 
#elif defined(LINUX_NATIVE_AIO)
3281
 
 
3282
 
                memset(&slot->control, 0x0, sizeof(slot->control));
3283
 
                slot->n_bytes = 0;
3284
 
                slot->ret = 0;
 
2952
                over->hEvent = slot->event->handle;
 
2953
 
 
2954
                *((array->native_events) + i) = over->hEvent;
3285
2955
#endif
3286
2956
        }
3287
2957
 
3288
2958
        return(array);
3289
2959
}
3290
2960
 
3291
 
/************************************************************************//**
3292
 
Frees an aio wait array. */
3293
 
static
3294
 
void
3295
 
os_aio_array_free(
3296
 
/*==============*/
3297
 
        os_aio_array_t* array)  /*!< in, own: array to free */
3298
 
{
3299
 
#ifdef WIN_ASYNC_IO
3300
 
        ulint   i;
3301
 
 
3302
 
        for (i = 0; i < array->n_slots; i++) {
3303
 
                os_aio_slot_t*  slot = os_aio_array_get_nth_slot(array, i);
3304
 
                CloseHandle(slot->handle);
3305
 
        }
3306
 
#endif /* WIN_ASYNC_IO */
3307
 
 
3308
 
#ifdef __WIN__
3309
 
        ut_free(array->handles);
3310
 
#endif /* __WIN__ */
3311
 
        os_mutex_free(array->mutex);
3312
 
        os_event_free(array->not_full);
3313
 
        os_event_free(array->is_empty);
3314
 
 
3315
 
#if defined(LINUX_NATIVE_AIO)
3316
 
        if (srv_use_native_aio) {
3317
 
                ut_free(array->aio_events);
3318
 
                ut_free(array->aio_ctx);
3319
 
        }
3320
 
#endif /* LINUX_NATIVE_AIO */
3321
 
 
3322
 
        ut_free(array->slots);
3323
 
        ut_free(array);
3324
 
}
3325
 
 
3326
2961
/***********************************************************************
3327
2962
Initializes the asynchronous io system. Creates one array each for ibuf
3328
2963
and log i/o. Also creates one array each for read and write where each
3331
2966
segment in these arrays. This function also creates the sync array.
3332
2967
No i/o handler thread needs to be created for that */
3333
2968
UNIV_INTERN
3334
 
ibool
 
2969
void
3335
2970
os_aio_init(
3336
2971
/*========*/
3337
2972
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3356
2991
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3357
2992
 
3358
2993
        os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
3359
 
        if (os_aio_ibuf_array == NULL) {
3360
 
                goto err_exit;
3361
 
        }
3362
2994
 
3363
2995
        srv_io_thread_function[0] = "insert buffer thread";
3364
2996
 
3365
2997
        os_aio_log_array = os_aio_array_create(n_per_seg, 1);
3366
 
        if (os_aio_log_array == NULL) {
3367
 
                goto err_exit;
3368
 
        }
3369
2998
 
3370
2999
        srv_io_thread_function[1] = "log thread";
3371
3000
 
3372
3001
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3373
3002
                                                n_read_segs);
3374
 
        if (os_aio_read_array == NULL) {
3375
 
                goto err_exit;
3376
 
        }
3377
 
 
3378
3003
        for (i = 2; i < 2 + n_read_segs; i++) {
3379
3004
                ut_a(i < SRV_MAX_N_IO_THREADS);
3380
3005
                srv_io_thread_function[i] = "read thread";
3382
3007
 
3383
3008
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3384
3009
                                                 n_write_segs);
3385
 
        if (os_aio_write_array == NULL) {
3386
 
                goto err_exit;
3387
 
        }
3388
 
 
3389
3010
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3390
3011
                ut_a(i < SRV_MAX_N_IO_THREADS);
3391
3012
                srv_io_thread_function[i] = "write thread";
3392
3013
        }
3393
3014
 
3394
3015
        os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
3395
 
        if (os_aio_sync_array == NULL) {
3396
 
                goto err_exit;
3397
 
        }
3398
 
 
3399
3016
 
3400
3017
        os_aio_n_segments = n_segments;
3401
3018
 
3409
3026
 
3410
3027
        os_last_printout = time(NULL);
3411
3028
 
3412
 
        return(TRUE);
3413
 
 
3414
 
err_exit:
3415
 
        return(FALSE);
3416
 
 
3417
 
}
3418
 
 
3419
 
/***********************************************************************
3420
 
Frees the asynchronous io system. */
3421
 
UNIV_INTERN
3422
 
void
3423
 
os_aio_free(void)
3424
 
/*=============*/
3425
 
{
3426
 
        ulint   i;
3427
 
 
3428
 
        os_aio_array_free(os_aio_ibuf_array);
3429
 
        os_aio_ibuf_array = NULL;
3430
 
        os_aio_array_free(os_aio_log_array);
3431
 
        os_aio_log_array = NULL;
3432
 
        os_aio_array_free(os_aio_read_array);
3433
 
        os_aio_read_array = NULL;
3434
 
        os_aio_array_free(os_aio_write_array);
3435
 
        os_aio_write_array = NULL;
3436
 
        os_aio_array_free(os_aio_sync_array);
3437
 
        os_aio_sync_array = NULL;
3438
 
 
3439
 
        for (i = 0; i < os_aio_n_segments; i++) {
3440
 
                os_event_free(os_aio_segment_wait_events[i]);
3441
 
        }
3442
 
 
3443
 
        ut_free(os_aio_segment_wait_events);
3444
 
        os_aio_segment_wait_events = 0;
3445
 
        os_aio_n_segments = 0;
3446
3029
}
3447
3030
 
3448
3031
#ifdef WIN_ASYNC_IO
3459
3042
 
3460
3043
        for (i = 0; i < array->n_slots; i++) {
3461
3044
 
3462
 
                SetEvent((array->slots + i)->handle);
 
3045
                os_event_set((array->slots + i)->event);
3463
3046
        }
3464
3047
}
3465
3048
#endif
3480
3063
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3481
3064
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3482
3065
        os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
3483
 
 
3484
 
#elif defined(LINUX_NATIVE_AIO)
3485
 
 
3486
 
        /* When using native AIO interface the io helper threads
3487
 
        wait on io_getevents with a timeout value of 500ms. At
3488
 
        each wake up these threads check the server status.
3489
 
        No need to do anything to wake them up. */
3490
 
 
3491
 
        if (srv_use_native_aio) {
3492
 
                return;
3493
 
        }
3494
 
        /* Fall through to simulated AIO handler wakeup if we are
3495
 
        not using native AIO. */
3496
3066
#endif
3497
3067
        /* This loop wakes up all simulated ai/o threads */
3498
3068
 
3610
3180
                                offset */
3611
3181
        ulint           len)    /*!< in: length of the block to read or write */
3612
3182
{
3613
 
        os_aio_slot_t*  slot = NULL;
 
3183
        os_aio_slot_t*  slot;
3614
3184
#ifdef WIN_ASYNC_IO
3615
3185
        OVERLAPPED*     control;
3616
 
 
3617
 
#elif defined(LINUX_NATIVE_AIO)
3618
 
 
3619
 
        struct iocb*    iocb;
3620
 
        off_t           aio_offset;
3621
 
 
3622
3186
#endif
3623
3187
        ulint           i;
3624
 
        ulint           counter;
3625
3188
        ulint           slots_per_seg;
3626
3189
        ulint           local_seg;
3627
3190
 
3640
3203
        if (array->n_reserved == array->n_slots) {
3641
3204
                os_mutex_exit(array->mutex);
3642
3205
 
3643
 
                if (!srv_use_native_aio) {
 
3206
                if (!os_aio_use_native_aio) {
3644
3207
                        /* If the handler threads are suspended, wake them
3645
3208
                        so that we get more slots */
3646
3209
 
3652
3215
                goto loop;
3653
3216
        }
3654
3217
 
3655
 
        /* We start our search for an available slot from our preferred
3656
 
        local segment and do a full scan of the array. We are
3657
 
        guaranteed to find a slot in full scan. */
3658
 
        for (i = local_seg * slots_per_seg, counter = 0;
3659
 
             counter < array->n_slots; i++, counter++) {
3660
 
 
3661
 
                i %= array->n_slots;
3662
 
                slot = os_aio_array_get_nth_slot(array, i);
3663
 
 
3664
 
                if (slot->reserved == FALSE) {
3665
 
                        goto found;
3666
 
                }
3667
 
        }
3668
 
 
3669
 
        /* We MUST always be able to get hold of a reserved slot. */
3670
 
        ut_error;
 
3218
        /* First try to find a slot in the preferred local segment */
 
3219
        for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
 
3220
                slot = os_aio_array_get_nth_slot(array, i);
 
3221
 
 
3222
                if (slot->reserved == FALSE) {
 
3223
                        goto found;
 
3224
                }
 
3225
        }
 
3226
 
 
3227
        /* Fall back to a full scan. We are guaranteed to find a slot */
 
3228
        for (i = 0;; i++) {
 
3229
                slot = os_aio_array_get_nth_slot(array, i);
 
3230
 
 
3231
                if (slot->reserved == FALSE) {
 
3232
                        goto found;
 
3233
                }
 
3234
        }
3671
3235
 
3672
3236
found:
3673
3237
        ut_a(slot->reserved == FALSE);
3698
3262
        control = &(slot->control);
3699
3263
        control->Offset = (DWORD)offset;
3700
3264
        control->OffsetHigh = (DWORD)offset_high;
3701
 
        ResetEvent(slot->handle);
3702
 
 
3703
 
#elif defined(LINUX_NATIVE_AIO)
3704
 
 
3705
 
        /* If we are not using native AIO skip this part. */
3706
 
        if (!srv_use_native_aio) {
3707
 
                goto skip_native_aio;
3708
 
        }
3709
 
 
3710
 
        /* Check if we are dealing with 64 bit arch.
3711
 
        If not then make sure that offset fits in 32 bits. */
3712
 
        if (sizeof(aio_offset) == 8) {
3713
 
                aio_offset = offset_high;
3714
 
                aio_offset <<= 32;
3715
 
                aio_offset += offset;
3716
 
        } else {
3717
 
                ut_a(offset_high == 0);
3718
 
                aio_offset = offset;
3719
 
        }
3720
 
 
3721
 
        iocb = &slot->control;
3722
 
 
3723
 
        if (type == OS_FILE_READ) {
3724
 
                io_prep_pread(iocb, file, buf, len, aio_offset);
3725
 
        } else {
3726
 
                ut_a(type == OS_FILE_WRITE);
3727
 
                io_prep_pwrite(iocb, file, buf, len, aio_offset);
3728
 
        }
3729
 
 
3730
 
        iocb->data = (void*)slot;
3731
 
        slot->n_bytes = 0;
3732
 
        slot->ret = 0;
3733
 
        /*fprintf(stderr, "Filled up Linux native iocb.\n");*/
3734
 
        
3735
 
 
3736
 
skip_native_aio:
3737
 
#endif /* LINUX_NATIVE_AIO */
 
3265
        os_event_reset(slot->event);
 
3266
#endif
 
3267
 
3738
3268
        os_mutex_exit(array->mutex);
3739
3269
 
3740
3270
        return(slot);
3769
3299
        }
3770
3300
 
3771
3301
#ifdef WIN_ASYNC_IO
3772
 
 
3773
 
        ResetEvent(slot->handle);
3774
 
 
3775
 
#elif defined(LINUX_NATIVE_AIO)
3776
 
 
3777
 
        if (srv_use_native_aio) {
3778
 
                memset(&slot->control, 0x0, sizeof(slot->control));
3779
 
                slot->n_bytes = 0;
3780
 
                slot->ret = 0;
3781
 
                /*fprintf(stderr, "Freed up Linux native slot.\n");*/
3782
 
        } else {
3783
 
                /* These fields should not be used if we are not
3784
 
                using native AIO. */
3785
 
                ut_ad(slot->n_bytes == 0);
3786
 
                ut_ad(slot->ret == 0);
3787
 
        }
3788
 
 
 
3302
        os_event_reset(slot->event);
3789
3303
#endif
3790
3304
        os_mutex_exit(array->mutex);
3791
3305
}
3805
3319
        ulint           n;
3806
3320
        ulint           i;
3807
3321
 
3808
 
        ut_ad(!srv_use_native_aio);
 
3322
        ut_ad(!os_aio_use_native_aio);
3809
3323
 
3810
3324
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3811
3325
 
3841
3355
{
3842
3356
        ulint   i;
3843
3357
 
3844
 
        if (srv_use_native_aio) {
 
3358
        if (os_aio_use_native_aio) {
3845
3359
                /* We do not use simulated aio: do nothing */
3846
3360
 
3847
3361
                return;
3864
3378
os_aio_simulated_put_read_threads_to_sleep(void)
3865
3379
/*============================================*/
3866
3380
{
3867
 
 
3868
 
/* The idea of putting background IO threads to sleep is only for
3869
 
Windows when using simulated AIO. Windows XP seems to schedule
3870
 
background threads too eagerly to allow for coalescing during
3871
 
readahead requests. */
3872
 
#ifdef __WIN__
3873
3381
        os_aio_array_t* array;
3874
3382
        ulint           g;
3875
3383
 
3876
 
        if (srv_use_native_aio) {
3877
 
                /* We do not use simulated aio: do nothing */
3878
 
 
3879
 
                return;
3880
 
        }
3881
 
 
3882
3384
        os_aio_recommend_sleep_for_read_threads = TRUE;
3883
3385
 
3884
3386
        for (g = 0; g < os_aio_n_segments; g++) {
3889
3391
                        os_event_reset(os_aio_segment_wait_events[g]);
3890
3392
                }
3891
3393
        }
3892
 
#endif /* __WIN__ */
3893
 
}
3894
 
 
3895
 
#if defined(LINUX_NATIVE_AIO)
3896
 
/*******************************************************************//**
3897
 
Dispatch an AIO request to the kernel.
3898
 
@return TRUE on success. */
3899
 
static
3900
 
ibool
3901
 
os_aio_linux_dispatch(
3902
 
/*==================*/
3903
 
        os_aio_array_t* array,  /*!< in: io request array. */
3904
 
        os_aio_slot_t*  slot)   /*!< in: an already reserved slot. */
3905
 
{
3906
 
        int             ret;
3907
 
        ulint           io_ctx_index;
3908
 
        struct iocb*    iocb;
3909
 
 
3910
 
        ut_ad(slot != NULL);
3911
 
        ut_ad(array);
3912
 
 
3913
 
        ut_a(slot->reserved);
3914
 
 
3915
 
        /* Find out what we are going to work with.
3916
 
        The iocb struct is directly in the slot.
3917
 
        The io_context is one per segment. */
3918
 
 
3919
 
        iocb = &slot->control;
3920
 
        io_ctx_index = (slot->pos * array->n_segments) / array->n_slots;
3921
 
 
3922
 
        ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb);
3923
 
 
3924
 
#if defined(UNIV_AIO_DEBUG)
3925
 
        fprintf(stderr,
3926
 
                "io_submit[%c] ret[%d]: slot[%p] ctx[%p] seg[%lu]\n",
3927
 
                (slot->type == OS_FILE_WRITE) ? 'w' : 'r', ret, slot,
3928
 
                array->aio_ctx[io_ctx_index], (ulong)io_ctx_index);
3929
 
#endif
3930
 
 
3931
 
        /* io_submit returns number of successfully
3932
 
        queued requests or -errno. */
3933
 
        if (UNIV_UNLIKELY(ret != 1)) {
3934
 
                errno = -ret;
3935
 
                return(FALSE);
3936
 
        }
3937
 
 
3938
 
        return(TRUE);
3939
 
}
3940
 
#endif /* LINUX_NATIVE_AIO */
3941
 
 
3942
 
 
3943
 
/*******************************************************************//**
3944
 
NOTE! Use the corresponding macro os_aio(), not directly this function!
 
3394
}
 
3395
 
 
3396
/*******************************************************************//**
3945
3397
Requests an asynchronous i/o operation.
3946
3398
@return TRUE if request was queued successfully, FALSE if fail */
3947
3399
UNIV_INTERN
3948
3400
ibool
3949
 
os_aio_func(
3950
 
/*========*/
 
3401
os_aio(
 
3402
/*===*/
3951
3403
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3952
3404
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3953
3405
                                to OS_AIO_SIMULATED_WAKE_LATER: the
3990
3442
        struct fil_node_struct * dummy_mess1;
3991
3443
        void*           dummy_mess2;
3992
3444
        ulint           dummy_type;
3993
 
#endif /* WIN_ASYNC_IO */
3994
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
 
3445
#endif
 
3446
        ulint           err             = 0;
3995
3447
        ibool           retry;
3996
 
#endif
3997
3448
        ulint           wake_later;
3998
3449
 
3999
3450
        ut_ad(file);
4008
3459
 
4009
3460
        if (mode == OS_AIO_SYNC
4010
3461
#ifdef WIN_ASYNC_IO
4011
 
            && !srv_use_native_aio
4012
 
#endif /* WIN_ASYNC_IO */
 
3462
            && !os_aio_use_native_aio
 
3463
#endif
4013
3464
            ) {
4014
3465
                /* This is actually an ordinary synchronous read or write:
4015
3466
                no need to use an i/o-handler thread. NOTE that if we use
4028
3479
                return(os_file_write(name, file, buf, offset, offset_high, n));
4029
3480
        }
4030
3481
 
4031
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4032
3482
try_again:
4033
 
#endif
4034
3483
        if (mode == OS_AIO_NORMAL) {
4035
3484
                if (type == OS_FILE_READ) {
4036
3485
                        array = os_aio_read_array;
4050
3499
                array = os_aio_log_array;
4051
3500
        } else if (mode == OS_AIO_SYNC) {
4052
3501
                array = os_aio_sync_array;
4053
 
 
4054
 
#if defined(LINUX_NATIVE_AIO)
4055
 
                /* In Linux native AIO we don't use sync IO array. */
4056
 
                ut_a(!srv_use_native_aio);
4057
 
#endif /* LINUX_NATIVE_AIO */
4058
3502
        } else {
4059
3503
                array = NULL; /* Eliminate compiler warning */
4060
3504
                ut_error;
4063
3507
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
4064
3508
                                         name, buf, offset, offset_high, n);
4065
3509
        if (type == OS_FILE_READ) {
4066
 
                if (srv_use_native_aio) {
 
3510
                if (os_aio_use_native_aio) {
 
3511
#ifdef WIN_ASYNC_IO
4067
3512
                        os_n_file_reads++;
4068
 
                        os_bytes_read_since_printout += n;
4069
 
#ifdef WIN_ASYNC_IO
 
3513
                        os_bytes_read_since_printout += len;
 
3514
 
4070
3515
                        ret = ReadFile(file, buf, (DWORD)n, &len,
4071
3516
                                       &(slot->control));
4072
 
 
4073
 
#elif defined(LINUX_NATIVE_AIO)
4074
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4075
 
                                goto err_exit;
4076
 
                        }
4077
3517
#endif
4078
3518
                } else {
4079
3519
                        if (!wake_later) {
4083
3523
                        }
4084
3524
                }
4085
3525
        } else if (type == OS_FILE_WRITE) {
4086
 
                if (srv_use_native_aio) {
 
3526
                if (os_aio_use_native_aio) {
 
3527
#ifdef WIN_ASYNC_IO
4087
3528
                        os_n_file_writes++;
4088
 
#ifdef WIN_ASYNC_IO
4089
3529
                        ret = WriteFile(file, buf, (DWORD)n, &len,
4090
3530
                                        &(slot->control));
4091
 
 
4092
 
#elif defined(LINUX_NATIVE_AIO)
4093
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4094
 
                                goto err_exit;
4095
 
                        }
4096
3531
#endif
4097
3532
                } else {
4098
3533
                        if (!wake_later) {
4106
3541
        }
4107
3542
 
4108
3543
#ifdef WIN_ASYNC_IO
4109
 
        if (srv_use_native_aio) {
 
3544
        if (os_aio_use_native_aio) {
4110
3545
                if ((ret && len == n)
4111
3546
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
4112
3547
                        /* aio was queued successfully! */
4129
3564
                        return(TRUE);
4130
3565
                }
4131
3566
 
4132
 
                goto err_exit;
4133
 
        }
4134
 
#endif /* WIN_ASYNC_IO */
4135
 
        /* aio was queued successfully! */
4136
 
        return(TRUE);
4137
 
 
4138
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4139
 
err_exit:
 
3567
                err = 1; /* Fall through the next if */
 
3568
        }
 
3569
#endif
 
3570
        if (err == 0) {
 
3571
                /* aio was queued successfully! */
 
3572
 
 
3573
                return(TRUE);
 
3574
        }
 
3575
 
4140
3576
        os_aio_array_free_slot(array, slot);
4141
3577
 
4142
3578
        retry = os_file_handle_error(name,
4148
3584
        }
4149
3585
 
4150
3586
        return(FALSE);
4151
 
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
4152
3587
}
4153
3588
 
4154
3589
#ifdef WIN_ASYNC_IO
4190
3625
        ibool           ret_val;
4191
3626
        BOOL            ret;
4192
3627
        DWORD           len;
4193
 
        BOOL            retry           = FALSE;
4194
3628
 
4195
3629
        if (segment == ULINT_UNDEFINED) {
4196
3630
                array = os_aio_sync_array;
4208
3642
        n = array->n_slots / array->n_segments;
4209
3643
 
4210
3644
        if (array == os_aio_sync_array) {
4211
 
                WaitForSingleObject(
4212
 
                        os_aio_array_get_nth_slot(array, pos)->handle,
4213
 
                        INFINITE);
 
3645
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
4214
3646
                i = pos;
4215
3647
        } else {
4216
3648
                srv_set_io_thread_op_info(orig_seg, "wait Windows aio");
4217
 
                i = WaitForMultipleObjects((DWORD) n,
4218
 
                                           array->handles + segment * n,
4219
 
                                           FALSE,
4220
 
                                           INFINITE);
4221
 
        }
4222
 
 
4223
 
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
4224
 
                os_thread_exit(NULL);
 
3649
                i = os_event_wait_multiple(n,
 
3650
                                           (array->native_events)
 
3651
                                           + segment * n);
4225
3652
        }
4226
3653
 
4227
3654
        os_mutex_enter(array->mutex);
4248
3675
#ifdef UNIV_DO_FLUSH
4249
3676
                if (slot->type == OS_FILE_WRITE
4250
3677
                    && !os_do_not_call_flush_at_each_write) {
4251
 
                        if (!os_file_flush(slot->file)) {
4252
 
                                ut_error;
4253
 
                        }
 
3678
                        ut_a(TRUE == os_file_flush(slot->file));
4254
3679
                }
4255
3680
#endif /* UNIV_DO_FLUSH */
4256
 
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
4257
 
 
4258
 
                retry = TRUE;
4259
3681
        } else {
 
3682
                os_file_handle_error(slot->name, "Windows aio");
4260
3683
 
4261
3684
                ret_val = FALSE;
4262
3685
        }
4263
3686
 
4264
3687
        os_mutex_exit(array->mutex);
4265
3688
 
4266
 
        if (retry) {
4267
 
                /* retry failed read/write operation synchronously.
4268
 
                No need to hold array->mutex. */
4269
 
 
4270
 
#ifdef UNIV_PFS_IO
4271
 
                /* This read/write does not go through os_file_read
4272
 
                and os_file_write APIs, need to register with
4273
 
                performance schema explicitly here. */
4274
 
                struct PSI_file_locker* locker = NULL;
4275
 
                register_pfs_file_io_begin(locker, slot->file, slot->len,
4276
 
                                           (slot->type == OS_FILE_WRITE)
4277
 
                                                ? PSI_FILE_WRITE
4278
 
                                                : PSI_FILE_READ,
4279
 
                                            __FILE__, __LINE__);
4280
 
#endif
4281
 
 
4282
 
                switch (slot->type) {
4283
 
                case OS_FILE_WRITE:
4284
 
                        ret = WriteFile(slot->file, slot->buf,
4285
 
                                        slot->len, &len,
4286
 
                                        &(slot->control));
4287
 
 
4288
 
                        break;
4289
 
                case OS_FILE_READ:
4290
 
                        ret = ReadFile(slot->file, slot->buf,
4291
 
                                       slot->len, &len,
4292
 
                                       &(slot->control));
4293
 
 
4294
 
                        break;
4295
 
                default:
4296
 
                        ut_error;
4297
 
                }
4298
 
 
4299
 
#ifdef UNIV_PFS_IO
4300
 
                register_pfs_file_io_end(locker, len);
4301
 
#endif
4302
 
 
4303
 
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
4304
 
                        /* aio was queued successfully!
4305
 
                        We want a synchronous i/o operation on a
4306
 
                        file where we also use async i/o: in Windows
4307
 
                        we must use the same wait mechanism as for
4308
 
                        async i/o */
4309
 
 
4310
 
                        ret = GetOverlappedResult(slot->file,
4311
 
                                                  &(slot->control),
4312
 
                                                  &len, TRUE);
4313
 
                }
4314
 
 
4315
 
                ret_val = ret && len == slot->len;
4316
 
        }
4317
 
 
4318
3689
        os_aio_array_free_slot(array, slot);
4319
3690
 
4320
3691
        return(ret_val);
4321
3692
}
4322
3693
#endif
4323
3694
 
4324
 
#if defined(LINUX_NATIVE_AIO)
4325
 
/******************************************************************//**
4326
 
This function is only used in Linux native asynchronous i/o. This is
4327
 
called from within the io-thread. If there are no completed IO requests
4328
 
in the slot array, the thread calls this function to collect more
4329
 
requests from the kernel.
4330
 
The io-thread waits on io_getevents(), which is a blocking call, with
4331
 
a timeout value. Unless the system is very heavy loaded, keeping the
4332
 
io-thread very busy, the io-thread will spend most of its time waiting
4333
 
in this function.
4334
 
The io-thread also exits in this function. It checks server status at
4335
 
each wakeup and that is why we use timed wait in io_getevents(). */
4336
 
static
4337
 
void
4338
 
os_aio_linux_collect(
4339
 
/*=================*/
4340
 
        os_aio_array_t* array,          /*!< in/out: slot array. */
4341
 
        ulint           segment,        /*!< in: local segment no. */
4342
 
        ulint           seg_size)       /*!< in: segment size. */
4343
 
{
4344
 
        int                     i;
4345
 
        int                     ret;
4346
 
        ulint                   start_pos;
4347
 
        ulint                   end_pos;
4348
 
        struct timespec         timeout;
4349
 
        struct io_event*        events;
4350
 
        struct io_context*      io_ctx;
4351
 
 
4352
 
        /* sanity checks. */
4353
 
        ut_ad(array != NULL);
4354
 
        ut_ad(seg_size > 0);
4355
 
        ut_ad(segment < array->n_segments);
4356
 
 
4357
 
        /* Which part of event array we are going to work on. */
4358
 
        events = &array->aio_events[segment * seg_size];
4359
 
 
4360
 
        /* Which io_context we are going to use. */
4361
 
        io_ctx = array->aio_ctx[segment];
4362
 
 
4363
 
        /* Starting point of the segment we will be working on. */
4364
 
        start_pos = segment * seg_size;
4365
 
 
4366
 
        /* End point. */
4367
 
        end_pos = start_pos + seg_size;
4368
 
 
4369
 
retry:
4370
 
 
4371
 
        /* Go down if we are in shutdown mode.
4372
 
        In case of srv_fast_shutdown == 2, there may be pending
4373
 
        IO requests but that should be OK as we essentially treat
4374
 
        that as a crash of InnoDB. */
4375
 
        if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
4376
 
                os_thread_exit(NULL);
4377
 
        }
4378
 
 
4379
 
        /* Initialize the events. The timeout value is arbitrary.
4380
 
        We probably need to experiment with it a little. */
4381
 
        memset(events, 0, sizeof(*events) * seg_size);
4382
 
        timeout.tv_sec = 0;
4383
 
        timeout.tv_nsec = OS_AIO_REAP_TIMEOUT;
4384
 
 
4385
 
        ret = io_getevents(io_ctx, 1, seg_size, events, &timeout);
4386
 
 
4387
 
        /* This error handling is for any error in collecting the
4388
 
        IO requests. The errors, if any, for any particular IO
4389
 
        request are simply passed on to the calling routine. */
4390
 
 
4391
 
        /* Not enough resources! Try again. */
4392
 
        if (ret == -EAGAIN) {
4393
 
                goto retry;
4394
 
        }
4395
 
 
4396
 
        /* Interrupted! I have tested the behaviour in case of an
4397
 
        interrupt. If we have some completed IOs available then
4398
 
        the return code will be the number of IOs. We get EINTR only
4399
 
        if there are no completed IOs and we have been interrupted. */
4400
 
        if (ret == -EINTR) {
4401
 
                goto retry;
4402
 
        }
4403
 
 
4404
 
        /* No pending request! Go back and check again. */
4405
 
        if (ret == 0) {
4406
 
                goto retry;
4407
 
        }
4408
 
 
4409
 
        /* All other errors! should cause a trap for now. */
4410
 
        if (UNIV_UNLIKELY(ret < 0)) {
4411
 
                ut_print_timestamp(stderr);
4412
 
                fprintf(stderr,
4413
 
                        "  InnoDB: unexpected ret_code[%d] from"
4414
 
                        " io_getevents()!\n", ret);
4415
 
                ut_error;
4416
 
        }
4417
 
 
4418
 
        ut_a(ret > 0);
4419
 
 
4420
 
        for (i = 0; i < ret; i++) {
4421
 
                os_aio_slot_t*  slot;
4422
 
                struct iocb*    control;
4423
 
 
4424
 
                control = (struct iocb *)events[i].obj;
4425
 
                ut_a(control != NULL);
4426
 
 
4427
 
                slot = (os_aio_slot_t *) control->data;
4428
 
 
4429
 
                /* Some sanity checks. */
4430
 
                ut_a(slot != NULL);
4431
 
                ut_a(slot->reserved);
4432
 
 
4433
 
#if defined(UNIV_AIO_DEBUG)
4434
 
                fprintf(stderr,
4435
 
                        "io_getevents[%c]: slot[%p] ctx[%p]"
4436
 
                        " seg[%lu]\n",
4437
 
                        (slot->type == OS_FILE_WRITE) ? 'w' : 'r',
4438
 
                        slot, io_ctx, segment);
4439
 
#endif
4440
 
 
4441
 
                /* We are not scribbling previous segment. */
4442
 
                ut_a(slot->pos >= start_pos);
4443
 
 
4444
 
                /* We have not overstepped to next segment. */
4445
 
                ut_a(slot->pos < end_pos);
4446
 
 
4447
 
                /* Mark this request as completed. The error handling
4448
 
                will be done in the calling function. */
4449
 
                os_mutex_enter(array->mutex);
4450
 
                slot->n_bytes = events[i].res;
4451
 
                slot->ret = events[i].res2;
4452
 
                slot->io_already_done = TRUE;
4453
 
                os_mutex_exit(array->mutex);
4454
 
        }
4455
 
 
4456
 
        return;
4457
 
}
4458
 
 
4459
 
/**********************************************************************//**
4460
 
This function is only used in Linux native asynchronous i/o.
4461
 
Waits for an aio operation to complete. This function is used to wait for
4462
 
the completed requests. The aio array of pending requests is divided
4463
 
into segments. The thread specifies which segment or slot it wants to wait
4464
 
for. NOTE: this function will also take care of freeing the aio slot,
4465
 
therefore no other thread is allowed to do the freeing!
4466
 
@return TRUE if the IO was successful */
4467
 
UNIV_INTERN
4468
 
ibool
4469
 
os_aio_linux_handle(
4470
 
/*================*/
4471
 
        ulint   global_seg,     /*!< in: segment number in the aio array
4472
 
                                to wait for; segment 0 is the ibuf
4473
 
                                i/o thread, segment 1 is log i/o thread,
4474
 
                                then follow the non-ibuf read threads,
4475
 
                                and the last are the non-ibuf write
4476
 
                                threads. */
4477
 
        fil_node_t**message1,   /*!< out: the messages passed with the */
4478
 
        void**  message2,       /*!< aio request; note that in case the
4479
 
                                aio operation failed, these output
4480
 
                                parameters are valid and can be used to
4481
 
                                restart the operation. */
4482
 
        ulint*  type)           /*!< out: OS_FILE_WRITE or ..._READ */
4483
 
{
4484
 
        ulint           segment;
4485
 
        os_aio_array_t* array;
4486
 
        os_aio_slot_t*  slot;
4487
 
        ulint           n;
4488
 
        ulint           i;
4489
 
        ibool           ret = FALSE;
4490
 
 
4491
 
        /* Should never be doing Sync IO here. */
4492
 
        ut_a(global_seg != ULINT_UNDEFINED);
4493
 
 
4494
 
        /* Find the array and the local segment. */
4495
 
        segment = os_aio_get_array_and_local_segment(&array, global_seg);
4496
 
        n = array->n_slots / array->n_segments;
4497
 
 
4498
 
        /* Loop until we have found a completed request. */
4499
 
        for (;;) {
4500
 
                os_mutex_enter(array->mutex);
4501
 
                for (i = 0; i < n; ++i) {
4502
 
                        slot = os_aio_array_get_nth_slot(
4503
 
                                        array, i + segment * n);
4504
 
                        if (slot->reserved && slot->io_already_done) {
4505
 
                                /* Something for us to work on. */
4506
 
                                goto found;
4507
 
                        }
4508
 
                }
4509
 
 
4510
 
                os_mutex_exit(array->mutex);
4511
 
 
4512
 
                /* We don't have any completed request.
4513
 
                Wait for some request. Note that we return
4514
 
                from wait iff we have found a request. */
4515
 
 
4516
 
                srv_set_io_thread_op_info(global_seg,
4517
 
                        "waiting for completed aio requests");
4518
 
                os_aio_linux_collect(array, segment, n);
4519
 
        }
4520
 
 
4521
 
found:
4522
 
        /* Note that it may be that there are more then one completed
4523
 
        IO requests. We process them one at a time. We may have a case
4524
 
        here to improve the performance slightly by dealing with all
4525
 
        requests in one sweep. */
4526
 
        srv_set_io_thread_op_info(global_seg,
4527
 
                                "processing completed aio requests");
4528
 
 
4529
 
        /* Ensure that we are scribbling only our segment. */
4530
 
        ut_a(i < n);
4531
 
 
4532
 
        ut_ad(slot != NULL);
4533
 
        ut_ad(slot->reserved);
4534
 
        ut_ad(slot->io_already_done);
4535
 
 
4536
 
        *message1 = slot->message1;
4537
 
        *message2 = slot->message2;
4538
 
 
4539
 
        *type = slot->type;
4540
 
 
4541
 
        if ((slot->ret == 0) && (slot->n_bytes == (long)slot->len)) {
4542
 
                ret = TRUE;
4543
 
 
4544
 
#ifdef UNIV_DO_FLUSH
4545
 
                if (slot->type == OS_FILE_WRITE
4546
 
                    && !os_do_not_call_flush_at_each_write)
4547
 
                    && !os_file_flush(slot->file) {
4548
 
                        ut_error;
4549
 
                }
4550
 
#endif /* UNIV_DO_FLUSH */
4551
 
        } else {
4552
 
                errno = -slot->ret;
4553
 
 
4554
 
                /* os_file_handle_error does tell us if we should retry
4555
 
                this IO. As it stands now, we don't do this retry when
4556
 
                reaping requests from a different context than
4557
 
                the dispatcher. This non-retry logic is the same for
4558
 
                windows and linux native AIO.
4559
 
                We should probably look into this to transparently
4560
 
                re-submit the IO. */
4561
 
                os_file_handle_error(slot->name, "Linux aio");
4562
 
 
4563
 
                ret = FALSE;
4564
 
        }
4565
 
 
4566
 
        os_mutex_exit(array->mutex);
4567
 
 
4568
 
        os_aio_array_free_slot(array, slot);
4569
 
 
4570
 
        return(ret);
4571
 
}
4572
 
#endif /* LINUX_NATIVE_AIO */
4573
 
 
4574
3695
/**********************************************************************//**
4575
3696
Does simulated aio. This function should be called by an i/o-handler
4576
3697
thread.
4609
3730
        ulint           n;
4610
3731
        ulint           i;
4611
3732
 
4612
 
        /* Fix compiler warning */
4613
 
        *consecutive_ios = NULL;
4614
 
 
4615
3733
        memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
4616
3734
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
4617
3735
 
4724
3842
                goto wait_for_io;
4725
3843
        }
4726
3844
 
4727
 
        /* if n_consecutive != 0, then we have assigned
4728
 
        something valid to consecutive_ios[0] */
4729
 
        ut_ad(n_consecutive != 0);
4730
 
        ut_ad(consecutive_ios[0] != NULL);
4731
 
 
4732
3845
        slot = consecutive_ios[0];
4733
3846
 
4734
3847
        /* Check if there are several consecutive blocks to read or write */
4955
4068
}
4956
4069
 
4957
4070
/**********************************************************************//**
4958
 
Prints pending IO requests per segment of an aio array.
4959
 
We probably don't need per segment statistics but they can help us
4960
 
during development phase to see if the IO requests are being
4961
 
distributed as expected. */
4962
 
static
4963
 
void
4964
 
os_aio_print_segment_info(
4965
 
/*======================*/
4966
 
        FILE*           file,   /*!< in: file where to print */
4967
 
        ulint*          n_seg,  /*!< in: pending IO array */
4968
 
        os_aio_array_t* array)  /*!< in: array to process */
4969
 
{
4970
 
        ulint   i;
4971
 
 
4972
 
        ut_ad(array);
4973
 
        ut_ad(n_seg);
4974
 
        ut_ad(array->n_segments > 0);
4975
 
 
4976
 
        if (array->n_segments == 1) {
4977
 
                return;
4978
 
        }
4979
 
 
4980
 
        fprintf(file, " [");
4981
 
        for (i = 0; i < array->n_segments; i++) {
4982
 
                if (i != 0) {
4983
 
                        fprintf(file, ", ");
4984
 
                }
4985
 
 
4986
 
                fprintf(file, "%lu", n_seg[i]);
4987
 
        }
4988
 
        fprintf(file, "] ");
4989
 
}
4990
 
 
4991
 
/**********************************************************************//**
4992
4071
Prints info of the aio arrays. */
4993
4072
UNIV_INTERN
4994
4073
void
4999
4078
        os_aio_array_t* array;
5000
4079
        os_aio_slot_t*  slot;
5001
4080
        ulint           n_reserved;
5002
 
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
5003
4081
        time_t          current_time;
5004
4082
        double          time_elapsed;
5005
4083
        double          avg_bytes_read;
5032
4110
 
5033
4111
        n_reserved = 0;
5034
4112
 
5035
 
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
5036
 
 
5037
4113
        for (i = 0; i < array->n_slots; i++) {
5038
 
                ulint   seg_no;
5039
 
 
5040
4114
                slot = os_aio_array_get_nth_slot(array, i);
5041
4115
 
5042
 
                seg_no = (i * array->n_segments) / array->n_slots;
5043
4116
                if (slot->reserved) {
5044
4117
                        n_reserved++;
5045
 
                        n_res_seg[seg_no]++;
5046
4118
#if 0
5047
4119
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
5048
4120
                                (void*) slot->message1,
5056
4128
 
5057
4129
        fprintf(file, " %lu", (ulong) n_reserved);
5058
4130
 
5059
 
        os_aio_print_segment_info(file, n_res_seg, array);
5060
 
 
5061
4131
        os_mutex_exit(array->mutex);
5062
4132
 
5063
4133
        if (array == os_aio_read_array) {