~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: lbieber
  • Date: 2010-10-01 12:16:18 UTC
  • mfrom: (1802.1.1 fix-bug-651256)
  • Revision ID: lbieber@orisndriz08-20101001121618-uqcboygpjwbiglem
Merge Vijay - fix bug 651256 - Remove --help-extended

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
 */
662
535
                if (errno == EAGAIN || errno == EACCES) {
663
536
                        fprintf(stderr,
664
537
                                "InnoDB: Check that you do not already have"
665
 
                                " another drizzled process\n"
 
538
                                " another mysqld process\n"
666
539
                                "InnoDB: using the same InnoDB data"
667
540
                                " or log files.\n");
668
541
                }
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);
940
813
 
941
814
        strcpy(info->name, ent->d_name);
942
815
 
943
 
        full_path = static_cast<char* >(ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10));
 
816
        full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10);
944
817
 
945
818
        sprintf(full_path, "%s/%s", dirname, ent->d_name);
946
819
 
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
1298
1150
os_file_set_nocache(
1299
1151
/*================*/
1300
1152
        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
 
1153
        const char*     file_name,      /*!< in: file name, used in the
 
1154
                                        diagnostic message */
 
1155
        const char*     operation_name) /*!< in: "open" or "create"; used in the
1304
1156
                                        diagnostic message */
1305
1157
{
1306
1158
        /* some versions of Solaris may not have DIRECTIO_ON */
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__
1937
1788
        /* Write up to 1 megabyte at a time. */
1938
1789
        buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
1939
1790
                * UNIV_PAGE_SIZE;
1940
 
        buf2 = static_cast<unsigned char *>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
 
1791
        buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
1941
1792
 
1942
1793
        /* Align the buffer for possible raw i/o */
1943
 
        buf = static_cast<unsigned char *>(ut_align(buf2, UNIV_PAGE_SIZE));
 
1794
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
1944
1795
 
1945
1796
        /* Write buffer full of zeros */
1946
1797
        memset(buf, 0, buf_size);
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
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2408
 
        no more than 32 bits. */
2409
2239
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2410
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2411
2240
 
2412
2241
        os_n_file_reads++;
2413
2242
        os_bytes_read_since_printout += n;
2424
2253
        os_n_pending_reads++;
2425
2254
        os_mutex_exit(os_file_count_mutex);
2426
2255
 
2427
 
#ifndef UNIV_HOTBACKUP
2428
2256
        /* Protect the seek / read operation with a mutex */
2429
2257
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2430
2258
 
2431
2259
        os_mutex_enter(os_file_seek_mutexes[i]);
2432
 
#endif /* !UNIV_HOTBACKUP */
2433
2260
 
2434
2261
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2435
2262
 
2436
2263
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2437
2264
 
2438
 
#ifndef UNIV_HOTBACKUP
2439
2265
                os_mutex_exit(os_file_seek_mutexes[i]);
2440
 
#endif /* !UNIV_HOTBACKUP */
2441
2266
 
2442
2267
                os_mutex_enter(os_file_count_mutex);
2443
2268
                os_n_pending_reads--;
2448
2273
 
2449
2274
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2450
2275
 
2451
 
#ifndef UNIV_HOTBACKUP
2452
2276
        os_mutex_exit(os_file_seek_mutexes[i]);
2453
 
#endif /* !UNIV_HOTBACKUP */
2454
2277
 
2455
2278
        os_mutex_enter(os_file_count_mutex);
2456
2279
        os_n_pending_reads--;
2459
2282
        if (ret && len == n) {
2460
2283
                return(TRUE);
2461
2284
        }
2462
 
#else /* __WIN__ */
 
2285
#else
2463
2286
        ibool   retry;
2464
2287
        ssize_t ret;
2465
2288
 
2478
2301
                "InnoDB: Was only able to read %ld.\n",
2479
2302
                (ulong)n, (ulong)offset_high,
2480
2303
                (ulong)offset, (long)ret);
2481
 
#endif /* __WIN__ */
 
2304
#endif
2482
2305
#ifdef __WIN__
2483
2306
error_handling:
2484
2307
#endif
2505
2328
}
2506
2329
 
2507
2330
/*******************************************************************//**
2508
 
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
2509
 
not directly this function!
2510
2331
Requests a synchronous positioned read operation. This function does not do
2511
2332
any error handling. In case of error it returns FALSE.
2512
2333
@return TRUE if request was successful, FALSE if fail */
2513
2334
UNIV_INTERN
2514
2335
ibool
2515
 
os_file_read_no_error_handling_func(
2516
 
/*================================*/
 
2336
os_file_read_no_error_handling(
 
2337
/*===========================*/
2517
2338
        os_file_t       file,   /*!< in: handle to a file */
2518
2339
        void*           buf,    /*!< in: buffer where to read */
2519
2340
        ulint           offset, /*!< in: least significant 32 bits of file
2529
2350
        DWORD           low;
2530
2351
        DWORD           high;
2531
2352
        ibool           retry;
2532
 
#ifndef UNIV_HOTBACKUP
2533
2353
        ulint           i;
2534
 
#endif /* !UNIV_HOTBACKUP */
2535
2354
 
2536
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2537
 
        no more than 32 bits. */
2538
2355
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2539
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2540
2356
 
2541
2357
        os_n_file_reads++;
2542
2358
        os_bytes_read_since_printout += n;
2553
2369
        os_n_pending_reads++;
2554
2370
        os_mutex_exit(os_file_count_mutex);
2555
2371
 
2556
 
#ifndef UNIV_HOTBACKUP
2557
2372
        /* Protect the seek / read operation with a mutex */
2558
2373
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2559
2374
 
2560
2375
        os_mutex_enter(os_file_seek_mutexes[i]);
2561
 
#endif /* !UNIV_HOTBACKUP */
2562
2376
 
2563
2377
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2564
2378
 
2565
2379
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2566
2380
 
2567
 
#ifndef UNIV_HOTBACKUP
2568
2381
                os_mutex_exit(os_file_seek_mutexes[i]);
2569
 
#endif /* !UNIV_HOTBACKUP */
2570
2382
 
2571
2383
                os_mutex_enter(os_file_count_mutex);
2572
2384
                os_n_pending_reads--;
2577
2389
 
2578
2390
        ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
2579
2391
 
2580
 
#ifndef UNIV_HOTBACKUP
2581
2392
        os_mutex_exit(os_file_seek_mutexes[i]);
2582
 
#endif /* !UNIV_HOTBACKUP */
2583
2393
 
2584
2394
        os_mutex_enter(os_file_count_mutex);
2585
2395
        os_n_pending_reads--;
2588
2398
        if (ret && len == n) {
2589
2399
                return(TRUE);
2590
2400
        }
2591
 
#else /* __WIN__ */
 
2401
#else
2592
2402
        ibool   retry;
2593
2403
        ssize_t ret;
2594
2404
 
2601
2411
 
2602
2412
                return(TRUE);
2603
2413
        }
2604
 
#endif /* __WIN__ */
 
2414
#endif
2605
2415
#ifdef __WIN__
2606
2416
error_handling:
2607
2417
#endif
2638
2448
}
2639
2449
 
2640
2450
/*******************************************************************//**
2641
 
NOTE! Use the corresponding macro os_file_write(), not directly
2642
 
this function!
2643
2451
Requests a synchronous write operation.
2644
2452
@return TRUE if request was successful, FALSE if fail */
2645
2453
UNIV_INTERN
2646
2454
ibool
2647
 
os_file_write_func(
2648
 
/*===============*/
 
2455
os_file_write(
 
2456
/*==========*/
2649
2457
        const char*     name,   /*!< in: name of the file or path as a
2650
2458
                                null-terminated string */
2651
2459
        os_file_t       file,   /*!< in: handle to a file */
2662
2470
        DWORD           ret2;
2663
2471
        DWORD           low;
2664
2472
        DWORD           high;
 
2473
        ulint           i;
2665
2474
        ulint           n_retries       = 0;
2666
2475
        ulint           err;
2667
 
#ifndef UNIV_HOTBACKUP
2668
 
        ulint           i;
2669
 
#endif /* !UNIV_HOTBACKUP */
2670
2476
 
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);
 
2477
        ut_a((offset & 0xFFFFFFFF) == offset);
2675
2478
 
2676
2479
        os_n_file_writes++;
2677
2480
 
2686
2489
        os_n_pending_writes++;
2687
2490
        os_mutex_exit(os_file_count_mutex);
2688
2491
 
2689
 
#ifndef UNIV_HOTBACKUP
2690
2492
        /* Protect the seek / write operation with a mutex */
2691
2493
        i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
2692
2494
 
2693
2495
        os_mutex_enter(os_file_seek_mutexes[i]);
2694
 
#endif /* !UNIV_HOTBACKUP */
2695
2496
 
2696
2497
        ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
2697
2498
 
2698
2499
        if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
2699
2500
 
2700
 
#ifndef UNIV_HOTBACKUP
2701
2501
                os_mutex_exit(os_file_seek_mutexes[i]);
2702
 
#endif /* !UNIV_HOTBACKUP */
2703
2502
 
2704
2503
                os_mutex_enter(os_file_count_mutex);
2705
2504
                os_n_pending_writes--;
2733
2532
        }
2734
2533
# endif /* UNIV_DO_FLUSH */
2735
2534
 
2736
 
#ifndef UNIV_HOTBACKUP
2737
2535
        os_mutex_exit(os_file_seek_mutexes[i]);
2738
 
#endif /* !UNIV_HOTBACKUP */
2739
2536
 
2740
2537
        os_mutex_enter(os_file_count_mutex);
2741
2538
        os_n_pending_writes--;
3107
2904
        return((array->slots) + index);
3108
2905
}
3109
2906
 
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 */
 
2907
/************************************************************************//**
 
2908
Creates an aio wait array.
 
2909
@return own: aio array */
3203
2910
static
3204
2911
os_aio_array_t*
3205
2912
os_aio_array_create(
3206
2913
/*================*/
3207
 
        ulint   n,              /*!< in: maximum number of pending aio
3208
 
                                operations allowed; n must be
3209
 
                                divisible by n_segments */
 
2914
        ulint   n,              /*!< in: maximum number of pending aio operations
 
2915
                                allowed; n must be divisible by n_segments */
3210
2916
        ulint   n_segments)     /*!< in: number of segments in the aio array */
3211
2917
{
3212
2918
        os_aio_array_t* array;
3214
2920
        os_aio_slot_t*  slot;
3215
2921
#ifdef WIN_ASYNC_IO
3216
2922
        OVERLAPPED*     over;
3217
 
#elif defined(LINUX_NATIVE_AIO)
3218
 
        struct io_event*        aio_event = NULL;
3219
2923
#endif
3220
2924
        ut_a(n > 0);
3221
2925
        ut_a(n_segments > 0);
3222
2926
 
3223
 
        array = static_cast<os_aio_array_t *>(ut_malloc(sizeof(os_aio_array_t)));
 
2927
        array = ut_malloc(sizeof(os_aio_array_t));
3224
2928
 
3225
 
        array->mutex            = os_mutex_create();
 
2929
        array->mutex            = os_mutex_create(NULL);
3226
2930
        array->not_full         = os_event_create(NULL);
3227
2931
        array->is_empty         = os_event_create(NULL);
3228
2932
 
3231
2935
        array->n_slots          = n;
3232
2936
        array->n_segments       = n_segments;
3233
2937
        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)));
 
2938
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
3236
2939
#ifdef __WIN__
3237
 
        array->handles          = ut_malloc(n * sizeof(HANDLE));
 
2940
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
3238
2941
#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
2942
        for (i = 0; i < n; i++) {
3276
2943
                slot = os_aio_array_get_nth_slot(array, i);
3277
2944
 
3278
2945
                slot->pos = i;
3279
2946
                slot->reserved = FALSE;
3280
2947
#ifdef WIN_ASYNC_IO
3281
 
                slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
 
2948
                slot->event = os_event_create(NULL);
3282
2949
 
3283
2950
                over = &(slot->control);
3284
2951
 
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;
 
2952
                over->hEvent = slot->event->handle;
 
2953
 
 
2954
                *((array->native_events) + i) = over->hEvent;
3294
2955
#endif
3295
2956
        }
3296
2957
 
3297
2958
        return(array);
3298
2959
}
3299
2960
 
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
2961
/***********************************************************************
3336
2962
Initializes the asynchronous io system. Creates one array each for ibuf
3337
2963
and log i/o. Also creates one array each for read and write where each
3340
2966
segment in these arrays. This function also creates the sync array.
3341
2967
No i/o handler thread needs to be created for that */
3342
2968
UNIV_INTERN
3343
 
ibool
 
2969
void
3344
2970
os_aio_init(
3345
2971
/*========*/
3346
2972
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3365
2991
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3366
2992
 
3367
2993
        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
2994
 
3372
2995
        srv_io_thread_function[0] = "insert buffer thread";
3373
2996
 
3374
2997
        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
2998
 
3379
2999
        srv_io_thread_function[1] = "log thread";
3380
3000
 
3381
3001
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3382
3002
                                                n_read_segs);
3383
 
        if (os_aio_read_array == NULL) {
3384
 
                goto err_exit;
3385
 
        }
3386
 
 
3387
3003
        for (i = 2; i < 2 + n_read_segs; i++) {
3388
3004
                ut_a(i < SRV_MAX_N_IO_THREADS);
3389
3005
                srv_io_thread_function[i] = "read thread";
3391
3007
 
3392
3008
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3393
3009
                                                 n_write_segs);
3394
 
        if (os_aio_write_array == NULL) {
3395
 
                goto err_exit;
3396
 
        }
3397
 
 
3398
3010
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3399
3011
                ut_a(i < SRV_MAX_N_IO_THREADS);
3400
3012
                srv_io_thread_function[i] = "write thread";
3401
3013
        }
3402
3014
 
3403
3015
        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
3016
 
3409
3017
        os_aio_n_segments = n_segments;
3410
3018
 
3411
3019
        os_aio_validate();
3412
3020
 
3413
 
        os_aio_segment_wait_events = static_cast<os_event_t *>(ut_malloc(n_segments * sizeof(void*)));
 
3021
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
3414
3022
 
3415
3023
        for (i = 0; i < n_segments; i++) {
3416
3024
                os_aio_segment_wait_events[i] = os_event_create(NULL);
3418
3026
 
3419
3027
        os_last_printout = time(NULL);
3420
3028
 
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
3029
}
3456
3030
 
3457
3031
#ifdef WIN_ASYNC_IO
3468
3042
 
3469
3043
        for (i = 0; i < array->n_slots; i++) {
3470
3044
 
3471
 
                SetEvent((array->slots + i)->handle);
 
3045
                os_event_set((array->slots + i)->event);
3472
3046
        }
3473
3047
}
3474
3048
#endif
3489
3063
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3490
3064
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3491
3065
        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
3066
#endif
3506
3067
        /* This loop wakes up all simulated ai/o threads */
3507
3068
 
3619
3180
                                offset */
3620
3181
        ulint           len)    /*!< in: length of the block to read or write */
3621
3182
{
3622
 
        os_aio_slot_t*  slot = NULL;
 
3183
        os_aio_slot_t*  slot;
3623
3184
#ifdef WIN_ASYNC_IO
3624
3185
        OVERLAPPED*     control;
3625
 
 
3626
 
#elif defined(LINUX_NATIVE_AIO)
3627
 
 
3628
 
        struct iocb*    iocb;
3629
 
        off_t           aio_offset;
3630
 
 
3631
3186
#endif
3632
3187
        ulint           i;
3633
 
        ulint           counter;
3634
3188
        ulint           slots_per_seg;
3635
3189
        ulint           local_seg;
3636
3190
 
3637
 
#ifdef WIN_ASYNC_IO
3638
 
        ut_a((len & 0xFFFFFFFFUL) == len);
3639
 
#endif
3640
 
 
3641
3191
        /* No need of a mutex. Only reading constant fields */
3642
3192
        slots_per_seg = array->n_slots / array->n_segments;
3643
3193
 
3653
3203
        if (array->n_reserved == array->n_slots) {
3654
3204
                os_mutex_exit(array->mutex);
3655
3205
 
3656
 
                if (!srv_use_native_aio) {
 
3206
                if (!os_aio_use_native_aio) {
3657
3207
                        /* If the handler threads are suspended, wake them
3658
3208
                        so that we get more slots */
3659
3209
 
3665
3215
                goto loop;
3666
3216
        }
3667
3217
 
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;
 
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
        }
3684
3235
 
3685
3236
found:
3686
3237
        ut_a(slot->reserved == FALSE);
3702
3253
        slot->name     = name;
3703
3254
        slot->len      = len;
3704
3255
        slot->type     = type;
3705
 
        slot->buf      = static_cast<unsigned char *>(buf);
 
3256
        slot->buf      = buf;
3706
3257
        slot->offset   = offset;
3707
3258
        slot->offset_high = offset_high;
3708
3259
        slot->io_already_done = FALSE;
3711
3262
        control = &(slot->control);
3712
3263
        control->Offset = (DWORD)offset;
3713
3264
        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 */
 
3265
        os_event_reset(slot->event);
 
3266
#endif
 
3267
 
3751
3268
        os_mutex_exit(array->mutex);
3752
3269
 
3753
3270
        return(slot);
3782
3299
        }
3783
3300
 
3784
3301
#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
 
 
 
3302
        os_event_reset(slot->event);
3802
3303
#endif
3803
3304
        os_mutex_exit(array->mutex);
3804
3305
}
3818
3319
        ulint           n;
3819
3320
        ulint           i;
3820
3321
 
3821
 
        ut_ad(!srv_use_native_aio);
 
3322
        ut_ad(!os_aio_use_native_aio);
3822
3323
 
3823
3324
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3824
3325
 
3854
3355
{
3855
3356
        ulint   i;
3856
3357
 
3857
 
        if (srv_use_native_aio) {
 
3358
        if (os_aio_use_native_aio) {
3858
3359
                /* We do not use simulated aio: do nothing */
3859
3360
 
3860
3361
                return;
3877
3378
os_aio_simulated_put_read_threads_to_sleep(void)
3878
3379
/*============================================*/
3879
3380
{
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
3381
        os_aio_array_t* array;
3887
3382
        ulint           g;
3888
3383
 
3889
 
        if (srv_use_native_aio) {
3890
 
                /* We do not use simulated aio: do nothing */
3891
 
 
3892
 
                return;
3893
 
        }
3894
 
 
3895
3384
        os_aio_recommend_sleep_for_read_threads = TRUE;
3896
3385
 
3897
3386
        for (g = 0; g < os_aio_n_segments; g++) {
3902
3391
                        os_event_reset(os_aio_segment_wait_events[g]);
3903
3392
                }
3904
3393
        }
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!
 
3394
}
 
3395
 
 
3396
/*******************************************************************//**
3958
3397
Requests an asynchronous i/o operation.
3959
3398
@return TRUE if request was queued successfully, FALSE if fail */
3960
3399
UNIV_INTERN
3961
3400
ibool
3962
 
os_aio_func(
3963
 
/*========*/
 
3401
os_aio(
 
3402
/*===*/
3964
3403
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3965
3404
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3966
3405
                                to OS_AIO_SIMULATED_WAKE_LATER: the
4003
3442
        struct fil_node_struct * dummy_mess1;
4004
3443
        void*           dummy_mess2;
4005
3444
        ulint           dummy_type;
4006
 
#endif /* WIN_ASYNC_IO */
4007
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
 
3445
#endif
 
3446
        ulint           err             = 0;
4008
3447
        ibool           retry;
4009
 
#endif
4010
3448
        ulint           wake_later;
4011
3449
 
4012
3450
        ut_ad(file);
4015
3453
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
4016
3454
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
4017
3455
        ut_ad(os_aio_validate());
4018
 
#ifdef WIN_ASYNC_IO
4019
 
        ut_ad((n & 0xFFFFFFFFUL) == n);
4020
 
#endif
4021
3456
 
4022
3457
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
4023
3458
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
4024
3459
 
4025
3460
        if (mode == OS_AIO_SYNC
4026
3461
#ifdef WIN_ASYNC_IO
4027
 
            && !srv_use_native_aio
4028
 
#endif /* WIN_ASYNC_IO */
 
3462
            && !os_aio_use_native_aio
 
3463
#endif
4029
3464
            ) {
4030
3465
                /* This is actually an ordinary synchronous read or write:
4031
3466
                no need to use an i/o-handler thread. NOTE that if we use
4044
3479
                return(os_file_write(name, file, buf, offset, offset_high, n));
4045
3480
        }
4046
3481
 
4047
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4048
3482
try_again:
4049
 
#endif
4050
3483
        if (mode == OS_AIO_NORMAL) {
4051
3484
                if (type == OS_FILE_READ) {
4052
3485
                        array = os_aio_read_array;
4066
3499
                array = os_aio_log_array;
4067
3500
        } else if (mode == OS_AIO_SYNC) {
4068
3501
                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
3502
        } else {
4075
3503
                array = NULL; /* Eliminate compiler warning */
4076
3504
                ut_error;
4079
3507
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
4080
3508
                                         name, buf, offset, offset_high, n);
4081
3509
        if (type == OS_FILE_READ) {
4082
 
                if (srv_use_native_aio) {
 
3510
                if (os_aio_use_native_aio) {
 
3511
#ifdef WIN_ASYNC_IO
4083
3512
                        os_n_file_reads++;
4084
 
                        os_bytes_read_since_printout += n;
4085
 
#ifdef WIN_ASYNC_IO
 
3513
                        os_bytes_read_since_printout += len;
 
3514
 
4086
3515
                        ret = ReadFile(file, buf, (DWORD)n, &len,
4087
3516
                                       &(slot->control));
4088
 
 
4089
 
#elif defined(LINUX_NATIVE_AIO)
4090
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4091
 
                                goto err_exit;
4092
 
                        }
4093
3517
#endif
4094
3518
                } else {
4095
3519
                        if (!wake_later) {
4099
3523
                        }
4100
3524
                }
4101
3525
        } else if (type == OS_FILE_WRITE) {
4102
 
                if (srv_use_native_aio) {
 
3526
                if (os_aio_use_native_aio) {
 
3527
#ifdef WIN_ASYNC_IO
4103
3528
                        os_n_file_writes++;
4104
 
#ifdef WIN_ASYNC_IO
4105
3529
                        ret = WriteFile(file, buf, (DWORD)n, &len,
4106
3530
                                        &(slot->control));
4107
 
 
4108
 
#elif defined(LINUX_NATIVE_AIO)
4109
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4110
 
                                goto err_exit;
4111
 
                        }
4112
3531
#endif
4113
3532
                } else {
4114
3533
                        if (!wake_later) {
4122
3541
        }
4123
3542
 
4124
3543
#ifdef WIN_ASYNC_IO
4125
 
        if (srv_use_native_aio) {
 
3544
        if (os_aio_use_native_aio) {
4126
3545
                if ((ret && len == n)
4127
3546
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
4128
3547
                        /* aio was queued successfully! */
4145
3564
                        return(TRUE);
4146
3565
                }
4147
3566
 
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:
 
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
 
4156
3576
        os_aio_array_free_slot(array, slot);
4157
3577
 
4158
3578
        retry = os_file_handle_error(name,
4164
3584
        }
4165
3585
 
4166
3586
        return(FALSE);
4167
 
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
4168
3587
}
4169
3588
 
4170
3589
#ifdef WIN_ASYNC_IO
4206
3625
        ibool           ret_val;
4207
3626
        BOOL            ret;
4208
3627
        DWORD           len;
4209
 
        BOOL            retry           = FALSE;
4210
3628
 
4211
3629
        if (segment == ULINT_UNDEFINED) {
4212
3630
                array = os_aio_sync_array;
4224
3642
        n = array->n_slots / array->n_segments;
4225
3643
 
4226
3644
        if (array == os_aio_sync_array) {
4227
 
                WaitForSingleObject(
4228
 
                        os_aio_array_get_nth_slot(array, pos)->handle,
4229
 
                        INFINITE);
 
3645
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
4230
3646
                i = pos;
4231
3647
        } else {
4232
3648
                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);
 
3649
                i = os_event_wait_multiple(n,
 
3650
                                           (array->native_events)
 
3651
                                           + segment * n);
4241
3652
        }
4242
3653
 
4243
3654
        os_mutex_enter(array->mutex);
4264
3675
#ifdef UNIV_DO_FLUSH
4265
3676
                if (slot->type == OS_FILE_WRITE
4266
3677
                    && !os_do_not_call_flush_at_each_write) {
4267
 
                        if (!os_file_flush(slot->file)) {
4268
 
                                ut_error;
4269
 
                        }
 
3678
                        ut_a(TRUE == os_file_flush(slot->file));
4270
3679
                }
4271
3680
#endif /* UNIV_DO_FLUSH */
4272
 
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
4273
 
 
4274
 
                retry = TRUE;
4275
3681
        } else {
 
3682
                os_file_handle_error(slot->name, "Windows aio");
4276
3683
 
4277
3684
                ret_val = FALSE;
4278
3685
        }
4279
3686
 
4280
3687
        os_mutex_exit(array->mutex);
4281
3688
 
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
3689
        os_aio_array_free_slot(array, slot);
4337
3690
 
4338
3691
        return(ret_val);
4339
3692
}
4340
3693
#endif
4341
3694
 
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
3695
/**********************************************************************//**
4593
3696
Does simulated aio. This function should be called by an i/o-handler
4594
3697
thread.
4627
3730
        ulint           n;
4628
3731
        ulint           i;
4629
3732
 
4630
 
        /* Fix compiler warning */
4631
 
        *consecutive_ios = NULL;
4632
 
 
4633
3733
        memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
4634
3734
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
4635
3735
 
4742
3842
                goto wait_for_io;
4743
3843
        }
4744
3844
 
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
3845
        slot = consecutive_ios[0];
4751
3846
 
4752
3847
        /* Check if there are several consecutive blocks to read or write */
4797
3892
                combined_buf = slot->buf;
4798
3893
                combined_buf2 = NULL;
4799
3894
        } else {
4800
 
                combined_buf2 = static_cast<unsigned char *>(ut_malloc(total_len + UNIV_PAGE_SIZE));
 
3895
                combined_buf2 = ut_malloc(total_len + UNIV_PAGE_SIZE);
4801
3896
 
4802
3897
                ut_a(combined_buf2);
4803
3898
 
4804
 
                combined_buf = static_cast<unsigned char *>(ut_align(combined_buf2, UNIV_PAGE_SIZE));
 
3899
                combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE);
4805
3900
        }
4806
3901
 
4807
3902
        /* We release the array mutex for the time of the i/o: NOTE that
4973
4068
}
4974
4069
 
4975
4070
/**********************************************************************//**
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
4071
Prints info of the aio arrays. */
5011
4072
UNIV_INTERN
5012
4073
void
5017
4078
        os_aio_array_t* array;
5018
4079
        os_aio_slot_t*  slot;
5019
4080
        ulint           n_reserved;
5020
 
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
5021
4081
        time_t          current_time;
5022
4082
        double          time_elapsed;
5023
4083
        double          avg_bytes_read;
5050
4110
 
5051
4111
        n_reserved = 0;
5052
4112
 
5053
 
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
5054
 
 
5055
4113
        for (i = 0; i < array->n_slots; i++) {
5056
 
                ulint   seg_no;
5057
 
 
5058
4114
                slot = os_aio_array_get_nth_slot(array, i);
5059
4115
 
5060
 
                seg_no = (i * array->n_segments) / array->n_slots;
5061
4116
                if (slot->reserved) {
5062
4117
                        n_reserved++;
5063
 
                        n_res_seg[seg_no]++;
5064
4118
#if 0
5065
4119
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
5066
4120
                                (void*) slot->message1,
5074
4128
 
5075
4129
        fprintf(file, " %lu", (ulong) n_reserved);
5076
4130
 
5077
 
        os_aio_print_segment_info(file, n_res_seg, array);
5078
 
 
5079
4131
        os_mutex_exit(array->mutex);
5080
4132
 
5081
4133
        if (array == os_aio_read_array) {