~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-11-10 01:54:13 UTC
  • mto: (1921.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 1922.
  • Revision ID: brian@tangent.org-20101110015413-72hfqxgpklzjz0m5
Update so that we use shared_ptr from the cache throughout more of the
system.

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
23
15
St, Fifth Floor, Boston, MA 02110-1301 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
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 */
82
91
/* We do not call os_file_flush in every os_file_write. */
83
92
#endif /* UNIV_DO_FLUSH */
84
93
 
85
 
#ifndef UNIV_HOTBACKUP
 
94
#ifdef UNIV_HOTBACKUP
 
95
# define os_aio_use_native_aio  FALSE
 
96
#else /* UNIV_HOTBACKUP */
86
97
/* We use these mutexes to protect lseek + file i/o operation, if the
87
98
OS does not provide an atomic pread or pwrite, or similar */
88
99
#define OS_FILE_N_SEEK_MUTEXES  16
91
102
/* In simulated aio, merge at most this many consecutive i/os */
92
103
#define OS_AIO_MERGE_N_CONSECUTIVE      64
93
104
 
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
 
**********************************************************************/
 
105
/** If this flag is TRUE, then we will use the native aio of the
 
106
OS (provided we compiled Innobase with it in), otherwise we will
 
107
use simulated aio we build below with threads */
 
108
 
 
109
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
147
110
 
148
111
/** Flag: enable debug printout for asynchronous i/o */
149
112
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
150
113
 
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
114
/** The asynchronous i/o array slot structure */
159
115
typedef struct os_aio_slot_struct       os_aio_slot_t;
160
116
 
185
141
                                        which pending aio operation was
186
142
                                        completed */
187
143
#ifdef WIN_ASYNC_IO
188
 
        HANDLE          handle;         /*!< handle object we need in the
 
144
        os_event_t      event;          /*!< event object we need in the
189
145
                                        OVERLAPPED struct */
190
146
        OVERLAPPED      control;        /*!< Windows control block for the
191
147
                                        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
148
#endif
197
149
};
198
150
 
218
170
                                array of pending aio requests. A
219
171
                                thread can wait separately for any one
220
172
                                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
173
        ulint           n_reserved;
226
174
                                /*!< Number of reserved slots in the
227
175
                                aio array outside the ibuf segment */
228
176
        os_aio_slot_t*  slots;  /*!< Pointer to the slots in the array */
229
177
#ifdef __WIN__
230
 
        HANDLE*         handles;
 
178
        os_native_event_t* native_events;
231
179
                                /*!< Pointer to an array of OS native
232
180
                                event handles where we copied the
233
181
                                handles from slots, in the same
235
183
                                WaitForMultipleObjects; used only in
236
184
                                Windows */
237
185
#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
186
};
251
187
 
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
188
/** Array of events used in simulated aio */
264
189
static os_event_t*      os_aio_segment_wait_events      = NULL;
265
190
 
278
203
/** If the following is TRUE, read i/o handler threads try to
279
204
wait until a batch of new read requests have been posted */
280
205
static ibool    os_aio_recommend_sleep_for_read_threads = FALSE;
281
 
#endif /* !UNIV_HOTBACKUP */
 
206
#endif /* UNIV_HOTBACKUP */
282
207
 
283
208
UNIV_INTERN ulint       os_n_file_reads         = 0;
284
209
UNIV_INTERN ulint       os_bytes_read_since_printout = 0;
306
231
 
307
232
/***********************************************************************//**
308
233
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. */
 
234
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
311
235
UNIV_INTERN
312
236
ulint
313
237
os_get_os_version(void)
325
249
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
326
250
                return(OS_WIN95);
327
251
        } 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;
 
252
                if (os_info.dwMajorVersion <= 4) {
 
253
                        return(OS_WINNT);
 
254
                } else {
 
255
                        return(OS_WIN2000);
340
256
                }
341
257
        } else {
342
258
                ut_error;
493
409
 
494
410
        fflush(stderr);
495
411
 
496
 
        switch (err) {
497
 
        case ENOSPC:
 
412
        if (err == ENOSPC) {
498
413
                return(OS_FILE_DISK_FULL);
499
 
        case ENOENT:
 
414
        } else if (err == ENOENT) {
500
415
                return(OS_FILE_NOT_FOUND);
501
 
        case EEXIST:
 
416
        } else if (err == EEXIST) {
502
417
                return(OS_FILE_ALREADY_EXISTS);
503
 
        case EXDEV:
504
 
        case ENOTDIR:
505
 
        case EISDIR:
 
418
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
506
419
                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;
 
420
        } else {
 
421
                return(100 + err);
517
422
        }
518
 
        return(100 + err);
519
423
#endif
520
424
}
521
425
 
565
469
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
566
470
 
567
471
                return(TRUE);
568
 
        } else if (err == OS_FILE_AIO_INTERRUPTED) {
569
 
 
570
 
                return(TRUE);
571
472
        } else if (err == OS_FILE_ALREADY_EXISTS
572
473
                   || err == OS_FILE_PATH_ERROR) {
573
474
 
634
535
 
635
536
#undef USE_FILE_LOCK
636
537
#define USE_FILE_LOCK
637
 
#if defined(UNIV_HOTBACKUP) || defined(__WIN__)
 
538
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
638
539
/* InnoDB Hot Backup does not lock the data files.
639
540
 * On Windows, mandatory locking is used.
640
541
 */
662
563
                if (errno == EAGAIN || errno == EACCES) {
663
564
                        fprintf(stderr,
664
565
                                "InnoDB: Check that you do not already have"
665
 
                                " another drizzled process\n"
 
566
                                " another mysqld process\n"
666
567
                                "InnoDB: using the same InnoDB data"
667
568
                                " or log files.\n");
668
569
                }
684
585
{
685
586
        ulint   i;
686
587
 
687
 
        os_file_count_mutex = os_mutex_create();
 
588
        os_file_count_mutex = os_mutex_create(NULL);
688
589
 
689
590
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
690
 
                os_file_seek_mutexes[i] = os_mutex_create();
 
591
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
691
592
        }
692
593
}
693
594
 
694
595
/***********************************************************************//**
695
596
Creates a temporary file.  This function is like tmpfile(3), but
696
597
the temporary file is created in the MySQL temporary directory.
 
598
On Netware, this function is like tmpfile(3), because the C run-time
 
599
library of Netware does not expose the delete-on-close flag.
697
600
@return temporary file handle, or NULL on error */
698
601
UNIV_INTERN
699
602
FILE*
700
603
os_file_create_tmpfile(void)
701
604
/*========================*/
702
605
{
 
606
#ifdef __NETWARE__
 
607
        FILE*   file    = tmpfile();
 
608
#else /* __NETWARE__ */
703
609
        FILE*   file    = NULL;
704
610
        int     fd      = innobase_mysql_tmpfile();
705
611
 
706
612
        if (fd >= 0) {
707
613
                file = fdopen(fd, "w+b");
708
614
        }
 
615
#endif /* __NETWARE__ */
709
616
 
710
617
        if (!file) {
711
618
                ut_print_timestamp(stderr);
712
619
                fprintf(stderr,
713
620
                        "  InnoDB: Error: unable to create temporary file;"
714
621
                        " errno: %d\n", errno);
 
622
#ifndef __NETWARE__
715
623
                if (fd >= 0) {
716
624
                        close(fd);
717
625
                }
 
626
#endif /* !__NETWARE__ */
718
627
        }
719
628
 
720
629
        return(file);
900
809
#ifdef HAVE_READDIR_R
901
810
        ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
902
811
 
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
 
           ) {
 
812
        if (ret != 0) {
912
813
                fprintf(stderr,
913
814
                        "InnoDB: cannot read directory %s, error %lu\n",
914
815
                        dirname, (ulong)ret);
940
841
 
941
842
        strcpy(info->name, ent->d_name);
942
843
 
943
 
        full_path = static_cast<char* >(ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10));
 
844
        full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10);
944
845
 
945
846
        sprintf(full_path, "%s/%s", dirname, ent->d_name);
946
847
 
1035
936
}
1036
937
 
1037
938
/****************************************************************//**
1038
 
NOTE! Use the corresponding macro os_file_create_simple(), not directly
1039
 
this function!
1040
939
A simple function to open or create a file.
1041
940
@return own: handle to the file, not defined if error, error number
1042
941
can be retrieved with os_file_get_last_error */
1043
942
UNIV_INTERN
1044
943
os_file_t
1045
 
os_file_create_simple_func(
1046
 
/*=======================*/
 
944
os_file_create_simple(
 
945
/*==================*/
1047
946
        const char*     name,   /*!< in: name of the file or path as a
1048
947
                                null-terminated string */
1049
948
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
1178
1077
}
1179
1078
 
1180
1079
/****************************************************************//**
1181
 
NOTE! Use the corresponding macro
1182
 
os_file_create_simple_no_error_handling(), not directly this function!
1183
1080
A simple function to open or create a file.
1184
1081
@return own: handle to the file, not defined if error, error number
1185
1082
can be retrieved with os_file_get_last_error */
1186
1083
UNIV_INTERN
1187
1084
os_file_t
1188
 
os_file_create_simple_no_error_handling_func(
1189
 
/*=========================================*/
 
1085
os_file_create_simple_no_error_handling(
 
1086
/*====================================*/
1190
1087
        const char*     name,   /*!< in: name of the file or path as a
1191
1088
                                null-terminated string */
1192
1089
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1298
1195
os_file_set_nocache(
1299
1196
/*================*/
1300
1197
        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
 
1198
        const char*     file_name,      /*!< in: file name, used in the
 
1199
                                        diagnostic message */
 
1200
        const char*     operation_name) /*!< in: "open" or "create"; used in the
1304
1201
                                        diagnostic message */
1305
1202
{
1306
1203
        /* some versions of Solaris may not have DIRECTIO_ON */
1339
1236
}
1340
1237
 
1341
1238
/****************************************************************//**
1342
 
NOTE! Use the corresponding macro os_file_create(), not directly
1343
 
this function!
1344
1239
Opens an existing file or creates a new.
1345
1240
@return own: handle to the file, not defined if error, error number
1346
1241
can be retrieved with os_file_get_last_error */
1347
1242
UNIV_INTERN
1348
1243
os_file_t
1349
 
os_file_create_func(
1350
 
/*================*/
 
1244
os_file_create(
 
1245
/*===========*/
1351
1246
        const char*     name,   /*!< in: name of the file or path as a
1352
1247
                                null-terminated string */
1353
1248
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1397
1292
                buffering of writes in the OS */
1398
1293
                attributes = 0;
1399
1294
#ifdef WIN_ASYNC_IO
1400
 
                if (srv_use_native_aio) {
 
1295
                if (os_aio_use_native_aio) {
1401
1296
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
1402
1297
                }
1403
1298
#endif
1460
1355
 
1461
1356
                /* When srv_file_per_table is on, file creation failure may not
1462
1357
                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 */
 
1358
                case of unknown errors. */
1468
1359
                if (srv_file_per_table) {
1469
1360
                        retry = os_file_handle_error_no_exit(name,
1470
1361
                                                create_mode == OS_FILE_CREATE ?
1488
1379
        int             create_flag;
1489
1380
        ibool           retry;
1490
1381
        const char*     mode_str        = NULL;
 
1382
        const char*     type_str        = NULL;
 
1383
        const char*     purpose_str     = NULL;
1491
1384
 
1492
1385
try_again:
1493
1386
        ut_a(name);
1507
1400
                ut_error;
1508
1401
        }
1509
1402
 
1510
 
        ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
1511
 
        ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL);
1512
 
 
 
1403
        if (type == OS_LOG_FILE) {
 
1404
                type_str = "LOG";
 
1405
        } else if (type == OS_DATA_FILE) {
 
1406
                type_str = "DATA";
 
1407
        } else {
 
1408
                ut_error;
 
1409
        }
 
1410
 
 
1411
        if (purpose == OS_FILE_AIO) {
 
1412
                purpose_str = "AIO";
 
1413
        } else if (purpose == OS_FILE_NORMAL) {
 
1414
                purpose_str = "NORMAL";
 
1415
        } else {
 
1416
                ut_error;
 
1417
        }
 
1418
 
 
1419
#if 0
 
1420
        fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n",
 
1421
                name, mode_str, type_str, purpose_str);
 
1422
#endif
1513
1423
#ifdef O_SYNC
1514
1424
        /* We let O_SYNC only affect log files; note that we map O_DSYNC to
1515
1425
        O_SYNC because the datasync options seemed to corrupt files in 2001
1532
1442
 
1533
1443
                /* When srv_file_per_table is on, file creation failure may not
1534
1444
                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 */
 
1445
                case of unknown errors. */
1540
1446
                if (srv_file_per_table) {
1541
1447
                        retry = os_file_handle_error_no_exit(name,
1542
1448
                                                create_mode == OS_FILE_CREATE ?
1721
1627
}
1722
1628
 
1723
1629
/***********************************************************************//**
1724
 
NOTE! Use the corresponding macro os_file_rename(), not directly this function!
1725
1630
Renames a file (can also move it to another directory). It is safest that the
1726
1631
file is closed before calling this function.
1727
1632
@return TRUE if success */
1728
1633
UNIV_INTERN
1729
1634
ibool
1730
 
os_file_rename_func(
1731
 
/*================*/
 
1635
os_file_rename(
 
1636
/*===========*/
1732
1637
        const char*     oldpath,/*!< in: old file path as a null-terminated
1733
1638
                                string */
1734
1639
        const char*     newpath)/*!< in: new file path */
1761
1666
}
1762
1667
 
1763
1668
/***********************************************************************//**
1764
 
NOTE! Use the corresponding macro os_file_close(), not directly this function!
1765
1669
Closes a file handle. In case of error, error number can be retrieved with
1766
1670
os_file_get_last_error.
1767
1671
@return TRUE if success */
1768
1672
UNIV_INTERN
1769
1673
ibool
1770
 
os_file_close_func(
1771
 
/*===============*/
 
1674
os_file_close(
 
1675
/*==========*/
1772
1676
        os_file_t       file)   /*!< in, own: handle to a file */
1773
1677
{
1774
1678
#ifdef __WIN__
1937
1841
        /* Write up to 1 megabyte at a time. */
1938
1842
        buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
1939
1843
                * UNIV_PAGE_SIZE;
1940
 
        buf2 = static_cast<unsigned char *>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
 
1844
        buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
1941
1845
 
1942
1846
        /* Align the buffer for possible raw i/o */
1943
 
        buf = static_cast<unsigned char *>(ut_align(buf2, UNIV_PAGE_SIZE));
 
1847
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
1944
1848
 
1945
1849
        /* Write buffer full of zeros */
1946
1850
        memset(buf, 0, buf_size);
2064
1968
#endif /* !__WIN__ */
2065
1969
 
2066
1970
/***********************************************************************//**
2067
 
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
2068
1971
Flushes the write buffers of a given file to the disk.
2069
1972
@return TRUE if success */
2070
1973
UNIV_INTERN
2071
1974
ibool
2072
 
os_file_flush_func(
2073
 
/*===============*/
 
1975
os_file_flush(
 
1976
/*==========*/
2074
1977
        os_file_t       file)   /*!< in, own: handle to a file */
2075
1978
{
2076
1979
#ifdef __WIN__
2377
2280
#endif
2378
2281
 
2379
2282
/*******************************************************************//**
2380
 
NOTE! Use the corresponding macro os_file_read(), not directly this
2381
 
function!
2382
2283
Requests a synchronous positioned read operation.
2383
2284
@return TRUE if request was successful, FALSE if fail */
2384
2285
UNIV_INTERN
2385
2286
ibool
2386
 
os_file_read_func(
2387
 
/*==============*/
 
2287
os_file_read(
 
2288
/*=========*/
2388
2289
        os_file_t       file,   /*!< in: handle to a file */
2389
2290
        void*           buf,    /*!< in: buffer where to read */
2390
2291
        ulint           offset, /*!< in: least significant 32 bits of file
2404
2305
        ulint           i;
2405
2306
#endif /* !UNIV_HOTBACKUP */
2406
2307
 
2407
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2408
 
        no more than 32 bits. */
2409
2308
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2410
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2411
2309
 
2412
2310
        os_n_file_reads++;
2413
2311
        os_bytes_read_since_printout += n;
2505
2403
}
2506
2404
 
2507
2405
/*******************************************************************//**
2508
 
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
2509
 
not directly this function!
2510
2406
Requests a synchronous positioned read operation. This function does not do
2511
2407
any error handling. In case of error it returns FALSE.
2512
2408
@return TRUE if request was successful, FALSE if fail */
2513
2409
UNIV_INTERN
2514
2410
ibool
2515
 
os_file_read_no_error_handling_func(
2516
 
/*================================*/
 
2411
os_file_read_no_error_handling(
 
2412
/*===========================*/
2517
2413
        os_file_t       file,   /*!< in: handle to a file */
2518
2414
        void*           buf,    /*!< in: buffer where to read */
2519
2415
        ulint           offset, /*!< in: least significant 32 bits of file
2533
2429
        ulint           i;
2534
2430
#endif /* !UNIV_HOTBACKUP */
2535
2431
 
2536
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2537
 
        no more than 32 bits. */
2538
2432
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2539
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2540
2433
 
2541
2434
        os_n_file_reads++;
2542
2435
        os_bytes_read_since_printout += n;
2638
2531
}
2639
2532
 
2640
2533
/*******************************************************************//**
2641
 
NOTE! Use the corresponding macro os_file_write(), not directly
2642
 
this function!
2643
2534
Requests a synchronous write operation.
2644
2535
@return TRUE if request was successful, FALSE if fail */
2645
2536
UNIV_INTERN
2646
2537
ibool
2647
 
os_file_write_func(
2648
 
/*===============*/
 
2538
os_file_write(
 
2539
/*==========*/
2649
2540
        const char*     name,   /*!< in: name of the file or path as a
2650
2541
                                null-terminated string */
2651
2542
        os_file_t       file,   /*!< in: handle to a file */
2668
2559
        ulint           i;
2669
2560
#endif /* !UNIV_HOTBACKUP */
2670
2561
 
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);
 
2562
        ut_a((offset & 0xFFFFFFFF) == offset);
2675
2563
 
2676
2564
        os_n_file_writes++;
2677
2565
 
3107
2995
        return((array->slots) + index);
3108
2996
}
3109
2997
 
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 */
 
2998
/************************************************************************//**
 
2999
Creates an aio wait array.
 
3000
@return own: aio array */
3203
3001
static
3204
3002
os_aio_array_t*
3205
3003
os_aio_array_create(
3206
3004
/*================*/
3207
 
        ulint   n,              /*!< in: maximum number of pending aio
3208
 
                                operations allowed; n must be
3209
 
                                divisible by n_segments */
 
3005
        ulint   n,              /*!< in: maximum number of pending aio operations
 
3006
                                allowed; n must be divisible by n_segments */
3210
3007
        ulint   n_segments)     /*!< in: number of segments in the aio array */
3211
3008
{
3212
3009
        os_aio_array_t* array;
3214
3011
        os_aio_slot_t*  slot;
3215
3012
#ifdef WIN_ASYNC_IO
3216
3013
        OVERLAPPED*     over;
3217
 
#elif defined(LINUX_NATIVE_AIO)
3218
 
        struct io_event*        aio_event = NULL;
3219
3014
#endif
3220
3015
        ut_a(n > 0);
3221
3016
        ut_a(n_segments > 0);
3222
3017
 
3223
 
        array = static_cast<os_aio_array_t *>(ut_malloc(sizeof(os_aio_array_t)));
 
3018
        array = ut_malloc(sizeof(os_aio_array_t));
3224
3019
 
3225
 
        array->mutex            = os_mutex_create();
 
3020
        array->mutex            = os_mutex_create(NULL);
3226
3021
        array->not_full         = os_event_create(NULL);
3227
3022
        array->is_empty         = os_event_create(NULL);
3228
3023
 
3231
3026
        array->n_slots          = n;
3232
3027
        array->n_segments       = n_segments;
3233
3028
        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)));
 
3029
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
3236
3030
#ifdef __WIN__
3237
 
        array->handles          = ut_malloc(n * sizeof(HANDLE));
 
3031
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
3238
3032
#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
3033
        for (i = 0; i < n; i++) {
3276
3034
                slot = os_aio_array_get_nth_slot(array, i);
3277
3035
 
3278
3036
                slot->pos = i;
3279
3037
                slot->reserved = FALSE;
3280
3038
#ifdef WIN_ASYNC_IO
3281
 
                slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
 
3039
                slot->event = os_event_create(NULL);
3282
3040
 
3283
3041
                over = &(slot->control);
3284
3042
 
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;
 
3043
                over->hEvent = slot->event->handle;
 
3044
 
 
3045
                *((array->native_events) + i) = over->hEvent;
3294
3046
#endif
3295
3047
        }
3296
3048
 
3310
3062
 
3311
3063
        for (i = 0; i < array->n_slots; i++) {
3312
3064
                os_aio_slot_t*  slot = os_aio_array_get_nth_slot(array, i);
3313
 
                CloseHandle(slot->handle);
 
3065
                os_event_free(slot->event);
3314
3066
        }
3315
3067
#endif /* WIN_ASYNC_IO */
3316
3068
 
3317
3069
#ifdef __WIN__
3318
 
        ut_free(array->handles);
 
3070
        ut_free(array->native_events);
3319
3071
#endif /* __WIN__ */
3320
3072
        os_mutex_free(array->mutex);
3321
3073
        os_event_free(array->not_full);
3322
3074
        os_event_free(array->is_empty);
3323
3075
 
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
3076
        ut_free(array->slots);
3332
3077
        ut_free(array);
3333
3078
}
3340
3085
segment in these arrays. This function also creates the sync array.
3341
3086
No i/o handler thread needs to be created for that */
3342
3087
UNIV_INTERN
3343
 
ibool
 
3088
void
3344
3089
os_aio_init(
3345
3090
/*========*/
3346
3091
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3365
3110
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3366
3111
 
3367
3112
        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
3113
 
3372
3114
        srv_io_thread_function[0] = "insert buffer thread";
3373
3115
 
3374
3116
        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
3117
 
3379
3118
        srv_io_thread_function[1] = "log thread";
3380
3119
 
3381
3120
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3382
3121
                                                n_read_segs);
3383
 
        if (os_aio_read_array == NULL) {
3384
 
                goto err_exit;
3385
 
        }
3386
 
 
3387
3122
        for (i = 2; i < 2 + n_read_segs; i++) {
3388
3123
                ut_a(i < SRV_MAX_N_IO_THREADS);
3389
3124
                srv_io_thread_function[i] = "read thread";
3391
3126
 
3392
3127
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3393
3128
                                                 n_write_segs);
3394
 
        if (os_aio_write_array == NULL) {
3395
 
                goto err_exit;
3396
 
        }
3397
 
 
3398
3129
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3399
3130
                ut_a(i < SRV_MAX_N_IO_THREADS);
3400
3131
                srv_io_thread_function[i] = "write thread";
3401
3132
        }
3402
3133
 
3403
3134
        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
3135
 
3409
3136
        os_aio_n_segments = n_segments;
3410
3137
 
3411
3138
        os_aio_validate();
3412
3139
 
3413
 
        os_aio_segment_wait_events = static_cast<os_event_t *>(ut_malloc(n_segments * sizeof(void*)));
 
3140
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
3414
3141
 
3415
3142
        for (i = 0; i < n_segments; i++) {
3416
3143
                os_aio_segment_wait_events[i] = os_event_create(NULL);
3418
3145
 
3419
3146
        os_last_printout = time(NULL);
3420
3147
 
3421
 
        return(TRUE);
3422
 
 
3423
 
err_exit:
3424
 
        return(FALSE);
3425
 
 
3426
3148
}
3427
3149
 
3428
3150
/***********************************************************************
3468
3190
 
3469
3191
        for (i = 0; i < array->n_slots; i++) {
3470
3192
 
3471
 
                SetEvent((array->slots + i)->handle);
 
3193
                os_event_set((array->slots + i)->event);
3472
3194
        }
3473
3195
}
3474
3196
#endif
3489
3211
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3490
3212
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3491
3213
        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
3214
#endif
3506
3215
        /* This loop wakes up all simulated ai/o threads */
3507
3216
 
3619
3328
                                offset */
3620
3329
        ulint           len)    /*!< in: length of the block to read or write */
3621
3330
{
3622
 
        os_aio_slot_t*  slot = NULL;
 
3331
        os_aio_slot_t*  slot;
3623
3332
#ifdef WIN_ASYNC_IO
3624
3333
        OVERLAPPED*     control;
3625
 
 
3626
 
#elif defined(LINUX_NATIVE_AIO)
3627
 
 
3628
 
        struct iocb*    iocb;
3629
 
        off_t           aio_offset;
3630
 
 
3631
3334
#endif
3632
3335
        ulint           i;
3633
 
        ulint           counter;
3634
3336
        ulint           slots_per_seg;
3635
3337
        ulint           local_seg;
3636
3338
 
3637
 
#ifdef WIN_ASYNC_IO
3638
 
        ut_a((len & 0xFFFFFFFFUL) == len);
3639
 
#endif
3640
 
 
3641
3339
        /* No need of a mutex. Only reading constant fields */
3642
3340
        slots_per_seg = array->n_slots / array->n_segments;
3643
3341
 
3653
3351
        if (array->n_reserved == array->n_slots) {
3654
3352
                os_mutex_exit(array->mutex);
3655
3353
 
3656
 
                if (!srv_use_native_aio) {
 
3354
                if (!os_aio_use_native_aio) {
3657
3355
                        /* If the handler threads are suspended, wake them
3658
3356
                        so that we get more slots */
3659
3357
 
3665
3363
                goto loop;
3666
3364
        }
3667
3365
 
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;
 
3366
        /* First try to find a slot in the preferred local segment */
 
3367
        for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
 
3368
                slot = os_aio_array_get_nth_slot(array, i);
 
3369
 
 
3370
                if (slot->reserved == FALSE) {
 
3371
                        goto found;
 
3372
                }
 
3373
        }
 
3374
 
 
3375
        /* Fall back to a full scan. We are guaranteed to find a slot */
 
3376
        for (i = 0;; i++) {
 
3377
                slot = os_aio_array_get_nth_slot(array, i);
 
3378
 
 
3379
                if (slot->reserved == FALSE) {
 
3380
                        goto found;
 
3381
                }
 
3382
        }
3684
3383
 
3685
3384
found:
3686
3385
        ut_a(slot->reserved == FALSE);
3702
3401
        slot->name     = name;
3703
3402
        slot->len      = len;
3704
3403
        slot->type     = type;
3705
 
        slot->buf      = static_cast<unsigned char *>(buf);
 
3404
        slot->buf      = buf;
3706
3405
        slot->offset   = offset;
3707
3406
        slot->offset_high = offset_high;
3708
3407
        slot->io_already_done = FALSE;
3711
3410
        control = &(slot->control);
3712
3411
        control->Offset = (DWORD)offset;
3713
3412
        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 */
 
3413
        os_event_reset(slot->event);
 
3414
#endif
 
3415
 
3751
3416
        os_mutex_exit(array->mutex);
3752
3417
 
3753
3418
        return(slot);
3782
3447
        }
3783
3448
 
3784
3449
#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
 
 
 
3450
        os_event_reset(slot->event);
3802
3451
#endif
3803
3452
        os_mutex_exit(array->mutex);
3804
3453
}
3818
3467
        ulint           n;
3819
3468
        ulint           i;
3820
3469
 
3821
 
        ut_ad(!srv_use_native_aio);
 
3470
        ut_ad(!os_aio_use_native_aio);
3822
3471
 
3823
3472
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3824
3473
 
3854
3503
{
3855
3504
        ulint   i;
3856
3505
 
3857
 
        if (srv_use_native_aio) {
 
3506
        if (os_aio_use_native_aio) {
3858
3507
                /* We do not use simulated aio: do nothing */
3859
3508
 
3860
3509
                return;
3886
3535
        os_aio_array_t* array;
3887
3536
        ulint           g;
3888
3537
 
3889
 
        if (srv_use_native_aio) {
 
3538
        if (os_aio_use_native_aio) {
3890
3539
                /* We do not use simulated aio: do nothing */
3891
3540
 
3892
3541
                return;
3905
3554
#endif /* __WIN__ */
3906
3555
}
3907
3556
 
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!
 
3557
/*******************************************************************//**
3958
3558
Requests an asynchronous i/o operation.
3959
3559
@return TRUE if request was queued successfully, FALSE if fail */
3960
3560
UNIV_INTERN
3961
3561
ibool
3962
 
os_aio_func(
3963
 
/*========*/
 
3562
os_aio(
 
3563
/*===*/
3964
3564
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3965
3565
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3966
3566
                                to OS_AIO_SIMULATED_WAKE_LATER: the
4003
3603
        struct fil_node_struct * dummy_mess1;
4004
3604
        void*           dummy_mess2;
4005
3605
        ulint           dummy_type;
4006
 
#endif /* WIN_ASYNC_IO */
4007
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
 
3606
#endif
 
3607
        ulint           err             = 0;
4008
3608
        ibool           retry;
4009
 
#endif
4010
3609
        ulint           wake_later;
4011
3610
 
4012
3611
        ut_ad(file);
4015
3614
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
4016
3615
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
4017
3616
        ut_ad(os_aio_validate());
4018
 
#ifdef WIN_ASYNC_IO
4019
 
        ut_ad((n & 0xFFFFFFFFUL) == n);
4020
 
#endif
4021
3617
 
4022
3618
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
4023
3619
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
4024
3620
 
4025
3621
        if (mode == OS_AIO_SYNC
4026
3622
#ifdef WIN_ASYNC_IO
4027
 
            && !srv_use_native_aio
4028
 
#endif /* WIN_ASYNC_IO */
 
3623
            && !os_aio_use_native_aio
 
3624
#endif
4029
3625
            ) {
4030
3626
                /* This is actually an ordinary synchronous read or write:
4031
3627
                no need to use an i/o-handler thread. NOTE that if we use
4044
3640
                return(os_file_write(name, file, buf, offset, offset_high, n));
4045
3641
        }
4046
3642
 
4047
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4048
3643
try_again:
4049
 
#endif
4050
3644
        if (mode == OS_AIO_NORMAL) {
4051
3645
                if (type == OS_FILE_READ) {
4052
3646
                        array = os_aio_read_array;
4066
3660
                array = os_aio_log_array;
4067
3661
        } else if (mode == OS_AIO_SYNC) {
4068
3662
                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
3663
        } else {
4075
3664
                array = NULL; /* Eliminate compiler warning */
4076
3665
                ut_error;
4079
3668
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
4080
3669
                                         name, buf, offset, offset_high, n);
4081
3670
        if (type == OS_FILE_READ) {
4082
 
                if (srv_use_native_aio) {
 
3671
                if (os_aio_use_native_aio) {
 
3672
#ifdef WIN_ASYNC_IO
4083
3673
                        os_n_file_reads++;
4084
 
                        os_bytes_read_since_printout += n;
4085
 
#ifdef WIN_ASYNC_IO
 
3674
                        os_bytes_read_since_printout += len;
 
3675
 
4086
3676
                        ret = ReadFile(file, buf, (DWORD)n, &len,
4087
3677
                                       &(slot->control));
4088
 
 
4089
 
#elif defined(LINUX_NATIVE_AIO)
4090
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4091
 
                                goto err_exit;
4092
 
                        }
4093
3678
#endif
4094
3679
                } else {
4095
3680
                        if (!wake_later) {
4099
3684
                        }
4100
3685
                }
4101
3686
        } else if (type == OS_FILE_WRITE) {
4102
 
                if (srv_use_native_aio) {
 
3687
                if (os_aio_use_native_aio) {
 
3688
#ifdef WIN_ASYNC_IO
4103
3689
                        os_n_file_writes++;
4104
 
#ifdef WIN_ASYNC_IO
4105
3690
                        ret = WriteFile(file, buf, (DWORD)n, &len,
4106
3691
                                        &(slot->control));
4107
 
 
4108
 
#elif defined(LINUX_NATIVE_AIO)
4109
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4110
 
                                goto err_exit;
4111
 
                        }
4112
3692
#endif
4113
3693
                } else {
4114
3694
                        if (!wake_later) {
4122
3702
        }
4123
3703
 
4124
3704
#ifdef WIN_ASYNC_IO
4125
 
        if (srv_use_native_aio) {
 
3705
        if (os_aio_use_native_aio) {
4126
3706
                if ((ret && len == n)
4127
3707
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
4128
3708
                        /* aio was queued successfully! */
4145
3725
                        return(TRUE);
4146
3726
                }
4147
3727
 
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:
 
3728
                err = 1; /* Fall through the next if */
 
3729
        }
 
3730
#endif
 
3731
        if (err == 0) {
 
3732
                /* aio was queued successfully! */
 
3733
 
 
3734
                return(TRUE);
 
3735
        }
 
3736
 
4156
3737
        os_aio_array_free_slot(array, slot);
4157
3738
 
4158
3739
        retry = os_file_handle_error(name,
4164
3745
        }
4165
3746
 
4166
3747
        return(FALSE);
4167
 
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
4168
3748
}
4169
3749
 
4170
3750
#ifdef WIN_ASYNC_IO
4224
3804
        n = array->n_slots / array->n_segments;
4225
3805
 
4226
3806
        if (array == os_aio_sync_array) {
4227
 
                WaitForSingleObject(
4228
 
                        os_aio_array_get_nth_slot(array, pos)->handle,
4229
 
                        INFINITE);
 
3807
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
4230
3808
                i = pos;
4231
3809
        } else {
4232
3810
                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);
 
3811
                i = os_event_wait_multiple(n,
 
3812
                                           (array->native_events)
 
3813
                                           + segment * n);
4241
3814
        }
4242
3815
 
4243
3816
        os_mutex_enter(array->mutex);
4264
3837
#ifdef UNIV_DO_FLUSH
4265
3838
                if (slot->type == OS_FILE_WRITE
4266
3839
                    && !os_do_not_call_flush_at_each_write) {
4267
 
                        if (!os_file_flush(slot->file)) {
4268
 
                                ut_error;
4269
 
                        }
 
3840
                        ut_a(TRUE == os_file_flush(slot->file));
4270
3841
                }
4271
3842
#endif /* UNIV_DO_FLUSH */
4272
3843
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
4283
3854
                /* retry failed read/write operation synchronously.
4284
3855
                No need to hold array->mutex. */
4285
3856
 
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
3857
                switch (slot->type) {
4301
3858
                case OS_FILE_WRITE:
4302
3859
                        ret = WriteFile(slot->file, slot->buf,
4303
 
                                        (DWORD) slot->len, &len,
 
3860
                                        slot->len, &len,
4304
3861
                                        &(slot->control));
4305
3862
 
4306
3863
                        break;
4307
3864
                case OS_FILE_READ:
4308
3865
                        ret = ReadFile(slot->file, slot->buf,
4309
 
                                       (DWORD) slot->len, &len,
 
3866
                                       slot->len, &len,
4310
3867
                                       &(slot->control));
4311
3868
 
4312
3869
                        break;
4314
3871
                        ut_error;
4315
3872
                }
4316
3873
 
4317
 
#ifdef UNIV_PFS_IO
4318
 
                register_pfs_file_io_end(locker, len);
4319
 
#endif
4320
 
 
4321
3874
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
4322
3875
                        /* aio was queued successfully!
4323
3876
                        We want a synchronous i/o operation on a
4339
3892
}
4340
3893
#endif
4341
3894
 
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
3895
/**********************************************************************//**
4593
3896
Does simulated aio. This function should be called by an i/o-handler
4594
3897
thread.
4627
3930
        ulint           n;
4628
3931
        ulint           i;
4629
3932
 
4630
 
        /* Fix compiler warning */
4631
 
        *consecutive_ios = NULL;
4632
 
 
4633
3933
        memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
4634
3934
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
4635
3935
 
4742
4042
                goto wait_for_io;
4743
4043
        }
4744
4044
 
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
4045
        slot = consecutive_ios[0];
4751
4046
 
4752
4047
        /* Check if there are several consecutive blocks to read or write */
4797
4092
                combined_buf = slot->buf;
4798
4093
                combined_buf2 = NULL;
4799
4094
        } else {
4800
 
                combined_buf2 = static_cast<unsigned char *>(ut_malloc(total_len + UNIV_PAGE_SIZE));
 
4095
                combined_buf2 = ut_malloc(total_len + UNIV_PAGE_SIZE);
4801
4096
 
4802
4097
                ut_a(combined_buf2);
4803
4098
 
4804
 
                combined_buf = static_cast<unsigned char *>(ut_align(combined_buf2, UNIV_PAGE_SIZE));
 
4099
                combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE);
4805
4100
        }
4806
4101
 
4807
4102
        /* We release the array mutex for the time of the i/o: NOTE that
4973
4268
}
4974
4269
 
4975
4270
/**********************************************************************//**
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
4271
Prints info of the aio arrays. */
5011
4272
UNIV_INTERN
5012
4273
void
5017
4278
        os_aio_array_t* array;
5018
4279
        os_aio_slot_t*  slot;
5019
4280
        ulint           n_reserved;
5020
 
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
5021
4281
        time_t          current_time;
5022
4282
        double          time_elapsed;
5023
4283
        double          avg_bytes_read;
5050
4310
 
5051
4311
        n_reserved = 0;
5052
4312
 
5053
 
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
5054
 
 
5055
4313
        for (i = 0; i < array->n_slots; i++) {
5056
 
                ulint   seg_no;
5057
 
 
5058
4314
                slot = os_aio_array_get_nth_slot(array, i);
5059
4315
 
5060
 
                seg_no = (i * array->n_segments) / array->n_slots;
5061
4316
                if (slot->reserved) {
5062
4317
                        n_reserved++;
5063
 
                        n_res_seg[seg_no]++;
5064
4318
#if 0
5065
4319
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
5066
4320
                                (void*) slot->message1,
5074
4328
 
5075
4329
        fprintf(file, " %lu", (ulong) n_reserved);
5076
4330
 
5077
 
        os_aio_print_segment_info(file, n_res_seg, array);
5078
 
 
5079
4331
        os_mutex_exit(array->mutex);
5080
4332
 
5081
4333
        if (array == os_aio_read_array) {