~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-11-08 18:26:08 UTC
  • mto: This revision was merged to the branch mainline in revision 1931.
  • Revision ID: mordred@inaugust.com-20101108182608-lci86acl7r53sbi3
Replaced auto_ptr with scoped_ptr.

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.
 
3
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2009, Percona Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted
7
7
by Percona Inc.. Those modifications are
32
32
*******************************************************/
33
33
 
34
34
#include "os0file.h"
35
 
 
36
 
#ifdef UNIV_NONINL
37
 
#include "os0file.ic"
38
 
#endif
39
 
 
40
35
#include "ut0mem.h"
41
36
#include "srv0srv.h"
42
37
#include "srv0start.h"
57
52
# endif /* __WIN__ */
58
53
#endif /* !UNIV_HOTBACKUP */
59
54
 
60
 
#if defined(LINUX_NATIVE_AIO)
61
 
#include <libaio.h>
62
 
#endif
63
 
 
64
55
/* This specifies the file permissions InnoDB uses when it creates files in
65
56
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
66
57
my_umask */
82
73
/* We do not call os_file_flush in every os_file_write. */
83
74
#endif /* UNIV_DO_FLUSH */
84
75
 
85
 
#ifndef UNIV_HOTBACKUP
 
76
#ifdef UNIV_HOTBACKUP
 
77
# define os_aio_use_native_aio  FALSE
 
78
#else /* UNIV_HOTBACKUP */
86
79
/* We use these mutexes to protect lseek + file i/o operation, if the
87
80
OS does not provide an atomic pread or pwrite, or similar */
88
81
#define OS_FILE_N_SEEK_MUTEXES  16
91
84
/* In simulated aio, merge at most this many consecutive i/os */
92
85
#define OS_AIO_MERGE_N_CONSECUTIVE      64
93
86
 
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
 
**********************************************************************/
 
87
/** If this flag is TRUE, then we will use the native aio of the
 
88
OS (provided we compiled Innobase with it in), otherwise we will
 
89
use simulated aio we build below with threads */
 
90
 
 
91
UNIV_INTERN ibool       os_aio_use_native_aio   = FALSE;
147
92
 
148
93
/** Flag: enable debug printout for asynchronous i/o */
149
94
UNIV_INTERN ibool       os_aio_print_debug      = FALSE;
150
95
 
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
96
/** The asynchronous i/o array slot structure */
159
97
typedef struct os_aio_slot_struct       os_aio_slot_t;
160
98
 
185
123
                                        which pending aio operation was
186
124
                                        completed */
187
125
#ifdef WIN_ASYNC_IO
188
 
        HANDLE          handle;         /*!< handle object we need in the
 
126
        os_event_t      event;          /*!< event object we need in the
189
127
                                        OVERLAPPED struct */
190
128
        OVERLAPPED      control;        /*!< Windows control block for the
191
129
                                        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
130
#endif
197
131
};
198
132
 
218
152
                                array of pending aio requests. A
219
153
                                thread can wait separately for any one
220
154
                                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
155
        ulint           n_reserved;
226
156
                                /*!< Number of reserved slots in the
227
157
                                aio array outside the ibuf segment */
228
158
        os_aio_slot_t*  slots;  /*!< Pointer to the slots in the array */
229
159
#ifdef __WIN__
230
 
        HANDLE*         handles;
 
160
        os_native_event_t* native_events;
231
161
                                /*!< Pointer to an array of OS native
232
162
                                event handles where we copied the
233
163
                                handles from slots, in the same
235
165
                                WaitForMultipleObjects; used only in
236
166
                                Windows */
237
167
#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
168
};
251
169
 
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
170
/** Array of events used in simulated aio */
264
171
static os_event_t*      os_aio_segment_wait_events      = NULL;
265
172
 
278
185
/** If the following is TRUE, read i/o handler threads try to
279
186
wait until a batch of new read requests have been posted */
280
187
static ibool    os_aio_recommend_sleep_for_read_threads = FALSE;
281
 
#endif /* !UNIV_HOTBACKUP */
 
188
#endif /* UNIV_HOTBACKUP */
282
189
 
283
190
UNIV_INTERN ulint       os_n_file_reads         = 0;
284
191
UNIV_INTERN ulint       os_bytes_read_since_printout = 0;
306
213
 
307
214
/***********************************************************************//**
308
215
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. */
 
216
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
311
217
UNIV_INTERN
312
218
ulint
313
219
os_get_os_version(void)
325
231
        } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
326
232
                return(OS_WIN95);
327
233
        } 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;
 
234
                if (os_info.dwMajorVersion <= 4) {
 
235
                        return(OS_WINNT);
 
236
                } else {
 
237
                        return(OS_WIN2000);
340
238
                }
341
239
        } else {
342
240
                ut_error;
493
391
 
494
392
        fflush(stderr);
495
393
 
496
 
        switch (err) {
497
 
        case ENOSPC:
 
394
        if (err == ENOSPC) {
498
395
                return(OS_FILE_DISK_FULL);
499
 
        case ENOENT:
 
396
        } else if (err == ENOENT) {
500
397
                return(OS_FILE_NOT_FOUND);
501
 
        case EEXIST:
 
398
        } else if (err == EEXIST) {
502
399
                return(OS_FILE_ALREADY_EXISTS);
503
 
        case EXDEV:
504
 
        case ENOTDIR:
505
 
        case EISDIR:
 
400
        } else if (err == EXDEV || err == ENOTDIR || err == EISDIR) {
506
401
                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;
 
402
        } else {
 
403
                return(100 + err);
517
404
        }
518
 
        return(100 + err);
519
405
#endif
520
406
}
521
407
 
565
451
        } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
566
452
 
567
453
                return(TRUE);
568
 
        } else if (err == OS_FILE_AIO_INTERRUPTED) {
569
 
 
570
 
                return(TRUE);
571
454
        } else if (err == OS_FILE_ALREADY_EXISTS
572
455
                   || err == OS_FILE_PATH_ERROR) {
573
456
 
634
517
 
635
518
#undef USE_FILE_LOCK
636
519
#define USE_FILE_LOCK
637
 
#if defined(UNIV_HOTBACKUP) || defined(__WIN__)
 
520
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
638
521
/* InnoDB Hot Backup does not lock the data files.
639
522
 * On Windows, mandatory locking is used.
640
523
 */
662
545
                if (errno == EAGAIN || errno == EACCES) {
663
546
                        fprintf(stderr,
664
547
                                "InnoDB: Check that you do not already have"
665
 
                                " another drizzled process\n"
 
548
                                " another mysqld process\n"
666
549
                                "InnoDB: using the same InnoDB data"
667
550
                                " or log files.\n");
668
551
                }
684
567
{
685
568
        ulint   i;
686
569
 
687
 
        os_file_count_mutex = os_mutex_create();
 
570
        os_file_count_mutex = os_mutex_create(NULL);
688
571
 
689
572
        for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
690
 
                os_file_seek_mutexes[i] = os_mutex_create();
 
573
                os_file_seek_mutexes[i] = os_mutex_create(NULL);
691
574
        }
692
575
}
693
576
 
694
577
/***********************************************************************//**
695
578
Creates a temporary file.  This function is like tmpfile(3), but
696
579
the temporary file is created in the MySQL temporary directory.
 
580
On Netware, this function is like tmpfile(3), because the C run-time
 
581
library of Netware does not expose the delete-on-close flag.
697
582
@return temporary file handle, or NULL on error */
698
583
UNIV_INTERN
699
584
FILE*
700
585
os_file_create_tmpfile(void)
701
586
/*========================*/
702
587
{
 
588
#ifdef __NETWARE__
 
589
        FILE*   file    = tmpfile();
 
590
#else /* __NETWARE__ */
703
591
        FILE*   file    = NULL;
704
592
        int     fd      = innobase_mysql_tmpfile();
705
593
 
706
594
        if (fd >= 0) {
707
595
                file = fdopen(fd, "w+b");
708
596
        }
 
597
#endif /* __NETWARE__ */
709
598
 
710
599
        if (!file) {
711
600
                ut_print_timestamp(stderr);
712
601
                fprintf(stderr,
713
602
                        "  InnoDB: Error: unable to create temporary file;"
714
603
                        " errno: %d\n", errno);
 
604
#ifndef __NETWARE__
715
605
                if (fd >= 0) {
716
606
                        close(fd);
717
607
                }
 
608
#endif /* !__NETWARE__ */
718
609
        }
719
610
 
720
611
        return(file);
940
831
 
941
832
        strcpy(info->name, ent->d_name);
942
833
 
943
 
        full_path = static_cast<char* >(ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10));
 
834
        full_path = ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10);
944
835
 
945
836
        sprintf(full_path, "%s/%s", dirname, ent->d_name);
946
837
 
1035
926
}
1036
927
 
1037
928
/****************************************************************//**
1038
 
NOTE! Use the corresponding macro os_file_create_simple(), not directly
1039
 
this function!
1040
929
A simple function to open or create a file.
1041
930
@return own: handle to the file, not defined if error, error number
1042
931
can be retrieved with os_file_get_last_error */
1043
932
UNIV_INTERN
1044
933
os_file_t
1045
 
os_file_create_simple_func(
1046
 
/*=======================*/
 
934
os_file_create_simple(
 
935
/*==================*/
1047
936
        const char*     name,   /*!< in: name of the file or path as a
1048
937
                                null-terminated string */
1049
938
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file is
1178
1067
}
1179
1068
 
1180
1069
/****************************************************************//**
1181
 
NOTE! Use the corresponding macro
1182
 
os_file_create_simple_no_error_handling(), not directly this function!
1183
1070
A simple function to open or create a file.
1184
1071
@return own: handle to the file, not defined if error, error number
1185
1072
can be retrieved with os_file_get_last_error */
1186
1073
UNIV_INTERN
1187
1074
os_file_t
1188
 
os_file_create_simple_no_error_handling_func(
1189
 
/*=========================================*/
 
1075
os_file_create_simple_no_error_handling(
 
1076
/*====================================*/
1190
1077
        const char*     name,   /*!< in: name of the file or path as a
1191
1078
                                null-terminated string */
1192
1079
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1298
1185
os_file_set_nocache(
1299
1186
/*================*/
1300
1187
        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
 
1188
        const char*     file_name,      /*!< in: file name, used in the
 
1189
                                        diagnostic message */
 
1190
        const char*     operation_name) /*!< in: "open" or "create"; used in the
1304
1191
                                        diagnostic message */
1305
1192
{
1306
1193
        /* some versions of Solaris may not have DIRECTIO_ON */
1339
1226
}
1340
1227
 
1341
1228
/****************************************************************//**
1342
 
NOTE! Use the corresponding macro os_file_create(), not directly
1343
 
this function!
1344
1229
Opens an existing file or creates a new.
1345
1230
@return own: handle to the file, not defined if error, error number
1346
1231
can be retrieved with os_file_get_last_error */
1347
1232
UNIV_INTERN
1348
1233
os_file_t
1349
 
os_file_create_func(
1350
 
/*================*/
 
1234
os_file_create(
 
1235
/*===========*/
1351
1236
        const char*     name,   /*!< in: name of the file or path as a
1352
1237
                                null-terminated string */
1353
1238
        ulint           create_mode,/*!< in: OS_FILE_OPEN if an existing file
1397
1282
                buffering of writes in the OS */
1398
1283
                attributes = 0;
1399
1284
#ifdef WIN_ASYNC_IO
1400
 
                if (srv_use_native_aio) {
 
1285
                if (os_aio_use_native_aio) {
1401
1286
                        attributes = attributes | FILE_FLAG_OVERLAPPED;
1402
1287
                }
1403
1288
#endif
1460
1345
 
1461
1346
                /* When srv_file_per_table is on, file creation failure may not
1462
1347
                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 */
 
1348
                case of unknown errors. */
1468
1349
                if (srv_file_per_table) {
1469
1350
                        retry = os_file_handle_error_no_exit(name,
1470
1351
                                                create_mode == OS_FILE_CREATE ?
1488
1369
        int             create_flag;
1489
1370
        ibool           retry;
1490
1371
        const char*     mode_str        = NULL;
 
1372
        const char*     type_str        = NULL;
 
1373
        const char*     purpose_str     = NULL;
1491
1374
 
1492
1375
try_again:
1493
1376
        ut_a(name);
1507
1390
                ut_error;
1508
1391
        }
1509
1392
 
1510
 
        ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
1511
 
        ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL);
1512
 
 
 
1393
        if (type == OS_LOG_FILE) {
 
1394
                type_str = "LOG";
 
1395
        } else if (type == OS_DATA_FILE) {
 
1396
                type_str = "DATA";
 
1397
        } else {
 
1398
                ut_error;
 
1399
        }
 
1400
 
 
1401
        if (purpose == OS_FILE_AIO) {
 
1402
                purpose_str = "AIO";
 
1403
        } else if (purpose == OS_FILE_NORMAL) {
 
1404
                purpose_str = "NORMAL";
 
1405
        } else {
 
1406
                ut_error;
 
1407
        }
 
1408
 
 
1409
#if 0
 
1410
        fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n",
 
1411
                name, mode_str, type_str, purpose_str);
 
1412
#endif
1513
1413
#ifdef O_SYNC
1514
1414
        /* We let O_SYNC only affect log files; note that we map O_DSYNC to
1515
1415
        O_SYNC because the datasync options seemed to corrupt files in 2001
1532
1432
 
1533
1433
                /* When srv_file_per_table is on, file creation failure may not
1534
1434
                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 */
 
1435
                case of unknown errors. */
1540
1436
                if (srv_file_per_table) {
1541
1437
                        retry = os_file_handle_error_no_exit(name,
1542
1438
                                                create_mode == OS_FILE_CREATE ?
1721
1617
}
1722
1618
 
1723
1619
/***********************************************************************//**
1724
 
NOTE! Use the corresponding macro os_file_rename(), not directly this function!
1725
1620
Renames a file (can also move it to another directory). It is safest that the
1726
1621
file is closed before calling this function.
1727
1622
@return TRUE if success */
1728
1623
UNIV_INTERN
1729
1624
ibool
1730
 
os_file_rename_func(
1731
 
/*================*/
 
1625
os_file_rename(
 
1626
/*===========*/
1732
1627
        const char*     oldpath,/*!< in: old file path as a null-terminated
1733
1628
                                string */
1734
1629
        const char*     newpath)/*!< in: new file path */
1761
1656
}
1762
1657
 
1763
1658
/***********************************************************************//**
1764
 
NOTE! Use the corresponding macro os_file_close(), not directly this function!
1765
1659
Closes a file handle. In case of error, error number can be retrieved with
1766
1660
os_file_get_last_error.
1767
1661
@return TRUE if success */
1768
1662
UNIV_INTERN
1769
1663
ibool
1770
 
os_file_close_func(
1771
 
/*===============*/
 
1664
os_file_close(
 
1665
/*==========*/
1772
1666
        os_file_t       file)   /*!< in, own: handle to a file */
1773
1667
{
1774
1668
#ifdef __WIN__
1937
1831
        /* Write up to 1 megabyte at a time. */
1938
1832
        buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
1939
1833
                * UNIV_PAGE_SIZE;
1940
 
        buf2 = static_cast<unsigned char *>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
 
1834
        buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE);
1941
1835
 
1942
1836
        /* Align the buffer for possible raw i/o */
1943
 
        buf = static_cast<unsigned char *>(ut_align(buf2, UNIV_PAGE_SIZE));
 
1837
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
1944
1838
 
1945
1839
        /* Write buffer full of zeros */
1946
1840
        memset(buf, 0, buf_size);
2064
1958
#endif /* !__WIN__ */
2065
1959
 
2066
1960
/***********************************************************************//**
2067
 
NOTE! Use the corresponding macro os_file_flush(), not directly this function!
2068
1961
Flushes the write buffers of a given file to the disk.
2069
1962
@return TRUE if success */
2070
1963
UNIV_INTERN
2071
1964
ibool
2072
 
os_file_flush_func(
2073
 
/*===============*/
 
1965
os_file_flush(
 
1966
/*==========*/
2074
1967
        os_file_t       file)   /*!< in, own: handle to a file */
2075
1968
{
2076
1969
#ifdef __WIN__
2377
2270
#endif
2378
2271
 
2379
2272
/*******************************************************************//**
2380
 
NOTE! Use the corresponding macro os_file_read(), not directly this
2381
 
function!
2382
2273
Requests a synchronous positioned read operation.
2383
2274
@return TRUE if request was successful, FALSE if fail */
2384
2275
UNIV_INTERN
2385
2276
ibool
2386
 
os_file_read_func(
2387
 
/*==============*/
 
2277
os_file_read(
 
2278
/*=========*/
2388
2279
        os_file_t       file,   /*!< in: handle to a file */
2389
2280
        void*           buf,    /*!< in: buffer where to read */
2390
2281
        ulint           offset, /*!< in: least significant 32 bits of file
2404
2295
        ulint           i;
2405
2296
#endif /* !UNIV_HOTBACKUP */
2406
2297
 
2407
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2408
 
        no more than 32 bits. */
2409
2298
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2410
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2411
2299
 
2412
2300
        os_n_file_reads++;
2413
2301
        os_bytes_read_since_printout += n;
2505
2393
}
2506
2394
 
2507
2395
/*******************************************************************//**
2508
 
NOTE! Use the corresponding macro os_file_read_no_error_handling(),
2509
 
not directly this function!
2510
2396
Requests a synchronous positioned read operation. This function does not do
2511
2397
any error handling. In case of error it returns FALSE.
2512
2398
@return TRUE if request was successful, FALSE if fail */
2513
2399
UNIV_INTERN
2514
2400
ibool
2515
 
os_file_read_no_error_handling_func(
2516
 
/*================================*/
 
2401
os_file_read_no_error_handling(
 
2402
/*===========================*/
2517
2403
        os_file_t       file,   /*!< in: handle to a file */
2518
2404
        void*           buf,    /*!< in: buffer where to read */
2519
2405
        ulint           offset, /*!< in: least significant 32 bits of file
2533
2419
        ulint           i;
2534
2420
#endif /* !UNIV_HOTBACKUP */
2535
2421
 
2536
 
        /* On 64-bit Windows, ulint is 64 bits. But offset and n should be
2537
 
        no more than 32 bits. */
2538
2422
        ut_a((offset & 0xFFFFFFFFUL) == offset);
2539
 
        ut_a((n & 0xFFFFFFFFUL) == n);
2540
2423
 
2541
2424
        os_n_file_reads++;
2542
2425
        os_bytes_read_since_printout += n;
2638
2521
}
2639
2522
 
2640
2523
/*******************************************************************//**
2641
 
NOTE! Use the corresponding macro os_file_write(), not directly
2642
 
this function!
2643
2524
Requests a synchronous write operation.
2644
2525
@return TRUE if request was successful, FALSE if fail */
2645
2526
UNIV_INTERN
2646
2527
ibool
2647
 
os_file_write_func(
2648
 
/*===============*/
 
2528
os_file_write(
 
2529
/*==========*/
2649
2530
        const char*     name,   /*!< in: name of the file or path as a
2650
2531
                                null-terminated string */
2651
2532
        os_file_t       file,   /*!< in: handle to a file */
2668
2549
        ulint           i;
2669
2550
#endif /* !UNIV_HOTBACKUP */
2670
2551
 
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);
 
2552
        ut_a((offset & 0xFFFFFFFF) == offset);
2675
2553
 
2676
2554
        os_n_file_writes++;
2677
2555
 
3107
2985
        return((array->slots) + index);
3108
2986
}
3109
2987
 
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 */
 
2988
/************************************************************************//**
 
2989
Creates an aio wait array.
 
2990
@return own: aio array */
3203
2991
static
3204
2992
os_aio_array_t*
3205
2993
os_aio_array_create(
3206
2994
/*================*/
3207
 
        ulint   n,              /*!< in: maximum number of pending aio
3208
 
                                operations allowed; n must be
3209
 
                                divisible by n_segments */
 
2995
        ulint   n,              /*!< in: maximum number of pending aio operations
 
2996
                                allowed; n must be divisible by n_segments */
3210
2997
        ulint   n_segments)     /*!< in: number of segments in the aio array */
3211
2998
{
3212
2999
        os_aio_array_t* array;
3214
3001
        os_aio_slot_t*  slot;
3215
3002
#ifdef WIN_ASYNC_IO
3216
3003
        OVERLAPPED*     over;
3217
 
#elif defined(LINUX_NATIVE_AIO)
3218
 
        struct io_event*        aio_event = NULL;
3219
3004
#endif
3220
3005
        ut_a(n > 0);
3221
3006
        ut_a(n_segments > 0);
3222
3007
 
3223
 
        array = static_cast<os_aio_array_t *>(ut_malloc(sizeof(os_aio_array_t)));
 
3008
        array = ut_malloc(sizeof(os_aio_array_t));
3224
3009
 
3225
 
        array->mutex            = os_mutex_create();
 
3010
        array->mutex            = os_mutex_create(NULL);
3226
3011
        array->not_full         = os_event_create(NULL);
3227
3012
        array->is_empty         = os_event_create(NULL);
3228
3013
 
3231
3016
        array->n_slots          = n;
3232
3017
        array->n_segments       = n_segments;
3233
3018
        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)));
 
3019
        array->slots            = ut_malloc(n * sizeof(os_aio_slot_t));
3236
3020
#ifdef __WIN__
3237
 
        array->handles          = ut_malloc(n * sizeof(HANDLE));
 
3021
        array->native_events    = ut_malloc(n * sizeof(os_native_event_t));
3238
3022
#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
3023
        for (i = 0; i < n; i++) {
3276
3024
                slot = os_aio_array_get_nth_slot(array, i);
3277
3025
 
3278
3026
                slot->pos = i;
3279
3027
                slot->reserved = FALSE;
3280
3028
#ifdef WIN_ASYNC_IO
3281
 
                slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
 
3029
                slot->event = os_event_create(NULL);
3282
3030
 
3283
3031
                over = &(slot->control);
3284
3032
 
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;
 
3033
                over->hEvent = slot->event->handle;
 
3034
 
 
3035
                *((array->native_events) + i) = over->hEvent;
3294
3036
#endif
3295
3037
        }
3296
3038
 
3310
3052
 
3311
3053
        for (i = 0; i < array->n_slots; i++) {
3312
3054
                os_aio_slot_t*  slot = os_aio_array_get_nth_slot(array, i);
3313
 
                CloseHandle(slot->handle);
 
3055
                os_event_free(slot->event);
3314
3056
        }
3315
3057
#endif /* WIN_ASYNC_IO */
3316
3058
 
3317
3059
#ifdef __WIN__
3318
 
        ut_free(array->handles);
 
3060
        ut_free(array->native_events);
3319
3061
#endif /* __WIN__ */
3320
3062
        os_mutex_free(array->mutex);
3321
3063
        os_event_free(array->not_full);
3322
3064
        os_event_free(array->is_empty);
3323
3065
 
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
3066
        ut_free(array->slots);
3332
3067
        ut_free(array);
3333
3068
}
3340
3075
segment in these arrays. This function also creates the sync array.
3341
3076
No i/o handler thread needs to be created for that */
3342
3077
UNIV_INTERN
3343
 
ibool
 
3078
void
3344
3079
os_aio_init(
3345
3080
/*========*/
3346
3081
        ulint   n_per_seg,      /*<! in: maximum number of pending aio
3365
3100
        /* fprintf(stderr, "Array n per seg %lu\n", n_per_seg); */
3366
3101
 
3367
3102
        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
3103
 
3372
3104
        srv_io_thread_function[0] = "insert buffer thread";
3373
3105
 
3374
3106
        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
3107
 
3379
3108
        srv_io_thread_function[1] = "log thread";
3380
3109
 
3381
3110
        os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3382
3111
                                                n_read_segs);
3383
 
        if (os_aio_read_array == NULL) {
3384
 
                goto err_exit;
3385
 
        }
3386
 
 
3387
3112
        for (i = 2; i < 2 + n_read_segs; i++) {
3388
3113
                ut_a(i < SRV_MAX_N_IO_THREADS);
3389
3114
                srv_io_thread_function[i] = "read thread";
3391
3116
 
3392
3117
        os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
3393
3118
                                                 n_write_segs);
3394
 
        if (os_aio_write_array == NULL) {
3395
 
                goto err_exit;
3396
 
        }
3397
 
 
3398
3119
        for (i = 2 + n_read_segs; i < n_segments; i++) {
3399
3120
                ut_a(i < SRV_MAX_N_IO_THREADS);
3400
3121
                srv_io_thread_function[i] = "write thread";
3401
3122
        }
3402
3123
 
3403
3124
        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
3125
 
3409
3126
        os_aio_n_segments = n_segments;
3410
3127
 
3411
3128
        os_aio_validate();
3412
3129
 
3413
 
        os_aio_segment_wait_events = static_cast<os_event_t *>(ut_malloc(n_segments * sizeof(void*)));
 
3130
        os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*));
3414
3131
 
3415
3132
        for (i = 0; i < n_segments; i++) {
3416
3133
                os_aio_segment_wait_events[i] = os_event_create(NULL);
3418
3135
 
3419
3136
        os_last_printout = time(NULL);
3420
3137
 
3421
 
        return(TRUE);
3422
 
 
3423
 
err_exit:
3424
 
        return(FALSE);
3425
 
 
3426
3138
}
3427
3139
 
3428
3140
/***********************************************************************
3468
3180
 
3469
3181
        for (i = 0; i < array->n_slots; i++) {
3470
3182
 
3471
 
                SetEvent((array->slots + i)->handle);
 
3183
                os_event_set((array->slots + i)->event);
3472
3184
        }
3473
3185
}
3474
3186
#endif
3489
3201
        os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
3490
3202
        os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
3491
3203
        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
3204
#endif
3506
3205
        /* This loop wakes up all simulated ai/o threads */
3507
3206
 
3619
3318
                                offset */
3620
3319
        ulint           len)    /*!< in: length of the block to read or write */
3621
3320
{
3622
 
        os_aio_slot_t*  slot = NULL;
 
3321
        os_aio_slot_t*  slot;
3623
3322
#ifdef WIN_ASYNC_IO
3624
3323
        OVERLAPPED*     control;
3625
 
 
3626
 
#elif defined(LINUX_NATIVE_AIO)
3627
 
 
3628
 
        struct iocb*    iocb;
3629
 
        off_t           aio_offset;
3630
 
 
3631
3324
#endif
3632
3325
        ulint           i;
3633
 
        ulint           counter;
3634
3326
        ulint           slots_per_seg;
3635
3327
        ulint           local_seg;
3636
3328
 
3637
 
#ifdef WIN_ASYNC_IO
3638
 
        ut_a((len & 0xFFFFFFFFUL) == len);
3639
 
#endif
3640
 
 
3641
3329
        /* No need of a mutex. Only reading constant fields */
3642
3330
        slots_per_seg = array->n_slots / array->n_segments;
3643
3331
 
3653
3341
        if (array->n_reserved == array->n_slots) {
3654
3342
                os_mutex_exit(array->mutex);
3655
3343
 
3656
 
                if (!srv_use_native_aio) {
 
3344
                if (!os_aio_use_native_aio) {
3657
3345
                        /* If the handler threads are suspended, wake them
3658
3346
                        so that we get more slots */
3659
3347
 
3665
3353
                goto loop;
3666
3354
        }
3667
3355
 
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;
 
3356
        /* First try to find a slot in the preferred local segment */
 
3357
        for (i = local_seg * slots_per_seg; i < array->n_slots; i++) {
 
3358
                slot = os_aio_array_get_nth_slot(array, i);
 
3359
 
 
3360
                if (slot->reserved == FALSE) {
 
3361
                        goto found;
 
3362
                }
 
3363
        }
 
3364
 
 
3365
        /* Fall back to a full scan. We are guaranteed to find a slot */
 
3366
        for (i = 0;; i++) {
 
3367
                slot = os_aio_array_get_nth_slot(array, i);
 
3368
 
 
3369
                if (slot->reserved == FALSE) {
 
3370
                        goto found;
 
3371
                }
 
3372
        }
3684
3373
 
3685
3374
found:
3686
3375
        ut_a(slot->reserved == FALSE);
3702
3391
        slot->name     = name;
3703
3392
        slot->len      = len;
3704
3393
        slot->type     = type;
3705
 
        slot->buf      = static_cast<unsigned char *>(buf);
 
3394
        slot->buf      = buf;
3706
3395
        slot->offset   = offset;
3707
3396
        slot->offset_high = offset_high;
3708
3397
        slot->io_already_done = FALSE;
3711
3400
        control = &(slot->control);
3712
3401
        control->Offset = (DWORD)offset;
3713
3402
        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 */
 
3403
        os_event_reset(slot->event);
 
3404
#endif
 
3405
 
3751
3406
        os_mutex_exit(array->mutex);
3752
3407
 
3753
3408
        return(slot);
3782
3437
        }
3783
3438
 
3784
3439
#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
 
 
 
3440
        os_event_reset(slot->event);
3802
3441
#endif
3803
3442
        os_mutex_exit(array->mutex);
3804
3443
}
3818
3457
        ulint           n;
3819
3458
        ulint           i;
3820
3459
 
3821
 
        ut_ad(!srv_use_native_aio);
 
3460
        ut_ad(!os_aio_use_native_aio);
3822
3461
 
3823
3462
        segment = os_aio_get_array_and_local_segment(&array, global_segment);
3824
3463
 
3854
3493
{
3855
3494
        ulint   i;
3856
3495
 
3857
 
        if (srv_use_native_aio) {
 
3496
        if (os_aio_use_native_aio) {
3858
3497
                /* We do not use simulated aio: do nothing */
3859
3498
 
3860
3499
                return;
3886
3525
        os_aio_array_t* array;
3887
3526
        ulint           g;
3888
3527
 
3889
 
        if (srv_use_native_aio) {
 
3528
        if (os_aio_use_native_aio) {
3890
3529
                /* We do not use simulated aio: do nothing */
3891
3530
 
3892
3531
                return;
3905
3544
#endif /* __WIN__ */
3906
3545
}
3907
3546
 
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!
 
3547
/*******************************************************************//**
3958
3548
Requests an asynchronous i/o operation.
3959
3549
@return TRUE if request was queued successfully, FALSE if fail */
3960
3550
UNIV_INTERN
3961
3551
ibool
3962
 
os_aio_func(
3963
 
/*========*/
 
3552
os_aio(
 
3553
/*===*/
3964
3554
        ulint           type,   /*!< in: OS_FILE_READ or OS_FILE_WRITE */
3965
3555
        ulint           mode,   /*!< in: OS_AIO_NORMAL, ..., possibly ORed
3966
3556
                                to OS_AIO_SIMULATED_WAKE_LATER: the
4003
3593
        struct fil_node_struct * dummy_mess1;
4004
3594
        void*           dummy_mess2;
4005
3595
        ulint           dummy_type;
4006
 
#endif /* WIN_ASYNC_IO */
4007
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
 
3596
#endif
 
3597
        ulint           err             = 0;
4008
3598
        ibool           retry;
4009
 
#endif
4010
3599
        ulint           wake_later;
4011
3600
 
4012
3601
        ut_ad(file);
4015
3604
        ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
4016
3605
        ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
4017
3606
        ut_ad(os_aio_validate());
4018
 
#ifdef WIN_ASYNC_IO
4019
 
        ut_ad((n & 0xFFFFFFFFUL) == n);
4020
 
#endif
4021
3607
 
4022
3608
        wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
4023
3609
        mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
4024
3610
 
4025
3611
        if (mode == OS_AIO_SYNC
4026
3612
#ifdef WIN_ASYNC_IO
4027
 
            && !srv_use_native_aio
4028
 
#endif /* WIN_ASYNC_IO */
 
3613
            && !os_aio_use_native_aio
 
3614
#endif
4029
3615
            ) {
4030
3616
                /* This is actually an ordinary synchronous read or write:
4031
3617
                no need to use an i/o-handler thread. NOTE that if we use
4044
3630
                return(os_file_write(name, file, buf, offset, offset_high, n));
4045
3631
        }
4046
3632
 
4047
 
#if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
4048
3633
try_again:
4049
 
#endif
4050
3634
        if (mode == OS_AIO_NORMAL) {
4051
3635
                if (type == OS_FILE_READ) {
4052
3636
                        array = os_aio_read_array;
4066
3650
                array = os_aio_log_array;
4067
3651
        } else if (mode == OS_AIO_SYNC) {
4068
3652
                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
3653
        } else {
4075
3654
                array = NULL; /* Eliminate compiler warning */
4076
3655
                ut_error;
4079
3658
        slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
4080
3659
                                         name, buf, offset, offset_high, n);
4081
3660
        if (type == OS_FILE_READ) {
4082
 
                if (srv_use_native_aio) {
 
3661
                if (os_aio_use_native_aio) {
 
3662
#ifdef WIN_ASYNC_IO
4083
3663
                        os_n_file_reads++;
4084
 
                        os_bytes_read_since_printout += n;
4085
 
#ifdef WIN_ASYNC_IO
 
3664
                        os_bytes_read_since_printout += len;
 
3665
 
4086
3666
                        ret = ReadFile(file, buf, (DWORD)n, &len,
4087
3667
                                       &(slot->control));
4088
 
 
4089
 
#elif defined(LINUX_NATIVE_AIO)
4090
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4091
 
                                goto err_exit;
4092
 
                        }
4093
3668
#endif
4094
3669
                } else {
4095
3670
                        if (!wake_later) {
4099
3674
                        }
4100
3675
                }
4101
3676
        } else if (type == OS_FILE_WRITE) {
4102
 
                if (srv_use_native_aio) {
 
3677
                if (os_aio_use_native_aio) {
 
3678
#ifdef WIN_ASYNC_IO
4103
3679
                        os_n_file_writes++;
4104
 
#ifdef WIN_ASYNC_IO
4105
3680
                        ret = WriteFile(file, buf, (DWORD)n, &len,
4106
3681
                                        &(slot->control));
4107
 
 
4108
 
#elif defined(LINUX_NATIVE_AIO)
4109
 
                        if (!os_aio_linux_dispatch(array, slot)) {
4110
 
                                goto err_exit;
4111
 
                        }
4112
3682
#endif
4113
3683
                } else {
4114
3684
                        if (!wake_later) {
4122
3692
        }
4123
3693
 
4124
3694
#ifdef WIN_ASYNC_IO
4125
 
        if (srv_use_native_aio) {
 
3695
        if (os_aio_use_native_aio) {
4126
3696
                if ((ret && len == n)
4127
3697
                    || (!ret && GetLastError() == ERROR_IO_PENDING)) {
4128
3698
                        /* aio was queued successfully! */
4145
3715
                        return(TRUE);
4146
3716
                }
4147
3717
 
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:
 
3718
                err = 1; /* Fall through the next if */
 
3719
        }
 
3720
#endif
 
3721
        if (err == 0) {
 
3722
                /* aio was queued successfully! */
 
3723
 
 
3724
                return(TRUE);
 
3725
        }
 
3726
 
4156
3727
        os_aio_array_free_slot(array, slot);
4157
3728
 
4158
3729
        retry = os_file_handle_error(name,
4164
3735
        }
4165
3736
 
4166
3737
        return(FALSE);
4167
 
#endif /* LINUX_NATIVE_AIO || WIN_ASYNC_IO */
4168
3738
}
4169
3739
 
4170
3740
#ifdef WIN_ASYNC_IO
4224
3794
        n = array->n_slots / array->n_segments;
4225
3795
 
4226
3796
        if (array == os_aio_sync_array) {
4227
 
                WaitForSingleObject(
4228
 
                        os_aio_array_get_nth_slot(array, pos)->handle,
4229
 
                        INFINITE);
 
3797
                os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
4230
3798
                i = pos;
4231
3799
        } else {
4232
3800
                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);
 
3801
                i = os_event_wait_multiple(n,
 
3802
                                           (array->native_events)
 
3803
                                           + segment * n);
4241
3804
        }
4242
3805
 
4243
3806
        os_mutex_enter(array->mutex);
4264
3827
#ifdef UNIV_DO_FLUSH
4265
3828
                if (slot->type == OS_FILE_WRITE
4266
3829
                    && !os_do_not_call_flush_at_each_write) {
4267
 
                        if (!os_file_flush(slot->file)) {
4268
 
                                ut_error;
4269
 
                        }
 
3830
                        ut_a(TRUE == os_file_flush(slot->file));
4270
3831
                }
4271
3832
#endif /* UNIV_DO_FLUSH */
4272
3833
        } else if (os_file_handle_error(slot->name, "Windows aio")) {
4283
3844
                /* retry failed read/write operation synchronously.
4284
3845
                No need to hold array->mutex. */
4285
3846
 
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
3847
                switch (slot->type) {
4301
3848
                case OS_FILE_WRITE:
4302
3849
                        ret = WriteFile(slot->file, slot->buf,
4303
 
                                        (DWORD) slot->len, &len,
 
3850
                                        slot->len, &len,
4304
3851
                                        &(slot->control));
4305
3852
 
4306
3853
                        break;
4307
3854
                case OS_FILE_READ:
4308
3855
                        ret = ReadFile(slot->file, slot->buf,
4309
 
                                       (DWORD) slot->len, &len,
 
3856
                                       slot->len, &len,
4310
3857
                                       &(slot->control));
4311
3858
 
4312
3859
                        break;
4314
3861
                        ut_error;
4315
3862
                }
4316
3863
 
4317
 
#ifdef UNIV_PFS_IO
4318
 
                register_pfs_file_io_end(locker, len);
4319
 
#endif
4320
 
 
4321
3864
                if (!ret && GetLastError() == ERROR_IO_PENDING) {
4322
3865
                        /* aio was queued successfully!
4323
3866
                        We want a synchronous i/o operation on a
4339
3882
}
4340
3883
#endif
4341
3884
 
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
3885
/**********************************************************************//**
4593
3886
Does simulated aio. This function should be called by an i/o-handler
4594
3887
thread.
4742
4035
                goto wait_for_io;
4743
4036
        }
4744
4037
 
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
4038
        slot = consecutive_ios[0];
4751
4039
 
4752
4040
        /* Check if there are several consecutive blocks to read or write */
4797
4085
                combined_buf = slot->buf;
4798
4086
                combined_buf2 = NULL;
4799
4087
        } else {
4800
 
                combined_buf2 = static_cast<unsigned char *>(ut_malloc(total_len + UNIV_PAGE_SIZE));
 
4088
                combined_buf2 = ut_malloc(total_len + UNIV_PAGE_SIZE);
4801
4089
 
4802
4090
                ut_a(combined_buf2);
4803
4091
 
4804
 
                combined_buf = static_cast<unsigned char *>(ut_align(combined_buf2, UNIV_PAGE_SIZE));
 
4092
                combined_buf = ut_align(combined_buf2, UNIV_PAGE_SIZE);
4805
4093
        }
4806
4094
 
4807
4095
        /* We release the array mutex for the time of the i/o: NOTE that
4973
4261
}
4974
4262
 
4975
4263
/**********************************************************************//**
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
4264
Prints info of the aio arrays. */
5011
4265
UNIV_INTERN
5012
4266
void
5017
4271
        os_aio_array_t* array;
5018
4272
        os_aio_slot_t*  slot;
5019
4273
        ulint           n_reserved;
5020
 
        ulint           n_res_seg[SRV_MAX_N_IO_THREADS];
5021
4274
        time_t          current_time;
5022
4275
        double          time_elapsed;
5023
4276
        double          avg_bytes_read;
5050
4303
 
5051
4304
        n_reserved = 0;
5052
4305
 
5053
 
        memset(n_res_seg, 0x0, sizeof(n_res_seg));
5054
 
 
5055
4306
        for (i = 0; i < array->n_slots; i++) {
5056
 
                ulint   seg_no;
5057
 
 
5058
4307
                slot = os_aio_array_get_nth_slot(array, i);
5059
4308
 
5060
 
                seg_no = (i * array->n_segments) / array->n_slots;
5061
4309
                if (slot->reserved) {
5062
4310
                        n_reserved++;
5063
 
                        n_res_seg[seg_no]++;
5064
4311
#if 0
5065
4312
                        fprintf(stderr, "Reserved slot, messages %p %p\n",
5066
4313
                                (void*) slot->message1,
5074
4321
 
5075
4322
        fprintf(file, " %lu", (ulong) n_reserved);
5076
4323
 
5077
 
        os_aio_print_segment_info(file, n_res_seg, array);
5078
 
 
5079
4324
        os_mutex_exit(array->mutex);
5080
4325
 
5081
4326
        if (array == os_aio_read_array) {